Skip to content

Commit

Permalink
core/types, rlp: optimize derivesha (#21728)
Browse files Browse the repository at this point in the history
This PR contains a minor optimization in derivesha, by exposing the RLP
int-encoding and making use of it to write integers directly to a
buffer (an RLP integer is known to never require more than 9 bytes
total). rlp.AppendUint64 might be useful in other places too.

The code assumes, just as before, that the hasher (a trie) will copy the
key internally, which it does when doing keybytesToHex(key).

Co-authored-by: Felix Lange <fjl@twurst.com>
# Conflicts:
#	core/types/derive_sha.go
  • Loading branch information
holiman authored and mandrigin committed Dec 3, 2020
1 parent 040dceb commit 288f9bd
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 0 deletions.
71 changes: 71 additions & 0 deletions rlp/raw.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,74 @@ 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))
}
switch {
case i < (1 << 8):
return append(b, 0x81, byte(i))
case i < (1 << 16):
return append(b, 0x82,
byte(i>>8),
byte(i),
)
case i < (1 << 24):
return append(b, 0x83,
byte(i>>16),
byte(i>>8),
byte(i),
)
case i < (1 << 32):
return append(b, 0x84,
byte(i>>24),
byte(i>>16),
byte(i>>8),
byte(i),
)
case i < (1 << 40):
return append(b, 0x85,
byte(i>>32),
byte(i>>24),
byte(i>>16),
byte(i>>8),
byte(i),
)

case i < (1 << 48):
return append(b, 0x86,
byte(i>>40),
byte(i>>32),
byte(i>>24),
byte(i>>16),
byte(i>>8),
byte(i),
)
case i < (1 << 56):
return append(b, 0x87,
byte(i>>48),
byte(i>>40),
byte(i>>32),
byte(i>>24),
byte(i>>16),
byte(i>>8),
byte(i),
)

default:
return append(b, 0x88,
byte(i>>56),
byte(i>>48),
byte(i>>40),
byte(i>>32),
byte(i>>24),
byte(i>>16),
byte(i>>8),
byte(i),
)
}
}
38 changes: 38 additions & 0 deletions rlp/raw_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"io"
"reflect"
"testing"
"testing/quick"
)

func TestCountValues(t *testing.T) {
Expand Down Expand Up @@ -240,3 +241,40 @@ func TestReadSize(t *testing.T) {
}
}
}

func TestAppendUint64(t *testing.T) {
tests := []struct {
input uint64
slice []byte
output string
}{
{0, nil, "80"},
{1, nil, "01"},
{2, nil, "02"},
{127, nil, "7F"},
{128, nil, "8180"},
{129, nil, "8181"},
{0xFFFFFF, nil, "83FFFFFF"},
{127, []byte{1, 2, 3}, "0102037F"},
{0xFFFFFF, []byte{1, 2, 3}, "01020383FFFFFF"},
}

for _, test := range tests {
x := AppendUint64(test.slice, test.input)
if !bytes.Equal(x, unhex(test.output)) {
t.Errorf("AppendUint64(%v, %d): got %x, want %s", test.slice, test.input, x, test.output)
}
}
}

func TestAppendUint64Random(t *testing.T) {
fn := func(i uint64) bool {
enc, _ := EncodeToBytes(i)
encAppend := AppendUint64(nil, i)
return bytes.Equal(enc, encAppend)
}
config := quick.Config{MaxCountScale: 50}
if err := quick.Check(fn, &config); err != nil {
t.Fatal(err)
}
}

0 comments on commit 288f9bd

Please sign in to comment.