BREAKING CHANGE: requires Solana version v0.13.0 or greater

feat: Update to current solana tx format
This commit is contained in:
Tyera Eulberg 2019-04-10 12:31:50 -07:00 committed by Michael Vines
parent 853ea88fd0
commit efd0392706
12 changed files with 196 additions and 167 deletions

View File

@ -110,13 +110,13 @@ declare module '@solana/web3.js' {
declare export type TransactionSignature = string; declare export type TransactionSignature = string;
declare type TransactionInstructionCtorFields = {| declare type TransactionInstructionCtorFields = {|
keys: ?Array<PublicKey>, keys: ?Array<{pubkey: PublicKey, isSigner: boolean}>,
programId?: PublicKey, programId?: PublicKey,
data?: Buffer, data?: Buffer,
|}; |};
declare export class TransactionInstruction { declare export class TransactionInstruction {
keys: Array<PublicKey>; keys: Array<{pubkey: PublicKey, isSigner: boolean}>;
programId: PublicKey; programId: PublicKey;
data: Buffer; data: Buffer;
} }
@ -127,7 +127,6 @@ declare module '@solana/web3.js' {
|}; |};
declare type TransactionCtorFields = {| declare type TransactionCtorFields = {|
fee?: number,
recentBlockhash?: Blockhash, recentBlockhash?: Blockhash,
signatures?: Array<SignaturePubkeyPair>, signatures?: Array<SignaturePubkeyPair>,
|}; |};
@ -137,7 +136,6 @@ declare module '@solana/web3.js' {
signature: ?Buffer; signature: ?Buffer;
instructions: Array<TransactionInstruction>; instructions: Array<TransactionInstruction>;
recentBlockhash: ?Blockhash; recentBlockhash: ?Blockhash;
fee: number;
constructor(opts?: TransactionCtorFields): Transaction; constructor(opts?: TransactionCtorFields): Transaction;
add( add(

View File

@ -5805,7 +5805,7 @@
"dependencies": { "dependencies": {
"marked": { "marked": {
"version": "0.3.19", "version": "0.3.19",
"resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", "resolved": "http://registry.npmjs.org/marked/-/marked-0.3.19.tgz",
"integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==", "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==",
"dev": true "dev": true
}, },
@ -6069,7 +6069,7 @@
}, },
"marked": { "marked": {
"version": "0.3.19", "version": "0.3.19",
"resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", "resolved": "http://registry.npmjs.org/marked/-/marked-0.3.19.tgz",
"integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==", "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==",
"dev": true "dev": true
}, },
@ -12269,7 +12269,7 @@
}, },
"minimist": { "minimist": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true "dev": true
}, },
@ -16742,7 +16742,7 @@
"dependencies": { "dependencies": {
"minimist": { "minimist": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true "dev": true
} }

View File

@ -203,7 +203,7 @@ export class BudgetProgram {
} }
return new Transaction().add({ return new Transaction().add({
keys: [from, to], keys: [{pubkey: from, isSigner: true}, {pubkey: to, isSigner: false}],
programId: this.programId, programId: this.programId,
data: data.slice(0, pos), data: data.slice(0, pos),
}); });
@ -223,7 +223,11 @@ export class BudgetProgram {
} }
return new Transaction().add({ return new Transaction().add({
keys: [from, program, to], keys: [
{pubkey: from, isSigner: true},
{pubkey: program, isSigner: false},
{pubkey: to, isSigner: false},
],
programId: this.programId, programId: this.programId,
data: data.slice(0, pos), data: data.slice(0, pos),
}); });
@ -243,7 +247,11 @@ export class BudgetProgram {
} }
return new Transaction().add({ return new Transaction().add({
keys: [from, program, to], keys: [
{pubkey: from, isSigner: true},
{pubkey: program, isSigner: false},
{pubkey: to, isSigner: false},
],
programId: this.programId, programId: this.programId,
data: data.slice(0, pos), data: data.slice(0, pos),
}); });
@ -287,7 +295,11 @@ export class BudgetProgram {
pos += paymentData.length; pos += paymentData.length;
return new Transaction().add({ return new Transaction().add({
keys: [from, program, to], keys: [
{pubkey: from, isSigner: true},
{pubkey: program, isSigner: false},
{pubkey: to, isSigner: false},
],
programId: this.programId, programId: this.programId,
data: data.slice(0, pos), data: data.slice(0, pos),
}); });
@ -310,7 +322,11 @@ export class BudgetProgram {
whenData.copy(data, 4); whenData.copy(data, 4);
return new Transaction().add({ return new Transaction().add({
keys: [from, program, to], keys: [
{pubkey: from, isSigner: true},
{pubkey: program, isSigner: false},
{pubkey: to, isSigner: false},
],
programId: this.programId, programId: this.programId,
data, data,
}); });
@ -336,7 +352,11 @@ export class BudgetProgram {
); );
return new Transaction().add({ return new Transaction().add({
keys: [from, program, to], keys: [
{pubkey: from, isSigner: true},
{pubkey: program, isSigner: false},
{pubkey: to, isSigner: false},
],
programId: this.programId, programId: this.programId,
data, data,
}); });

View File

@ -75,7 +75,7 @@ export class Loader {
); );
const transaction = new Transaction().add({ const transaction = new Transaction().add({
keys: [program.publicKey], keys: [{pubkey: program.publicKey, isSigner: true}],
programId: this.programId, programId: this.programId,
data, data,
}); });
@ -119,7 +119,7 @@ export class Loader {
); );
const transaction = new Transaction().add({ const transaction = new Transaction().add({
keys: [program.publicKey], keys: [{pubkey: program.publicKey, isSigner: true}],
programId: this.programId, programId: this.programId,
data, data,
}); });

View File

@ -48,7 +48,10 @@ export class SystemProgram {
); );
return new Transaction().add({ return new Transaction().add({
keys: [from, newAccount], keys: [
{pubkey: from, isSigner: true},
{pubkey: newAccount, isSigner: false},
],
programId: SystemProgram.programId, programId: SystemProgram.programId,
data, data,
}); });
@ -73,7 +76,7 @@ export class SystemProgram {
); );
return new Transaction().add({ return new Transaction().add({
keys: [from, to], keys: [{pubkey: from, isSigner: true}, {pubkey: to, isSigner: false}],
programId: SystemProgram.programId, programId: SystemProgram.programId,
data, data,
}); });
@ -98,7 +101,7 @@ export class SystemProgram {
); );
return new Transaction().add({ return new Transaction().add({
keys: [from], keys: [{pubkey: from, isSigner: true}],
programId: SystemProgram.programId, programId: SystemProgram.programId,
data, data,
}); });

View File

@ -236,11 +236,13 @@ export class Token {
await sendAndConfirmTransaction(connection, transaction, owner); await sendAndConfirmTransaction(connection, transaction, owner);
transaction = new Transaction().add({ transaction = new Transaction().add({
keys: [tokenAccount.publicKey, initialAccountPublicKey], keys: [
{pubkey: tokenAccount.publicKey, isSigner: true},
{pubkey: initialAccountPublicKey, isSigner: false},
],
programId, programId,
data, data,
}); });
transaction.fee = 0; // TODO: Batch with the `SystemProgram.createAccount` and remove this line
await sendAndConfirmTransaction(connection, transaction, tokenAccount); await sendAndConfirmTransaction(connection, transaction, tokenAccount);
return [token, initialAccountPublicKey]; return [token, initialAccountPublicKey];
@ -284,16 +286,19 @@ export class Token {
await sendAndConfirmTransaction(this.connection, transaction, owner); await sendAndConfirmTransaction(this.connection, transaction, owner);
// Initialize the token account // Initialize the token account
const keys = [tokenAccount.publicKey, owner.publicKey, this.token]; const keys = [
{pubkey: tokenAccount.publicKey, isSigner: true},
{pubkey: owner.publicKey, isSigner: false},
{pubkey: this.token, isSigner: false},
];
if (source) { if (source) {
keys.push(source); keys.push({pubkey: source, isSigner: false});
} }
transaction = new Transaction().add({ transaction = new Transaction().add({
keys, keys,
programId: this.programId, programId: this.programId,
data, data,
}); });
transaction.fee = 0; // TODO: Batch with the `SystemProgram.createAccount` and remove this line
await sendAndConfirmTransaction(this.connection, transaction, tokenAccount); await sendAndConfirmTransaction(this.connection, transaction, tokenAccount);
return tokenAccount.publicKey; return tokenAccount.publicKey;
@ -480,9 +485,13 @@ export class Token {
data, data,
); );
const keys = [owner, source, destination]; const keys = [
{pubkey: owner, isSigner: true},
{pubkey: source, isSigner: false},
{pubkey: destination, isSigner: false},
];
if (accountInfo.source) { if (accountInfo.source) {
keys.push(accountInfo.source); keys.push({pubkey: accountInfo.source, isSigner: false});
} }
return new TransactionInstruction({ return new TransactionInstruction({
keys, keys,
@ -520,7 +529,11 @@ export class Token {
); );
return new TransactionInstruction({ return new TransactionInstruction({
keys: [owner, account, delegate], keys: [
{pubkey: owner, isSigner: true},
{pubkey: account, isSigner: false},
{pubkey: delegate, isSigner: false},
],
programId: this.programId, programId: this.programId,
data, data,
}); });
@ -564,7 +577,11 @@ export class Token {
); );
return new TransactionInstruction({ return new TransactionInstruction({
keys: [owner, account, newOwner], keys: [
{pubkey: owner, isSigner: true},
{pubkey: account, isSigner: false},
{pubkey: newOwner, isSigner: false},
],
programId: this.programId, programId: this.programId,
data, data,
}); });

View File

@ -30,7 +30,7 @@ export const PACKET_DATA_SIZE = 512;
* @property {?Buffer} data * @property {?Buffer} data
*/ */
type TransactionInstructionCtorFields = {| type TransactionInstructionCtorFields = {|
keys?: Array<PublicKey>, keys?: Array<{pubkey: PublicKey, isSigner: boolean}>,
programId?: PublicKey, programId?: PublicKey,
data?: Buffer, data?: Buffer,
|}; |};
@ -41,8 +41,9 @@ type TransactionInstructionCtorFields = {|
export class TransactionInstruction { export class TransactionInstruction {
/** /**
* Public keys to include in this transaction * Public keys to include in this transaction
* Boolean represents whether this pubkey needs to sign the transaction
*/ */
keys: Array<PublicKey> = []; keys: Array<{pubkey: PublicKey, isSigner: boolean}> = [];
/** /**
* Program Id to execute * Program Id to execute
@ -71,13 +72,11 @@ type SignaturePubkeyPair = {|
* List of Transaction object fields that may be initialized at construction * List of Transaction object fields that may be initialized at construction
* *
* @typedef {Object} TransactionCtorFields * @typedef {Object} TransactionCtorFields
* @property {?number} fee
* @property (?recentBlockhash} A recent block hash * @property (?recentBlockhash} A recent block hash
* @property (?signatures} One or more signatures * @property (?signatures} One or more signatures
* *
*/ */
type TransactionCtorFields = {| type TransactionCtorFields = {|
fee?: number,
recentBlockhash?: Blockhash, recentBlockhash?: Blockhash,
signatures?: Array<SignaturePubkeyPair>, signatures?: Array<SignaturePubkeyPair>,
|}; |};
@ -112,11 +111,6 @@ export class Transaction {
*/ */
recentBlockhash: ?Blockhash; recentBlockhash: ?Blockhash;
/**
* Fee for this transaction
*/
fee: number = 1;
/** /**
* Construct an empty Transaction * Construct an empty Transaction
*/ */
@ -158,6 +152,7 @@ export class Transaction {
} }
const keys = this.signatures.map(({publicKey}) => publicKey.toString()); const keys = this.signatures.map(({publicKey}) => publicKey.toString());
let numRequiredSignatures = 0;
const programIds = []; const programIds = [];
this.instructions.forEach(instruction => { this.instructions.forEach(instruction => {
@ -166,13 +161,15 @@ export class Transaction {
programIds.push(programId); programIds.push(programId);
} }
instruction.keys instruction.keys.forEach(keySignerPair => {
.map(key => key.toString()) const keyStr = keySignerPair.pubkey.toString();
.forEach(key => { if (keySignerPair.isSigner) {
if (!keys.includes(key)) { numRequiredSignatures += 1;
keys.push(key); }
} if (!keys.includes(keyStr)) {
}); keys.push(keyStr);
}
});
}); });
let keyCount = []; let keyCount = [];
@ -191,7 +188,9 @@ export class Transaction {
programIdIndex: programIds.indexOf(programId.toString()), programIdIndex: programIds.indexOf(programId.toString()),
keyIndicesCount: Buffer.from(keyIndicesCount), keyIndicesCount: Buffer.from(keyIndicesCount),
keyIndices: Buffer.from( keyIndices: Buffer.from(
instruction.keys.map(key => keys.indexOf(key.toString())), instruction.keys.map(keyObj =>
keys.indexOf(keyObj.pubkey.toString()),
),
), ),
dataLength: Buffer.from(dataCount), dataLength: Buffer.from(dataCount),
data, data,
@ -239,10 +238,10 @@ export class Transaction {
instructionBuffer = instructionBuffer.slice(0, instructionBufferLength); instructionBuffer = instructionBuffer.slice(0, instructionBufferLength);
const signDataLayout = BufferLayout.struct([ const signDataLayout = BufferLayout.struct([
BufferLayout.blob(1, 'numRequiredSignatures'),
BufferLayout.blob(keyCount.length, 'keyCount'), BufferLayout.blob(keyCount.length, 'keyCount'),
BufferLayout.seq(Layout.publicKey('key'), keys.length, 'keys'), BufferLayout.seq(Layout.publicKey('key'), keys.length, 'keys'),
Layout.publicKey('recentBlockhash'), Layout.publicKey('recentBlockhash'),
BufferLayout.ns64('fee'),
BufferLayout.blob(programIdCount.length, 'programIdCount'), BufferLayout.blob(programIdCount.length, 'programIdCount'),
BufferLayout.seq( BufferLayout.seq(
@ -253,10 +252,10 @@ export class Transaction {
]); ]);
const transaction = { const transaction = {
numRequiredSignatures: Buffer.from([numRequiredSignatures]),
keyCount: Buffer.from(keyCount), keyCount: Buffer.from(keyCount),
keys: keys.map(key => new PublicKey(key).toBuffer()), keys: keys.map(key => new PublicKey(key).toBuffer()),
recentBlockhash: Buffer.from(bs58.decode(recentBlockhash)), recentBlockhash: Buffer.from(bs58.decode(recentBlockhash)),
fee: this.fee,
programIdCount: Buffer.from(programIdCount), programIdCount: Buffer.from(programIdCount),
programIds: programIds.map(programId => programIds: programIds.map(programId =>
new PublicKey(programId).toBuffer(), new PublicKey(programId).toBuffer(),
@ -389,7 +388,7 @@ export class Transaction {
*/ */
get keys(): Array<PublicKey> { get keys(): Array<PublicKey> {
invariant(this.instructions.length === 1); invariant(this.instructions.length === 1);
return this.instructions[0].keys; return this.instructions[0].keys.map(keyObj => keyObj.pubkey);
} }
/** /**
@ -430,6 +429,8 @@ export class Transaction {
signatures.push(signature); signatures.push(signature);
} }
byteArray = byteArray.slice(1); // Skip numRequiredSignatures byte
const accountCount = shortvec.decodeLength(byteArray); const accountCount = shortvec.decodeLength(byteArray);
let accounts = []; let accounts = [];
for (let i = 0; i < accountCount; i++) { for (let i = 0; i < accountCount; i++) {
@ -441,11 +442,6 @@ export class Transaction {
const recentBlockhash = byteArray.slice(0, PUBKEY_LENGTH); const recentBlockhash = byteArray.slice(0, PUBKEY_LENGTH);
byteArray = byteArray.slice(PUBKEY_LENGTH); byteArray = byteArray.slice(PUBKEY_LENGTH);
let fee = 0;
for (let i = 0; i < 8; i++) {
fee += byteArray.shift() >> (8 * i);
}
const programIdCount = shortvec.decodeLength(byteArray); const programIdCount = shortvec.decodeLength(byteArray);
let programs = []; let programs = [];
for (let i = 0; i < programIdCount; i++) { for (let i = 0; i < programIdCount; i++) {
@ -470,7 +466,6 @@ export class Transaction {
// Populate Transaction object // Populate Transaction object
transaction.recentBlockhash = new PublicKey(recentBlockhash).toBase58(); transaction.recentBlockhash = new PublicKey(recentBlockhash).toBase58();
transaction.fee = fee;
for (let i = 0; i < signatureCount; i++) { for (let i = 0; i < signatureCount; i++) {
const sigPubkeyPair = { const sigPubkeyPair = {
signature: Buffer.from(signatures[i]), signature: Buffer.from(signatures[i]),
@ -485,9 +480,13 @@ export class Transaction {
data: Buffer.from(instructions[i].data), data: Buffer.from(instructions[i].data),
}; };
for (let j = 0; j < instructions[i].accountIndex.length; j++) { for (let j = 0; j < instructions[i].accountIndex.length; j++) {
instructionData.keys.push( const pubkey = new PublicKey(accounts[instructions[i].accountIndex[j]]);
new PublicKey(accounts[instructions[i].accountIndex[j]]), instructionData.keys.push({
); pubkey,
isSigner: transaction.signatures.some(
keyObj => keyObj.publicKey.toString() === pubkey.toString(),
),
});
} }
let instruction = new TransactionInstruction(instructionData); let instruction = new TransactionInstruction(instructionData);
transaction.instructions.push(instruction); transaction.instructions.push(instruction);

View File

@ -28,7 +28,7 @@ test('load BPF program', async () => {
const data = await fs.readFile('test/fixtures/noop/noop.so'); const data = await fs.readFile('test/fixtures/noop/noop.so');
const programId = await BpfLoader.load(connection, from, data); const programId = await BpfLoader.load(connection, from, data);
const transaction = new Transaction().add({ const transaction = new Transaction().add({
keys: [from.publicKey], keys: [{pubkey: from.publicKey, isSigner: true}],
programId, programId,
}); });
await sendAndConfirmTransaction(connection, transaction, from); await sendAndConfirmTransaction(connection, transaction, from);

View File

@ -301,7 +301,6 @@ test('transaction', async () => {
accountTo.publicKey, accountTo.publicKey,
10, 10,
); );
transaction.fee = 0;
const signature = await connection.sendTransaction(transaction, accountFrom); const signature = await connection.sendTransaction(transaction, accountFrom);
mockRpc.push([ mockRpc.push([
@ -396,7 +395,6 @@ test('multi-instruction transaction', async () => {
accountTo.publicKey, accountTo.publicKey,
10, 10,
).add(SystemProgram.move(accountTo.publicKey, accountFrom.publicKey, 10)); ).add(SystemProgram.move(accountTo.publicKey, accountFrom.publicKey, 10));
transaction.fee = 0;
const signature = await connection.sendTransaction( const signature = await connection.sendTransaction(
transaction, transaction,
accountFrom, accountFrom,
@ -445,7 +443,6 @@ test('account change notification', async () => {
3, 3,
BpfLoader.programId, BpfLoader.programId,
); );
transaction.fee = 0;
await sendAndConfirmTransaction(connection, transaction, owner); await sendAndConfirmTransaction(connection, transaction, owner);
const loader = new Loader(connection, BpfLoader.programId); const loader = new Loader(connection, BpfLoader.programId);
@ -500,7 +497,6 @@ test('program account change notification', async () => {
3, 3,
BpfLoader.programId, BpfLoader.programId,
); );
transaction.fee = 0;
await sendAndConfirmTransaction(connection, transaction, owner); await sendAndConfirmTransaction(connection, transaction, owner);
const loader = new Loader(connection, BpfLoader.programId); const loader = new Loader(connection, BpfLoader.programId);

View File

@ -25,7 +25,7 @@ test('load native program', async () => {
const from = await newAccountWithLamports(connection, 1024); const from = await newAccountWithLamports(connection, 1024);
const programId = await NativeLoader.load(connection, from, 'noop'); const programId = await NativeLoader.load(connection, from, 'noop');
const transaction = new Transaction().add({ const transaction = new Transaction().add({
keys: [from.publicKey], keys: [{pubkey: from.publicKey, isSigner: true}],
programId, programId,
}); });

View File

@ -607,4 +607,3 @@ test('set owner', async () => {
await testToken.setOwner(newOwner, account, owner.publicKey); await testToken.setOwner(newOwner, account, owner.publicKey);
}); });

View File

@ -1,4 +1,6 @@
// @flow // @flow
import nacl from 'tweetnacl';
import {Account} from '../src/account'; import {Account} from '../src/account';
import {PublicKey} from '../src/publickey'; import {PublicKey} from '../src/publickey';
import {Transaction} from '../src/transaction'; import {Transaction} from '../src/transaction';
@ -33,7 +35,6 @@ test('transfer signatures', () => {
const newTransaction = new Transaction({ const newTransaction = new Transaction({
recentBlockhash: orgTransaction.recentBlockhash, recentBlockhash: orgTransaction.recentBlockhash,
fee: orgTransaction.fee,
signatures: orgTransaction.signatures, signatures: orgTransaction.signatures,
}).add(move1, move2); }).add(move1, move2);
@ -41,8 +42,11 @@ test('transfer signatures', () => {
}); });
test('parse wire format and serialize', () => { test('parse wire format and serialize', () => {
const keypair = nacl.sign.keyPair.fromSeed(
Uint8Array.from(Array(32).fill(8)),
);
const sender = new Account(Buffer.from(keypair.secretKey)); // Arbitrary known account
const recentBlockhash = 'EETubP5AKHgjPAhzPAFcb8BAY1hMH639CWCFTqi3hq1k'; // Arbitrary known recentBlockhash const recentBlockhash = 'EETubP5AKHgjPAhzPAFcb8BAY1hMH639CWCFTqi3hq1k'; // Arbitrary known recentBlockhash
const sender = new Account(Buffer.alloc(64, 8)); // Arbitrary known account
const recipient = new PublicKey( const recipient = new PublicKey(
'J3dxNj7nDRRqRRXuEMynDG57DkZK4jYRuv3Garmb1i99', 'J3dxNj7nDRRqRRXuEMynDG57DkZK4jYRuv3Garmb1i99',
); // Arbitrary known public key ); // Arbitrary known public key
@ -52,103 +56,104 @@ test('parse wire format and serialize', () => {
const wireTransaction = Buffer.from([ const wireTransaction = Buffer.from([
1, 1,
50,
238,
193,
5,
227,
31,
95,
69,
85,
3,
132, 132,
143, 50,
216, 204,
77, 17,
235, 25,
129, 230,
3,
109,
89,
222,
127,
137,
228,
15,
113,
207,
169,
93,
167,
249,
71,
33, 33,
185, 52,
182, 8,
83, 149,
116, 124,
203, 56,
102, 114,
64, 17,
245, 236,
68, 92,
34, 93,
100, 53,
234,
122,
120,
219,
193, 193,
156, 255,
109,
35,
104,
119,
101,
197,
43,
141,
174,
228,
154,
146,
78,
216,
202,
18,
177,
179,
5,
2, 2,
8, 14,
8, 87,
8, 12,
8, 207,
8, 99,
8, 241,
8, 32,
8, 151,
8, 102,
8, 70,
8, 60,
8, 218,
8, 73,
8, 232,
8, 68,
8, 33,
8, 94,
8, 134,
8, 117,
8, 138,
8, 182,
8, 179,
8, 118,
8, 249,
8, 132,
8, 52,
8, 41,
8, 162,
8, 44,
8, 0,
8, 43,
8, 193,
242,
120,
108,
4,
163,
191,
6,
1,
2,
19,
152,
246,
44,
109,
26,
69,
124,
81,
186,
106,
75,
95,
61,
189,
47,
105,
252,
169,
50,
22,
33,
141,
200,
153,
126,
65,
107,
209,
125,
147,
202,
253, 253,
67, 67,
159, 159,
@ -221,14 +226,6 @@ test('parse wire format and serialize', () => {
0, 0,
0, 0,
0, 0,
1,
0,
0,
0,
0,
0,
0,
0,
0, 0,
0, 0,
0, 0,