qkc/types: port QuarkChain slavechain block, header & transaction types (byte-compatible)#20
qkc/types: port QuarkChain slavechain block, header & transaction types (byte-compatible)#20blockchaindevsh wants to merge 4 commits into
Conversation
Byte-compatible port of goquarkchain/core/types: MinorBlock/Header/Meta, Transaction+EvmTransaction, Receipt, Log, Bloom, TokenBalances, CalculateMerkleRoot and DeriveSha, plus passive RootBlock/RootBlockHeader. Header hash is keccak256(serialize(header)); adaptations are compile-level only. Byte-parity locked by goquarkchain's golden vectors. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
| hashList = append(hashList, common.Hash{}) | ||
| } else { | ||
| for i := 0; i < val.Len(); i++ { | ||
| bytes, _ := serialize.SerializeToBytes(val.Index(i).Interface()) |
There was a problem hiding this comment.
If serialize.SerializeToBytes fails, swallowing the error here means sha3_256(nil) will silently produce a wrong hash, corrupting the Merkle root in consensus-critical paths (NewMinorBlock, Finalize).
We should panic immediately on error here (similar to Receipts.Bytes)?
| var EmptyHash = common.Hash{} | ||
|
|
||
| func CalculateMerkleRoot(list interface{}) (h common.Hash) { | ||
| val := reflect.ValueOf(list) |
There was a problem hiding this comment.
reflect.ValueOf(nil).Type() will trigger an opaque runtime panic if a nil list is passed. Adding an explicit check improves API defensiveness and provides a much clearer error message.
|
|
||
| // Bytes implements DerivableList and returns the i'th element of s in serialize. | ||
| func (s MinorBlockHeaders) Bytes(i int) []byte { | ||
| enc, _ := serialize.SerializeToBytes(s[i]) |
There was a problem hiding this comment.
If a failure occurs, it returns nil bytes, resulting in a root hash error. Please follow the same panic(err) pattern as Receipts.Bytes?
| func (s Transactions) Len() int { return len(s) } | ||
|
|
||
| func (s Transactions) Bytes(i int) []byte { | ||
| enc, _ := serialize.SerializeToBytes(s[i]) //todo error handle? |
There was a problem hiding this comment.
If a failure occurs, it returns nil bytes, resulting in a root hash error. Please follow the same panic(err) pattern as Receipts.Bytes? TODO?
| } | ||
|
|
||
| func (s EIP155Signer) Sender(tx *EvmTransaction) (account.Recipient, error) { | ||
| if tx.Version() != 2 && tx.NetworkId() != s.networkId { |
There was a problem hiding this comment.
Missing network ID check for versions 0 and 1.
There was a problem hiding this comment.
Sorry, I meant to say that the network ID check should apply to all versions, not just tx.Version() != 2.
There was a problem hiding this comment.
v2's network_id is the Ethereum chain id (BASE_ETH_CHAIN_ID + chain_id + 1, e.g. 100001), not NETWORK_ID — so applying this check to v2 would reject every EIP155 tx. The real check is version-aware and belongs at admission (validateTx: v2 → EthChainID, else → NETWORK_ID, matching pyquarkchain shard_state.py), landing with the deferred execution port. v2 is also bound to its chain id via the EIP155 V here. So the != 2 guard is intentional.
There was a problem hiding this comment.
Is root block outside the scope of the shard chain?
The error from serialize.SerializeToBytes was swallowed, so a failure would silently hash nil (sha3_256(nil)) and corrupt the Merkle root in consensus-critical paths (NewMinorBlock, Finalize). Panic on error instead, mirroring Receipts.Bytes. Addresses review feedback from @iteyelmp. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…kleRoot
reflect.Value.Type() panics opaquely ("reflect: call of reflect.Value.Type
on zero Value") when CalculateMerkleRoot is passed a nil list. Value.Kind()
has no zero-Value guard and returns Invalid instead, so the existing clear
"expect slice input" error fires. Kind() == Type().Kind() for every valid
input, so this is behavior-preserving except on the nil case it fixes.
Addresses iteyelmp's review comment.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MinorBlockHeaders.Bytes and Transactions.Bytes (DerivableList.Bytes implementations) plus MinorBlock.Size/RootBlock.Size swallowed the SerializeToBytes error and returned nil/zero. A failure would then silently corrupt the DeriveSha root hash (Bytes) or the cached storage size (Size) instead of failing loudly. Follow the existing Receipts.Bytes pattern and panic(err). Addresses iteyelmp's review comment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Third of the 8 stacked PRs porting QuarkChain's shardchain
(slavechain) into
goshard. Builds on #12 (
qkc/serialize) and #16(
qkc/{common,account,params,config});the remaining layers (
qkc/core/rawdb,qkc/consensus,qkc/core,qkc/miner,cmd/qkcshard) stack on top of this one.This layer adds the
qkc/typespackage — the QuarkChainMinorBlocktype set andall its dependencies — byte-for-byte compatible with
QuarkChain (block/header/meta
hashes must match exactly).
What's included
minorblock.go—MinorBlock,MinorBlockHeader,MinorBlockMeta(+Hash/SealHash,Copy*, accessors, gencodec JSON).transaction.go/transaction_signing.go/solidity_abi_utils.go—EvmTransaction(+ shard keys & token ids), the
Transactionwrapper (type byteTransactions, and theEIP155Signer(v0/v1/v2 senderrecovery, incl. EIP-712 typed-data for v1).
receipt.go/log.go/bloom9.go— QuarkChain's ownReceipt/Receipts,Log/LogForStorage,and
Bloom/CreateBloom(deliberately not geth's — requiredfor byte-compat).
token.go—TokenBalances(multi-native-token balances;sorted-pair + >16-token trie forms).
derive_sha.go/utils.go—DeriveSha(receipt-root viatrie.StackTrie) andCalculateMerkleRoot(QuarkChain's custom keccak Merkle forMinorBlockMeta.TxHash— a tree, not a trie).special_rlp.go— theUint32special RLP (e.g.FullShardKey), plusXShardTxCursorInfo,CrossShardTransactionDeposit.rootblock.go—RootBlock/RootBlockHeaderported aspassive dependencies only, so shard
code that references root types compiles. No root-chain logic.
Byte-compatibility
Header/block hashing is
keccak256(serialize(...))(QuarkChain'sreflection serializer from #12, not
RLP);
SealHashexcludesnonce+mixhash;MinorBlockMeta.ReceiptHashis a trie root whileTxHashis thecustom binary Merkle root. Verified against goquarkchain golden
vectors (header hash, token-trie root,
CalculateMerkleRoot) and round-trip (Serialize→Deserialize)for header/meta/block/tx/receipt.
pyquarkchain alignment
Per the project rule (pyquarkchain is authoritative on behavior
where goquarkchain diverges), this PR
includes two behavioral fixes vs the verbatim goquarkchain port:
TokenBalances.Serializenow omits zero-balance entries(matches pyquarkchain's
TokenBalanceMapskip-func; also fixes a
Serialize/Deserializeasymmetry).CrossShardTransactionDepositV0field order corrected sois_from_root_chainserializes last(matches pyquarkchain
core.py; goquarkchain placed it aftertransfer_token_id).Both carry code comments citing the pyquarkchain source.
Out of scope (deferred)
Transaction execution / state transition is a separate issue —
these types are ported for byte-compat
and chain plumbing, not driven here. Root-chain implementation
is also out of scope (root types are
passive deps only).
Testing
go build ./...andgo test ./qkc/types/...green; byte-compatgolden vectors, round-trips, and v0/v1/v2
tx-signing tests included.