From 9637d74c72de9bbd92ae61b09875ebe7c5fc3139 Mon Sep 17 00:00:00 2001 From: Alex Sharov <AskAlexSharov@gmail.com> Date: Wed, 9 Jun 2021 14:20:47 +0700 Subject: [PATCH] More correct rlp of Sokol headers (#2124) * save * better rlp support * save --- core/genesis.go | 8 ++-- core/types/block.go | 49 +++++++++++++++++------- turbo/stages/genesis_test.go | 72 ++++++++++++++++++++++++------------ 3 files changed, 87 insertions(+), 42 deletions(-) diff --git a/core/genesis.go b/core/genesis.go index 37de2cf836..b15017f245 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -40,7 +40,6 @@ import ( "github.com/ledgerwatch/erigon/ethdb" "github.com/ledgerwatch/erigon/log" "github.com/ledgerwatch/erigon/params" - "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/turbo/trie" ) @@ -66,7 +65,7 @@ type Genesis struct { Mixhash common.Hash `json:"mixHash"` Coinbase common.Address `json:"coinbase"` Alloc GenesisAlloc `json:"alloc" gencodec:"required"` - Seal []rlp.RawValue `json:"seal"` + Seal [][]byte `json:"seal"` // These fields are used for consensus tests. Please don't use them // in actual genesis blocks. @@ -590,8 +589,9 @@ func DefaultSokolGenesisBlock() *Genesis { return &Genesis{ Config: params.SokolChainConfig, Timestamp: 0x0, - Seal: []rlp.RawValue{ - hexutil.MustDecode("0xb8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + Seal: [][]byte{ + common.FromHex(""), + common.FromHex("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), }, GasLimit: 0x663BE0, Difficulty: big.NewInt(0x20000), diff --git a/core/types/block.go b/core/types/block.go index b0e3b0a6ae..a2a7ca86ab 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -88,7 +88,7 @@ type Header struct { Nonce BlockNonce `json:"nonce"` BaseFee *big.Int `json:"baseFee"` Eip1559 bool // to avoid relying on BaseFee != nil for that - Seal []rlp.RawValue // AuRa POA network field + Seal [][]byte // AuRa POA network field WithSeal bool // to avoid relying on Seal != nil for that } @@ -96,12 +96,24 @@ func (h Header) EncodingSize() int { encodingSize := 33 /* ParentHash */ + 33 /* UncleHash */ + 21 /* Coinbase */ + 33 /* Root */ + 33 /* TxHash */ + 33 /* ReceiptHash */ + 259 /* Bloom */ + var sealListLen int if h.WithSeal { - encodingSize++ for i := range h.Seal { - //encodingSize++ - encodingSize += len(h.Seal[i]) + sealListLen++ + switch len(h.Seal[i]) { + case 0: + case 1: + if h.Seal[i][0] >= 128 { + sealListLen++ + } + default: + if len(h.Seal[i]) >= 56 { + sealListLen += (bits.Len(uint(len(h.Seal[i]))) + 7) / 8 + } + sealListLen += len(h.Seal[i]) + } } + encodingSize += sealListLen } else { encodingSize += 33 /* MixDigest */ + 9 /* BlockNonce */ } @@ -166,12 +178,25 @@ func (h Header) EncodeRLP(w io.Writer) error { // Precompute the size of the encoding encodingSize := 33 /* ParentHash */ + 33 /* UncleHash */ + 21 /* Coinbase */ + 33 /* Root */ + 33 /* TxHash */ + 33 /* ReceiptHash */ + 259 /* Bloom */ + + var sealListLen int if h.WithSeal { - encodingSize++ for i := range h.Seal { - //encodingSize++ - encodingSize += len(h.Seal[i]) + sealListLen++ + switch len(h.Seal[i]) { + case 0: + case 1: + if h.Seal[i][0] >= 128 { + sealListLen++ + } + default: + if len(h.Seal[i]) >= 56 { + sealListLen += (bits.Len(uint(len(h.Seal[i]))) + 7) / 8 + } + sealListLen += len(h.Seal[i]) + } } + encodingSize += sealListLen } else { encodingSize += 33 /* MixDigest */ + 9 /* BlockNonce */ } @@ -351,12 +376,8 @@ func (h Header) EncodeRLP(w io.Writer) error { } if h.WithSeal { - b[0] = 128 - if _, err := w.Write(b[:1]); err != nil { - return err - } for i := range h.Seal { - if _, err := w.Write(h.Seal[i]); err != nil { + if err := EncodeString(h.Seal[i], w, b[:]); err != nil { return err } } @@ -482,7 +503,7 @@ func (h *Header) DecodeRLP(s *rlp.Stream) error { if h.WithSeal { h.WithSeal = true - for b, err = s.Raw(); err == nil; b, err = s.Raw() { + for b, err = s.Bytes(); err == nil; b, err = s.Bytes() { h.Seal = append(h.Seal, make(rlp.RawValue, len(b))) copy(h.Seal[len(h.Seal)-1][:], b) } @@ -963,7 +984,7 @@ func CopyHeader(h *Header) *Header { copy(cpy.Extra, h.Extra) } if len(h.Seal) > 0 { - cpy.Seal = make([]rlp.RawValue, len(h.Seal)) + cpy.Seal = make([][]byte, len(h.Seal)) for i := range h.Seal { cpy.Seal[i] = common.CopyBytes(h.Seal[i]) } diff --git a/turbo/stages/genesis_test.go b/turbo/stages/genesis_test.go index 7d86cfe7d1..e262e4dd6f 100644 --- a/turbo/stages/genesis_test.go +++ b/turbo/stages/genesis_test.go @@ -17,8 +17,8 @@ package stages_test import ( - "bytes" "context" + "fmt" "math/big" "reflect" "testing" @@ -61,6 +61,8 @@ func TestDefaultGenesisBlock(t *testing.T) { if err != nil { t.Errorf("error: %w", err) } + aa, _ := rlp.EncodeToBytes(block.Header()) + fmt.Printf("a: %x\n", aa) if block.Root() != params.SokolGenesisStateRoot { t.Errorf("wrong sokol genesis state root, got %v, want %v", block.Root(), params.SokolGenesisStateRoot) } @@ -70,30 +72,52 @@ func TestDefaultGenesisBlock(t *testing.T) { } func TestSokolHeaderRLP(t *testing.T) { - block, _, err := core.DefaultSokolGenesisBlock().ToBlock() - require.NoError(t, err) - b, err := rlp.EncodeToBytes(block.Header()) - require.NoError(t, err) - expect := common.FromHex("f9020da00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0fad4af258fd11939fae0c6c6eec9d340b1caac0b0196fd9a1bc3f489c5bf00b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083663be080808080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") - require.Equal(t, expect, b) - - { - h2 := &types.Header{WithSeal: true} - err = rlp.Decode(bytes.NewReader(expect), h2) - require.NoError(t, err) - require.Equal(t, 2, len(h2.Seal)) - expectSeal2 := common.FromHex("b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") - require.Equal(t, common.FromHex("80"), []byte(h2.Seal[0])) - require.Equal(t, expectSeal2, []byte(h2.Seal[1])) + require := require.New(t) + { //sokol + expect := common.FromHex("f9020da00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0fad4af258fd11939fae0c6c6eec9d340b1caac0b0196fd9a1bc3f489c5bf00b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083663be080808080b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + block, _, err := core.DefaultSokolGenesisBlock().ToBlock() + require.NoError(err) + b, err := rlp.EncodeToBytes(block.Header()) + require.NoError(err) + require.Equal(expect, b) + h := &types.Header{WithSeal: true} + err = rlp.DecodeBytes(expect, h) + require.NoError(err) + require.Equal(2, len(h.Seal)) + + expectSeal2 := common.FromHex("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + require.Equal(common.FromHex(""), h.Seal[0]) + require.Equal(expectSeal2, h.Seal[1]) + enc, err := rlp.EncodeToBytes(h) + require.NoError(err) + require.Equal(expect, enc) } - { - h3 := &types.Header{WithSeal: true} - err = rlp.Decode(bytes.NewReader(common.FromHex("f9020da00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0fad4af258fd11939fae0c6c6eec9d340b1caac0b0196fd9a1bc3f489c5bf00b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083663be080808001b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001")), h3) - require.NoError(t, err) - require.Equal(t, 2, len(h3.Seal)) - require.Equal(t, common.FromHex("1"), []byte(h3.Seal[0])) - expectSeal2 := common.FromHex("b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001") - require.Equal(t, expectSeal2, []byte(h3.Seal[1])) + + { // sokol, more seals + h := &types.Header{WithSeal: true} + enc := common.FromHex("f9020da00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0fad4af258fd11939fae0c6c6eec9d340b1caac0b0196fd9a1bc3f489c5bf00b3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083663be080808002b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001") + err := rlp.DecodeBytes(enc, h) + require.NoError(err) + require.Equal(2, len(h.Seal)) + require.Equal(common.FromHex("2"), h.Seal[0]) + + expectSeal2 := common.FromHex("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001") + require.Equal(expectSeal2, h.Seal[1]) + + res, err := rlp.EncodeToBytes(h) // after encode getting source bytes + require.NoError(err) + require.Equal(enc, res) + } + + { // ethash + expect := common.FromHex("f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23") + h := &types.Header{WithSeal: false} + err := rlp.DecodeBytes(expect, h) + require.NoError(err) + + res, err := rlp.EncodeToBytes(h) // after encode getting source bytes + require.NoError(err) + require.Equal(expect, res) } } -- GitLab