Implement child wallets - #351
Draft
itsafuu wants to merge 144 commits into
Draft
Conversation
…es, registration=8 oneof arm - Append RegistrationMetadata (game_id, publisher_id, dev_wallet, peers_cut) to SGTransaction.proto - Append RegistrationTx (dag_struct, main_address, sequence, metadata) to SGTransaction.proto - Add SGTransaction.RegistrationTx registration = 8 to Consensus.proto EmbeddedTransaction oneof - Purely additive — no existing fields or messages modified
…alization, deserialization - Header: class RegistrationTransaction final : public GeniusTransaction - New() factory constructs instance and calls FillHash - SerializeByteVector / SerializeToEmbeddedTransaction populate RegistrationTx proto - DeSerializeByteVector parses proto via ParseFromArray, returns shared_ptr or nullptr - GetTopics includes main_address_ for pubsub discovery - Static Register() + inline registered for automatic deserializer registration - Follows TransferTransaction/MintTransaction reference patterns exactly
…ests - Add RegistrationTransaction.cpp to GENIUS_NODE_SOURCES (genius_node + genius_node_test) - Create registration_transaction_test.cpp with 4 test cases: RoundTripSerialization: SerializeByteVector → DeSerializeByteVector round-trip FactoryFillHash: New() produces non-empty hash and correct type SerializeToEmbeddedTransaction: oneof registration() set with correct values GetTopics: main_address_ included in topic set - Add test target to test/src/account/CMakeLists.txt with genius_node_test link
…and add RegisterChild API - Add 'registration' deserializer registration in static lambda - Add case EmbeddedTransaction::kRegistration to DeSerializeEmbeddedTransaction switch - TransactionManager::RegisterChild(main_address, metadata, sequence) constructs via New(), signs child-only via MakeSignature, enqueues, returns hash - GeniusNode::RegisterChild thin wrapper delegating to TransactionManager with READY state check
- SendTransactionItem diverts RegistrationTx to GetBlockChainBase()+reg/{child_addr}
- FilterRegistration with Phase 4 gates: (a) deserialization failure, (b) invalid child signature, (c) malformed main_address
- FilterRegistration registered on ^/?/bc-{net}/reg/[^/]+ pattern in New()
…on gates - ChildRegistrationEndToEnd: full RegisterChild flow through TM (skips if not READY) - ChildRegistrationTamperedSignatureRejected: post-signature tampering fails CheckSignature - FilterRegistrationAcceptsValid: valid RegistrationTx passes filter (nullopt) - FilterRegistrationRejectsBadMainAddress: malformed main_address gets tombstone - FilterRegistrationRejectsTamperedSignature: tampered signature gets tombstone - Add RegistrationE2ETestAccess friend class for private TM method access - Link base_crdt_test for CRDTFixture support
… test reaches READY
- FilterRegistrationRejectsZeroSequence: seq=0 always rejected - FilterRegistrationRejectsNonMonotonicSequence: seq=3 rejected when stored=4 - FilterRegistrationAcceptsHigherSequence: seq=5 accepted when stored=4
…ration
- Gate (d) per D-46: reject sequence==0 (well-formed check)
- Gate (d): read existing reg/{child_addr} via CRDT Get, reject if incoming <= stored
- Graceful skip when stored record is unreadable (null optional/has_error guard)
- Updated FilterRegistration doxygen to describe gate (d)
…o-derive overload - Add 2-arg RegisterChild declarations to TransactionManager.hpp and GeniusNode.hpp - RegisterChildAutoDeriveFirstRegistration: 2-arg call, no prior -> seq=1 - RegisterChildAutoDeriveIncrementsFromStored: 2-arg after stored=5 -> seq=6 - RegisterChildPreservesCallerSequence: 3-arg preserves explicit seq=5
- TransactionManager::RegisterChild(main_address, metadata) reads reg/{child_addr} from CRDT
- Auto-derives sequence as stored_sequence + 1 (or 1 for first registration)
- Delegates to 3-arg RegisterChild after auto-derive
- GeniusNode wrapper follows existing two-layer pattern (state guard, BOOST_OUTCOME_TRY)
…ansactionItem reg/ path - Fix 1: null-check after dynamic_pointer_cast (matches FilterRegistration pattern) - Fix 2: explicit empty-check on SerializeByteVector before CRDT write - Both fixes return invalid_argument error code on failure (matching existing pattern)
…veryEntry + GetRegistrationsForMain - Add RegistrationDiscoveryEntry struct in TransactionManager.hpp at namespace sgns - Add GetRegistrationsForMain declaration (protected, after KeyExistsInDB) - Add RegistrationE2ETestAccess::GetRegistrationsForMain accessor - Add 3 test cases: empty-result, returns-matching, filters-by-main-address
…onManager - Scan reg/ CRDT namespace across all monitored networks via QueryKeyValues - Deserialize each value, filter by GetType()=='registration', cast to RegistrationTransaction - Filter by main_address match, build RegistrationDiscoveryEntry vector - Return empty vector (not error) when no matches found - Log errors for QueryKeyValues failures, trace for per-key filtering
…ForMain wrapper + RegElementCallback - Add GeniusNode::GetRegistrationsForMain declaration (two-layer API pattern) - Add TransactionManager::RegElementCallback declaration for reg/ CID notification handler - Both follow existing patterns: two-layer wrapper convention and NewElementCallback analog
…egElementCallback CID handler - Add GeniusNode::GetRegistrationsForMain two-layer wrapper with TRANSACTIONS_NOT_READY guard - Register RegisterNewElementCallback for reg/ namespace in TransactionManager::New() - Implement RegElementCallback: deserialize, check main_address==local, AddListenTopic(child_addr) - Unregister reg/ patterns (filter + callback) in ~TransactionManager - Follows D-49 CID notification handler + AddListenTopic follow pattern
…tion (RED) - Create regtest/CMakeLists.txt for child_registration_test target - Add add_subdirectory(regtest) to multiaccount CMakeLists.txt - Create ChildRegistrationIntegrationTest fixture with static SetUpTestSuite/TearDownTestSuite - Implement CreateNode helper (copied from multi_account_sync.cpp, FILE_PREFIX='cri_') - 3-node network boot pattern: genesis-authorized + main A + child B per D-51/D-52 - RegTestAccess friend accessor for FilterRegistration (needed by Task 3)
…(RED) - TEST-02 ChildRegistersWithMain: child_node_ submits RegistrationTx to main_node_, asserts valid 64-char tx hash - TEST-03 MainDiscoversChild: polls main_node_ GetRegistrationsForMain for up to 60s, asserts correct child_addr/main_addr/sequence - Uses distinct sequences per D-52 (1 and 2) for CRDT state isolation across test cases - assertWaitForCondition used without bool capture (returns void — Rule 1 auto-fix from plan template)
…rationRejected (RED) - Sub-case A: Tampered child signature → FilterRegistration returns tombstone - Sub-case B: Malformed main_address (64-char, not 128-hex) → tombstone - Sub-case C: Non-monotonic sequence — submit seq=50 through pipeline, wait for CRDT sync, then inject seq=49 via filter accessor → tombstone per gate (d) - End-to-end assertion: GetRegistrationsForMain confirms no rejected entries appear in discovery - Uses child_node_->account_ (public member) for signing test transactions - Sub-case C uses pipeline approach: RegisterChild API → pubsub propagation wait → filter injection
…rationIntegrationTest - Add friend class RegTestAccess at TransactionManager.hpp:319 to resolve CR-01 - Add friend class ChildRegistrationIntegrationTest at GeniusNode.hpp:741 to resolve CR-02 - Both declarations follow existing test-access friend patterns in each file
…DAG signature tampering - registration_transaction_test.cpp FilterRegistrationRejectsTamperedSignature: replace raw-byte tampering with proto-level dag_mutable->signature() modification + re-serialize - child_registration.cpp InvalidRegistrationRejected sub-case A: same proto-level approach - Both sites now use ASSERT_TRUE/ASSERT_FALSE instead of conditional if-checks - Fixes WR-02 and WR-03 — signature tampering is now deterministic regardless of proto field layout
…s, namespace, link deps) - Fix crdt/proto/crdt.pb.h -> crdt/proto/delta.pb.h (correct proto header) - Fix SGTransaction.pb.h -> account/proto/SGTransaction.pb.h (include path) - Move ChildRegistrationIntegrationTest and TEST_F macros into namespace sgns so friend class ChildRegistrationIntegrationTest in GeniusNode.hpp resolves - Add base_crdt_test to child_registration_test link deps (provides CRDT proto include paths, matching registration_transaction_test pattern)
…ccess - Replace friend class ChildRegistrationIntegrationTest with friend class ChildRegTestAccess in GeniusNode.hpp to match established MultiAccountTestAccess pattern - Define ChildRegTestAccess in child_registration.cpp with GetAccount() and GetTransactionManager() static methods - Update all test code to use ChildRegTestAccess::GetAccount() and ::GetTransactionManager() instead of direct protected member access
- Remove stray 'auto' from ASSERT_OUTCOME_SUCCESS calls (macro already provides auto&&) - Use GeniusNode::Error::TRANSACTIONS_NOT_READY instead of Error::UNSPECIFIED
- Declare token-filtered and all-tokens GetChildBalance overloads in GeniusNode.hpp, mirroring the GetBalance family Doxygen style - Implement both overloads in GeniusNode.cpp as thin delegations to account_->GetUTXOManager().GetBalance(...), with argument order swapped (token first) for the token-filtered overload per D-56
- child_node_ mints its own DevConfig token via MintTokens - polls child_node_'s own balance until mint lands - polls main_node_'s GetChildBalance until CRDT sync converges - asserts main_node_->GetChildBalance equals the exact minted amount
- MintTokens' chainid arg selects the InputValidator (see testutil/TestMintInputValidator.hpp, which registers "test"); an unregistered chainid like "test_05_balance" falls back to the public-chain validator requiring real RPC burn verification, causing the mint to be rejected immediately - switched to "test" to match the registered test-only validator, consistent with the multi_account_sync.cpp precedent
- Declares CheckCertifiedParent(child_addr) -> optional<main_addr> on Blockchain - Implements via direct reg/ CRDT read + raw RegistrationTx proto parse, gated on CheckCertificate(reg_hash) per D-26 certified-status requirement - No genius_node/TransactionManager dependency introduced (blockchain_genesis builds standalone, verified)
- CheckSignatureAgainst(address) verifies a signature against an arbitrary caller-supplied address (clear-signature/serialize/ VerifySignature sequence, formerly inline in CheckSignature) - CheckSignature() now delegates: CheckSignatureAgainst(dag_st.source_addr()) - Behavior-preserving refactor; CheckDAGSignatureLegacy untouched
…th fix (Gap 5) Pulls in the MNN_String resize fix: the job's schema-declared "maxLength" parameter now drives the per-tensor resize target instead of a hardcoded 128 literal, fixing StringConformanceProcessingTest's reshape error against the tiny embedding model while keeping the legacy StringInputProcessingTest (128-length BERT model) passing. runSession()'s return code is now checked and surfaces as a structured ProcessingResult.error instead of reading a garbage/unresized tensor.
…essage fix Picks up SGProcessingManager 30cf9f1 (embed human-readable PassType name in CanExecute rejection message, TEST-01 gap closure)
… its own binary dir - set_tests_properties(processing_dispatch_test PROPERTIES WORKING_DIRECTORY $<TARGET_FILE_DIR:processing_dispatch_test>) - Fixes ctest defaulting to source-tree-mirrored cwd (no processing_dispatch/ fixtures there), which caused spurious GLSL #version 140 errors on 4 render-pass sub-tests - Scoped to this single named target only; cmake/functions.cmake's shared addtest() helper untouched
…hen repeat-run hash assertion - render-pass-happy-path-definition.json: outputs[] was always empty since Phase 03, so ProcessingManager::Process()'s !outputs.empty()-gated artifact/manifest/combinedHash assembly never fired for this fixture even though the render pass genuinely succeeds. Add a single outputs[0] entry (renderOutput) mirroring the already-proven regression-b-parseblocksize-model-only.json pattern. - processing_dispatch_test.cpp: RenderPassSameNodeRepeatedExecutionProducesBitExactHash now asserts iterHash.size()==32 per iteration before pushing it, so a regression that empties combinedHash again can no longer pass vacuously on 10 equal-but-empty hash vectors. - RenderPassEndToEndProducesVerifiedOutputHash's existing size/non-zero-sentinel assertions are now genuinely exercised (was previously failing on an always-empty hash).
…gManager)
Plan 10-06 wires SGProcessingManager/test/ into the main build for the
first time. That surfaced a pre-existing ordering bug: enable_testing()
was only called inside the later if(BUILD_TESTING) block, after
ProofSystem/SGProcessingManager/evmrelay/src were already add_subdirectory()'d.
CTest's per-directory CTestTestfile.cmake chain can only be generated for
directories configured after testing is enabled, so ctest run from the
build root silently found zero tests under SGProcessingManager/test/ even
though its leaf CMakeLists.txt files call enable_testing()/add_test()
themselves -- the root's own CTestTestfile.cmake had a dangling
subdirs("SGProcessingManager") entry with no CTestTestfile.cmake on the
other end.
Moves enable_testing() to run unconditionally (under the existing
BUILD_TESTING guard) before the four add_subdirectory() calls; the
add_subdirectory(test) call keeps its own if(BUILD_TESTING) guard.
No other behavior change -- BUILD_TESTING is already resolved earlier in
this file, and calling enable_testing() twice is idempotent.
Verified: ctest -N now lists CapabilityValidatorTest and CaptureSmokeTest
(test count 84 -> 101); ctest -R CaptureSmokeTest and
-R CapabilityValidatorTest both pass.
Wires SGProcessingManager/test/ into the main build and adds capture_smoke_test (CTest smoke test for capture_harness).
…unit tests Picks up 76f6ae6: real QuantizeFloatBuffer/QuantizeByteBuffer implementations (D-03 through D-09) and the new QuantizationTest CTest target.
…Identity Adds OutputHashingTest.PostQuantizationHashAgreesWithArtifactIdentity: wires a caller-owned ExecutionContext's rawOutputCapture through the 5-arg Process() overload, independently re-hashes the last (stitched-combined) captured quantized-bytes invocation via sgprocmanagersha::sha256(), and memcmp's it against pr.value().artifacts[0].artifactId. Proves the processor's own post-quantization hash and ComputeArtifactIdentity's independent re-hash of the same bytes agree (QUANT-02, ROADMAP Phase 12 SC2). Does not touch ComputeManifestHash/ExecutionManifest/executorIdentity/ gpuMemoryUsedBytes (D-01/D-02 scope boundary) and never compares against combinedHash.
- secv01-wrong-color.frag: deliberately-wrong solid mid-gray fragment shader fixture (D-11), structurally identical to processing_conformance_regression/fixtures/passthrough.frag but outputting a materially different, still well-formed color - secv01-corrupted-float_model.mnn: byte-perturbed copy of float_model.mnn (D-10) -- single byte at offset 15360 XORed with 0xFF (Linear layer weight region); empirically confirmed loadable by MNN::Interpreter::createFromBuffer() and produces a materially different inference result than the original
New CTest target processing_conformance_security_test with two
TEST_F cases proving Plan 12-01's real quantization tolerance is not
loose enough to also mask a substituted result:
- MnnCorruptedModelStillDiverges: runs the same MNN float pipeline
shape as float-processing-definition.json against the correct
float_model.mnn and Task 1's byte-perturbed corrupted copy;
asserts their post-quantization artifactId differs (T-12-06).
- RenderWrongShaderConstantStillDiverges: runs the same render
pipeline against the correct passthrough.frag.spv and Task 1's
secv01-wrong-color.frag GLSL source (compiled+validated at
runtime); asserts their post-quantization artifactId differs
(T-12-07). Skips (does not fail) on hosts with no usable Vulkan
device (Phase 09 D-05 pattern).
Both assertions are a binary std::memcmp != 0 on
output.artifacts[0].artifactId only, never on combinedHash or any
ExecutionManifest field (D-13).
Deviation: the render job JSON needed an explicit
"pipeline_state": {"topology": "point_list", ...} to actually
rasterize fragments -- the default TRIANGLE_LIST topology with
float_input.bin's arbitrary vertex data produced no visible
fragments in either run, making the fragment-shader difference
untestable (both runs hashed the identical clear-color-only output).
This mirrors the topology pipeline_state already proven working by
processing_dispatch_test.cpp's render-pass-happy-path fixture.
Registers add_subdirectory(processing_conformance_security) in
test/src/CMakeLists.txt alongside the Phase 09 processing_conformance_*
suites.
…us into dev_childwallet
… grid Points at the S=2^15 gap-closure commit for VALD-01's MNN cross-hardware divergence, empirically bounded safe against SECV-01's corrupted-model regression via local binary search.
…nk numeric diff extension
…High for MNN float processor
…quantization resolvers Threads ResolveQuantScale/ResolveByteQuantMode + the new required scale/maskBits Quantize*Buffer parameters, plus their full quantization_test.cpp coverage.
Wires ResolveQuantScale/ResolveByteQuantMode into all 21 existing QuantizeFloatBuffer/QuantizeByteBuffer call sites across the 14 processor files.
…1 counter-test - Byte-perturbed copy of spleen_ct_seg.mnn (19339764 bytes, same size), single byte at offset 15000000 XORed with 0xFF (back-region weight-tensor area, past the flatbuffers schema/vtable region near the front) - Empirically confirmed via the real MNN::Interpreter load path (Task 2's counter-test): loads successfully and produces a materially different post-quantization artifactId than the original across the entire tested quantScale range (Phase 14 T-14-07/QUANT-CFG-03)
…uantScale - New secv01_tex3d_counter_test.cpp (Secv01Tex3dCounterTest. MnnCorruptedSpleenCtSegModelStillDiverges): mirrors secv01_counter_test.cpp's exact artifactId-memcmp methodology (never .combinedHash) applied to the tex3d/spleen_ct_seg pipeline shape, registered as a second source in the existing processing_conformance_security_test CTest target - Local binary search over power-of-two quantScale values (256, 128, 64, 2, 1) found no SECV-01 failure boundary in the valid domain for this corruption -- unlike Phase 13's small-model search, the offset-15000000 byte flip propagates into a divergence too large for any power-of-two grid in that range to mask - Final quantScale=128.0 (2^7) chosen instead by the other empirical constraint D-10 cites: the finest (largest) power-of-two grid step that still exceeds the real captured cross-hardware divergence delta (0.005126953125, ~1.53x margin at S=128 vs sub-unity margin at S=256), while empirically confirmed to still pass this counter-test - texture3d-processing-definition.json's parameters array gains the matching quantScale=128.0 entry with a citation trail to the measured delta and the binary-search range searched (QUANT-CFG-03)
…ing test coverage
…traction + tolerance derivation Picks up: diff_utils.hpp/.cpp extraction of capture_diff's numeric-diff primitives into a new shared sgprocmanagerdiff static library, plus new D-03/D-04 tolerance-derivation functions (ResolveChunkElementTypeHint/ IsFloatChunkWithinTolerance/IsByteChunkWithinTolerance); CMake wiring (sgprocmanagerdiff target, SGProcessors PUBLIC link, capture_diff link, diff_utils_test registration); capture_diff.cpp refactored to call the shared library with unchanged CLI behavior.
- Restructured chunks accumulator to chunksBySubtask (chunkKey -> subtaskId -> ChunkContribution) so each subtask's chunk-hash contribution stays independently addressable instead of being concatenated into one shared buffer - Added genuine cross-subtask comparison pass: identical hashes still pass (SC2), differing hashes now correctly fail (SC1, fixing the line-84 concatenation bug) - Added CHUNK_HASH_MISMATCH_UNTOLERATED error enumerator and a stubbed AttemptToleranceFallback (Task 2 implements the real fetch+slice+diff logic) - ValidateResults gained two defaulted trailing parameters (jobParameters, fetchOutputData) for the upcoming tolerance fallback, keeping all existing call sites source-compatible - New live processing_validation_core_test.cpp / ProcessingValidationCoreTest CTest target (3 cases)
…ve SC3/SC4 - AttemptToleranceFallback fetches each contributing subtask's output blob via the injected fetchOutputData capability (keyed by ipfs_results_data_id), slices out this chunk's byte range (single-chunk subtasks use the whole blob; multi-chunk uses uniform division when the blob size divides evenly; anything else fails closed per Pitfall 3), and diffs the slices via sgprocmanagerdiff::ResolveChunkElementTypeHint + IsFloatChunkWithinTolerance/IsByteChunkWithinTolerance - Fails closed (returns false) on: no fetchOutputData capability (D-02), empty ipfs_results_data_id, any fetch outcome::failure, or an unsliceable multi-chunk blob size -- no crash, no silently-wrong comparison - Added 2 new TEST cases: DifferingHashesWithinToleranceStillPass (SC3) and DifferingHashesExceedsToleranceFail (SC4), for 5 total in ProcessingValidationCoreTest
…ssingCoreImpl - ProcessingCore gains a new non-pure virtual GetTaskQueue() (default nullptr), mirroring GetProgress()'s safe-default pattern - ProcessingCoreImpl overrides it to expose its already-existing task_queue_ member - Forward-declares ProcessingTaskQueue in processing_core.hpp (only a shared_ptr is returned, no full include needed)
…o FinalizeQueueProcessing - SubTaskQueueAccessorImpl gains an optional 6th constructor parameter (std::shared_ptr<ProcessingCore>, defaulted to nullptr) and a matching m_processingCore member - FinalizeQueueProcessing resolves the job's schema-declared quantScale/byteQuantMode by looking up the originating Task via GetTaskQueue()->GetTask(subTask.ipfsblock()) (same mechanism ProcessingCoreImpl::ProcessSubTask already uses), parsing its json_data() -- any parse/lookup failure is caught and logged, falling back to jobParameters == nullptr (D-04's fixed-constant fallback), never crashing - fetchOutputData now performs real I/O via FileManager::LoadASync on a fresh, call-scoped io_context (never m_localContext, avoiding reset()/run() reentrancy with its already-running background thread), mirroring ProcessingManager::GetSubCidForProc's exact callback shape - ProcessingNode::Initialize() passes its existing m_processingCore member as the accessor's 6th constructor argument - processing_validation_core_test (Plan 15-02, 5 cases) still passes unchanged -- no regression
- New secv02_counter_test.cpp: two real ProcessingManager::Process() runs (correct vs. corrupted MNN model) produce genuine chunk hashes and file:// output locations, fed into ProcessTaskSplitter::SplitTask's real addvalidationsubtask=true production path (two subtasks sharing one ProcessingChunk), then through SubTaskQueueAccessorImpl's real public API (AssignSubTasks/GrabSubTask, never ValidateResults directly). Asserts the fixed ValidateResults plus its tolerance fallback (Plans 15-01/15-02/15-03) still flags the corrupted result as invalid. - New fixtures/secv02-corrupted-float_model.mnn: a dedicated byte-perturbed copy of float_model.mnn (100 exponent bytes XORed at the same weight region SECV-01's own fixture perturbs), created because SECV-01's existing corrupted fixture was empirically confirmed NOT to diverge at the single-window (width=64/block_len=64) granularity this test requires for exact tolerance-fallback blob-to-chunk slicing. - CMakeLists.txt: wires secv02_counter_test.cpp into the existing processing_conformance_security_test target, adds processing_service to its link libraries (transitively brings SubTaskQueueAccessorImpl/ ProcessingSubTaskQueueManager/SGProcessingProto), plus ipfs-bitswap-cpp/logger/Boost::headers/p2p::p2p_logger/ipfs-pubsub (needed once processing_subtask_queue_accessor_impl.hpp is included directly, mirroring processing_result_durability_test's existing link set).
# Conflicts: # src/account/GeniusNode.hpp # src/account/TransactionManager.hpp # test/testutil/storage/base_crdt_test.cpp
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.
No description provided.