Replace legacy db_*_i64 intrinsics with KV intrinsics#269
Open
Replace legacy db_*_i64 intrinsics with KV intrinsics#269
Conversation
jglanz
requested changes
Mar 23, 2026
Comment on lines
+2
to
+6
| add_contract( bench_kv_db bench_kv_db bench_kv_db.cpp ) | ||
| else() | ||
| configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/bench_kv_db.wasm ${CMAKE_CURRENT_BINARY_DIR}/bench_kv_db.wasm COPYONLY ) | ||
| configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/bench_kv_db.abi ${CMAKE_CURRENT_BINARY_DIR}/bench_kv_db.abi COPYONLY ) | ||
| endif() |
Collaborator
There was a problem hiding this comment.
Considering this is new code, shouldn't we be using GLOB[_RECURSE] file sets?
This applies to all new CMake files in the PR under unittests/test-contracts/*/CMakeLists.txt
e34729f to
3014888
Compare
fc29c55 to
14b9eb6
Compare
…tioned index Host-side KV database: - 22 KV intrinsics replacing 60 legacy db_*_i64 intrinsics - Format-partitioned by_code_key index: format=0 (raw_table) and format=1 (multi_index/table) stored in separate partitions, preventing collisions - key_format parameter added to kv_get, kv_erase, kv_contains, kv_it_create - config::kv_format_raw and config::kv_format_standard constants New API endpoint: - /v1/chain/get_kv_rows for querying format=0 (raw_table) KV data - Supports JSON key decoding via ABI key metadata, pagination, bounds, reverse - be_key_codec for server-side BE key encoding/decoding SysioTester build-tree support: - Auto-discover libraries, includes, and vcpkg paths from uninstalled wire-sysio - Enables CDT integration tests against build dir without install All contracts recompiled with updated CDT intrinsic signatures. Reference data regenerated (deep-mind log, snapshots, consensus blockchain).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR replaces the 60 legacy EOSIO
db_*_i64anddb_idx*host functions with 22 new KV (key-value) database intrinsics. All contract storage now uses a unified key-value model instead of the legacy multi-table system inherited from EOSIO.Companion CDT PR: Wire-Network/wire-cdt#41
Why
The legacy database layer is a complex subsystem inherited from EOSIO:
table_id_object→ then findkey_value_objectwithin itidx64,idx128,idx256,idx_double,idx_long_double), each with 10 host functions and its own chainbase objectWire is a new chain that hasn't launched yet. We have the rare opportunity to replace this before any production state exists.
What Changed
Chain Library (22 new intrinsics replacing 60)
db_store/update/remove/get_i64kv_set,kv_get,kv_erase,kv_containsdb_find/next/previous/lowerbound/upperbound/end_i64kv_it_create/destroy/status/next/prev/lower_bound/key/valuekv_idx_*functionsKey Design Decisions
SSO (Small String Optimization) — Keys ≤24 bytes stored inline in the chainbase object, avoiding heap allocation. The standard key layout
[table:8B][scope:8B][pk:8B]= 24 bytes fits exactly in SSO.Integer fast-path comparator — 8-byte keys compared via
bswap64+ integer comparison instead ofmemcmp. Endian-portable viakv_load_be64(bswap on LE, identity on BE).Unified secondary index — One
kv_index_objecttype replaces all 5 legacy secondary index types. Secondary keys stored as variable-length bytes with order-preserving encoding.key_format field — Each row has a
key_format(0=raw, 1=standard 24-byte). SHiP uses this to deterministically decode keys back to legacy(code, scope, table, pk)format.kv_idx_find_secondary/kv_idx_lower_boundreturnint32_t— Returns-1for not-found (no handle allocated),>= 0for valid handle.kv_idx_lower_boundreturns handle initerator_endstate when bound is past all entries but table is non-empty (enableskv_idx_prevfor reverse iteration). Saves 1-2 host function calls per secondary lookup.Iterator cached-ID fast path — Iterators cache the chainbase object ID. On
next/prev, the fast path doesdb.find(cached_id)+ O(1)iterator_to+ O(1) advance, avoiding the expensive composite-keylower_boundre-seek. Falls back to composite key lookup only when the row was erased mid-iteration. Thekey/valueread functions also use the cached ID, eliminating composite index lookups for the common case. Per-step cost drops from 3 composite index lookups to 3 simple integer-key lookups (~3x faster constant factor).RPC API
get_table_rows— Fully functional for both primary AND secondary index queries. Supports all key types:i64,i128,sha256/i256,float64,float128. Forward/reverse iteration, pagination withnext_key, scope filtering.get_kv_rows— New endpoint for querying format=0 (raw_table) entries with composite key decoding. Usesbe_key_codecwith NUL-escape string encoding.get_table_by_scope— Reimplemented with KV prefix scanning.SHiP Compatibility
"contract_row"— backward compatible with Hyperion"contract_row_kv"— new delta type, clients opt incontract_tabledeltas removed (tables are implicit in KV key prefixes). Secondary index deltas consolidated intocontract_index_kv(generic bytes instead of typed fields). SHiP consumers that parse secondary index deltas or track table creation/removal events must be updated.Deep Mind
DB_OP INS/UPD/REM— same format as legacy for backward compatibilityKV_OP INS/UPD/REM— new log format with hex-encoded keysold_payer:new_payer(old payer captured beforedb.modify)Snapshot Format
std::vector<char>instead ofshared_blob— JSON snapshots encode key/value fields as hex (previously base64). Binary snapshot format is unchanged.CDT Changes
#include <sysio/multi_index.hpp>andsysio::multi_indexstill work — they forward to the KV implementationsysio::singletonsysio::kv::tablefor zero-copy high-performance contractssysio::kv::raw_tablefor ordered key-value store with custom keys++it/--it)be_key_streamsupports all types: int8-128 (signed/unsigned), float, double, bool, name, NUL-escaped strings, vectorPros
Simplicity
kv_object+kv_index_objectreplacetable_id_object+key_value_object+ 5 secondary index typestable_id_objectindirection — every lookup is directiterator_cachewith raw pointers — KV iterators re-seek by key with cached-ID fast pathSecurity
receivermemcpy/memsetcalls in SSO assign functions guarded against null pointers with size checksPerformance
table_id_objectlookup on every operationkv::tablezero-copy path for trivially_copyable structsint32_treturn encodingnext/prev/key/valueuse O(1)iterator_toinstead of composite key re-seekRAM Efficiency
table_id_objectoverhead (108 bytes per unique scope)Cons
Breaking Change
db_*imports must be recompiledcontract_tableremoved, secondary index deltas consolidatedSecondary Index Overhead
kv_index_objecttable_id_objectoverheadCDT Dependency
feature/cdt-db-kvbranch is required