rlp,trie: add AppendString & EndList to avoid importing 3rd-party lib.

This commit is contained in:
qianbin 2024-01-02 18:01:40 +08:00
parent 17d0291609
commit 57c39e886e
5 changed files with 188 additions and 28 deletions

1
go.mod
View file

@ -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

2
go.sum
View file

@ -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=

View file

@ -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
}

View file

@ -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

View file

@ -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 {