Feature/jsonrpc#1
Conversation
…on and execution, test coverage of JsonRpcService, moved keystore tests to nunit
…on and execution, test coverage of JsonRpcService, moved keystore tests to nunit
…mind into feature/jsonrpc
…ethod and mappers for json RPC
| // lower difficulty branch | ||
| _blockStore.AddBlock(suggestedBlock, false); | ||
| } | ||
| SuggestedBlock = null; |
| public interface IBlockchainProcessor | ||
| { | ||
| Block HeadBlock { get; } | ||
| //Currently processing block |
|
|
||
| public Address Address => PublicKey.Address; | ||
|
|
||
| public Guid Id { get; set; } |
There was a problem hiding this comment.
we will need to review how we pass private key around in memory (need to be protected and overwritten), separately - let us discuss why we need Guid - can't we store by public key? (or is it to cover all the scenarios when public key is same? - rare)
| } | ||
|
|
||
| public static byte[] GenerateRandomBytes(int lenght) | ||
| { |
There was a problem hiding this comment.
if not behind interface then equally we can use SecureRandom.GetBytes directly, otherwise let us push it behind ISecureRandom so we can test with this class wherever used
| transaction.Signature = signature; | ||
| } | ||
|
|
||
| transaction.RecomputeHash(); |
There was a problem hiding this comment.
any suggestion how to do that nicer? I did not like it in my code (for block header) and wanted to refactor
There was a problem hiding this comment.
maybe some change tracking and getter for hash that would always recompute when onvoked and any changes were made...
| } | ||
|
|
||
| public byte[] ToBytes() | ||
| { |
There was a problem hiding this comment.
there is implicit conversion operator, not sure if we need it ever
There was a problem hiding this comment.
I am not a great fan of the Hex class any more by the way, we will review when alpha version fiinished
| { | ||
| void Log(string text); | ||
| void Debug(string text); | ||
| void Error(string text, Exception ex = null); |
There was a problem hiding this comment.
maybe better Error(string text) and Error(Exception ex) separately?
| public Keccak Hash { get; set; } | ||
|
|
||
| public void RecomputeHash() | ||
| { |
There was a problem hiding this comment.
do we have a single test for this (not that I never neglected it)
| public long GasUsed { get; set; } | ||
| public Bloom Bloom { get; set; } | ||
| public LogEntry[] Logs { get; set; } | ||
| public Address Recipient { get; set; } |
There was a problem hiding this comment.
need to learn more - this I guess is only in the network version but not in the one created by EVM
| void AddTransactionReceipt(Keccak transactionHash, TransactionReceipt transactionReceipt, Keccak blockhash); | ||
| Transaction GetTransaction(Keccak transactionHash); | ||
| TransactionReceipt GetTransactionReceipt(Keccak transactionHash); | ||
| bool WasProcessed(Keccak transactionHash); |
There was a problem hiding this comment.
what does it mean? it may not be on the main chain even if it was added, maybe worth to clarify the API, let us discuss
| transactionReceipt.GasUsed = gasUsedSoFar; | ||
| transactionReceipt.PostTransactionState = _stateProvider.StateRoot; | ||
| transactionReceipt.StatusCode = statusCode; | ||
| transactionReceipt.Recipient = recipient; |
There was a problem hiding this comment.
cool but I guess it was never tested so worth adding a test if not there yet
| } | ||
|
|
||
| public void AddTransactionReceipt(Keccak transactionHash, TransactionReceipt transactionReceipt, Keccak blockhash) | ||
| { |
There was a problem hiding this comment.
let me know how it discriminates between processed and failed or succeeded and also if it matters whether it was included in the main chain
| _transactions[transaction.Hash] = transaction; | ||
| } | ||
|
|
||
| public void AddTransactionReceipt(Keccak transactionHash, TransactionReceipt transactionReceipt, Keccak blockhash) |
…ainst extension-only split Two coupled fixes for the EXPB sparse-vs-Patricia mismatch: 1. MultiProofReader: when walking through an Extension, ALWAYS load the underlying Branch and include it in the proof — not just when a target fully matches the extension's shortKey. This is required for the absence-at-extension case where an update partially matches the prefix then diverges, triggering a split. The split needs to know the inner Branch's content to encode the existing extension+branch correctly as a child of the new wrapping branch. 2. SparseSubtrie.UpdateAtBranch: detect extension-only state (stateMask == 0 with non-empty shortKey, meaning the inner Branch was revealed by hash only) and return NeedsProof so the retry loop fetches a proof that materializes the inner Branch. This is a safety net for any edge case where fix #1 doesn't apply. Root cause from EXPB diagnostic: at depth ~7, sparse produced inline 'D1 80×17' (an empty Branch RLP) where Patricia had a real 32-byte hash. The empty Branch came from SplitExtensionAndInsert truncating the shortKey of an extension-only BranchWithExtension whose inner Branch was never revealed (stateMask=0).
…plit result Two related fixes for the retry-loop stall at block 22360144 (non-USDT account 0x4a29406e...). EXPB diagnostic showed: 1 stuck update target, isDelete=False, TryFindBlindedEntryOnPath returns false (no boundary on path), TryFindBlindedSiblingForDeletion returns false. UpdateLeaves keeps reporting NeedsProof but the retry loop can't find anything to fetch — so it loops 10 times and throws. Root cause #1: UpdateAtBranch's pre-recursion check returned NeedsProof for ANY non-delete update hitting an extension-only node, including when the update's path DIVERGES inside the extension's shortKey. That diverge case can be split LOCALLY without revealing the inner branch — the original extension just gets a shorter shortKey, its blinded child reference stays intact, and a new leaf joins via a new parent branch. Now the pre-check only requests a proof when the path matches the full shortKey (continuing INTO the inner branch). Root cause #2: SplitExtensionAndInsert can shrink an extension's ShortKey to empty (commonLen+1 == extensionKey.Length). The current code sets ShortKey = null, leaving a degenerate node: Kind=Branch, StateMask=Empty, ShortKey=null, one orphaned blinded child slot. HashNode's extension-only check requires HasShortKey, so this falls through to EncodeBranch and emits a 17-element empty branch — wrong. Fix: when ShortKey would become empty, promote the blinded child reference directly into the new parent's child slot at existingNibble and free the degenerate node.
…GetCacheSize) Analysis of the cross-block sparse cache (PreservedSparseTrie) showed it works near-optimally for its job: block #1 cold-reads the full proof (proof=26ms, 1818 nodes), block #2+ are warm (proof=0-1ms) because hot paths stay revealed. Warm sparse root computation is 1-3ms/block. The catch is SIZE. With pruning off by default, SparseStateTrie._storageTries grows one SparsePatriciaTree arena per contract ever touched and only evicts on reorg/clear — unbounded retained memory on a long-running node. Prune is the bound (it drops cold contracts and prunes cold slots) but it's disabled by default, and until now there was no way to even observe the growth. Adds cheap, allocation-free size reporting: - SparseSubtrie.ArenaHighWater / SparsePatriciaTree.ArenaHighWater: arena slot high-water mark, a monotonic proxy for retained footprint. - SparseStateTrie.GetCacheSize(): (storageTrieCount, accountArenaNodes, storageArenaNodes). storageTrieCount is the value that grows unbounded. - FlatWorldStateScope logs the cache size at Debug on each anchored commit, tagged with whether pruning is on. This is the prerequisite for safely enabling a bounded cache in production: you can now watch the retained set and size the prune caps to a memory budget. No behavior change to root computation; metrics only. Note: profiling established the sparse trie is NOT on the EVM execution read path (EVM reads go WorldState -> PersistentStorageProvider -> SnapshotBundle -> RocksDB), so warming the sparse trie cannot reduce execution-time storage reads — it only saves proof reads, which the cross-block cache already drives to ~0. The remaining DB-read cost lives in a separate subsystem. Tests: 521 + 432 green.
…nchmarks runner Fixes from smoke run #1 and adversarial review: - flood: pin uv tool env to Python 3.10 (pyarrow 12.0.1 has no cp313 wheels), use 'flood print' for the text summary, fail-fast vegeta download - stop-node: stop before capturing logs so shutdown-phase exceptions are scanned - quality gate now fails the job when the tool step (continue-on-error) failed - fingerprint: typed listing with mode/owner, loud failure on partial listings, cross-run anchor persisted after clean verify - path safety: canonical (symlink-proof) guards + input shape validation in resolve; defensive cleanup moved to guarded cleanup.sh; reap stale containers by name prefix; never rm -rf while mounts remain underneath - EthCallChaos: camelCase JSON fields in jq, corpus from corpus-v1 release asset
jsonRpc initial version, key store impementation