From 9292105a4a650ebf574ab2abd9d5278dd0226236 Mon Sep 17 00:00:00 2001 From: iteye Date: Mon, 6 Jul 2026 18:44:27 +0800 Subject: [PATCH] fix bugs --- qkc/cluster/wire/messages.go | 15 -------- qkc/cluster/wire/messages_test.go | 13 +++++-- qkc/cluster/wire/rawbytes_placeholder.go | 46 ++++++++++++++---------- qkc/cluster/wire/types.go | 6 ++-- 4 files changed, 43 insertions(+), 37 deletions(-) diff --git a/qkc/cluster/wire/messages.go b/qkc/cluster/wire/messages.go index 2d956d6402..6e43a4f095 100644 --- a/qkc/cluster/wire/messages.go +++ b/qkc/cluster/wire/messages.go @@ -239,7 +239,6 @@ type DestroyClusterPeerConnectionCommand struct { // FIELDS = [("root_block", RootBlock), ("expect_switch", boolean)] type AddRootBlockRequest struct { // TODO: Replace with *RootBlock once core.RootBlock is ported. - // WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes. RootBlock *RawBytes ExpectSwitch bool } @@ -346,7 +345,6 @@ type AccountBranchData struct { Branch uint32 TransactionCount *big.Int // uint256 // TODO: Replace with *TokenBalanceMap once core.TokenBalanceMap is ported. - // WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes. TokenBalances *RawBytes IsContract bool PoswMineableBlocks uint16 @@ -415,12 +413,10 @@ type ShardStats struct { // ] type AddMinorBlockHeaderRequest struct { // TODO: Replace with *MinorBlockHeader once core.MinorBlockHeader is ported. - // WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes. MinorBlockHeader *RawBytes TxCount uint32 XShardTxCount uint32 // TODO: Replace with *TokenBalanceMap once core.TokenBalanceMap is ported. - // WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes. CoinbaseAmountMap *RawBytes ShardStats ShardStats } @@ -461,7 +457,6 @@ type SyncMinorBlockListRequest struct { type SyncMinorBlockListResponse struct { ErrorCode uint32 // TODO: Replace with real block_coinbase_map once core.TokenBalanceMap is ported. - // WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes. BlockCoinbaseMap *RawBytes ShardStats *ShardStats `ser:"nil"` } @@ -489,7 +484,6 @@ type GetMinorBlockRequest struct { type GetMinorBlockResponse struct { ErrorCode uint32 // TODO: Replace with *MinorBlock once core.MinorBlock is ported. - // WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes. MinorBlock *RawBytes ExtraInfo *MinorBlockExtraInfo `ser:"nil"` } @@ -504,7 +498,6 @@ type GetTransactionRequest struct { type GetTransactionResponse struct { ErrorCode uint32 // TODO: Replace with *MinorBlock once core.MinorBlock is ported. - // WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes. MinorBlock *RawBytes Index uint32 } @@ -512,7 +505,6 @@ type GetTransactionResponse struct { // ExecuteTransactionRequest (ClusterOp.EXECUTE_TRANSACTION_REQUEST, 0xA3). type ExecuteTransactionRequest struct { // TODO: Replace with *TypedTransaction once core.TypedTransaction is ported. - // WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes. Tx *RawBytes FromAddress [AddressLength]byte BlockHeight *uint64 `ser:"nil"` @@ -534,7 +526,6 @@ type GetTransactionReceiptRequest struct { type GetTransactionReceiptResponse struct { ErrorCode uint32 // TODO: Replace with *MinorBlock once core.MinorBlock is ported. - // WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes. MinorBlock *RawBytes Index uint32 // TODO: Replace with *TransactionReceipt once core.TransactionReceipt is ported. @@ -612,7 +603,6 @@ type GetLogResponse struct { // EstimateGasRequest (ClusterOp.ESTIMATE_GAS_REQUEST, 0xAF). type EstimateGasRequest struct { // TODO: Replace with *TypedTransaction once core.TypedTransaction is ported. - // WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes. Tx *RawBytes FromAddress [AddressLength]byte } @@ -773,7 +763,6 @@ type HelloCommand struct { PeerPort uint16 ChainMaskList []uint32 `bytesizeofslicelen:"4"` // TODO: Replace with *RootBlockHeader once core.RootBlockHeader is ported. - // WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes. RootBlockHeader *RawBytes GenesisRootBlockHash [HashLength]byte } @@ -781,7 +770,6 @@ type HelloCommand struct { // NewMinorBlockHeaderListCommand (CommandOp.NEW_MINOR_BLOCK_HEADER_LIST, 0x01). type NewMinorBlockHeaderListCommand struct { // TODO: Replace with *RootBlockHeader once core.RootBlockHeader is ported. - // WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes. RootBlockHeader *RawBytes 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). type GetRootBlockHeaderListResponse struct { // TODO: Replace with *RootBlockHeader once core.RootBlockHeader is ported. - // WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes. RootTip *RawBytes 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). type GetMinorBlockHeaderListResponse struct { // TODO: Replace with *RootBlockHeader once core.RootBlockHeader is ported. - // WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes. RootTip *RawBytes // TODO: Replace with *MinorBlockHeader once core.MinorBlockHeader is ported. - // WARNING: not the last field; RawBytes.Deserialize consumes remaining bytes. ShardTip *RawBytes BlockHeaderList []*RawBytes `bytesizeofslicelen:"4"` // TODO: Replace with []*MinorBlockHeader once core.MinorBlockHeader is ported } diff --git a/qkc/cluster/wire/messages_test.go b/qkc/cluster/wire/messages_test.go index b75ec02d47..18f7375736 100644 --- a/qkc/cluster/wire/messages_test.go +++ b/qkc/cluster/wire/messages_test.go @@ -357,8 +357,17 @@ func TestNonOptionalRawBytes_NoMarker(t *testing.T) { if err := serialize.Serialize(&buf, &req); err != nil { t.Fatalf("Serialize: %v", err) } - if buf[0] != 0xAA { - t.Errorf("non-optional RawBytes should not have presence marker, got %x", buf[0]) + // RawBytes now uses 4-byte length prefix, so first bytes should be 00000001 (length=1) + // 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 + } } } diff --git a/qkc/cluster/wire/rawbytes_placeholder.go b/qkc/cluster/wire/rawbytes_placeholder.go index 6f3d0d53da..2a3e260290 100644 --- a/qkc/cluster/wire/rawbytes_placeholder.go +++ b/qkc/cluster/wire/rawbytes_placeholder.go @@ -39,14 +39,16 @@ // 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 // by the Python FIELDS schema but is not yet implemented in Go. // // Wire behavior: -// - Serialize: writes raw bytes unchanged -// - Deserialize: consumes ALL remaining bytes in buffer +// - Serialize: writes 4-byte length prefix + raw bytes (matches Python PrependedSizeBytesSerializer(4)) +// - 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 @@ -54,10 +56,9 @@ // // RawBytes MUST obey the following rules: // -// 1. MUST only appear as the LAST field in a struct -// 2. MUST NOT be partially decoded or inspected -// 3. MUST NOT be used in stable protocol definitions -// 4. MUST be removed once real Go types are introduced +// 1. MUST NOT be partially decoded or inspected +// 2. MUST NOT be used in stable protocol definitions +// 3. MUST be removed once real Go types are introduced // // Any violation of these rules results in undefined wire behavior. // @@ -81,6 +82,7 @@ package wire import ( + "encoding/binary" "fmt" "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) } + // 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...) return nil } -// Deserialize consumes all remaining bytes from the buffer. -// -// 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. +// Deserialize reads 4-byte length prefix and corresponding bytes. // // TEMPORARY: Delete this placeholder once real types (RootBlock, MinorBlockHeader) are ported. func (r *RawBytes) Deserialize(bb *serialize.ByteBuffer) error { 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) - } - bytes, err := bb.ReadRemaining() + + // Read 4-byte length prefix + length, err := bb.GetUInt32() if err != nil { 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) return nil } diff --git a/qkc/cluster/wire/types.go b/qkc/cluster/wire/types.go index 6c4ff0ccb5..5790d4e572 100644 --- a/qkc/cluster/wire/types.go +++ b/qkc/cluster/wire/types.go @@ -74,13 +74,15 @@ func (p *PrependedSizeHashList4) Deserialize(bb *serialize.ByteBuffer) error { 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++ { hashBytes, err := bb.ReadBytes(HashLength) if err != nil { return err } - list[i] = [HashLength]byte(hashBytes) + var hash [HashLength]byte + copy(hash[:], hashBytes) + list[i] = hash } *p = PrependedSizeHashList4(list)