This commit is contained in:
iteye 2026-07-06 18:44:27 +08:00
parent 9db15e21f4
commit 9292105a4a
4 changed files with 43 additions and 37 deletions

View file

@ -239,7 +239,6 @@ type DestroyClusterPeerConnectionCommand struct {
// FIELDS = [("root_block", RootBlock), ("expect_switch", boolean)] // FIELDS = [("root_block", RootBlock), ("expect_switch", boolean)]
type AddRootBlockRequest struct { type AddRootBlockRequest struct {
// TODO: Replace with *RootBlock once core.RootBlock is ported. // TODO: Replace with *RootBlock once core.RootBlock is ported.
// WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes.
RootBlock *RawBytes RootBlock *RawBytes
ExpectSwitch bool ExpectSwitch bool
} }
@ -346,7 +345,6 @@ type AccountBranchData struct {
Branch uint32 Branch uint32
TransactionCount *big.Int // uint256 TransactionCount *big.Int // uint256
// TODO: Replace with *TokenBalanceMap once core.TokenBalanceMap is ported. // TODO: Replace with *TokenBalanceMap once core.TokenBalanceMap is ported.
// WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes.
TokenBalances *RawBytes TokenBalances *RawBytes
IsContract bool IsContract bool
PoswMineableBlocks uint16 PoswMineableBlocks uint16
@ -415,12 +413,10 @@ type ShardStats struct {
// ] // ]
type AddMinorBlockHeaderRequest struct { type AddMinorBlockHeaderRequest struct {
// TODO: Replace with *MinorBlockHeader once core.MinorBlockHeader is ported. // TODO: Replace with *MinorBlockHeader once core.MinorBlockHeader is ported.
// WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes.
MinorBlockHeader *RawBytes MinorBlockHeader *RawBytes
TxCount uint32 TxCount uint32
XShardTxCount uint32 XShardTxCount uint32
// TODO: Replace with *TokenBalanceMap once core.TokenBalanceMap is ported. // TODO: Replace with *TokenBalanceMap once core.TokenBalanceMap is ported.
// WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes.
CoinbaseAmountMap *RawBytes CoinbaseAmountMap *RawBytes
ShardStats ShardStats ShardStats ShardStats
} }
@ -461,7 +457,6 @@ type SyncMinorBlockListRequest struct {
type SyncMinorBlockListResponse struct { type SyncMinorBlockListResponse struct {
ErrorCode uint32 ErrorCode uint32
// TODO: Replace with real block_coinbase_map once core.TokenBalanceMap is ported. // TODO: Replace with real block_coinbase_map once core.TokenBalanceMap is ported.
// WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes.
BlockCoinbaseMap *RawBytes BlockCoinbaseMap *RawBytes
ShardStats *ShardStats `ser:"nil"` ShardStats *ShardStats `ser:"nil"`
} }
@ -489,7 +484,6 @@ type GetMinorBlockRequest struct {
type GetMinorBlockResponse struct { type GetMinorBlockResponse struct {
ErrorCode uint32 ErrorCode uint32
// TODO: Replace with *MinorBlock once core.MinorBlock is ported. // TODO: Replace with *MinorBlock once core.MinorBlock is ported.
// WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes.
MinorBlock *RawBytes MinorBlock *RawBytes
ExtraInfo *MinorBlockExtraInfo `ser:"nil"` ExtraInfo *MinorBlockExtraInfo `ser:"nil"`
} }
@ -504,7 +498,6 @@ type GetTransactionRequest struct {
type GetTransactionResponse struct { type GetTransactionResponse struct {
ErrorCode uint32 ErrorCode uint32
// TODO: Replace with *MinorBlock once core.MinorBlock is ported. // TODO: Replace with *MinorBlock once core.MinorBlock is ported.
// WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes.
MinorBlock *RawBytes MinorBlock *RawBytes
Index uint32 Index uint32
} }
@ -512,7 +505,6 @@ type GetTransactionResponse struct {
// ExecuteTransactionRequest (ClusterOp.EXECUTE_TRANSACTION_REQUEST, 0xA3). // ExecuteTransactionRequest (ClusterOp.EXECUTE_TRANSACTION_REQUEST, 0xA3).
type ExecuteTransactionRequest struct { type ExecuteTransactionRequest struct {
// TODO: Replace with *TypedTransaction once core.TypedTransaction is ported. // TODO: Replace with *TypedTransaction once core.TypedTransaction is ported.
// WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes.
Tx *RawBytes Tx *RawBytes
FromAddress [AddressLength]byte FromAddress [AddressLength]byte
BlockHeight *uint64 `ser:"nil"` BlockHeight *uint64 `ser:"nil"`
@ -534,7 +526,6 @@ type GetTransactionReceiptRequest struct {
type GetTransactionReceiptResponse struct { type GetTransactionReceiptResponse struct {
ErrorCode uint32 ErrorCode uint32
// TODO: Replace with *MinorBlock once core.MinorBlock is ported. // TODO: Replace with *MinorBlock once core.MinorBlock is ported.
// WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes.
MinorBlock *RawBytes MinorBlock *RawBytes
Index uint32 Index uint32
// TODO: Replace with *TransactionReceipt once core.TransactionReceipt is ported. // TODO: Replace with *TransactionReceipt once core.TransactionReceipt is ported.
@ -612,7 +603,6 @@ type GetLogResponse struct {
// EstimateGasRequest (ClusterOp.ESTIMATE_GAS_REQUEST, 0xAF). // EstimateGasRequest (ClusterOp.ESTIMATE_GAS_REQUEST, 0xAF).
type EstimateGasRequest struct { type EstimateGasRequest struct {
// TODO: Replace with *TypedTransaction once core.TypedTransaction is ported. // TODO: Replace with *TypedTransaction once core.TypedTransaction is ported.
// WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes.
Tx *RawBytes Tx *RawBytes
FromAddress [AddressLength]byte FromAddress [AddressLength]byte
} }
@ -773,7 +763,6 @@ type HelloCommand struct {
PeerPort uint16 PeerPort uint16
ChainMaskList []uint32 `bytesizeofslicelen:"4"` ChainMaskList []uint32 `bytesizeofslicelen:"4"`
// TODO: Replace with *RootBlockHeader once core.RootBlockHeader is ported. // TODO: Replace with *RootBlockHeader once core.RootBlockHeader is ported.
// WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes.
RootBlockHeader *RawBytes RootBlockHeader *RawBytes
GenesisRootBlockHash [HashLength]byte GenesisRootBlockHash [HashLength]byte
} }
@ -781,7 +770,6 @@ type HelloCommand struct {
// NewMinorBlockHeaderListCommand (CommandOp.NEW_MINOR_BLOCK_HEADER_LIST, 0x01). // NewMinorBlockHeaderListCommand (CommandOp.NEW_MINOR_BLOCK_HEADER_LIST, 0x01).
type NewMinorBlockHeaderListCommand struct { type NewMinorBlockHeaderListCommand struct {
// TODO: Replace with *RootBlockHeader once core.RootBlockHeader is ported. // TODO: Replace with *RootBlockHeader once core.RootBlockHeader is ported.
// WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes.
RootBlockHeader *RawBytes RootBlockHeader *RawBytes
MinorBlockHeaderList []*RawBytes `bytesizeofslicelen:"4"` // TODO: Replace with []*MinorBlockHeader once core.MinorBlockHeader is ported MinorBlockHeaderList []*RawBytes `bytesizeofslicelen:"4"` // TODO: Replace with []*MinorBlockHeader once core.MinorBlockHeader is ported
} }
@ -836,7 +824,6 @@ type GetRootBlockHeaderListRequest struct {
// GetRootBlockHeaderListResponse (CommandOp.GET_ROOT_BLOCK_HEADER_LIST_RESPONSE, 0x06). // GetRootBlockHeaderListResponse (CommandOp.GET_ROOT_BLOCK_HEADER_LIST_RESPONSE, 0x06).
type GetRootBlockHeaderListResponse struct { type GetRootBlockHeaderListResponse struct {
// TODO: Replace with *RootBlockHeader once core.RootBlockHeader is ported. // TODO: Replace with *RootBlockHeader once core.RootBlockHeader is ported.
// WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes.
RootTip *RawBytes RootTip *RawBytes
BlockHeaderList []*RawBytes `bytesizeofslicelen:"4"` // TODO: Replace with []*RootBlockHeader once core.RootBlockHeader is ported BlockHeaderList []*RawBytes `bytesizeofslicelen:"4"` // TODO: Replace with []*RootBlockHeader once core.RootBlockHeader is ported
} }
@ -881,10 +868,8 @@ type GetMinorBlockHeaderListRequest struct {
// GetMinorBlockHeaderListResponse (CommandOp.GET_MINOR_BLOCK_HEADER_LIST_RESPONSE, 0x0C). // GetMinorBlockHeaderListResponse (CommandOp.GET_MINOR_BLOCK_HEADER_LIST_RESPONSE, 0x0C).
type GetMinorBlockHeaderListResponse struct { type GetMinorBlockHeaderListResponse struct {
// TODO: Replace with *RootBlockHeader once core.RootBlockHeader is ported. // TODO: Replace with *RootBlockHeader once core.RootBlockHeader is ported.
// WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes.
RootTip *RawBytes RootTip *RawBytes
// TODO: Replace with *MinorBlockHeader once core.MinorBlockHeader is ported. // TODO: Replace with *MinorBlockHeader once core.MinorBlockHeader is ported.
// WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes.
ShardTip *RawBytes ShardTip *RawBytes
BlockHeaderList []*RawBytes `bytesizeofslicelen:"4"` // TODO: Replace with []*MinorBlockHeader once core.MinorBlockHeader is ported BlockHeaderList []*RawBytes `bytesizeofslicelen:"4"` // TODO: Replace with []*MinorBlockHeader once core.MinorBlockHeader is ported
} }

View file

@ -357,8 +357,17 @@ func TestNonOptionalRawBytes_NoMarker(t *testing.T) {
if err := serialize.Serialize(&buf, &req); err != nil { if err := serialize.Serialize(&buf, &req); err != nil {
t.Fatalf("Serialize: %v", err) t.Fatalf("Serialize: %v", err)
} }
if buf[0] != 0xAA { // RawBytes now uses 4-byte length prefix, so first bytes should be 00000001 (length=1)
t.Errorf("non-optional RawBytes should not have presence marker, got %x", buf[0]) // followed by AA (actual data), then 01 (ExpectSwitch=true)
want := []byte{0x00, 0x00, 0x00, 0x01, 0xAA, 0x01}
if len(buf) < len(want) {
t.Fatalf("buffer too short: got %d bytes, want at least %d", len(buf), len(want))
}
for i, b := range want {
if buf[i] != b {
t.Errorf("byte %d: got %x, want %x\nfull buf: %x", i, buf[i], b, buf)
break
}
} }
} }

View file

@ -39,14 +39,16 @@
// RawBytes Semantics // RawBytes Semantics
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// //
// RawBytes is a terminal wire sink type. // RawBytes is a bounded-length passthrough placeholder.
// //
// It represents an opaque byte segment whose internal structure is defined // It represents an opaque byte segment whose internal structure is defined
// by the Python FIELDS schema but is not yet implemented in Go. // by the Python FIELDS schema but is not yet implemented in Go.
// //
// Wire behavior: // Wire behavior:
// - Serialize: writes raw bytes unchanged // - Serialize: writes 4-byte length prefix + raw bytes (matches Python PrependedSizeBytesSerializer(4))
// - Deserialize: consumes ALL remaining bytes in buffer // - Deserialize: reads 4-byte length prefix + corresponding bytes
//
// This design allows RawBytes to be used in ANY struct position (not just last field).
// //
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// SAFETY CONSTRAINTS // SAFETY CONSTRAINTS
@ -54,10 +56,9 @@
// //
// RawBytes MUST obey the following rules: // RawBytes MUST obey the following rules:
// //
// 1. MUST only appear as the LAST field in a struct // 1. MUST NOT be partially decoded or inspected
// 2. MUST NOT be partially decoded or inspected // 2. MUST NOT be used in stable protocol definitions
// 3. MUST NOT be used in stable protocol definitions // 3. MUST be removed once real Go types are introduced
// 4. MUST be removed once real Go types are introduced
// //
// Any violation of these rules results in undefined wire behavior. // Any violation of these rules results in undefined wire behavior.
// //
@ -81,6 +82,7 @@
package wire package wire
import ( import (
"encoding/binary"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/qkc/serialize" "github.com/ethereum/go-ethereum/qkc/serialize"
@ -95,28 +97,36 @@ func (r RawBytes) Serialize(w *[]byte) error {
return fmt.Errorf("RawBytes.Serialize: size %d exceeds max %d", len(r), maxRawBytesSize) return fmt.Errorf("RawBytes.Serialize: size %d exceeds max %d", len(r), maxRawBytesSize)
} }
// Write 4-byte length prefix (matches Python PrependedSizeBytesSerializer(4))
lenBuf := make([]byte, 4)
binary.BigEndian.PutUint32(lenBuf, uint32(len(r)))
*w = append(*w, lenBuf...)
*w = append(*w, r...) *w = append(*w, r...)
return nil return nil
} }
// Deserialize consumes all remaining bytes from the buffer. // Deserialize reads 4-byte length prefix and corresponding bytes.
//
// SAFETY: This is only safe when RawBytes is the LAST field in its parent
// struct. If RawBytes appears before other fields, consuming the remaining
// bytes will corrupt subsequent fields. Structs with non-last RawBytes fields
// are marked with a WARNING in messages.go and cannot be correctly deserialized
// until the real Go type is ported.
// //
// TEMPORARY: Delete this placeholder once real types (RootBlock, MinorBlockHeader) are ported. // TEMPORARY: Delete this placeholder once real types (RootBlock, MinorBlockHeader) are ported.
func (r *RawBytes) Deserialize(bb *serialize.ByteBuffer) error { func (r *RawBytes) Deserialize(bb *serialize.ByteBuffer) error {
const maxRawBytesSize = 100 * 1024 * 1024 // 100 MB, matches Serialize const maxRawBytesSize = 100 * 1024 * 1024 // 100 MB, matches Serialize
if bb.Remaining() > maxRawBytesSize {
return fmt.Errorf("RawBytes.Deserialize: size %d exceeds max %d", bb.Remaining(), maxRawBytesSize) // Read 4-byte length prefix
} length, err := bb.GetUInt32()
bytes, err := bb.ReadRemaining()
if err != nil { if err != nil {
return err return err
} }
if length > maxRawBytesSize {
return fmt.Errorf("RawBytes.Deserialize: length %d exceeds max %d", length, maxRawBytesSize)
}
// Read the actual bytes
bytes, err := bb.ReadBytes(int(length))
if err != nil {
return err
}
*r = RawBytes(bytes) *r = RawBytes(bytes)
return nil return nil
} }

View file

@ -74,13 +74,15 @@ func (p *PrependedSizeHashList4) Deserialize(bb *serialize.ByteBuffer) error {
return fmt.Errorf("PrependedSizeHashList4.Deserialize: length %d exceeds capacity", length) return fmt.Errorf("PrependedSizeHashList4.Deserialize: length %d exceeds capacity", length)
} }
list := make([][HashLength]byte, length) list := make([][HashLength]byte, int(length))
for i := 0; i < int(length); i++ { for i := 0; i < int(length); i++ {
hashBytes, err := bb.ReadBytes(HashLength) hashBytes, err := bb.ReadBytes(HashLength)
if err != nil { if err != nil {
return err return err
} }
list[i] = [HashLength]byte(hashBytes) var hash [HashLength]byte
copy(hash[:], hashBytes)
list[i] = hash
} }
*p = PrependedSizeHashList4(list) *p = PrependedSizeHashList4(list)