slave (M1): add slave node with config and genesis#21
Conversation
Boot a slave from a pyquarkchain-compatible cluster_config.json. The slave hosts the shards assigned to one slave identity and performs no network I/O yet (tracking issue #17). - cmd/slave: `config` (validate + print a normalized per-slave summary) and `genesis` (derive the root genesis block, hash byte-identical to pyquarkchain's GenesisManager.create_root_block()) - qkc/config: cluster config loader (load.go) and checked-in singularity mainnet/devnet configs - qkc/genesis: root-block derivation - qkc/types: root block, token balances, helpers - Makefile: `make slave` target Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Looks like both this PR and #20 are adding duplicate content to |
All types required to achieve the current milestone. We can use a refactor later before merging into the base. |
| app.Flags = slices.Concat( | ||
| []cli.Flag{}, | ||
| debug.Flags, | ||
| ) |
There was a problem hiding this comment.
The expression slices.Concat([]cli.Flag{}, debug.Flags) is unnecessarily complex. Concatenating with an empty slice produces the same result as debug.Flags alone. Simplifying to debug.Flags removes one import ("slices") and makes the intent clearer.
| len(shard.Genesis.Alloc), | ||
| ) | ||
| } | ||
| tw.Flush() |
There was a problem hiding this comment.
The error returned by tw.Flush() is silently ignored.
There was a problem hiding this comment.
Ignoring Flush() errors is consistent with surrounding Fprintf calls, both of which write targeting os.Stdout. This is common in geth, so it's acceptable and not a defect.
| if v.Sign() == 0 { | ||
| continue | ||
| } | ||
| t.balances[k.Uint64()] = v |
There was a problem hiding this comment.
Validate bigint(k) range before converting to uint64 to prevent truncation collisions.
| num, err := bb.GetUInt32() | ||
| if err != nil { | ||
| return err | ||
| } |
There was a problem hiding this comment.
Should we add an entry count validation here to prevent potential OOM/DoS attacks from malicious data?
There was a problem hiding this comment.
Not really. Firstly, make does not pre-allocate according to num; secondly, every time an entry is read, it goes through the getBytes boundary check; plus, forcing an upper limit that pyquarkchain does not have will only create consensus disagreements.
| // pyquarkchain's TokenBalanceMap. | ||
| type TokenBalances struct { | ||
| balances map[uint64]*big.Int | ||
| } |
There was a problem hiding this comment.
MNT will use this stuct and create it under core/types/.
There was a problem hiding this comment.
TokenBalances is QKC-specific so it is better stay at qkc/types.
| // so it can be embedded in RootBlockHeader and hashed byte-identically to | ||
| // pyquarkchain's TokenBalanceMap. | ||
| type TokenBalances struct { | ||
| balances map[uint64]*big.Int |
There was a problem hiding this comment.
Should we use *uint256.Int instead of *big.Int
There was a problem hiding this comment.
I would prefer big.Int because
- pyquarkchain's wire format is a variable-length biguint.
- In geth it is only converted to uint256.Int when executed within the EVM.
- qkc/serialize currently natively recognizes big.Int, but not uint256.Int.
pyquarkchain always derives ETH_CHAIN_ID as BASE_ETH_CHAIN_ID + CHAIN_ID + 1 and overwrites any configured value with that derivation on load (config.py:534); accept a configured value only when consistent with it.
pyquarkchain's arithmetic is unbounded, so BASE_ETH_CHAIN_ID + CHAIN_ID + 1 may exceed uint32; the uint32 sum wrapped silently (worst case to 0, which reads as "absent" and passes any configured value).
Adopt the final CLI shape in the milestone that creates these files: newApp assembles the app for tests, the cluster_config/node_id flags register globally without Required (actions validate presence via loadClusterConfig), and only non-networked debug flags are exposed, pinned by TestNoNetworkedDebugFlags. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…stone Drop the milestone markers and the not-yet-implemented tracker, adopt the final fixtures/pyquarkchain cross-validation section (including the virtualenv note in the singularity regeneration command), so later milestones only add sections. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The pyquarkchain derivation snippet already lives (with seal/serialize output) in qkc/config/singularity/README.md; link to that section instead of carrying a trimmed copy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Boot a slave from a pyquarkchain-compatible cluster_config.json. The slave hosts the shards assigned to one slave identity (tracking issue #17).
config(validate + print a normalized per-slave summary) andgenesis(derive the root genesis block, hash byte-identical to pyquarkchain's GenesisManager.create_root_block())ETH_CHAIN_IDconsistency check) and checked-in singularity mainnet/devnet configsmake slavetargetTests passed: