Line data Source code
1 : #include "fd_blockdb.h"
2 : #include "../../ballet/sha256/fd_sha256.h"
3 :
4 : #define MAP_NAME fd_blockdb_map
5 0 : #define MAP_ELE_T fd_blockdb_blk_t
6 : #define MAP_KEY_T fd_blockdb_key_t
7 0 : #define MAP_KEY key
8 0 : #define MAP_IDX_T uint
9 0 : #define MAP_NEXT next
10 0 : #define MAP_PREV prev
11 0 : #define MAP_KEY_EQ(k0,k1) (!memcmp( (k0), (k1), sizeof(fd_blockdb_key_t) ))
12 0 : #define MAP_KEY_HASH(key,seed) fd_hash( (seed), (key), sizeof(fd_blockdb_key_t) )
13 : #define MAP_OPTIMIZE_RANDOM_ACCESS_REMOVAL 1
14 : #include "../../util/tmpl/fd_map_chain.c"
15 :
16 : ulong
17 0 : fd_blockdb_footprint( ulong ele_max ) {
18 0 : if( FD_UNLIKELY( !ele_max || ele_max>=UINT_MAX ) ) return 0UL;
19 :
20 0 : ulong l = FD_LAYOUT_INIT;
21 0 : l = FD_LAYOUT_APPEND( l, alignof(fd_blockdb_t), sizeof(fd_blockdb_t) );
22 0 : l = FD_LAYOUT_APPEND( l, alignof(fd_blockdb_blk_t), ele_max*sizeof(fd_blockdb_blk_t) );
23 0 : l = FD_LAYOUT_APPEND( l, fd_blockdb_map_align(), fd_blockdb_map_footprint( fd_blockdb_map_chain_cnt_est( ele_max ) ) );
24 0 : l = FD_LAYOUT_APPEND( l, FD_BMTREE_COMMIT_ALIGN, FD_BMTREE_COMMIT_FOOTPRINT( FD_BLOCKDB_TREE_LAYER_MAX ) );
25 0 : return FD_LAYOUT_FINI( l, fd_blockdb_align() );
26 0 : }
27 :
28 : void *
29 : fd_blockdb_new( void * shmem,
30 : ulong ele_max,
31 0 : ulong seed ) {
32 0 : if( FD_UNLIKELY( !shmem ) ) {
33 0 : FD_LOG_WARNING(( "NULL mem" ));
34 0 : return NULL;
35 0 : }
36 :
37 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_blockdb_align() ) ) ) {
38 0 : FD_LOG_WARNING(( "misaligned mem" ));
39 0 : return NULL;
40 0 : }
41 :
42 0 : ulong footprint = fd_blockdb_footprint( ele_max );
43 0 : if( FD_UNLIKELY( !footprint ) ) {
44 0 : FD_LOG_WARNING(( "bad ele_max (%lu)", ele_max ));
45 0 : return NULL;
46 0 : }
47 :
48 0 : ulong chain_cnt = fd_blockdb_map_chain_cnt_est( ele_max );
49 :
50 0 : FD_SCRATCH_ALLOC_INIT( l, shmem );
51 0 : fd_blockdb_t * blockdb = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_blockdb_t), sizeof(fd_blockdb_t) );
52 0 : fd_blockdb_blk_t * ele = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_blockdb_blk_t), ele_max*sizeof(fd_blockdb_blk_t) );
53 0 : void * map = FD_SCRATCH_ALLOC_APPEND( l, fd_blockdb_map_align(), fd_blockdb_map_footprint( chain_cnt ) );
54 0 : void * tree = FD_SCRATCH_ALLOC_APPEND( l, FD_BMTREE_COMMIT_ALIGN, FD_BMTREE_COMMIT_FOOTPRINT( FD_BLOCKDB_TREE_LAYER_MAX ) );
55 0 : FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_blockdb_align() )==(ulong)shmem + footprint );
56 0 : FD_TEST( fd_bmtree_depth( FD_FEC_BLK_MAX+1UL )==FD_BLOCKDB_TREE_LAYER_MAX );
57 :
58 0 : blockdb->ele_max = ele_max;
59 0 : blockdb->seq = 0UL;
60 0 : blockdb->ele = ele;
61 0 : blockdb->tree = tree;
62 0 : blockdb->map = fd_blockdb_map_new( map, chain_cnt, seed );
63 0 : if( FD_UNLIKELY( !blockdb->map ) ) return NULL;
64 :
65 0 : return shmem;
66 0 : }
67 :
68 : fd_blockdb_t *
69 0 : fd_blockdb_join( void * shblockdb ) {
70 0 : if( FD_UNLIKELY( !shblockdb ) ) {
71 0 : FD_LOG_WARNING(( "NULL blockdb" ));
72 0 : return NULL;
73 0 : }
74 :
75 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shblockdb, fd_blockdb_align() ) ) ) {
76 0 : FD_LOG_WARNING(( "misaligned blockdb" ));
77 0 : return NULL;
78 0 : }
79 :
80 0 : fd_blockdb_t * blockdb = (fd_blockdb_t *)shblockdb;
81 0 : blockdb->map = fd_blockdb_map_join( blockdb->map );
82 0 : if( FD_UNLIKELY( !blockdb->map ) ) return NULL;
83 :
84 0 : return blockdb;
85 0 : }
86 :
87 : void *
88 0 : fd_blockdb_leave( fd_blockdb_t const * blockdb ) {
89 0 : if( FD_UNLIKELY( !blockdb ) ) {
90 0 : FD_LOG_WARNING(( "NULL blockdb" ));
91 0 : return NULL;
92 0 : }
93 :
94 0 : return (void *)blockdb;
95 0 : }
96 :
97 : void *
98 0 : fd_blockdb_delete( void * shblockdb ) {
99 0 : if( FD_UNLIKELY( !shblockdb ) ) {
100 0 : FD_LOG_WARNING(( "NULL blockdb" ));
101 0 : return NULL;
102 0 : }
103 :
104 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shblockdb, fd_blockdb_align() ) ) ) {
105 0 : FD_LOG_WARNING(( "misaligned blockdb" ));
106 0 : return NULL;
107 0 : }
108 :
109 0 : return shblockdb;
110 0 : }
111 :
112 : fd_blockdb_blk_t *
113 : fd_blockdb_insert( fd_blockdb_t * blockdb,
114 : ulong slot,
115 : fd_hash_t const * block_id,
116 : ulong parent_slot,
117 : fd_hash_t const * parent_block_id,
118 : uint fec_set_cnt,
119 0 : uchar const * merkle_roots ) {
120 0 : if( FD_UNLIKELY( !fec_set_cnt || fec_set_cnt>FD_FEC_BLK_MAX ) ) return NULL;
121 :
122 0 : fd_blockdb_map_t * map = (fd_blockdb_map_t *)blockdb->map;
123 0 : fd_blockdb_key_t key = { .slot = slot, .block_id = *block_id };
124 :
125 0 : fd_blockdb_blk_t * blk = fd_blockdb_map_ele_query( map, &key, NULL, blockdb->ele );
126 0 : if( FD_LIKELY( !blk ) ) {
127 : /* Take the oldest slot, unlinking its previous occupant once the
128 : array has wrapped. */
129 0 : blk = blockdb->ele + (blockdb->seq % blockdb->ele_max);
130 0 : if( FD_LIKELY( blockdb->seq>=blockdb->ele_max ) ) fd_blockdb_map_ele_remove_fast( map, blk, blockdb->ele );
131 0 : blockdb->seq++;
132 0 : blk->key = key;
133 0 : fd_blockdb_map_ele_insert( map, blk, blockdb->ele );
134 0 : }
135 :
136 0 : blk->parent_slot = parent_slot;
137 0 : blk->parent_block_id = *parent_block_id;
138 0 : blk->fec_set_cnt = fec_set_cnt;
139 0 : fd_memcpy( blk->merkle_roots, merkle_roots, fec_set_cnt*FD_SHRED_MERKLE_NODE_SZ );
140 0 : return blk;
141 0 : }
142 :
143 : fd_blockdb_blk_t const *
144 : fd_blockdb_query( fd_blockdb_t const * blockdb,
145 : ulong slot,
146 0 : fd_hash_t const * block_id ) {
147 0 : fd_blockdb_key_t key = { .slot = slot, .block_id = *block_id };
148 0 : return fd_blockdb_map_ele_query_const( (fd_blockdb_map_t const *)blockdb->map, &key, NULL, blockdb->ele );
149 0 : }
150 :
151 : int
152 : fd_blockdb_proof( fd_blockdb_t * blockdb,
153 : fd_blockdb_blk_t const * blk,
154 : ulong leaf_idx,
155 0 : uchar proof[ FD_BLOCKDB_PROOF_NODE_MAX*FD_SHRED_MERKLE_NODE_SZ ] ) {
156 0 : if( FD_UNLIKELY( leaf_idx>blk->fec_set_cnt ) ) return -1;
157 :
158 0 : fd_bmtree_commit_t * tree = fd_bmtree_commit_init( blockdb->tree, FD_SHRED_MERKLE_NODE_SZ, FD_BMTREE_LONG_PREFIX_SZ, FD_BLOCKDB_TREE_LAYER_MAX );
159 :
160 : /* Only the first FD_SHRED_MERKLE_NODE_SZ bytes of a node are hashed,
161 : so a zero-padded root prefix is an exact leaf. */
162 0 : fd_bmtree_node_t leaf[1] = {0};
163 0 : for( uint k=0U; k<blk->fec_set_cnt; k++ ) {
164 0 : memcpy( leaf->hash, blk->merkle_roots[ k ], FD_SHRED_MERKLE_NODE_SZ );
165 0 : fd_bmtree_commit_append( tree, leaf, 1UL );
166 0 : }
167 :
168 0 : fd_sha256_t sha[1];
169 0 : fd_sha256_init ( sha );
170 0 : fd_sha256_append( sha, &blk->parent_slot, sizeof(ulong) );
171 0 : fd_sha256_append( sha, blk->parent_block_id.uc, sizeof(fd_hash_t) );
172 0 : fd_sha256_append( sha, &blk->fec_set_cnt, sizeof(uint) );
173 0 : fd_sha256_fini ( sha, leaf->hash );
174 0 : fd_bmtree_commit_append( tree, leaf, 1UL );
175 :
176 0 : fd_bmtree_commit_fini( tree );
177 0 : return fd_bmtree_get_proof( tree, proof, leaf_idx );
178 0 : }
|