From b5f3ced860537ef5b0bcafec5b4885b1bc5d0b9e Mon Sep 17 00:00:00 2001 From: Michael Vines Date: Fri, 14 Aug 2020 23:53:58 -0700 Subject: [PATCH] Add base64 (binary64) encoding for getConfirmedTransaction/getConfirmedBlock --- Cargo.lock | 1 + cli/src/cli.rs | 2 +- docs/src/apps/jsonrpc-api.md | 30 +++++++++++++++--------------- ledger-tool/src/bigtable.rs | 6 +++--- ledger/src/blockstore.rs | 4 ++-- stake-monitor/src/lib.rs | 4 +++- transaction-status/Cargo.toml | 1 + transaction-status/src/lib.rs | 25 ++++++++++++++++++++----- watchtower/src/main.rs | 2 +- 9 files changed, 47 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 97f3184b87..6f73a4d84e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4467,6 +4467,7 @@ name = "solana-transaction-status" version = "1.4.0" dependencies = [ "Inflector", + "base64 0.12.3", "bincode", "bs58", "lazy_static", diff --git a/cli/src/cli.rs b/cli/src/cli.rs index 8fd4f6373e..c9078e876b 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -1068,7 +1068,7 @@ fn process_confirm( if let Some(transaction_status) = status { if config.verbose { match rpc_client - .get_confirmed_transaction(signature, UiTransactionEncoding::Binary) + .get_confirmed_transaction(signature, UiTransactionEncoding::Binary64) { Ok(confirmed_transaction) => { println!( diff --git a/docs/src/apps/jsonrpc-api.md b/docs/src/apps/jsonrpc-api.md index 781f1291fc..6cc512197a 100644 --- a/docs/src/apps/jsonrpc-api.md +++ b/docs/src/apps/jsonrpc-api.md @@ -157,7 +157,7 @@ Returns all information associated with the account of provided Pubkey - `` - Pubkey of account to query, as base-58 encoded string - `` - (optional) Configuration object containing the following optional fields: - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment) - - (optional) `encoding: ` - encoding for Account data, either "binary", "binary64", or jsonParsed". If parameter not provided, the default encoding is "binary". "binary" is base-58 encoded and limited to Account data of less than 128 bytes. "binary64" will return base64 encoded data for Account data of any size. + - (optional) `encoding: ` - encoding for Account data, either "binary" (*slow*), "binary64", or jsonParsed". If parameter not provided, the default encoding is "binary". "binary" is base-58 encoded and limited to Account data of less than 128 bytes. "binary64" will return base64 encoded data for Account data of any size. Parsed-JSON encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If parsed-JSON is requested but a parser cannot be found, the field falls back to binary encoding, detectable when the `data` field is type ``. **jsonParsed encoding is UNSTABLE** - (optional) `dataSlice: ` - limit the returned account data using the provided `offset: ` and `length: ` fields; only available for "binary" or "binary64" encoding. @@ -307,7 +307,7 @@ Returns identity and transaction information about a confirmed block in the ledg #### Parameters: - `` - slot, as u64 integer -- `` - (optional) encoding for each returned Transaction, either "json", "jsonParsed", or "binary". If parameter not provided, the default encoding is JSON. **jsonParsed encoding is UNSTABLE** +- `` - (optional) encoding for each returned Transaction, either "json", "jsonParsed", "binary" (*slow*), or "binary64". If parameter not provided, the default encoding is JSON. **jsonParsed encoding is UNSTABLE** Parsed-JSON encoding attempts to use program-specific instruction parsers to return more human-readable and explicit data in the `transaction.message.instructions` list. If parsed-JSON is requested but a parser cannot be found, the instruction falls back to regular JSON encoding (`accounts`, `data`, and `programIdIndex` fields). #### Results: @@ -341,13 +341,13 @@ The result field will be an object with the following fields: curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id":1,"method":"getConfirmedBlock","params":[430, "json"]}' localhost:8899 // Result -{"jsonrpc":"2.0","result":{"blockhash":"Gp3t5bfDsJv1ovP8cB1SuRhXVuoTqDv7p3tymyubYg5","parentSlot":429,"previousBlockhash":"EFejToxii1L5aUF2NrK9dsbAEmZSNyN5nsipmZHQR1eA","transactions":[{"transaction":{"message":{"accountKeys":["6H94zdiaYfRfPfKjYLjyr2VFBg6JHXygy84r3qhc3NsC","39UAy8hsoYPywGPGdmun747omSr79zLSjqvPJN3zetoH","SysvarS1otHashes111111111111111111111111111","SysvarC1ock11111111111111111111111111111111","Vote111111111111111111111111111111111111111"],"header":{"numReadonlySignedAccounts":0,"numReadonlyUnsignedAccounts":3,"numRequiredSignatures":2},"instructions":[{"accounts":[1,2,3],"data":"29z5mr1JoRmJYQ6ynmk3pf31cGFRziAF1M3mT3L6sFXf5cKLdkEaMXMT8AqLpD4CpcupHmuMEmtZHpomrwfdZetSomNy3d","programIdIndex":4}],"recentBlockhash":"EFejToxii1L5aUF2NrK9dsbAEmZSNyN5nsipmZHQR1eA"},"signatures":["35YGay1Lwjwgxe9zaH6APSHbt9gYQUCtBWTNL3aVwVGn9xTFw2fgds7qK5AL29mP63A9j3rh8KpN1TgSR62XCaby","4vANMjSKiwEchGSXwVrQkwHnmsbKQmy9vdrsYxWdCup1bLsFzX8gKrFTSVDCZCae2dbxJB9mPNhqB2sD1vvr4sAD"]},"meta":{"err":null,"fee":18000,"postBalances":[499999972500,15298080,1,1,1],"preBalances":[499999990500,15298080,1,1,1],"status":{"Ok":null}}}]},"id":1} +{"jsonrpc":"2.0","result":{"blockTime":null,"blockhash":"3Eq21vXNB5s86c62bVuUfTeaMif1N2kUqRPBmGRJhyTA","parentSlot":429,"previousBlockhash":"mfcyqEXB3DnHXki6KjjmZck6YjmZLvpAByy2fj4nh6B","rewards":[],"transactions":[{"meta":{"err":null,"fee":5000,"postBalances":[499998932500,26858640,1,1,1],"preBalances":[499998937500,26858640,1,1,1],"status":{"Ok":null}},"transaction":{"message":{"accountKeys":["3UVYmECPPMZSCqWKfENfuoTv51fTDTWicX9xmBD2euKe","AjozzgE83A3x1sHNUR64hfH7zaEBWeMaFuAN9kQgujrc","SysvarS1otHashes111111111111111111111111111","SysvarC1ock11111111111111111111111111111111","Vote111111111111111111111111111111111111111"],"header":{"numReadonlySignedAccounts":0,"numReadonlyUnsignedAccounts":3,"numRequiredSignatures":1},"instructions":[{"accounts":[1,2,3,0],"data":"37u9WtQpcm6ULa3WRQHmj49EPs4if7o9f1jSRVZpm2dvihR9C8jY4NqEwXUbLwx15HBSNcP1","programIdIndex":4}],"recentBlockhash":"mfcyqEXB3DnHXki6KjjmZck6YjmZLvpAByy2fj4nh6B"},"signatures":["2nBhEBYYvfaAe16UMNqRHre4YNSskvuYgx3M6E4JP1oDYvZEJHvoPzyUidNgNX5r9sTyN1J9UxtbCXy2rqYcuyuv"]}}]},"id":1} // Request -curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id":1,"method":"getConfirmedBlock","params":[430, "binary"]}' localhost:8899 +curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id":1,"method":"getConfirmedBlock","params":[430, "binary64"]}' localhost:8899 // Result -{"jsonrpc":"2.0","result":{"blockhash":"Gp3t5bfDsJv1ovP8cB1SuRhXVuoTqDv7p3tymyubYg5","parentSlot":429,"previousBlockhash":"EFejToxii1L5aUF2NrK9dsbAEmZSNyN5nsipmZHQR1eA","transactions":[{"transaction":"81UZJt4dh4Do66jDhrgkQudS8J2N6iG3jaVav7gJrqJSFY4Ug53iA9JFJZh2gxKWcaFdLJwhHx9mRdg9JwDAWB4ywiu5154CRwXV4FMdnPLg7bhxRLwhhYaLsVgMF5AyNRcTzjCVoBvqFgDU7P8VEKDEiMvD3qxzm1pLZVxDG1LTQpT3Dz4Uviv4KQbFQNuC22KupBoyHFB7Zh6KFdMqux4M9PvhoqcoJsJKwXjWpKu7xmEKnnrSbfLadkgjBmmjhW3fdTrFvnhQdTkhtdJxUL1xS9GMuJQer8YgSKNtUXB1eXZQwXU8bU2BjYkZE6Q5Xww8hu9Z4E4Mo4QsooVtHoP6BM3NKw8zjVbWfoCQqxTrwuSzrNCWCWt58C24LHecH67CTt2uXbYSviixvrYkK7A3t68BxTJcF1dXJitEPTFe2ceTkauLJqrJgnER4iUrsjr26T8YgWvpY9wkkWFSviQW6wV5RASTCUasVEcrDiaKj8EQMkgyDoe9HyKitSVg67vMWJFpUXpQobseWJUs5FTWWzmfHmFp8FZ","meta":{"err":null,"fee":18000,"postBalances":[499999972500,15298080,1,1,1],"preBalances":[499999990500,15298080,1,1,1],"status":{"Ok":null}}}]},"id":1} +{"jsonrpc":"2.0","result":{"blockTime":null,"blockhash":"3Eq21vXNB5s86c62bVuUfTeaMif1N2kUqRPBmGRJhyTA","parentSlot":429,"previousBlockhash":"mfcyqEXB3DnHXki6KjjmZck6YjmZLvpAByy2fj4nh6B","rewards":[],"transactions":[{"meta":{"err":null,"fee":5000,"postBalances":[499998932500,26858640,1,1,1],"preBalances":[499998937500,26858640,1,1,1],"status":{"Ok":null}},"transaction":"AVj7dxHlQ9IrvdYVIjuiRFs1jLaDMHixgrv+qtHBwz51L4/ImLZhszwiyEJDIp7xeBSpm/TX5B7mYzxa+fPOMw0BAAMFJMJVqLw+hJYheizSoYlLm53KzgT82cDVmazarqQKG2GQsLgiqktA+a+FDR4/7xnDX7rsusMwryYVUdixfz1B1Qan1RcZLwqvxvJl4/t3zHragsUp0L47E24tAFUgAAAABqfVFxjHdMkoVmOYaR1etoteuKObS21cc1VbIQAAAAAHYUgdNXR0u3xNdiTr072z2DVec9EQQ/wNo1OAAAAAAAtxOUhPBp2WSjUNJEgfvy70BbxI00fZyEPvFHNfxrtEAQQEAQIDADUCAAAAAQAAAAAAAACtAQAAAAAAAAdUE18R96XTJCe+YfRfUp6WP+YKCy/72ucOL8AoBFSpAA=="}]},"id":1} ``` #### Transaction Structure @@ -465,7 +465,7 @@ Returns transaction details for a confirmed transaction - `` - transaction signature as base-58 encoded string N encoding attempts to use program-specific instruction parsers to return more human-readable and explicit data in the `transaction.message.instructions` list. If parsed-JSON is requested but a parser cannot be found, the instruction falls back to regular JSON encoding (`accounts`, `data`, and `programIdIndex` fields). -- `` - (optional) encoding for the returned Transaction, either "json", "jsonParsed", or "binary". **jsonParsed encoding is UNSTABLE** +- `` - (optional) encoding for the returned Transaction, either "json", "jsonParsed", "binary" (*slow*), or "binary64". If parameter not provided, the default encoding is JSON. **jsonParsed encoding is UNSTABLE** #### Results: @@ -486,16 +486,16 @@ N encoding attempts to use program-specific instruction parsers to return more h ```bash // Request -curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id":1,"method":"getConfirmedTransaction","params":["35YGay1Lwjwgxe9zaH6APSHbt9gYQUCtBWTNL3aVwVGn9xTFw2fgds7qK5AL29mP63A9j3rh8KpN1TgSR62XCaby", "json"]}' localhost:8899 +curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id":1,"method":"getConfirmedTransaction","params":["2nBhEBYYvfaAe16UMNqRHre4YNSskvuYgx3M6E4JP1oDYvZEJHvoPzyUidNgNX5r9sTyN1J9UxtbCXy2rqYcuyuv", "json"]}' localhost:8899 // Result -{"jsonrpc":"2.0","result":{"slot":430,"transaction":{"message":{"accountKeys":["6H94zdiaYfRfPfKjYLjyr2VFBg6JHXygy84r3qhc3NsC","39UAy8hsoYPywGPGdmun747omSr79zLSjqvPJN3zetoH","SysvarS1otHashes111111111111111111111111111","SysvarC1ock11111111111111111111111111111111","Vote111111111111111111111111111111111111111"],"header":{"numReadonlySignedAccounts":0,"numReadonlyUnsignedAccounts":3,"numRequiredSignatures":2},"instructions":[{"accounts":[1,2,3],"data":"29z5mr1JoRmJYQ6ynmk3pf31cGFRziAF1M3mT3L6sFXf5cKLdkEaMXMT8AqLpD4CpcupHmuMEmtZHpomrwfdZetSomNy3d","programIdIndex":4}],"recentBlockhash":"EFejToxii1L5aUF2NrK9dsbAEmZSNyN5nsipmZHQR1eA"},"signatures":["35YGay1Lwjwgxe9zaH6APSHbt9gYQUCtBWTNL3aVwVGn9xTFw2fgds7qK5AL29mP63A9j3rh8KpN1TgSR62XCaby","4vANMjSKiwEchGSXwVrQkwHnmsbKQmy9vdrsYxWdCup1bLsFzX8gKrFTSVDCZCae2dbxJB9mPNhqB2sD1vvr4sAD"]},"meta":{"err":null,"fee":18000,"postBalances":[499999972500,15298080,1,1,1],"preBalances":[499999990500,15298080,1,1,1],"status":{"Ok":null}}},"id":1} +{"jsonrpc":"2.0","result":{"meta":{"err":null,"fee":5000,"postBalances":[499998932500,26858640,1,1,1],"preBalances":[499998937500,26858640,1,1,1],"status":{"Ok":null}},"slot":430,"transaction":{"message":{"accountKeys":["3UVYmECPPMZSCqWKfENfuoTv51fTDTWicX9xmBD2euKe","AjozzgE83A3x1sHNUR64hfH7zaEBWeMaFuAN9kQgujrc","SysvarS1otHashes111111111111111111111111111","SysvarC1ock11111111111111111111111111111111","Vote111111111111111111111111111111111111111"],"header":{"numReadonlySignedAccounts":0,"numReadonlyUnsignedAccounts":3,"numRequiredSignatures":1},"instructions":[{"accounts":[1,2,3,0],"data":"37u9WtQpcm6ULa3WRQHmj49EPs4if7o9f1jSRVZpm2dvihR9C8jY4NqEwXUbLwx15HBSNcP1","programIdIndex":4}],"recentBlockhash":"mfcyqEXB3DnHXki6KjjmZck6YjmZLvpAByy2fj4nh6B"},"signatures":["2nBhEBYYvfaAe16UMNqRHre4YNSskvuYgx3M6E4JP1oDYvZEJHvoPzyUidNgNX5r9sTyN1J9UxtbCXy2rqYcuyuv"]}},"id":1} // Request -curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id":1,"method":"getConfirmedTransaction","params":["35YGay1Lwjwgxe9zaH6APSHbt9gYQUCtBWTNL3aVwVGn9xTFw2fgds7qK5AL29mP63A9j3rh8KpN1TgSR62XCaby", "binary"]}' localhost:8899 +curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id":1,"method":"getConfirmedTransaction","params":["2nBhEBYYvfaAe16UMNqRHre4YNSskvuYgx3M6E4JP1oDYvZEJHvoPzyUidNgNX5r9sTyN1J9UxtbCXy2rqYcuyuv", "binary64"]}' localhost:8899 // Result -{"jsonrpc":"2.0","result":{"slot":430,"transaction":"81UZJt4dh4Do66jDhrgkQudS8J2N6iG3jaVav7gJrqJSFY4Ug53iA9JFJZh2gxKWcaFdLJwhHx9mRdg9JwDAWB4ywiu5154CRwXV4FMdnPLg7bhxRLwhhYaLsVgMF5AyNRcTzjCVoBvqFgDU7P8VEKDEiMvD3qxzm1pLZVxDG1LTQpT3Dz4Uviv4KQbFQNuC22KupBoyHFB7Zh6KFdMqux4M9PvhoqcoJsJKwXjWpKu7xmEKnnrSbfLadkgjBmmjhW3fdTrFvnhQdTkhtdJxUL1xS9GMuJQer8YgSKNtUXB1eXZQwXU8bU2BjYkZE6Q5Xww8hu9Z4E4Mo4QsooVtHoP6BM3NKw8zjVbWfoCQqxTrwuSzrNCWCWt58C24LHecH67CTt2uXbYSviixvrYkK7A3t68BxTJcF1dXJitEPTFe2ceTkauLJqrJgnER4iUrsjr26T8YgWvpY9wkkWFSviQW6wV5RASTCUasVEcrDiaKj8EQMkgyDoe9HyKitSVg67vMWJFpUXpQobseWJUs5FTWWzmfHmFp8FZ","meta":{"err":null,"fee":18000,"postBalances":[499999972500,15298080,1,1,1],"preBalances":[499999990500,15298080,1,1,1],"status":{"Ok":null}}},"id":1} +{"jsonrpc":"2.0","result":{"meta":{"err":null,"fee":5000,"postBalances":[499998932500,26858640,1,1,1],"preBalances":[499998937500,26858640,1,1,1],"status":{"Ok":null}},"slot":430,"transaction":"AVj7dxHlQ9IrvdYVIjuiRFs1jLaDMHixgrv+qtHBwz51L4/ImLZhszwiyEJDIp7xeBSpm/TX5B7mYzxa+fPOMw0BAAMFJMJVqLw+hJYheizSoYlLm53KzgT82cDVmazarqQKG2GQsLgiqktA+a+FDR4/7xnDX7rsusMwryYVUdixfz1B1Qan1RcZLwqvxvJl4/t3zHragsUp0L47E24tAFUgAAAABqfVFxjHdMkoVmOYaR1etoteuKObS21cc1VbIQAAAAAHYUgdNXR0u3xNdiTr072z2DVec9EQQ/wNo1OAAAAAAAtxOUhPBp2WSjUNJEgfvy70BbxI00fZyEPvFHNfxrtEAQQEAQIDADUCAAAAAQAAAAAAAACtAQAAAAAAAAdUE18R96XTJCe+YfRfUp6WP+YKCy/72ucOL8AoBFSpAA=="},"id":1} ``` ### getEpochInfo @@ -845,7 +845,7 @@ Returns all accounts owned by the provided program Pubkey - `` - Pubkey of program, as base-58 encoded string - `` - (optional) Configuration object containing the following optional fields: - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment) - - (optional) `encoding: ` - encoding for Account data, either "binary" or jsonParsed". If parameter not provided, the default encoding is binary. + - (optional) `encoding: ` - encoding for Account data, either "binary" (*slow*), "binary64" or jsonParsed". If parameter not provided, the default encoding is binary. Parsed-JSON encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If parsed-JSON is requested but a parser cannot be found, the field falls back to binary encoding, detectable when the `data` field is type ``. **jsonParsed encoding is UNSTABLE** - (optional) `dataSlice: ` - limit the returned account data using the provided `offset: ` and `length: ` fields; only available for "binary" or "binary64" encoding. - (optional) `filters: ` - filter results using various [filter objects](jsonrpc-api.md#filters); account must meet all filter criteria to be included in results @@ -1100,7 +1100,7 @@ Returns all SPL Token accounts by approved Delegate. **UNSTABLE** * `programId: ` - Pubkey of the Token program ID that owns the accounts, as base-58 encoded string - `` - (optional) Configuration object containing the following optional fields: - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment) - - (optional) `encoding: ` - encoding for Account data, either "binary" or jsonParsed". If parameter not provided, the default encoding is binary. + - (optional) `encoding: ` - encoding for Account data, either "binary" (*slow*), "binary64" or jsonParsed". If parameter not provided, the default encoding is binary. Parsed-JSON encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If parsed-JSON is requested but a parser cannot be found, the field falls back to binary encoding, detectable when the `data` field is type ``. **jsonParsed encoding is UNSTABLE** - (optional) `dataSlice: ` - limit the returned account data using the provided `offset: ` and `length: ` fields; only available for "binary" or "binary64" encoding. @@ -1137,7 +1137,7 @@ Returns all SPL Token accounts by token owner. **UNSTABLE** * `programId: ` - Pubkey of the Token program ID that owns the accounts, as base-58 encoded string - `` - (optional) Configuration object containing the following optional fields: - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment) - - (optional) `encoding: ` - encoding for Account data, either "binary" or jsonParsed". If parameter not provided, the default encoding is binary. + - (optional) `encoding: ` - encoding for Account data, either "binary" (*slow*), "binary64" or jsonParsed". If parameter not provided, the default encoding is binary. Parsed-JSON encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If parsed-JSON is requested but a parser cannot be found, the field falls back to binary encoding, detectable when the `data` field is type ``. **jsonParsed encoding is UNSTABLE** - (optional) `dataSlice: ` - limit the returned account data using the provided `offset: ` and `length: ` fields; only available for "binary" or "binary64" encoding. @@ -1457,7 +1457,7 @@ Subscribe to an account to receive notifications when the lamports or data for a - `` - account Pubkey, as base-58 encoded string - `` - (optional) Configuration object containing the following optional fields: - `` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment) - - (optional) `encoding: ` - encoding for Account data, either "binary" or jsonParsed". If parameter not provided, the default encoding is binary. + - (optional) `encoding: ` - encoding for Account data, either "binary" (*slow*), "binary64" or jsonParsed". If parameter not provided, the default encoding is binary. Parsed-JSON encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If parsed-JSON is requested but a parser cannot be found, the field falls back to binary encoding, detectable when the `data` field is type ``. **jsonParsed encoding is UNSTABLE** #### Results: @@ -1567,7 +1567,7 @@ Subscribe to a program to receive notifications when the lamports or data for a - `` - program_id Pubkey, as base-58 encoded string - `` - (optional) Configuration object containing the following optional fields: - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment) - - (optional) `encoding: ` - encoding for Account data, either "binary" or jsonParsed". If parameter not provided, the default encoding is binary. + - (optional) `encoding: ` - encoding for Account data, either "binary" (*slow*), "binary64" or jsonParsed". If parameter not provided, the default encoding is binary. Parsed-JSON encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If parsed-JSON is requested but a parser cannot be found, the field falls back to binary encoding, detectable when the `data` field is type ``. **jsonParsed encoding is UNSTABLE** - (optional) `filters: ` - filter results using various [filter objects](jsonrpc-api.md#filters); account must meet all filter criteria to be included in results diff --git a/ledger-tool/src/bigtable.rs b/ledger-tool/src/bigtable.rs index db70f7283f..8a2b9d1dda 100644 --- a/ledger-tool/src/bigtable.rs +++ b/ledger-tool/src/bigtable.rs @@ -134,7 +134,7 @@ async fn upload( for (i, slot) in blocks_to_upload.iter().enumerate() { let _ = match blockstore.get_confirmed_block( *slot, - Some(solana_transaction_status::UiTransactionEncoding::Binary), + Some(solana_transaction_status::UiTransactionEncoding::Binary64), ) { Ok(confirmed_block) => sender.send((*slot, Some(confirmed_block))), Err(err) => { @@ -231,7 +231,7 @@ async fn block(slot: Slot) -> Result<(), Box> { .map_err(|err| format!("Failed to connect to storage: {:?}", err))?; let block = bigtable - .get_confirmed_block(slot, UiTransactionEncoding::Binary) + .get_confirmed_block(slot, UiTransactionEncoding::Binary64) .await?; println!("Slot: {}", slot); @@ -276,7 +276,7 @@ async fn confirm(signature: &Signature, verbose: bool) -> Result<(), Box { diff --git a/ledger/src/blockstore.rs b/ledger/src/blockstore.rs index 82cd9a551e..1e9b2ff984 100644 --- a/ledger/src/blockstore.rs +++ b/ledger/src/blockstore.rs @@ -1959,7 +1959,7 @@ impl Blockstore { None => return Ok(vec![]), Some((slot, _)) => { let confirmed_block = self - .get_confirmed_block(slot, Some(UiTransactionEncoding::Binary)) + .get_confirmed_block(slot, Some(UiTransactionEncoding::Binary64)) .map_err(|err| { BlockstoreError::IO(IOError::new( ErrorKind::Other, @@ -2013,7 +2013,7 @@ impl Blockstore { None => (0, HashSet::new()), Some((slot, _)) => { let confirmed_block = self - .get_confirmed_block(slot, Some(UiTransactionEncoding::Binary)) + .get_confirmed_block(slot, Some(UiTransactionEncoding::Binary64)) .map_err(|err| { BlockstoreError::IO(IOError::new( ErrorKind::Other, diff --git a/stake-monitor/src/lib.rs b/stake-monitor/src/lib.rs index 09eebfdff4..e8876a364b 100644 --- a/stake-monitor/src/lib.rs +++ b/stake-monitor/src/lib.rs @@ -267,6 +267,8 @@ fn process_confirmed_block( ("err", "Transaction signature verification failed", String) ); } + } else { + error!("Transaction decode failed"); } } } @@ -289,7 +291,7 @@ fn load_blocks( let mut blocks = vec![]; for slot in slots.into_iter() { let block = - rpc_client.get_confirmed_block_with_encoding(slot, UiTransactionEncoding::Binary)?; + rpc_client.get_confirmed_block_with_encoding(slot, UiTransactionEncoding::Binary64)?; blocks.push((slot, block)); } Ok(blocks) diff --git a/transaction-status/Cargo.toml b/transaction-status/Cargo.toml index 83de415c85..3399b7553d 100644 --- a/transaction-status/Cargo.toml +++ b/transaction-status/Cargo.toml @@ -9,6 +9,7 @@ license = "Apache-2.0" edition = "2018" [dependencies] +base64 = "0.12.3" bincode = "1.3.1" bs58 = "0.3.1" Inflector = "0.11.4" diff --git a/transaction-status/src/lib.rs b/transaction-status/src/lib.rs index 6044ee1193..0069e0eeb3 100644 --- a/transaction-status/src/lib.rs +++ b/transaction-status/src/lib.rs @@ -217,7 +217,8 @@ pub struct TransactionWithStatusMeta { #[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq)] #[serde(rename_all = "camelCase")] pub enum UiTransactionEncoding { - Binary, + Binary, // base-58 encoded string. SLOW! Avoid this encoding + Binary64, // base-64 encoded string Json, JsonParsed, } @@ -225,17 +226,22 @@ pub enum UiTransactionEncoding { #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase", untagged)] pub enum EncodedTransaction { - Binary(String), + LegacyBinary(String), + Binary(String, UiTransactionEncoding), Json(UiTransaction), } impl EncodedTransaction { pub fn encode(transaction: Transaction, encoding: UiTransactionEncoding) -> Self { match encoding { - UiTransactionEncoding::Binary => EncodedTransaction::Binary( + UiTransactionEncoding::Binary => EncodedTransaction::LegacyBinary( bs58::encode(bincode::serialize(&transaction).unwrap()).into_string(), ), - _ => { + UiTransactionEncoding::Binary64 => EncodedTransaction::Binary( + base64::encode(bincode::serialize(&transaction).unwrap()), + encoding, + ), + UiTransactionEncoding::Json | UiTransactionEncoding::JsonParsed => { let message = if encoding == UiTransactionEncoding::Json { UiMessage::Raw(UiRawMessage { header: transaction.message.header, @@ -298,10 +304,19 @@ impl EncodedTransaction { pub fn decode(&self) -> Option { match self { EncodedTransaction::Json(_) => None, - EncodedTransaction::Binary(blob) => bs58::decode(blob) + EncodedTransaction::LegacyBinary(blob) => bs58::decode(blob) .into_vec() .ok() .and_then(|bytes| bincode::deserialize(&bytes).ok()), + EncodedTransaction::Binary(blob, encoding) => { + if *encoding == UiTransactionEncoding::Binary64 { + base64::decode(blob) + .ok() + .and_then(|bytes| bincode::deserialize(&bytes).ok()) + } else { + None + } + } } } } diff --git a/watchtower/src/main.rs b/watchtower/src/main.rs index 874aaa7d61..b8abed2aab 100644 --- a/watchtower/src/main.rs +++ b/watchtower/src/main.rs @@ -226,7 +226,7 @@ fn load_blocks( let mut blocks = vec![]; for slot in slots.into_iter() { let block = - rpc_client.get_confirmed_block_with_encoding(slot, UiTransactionEncoding::Binary)?; + rpc_client.get_confirmed_block_with_encoding(slot, UiTransactionEncoding::Binary64)?; blocks.push((slot, block)); } Ok(blocks)