Skip to content

Feature: QuarkChain Multi-Native Token (MNT) Support for goshard EVM#18

Open
ping-ke wants to merge 8 commits into
goshard/basefrom
feature/mnt-code
Open

Feature: QuarkChain Multi-Native Token (MNT) Support for goshard EVM#18
ping-ke wants to merge 8 commits into
goshard/basefrom
feature/mnt-code

Conversation

@ping-ke

@ping-ke ping-ke commented Jun 21, 2026

Copy link
Copy Markdown

QuarkChain Multi-Native Token (MNT) Support for goshard EVM

Summary

Port QuarkChain's multi-native token (MNT) account model and EVM extensions from goquarkchain into goshard, enabling state-root compatibility with the original pyquarkchain/goquarkchain chain. Add tooling to export and verify state trie correctness against a live pyquarkchain database.

Changes

common/

  • token_codec.go — 36-base token name ↔ uint64 ID codec (TokenIDEncode / TokenIDDecode), byte-compatible with goquarkchain

core/types/

  • token.goTokenBalances type: list-format RLP encoding (0x00 prefix, ≤16 tokens); trie format (>16 tokens) unsupported with clear error
  • state_account_qkc.goStateAccount.EncodeRLP / DecodeRLP overrides implementing QKC's 6-field wire format [nonce, tokenBal, root, codeHash, fullShardKey, optional], byte-compatible with pyquarkchain
  • DefaultTokenID = 35760 (TokenIDEncode("QKC"))

core/state/

  • state_object_qkc.goSetMntBalance, AddMntBalance, SubMntBalance, GetMntBalance on stateObject
  • statedb_qkc.go — same set on StateDB; SubBalanceByTokenID / GetBalanceByTokenID dispatch by token ID
  • journal.gomntBalanceChange journal entry + revert
  • mnt_test.go — unit tests for MNT balance state transitions

core/vm/

  • contracts_qkc.go — 5 MNT precompiles at QKC system addresses:
    • 0x…514b430001 currentMntID — returns active MNT token ID
    • 0x…514b430002 transferMnt — transfer MNT between accounts
    • 0x…514b430003 deploySystemContract — deploy NonReserved / General native token contracts
    • 0x…514b430004 mintMNT — mint new MNT tokens (only callable by authorised system contract)
    • 0x…514b430005 balanceMNT — query MNT balance

core/evm.go / core/state_transition.go

  • Wire MNT token ID through BlockContext and Message so precompiles and gas payment operate on the correct token

tools/

  • tools/verify_trie_root/main.go — loads trie_dump.json exported from a pyquarkchain DB, feeds all trie nodes into goshard's trie package, and asserts the recomputed root matches — verified ✓ on mainnet shard-1
  • tools/generatedata/dump_qkc_state_trie.py — exports the full state trie from a pyquarkchain RocksDB to JSON; handles latest-block lookup, backwards scan to find a persisted snapshot (~128-block checkpoint interval), outputs a node_store map consumable by verify_trie_root

Verification

Dump pyquarkchain trie data

python -m dump_qkc_state_trie --db-path ~/data/pyqkc/mainnet/shard-1.db --output  trie_dump.json  --limit 0
Opening DB: /root/data/pyqkc/mainnet/shard-1.db
Looking up block at height: latest
Block height:  23000709
Block hash:    b056ccff06dd44cc45a448f72fa082aeaa6c7dc7d4374dc3ca8bd48d5febb587
State root:    328e64f51560af15fe25fa4a87249fea219094769adab3fe553c0777873f05a4
Traversing trie (limit_accounts=0)...
  Nodes found:    34578
  Accounts found: 26018
  Node types:     {'branch': 8345, 'leaf': 26018, 'extension': 215}
Writing trie_dump.json...
Done. Output: trie_dump.json (47.8 MB)

Verify goshard mnt by trie root

go run ./tools/verify_state --input ./tools/dump_state/trie_dump.json
Loading ./tools/dump_state/trie_dump.json ...
State root from dump: 328e64f51560af15fe25fa4a87249fea219094769adab3fe553c0777873f05a4
Node store entries:   34578
Accounts in dump:     26018

Recomputing trie root via goshard trie package...
Expected root: 328e64f51560af15fe25fa4a87249fea219094769adab3fe553c0777873f05a4
Computed root: 0x328e64f51560af15fe25fa4a87249fea219094769adab3fe553c0777873f05a4

Out of scope / follow-up

  • EVM replay test (pre-state + transactions → assert post-state root); blocked on QKCChainConfig (Constantinople-level gas rules matching goquarkchain's go-ethereum v1.8.20)
  • Cross-shard transaction handling
  • TokenBalances trie format (accounts with >16 MNT tokens)

ping-ke and others added 3 commits June 20, 2026 21:28
… EVM

- Add TokenBalances type with RLP encoding for QKC multi-token account model
- Add QuarkChain StateAccount extension (6-field RLP with full_shard_key)
- Add token_id codec (36-base encoding) matching goquarkchain
- Add QKC precompile contracts: transferMnt, deployNativeToken
- Wire MNT balance reads/writes into EVM state transition and journal
- Add tools/verify_trie_root to cross-check trie root against goquarkchain
- Add tools/generatedata scripts for test data generation from RocksDB

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…ansition MNT wiring

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Remove the duplicate const in core/vm/evm.go and use the canonical
types.DefaultTokenID everywhere; add types import to contracts_qkc.go.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
ping-ke and others added 4 commits June 22, 2026 18:16
…ned dump script

- Rename tools/generatedata → tools/dump_state
- Rename tools/verify_trie_root → tools/verify_state
- Delete test_mainnet_compat.sh (replaced by tools/README.md)
- Add tools/README.md documenting the two-step workflow
- dump_qkc_state_trie.py: parse MinorBlock bytes directly via
  _parse_minor_block() — no pyquarkchain import needed
- Use binary search over mi_N keys to find chain tip (O(log N),
  no hardcoded height ceiling)
- .gitignore: exclude trie_dump.json and *.exe from tools/verify_state
- dump_qkc_state_trie.py: add _parse_minor_block() to extract
  hash_evm_state_root directly from raw bytes — no pyquarkchain import
- Replace hardcoded height scan with binary search over mi_N keys
  (O(log N), no ceiling assumption)
- Update tools/README.md: no pyquarkchain install needed
- Update tools/verify_state/main.go package comment path
- .gitignore: exclude trie_dump.json and *.exe under tools/verify_state
…ck FullShardKey

refactor TokenBal encoding to avoid rawTokenBal cache:
  - Remove rawTokenBal field and InvalidateRawTokenBal() from StateAccount
  - DecodeRLP: always set MntBalances when TokenBal has content (even if
    empty after stripping QKC), preserving nil vs empty list distinction
  - EncodeRLP: three-way switch — MntBalances==nil → 0x80, MntBalances
    empty list → 0x8200c0, normal → mergeSerializeToBytes
  - Remove InvalidateRawTokenBal calls from state_object.go and
    state_object_qkc.go
  - Remove unused GetFakeChainId() from params/config.go

This preserves byte-identical round-trip for the 9194 accounts with
0x8200c0 TokenBal (EOA that touched TokenBalances then emptied it)
without caching raw wire bytes. 26018 accounts all verified round-trip.

track FullShardKey end-to-end:
  - Add FullShardKey field to StateAccount (with Copy/Encode/Decode)
  - Add fullShardKey field and SetFullShardKey() to StateDB
  - Preserve existing account FullShardKey in createObject
  - Set fullShardKey in StateDB.Copy()

tests:
  - StateAccountEncodeDecodeRoundtrip: FullShardKey assertions
  - Pyquarkchain compatibility: FullShardKey in decode/encode checks
  - Slim round-trip: add FullShardKey=0 note
  - verify_state: read fullShardKey, TokenBalances strip & re-encode
  - Separate 0x80 / 0x8200c0 cases into separate JSON files

Co-Authored-By: Claude <noreply@anthropic.com>
Optial was a typo carried over from goquarkchain. The field name is now
Optional to match its intended meaning.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <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.

1 participant