Decoding incarnation and Tests (#2727)

This commit is contained in:
Enrique Jose Avila Asapche 2021-09-26 13:58:20 +01:00 committed by GitHub
parent 5da7fb64bf
commit 3f1d51121c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 215 additions and 0 deletions

View File

@ -504,6 +504,7 @@ func (a *Account) DecodeForStorage(enc []byte) error {
}
if fieldSet&8 > 0 {
decodeLength := int(enc[pos])
if decodeLength != 32 {
@ -526,6 +527,54 @@ func (a *Account) DecodeForStorage(enc []byte) error {
return nil
}
func DecodeIncarnationFromStorage(enc []byte) (uint64, error) {
if len(enc) == 0 {
return 0, nil
}
var fieldSet = enc[0]
var pos = 1
//looks for the position incarnation is at
if fieldSet&1 > 0 {
decodeLength := int(enc[pos])
if len(enc) < pos+decodeLength+1 {
return 0, fmt.Errorf(
"malformed CBOR for Account.Nonce: %s, Length %d",
enc[pos+1:], decodeLength)
}
pos += decodeLength + 1
}
if fieldSet&2 > 0 {
decodeLength := int(enc[pos])
if len(enc) < pos+decodeLength+1 {
return 0, fmt.Errorf(
"malformed CBOR for Account.Nonce: %s, Length %d",
enc[pos+1:], decodeLength)
}
pos += decodeLength + 1
}
if fieldSet&4 > 0 {
decodeLength := int(enc[pos])
//checks if the ending position is correct if not returns 0
if len(enc) < pos+decodeLength+1 {
return 0, fmt.Errorf(
"malformed CBOR for Account.Incarnation: %s, Length %d",
enc[pos+1:], decodeLength)
}
incarnation := bytesToUint64(enc[pos+1 : pos+decodeLength+1])
return incarnation, nil
}
return 0, nil
}
func (a *Account) SelfCopy() *Account {
newAcc := NewAccount()
newAcc.Copy(a)

View File

@ -289,6 +289,7 @@ func BenchmarkDecodingAccount(b *testing.B) {
b.StartTimer()
}
})
}
b.StopTimer()
@ -297,6 +298,78 @@ func BenchmarkDecodingAccount(b *testing.B) {
}
}
func BenchmarkDecodingIncarnation(b *testing.B) {
accountCases := []struct {
name string
acc *Account
}{
{
name: "EmptyAccount",
acc: &Account{
Nonce: 0,
Balance: *new(uint256.Int),
Root: emptyRoot, // extAccount doesn't have Root value
CodeHash: emptyCodeHash, // extAccount doesn't have CodeHash value
},
},
{
name: "AccountEncodeWithCode",
acc: &Account{
Nonce: 2,
Balance: *new(uint256.Int).SetUint64(1000),
Root: common.HexToHash("0000000000000000000000000000000000000000000000000000000000000021"),
CodeHash: common.BytesToHash(crypto.Keccak256([]byte{1, 2, 3})),
},
},
{
name: "AccountEncodeWithCodeWithStorageSizeHack",
acc: &Account{
Nonce: 2,
Balance: *new(uint256.Int).SetUint64(1000),
Root: common.HexToHash("0000000000000000000000000000000000000000000000000000000000000021"),
CodeHash: common.BytesToHash(crypto.Keccak256([]byte{1, 2, 3})),
},
},
}
var decodedIncarnations []uint64
b.ResetTimer()
for _, test := range accountCases {
test := test
encodedAccount := make([]byte, test.acc.EncodingLengthForStorage())
b.Run(fmt.Sprint(test.name), func(b *testing.B) {
for i := 0; i < b.N; i++ {
b.StopTimer()
test.acc.Nonce = uint64(i)
test.acc.Balance.SetUint64(uint64(i))
test.acc.EncodeForStorage(encodedAccount)
b.StartTimer()
if _, err := DecodeIncarnationFromStorage(encodedAccount); err != nil {
b.Fatal("can't decode the incarnation", err, encodedAccount)
}
decodedIncarnation, _ := DecodeIncarnationFromStorage(encodedAccount)
b.StopTimer()
decodedIncarnations = append(decodedIncarnations, decodedIncarnation)
b.StartTimer()
}
})
}
b.StopTimer()
for _, incarnation := range decodedIncarnations {
fmt.Fprint(ioutil.Discard, incarnation)
}
}
func BenchmarkRLPEncodingAccount(b *testing.B) {
accountCases := []struct {
name string

View File

@ -189,3 +189,96 @@ func isAccountsEqual(t *testing.T, src, dst Account) {
t.Fatal("cant decode the account Version", src.Incarnation, dst.Incarnation)
}
}
func testIncarnationForEmptyAccount(t *testing.T) {
a := Account{
Initialised: true,
Nonce: 100,
Balance: *new(uint256.Int),
Root: emptyRoot,
CodeHash: emptyCodeHash,
Incarnation: 4,
}
encodedAccount := make([]byte, a.EncodingLengthForStorage())
a.EncodeForStorage(encodedAccount)
var decodedIncarnation uint64
if _, err := DecodeIncarnationFromStorage(encodedAccount); err != nil {
t.Fatal("Can't decode the incarnation", err, encodedAccount)
}
decodedIncarnation, _ = DecodeIncarnationFromStorage(encodedAccount)
isIncarnationEqual(t, a.Incarnation, decodedIncarnation)
}
func testEmptyIncarnationForEmptyAccount2(t *testing.T) {
a := Account{}
encodedAccount := make([]byte, a.EncodingLengthForStorage())
a.EncodeForStorage(encodedAccount)
var decodedIncarnation uint64
if _, err := DecodeIncarnationFromStorage(encodedAccount); err != nil {
t.Fatal("Can't decode the incarnation", err, encodedAccount)
}
decodedIncarnation, _ = DecodeIncarnationFromStorage(encodedAccount)
isIncarnationEqual(t, a.Incarnation, decodedIncarnation)
}
func testIncarnationWithNonEmptyAccount(t *testing.T) {
a := Account{
Initialised: true,
Nonce: 2,
Balance: *new(uint256.Int).SetUint64(1000),
Root: common.HexToHash("0000000000000000000000000000000000000000000000000000000000000021"),
CodeHash: common.BytesToHash(crypto.Keccak256([]byte{1, 2, 3})),
Incarnation: 4,
}
encodedAccount := make([]byte, a.EncodingLengthForStorage())
a.EncodeForStorage(encodedAccount)
var decodedIncarnation uint64
if _, err := DecodeIncarnationFromStorage(encodedAccount); err != nil {
t.Fatal("Can't decode the incarnation", err, encodedAccount)
}
decodedIncarnation, _ = DecodeIncarnationFromStorage(encodedAccount)
isIncarnationEqual(t, a.Incarnation, decodedIncarnation)
}
func testIncarnationWithNoIncarnation(t *testing.T) {
a := Account{
Initialised: true,
Nonce: 2,
Balance: *new(uint256.Int).SetUint64(1000),
Root: common.HexToHash("0000000000000000000000000000000000000000000000000000000000000021"),
CodeHash: common.BytesToHash(crypto.Keccak256([]byte{1, 2, 3})),
Incarnation: 0,
}
encodedAccount := make([]byte, a.EncodingLengthForStorage())
a.EncodeForStorage(encodedAccount)
var decodedIncarnation uint64
if _, err := DecodeIncarnationFromStorage(encodedAccount); err != nil {
t.Fatal("Can't decode the incarnation", err, encodedAccount)
}
decodedIncarnation, _ = DecodeIncarnationFromStorage(encodedAccount)
isIncarnationEqual(t, a.Incarnation, decodedIncarnation)
}
func isIncarnationEqual(t *testing.T, initialIncarnation uint64, decodedIncarnation uint64) {
if initialIncarnation != decodedIncarnation {
t.Fatal("Can't decode the incarnation", initialIncarnation, decodedIncarnation)
}
}