diff --git a/src/app/fdctl/config.c b/src/app/fdctl/config.c index ba57e4491c..9e13e2d9a4 100644 --- a/src/app/fdctl/config.c +++ b/src/app/fdctl/config.c @@ -238,8 +238,7 @@ static int parse_key_value( config_t * config, ENTRY_UINT ( ., layout, bank_tile_count ); ENTRY_UINT ( ., layout, shred_tile_count ); - ENTRY_STR ( ., hugetlbfs, gigantic_page_mount_path ); - ENTRY_STR ( ., hugetlbfs, huge_page_mount_path ); + ENTRY_STR ( ., hugetlbfs, mount_path ); ENTRY_STR ( ., tiles.net, interface ); ENTRY_STR ( ., tiles.net, xdp_mode ); @@ -921,6 +920,19 @@ config_parse( int * pargc, if( FD_UNLIKELY( getgid() != 0 && config->gid != getgid() ) ) FD_LOG_ERR(( "running as gid %i, but config specifies gid %i", getgid(), config->gid )); + ulong len = strlen( config->hugetlbfs.mount_path ); + if( FD_UNLIKELY( !len ) ) FD_LOG_ERR(( "[hugetlbfs.mount_path] must be non-empty in your configuration file" )); + FD_TEST( fd_cstr_printf_check( config->hugetlbfs.gigantic_page_mount_path, + sizeof(config->hugetlbfs.gigantic_page_mount_path), + NULL, + "%s/.gigantic", + config->hugetlbfs.mount_path ) ); + FD_TEST( fd_cstr_printf_check( config->hugetlbfs.huge_page_mount_path, + sizeof(config->hugetlbfs.huge_page_mount_path), + NULL, + "%s/.huge", + config->hugetlbfs.mount_path ) ); + replace( config->log.path, "{user}", config->user ); replace( config->log.path, "{name}", config->name ); if( FD_LIKELY( !strcmp( "auto", config->log.colorize ) ) ) config->log.colorize1 = 2; diff --git a/src/app/fdctl/config.h b/src/app/fdctl/config.h index b124c6c355..bb062c8a76 100644 --- a/src/app/fdctl/config.h +++ b/src/app/fdctl/config.h @@ -128,6 +128,7 @@ typedef struct { struct { char gigantic_page_mount_path[ PATH_MAX ]; char huge_page_mount_path[ PATH_MAX ]; + char mount_path[ PATH_MAX ]; } hugetlbfs; struct { diff --git a/src/app/fdctl/config/default.toml b/src/app/fdctl/config/default.toml index a16bc8496b..40e18bdabc 100644 --- a/src/app/fdctl/config/default.toml +++ b/src/app/fdctl/config/default.toml @@ -578,16 +578,14 @@ dynamic_port_range = "8900-9000" # +-- scratch2.wksp [hugetlbfs] # The absolute path to a directory in the filesystem. Firedancer - # will mount the hugetlbfs filesystem for gigantic pages at this - # path, or if the path already exists, will use it as-is. If the - # mount already exists it should be writable by the Firedancer user. - gigantic_page_mount_path = "/mnt/.fd/.gigantic" - - # The absolute path to a directory in the filesystem. Firedancer - # will mount the hugetlbfs filesystem for huge pages at this path, - # or if the path already exists, will use it as-is. If the mount - # already exists it should be writable by the Firedancer user. - huge_page_mount_path = "/mnt/.fd/.huge" + # will mount the hugetlbfs filesystem for gigantic pages at a + # subdirectory named .gigantic under this path, or if the entire + # path already exists, will use it as-is. Firedancer will also + # mount the hugetlbfs filesystem for huge pages at a subdirectory + # named .huge under this path, or if the entire path already exists, + # will use it as-is. If the mount already exists it should be + # writable by the Firedancer user. + mount_path = "/mnt/.fd" # Tiles are described in detail in the layout section above. While the # layout configuration determines how many of each tile to place on diff --git a/src/app/fdctl/main1.c b/src/app/fdctl/main1.c index 344063dfa2..c4bf630129 100644 --- a/src/app/fdctl/main1.c +++ b/src/app/fdctl/main1.c @@ -170,6 +170,14 @@ fdctl_boot( int * pargc, strncpy( config->log.path, log_path, sizeof( config->log.path ) - 1 ); } + char * shmem_args[ 3 ]; + /* pass in --shmem-path value from the config */ + shmem_args[ 0 ] = "--shmem-path"; + shmem_args[ 1 ] = config->hugetlbfs.mount_path; + shmem_args[ 2 ] = NULL; + char ** argv = shmem_args; + int argc = 2; + int * log_lock = map_log_memfd( config->log.lock_fd ); ulong pid = fd_sandbox_getpid(); /* Need to read /proc since we might be in a PID namespace now */; @@ -199,7 +207,7 @@ fdctl_boot( int * pargc, config->log.log_fd, log_path ); config->log.log_fd = fd_log_private_logfile_fd(); - fd_shmem_private_boot( pargc, pargv );; + fd_shmem_private_boot( &argc, &argv ); fd_tile_private_boot( 0, NULL ); /* Kind of a hack but initializing NUMA config depends on shmem, which diff --git a/src/app/fdctl/run/tiles/fd_replay.c b/src/app/fdctl/run/tiles/fd_replay.c index 4ee730f4d5..429b18b991 100644 --- a/src/app/fdctl/run/tiles/fd_replay.c +++ b/src/app/fdctl/run/tiles/fd_replay.c @@ -1,4 +1,4 @@ -#define _GNU_SOURCE +#define _GNU_SOURCE #include "tiles.h" @@ -110,7 +110,7 @@ struct fd_replay_tile_ctx { ulong parent_slot; ulong flags; fd_hash_t blockhash; - + uchar tpool_mem[FD_TPOOL_FOOTPRINT( FD_TILE_MAX )] __attribute__( ( aligned( FD_TPOOL_ALIGN ) ) ); fd_tpool_t * tpool; ulong max_workers; @@ -156,14 +156,14 @@ during_frag( void * _ctx, ulong sz, int * opt_filter FD_PARAM_UNUSED ) { fd_replay_tile_ctx_t * ctx = (fd_replay_tile_ctx_t *)_ctx; - + if( FD_UNLIKELY( chunkstore_in_chunk0 || chunk>ctx->store_in_wmark || sz>MAX_TXNS_PER_REPLAY ) ) { FD_LOG_ERR(( "chunk %lu %lu corrupt, not in range [%lu,%lu]", chunk, sz, ctx->store_in_chunk0, ctx->store_in_wmark )); } void * dst_poh = fd_chunk_to_laddr( ctx->poh_out_mem, ctx->poh_out_chunk ); uchar * src = (uchar *)fd_chunk_to_laddr( ctx->store_in_mem, chunk ); - + /* Incoming packet from store tile. Format: * Parent slot (ulong - 8 bytes) * Updated block hash/PoH hash (fd_hash_t - 32 bytes) @@ -226,7 +226,7 @@ after_frag( void * _ctx, fork->slot_ctx.slot_bank.prev_slot = fork->slot_ctx.slot_bank.slot; fork->slot_ctx.slot_bank.slot = ctx->curr_slot; - + fd_funk_txn_xid_t xid; fd_memcpy(xid.uc, ctx->blockhash.uc, sizeof(fd_funk_txn_xid_t)); @@ -270,7 +270,7 @@ after_frag( void * _ctx, *opt_filter = 1; return; } - + fd_blockstore_start_write( ctx->replay->blockstore ); fd_block_t * block_ = fd_blockstore_block_query( ctx->replay->blockstore, ctx->curr_slot ); @@ -365,7 +365,31 @@ read_snapshot( void * _ctx, char const * snapshotfile, char const * incremental } static void -after_credit( void * _ctx, +init_after_snapshot( fd_replay_tile_ctx_t * ctx ) { + ulong snapshot_slot = ctx->slot_ctx->slot_bank.slot; + if( snapshot_slot != ctx->curr_slot ) { + /* The initial snapshot_slot was wrong or unspecified. Fix everything. */ + FD_LOG_NOTICE(( "detected snapshot slot %lu, prev_slot %lu", snapshot_slot, ctx->slot_ctx->slot_bank.prev_slot )); + fd_fork_t * ele = fd_fork_frontier_ele_remove( ctx->replay->forks->frontier, &ctx->curr_slot, NULL, ctx->replay->forks->pool ); + ele->slot = snapshot_slot; + fd_fork_frontier_ele_insert( ctx->replay->forks->frontier, ele, ctx->replay->forks->pool ); + ctx->replay->smr = snapshot_slot; + fd_bank_hash_cmp_t * bank_hash_cmp = fd_exec_epoch_ctx_bank_hash_cmp( ctx->epoch_ctx ); + bank_hash_cmp->slot = snapshot_slot; + ctx->curr_slot = snapshot_slot; + ctx->parent_slot = ctx->slot_ctx->slot_bank.prev_slot; + } + + fd_features_restore( ctx->slot_ctx ); + fd_runtime_update_leaders( ctx->slot_ctx, ctx->slot_ctx->slot_bank.slot ); + fd_calculate_epoch_accounts_hash_values( ctx->slot_ctx ); + fd_funk_start_write( ctx->slot_ctx->acc_mgr->funk ); + fd_bpf_scan_and_create_bpf_program_cache_entry( ctx->slot_ctx, ctx->slot_ctx->funk_txn ); + fd_funk_end_write( ctx->slot_ctx->acc_mgr->funk ); +} + +static void +after_credit( void * _ctx, fd_mux_context_t * mux_ctx ) { fd_replay_tile_ctx_t * ctx = (fd_replay_tile_ctx_t *)_ctx; @@ -392,12 +416,7 @@ after_credit( void * _ctx, fd_runtime_read_genesis( ctx->slot_ctx, ctx->genesis, is_snapshot ); - fd_features_restore( ctx->slot_ctx ); - fd_runtime_update_leaders( ctx->slot_ctx, ctx->slot_ctx->slot_bank.slot ); - fd_calculate_epoch_accounts_hash_values( ctx->slot_ctx ); - fd_funk_start_write( ctx->slot_ctx->acc_mgr->funk ); - fd_bpf_scan_and_create_bpf_program_cache_entry( ctx->slot_ctx, ctx->slot_ctx->funk_txn ); - fd_funk_end_write( ctx->slot_ctx->acc_mgr->funk ); + init_after_snapshot( ctx ); } FD_SCRATCH_SCOPE_END; } } @@ -525,17 +544,17 @@ unprivileged_init( fd_topo_t * topo, /* Valloc setup */ void * alloc_shalloc = fd_alloc_new( alloc_shmem, 3UL ); - if( FD_UNLIKELY( !alloc_shalloc ) ) { + if( FD_UNLIKELY( !alloc_shalloc ) ) { FD_LOG_ERR( ( "fd_allow_new failed" ) ); } fd_alloc_t * alloc = fd_alloc_join( alloc_shalloc, 3UL ); if( FD_UNLIKELY( !alloc ) ) { - FD_LOG_ERR( ( "fd_alloc_join failed" ) ); + FD_LOG_ERR( ( "fd_alloc_join failed" ) ); } fd_valloc_t valloc = fd_alloc_virtual( alloc ); - + ctx->epoch_ctx = fd_exec_epoch_ctx_join( fd_exec_epoch_ctx_new( ctx->epoch_ctx_mem , VOTE_ACC_MAX ) ); - + ctx->snapshot = tile->replay.snapshot; ctx->incremental = tile->replay.incremental; ctx->genesis = tile->replay.genesis; @@ -590,7 +609,7 @@ unprivileged_init( fd_topo_t * topo, } } } - + ctx->replay->tpool = ctx->tpool; ctx->replay->max_workers = ctx->max_workers; @@ -612,7 +631,7 @@ unprivileged_init( fd_topo_t * topo, ctx->store_out_chunk0 = fd_dcache_compact_chunk0( ctx->store_out_mem, store_out_link->dcache ); ctx->store_out_wmark = fd_dcache_compact_wmark( ctx->store_out_mem, store_out_link->dcache, store_out_link->mtu ); ctx->store_out_chunk = ctx->store_out_chunk0; - + fd_topo_link_t * poh_out_link = &topo->links[ tile->out_link_id[ POH_OUT_IDX ] ]; ctx->poh_out_mem = topo->workspaces[ topo->objs[ poh_out_link->dcache_obj_id ].wksp_id ].wksp; ctx->poh_out_chunk0 = fd_dcache_compact_chunk0( ctx->poh_out_mem, poh_out_link->dcache ); diff --git a/src/app/fdctl/run/tiles/fd_store_int.c b/src/app/fdctl/run/tiles/fd_store_int.c index 90219663bb..be6687353e 100644 --- a/src/app/fdctl/run/tiles/fd_store_int.c +++ b/src/app/fdctl/run/tiles/fd_store_int.c @@ -1,6 +1,6 @@ /* Store tile manages a blockstore and serves requests to repair and replay. */ -#define _GNU_SOURCE +#define _GNU_SOURCE #include "tiles.h" @@ -66,7 +66,7 @@ struct fd_store_tile_ctx { fd_wksp_t * replay_in_mem; ulong replay_in_chunk0; ulong replay_in_wmark; - + fd_wksp_t * pack_in_mem; ulong pack_in_chunk0; ulong pack_in_wmark; @@ -182,7 +182,7 @@ after_frag( void * _ctx, fd_mux_context_t * mux FD_PARAM_UNUSED ) { fd_store_tile_ctx_t * ctx = (fd_store_tile_ctx_t *)_ctx; - + ctx->store->now = fd_log_wallclock(); if( FD_UNLIKELY( in_idx==STAKE_IN_IDX ) ) { @@ -220,7 +220,7 @@ privileged_init( fd_topo_t * topo FD_PARAM_UNUSED, FD_LOG_ERR(( "identity_key_path not set" )); ctx->identity_key[ 0 ] = *(fd_pubkey_t *)fd_keyload_load( tile->store_int.identity_key_path, /* pubkey only: */ 1 ); - + FD_TEST( sizeof(ulong) == getrandom( &ctx->blockstore_seed, sizeof(ulong), 0 ) ); } @@ -243,11 +243,11 @@ fd_store_tile_slot_prepare( fd_store_tile_ctx_t * ctx, } /* We are leader at this slot and the slot is newer than turbine! */ - // FIXME: I dont think that this `ctx->store->curr_turbine_slot >= slot` + // FIXME: I dont think that this `ctx->store->curr_turbine_slot >= slot` // check works on fork switches to lower slot numbers. Use a given fork height // instead - if( ctx->store->curr_turbine_slot >= slot + if( ctx->store->curr_turbine_slot >= slot && memcmp( ctx->identity_key, slot_leader, sizeof(fd_pubkey_t) ) == 0 ) { if( store_slot_prepare_mode == FD_STORE_SLOT_PREPARE_CONTINUE ) { fd_block_t * block = fd_blockstore_block_query( ctx->blockstore, slot ); @@ -258,13 +258,13 @@ fd_store_tile_slot_prepare( fd_store_tile_ctx_t * ctx, return; } } - + ulong repair_req_cnt = 0; switch( store_slot_prepare_mode ) { case FD_STORE_SLOT_PREPARE_CONTINUE: { if( slot > 64UL ) { - ctx->store->smr = fd_ulong_max( ctx->store->smr, slot - 64UL ); - fd_pending_slots_set_lo_wmark( ctx->store->pending_slots, ctx->store->smr ); + ctx->blockstore->smr = fd_ulong_max( ctx->blockstore->smr, slot - 64UL ); + fd_pending_slots_set_lo_wmark( ctx->store->pending_slots, ctx->blockstore->smr ); } ctx->store->now = fd_log_wallclock(); break; @@ -292,7 +292,7 @@ fd_store_tile_slot_prepare( fd_store_tile_ctx_t * ctx, return; } } - + if( store_slot_prepare_mode == FD_STORE_SLOT_PREPARE_CONTINUE ) { ulong tspub = fd_frag_meta_ts_comp( fd_tickcount() ); @@ -318,14 +318,14 @@ fd_store_tile_slot_prepare( fd_store_tile_ctx_t * ctx, out_buf += sizeof(ulong); memcpy( out_buf, block_hash->uc, sizeof(fd_hash_t) ); - out_buf += sizeof(fd_hash_t); + out_buf += sizeof(fd_hash_t); uchar * block_data = fd_blockstore_block_data_laddr( ctx->blockstore, block ); FD_SCRATCH_SCOPE_BEGIN { fd_block_info_t block_info; fd_runtime_block_prepare( block_data, block->data_sz, fd_scratch_virtual(), &block_info ); - + FD_LOG_DEBUG(( "block prepared - slot: %lu", slot )); FD_LOG_NOTICE(( "first turbine: %lu, current received turbine: %lu, behind: %lu current " "executed: %lu, caught up: %d", @@ -395,7 +395,7 @@ unprivileged_init( fd_topo_t * topo, strcmp( topo->links[ tile->out_link_id[ REPLAY_OUT_IDX ] ].name, "store_replay" ) ) ) FD_LOG_ERR(( "store tile has none or unexpected output links %lu %s %s", tile->out_cnt, topo->links[ tile->out_link_id[ 0 ] ].name, topo->links[ tile->out_link_id[ 1 ] ].name )); - + if( FD_UNLIKELY( tile->out_link_id_primary != ULONG_MAX ) ) FD_LOG_ERR(( "store tile has a primary output link" )); @@ -414,9 +414,9 @@ unprivileged_init( fd_topo_t * topo, FD_TEST( (!!smem) & (!!fmem) ); fd_scratch_attach( smem, fmem, SCRATCH_SMAX, SCRATCH_SDEPTH ); - + ctx->wksp = topo->workspaces[ topo->objs[ tile->tile_obj_id ].wksp_id ].wksp; - + ulong blockstore_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "blockstore" ); FD_TEST( blockstore_obj_id!=ULONG_MAX ); ctx->blockstore_wksp = topo->workspaces[ topo->objs[ blockstore_obj_id ].wksp_id ].wksp; @@ -445,25 +445,12 @@ unprivileged_init( fd_topo_t * topo, FD_LOG_ERR( ( "failed to allocate a blockstore" ) ); } - FD_LOG_WARNING(("snapshot slot %lu", tile->store_int.snapshot_slot )); - /* fake the snapshot slot's block and mark it as executed */ - // fd_blockstore_slot_map_t * slot_entry = - // fd_blockstore_slot_map_insert( fd_blockstore_slot_map( blockstore ), tile->store_int.snapshot_slot ); - // slot_entry->block.data_gaddr = ULONG_MAX; - // slot_entry->block.flags = fd_uchar_set_bit( slot_entry->block.flags, FD_BLOCK_FLAG_SNAPSHOT ); - // slot_entry->block.flags = fd_uchar_set_bit( slot_entry->block.flags, FD_BLOCK_FLAG_PROCESSED ); - - // if( FD_LIKELY( tile->store_int.snapshot_slot != 0 ) ) { - // blockstore->root = tile->store_int.snapshot_slot; - // blockstore->min = tile->store_int.snapshot_slot; - // } - ctx->blockstore = blockstore; ctx->store->blockstore = blockstore; void * alloc_shmem = fd_wksp_alloc_laddr( ctx->wksp, fd_alloc_align(), fd_alloc_footprint(), 3UL ); - if( FD_UNLIKELY( !alloc_shmem ) ) { - FD_LOG_ERR( ( "fd_alloc too large for workspace" ) ); + if( FD_UNLIKELY( !alloc_shmem ) ) { + FD_LOG_ERR( ( "fd_alloc too large for workspace" ) ); } /* Set up shred tile input */ diff --git a/src/app/fdctl/run/topos/fd_firedancer.c b/src/app/fdctl/run/topos/fd_firedancer.c index 89bde07ed2..5ab7521b8a 100644 --- a/src/app/fdctl/run/topos/fd_firedancer.c +++ b/src/app/fdctl/run/topos/fd_firedancer.c @@ -1,4 +1,4 @@ -/* Firedancer topology used for testing the full validator. +/* Firedancer topology used for testing the full validator. Associated test script: test-firedancer.sh */ #include "topos.h" #include "../tiles/tiles.h" @@ -11,26 +11,8 @@ #include "../../../../util/tile/fd_tile_private.h" #include -static ulong -parse_snapshot_slot( char const * snapshot, char const * incremental ) { - char const * str = strlen( incremental ) > 0 ? incremental : snapshot; - ulong str_len = strlen( str ); - char const * end_ptr = &str[str_len - 1]; - - while( end_ptr > str && *end_ptr != '-') end_ptr--; - - if( end_ptr == str ) FD_LOG_ERR(("Could not parse snapshot slot out of snapshot file %s", str)); - - char const * start_ptr = (end_ptr - 1); - while( start_ptr > str && *start_ptr != '-') start_ptr--; - - if( start_ptr++ == str ) FD_LOG_ERR(("Could not parse snapshot slot out of snapshot file %s", str)); - char *eptr; - return strtoul(start_ptr, &eptr, 10); -} - void -fd_topo_firedancer( config_t * _config ) { +fd_topo_firedancer( config_t * _config ) { config_t * config = (config_t *)_config; ulong net_tile_cnt = config->layout.net_tile_count; ulong shred_tile_cnt = config->layout.shred_tile_count; @@ -52,7 +34,7 @@ fd_topo_firedancer( config_t * _config ) { fd_topob_wksp( topo, "shred_sign" ); fd_topob_wksp( topo, "sign_shred" ); - + fd_topob_wksp( topo, "gossip_sign" ); fd_topob_wksp( topo, "sign_gossip" ); @@ -185,11 +167,11 @@ fd_topo_firedancer( config_t * _config ) { FOR(shred_tile_cnt) fd_topob_tile_in( topo, "shred", i, "metric_in", "crds_shred", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); FOR(shred_tile_cnt) fd_topob_tile_out( topo, "shred", i, "shred_net", i ); FOR(shred_tile_cnt) fd_topob_tile_in( topo, "storei", 0UL, "metric_in", "shred_storei", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED ); - + /**/ fd_topob_tile_in( topo, "storei", 0UL, "metric_in", "repair_store", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); - /**/ fd_topob_tile_out( topo, "repair", 0UL, "repair_net", 0UL ); - /**/ fd_topob_tile_out( topo, "storei", 0UL, "store_repair", 0UL ); - /**/ fd_topob_tile_out( topo, "storei", 0UL, "store_replay", 0UL ); + /**/ fd_topob_tile_out( topo, "repair", 0UL, "repair_net", 0UL ); + /**/ fd_topob_tile_out( topo, "storei", 0UL, "store_repair", 0UL ); + /**/ fd_topob_tile_out( topo, "storei", 0UL, "store_replay", 0UL ); /**/ fd_topob_tile_in( topo, "storei", 0UL, "metric_in", "stake_out", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); @@ -205,7 +187,7 @@ fd_topo_firedancer( config_t * _config ) { /**/ fd_topob_tile_in( topo, "shred", i, "metric_in", "sign_shred", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_UNPOLLED ); /**/ fd_topob_tile_out( topo, "sign", 0UL, "sign_shred", i ); } - + FOR(net_tile_cnt) fd_topob_tile_out( topo, "net", i, "net_gossip", i ); FOR(net_tile_cnt) fd_topob_tile_in( topo, "gossip", 0UL, "metric_in", "net_gossip", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /* No reliable consumers of networking fragments, may be dropped or overrun */ /**/ fd_topob_tile_out( topo, "gossip", 0UL, "crds_shred", 0UL ); @@ -221,7 +203,7 @@ fd_topo_firedancer( config_t * _config ) { /**/ fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "gossip_repai", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /**/ fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "stake_out", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /**/ fd_topob_tile_in( topo, "repair", 0UL, "metric_in", "store_repair", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); - + /**/ fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "store_replay", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED ); /**/ fd_topob_tile_out( topo, "replay", 0UL, "replay_poh", 0UL ); @@ -264,7 +246,6 @@ fd_topo_firedancer( config_t * _config ) { } else if( FD_UNLIKELY( !strcmp( tile->name, "storei" ) ) ) { strncpy( tile->store_int.identity_key_path, config->consensus.identity_path, sizeof(tile->store_int.identity_key_path) ); - tile->store_int.snapshot_slot = parse_snapshot_slot( config->tiles.replay.snapshot, config->tiles.replay.incremental ); } else if( FD_UNLIKELY( !strcmp( tile->name, "gossip" ) ) ) { tile->gossip.ip_addr = config->tiles.net.ip_addr; memcpy( tile->gossip.src_mac_addr, config->tiles.net.mac_addr, 6UL ); @@ -273,7 +254,7 @@ fd_topo_firedancer( config_t * _config ) { tile->gossip.tvu_port = config->tiles.shred.shred_listen_port; tile->gossip.tvu_fwd_port = config->tiles.shred.shred_listen_port; tile->gossip.expected_shred_version = config->consensus.expected_shred_version; - + FD_TEST( config->tiles.gossip.entrypoints_cnt == config->tiles.gossip.peer_ports_cnt ); tile->gossip.entrypoints_cnt = config->tiles.gossip.entrypoints_cnt; for (ulong i=0UL; itiles.gossip.entrypoints_cnt; i++) { @@ -294,13 +275,13 @@ fd_topo_firedancer( config_t * _config ) { } else if( FD_UNLIKELY( !strcmp( tile->name, "replay" ) )) { strncpy( tile->replay.snapshot, config->tiles.replay.snapshot, sizeof(tile->replay.snapshot) ); strncpy( tile->replay.incremental, config->tiles.replay.incremental, sizeof(tile->replay.incremental) ); - tile->replay.snapshot_slot = parse_snapshot_slot( config->tiles.replay.snapshot, config->tiles.replay.incremental ); + tile->replay.snapshot_slot = ULONG_MAX; /* Determine when we load the snapshot */ tile->replay.tpool_thread_count = config->tiles.replay.tpool_thread_count; tile->replay.pages = config->tiles.replay.funk_sz_gb; tile->replay.txn_max = config->tiles.replay.funk_txn_max; tile->replay.index_max = config->tiles.replay.funk_rec_max; - + if( FD_UNLIKELY( tile->replay.tpool_thread_count == 0 || tile->replay.tpool_thread_count>FD_TILE_MAX ) ) FD_LOG_ERR(( "bad tpool_thread_count %lu", tile->replay.tpool_thread_count )); } else if( FD_UNLIKELY( !strcmp( tile->name, "bhole" ) ) ) { diff --git a/src/disco/topo/fd_topo.h b/src/disco/topo/fd_topo.h index 5a3b502724..6016ba4755 100644 --- a/src/disco/topo/fd_topo.h +++ b/src/disco/topo/fd_topo.h @@ -124,7 +124,7 @@ typedef struct { may point to the link, if there are multiple consumers. An fseq can be uniquely identified via (link_id, tile_id), or (link_kind, link_kind_id, tile_kind, tile_kind_id) */ - ulong * in_link_fseq[ FD_TOPO_MAX_TILE_IN_LINKS ]; + ulong * in_link_fseq[ FD_TOPO_MAX_TILE_IN_LINKS ]; }; /* Configuration fields. These are required to be known by the topology so it can determine the @@ -256,7 +256,6 @@ typedef struct { } gossip; struct { - ulong snapshot_slot; char identity_key_path[ PATH_MAX ]; } store_int; }; @@ -469,7 +468,7 @@ fd_topo_join_workspaces( fd_topo_t * topo, /* Leave (unmap from the process) the shared memory needed for the given workspace in the topology, if it was previously mapped. - + topo and wksp are assumed non-NULL. It is OK if the workspace has not been previously joined, in which case this is a no-op. */ @@ -494,7 +493,7 @@ fd_topo_leave_workspaces( fd_topo_t * topo ); Returns 0 on success and -1 on failure, with errno set to the error. The only reason for failure currently that will be returned is ENOMEM, as other unexpected errors will cause the program to exit. - + If update_existing is 1, the workspace will not be created from scratch but it will be assumed that it already exists from a prior run and needs to be maybe resized and then have the header @@ -537,12 +536,12 @@ fd_topo_fill( fd_topo_t * topo ); /* fd_topo_tile_stack_new creates a new huge page optimized stack for provided tile. The stack is placed in a workspace in the hugetlbfs mount. - + If optimize is 1, fd_topo_tile_stack_new creates a new huge page optimized stack for the provided tile. The stack will be placed in a workspace in the hugetlbfs, with a name determined by the provided app_name, tile_name, and tile_kind_id arguments. - + If optimize is 0, fd_topo_tile_stack_new creates a new regular page backed stack, which is not placed in the hugetlbfs. In this case cpu_idx and the other arguments are ignored. */ @@ -573,7 +572,7 @@ fd_topo_tile_stack_new( int optimize, production Firedancer process runs. For production, each tile is run in its own address space with a separate process and full security sandbox. - + The solana_labs argument determines which tiles are started. If the argument is 0 or 1, only non-labs (or only labs) tiles are started. If the argument is any other value, all tiles in the topology are @@ -591,7 +590,7 @@ fd_topo_run_single_process( fd_topo_t * topo, process (and thread). The function will never return, as tiles are expected to run forever. An error is logged and the application will exit if the tile exits. - + The sandbox argument determines if the current process will be sandboxed fully before starting the tile. The thread will switch to the UID and GID provided before starting the tile, even if the thread @@ -599,14 +598,14 @@ fd_topo_run_single_process( fd_topo_t * topo, a process must share a UID and GID, this is not the case on Linux. The thread will switch to the provided UID and GID without switching the other threads in the process. - + The allow_fd argument is only used if sandbox is true, and is a file descriptor which will be allowed to exist in the process. Normally the sandbox code rejects and aborts if there is an unexpected file descriptor present on boot. This is helpful to allow a parent process to be notified on termination of the tile by waiting for a pipe file descriptor to get closed. - + wait and debugger are both used in debugging. If wait is non-NULL, the runner will wait until the value pointed to by wait is non-zero before launching the tile. Likewise, if debugger is non-NULL, the diff --git a/src/disco/tvu/fd_store.h b/src/disco/tvu/fd_store.h index 80fc3656a0..7664a4a8b9 100644 --- a/src/disco/tvu/fd_store.h +++ b/src/disco/tvu/fd_store.h @@ -20,7 +20,6 @@ struct __attribute__((aligned(128UL))) fd_store { long now; /* Current time */ /* metadata */ - ulong smr; /* super-majority root */ ulong snapshot_slot; /* the snapshot slot */ ulong first_turbine_slot; /* the first turbine slot we received on startup */ ulong curr_turbine_slot; @@ -50,7 +49,7 @@ fd_store_footprint( void ) { void * fd_store_new( void * mem, ulong lo_wmark_slot ); -fd_store_t * +fd_store_t * fd_store_join( void * store ); void * diff --git a/src/disco/tvu/fd_tvu.c b/src/disco/tvu/fd_tvu.c index d21e1d3a3e..a409b0ee54 100644 --- a/src/disco/tvu/fd_tvu.c +++ b/src/disco/tvu/fd_tvu.c @@ -811,7 +811,7 @@ void capture_ctx_setup( fd_runtime_ctx_t * runtime_ctx, fd_runtime_args_t * args runtime_ctx->capture_ctx->dump_insn_sig_filter = args->dump_insn_sig_filter; runtime_ctx->capture_ctx->dump_insn_output_dir = args->dump_insn_output_dir; } - + } typedef struct { @@ -1289,7 +1289,6 @@ fd_tvu_main_setup( fd_runtime_ctx_t * runtime_ctx, void * store_mem = fd_valloc_malloc( valloc, fd_store_align(), fd_store_footprint() ); fd_store_t * store = fd_store_join( fd_store_new( store_mem, snapshot_slot ) ); store->blockstore = blockstore_setup_out.blockstore; - store->smr = snapshot_slot; store->snapshot_slot = snapshot_slot; store->valloc = valloc; diff --git a/src/flamenco/runtime/fd_executor.c b/src/flamenco/runtime/fd_executor.c index 42878f46c0..cddb9a6fef 100644 --- a/src/flamenco/runtime/fd_executor.c +++ b/src/flamenco/runtime/fd_executor.c @@ -704,8 +704,15 @@ fd_execute_instr( fd_exec_txn_ctx_t * txn_ctx, } txn_ctx->num_instructions++; fd_pubkey_t const * txn_accs = txn_ctx->accounts; - ulong starting_lamports = fd_instr_info_sum_account_lamports( instr ); - instr->starting_lamports = starting_lamports; + + ulong starting_lamports_h = 0; + ulong starting_lamports_l = 0; + int err = fd_instr_info_sum_account_lamports( instr, &starting_lamports_h, &starting_lamports_l ); + if( err ) { + return err; + } + instr->starting_lamports_h = starting_lamports_h; + instr->starting_lamports_l = starting_lamports_l; fd_exec_instr_ctx_t * parent = NULL; if( txn_ctx->instr_stack_sz ) @@ -754,11 +761,14 @@ fd_execute_instr( fd_exec_txn_ctx_t * txn_ctx, // FD_LOG_NOTICE(("COMPUTE METER END %lu %lu %lu %64J", before_instr_cus - txn_ctx->compute_meter, txn_ctx->compute_meter, txn_ctx->compute_unit_limit, sig )); if( exec_result == FD_EXECUTOR_INSTR_SUCCESS ) { - ulong ending_lamports = fd_instr_info_sum_account_lamports( instr ); - // FD_LOG_WARNING(("check lamports %lu %lu %lu", starting_lamports, instr->starting_lamports, ending_lamports )); + ulong ending_lamports_h = 0UL; + ulong ending_lamports_l = 0UL; + err = fd_instr_info_sum_account_lamports( instr, &ending_lamports_h, &ending_lamports_l ); + if( err ) { + return err; + } - if( starting_lamports != ending_lamports ) { - FD_LOG_WARNING(("starting lamports mismatched %lu %lu %lu", starting_lamports, instr->starting_lamports, ending_lamports )); + if( ending_lamports_l != starting_lamports_l || ending_lamports_h != starting_lamports_h ) { exec_result = FD_EXECUTOR_INSTR_ERR_UNBALANCED_INSTR; } diff --git a/src/flamenco/runtime/info/fd_instr_info.c b/src/flamenco/runtime/info/fd_instr_info.c index 65c1304285..2dd37dbf48 100644 --- a/src/flamenco/runtime/info/fd_instr_info.c +++ b/src/flamenco/runtime/info/fd_instr_info.c @@ -1,6 +1,7 @@ #include "fd_instr_info.h" #include "../fd_account.h" +#include "../../../util/bits/fd_uwide.h" /* demote_program_id() in https://github.com/solana-labs/solana/blob/061bed0a8ca80afb97f4438155e8a6b47bbf7f6d/sdk/program/src/message/versions/v0/loaded.rs#L150 */ int @@ -35,12 +36,15 @@ fd_convert_txn_instr_to_instr( fd_exec_txn_ctx_t * txn_ctx, fd_rawtxn_b_t const * txn_raw = txn_ctx->_txn_raw; const fd_pubkey_t * accounts = txn_ctx->accounts; - ulong starting_lamports = 0; - instr->program_id = txn_instr->program_id; + /* TODO: Lamport check may be redundant */ + ulong starting_lamports_h = 0; + ulong starting_lamports_l = 0; + + instr->program_id = txn_instr->program_id; instr->program_id_pubkey = accounts[txn_instr->program_id]; - instr->acct_cnt = txn_instr->acct_cnt; - instr->data_sz = txn_instr->data_sz; - instr->data = (uchar *)txn_raw->raw + txn_instr->data_off; + instr->acct_cnt = txn_instr->acct_cnt; + instr->data_sz = txn_instr->data_sz; + instr->data = (uchar *)txn_raw->raw + txn_instr->data_off; uchar acc_idx_seen[256]; memset(acc_idx_seen, 0, 256); @@ -57,10 +61,12 @@ fd_convert_txn_instr_to_instr( fd_exec_txn_ctx_t * txn_ctx, instr->is_duplicate[i] = acc_idx_seen[acc_idx]; if( FD_LIKELY( !acc_idx_seen[acc_idx] ) ) { /* This is the first time seeing this account */ - acc_idx_seen[acc_idx] = 1; if( instr->borrowed_accounts[i] != NULL && instr->borrowed_accounts[i]->const_meta != NULL ) { - starting_lamports += instr->borrowed_accounts[i]->const_meta->info.lamports; + fd_uwide_inc( &starting_lamports_h, &starting_lamports_l, + starting_lamports_h, starting_lamports_l, + instr->borrowed_accounts[i]->const_meta->info.lamports ); } + acc_idx_seen[acc_idx] = 1; } instr->acct_txn_idxs[i] = acc_idx; @@ -76,10 +82,12 @@ fd_convert_txn_instr_to_instr( fd_exec_txn_ctx_t * txn_ctx, } } - instr->starting_lamports = starting_lamports; + instr->starting_lamports_h = starting_lamports_h; + instr->starting_lamports_l = starting_lamports_l; + } -FD_FN_PURE int +int fd_instr_any_signed( fd_instr_info_t const * info, fd_pubkey_t const * pubkey ) { int is_signer = 0; @@ -90,20 +98,34 @@ fd_instr_any_signed( fd_instr_info_t const * info, return is_signer; } -/* - TODO: We should modify this function to handle overflows / other issues similar to Agave. - https://github.com/anza-xyz/agave/blob/9706a6464665f7ebd6ead47f0d12f853ccacbab9/sdk/src/transaction_context.rs#L407 -*/ -ulong -fd_instr_info_sum_account_lamports( fd_instr_info_t const * instr ) { - ulong total_lamports = 0; - for( ulong i = 0; i < instr->acct_cnt; i++ ) { - if( instr->borrowed_accounts[i] != NULL && !instr->is_duplicate[i] && instr->borrowed_accounts[i]->const_meta != NULL ) { - // FD_LOG_WARNING(("SUM INSTR INFO LAMPS: %32J %lu", instr->acct_pubkeys[i].key, instr->borrowed_accounts[i]->const_meta->info.lamports )); - total_lamports += instr->borrowed_accounts[i]->const_meta->info.lamports; +/* https://github.com/anza-xyz/agave/blob/9706a6464665f7ebd6ead47f0d12f853ccacbab9/sdk/src/transaction_context.rs#L40 */ +int +fd_instr_info_sum_account_lamports( fd_instr_info_t const * instr, + ulong * total_lamports_h, + ulong * total_lamports_l ) { + *total_lamports_h = 0UL; + *total_lamports_l = 0UL; + for( ulong i=0UL; iacct_cnt; ++i ) { + if( instr->borrowed_accounts[i] == NULL || + instr->is_duplicate[i] || + instr->borrowed_accounts[i]->const_meta == NULL ) { + continue; } + + /* Perform a checked add on a fd_uwide */ + ulong tmp_total_lamports_h = 0UL; + ulong tmp_total_lamports_l = 0UL; + + fd_uwide_inc( &tmp_total_lamports_h, &tmp_total_lamports_l, *total_lamports_h, *total_lamports_l, + instr->borrowed_accounts[i]->const_meta->info.lamports ); + + if( tmp_total_lamports_h < *total_lamports_h ) { + return FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW; + } + + *total_lamports_h = tmp_total_lamports_h; + *total_lamports_l = tmp_total_lamports_l; } - // FD_LOG_WARNING(("SUM: %lu", total_lamports)); - return total_lamports; + return FD_EXECUTOR_INSTR_SUCCESS; } diff --git a/src/flamenco/runtime/info/fd_instr_info.h b/src/flamenco/runtime/info/fd_instr_info.h index 557ceb97e3..22c5ecbcf7 100644 --- a/src/flamenco/runtime/info/fd_instr_info.h +++ b/src/flamenco/runtime/info/fd_instr_info.h @@ -12,21 +12,23 @@ #define FD_INSTR_ACCT_MAX (256) struct fd_instr_info { - uchar program_id; - ushort data_sz; - ushort acct_cnt; + uchar program_id; + ushort data_sz; + ushort acct_cnt; - uchar * data; - fd_pubkey_t program_id_pubkey; + uchar * data; + fd_pubkey_t program_id_pubkey; - uchar acct_txn_idxs[FD_INSTR_ACCT_MAX]; - uchar acct_flags[FD_INSTR_ACCT_MAX]; - fd_pubkey_t acct_pubkeys[FD_INSTR_ACCT_MAX]; - uchar is_duplicate[FD_INSTR_ACCT_MAX]; + uchar acct_txn_idxs[FD_INSTR_ACCT_MAX]; + uchar acct_flags[FD_INSTR_ACCT_MAX]; + fd_pubkey_t acct_pubkeys[FD_INSTR_ACCT_MAX]; + uchar is_duplicate[FD_INSTR_ACCT_MAX]; fd_borrowed_account_t * borrowed_accounts[FD_INSTR_ACCT_MAX]; - ulong starting_lamports; + /* fd_uwide representation of uint_128 */ + ulong starting_lamports_h; + ulong starting_lamports_l; }; typedef struct fd_instr_info fd_instr_info_t; @@ -96,8 +98,10 @@ fd_instr_any_signed( fd_instr_info_t const * info, Aborts on integer overflow. */ -FD_FN_PURE ulong -fd_instr_info_sum_account_lamports( fd_instr_info_t const * instr ); +int +fd_instr_info_sum_account_lamports( fd_instr_info_t const * instr, + ulong * total_lamports_h, + ulong * total_lamports_l ); static inline void fd_instr_get_signers( fd_instr_info_t const * self, diff --git a/src/flamenco/runtime/program/fd_native_cpi.c b/src/flamenco/runtime/program/fd_native_cpi.c index 64b3df438a..7ba08cff22 100644 --- a/src/flamenco/runtime/program/fd_native_cpi.c +++ b/src/flamenco/runtime/program/fd_native_cpi.c @@ -1,6 +1,7 @@ #include "../fd_account.h" #include "../../vm/fd_vm_syscalls.h" #include "../../vm/fd_vm_interp.h" +#include "../../../util/bits/fd_uwide.h" int fd_native_cpi_execute_system_program_instruction( fd_exec_instr_ctx_t * ctx, @@ -20,7 +21,9 @@ fd_native_cpi_execute_system_program_instruction( fd_exec_instr_ctx_t * ctx, } } - ulong starting_lamports = 0; + /* TODO: Lamport check may be redundant */ + ulong starting_lamports_h = 0; + ulong starting_lamports_l = 0; uchar acc_idx_seen[256]; memset( acc_idx_seen, 0, 256 ); @@ -41,7 +44,9 @@ fd_native_cpi_execute_system_program_instruction( fd_exec_instr_ctx_t * ctx, /* This is the first time seeing this account */ acc_idx_seen[k] = 1; if( instr_info->borrowed_accounts[j]->const_meta != NULL ) { - starting_lamports += instr_info->borrowed_accounts[j]->const_meta->info.lamports; + fd_uwide_inc( &starting_lamports_h, &starting_lamports_l, + starting_lamports_h, starting_lamports_l, + instr_info->borrowed_accounts[j]->const_meta->info.lamports ); } } @@ -63,7 +68,8 @@ fd_native_cpi_execute_system_program_instruction( fd_exec_instr_ctx_t * ctx, } } - instr_info->starting_lamports = starting_lamports; + instr_info->starting_lamports_h = starting_lamports_h; + instr_info->starting_lamports_l = starting_lamports_l; } fd_bincode_encode_ctx_t ctx2; diff --git a/src/flamenco/runtime/program/fd_stake_program.c b/src/flamenco/runtime/program/fd_stake_program.c index 60258369a4..ed0c2768d9 100644 --- a/src/flamenco/runtime/program/fd_stake_program.c +++ b/src/flamenco/runtime/program/fd_stake_program.c @@ -905,15 +905,14 @@ stake_weighted_credits_observed( fd_stake_t const * stake, ulong absorbed_lamports, ulong absorbed_credits_observed, ulong * out ) { - // FIXME: FD_LIKELY - if( stake->credits_observed == absorbed_credits_observed ) { + if( FD_LIKELY( stake->credits_observed == absorbed_credits_observed ) ) { *out = stake->credits_observed; return 1; } else { /* total_stake = stake->delegation.stake + absorbed_lamports */ - ulong total_stake_h = 0; - ulong total_stake_l = 0; - fd_uwide_inc( &total_stake_h, &total_stake_l, 0, stake->delegation.stake, + ulong total_stake_h = 0UL; + ulong total_stake_l = 0UL; + fd_uwide_inc( &total_stake_h, &total_stake_l, 0UL, stake->delegation.stake, absorbed_lamports ); /* stake_weighted_credits = stake->credits_observed + stake->delegation.stake */ @@ -933,26 +932,26 @@ stake_weighted_credits_observed( fd_stake_t const * stake, ulong total_weighted_credits_partial_one_l; fd_uwide_add( &total_weighted_credits_partial_one_h, &total_weighted_credits_partial_one_l, stake_weighted_credits_h, stake_weighted_credits_l, - absorbed_weighted_credits_h, absorbed_weighted_credits_l, 0 ); + absorbed_weighted_credits_h, absorbed_weighted_credits_l, 0UL ); ulong total_weighted_credits_partial_two_h; ulong total_weighted_credits_partial_two_l; fd_uwide_add( &total_weighted_credits_partial_two_h, &total_weighted_credits_partial_two_l, total_weighted_credits_partial_one_h, total_weighted_credits_partial_one_l, - total_stake_h, total_stake_l, 0 ); + total_stake_h, total_stake_l, 0UL ); ulong total_weighted_credits_h; ulong total_weighted_credits_l; fd_uwide_dec( &total_weighted_credits_h, &total_weighted_credits_l, - total_weighted_credits_partial_two_h, total_weighted_credits_partial_two_l, 1 ); + total_weighted_credits_partial_two_h, total_weighted_credits_partial_two_l, 1UL ); /* FIXME: fd_uwide_div doesn't support denominator that is an fd_uwide */ /* res = totalWeighted_credits / total_stake */ ulong res_h; ulong res_l; - FD_TEST(( total_stake_h == 0 )); + FD_TEST( total_stake_h == 0UL ); fd_uwide_div( &res_h, &res_l, total_weighted_credits_h, total_weighted_credits_l, total_stake_l ); - FD_TEST(( res_h == 0 )); + FD_TEST( res_h == 0UL ); //*out = total_weighted_credits / total_stake; *out = res_l; return 1; diff --git a/src/flamenco/runtime/program/fd_vote_program.c b/src/flamenco/runtime/program/fd_vote_program.c index 6afa31b4b6..71de7c4f94 100644 --- a/src/flamenco/runtime/program/fd_vote_program.c +++ b/src/flamenco/runtime/program/fd_vote_program.c @@ -579,16 +579,22 @@ credits_for_vote_at_index( fd_vote_state_t * self, ulong index ) { // If latency is 0, this means that the Lockout was created and stored from a software version // that did not store vote latencies; in this case, 1 credit is awarded - if( FD_UNLIKELY( latency == 0 ) ) return 1; + if( FD_UNLIKELY( latency == 0 ) ) { + return 1; + } - ulong diff = ULONG_MAX; + ulong diff = 0; int cf = fd_ulong_checked_sub( latency, VOTE_CREDITS_GRACE_SLOTS, &diff ); - // https://github.com/firedancer-io/solana/blob/v1.17.5/sdk/program/src/vote/state/mod.rs#L507-L523 - return fd_ulong_if( - cf | !diff, - VOTE_CREDITS_MAXIMUM_PER_SLOT, - fd_ulong_if( - fd_ulong_checked_sub( VOTE_CREDITS_MAXIMUM_PER_SLOT, diff, &diff ) | !diff, 1, diff ) ); + if( cf != 0 || diff == 0 ) { + return VOTE_CREDITS_MAXIMUM_PER_SLOT; + } + + ulong credits = 0; + cf = fd_ulong_checked_sub( VOTE_CREDITS_MAXIMUM_PER_SLOT, diff, &credits ); + if( cf != 0 || credits == 0 ) { + return 1; + } + return credits; } // https://github.com/firedancer-io/solana/blob/da470eef4652b3b22598a1f379cacfe82bd5928d/sdk/program/src/vote/state/mod.rs#L447 diff --git a/src/flamenco/runtime/tests/run_ledger_tests.sh b/src/flamenco/runtime/tests/run_ledger_tests.sh index 3308ea209b..5c91bcabdc 100755 --- a/src/flamenco/runtime/tests/run_ledger_tests.sh +++ b/src/flamenco/runtime/tests/run_ledger_tests.sh @@ -276,9 +276,6 @@ if [[ $ON_DEMAND = 1 ]]; then $TILE_CPUS >& $LOG status=$? - if [ $status -ne 0 ]; then - echo_error "on demand 1 $LOG" - fi { set +x; } &> /dev/null echo_notice "Finished on-demand ingest and replay\n" fi diff --git a/src/flamenco/runtime/tests/run_ledger_tests_all.txt b/src/flamenco/runtime/tests/run_ledger_tests_all.txt index 902d60c446..44f1a0825b 100644 --- a/src/flamenco/runtime/tests/run_ledger_tests_all.txt +++ b/src/flamenco/runtime/tests/run_ledger_tests_all.txt @@ -21,3 +21,5 @@ src/flamenco/runtime/tests/run_ledger_tests.sh -l mainnet-257058865 -s snapshot- src/flamenco/runtime/tests/run_ledger_tests.sh -l mainnet-257059815 -s snapshot-257059815-AmWkVebTmg6ih2VTEjMmU9WtXhT3RygEoSJBHfDpyAG3.tar.zst -p 16 -y 16 -m 5000000 -e 257059818 --zst src/flamenco/runtime/tests/run_ledger_tests.sh -l mainnet-257061172 -s snapshot-257061172-8e6cUSMUx2VZZBDzwXjEY6bGkzPgnUmqrDyr4uErG8BF.tar.zst -p 16 -y 16 -m 5000000 -e 257061175 --zst src/flamenco/runtime/tests/run_ledger_tests.sh -l mainnet-257222682 -s snapshot-257222682-Dudsosehu5xdHbqzG5sy72qEu6KyS9FmHnW7oV8pRoNn.tar.zst -p 16 -y 16 -m 5000000 -e 257222688 --zst +src/flamenco/runtime/tests/run_ledger_tests.sh -l mainnet-264890264 -s snapshot-264890263-G9sNBh5CPSU9A1nXtC6QE87o1NPkwyMPh7XVKG5mw1Ka.tar.zst -p 32 -y 16 -m 5000000 -e 264890265 --zst +src/flamenco/runtime/tests/run_ledger_tests.sh -l mainnet-257229353 -s snapshot-257229353-9wETKbJxKf7ceWxtLFJN8VffLQJ2xQVXLUgrXtp6UMx.tar.zst -p 16 -y 16 -m 5000000 -e 257229353 --zst diff --git a/src/flamenco/vm/fd_vm_syscalls.c b/src/flamenco/vm/fd_vm_syscalls.c index 58dedaba19..8205610d5b 100644 --- a/src/flamenco/vm/fd_vm_syscalls.c +++ b/src/flamenco/vm/fd_vm_syscalls.c @@ -15,6 +15,7 @@ #include "../runtime/context/fd_exec_txn_ctx.h" #include "../runtime/context/fd_exec_instr_ctx.h" #include "../../ballet/ed25519/fd_curve25519.h" +#include "../../util/bits/fd_uwide.h" #include #include @@ -717,7 +718,8 @@ fd_vm_syscall_cpi_c_instruction_to_instr( fd_vm_exec_context_t * ctx, } } - ulong starting_lamports = 0; + ulong starting_lamports_h = 0; + ulong starting_lamports_l = 0; uchar acc_idx_seen[256]; memset(acc_idx_seen, 0, 256); for( ulong i = 0; i < cpi_instr->accounts_len; i++ ) { @@ -742,7 +744,9 @@ fd_vm_syscall_cpi_c_instruction_to_instr( fd_vm_exec_context_t * ctx, /* This is the first time seeing this account */ acc_idx_seen[j] = 1; if( instr->borrowed_accounts[i]->const_meta != NULL ) { - starting_lamports += instr->borrowed_accounts[i]->const_meta->info.lamports; + fd_uwide_inc( &starting_lamports_h, &starting_lamports_l, + starting_lamports_h, starting_lamports_l, + instr->borrowed_accounts[i]->const_meta->info.lamports ); } } // TODO: should check the parent has writable flag set @@ -769,10 +773,11 @@ fd_vm_syscall_cpi_c_instruction_to_instr( fd_vm_exec_context_t * ctx, } } - instr->data_sz = (ushort)cpi_instr->data_len; - instr->data = (uchar *)cpi_instr_data; - instr->acct_cnt = (ushort)cpi_instr->accounts_len; - instr->starting_lamports = starting_lamports; + instr->starting_lamports_h = starting_lamports_h; + instr->starting_lamports_l = starting_lamports_l; + instr->data_sz = (ushort)cpi_instr->data_len; + instr->data = (uchar *)cpi_instr_data; + instr->acct_cnt = (ushort)cpi_instr->accounts_len; } @@ -797,7 +802,8 @@ fd_vm_syscall_cpi_rust_instruction_to_instr( fd_vm_exec_context_t const * ctx, } } - ulong starting_lamports = 0; + ulong starting_lamports_h = 0; + ulong starting_lamports_l = 0; uchar acc_idx_seen[256]; memset(acc_idx_seen, 0, 256); // FD_LOG_DEBUG(("Accounts cnt %lu %lu", ctx->instr_ctx->txn_ctx->accounts_cnt, ctx->instr_ctx->txn_ctx->txn_descriptor->acct_addr_cnt)); @@ -817,7 +823,9 @@ fd_vm_syscall_cpi_rust_instruction_to_instr( fd_vm_exec_context_t const * ctx, /* This is the first time seeing this account */ acc_idx_seen[j] = 1; if( instr->borrowed_accounts[i]->const_meta != NULL ) { - starting_lamports += instr->borrowed_accounts[i]->const_meta->info.lamports; + fd_uwide_inc( &starting_lamports_h, &starting_lamports_l, + starting_lamports_h, starting_lamports_l, + instr->borrowed_accounts[i]->const_meta->info.lamports ); } } @@ -844,12 +852,11 @@ fd_vm_syscall_cpi_rust_instruction_to_instr( fd_vm_exec_context_t const * ctx, } } - instr->data_sz = (ushort)cpi_instr->data.len; - instr->data = (uchar *)cpi_instr_data; - instr->acct_cnt = (ushort)cpi_instr->accounts.len; - instr->starting_lamports = starting_lamports; - - // FD_LOG_WARNING(("starting lamps CPI: %lu", instr->starting_lamports)); + instr->data_sz = (ushort)cpi_instr->data.len; + instr->data = (uchar *)cpi_instr_data; + instr->acct_cnt = (ushort)cpi_instr->accounts.len; + instr->starting_lamports_h = starting_lamports_h; + instr->starting_lamports_l = starting_lamports_l; } @@ -1593,9 +1600,6 @@ fd_vm_syscall_cpi_c( memcpy( acct_keys[i].uc, acct_addr->uc, sizeof(fd_pubkey_t) ); } - /* TODO: Dispatch CPI to executor. - For now, we'll just log parameters. */ - fd_instruction_account_t instruction_accounts[256]; ulong instruction_accounts_cnt; fd_instr_info_t cpi_instr; @@ -1603,7 +1607,7 @@ fd_vm_syscall_cpi_c( fd_vm_syscall_cpi_c_instruction_to_instr( ctx, instruction, accounts, signers, signers_seeds_cnt, data, &cpi_instr ); err = fd_vm_prepare_instruction(ctx->instr_ctx->instr, &cpi_instr, ctx->instr_ctx, instruction_accounts, &instruction_accounts_cnt, signers, signers_seeds_cnt ); if( err != 0 ) { - FD_LOG_WARNING(("PREPARE FAILED")); + FD_LOG_WARNING(("vm preparation failed")); return err; } @@ -1617,12 +1621,21 @@ fd_vm_syscall_cpi_c( return err; } - ulong caller_lamports = fd_instr_info_sum_account_lamports( ctx->instr_ctx->instr ); - if( caller_lamports != ctx->instr_ctx->instr->starting_lamports ) { + /* TODO: lamport checks in cpi_c may be redundant as it is checked in fd_execute_instr */ + ulong caller_lamports_h = 0; + ulong caller_lamports_l = 0; + int err_exec = fd_instr_info_sum_account_lamports( ctx->instr_ctx->instr, &caller_lamports_h, &caller_lamports_l ); + if( err_exec ) { + return FD_VM_SYSCALL_ERR_INSTR_ERR; + } + + if( caller_lamports_h != ctx->instr_ctx->instr->starting_lamports_h || + caller_lamports_l != ctx->instr_ctx->instr->starting_lamports_l ) { return FD_VM_SYSCALL_ERR_INSTR_ERR; } + ctx->instr_ctx->txn_ctx->compute_meter = ctx->compute_meter; - int err_exec = fd_execute_instr( ctx->instr_ctx->txn_ctx, &cpi_instr ); + err_exec = fd_execute_instr( ctx->instr_ctx->txn_ctx, &cpi_instr ); ulong instr_exec_res = (ulong)err_exec; // uchar * sig = (uchar *)ctx->instr_ctx->txn_ctx->_txn_raw->raw + ctx->instr_ctx->txn_ctx->txn_descriptor->signature_off; // FD_LOG_WARNING(( "CPI CUs CONSUMED: %lu %lu %lu %64J", ctx->compute_meter, ctx->instr_ctx->txn_ctx->compute_meter, ctx->compute_meter - ctx->instr_ctx->txn_ctx->compute_meter, sig)); @@ -1640,8 +1653,15 @@ fd_vm_syscall_cpi_c( if( FD_UNLIKELY( res != FD_VM_SYSCALL_SUCCESS ) ) return res; } - caller_lamports = fd_instr_info_sum_account_lamports( ctx->instr_ctx->instr ); - if( caller_lamports != ctx->instr_ctx->instr->starting_lamports ) { + caller_lamports_h = 0; + caller_lamports_l = 0; + err_exec = fd_instr_info_sum_account_lamports( ctx->instr_ctx->instr, &caller_lamports_h, &caller_lamports_l ); + if( err_exec ) { + return FD_VM_SYSCALL_ERR_INSTR_ERR; + } + + if( caller_lamports_h != ctx->instr_ctx->instr->starting_lamports_h || + caller_lamports_l != ctx->instr_ctx->instr->starting_lamports_l ) { return FD_VM_SYSCALL_ERR_INSTR_ERR; } @@ -1750,9 +1770,6 @@ fd_vm_syscall_cpi_rust( memcpy( acct_keys[i].uc, acct_addr->uc, sizeof(fd_pubkey_t) ); } - /* TODO: Dispatch CPI to executor. - For now, we'll just log parameters. */ - fd_instruction_account_t instruction_accounts[256]; ulong instruction_accounts_cnt; fd_instr_info_t cpi_instr; @@ -1760,7 +1777,7 @@ fd_vm_syscall_cpi_rust( fd_vm_syscall_cpi_rust_instruction_to_instr( ctx, instruction, accounts, signers, signers_seeds_cnt, data, &cpi_instr ); err = fd_vm_prepare_instruction(ctx->instr_ctx->instr, &cpi_instr, ctx->instr_ctx, instruction_accounts, &instruction_accounts_cnt, signers, signers_seeds_cnt ); if( err != 0 ) { - FD_LOG_WARNING(("PREPARE FAILED")); + FD_LOG_WARNING(("vm prepare failed")); return err; } @@ -1774,12 +1791,21 @@ fd_vm_syscall_cpi_rust( return err; } - ulong caller_lamports = fd_instr_info_sum_account_lamports( ctx->instr_ctx->instr ); - if( caller_lamports != ctx->instr_ctx->instr->starting_lamports ) { + /* TODO: lamport checks in cpi_c may be redundant as it is checked in fd_execute_instr */ + ulong caller_lamports_h = 0; + ulong caller_lamports_l = 0; + int err_exec = fd_instr_info_sum_account_lamports( ctx->instr_ctx->instr, &caller_lamports_h, &caller_lamports_l ); + if( err_exec ) { + return FD_VM_SYSCALL_ERR_INSTR_ERR; + } + + if( caller_lamports_h != ctx->instr_ctx->instr->starting_lamports_h || + caller_lamports_l != ctx->instr_ctx->instr->starting_lamports_l ) { return FD_VM_SYSCALL_ERR_INSTR_ERR; } + ctx->instr_ctx->txn_ctx->compute_meter = ctx->compute_meter; - int err_exec = fd_execute_instr( ctx->instr_ctx->txn_ctx, &cpi_instr ); + err_exec = fd_execute_instr( ctx->instr_ctx->txn_ctx, &cpi_instr ); ulong instr_exec_res = (ulong)err_exec; #ifdef VLOG uchar * sig = (uchar *)ctx->instr_ctx->txn_ctx->_txn_raw->raw + ctx->instr_ctx->txn_ctx->txn_descriptor->signature_off; @@ -1803,8 +1829,15 @@ fd_vm_syscall_cpi_rust( } } - caller_lamports = fd_instr_info_sum_account_lamports( ctx->instr_ctx->instr ); - if( caller_lamports != ctx->instr_ctx->instr->starting_lamports ) { + caller_lamports_h = 0; + caller_lamports_l = 0; + err_exec = fd_instr_info_sum_account_lamports( ctx->instr_ctx->instr, &caller_lamports_h, &caller_lamports_l ); + if( err_exec ) { + return FD_VM_SYSCALL_ERR_INSTR_ERR; + } + + if( caller_lamports_h != ctx->instr_ctx->instr->starting_lamports_h || + caller_lamports_l != ctx->instr_ctx->instr->starting_lamports_l ) { return FD_VM_SYSCALL_ERR_INSTR_ERR; }