From 57c39e886e393dd3ee941dc59e13d0a066761419 Mon Sep 17 00:00:00 2001 From: qianbin Date: Tue, 2 Jan 2024 18:01:40 +0800 Subject: [PATCH] rlp,trie: add AppendString & EndList to avoid importing 3rd-party lib. --- go.mod | 1 - go.sum | 2 - rlp/raw.go | 77 +++++++++++++++++++++++------- rlp/raw_test.go | 120 +++++++++++++++++++++++++++++++++++++++++++++++ trie/node_enc.go | 16 +++---- 5 files changed, 188 insertions(+), 28 deletions(-) diff --git a/go.mod b/go.mod index 6124aa9fdc..b4d077fc47 100644 --- a/go.mod +++ b/go.mod @@ -53,7 +53,6 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 github.com/protolambda/bls12-381-util v0.0.0-20220416220906-d8552aa452c7 - github.com/qianbin/drlp v0.0.0-20231230065804-db474f66bf91 github.com/rs/cors v1.7.0 github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible github.com/status-im/keycard-go v0.2.0 diff --git a/go.sum b/go.sum index 8e6134c3ab..bab51b1345 100644 --- a/go.sum +++ b/go.sum @@ -522,8 +522,6 @@ github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/protolambda/bls12-381-util v0.0.0-20220416220906-d8552aa452c7 h1:cZC+usqsYgHtlBaGulVnZ1hfKAi8iWtujBnRLQE698c= github.com/protolambda/bls12-381-util v0.0.0-20220416220906-d8552aa452c7/go.mod h1:IToEjHuttnUzwZI5KBSM/LOOW3qLbbrHOEfp3SbECGY= -github.com/qianbin/drlp v0.0.0-20231230065804-db474f66bf91 h1:N1pcRULtPB7CndtexGDr94ai8wsJLx55AKYfo7F6qEs= -github.com/qianbin/drlp v0.0.0-20231230065804-db474f66bf91/go.mod h1:OnClEjurpFUtR3RUCauP9HxNNl8xjfGAOv0kWYTznOc= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= diff --git a/rlp/raw.go b/rlp/raw.go index 773aa7e614..53da9f0d46 100644 --- a/rlp/raw.go +++ b/rlp/raw.go @@ -222,45 +222,40 @@ func readSize(b []byte, slen byte) (uint64, error) { return s, nil } -// AppendUint64 appends the RLP encoding of i to b, and returns the resulting slice. -func AppendUint64(b []byte, i uint64) []byte { - if i == 0 { - return append(b, 0x80) - } else if i < 128 { - return append(b, byte(i)) - } +// appendUintWithTag appends kind tag and i to b in big endian byte order, +// using the least number of bytes needed to represent i. +func appendUintWithTag(b []byte, i uint64, kindTag byte) []byte { switch { case i < (1 << 8): - return append(b, 0x81, byte(i)) + return append(b, kindTag+1, byte(i)) case i < (1 << 16): - return append(b, 0x82, + return append(b, kindTag+2, byte(i>>8), byte(i), ) case i < (1 << 24): - return append(b, 0x83, + return append(b, kindTag+3, byte(i>>16), byte(i>>8), byte(i), ) case i < (1 << 32): - return append(b, 0x84, + return append(b, kindTag+4, byte(i>>24), byte(i>>16), byte(i>>8), byte(i), ) case i < (1 << 40): - return append(b, 0x85, + return append(b, kindTag+5, byte(i>>32), byte(i>>24), byte(i>>16), byte(i>>8), byte(i), ) - case i < (1 << 48): - return append(b, 0x86, + return append(b, kindTag+6, byte(i>>40), byte(i>>32), byte(i>>24), @@ -269,7 +264,7 @@ func AppendUint64(b []byte, i uint64) []byte { byte(i), ) case i < (1 << 56): - return append(b, 0x87, + return append(b, kindTag+7, byte(i>>48), byte(i>>40), byte(i>>32), @@ -278,9 +273,8 @@ func AppendUint64(b []byte, i uint64) []byte { byte(i>>8), byte(i), ) - default: - return append(b, 0x88, + return append(b, kindTag+8, byte(i>>56), byte(i>>48), byte(i>>40), @@ -292,3 +286,52 @@ func AppendUint64(b []byte, i uint64) []byte { ) } } + +// AppendUint64 appends the RLP encoding of i to b, and returns the resulting slice. +func AppendUint64(b []byte, i uint64) []byte { + if i == 0 { + return append(b, 0x80) + } else if i < 128 { + // fits single byte + return append(b, byte(i)) + } else { + return appendUintWithTag(b, i, 0x80) + } +} + +// AppendString appends RLP-encoded str to buf and returns the extended buffer. +func AppendString(buf, str []byte) []byte { + if size := len(str); size == 0 { + return append(buf, 0x80) + } else if size == 1 && str[0] < 128 { + // fits single byte, no string header + return append(buf, str[0]) + } else if size < 56 { + buf = append(buf, 0x80+byte(size)) + return append(buf, str...) + } else { + buf = appendUintWithTag(buf, uint64(size), 0xB7) + return append(buf, str...) + } +} + +// EndList ends up list starting from offset and returns the extended buffer. +// Content after offset is treated as list content. +func EndList(buf []byte, offset int) []byte { + contentSize := len(buf) - offset + if contentSize == 0 { + buf = append(buf, 0xC0) + } else if contentSize < 56 { + // shift the content for room of list header + buf = append(buf[:offset+1], buf[offset:]...) + // write list header + buf[offset] = 0xC0 + byte(contentSize) + } else { + headerSize := intsize(uint64(contentSize)) + 1 + // shift the content for room of list header + buf = append(buf[:offset+headerSize], buf[offset:]...) + // write list header + appendUintWithTag(buf[:offset], uint64(contentSize), 0xF7) + } + return buf +} diff --git a/rlp/raw_test.go b/rlp/raw_test.go index 7b3255eca3..c44dea6083 100644 --- a/rlp/raw_test.go +++ b/rlp/raw_test.go @@ -304,6 +304,126 @@ func TestAppendUint64Random(t *testing.T) { } } +func TestAppendString(t *testing.T) { + tests := []struct { + input []byte + slice []byte + output string + }{ + {[]byte{}, nil, "80"}, + {[]byte{0x7E}, nil, "7E"}, + {[]byte{0x7F}, nil, "7F"}, + {[]byte{0x80}, nil, "8180"}, + {[]byte{1, 2, 3}, nil, "83010203"}, + { + []byte("Lorem ipsum dolor sit amet, consectetur adipisicing eli"), nil, + "B74C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E7365637465747572206164697069736963696E6720656C69", + }, + { + []byte("Lorem ipsum dolor sit amet, consectetur adipisicing elit"), nil, + "B8384C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E7365637465747572206164697069736963696E6720656C6974", + }, + { + []byte("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mauris magna, suscipit sed vehicula non, iaculis faucibus tortor. Proin suscipit ultricies malesuada. Duis tortor elit, dictum quis tristique eu, ultrices at risus. Morbi a est imperdiet mi ullamcorper aliquet suscipit nec lorem. Aenean quis leo mollis, vulputate elit varius, consequat enim. Nulla ultrices turpis justo, et posuere urna consectetur nec. Proin non convallis metus. Donec tempor ipsum in mauris congue sollicitudin. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse convallis sem vel massa faucibus, eget lacinia lacus tempor. Nulla quis ultricies purus. Proin auctor rhoncus nibh condimentum mollis. Aliquam consequat enim at metus luctus, a eleifend purus egestas. Curabitur at nibh metus. Nam bibendum, neque at auctor tristique, lorem libero aliquet arcu, non interdum tellus lectus sit amet eros. Cras rhoncus, metus ac ornare cursus, dolor justo ultrices metus, at ullamcorper volutpat"), nil, + "B904004C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E73656374657475722061646970697363696E6720656C69742E20437572616269747572206D6175726973206D61676E612C20737573636970697420736564207665686963756C61206E6F6E2C20696163756C697320666175636962757320746F72746F722E2050726F696E20737573636970697420756C74726963696573206D616C6573756164612E204475697320746F72746F7220656C69742C2064696374756D2071756973207472697374697175652065752C20756C7472696365732061742072697375732E204D6F72626920612065737420696D70657264696574206D6920756C6C616D636F7270657220616C6971756574207375736369706974206E6563206C6F72656D2E2041656E65616E2071756973206C656F206D6F6C6C69732C2076756C70757461746520656C6974207661726975732C20636F6E73657175617420656E696D2E204E756C6C6120756C74726963657320747572706973206A7573746F2C20657420706F73756572652075726E6120636F6E7365637465747572206E65632E2050726F696E206E6F6E20636F6E76616C6C6973206D657475732E20446F6E65632074656D706F7220697073756D20696E206D617572697320636F6E67756520736F6C6C696369747564696E2E20566573746962756C756D20616E746520697073756D207072696D697320696E206661756369627573206F726369206C756374757320657420756C74726963657320706F737565726520637562696C69612043757261653B2053757370656E646973736520636F6E76616C6C69732073656D2076656C206D617373612066617563696275732C2065676574206C6163696E6961206C616375732074656D706F722E204E756C6C61207175697320756C747269636965732070757275732E2050726F696E20617563746F722072686F6E637573206E69626820636F6E64696D656E74756D206D6F6C6C69732E20416C697175616D20636F6E73657175617420656E696D206174206D65747573206C75637475732C206120656C656966656E6420707572757320656765737461732E20437572616269747572206174206E696268206D657475732E204E616D20626962656E64756D2C206E6571756520617420617563746F72207472697374697175652C206C6F72656D206C696265726F20616C697175657420617263752C206E6F6E20696E74657264756D2074656C6C7573206C65637475732073697420616D65742065726F732E20437261732072686F6E6375732C206D65747573206163206F726E617265206375727375732C20646F6C6F72206A7573746F20756C747269636573206D657475732C20617420756C6C616D636F7270657220766F6C7574706174", + }, + } + + for _, test := range tests { + x := AppendString(test.slice, test.input) + if !bytes.Equal(x, unhex(test.output)) { + t.Errorf("TestAppendString(%v, %d): got %x, want %s", test.slice, test.input, x, test.output) + } + } +} + +func TestEndList(t *testing.T) { + tests := []struct { + input interface{} + slice []byte + output string + }{ + {[]interface{}{}, nil, "C0"}, + {[]interface{}{1, 2, 3}, nil, "C3010203"}, + { + // [ [], [[]], [ [], [[]] ] ] + []interface{}{[]interface{}{}, []interface{}{[]interface{}{}}, []interface{}{[]interface{}{}, []interface{}{[]interface{}{}}}}, nil, + "C7C0C1C0C3C0C1C0", + }, + { + []interface{}{"aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk", "lll", "mmm", "nnn", "ooo"}, nil, + "F83C836161618362626283636363836464648365656583666666836767678368686883696969836A6A6A836B6B6B836C6C6C836D6D6D836E6E6E836F6F6F", + }, + { + []interface{}{1, 0xFFFFFF, []interface{}{[]interface{}{4, 5, 5}}, "abc"}, nil, + "CE0183FFFFFFC4C304050583616263", + }, + {[]interface{}{ + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}, + []interface{}{"asdf", "qwer", "zxcv"}}, nil, + "F90200CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376"}, + } + + var encode func(buf []byte, v interface{}) []byte + encode = func(buf []byte, v interface{}) []byte { + switch v := v.(type) { + case []interface{}: + offset := len(buf) + for _, c := range v { + buf = encode(buf, c) + } + return EndList(buf, offset) + case int: + return AppendUint64(buf, uint64(v)) + case uint64: + return AppendUint64(buf, v) + case []byte: + return AppendString(buf, v) + case string: + return AppendString(buf, []byte(v)) + default: + panic(errors.New("unexpected value type")) + } + } + + for _, test := range tests { + x := encode(test.slice, test.input) + if !bytes.Equal(x, unhex(test.output)) { + t.Errorf("TestEndList(%v, %d): got %x, want %s", test.slice, test.input, x, test.output) + } + } +} + func TestBytesSize(t *testing.T) { tests := []struct { v []byte diff --git a/trie/node_enc.go b/trie/node_enc.go index 1309a0063f..c2a32a5d98 100644 --- a/trie/node_enc.go +++ b/trie/node_enc.go @@ -17,7 +17,7 @@ package trie import ( - "github.com/qianbin/drlp" + "github.com/ethereum/go-ethereum/rlp" ) func (n *fullNode) encode(buf []byte) []byte { @@ -29,10 +29,10 @@ func (n *fullNode) encode(buf []byte) []byte { if c != nil { buf = c.encode(buf) } else { - buf = drlp.AppendUint(buf, 0) + buf = rlp.AppendUint64(buf, 0) } } - return drlp.EndList(buf, offset) + return rlp.EndList(buf, offset) } func (n *shortNode) encode(buf []byte) []byte { @@ -40,21 +40,21 @@ func (n *shortNode) encode(buf []byte) []byte { buf = make([]byte, 0, len(n.Key)+40) } offset := len(buf) - buf = drlp.AppendString(buf, n.Key) + buf = rlp.AppendString(buf, n.Key) if n.Val != nil { buf = n.Val.encode(buf) } else { - buf = drlp.AppendUint(buf, 0) + buf = rlp.AppendUint64(buf, 0) } - return drlp.EndList(buf, offset) + return rlp.EndList(buf, offset) } func (n hashNode) encode(buf []byte) []byte { - return drlp.AppendString(buf, n) + return rlp.AppendString(buf, n) } func (n valueNode) encode(buf []byte) []byte { - return drlp.AppendString(buf, n) + return rlp.AppendString(buf, n) } func (n rawNode) encode(buf []byte) []byte {