-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support decompiling transaction messages fetched using getTransaction
that involve lookup tables in a single pass.
#15
Comments
getTransaction
in a single pass.getTransaction
that involve lookup tables in a single pass.
This sounds like a good idea! I think we could implement it like this, contingent on the RPC ordering things sensibly (which I haven't checked):
"loadedAddresses": {
"readonly": [
"So11111111111111111111111111111111111111112",
"5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1",
"675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"
],
"writable": [
"728XPhZKjAYWp6dys98pvQg1zukjRq5Cckt2tqpEDgrS",
"9DZiJL5dwHVje2MeDNAWNZkxYvF6y7jzqZUxS5BPFFdn",
"GJmxsfhhho2nej3Bc2kSpc7DGJBPXPAinAYTkTHsKRob"
]
},
"addressTableLookups": [
{
"accountKey": "GtXcpBiwyhpd8sJrUDcBaRKWt3oUnsZijwBWP4hwJh3y",
"readonlyIndexes": [
23,
3,
0
],
"writableIndexes": [
155,
158,
153
]
}
], This should be sufficient to generate Eg {
address: 'So11111111111111111111111111111111111111112',
addressIndex: 23,
lookupTableAddress: 'GtXcpBiwyhpd8sJrUDcBaRKWt3oUnsZijwBWP4hwJh3y',
role: AccountRole.READONLY The assumption this is contingent on is how the RPC orders Suppose we add another address table lookup: "addressTableLookups": [
{
"accountKey": "GtXcpBiwyhpd8sJrUDcBaRKWt3oUnsZijwBWP4hwJh3y",
"readonlyIndexes": [
23,
3,
0
],
"writableIndexes": [
155,
158,
153
]
},
{
"accountKey": "test",
"readonlyIndexes": [0],
"writableIndexes": [1]
}
], Then "loadedAddresses": {
"readonly": [
"So11111111111111111111111111111111111111112",
"5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1",
"675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8",
"index 0 of test"
],
"writable": [
"728XPhZKjAYWp6dys98pvQg1zukjRq5Cckt2tqpEDgrS",
"9DZiJL5dwHVje2MeDNAWNZkxYvF6y7jzqZUxS5BPFFdn",
"GJmxsfhhho2nej3Bc2kSpc7DGJBPXPAinAYTkTHsKRob",
"index 1 of test"
]
}, We will then have enough information to correctly map these addresses to their lookup table and index. As an aside the function names I used here are pretty bad, probably need to think of something better and more descriptive. |
It looks like it just concatenates the readable and writable addresses together. As for how it orders the addresses of the lookup table accounts themselves, it looks like it's just in the order found in the message. Whatever we do, we shouldn't bother // NEW
const addressesByLookupTableAddress = createAddressesByLookupTableAddressFromLoadedAddresses({
addressTableLookups, // compiledTransactionMessage.addressTableLookups
loadedAddresses, // result.meta.loadedAddresses
});
// EXISTING
const message = decompileTransactionMessage(compiledTransactionMessage, {
addressesByLookupTableAddress,
}); |
@steveluscher thanks for the links with regards to ordering - I implemented I confirmed that addresses are fetched and ordered correctly. Test code below references a random transaction I picked off of a recent slot. it.only("works", async () => {
const rpc = createRpc({ ... });
const raw = await rpc
.getTransaction(
signature(
"23ziNjdwh6bMYBkGnbTNHuYYmWa6tBmNrmvDBpp2U7DgSUFtzhXPkriDdyrCmVRWxs97yK7HKMmtP6msH655yTtM"
),
{
maxSupportedTransactionVersion: 0,
encoding: "base64",
}
)
.send();
const tx = getTransactionDecoder().decode(
Buffer.from(raw!.transaction[0], "base64")
);
const compiledTransactionMessage =
getCompiledTransactionMessageDecoder().decode(tx.messageBytes);
function createAddressesByLookupTableAddressFromLoadedAddresses({
loadedAddresses,
addressTableLookups,
}: {
loadedAddresses: {
writable: readonly Address[];
readonly: readonly Address[];
};
addressTableLookups: {
lookupTableAddress: Address;
writableIndices: readonly number[];
readableIndices: readonly number[];
}[];
}) {
const addressesByLookupTableAddress: AddressesByLookupTableAddress = {};
const loadedWritableAddresses = [...loadedAddresses.writable];
const loadedReadonlyAddresses = [...loadedAddresses.readonly];
for (const lookup of addressTableLookups) {
const lookupTableAddresses = new Array<Address>();
for (const writableIndex of lookup.writableIndices) {
lookupTableAddresses[writableIndex] = loadedWritableAddresses.shift()!;
}
for (const readableIndex of lookup.readableIndices) {
lookupTableAddresses[readableIndex] = loadedReadonlyAddresses.shift()!;
}
addressesByLookupTableAddress[lookup.lookupTableAddress] =
lookupTableAddresses;
}
return addressesByLookupTableAddress;
}
let addressesByLookupTableAddress: AddressesByLookupTableAddress | undefined =
undefined;
if (
"addressTableLookups" in compiledTransactionMessage &&
compiledTransactionMessage.addressTableLookups !== undefined &&
raw?.meta?.loadedAddresses !== undefined
) {
addressesByLookupTableAddress =
createAddressesByLookupTableAddressFromLoadedAddresses({
loadedAddresses: raw.meta.loadedAddresses,
addressTableLookups: compiledTransactionMessage.addressTableLookups,
});
}
const transactionMessage = decompileTransactionMessage(
compiledTransactionMessage,
{
addressesByLookupTableAddress,
}
);
console.dir(transactionMessage, { depth: Infinity });
}); |
Neat. If you want to write comprehensive tests for that, write a README entry, and PR it up for |
Feel free to knock out solana-labs/web3.js-issue-conveyer#12 while you're in this area. |
Motivation
Suppose we use
getTransaction
to fetch the base64/base58-encoded bytes of a v0 transaction.getTransaction
additionally provides the list of addresses which the transaction loads from lookup tables asmeta.loadedAddresses
.It would be great to be able to provide
meta.loadedAddresses
todecompileTransactionMessage
in order to fully decode a transaction message.Doing this manually at the moment is quite a bit of boilerplate and requires in-depth understanding as to how addresses are organized within a v0 transaction.
A workaround at the moment is to use
decodeTransactionMessage
, thoughdecodeTransactionMessage
in this case would inefficiently fetch the lookup table's addresses from the RPC even though we already have the data at hand fromgetTransaction
.Example use case
Details
N/A
The text was updated successfully, but these errors were encountered: