fix: Add preliminary handling for credit-only account designation
This commit is contained in:
parent
78ad376bcd
commit
c99d8dd15c
|
@ -124,13 +124,13 @@ declare module '@solana/web3.js' {
|
||||||
declare export type TransactionSignature = string;
|
declare export type TransactionSignature = string;
|
||||||
|
|
||||||
declare type TransactionInstructionCtorFields = {|
|
declare type TransactionInstructionCtorFields = {|
|
||||||
keys: ?Array<{pubkey: PublicKey, isSigner: boolean}>,
|
keys: ?Array<{pubkey: PublicKey, isSigner: boolean, isDebitable: boolean}>,
|
||||||
programId?: PublicKey,
|
programId?: PublicKey,
|
||||||
data?: Buffer,
|
data?: Buffer,
|
||||||
|};
|
|};
|
||||||
|
|
||||||
declare export class TransactionInstruction {
|
declare export class TransactionInstruction {
|
||||||
keys: Array<{pubkey: PublicKey, isSigner: boolean}>;
|
keys: Array<{pubkey: PublicKey, isSigner: boolean, isDebitable: boolean}>;
|
||||||
programId: PublicKey;
|
programId: PublicKey;
|
||||||
data: Buffer;
|
data: Buffer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,7 +201,10 @@ export class BudgetProgram {
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Transaction().add({
|
return new Transaction().add({
|
||||||
keys: [{pubkey: from, isSigner: true}, {pubkey: to, isSigner: false}],
|
keys: [
|
||||||
|
{pubkey: from, isSigner: true, isDebitable: true},
|
||||||
|
{pubkey: to, isSigner: false, isDebitable: false},
|
||||||
|
],
|
||||||
programId: this.programId,
|
programId: this.programId,
|
||||||
data: data.slice(0, pos),
|
data: data.slice(0, pos),
|
||||||
});
|
});
|
||||||
|
@ -222,9 +225,9 @@ export class BudgetProgram {
|
||||||
|
|
||||||
return new Transaction().add({
|
return new Transaction().add({
|
||||||
keys: [
|
keys: [
|
||||||
{pubkey: from, isSigner: true},
|
{pubkey: from, isSigner: true, isDebitable: true},
|
||||||
{pubkey: program, isSigner: false},
|
{pubkey: program, isSigner: false, isDebitable: true},
|
||||||
{pubkey: to, isSigner: false},
|
{pubkey: to, isSigner: false, isDebitable: false},
|
||||||
],
|
],
|
||||||
programId: this.programId,
|
programId: this.programId,
|
||||||
data: data.slice(0, pos),
|
data: data.slice(0, pos),
|
||||||
|
@ -246,9 +249,9 @@ export class BudgetProgram {
|
||||||
|
|
||||||
return new Transaction().add({
|
return new Transaction().add({
|
||||||
keys: [
|
keys: [
|
||||||
{pubkey: from, isSigner: true},
|
{pubkey: from, isSigner: true, isDebitable: true},
|
||||||
{pubkey: program, isSigner: false},
|
{pubkey: program, isSigner: false, isDebitable: true},
|
||||||
{pubkey: to, isSigner: false},
|
{pubkey: to, isSigner: false, isDebitable: false},
|
||||||
],
|
],
|
||||||
programId: this.programId,
|
programId: this.programId,
|
||||||
data: data.slice(0, pos),
|
data: data.slice(0, pos),
|
||||||
|
@ -294,9 +297,9 @@ export class BudgetProgram {
|
||||||
|
|
||||||
return new Transaction().add({
|
return new Transaction().add({
|
||||||
keys: [
|
keys: [
|
||||||
{pubkey: from, isSigner: true},
|
{pubkey: from, isSigner: true, isDebitable: true},
|
||||||
{pubkey: program, isSigner: false},
|
{pubkey: program, isSigner: false, isDebitable: true},
|
||||||
{pubkey: to, isSigner: false},
|
{pubkey: to, isSigner: false, isDebitable: false},
|
||||||
],
|
],
|
||||||
programId: this.programId,
|
programId: this.programId,
|
||||||
data: data.slice(0, pos),
|
data: data.slice(0, pos),
|
||||||
|
@ -321,9 +324,9 @@ export class BudgetProgram {
|
||||||
|
|
||||||
return new Transaction().add({
|
return new Transaction().add({
|
||||||
keys: [
|
keys: [
|
||||||
{pubkey: from, isSigner: true},
|
{pubkey: from, isSigner: true, isDebitable: true},
|
||||||
{pubkey: program, isSigner: false},
|
{pubkey: program, isSigner: false, isDebitable: true},
|
||||||
{pubkey: to, isSigner: false},
|
{pubkey: to, isSigner: false, isDebitable: false},
|
||||||
],
|
],
|
||||||
programId: this.programId,
|
programId: this.programId,
|
||||||
data,
|
data,
|
||||||
|
@ -351,9 +354,9 @@ export class BudgetProgram {
|
||||||
|
|
||||||
return new Transaction().add({
|
return new Transaction().add({
|
||||||
keys: [
|
keys: [
|
||||||
{pubkey: from, isSigner: true},
|
{pubkey: from, isSigner: true, isDebitable: true},
|
||||||
{pubkey: program, isSigner: false},
|
{pubkey: program, isSigner: false, isDebitable: true},
|
||||||
{pubkey: to, isSigner: false},
|
{pubkey: to, isSigner: false, isDebitable: false},
|
||||||
],
|
],
|
||||||
programId: this.programId,
|
programId: this.programId,
|
||||||
data,
|
data,
|
||||||
|
|
|
@ -78,7 +78,7 @@ export class Loader {
|
||||||
);
|
);
|
||||||
|
|
||||||
const transaction = new Transaction().add({
|
const transaction = new Transaction().add({
|
||||||
keys: [{pubkey: program.publicKey, isSigner: true}],
|
keys: [{pubkey: program.publicKey, isSigner: true, isDebitable: true}],
|
||||||
programId,
|
programId,
|
||||||
data,
|
data,
|
||||||
});
|
});
|
||||||
|
@ -117,7 +117,7 @@ export class Loader {
|
||||||
);
|
);
|
||||||
|
|
||||||
const transaction = new Transaction().add({
|
const transaction = new Transaction().add({
|
||||||
keys: [{pubkey: program.publicKey, isSigner: true}],
|
keys: [{pubkey: program.publicKey, isSigner: true, isDebitable: true}],
|
||||||
programId,
|
programId,
|
||||||
data,
|
data,
|
||||||
});
|
});
|
||||||
|
|
|
@ -49,8 +49,8 @@ export class SystemProgram {
|
||||||
|
|
||||||
return new Transaction().add({
|
return new Transaction().add({
|
||||||
keys: [
|
keys: [
|
||||||
{pubkey: from, isSigner: true},
|
{pubkey: from, isSigner: true, isDebitable: true},
|
||||||
{pubkey: newAccount, isSigner: false},
|
{pubkey: newAccount, isSigner: false, isDebitable: true},
|
||||||
],
|
],
|
||||||
programId: SystemProgram.programId,
|
programId: SystemProgram.programId,
|
||||||
data,
|
data,
|
||||||
|
@ -76,7 +76,10 @@ export class SystemProgram {
|
||||||
);
|
);
|
||||||
|
|
||||||
return new Transaction().add({
|
return new Transaction().add({
|
||||||
keys: [{pubkey: from, isSigner: true}, {pubkey: to, isSigner: false}],
|
keys: [
|
||||||
|
{pubkey: from, isSigner: true, isDebitable: true},
|
||||||
|
{pubkey: to, isSigner: false, isDebitable: false},
|
||||||
|
],
|
||||||
programId: SystemProgram.programId,
|
programId: SystemProgram.programId,
|
||||||
data,
|
data,
|
||||||
});
|
});
|
||||||
|
@ -101,7 +104,7 @@ export class SystemProgram {
|
||||||
);
|
);
|
||||||
|
|
||||||
return new Transaction().add({
|
return new Transaction().add({
|
||||||
keys: [{pubkey: from, isSigner: true}],
|
keys: [{pubkey: from, isSigner: true, isDebitable: true}],
|
||||||
programId: SystemProgram.programId,
|
programId: SystemProgram.programId,
|
||||||
data,
|
data,
|
||||||
});
|
});
|
||||||
|
|
|
@ -237,8 +237,8 @@ export class Token {
|
||||||
|
|
||||||
transaction = new Transaction().add({
|
transaction = new Transaction().add({
|
||||||
keys: [
|
keys: [
|
||||||
{pubkey: tokenAccount.publicKey, isSigner: true},
|
{pubkey: tokenAccount.publicKey, isSigner: true, isDebitable: false},
|
||||||
{pubkey: initialAccountPublicKey, isSigner: false},
|
{pubkey: initialAccountPublicKey, isSigner: false, isDebitable: true},
|
||||||
],
|
],
|
||||||
programId,
|
programId,
|
||||||
data,
|
data,
|
||||||
|
@ -292,12 +292,12 @@ export class Token {
|
||||||
|
|
||||||
// Initialize the token account
|
// Initialize the token account
|
||||||
const keys = [
|
const keys = [
|
||||||
{pubkey: tokenAccount.publicKey, isSigner: true},
|
{pubkey: tokenAccount.publicKey, isSigner: true, isDebitable: true},
|
||||||
{pubkey: owner.publicKey, isSigner: false},
|
{pubkey: owner.publicKey, isSigner: false, isDebitable: false},
|
||||||
{pubkey: this.token, isSigner: false},
|
{pubkey: this.token, isSigner: false, isDebitable: false},
|
||||||
];
|
];
|
||||||
if (source) {
|
if (source) {
|
||||||
keys.push({pubkey: source, isSigner: false});
|
keys.push({pubkey: source, isSigner: false, isDebitable: false});
|
||||||
}
|
}
|
||||||
transaction = new Transaction().add({
|
transaction = new Transaction().add({
|
||||||
keys,
|
keys,
|
||||||
|
@ -496,12 +496,16 @@ export class Token {
|
||||||
);
|
);
|
||||||
|
|
||||||
const keys = [
|
const keys = [
|
||||||
{pubkey: owner, isSigner: true},
|
{pubkey: owner, isSigner: true, isDebitable: false},
|
||||||
{pubkey: source, isSigner: false},
|
{pubkey: source, isSigner: false, isDebitable: true},
|
||||||
{pubkey: destination, isSigner: false},
|
{pubkey: destination, isSigner: false, isDebitable: true},
|
||||||
];
|
];
|
||||||
if (accountInfo.source) {
|
if (accountInfo.source) {
|
||||||
keys.push({pubkey: accountInfo.source, isSigner: false});
|
keys.push({
|
||||||
|
pubkey: accountInfo.source,
|
||||||
|
isSigner: false,
|
||||||
|
isDebitable: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return new TransactionInstruction({
|
return new TransactionInstruction({
|
||||||
keys,
|
keys,
|
||||||
|
@ -540,9 +544,9 @@ export class Token {
|
||||||
|
|
||||||
return new TransactionInstruction({
|
return new TransactionInstruction({
|
||||||
keys: [
|
keys: [
|
||||||
{pubkey: owner, isSigner: true},
|
{pubkey: owner, isSigner: true, isDebitable: false},
|
||||||
{pubkey: account, isSigner: false},
|
{pubkey: account, isSigner: false, isDebitable: true},
|
||||||
{pubkey: delegate, isSigner: false},
|
{pubkey: delegate, isSigner: false, isDebitable: true},
|
||||||
],
|
],
|
||||||
programId: this.programId,
|
programId: this.programId,
|
||||||
data,
|
data,
|
||||||
|
@ -588,9 +592,9 @@ export class Token {
|
||||||
|
|
||||||
return new TransactionInstruction({
|
return new TransactionInstruction({
|
||||||
keys: [
|
keys: [
|
||||||
{pubkey: owner, isSigner: true},
|
{pubkey: owner, isSigner: true, isDebitable: false},
|
||||||
{pubkey: account, isSigner: false},
|
{pubkey: account, isSigner: false, isDebitable: true},
|
||||||
{pubkey: newOwner, isSigner: false},
|
{pubkey: newOwner, isSigner: false, isDebitable: true},
|
||||||
],
|
],
|
||||||
programId: this.programId,
|
programId: this.programId,
|
||||||
data,
|
data,
|
||||||
|
|
|
@ -30,7 +30,7 @@ export const PACKET_DATA_SIZE = 512;
|
||||||
* @property {?Buffer} data
|
* @property {?Buffer} data
|
||||||
*/
|
*/
|
||||||
type TransactionInstructionCtorFields = {|
|
type TransactionInstructionCtorFields = {|
|
||||||
keys?: Array<{pubkey: PublicKey, isSigner: boolean}>,
|
keys?: Array<{pubkey: PublicKey, isSigner: boolean, isDebitable: boolean}>,
|
||||||
programId?: PublicKey,
|
programId?: PublicKey,
|
||||||
data?: Buffer,
|
data?: Buffer,
|
||||||
|};
|
|};
|
||||||
|
@ -43,7 +43,11 @@ 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
|
* Boolean represents whether this pubkey needs to sign the transaction
|
||||||
*/
|
*/
|
||||||
keys: Array<{pubkey: PublicKey, isSigner: boolean}> = [];
|
keys: Array<{
|
||||||
|
pubkey: PublicKey,
|
||||||
|
isSigner: boolean,
|
||||||
|
isDebitable: boolean,
|
||||||
|
}> = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Program Id to execute
|
* Program Id to execute
|
||||||
|
@ -166,6 +170,13 @@ export class Transaction {
|
||||||
if (!keys.includes(keyStr)) {
|
if (!keys.includes(keyStr)) {
|
||||||
if (keySignerPair.isSigner) {
|
if (keySignerPair.isSigner) {
|
||||||
numRequiredSignatures += 1;
|
numRequiredSignatures += 1;
|
||||||
|
if (!keySignerPair.isDebitable) {
|
||||||
|
numCreditOnlySignedAccounts += 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!keySignerPair.isDebitable) {
|
||||||
|
numCreditOnlyUnsignedAccounts += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
keys.push(keyStr);
|
keys.push(keyStr);
|
||||||
}
|
}
|
||||||
|
@ -422,6 +433,20 @@ export class Transaction {
|
||||||
const PUBKEY_LENGTH = 32;
|
const PUBKEY_LENGTH = 32;
|
||||||
const SIGNATURE_LENGTH = 64;
|
const SIGNATURE_LENGTH = 64;
|
||||||
|
|
||||||
|
function isCreditDebit(
|
||||||
|
i: number,
|
||||||
|
numRequiredSignatures: number,
|
||||||
|
numCreditOnlySignedAccounts: number,
|
||||||
|
numCreditOnlyUnsignedAccounts: number,
|
||||||
|
numKeys: number,
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
i < numRequiredSignatures - numCreditOnlySignedAccounts ||
|
||||||
|
(i >= numRequiredSignatures &&
|
||||||
|
i < numKeys - numCreditOnlyUnsignedAccounts)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let transaction = new Transaction();
|
let transaction = new Transaction();
|
||||||
|
|
||||||
// Slice up wire data
|
// Slice up wire data
|
||||||
|
@ -435,9 +460,12 @@ export class Transaction {
|
||||||
signatures.push(signature);
|
signatures.push(signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
byteArray = byteArray.slice(1); // Skip numRequiredSignatures byte
|
const numRequiredSignatures = byteArray.shift();
|
||||||
byteArray = byteArray.slice(1); // Skip numCreditOnlySignedAccounts byte
|
// byteArray = byteArray.slice(1); // Skip numRequiredSignatures byte
|
||||||
byteArray = byteArray.slice(1); // Skip numCreditOnlyUnsignedAccounts byte
|
const numCreditOnlySignedAccounts = byteArray.shift();
|
||||||
|
// byteArray = byteArray.slice(1); // Skip numCreditOnlySignedAccounts byte
|
||||||
|
const numCreditOnlyUnsignedAccounts = byteArray.shift();
|
||||||
|
// byteArray = byteArray.slice(1); // Skip numCreditOnlyUnsignedAccounts byte
|
||||||
|
|
||||||
const accountCount = shortvec.decodeLength(byteArray);
|
const accountCount = shortvec.decodeLength(byteArray);
|
||||||
let accounts = [];
|
let accounts = [];
|
||||||
|
@ -481,11 +509,19 @@ export class Transaction {
|
||||||
};
|
};
|
||||||
for (let j = 0; j < instructions[i].accountIndex.length; j++) {
|
for (let j = 0; j < instructions[i].accountIndex.length; j++) {
|
||||||
const pubkey = new PublicKey(accounts[instructions[i].accountIndex[j]]);
|
const pubkey = new PublicKey(accounts[instructions[i].accountIndex[j]]);
|
||||||
|
|
||||||
instructionData.keys.push({
|
instructionData.keys.push({
|
||||||
pubkey,
|
pubkey,
|
||||||
isSigner: transaction.signatures.some(
|
isSigner: transaction.signatures.some(
|
||||||
keyObj => keyObj.publicKey.toString() === pubkey.toString(),
|
keyObj => keyObj.publicKey.toString() === pubkey.toString(),
|
||||||
),
|
),
|
||||||
|
isDebitable: isCreditDebit(
|
||||||
|
j,
|
||||||
|
numRequiredSignatures,
|
||||||
|
numCreditOnlySignedAccounts,
|
||||||
|
numCreditOnlyUnsignedAccounts,
|
||||||
|
accounts.length,
|
||||||
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let instruction = new TransactionInstruction(instructionData);
|
let instruction = new TransactionInstruction(instructionData);
|
||||||
|
|
|
@ -28,7 +28,7 @@ test('load BPF C program', async () => {
|
||||||
const data = await fs.readFile('test/fixtures/noop-c/noop.so');
|
const data = await fs.readFile('test/fixtures/noop-c/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: [{pubkey: from.publicKey, isSigner: true}],
|
keys: [{pubkey: from.publicKey, isSigner: true, isDebitable: true}],
|
||||||
programId,
|
programId,
|
||||||
});
|
});
|
||||||
await sendAndConfirmTransaction(connection, transaction, from);
|
await sendAndConfirmTransaction(connection, transaction, from);
|
||||||
|
@ -47,7 +47,7 @@ test('load BPF Rust program', async () => {
|
||||||
);
|
);
|
||||||
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: [{pubkey: from.publicKey, isSigner: true}],
|
keys: [{pubkey: from.publicKey, isSigner: true, isDebitable: true}],
|
||||||
programId,
|
programId,
|
||||||
});
|
});
|
||||||
await sendAndConfirmTransaction(connection, transaction, from);
|
await sendAndConfirmTransaction(connection, transaction, from);
|
||||||
|
|
|
@ -29,7 +29,7 @@ test('load native program', async () => {
|
||||||
'solana_noop_program',
|
'solana_noop_program',
|
||||||
);
|
);
|
||||||
const transaction = new Transaction().add({
|
const transaction = new Transaction().add({
|
||||||
keys: [{pubkey: from.publicKey, isSigner: true}],
|
keys: [{pubkey: from.publicKey, isSigner: true, isDebitable: true}],
|
||||||
programId,
|
programId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -93,73 +93,73 @@ test('parse wire format and serialize', () => {
|
||||||
|
|
||||||
const wireTransaction = Buffer.from([
|
const wireTransaction = Buffer.from([
|
||||||
1,
|
1,
|
||||||
91,
|
47,
|
||||||
132,
|
50,
|
||||||
173,
|
66,
|
||||||
1,
|
|
||||||
218,
|
|
||||||
94,
|
|
||||||
253,
|
|
||||||
18,
|
|
||||||
27,
|
|
||||||
79,
|
|
||||||
207,
|
|
||||||
114,
|
|
||||||
27,
|
|
||||||
167,
|
|
||||||
127,
|
|
||||||
17,
|
17,
|
||||||
202,
|
219,
|
||||||
183,
|
90,
|
||||||
204,
|
187,
|
||||||
12,
|
49,
|
||||||
69,
|
|
||||||
243,
|
|
||||||
25,
|
|
||||||
206,
|
|
||||||
165,
|
|
||||||
116,
|
|
||||||
182,
|
|
||||||
64,
|
|
||||||
185,
|
|
||||||
168,
|
|
||||||
238,
|
|
||||||
168,
|
|
||||||
193,
|
|
||||||
140,
|
|
||||||
86,
|
|
||||||
83,
|
|
||||||
107,
|
|
||||||
252,
|
|
||||||
239,
|
|
||||||
80,
|
|
||||||
40,
|
40,
|
||||||
91,
|
77,
|
||||||
44,
|
8,
|
||||||
6,
|
58,
|
||||||
160,
|
129,
|
||||||
84,
|
51,
|
||||||
43,
|
76,
|
||||||
227,
|
|
||||||
63,
|
|
||||||
170,
|
|
||||||
255,
|
|
||||||
185,
|
|
||||||
132,
|
|
||||||
242,
|
|
||||||
82,
|
|
||||||
46,
|
|
||||||
124,
|
|
||||||
217,
|
|
||||||
127,
|
|
||||||
147,
|
|
||||||
24,
|
|
||||||
254,
|
|
||||||
157,
|
|
||||||
13,
|
13,
|
||||||
|
206,
|
||||||
|
126,
|
||||||
|
157,
|
||||||
|
189,
|
||||||
|
188,
|
||||||
|
53,
|
||||||
|
174,
|
||||||
|
42,
|
||||||
|
80,
|
||||||
|
4,
|
||||||
|
4,
|
||||||
|
212,
|
||||||
|
55,
|
||||||
|
67,
|
||||||
|
171,
|
||||||
|
34,
|
||||||
|
224,
|
||||||
|
81,
|
||||||
|
68,
|
||||||
|
230,
|
||||||
|
120,
|
||||||
|
117,
|
||||||
|
204,
|
||||||
|
241,
|
||||||
|
167,
|
||||||
|
152,
|
||||||
|
74,
|
||||||
|
141,
|
||||||
|
132,
|
||||||
|
73,
|
||||||
|
166,
|
||||||
|
217,
|
||||||
|
173,
|
||||||
|
27,
|
||||||
|
75,
|
||||||
|
62,
|
||||||
|
171,
|
||||||
|
160,
|
||||||
|
100,
|
||||||
|
159,
|
||||||
|
116,
|
||||||
|
164,
|
||||||
|
45,
|
||||||
|
185,
|
||||||
|
64,
|
||||||
|
0,
|
||||||
|
72,
|
||||||
|
4,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
1,
|
2,
|
||||||
3,
|
3,
|
||||||
19,
|
19,
|
||||||
152,
|
152,
|
||||||
|
|
Loading…
Reference in New Issue