Line data Source code
1 : #include "fd_hashes.h"
2 : #include "fd_acc_mgr.h"
3 : #include "fd_bank.h"
4 : #include "context/fd_capture_ctx.h"
5 : #include "../capture/fd_solcap_writer.h"
6 : #include "../../ballet/blake3/fd_blake3.h"
7 : #include "../../ballet/lthash/fd_lthash.h"
8 : #include "../../ballet/sha256/fd_sha256.h"
9 : #include "fd_txn_account.h"
10 :
11 : void
12 : fd_hashes_account_lthash( fd_pubkey_t const * pubkey,
13 : fd_account_meta_t const * account,
14 : uchar const * data,
15 924 : fd_lthash_value_t * lthash_out ) {
16 924 : fd_hashes_account_lthash_simple( pubkey->uc,
17 924 : account->owner,
18 924 : account->lamports,
19 924 : account->executable,
20 924 : data,
21 924 : account->dlen,
22 924 : lthash_out );
23 924 : }
24 :
25 : void
26 : fd_hashes_account_lthash_simple( uchar const pubkey[ static FD_HASH_FOOTPRINT ],
27 : uchar const owner[ static FD_HASH_FOOTPRINT ],
28 : ulong lamports,
29 : uchar executable,
30 : uchar const * data,
31 : ulong data_len,
32 924 : fd_lthash_value_t * lthash_out ) {
33 924 : fd_lthash_zero( lthash_out );
34 :
35 : /* Accounts with zero lamports are not included in the hash, so they should always be treated as zero */
36 924 : if( FD_UNLIKELY( lamports == 0 ) ) {
37 9 : return;
38 9 : }
39 :
40 915 : uchar executable_flag = executable & 0x1;
41 :
42 915 : fd_blake3_t b3[1];
43 915 : fd_blake3_init( b3 );
44 915 : fd_blake3_append( b3, &lamports, sizeof( ulong ) );
45 915 : fd_blake3_append( b3, data, data_len );
46 915 : fd_blake3_append( b3, &executable_flag, sizeof( uchar ) );
47 915 : fd_blake3_append( b3, owner, FD_HASH_FOOTPRINT );
48 915 : fd_blake3_append( b3, pubkey, FD_HASH_FOOTPRINT );
49 915 : fd_blake3_fini_2048( b3, lthash_out->bytes );
50 915 : }
51 :
52 : void
53 : fd_hashes_hash_bank( fd_lthash_value_t const * lthash,
54 : fd_hash_t const * prev_bank_hash,
55 : fd_hash_t const * last_blockhash,
56 : ulong signature_count,
57 0 : fd_hash_t * hash_out ) {
58 :
59 : /* The bank hash for a slot is a sha256 of two sub-hashes:
60 : sha256(
61 : sha256( previous bank hash, signature count, last PoH blockhash ),
62 : lthash of the accounts modified in this slot
63 : )
64 : */
65 0 : fd_sha256_t sha;
66 0 : fd_sha256_init( &sha );
67 0 : fd_sha256_append( &sha, prev_bank_hash, sizeof( fd_hash_t ) );
68 0 : fd_sha256_append( &sha, (uchar const *) &signature_count, sizeof( ulong ) );
69 0 : fd_sha256_append( &sha, (uchar const *) last_blockhash, sizeof( fd_hash_t ) );
70 0 : fd_sha256_fini( &sha, hash_out->hash );
71 :
72 0 : fd_sha256_init( &sha );
73 0 : fd_sha256_append( &sha, (uchar const *) hash_out->hash, sizeof(fd_hash_t) );
74 0 : fd_sha256_append( &sha, (uchar const *) lthash->bytes, sizeof(fd_lthash_value_t) );
75 0 : fd_sha256_fini( &sha, hash_out->hash );
76 0 : }
77 :
78 : void
79 : fd_hashes_update_lthash( fd_txn_account_t const * account,
80 : fd_lthash_value_t const * prev_account_hash,
81 : fd_bank_t * bank,
82 462 : fd_capture_ctx_t * capture_ctx ) {
83 :
84 : /* Hash the new version of the account */
85 462 : fd_lthash_value_t new_hash[1];
86 462 : fd_account_meta_t const * meta = fd_txn_account_get_meta( account );
87 462 : fd_hashes_account_lthash( account->pubkey, meta, fd_txn_account_get_data( account ), new_hash );
88 :
89 : /* Subtract the old hash of the account from the bank lthash */
90 462 : fd_lthash_value_t * bank_lthash = fd_type_pun( fd_bank_lthash_locking_modify( bank ) );
91 462 : fd_lthash_sub( bank_lthash, prev_account_hash );
92 :
93 : /* Add the new hash of the account to the bank lthash */
94 462 : fd_lthash_add( bank_lthash, new_hash );
95 :
96 462 : fd_bank_lthash_end_locking_modify( bank );
97 :
98 : /* Write the new account state to the capture file */
99 462 : if( capture_ctx && capture_ctx->capture &&
100 462 : fd_bank_slot_get( bank )>=capture_ctx->solcap_start_slot &&
101 462 : memcmp( prev_account_hash->bytes, new_hash->bytes, sizeof(fd_lthash_value_t))!=0 ) {
102 0 : fd_solana_account_meta_t meta = fd_txn_account_get_solana_meta( account );
103 0 : int err = fd_solcap_write_account(
104 0 : capture_ctx->capture,
105 0 : account->pubkey,
106 0 : &meta,
107 0 : fd_txn_account_get_data( account ),
108 0 : fd_txn_account_get_data_len( account ) );
109 0 : if( FD_UNLIKELY( err ) ) {
110 0 : FD_LOG_ERR(( "Failed to write account to capture file" ));
111 0 : }
112 0 : }
113 462 : }
|