Skip to content

slave (M1): add slave node with config and genesis#21

Open
syntrust wants to merge 9 commits into
goshard/basefrom
slave-m1
Open

slave (M1): add slave node with config and genesis#21
syntrust wants to merge 9 commits into
goshard/basefrom
slave-m1

Conversation

@syntrust

@syntrust syntrust commented Jun 23, 2026

Copy link
Copy Markdown

Boot a slave from a pyquarkchain-compatible cluster_config.json. The slave hosts the shards assigned to one slave identity (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, incl. ETH_CHAIN_ID consistency check) and checked-in singularity mainnet/devnet configs
  • qkc/genesis: root-block derivation
  • qkc/types: root block, token balances, helpers
  • Makefile: make slave target

Tests passed:

go test ./cmd/slave/...
go test ./qkc/...

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>
@syntrust
syntrust marked this pull request as ready for review June 24, 2026 02:33
@syntrust syntrust changed the title slave: add slave node (M1) with config and genesis slave (M1): add slave node with config and genesis Jun 24, 2026
@blockchaindevsh

Copy link
Copy Markdown

Looks like both this PR and #20 are adding duplicate content to qkc/types/?

@syntrust

Copy link
Copy Markdown
Author

Looks like both this PR and #20 are adding duplicate content to qkc/types/?

All types required to achieve the current milestone. We can use a refactor later before merging into the base.

Comment thread cmd/slave/main.go Outdated
app.Flags = slices.Concat(
[]cli.Flag{},
debug.Flags,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in f92ba2f

Comment thread cmd/slave/configcmd.go
len(shard.Genesis.Alloc),
)
}
tw.Flush()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error returned by tw.Flush() is silently ignored.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validate bigint(k) range before converting to uint64 to prevent truncation collisions.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 53d3f97

num, err := bb.GetUInt32()
if err != nil {
return err
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add an entry count validation here to prevent potential OOM/DoS attacks from malicious data?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@syntrust
syntrust requested a review from iteyelmp July 3, 2026 03:14
// pyquarkchain's TokenBalanceMap.
type TokenBalances struct {
balances map[uint64]*big.Int
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MNT will use this stuct and create it under core/types/.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use *uint256.Int instead of *big.Int

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

syntrust and others added 5 commits July 14, 2026 16:25
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants