mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-25 13:07:17 +00:00
bcf04bbbcf
* migration tool + CBOR encoding for storage of account bucket * documentation updated * fixed * removed noncontract in EncodeForStorage * code adjustments * updated tests * switched to custom encoding * documentation updated
246 lines
6.7 KiB
Go
246 lines
6.7 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"math/big"
|
|
|
|
"github.com/ledgerwatch/turbo-geth/common"
|
|
"github.com/ledgerwatch/turbo-geth/core/types/accounts"
|
|
"github.com/ledgerwatch/turbo-geth/crypto"
|
|
)
|
|
|
|
func decodeRLP(buf []byte) (accounts.Account, error) {
|
|
acc := accounts.Account{}
|
|
length, structure, pos := decodeLength(buf, 0)
|
|
if pos+length != len(buf) {
|
|
return accounts.Account{}, fmt.Errorf(
|
|
"malformed RLP for Account(%x): prefixLength(%d) + dataLength(%d) != sliceLength(%d)",
|
|
buf, pos, length, len(buf))
|
|
}
|
|
if !structure {
|
|
return accounts.Account{}, fmt.Errorf(
|
|
"encoding of Account should be RLP struct, got byte array: %x",
|
|
buf,
|
|
)
|
|
}
|
|
|
|
acc.Initialised = true
|
|
acc.Nonce = 0
|
|
acc.Balance.SetInt64(0)
|
|
acc.Root = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
|
|
acc.CodeHash = crypto.Keccak256Hash(nil)
|
|
acc.StorageSize = 0
|
|
acc.HasStorageSize = false
|
|
if length == 0 && structure {
|
|
return accounts.Account{}, nil
|
|
}
|
|
|
|
if pos < len(buf) {
|
|
nonceBytes, s, newPos := decodeLength(buf, pos)
|
|
if s {
|
|
return accounts.Account{}, fmt.Errorf(
|
|
"encoding of Account.Nonce should be byte array, got RLP struct: %x",
|
|
buf[pos:newPos+nonceBytes],
|
|
)
|
|
}
|
|
|
|
if newPos+nonceBytes > len(buf) {
|
|
return accounts.Account{}, fmt.Errorf(
|
|
"malformed RLP for Account.Nonce(%x): prefixLength(%d) + dataLength(%d) >= sliceLength(%d)",
|
|
buf[pos:newPos+nonceBytes],
|
|
newPos-pos, nonceBytes, len(buf)-pos,
|
|
)
|
|
}
|
|
|
|
var nonce uint64
|
|
if nonceBytes == 0 && newPos == pos {
|
|
nonce = uint64(buf[newPos])
|
|
pos = newPos + 1
|
|
} else {
|
|
for _, b := range buf[newPos : newPos+nonceBytes] {
|
|
nonce = (nonce << 8) + uint64(b)
|
|
}
|
|
pos = newPos + nonceBytes
|
|
}
|
|
|
|
acc.Nonce = nonce
|
|
}
|
|
if pos < len(buf) {
|
|
balanceBytes, s, newPos := decodeLength(buf, pos)
|
|
if s {
|
|
return accounts.Account{}, fmt.Errorf(
|
|
"encoding of Account.Balance should be byte array, got RLP struct: %x",
|
|
buf[pos:newPos+balanceBytes],
|
|
)
|
|
}
|
|
|
|
if newPos+balanceBytes > len(buf) {
|
|
return accounts.Account{}, fmt.Errorf("malformed RLP for Account.Balance(%x): prefixLength(%d) + dataLength(%d) >= sliceLength(%d)",
|
|
buf[pos],
|
|
newPos-pos, balanceBytes, len(buf)-pos,
|
|
)
|
|
}
|
|
|
|
var bigB big.Int
|
|
if balanceBytes == 0 && newPos == pos {
|
|
acc.Balance.SetInt64(int64(buf[newPos]))
|
|
pos = newPos + 1
|
|
} else {
|
|
for _, b := range buf[newPos : newPos+balanceBytes] {
|
|
acc.Balance.Lsh(&acc.Balance, 8)
|
|
bigB.SetUint64(uint64(b))
|
|
acc.Balance.Add(&acc.Balance, &bigB)
|
|
}
|
|
pos = newPos + balanceBytes
|
|
}
|
|
}
|
|
|
|
// Skip incarnation decoding if this is not read from storage
|
|
if pos < len(buf) {
|
|
incarnationBytes, s, newPos := decodeLength(buf, pos)
|
|
if s {
|
|
return accounts.Account{}, fmt.Errorf(
|
|
"encoding of Account.Incarnation should be byte array, got RLP struct: %x",
|
|
buf[pos:newPos+incarnationBytes],
|
|
)
|
|
}
|
|
|
|
if newPos+incarnationBytes > len(buf) {
|
|
return accounts.Account{}, fmt.Errorf(
|
|
"malformed RLP for Account.Incarnation(%x): prefixLength(%d) + dataLength(%d) >= sliceLength(%d)",
|
|
buf[pos:newPos+incarnationBytes],
|
|
newPos-pos, incarnationBytes, len(buf)-pos,
|
|
)
|
|
}
|
|
|
|
var incarnation uint64
|
|
if incarnationBytes == 0 && newPos == pos {
|
|
incarnation = uint64(buf[newPos])
|
|
pos = newPos + 1
|
|
} else {
|
|
for _, b := range buf[newPos : newPos+incarnationBytes] {
|
|
incarnation = (incarnation << 8) + uint64(b)
|
|
}
|
|
pos = newPos + incarnationBytes
|
|
}
|
|
|
|
acc.Incarnation = incarnation
|
|
}
|
|
|
|
if pos < len(buf) {
|
|
rootBytes, s, newPos := decodeLength(buf, pos)
|
|
if s {
|
|
return accounts.Account{}, fmt.Errorf(
|
|
"encoding of Account.Root should be byte array, got RLP struct: %x",
|
|
buf[pos:newPos+rootBytes],
|
|
)
|
|
}
|
|
|
|
if rootBytes != 32 {
|
|
return accounts.Account{}, fmt.Errorf(
|
|
"encoding of Account.Root should have size 32, got %d",
|
|
rootBytes,
|
|
)
|
|
}
|
|
|
|
if newPos+rootBytes > len(buf) {
|
|
return accounts.Account{}, fmt.Errorf("malformed RLP for Account.Root(%x): prefixLength(%d) + dataLength(%d) >= sliceLength(%d)",
|
|
buf[pos],
|
|
newPos-pos, rootBytes, len(buf)-pos,
|
|
)
|
|
}
|
|
|
|
copy(acc.Root[:], buf[newPos:newPos+rootBytes])
|
|
pos = newPos + rootBytes
|
|
}
|
|
|
|
if pos < len(buf) {
|
|
codeHashBytes, s, newPos := decodeLength(buf, pos)
|
|
if s {
|
|
return accounts.Account{}, fmt.Errorf(
|
|
"encoding of Account.CodeHash should be byte array, got RLP struct: %x",
|
|
buf[pos:newPos+codeHashBytes],
|
|
)
|
|
}
|
|
|
|
if codeHashBytes != 32 {
|
|
return accounts.Account{}, fmt.Errorf(
|
|
"encoding of Account.CodeHash should have size 32, got %d",
|
|
codeHashBytes,
|
|
)
|
|
}
|
|
|
|
if newPos+codeHashBytes > len(buf) {
|
|
return accounts.Account{}, fmt.Errorf("malformed RLP for Account.CodeHash(%x): prefixLength(%d) + dataLength(%d) >= sliceLength(%d)",
|
|
buf[pos:newPos+codeHashBytes],
|
|
newPos-pos, codeHashBytes, len(buf)-pos,
|
|
)
|
|
}
|
|
|
|
copy(acc.CodeHash[:], buf[newPos:newPos+codeHashBytes])
|
|
pos = newPos + codeHashBytes
|
|
}
|
|
|
|
if pos < len(buf) {
|
|
storageSizeBytes, s, newPos := decodeLength(buf, pos)
|
|
if s {
|
|
return accounts.Account{}, fmt.Errorf(
|
|
"encoding of Account.StorageSize should be byte array, got RLP struct: %x",
|
|
buf[pos:newPos+storageSizeBytes],
|
|
)
|
|
}
|
|
|
|
if newPos+storageSizeBytes > len(buf) {
|
|
return accounts.Account{}, fmt.Errorf(
|
|
"malformed RLP for Account.StorageSize(%x): prefixLength(%d) + dataLength(%d) >= sliceLength(%d)",
|
|
buf[pos:newPos+storageSizeBytes],
|
|
newPos-pos, storageSizeBytes, len(buf)-pos,
|
|
)
|
|
}
|
|
|
|
var storageSize uint64
|
|
if storageSizeBytes == 0 && newPos == pos {
|
|
storageSize = uint64(buf[newPos])
|
|
// Commented out because of the ineffectual assignment - uncomment if adding more fields
|
|
//pos = newPos + 1
|
|
} else {
|
|
for _, b := range buf[newPos : newPos+storageSizeBytes] {
|
|
storageSize = (storageSize << 8) + uint64(b)
|
|
}
|
|
// Commented out because of the ineffectual assignment - uncomment if adding more fields
|
|
//pos = newPos + storageSizeBytes
|
|
}
|
|
|
|
acc.StorageSize = storageSize
|
|
acc.HasStorageSize = true
|
|
}
|
|
return acc, nil
|
|
}
|
|
|
|
func decodeLength(buffer []byte, pos int) (length int, structure bool, newPos int) {
|
|
switch firstByte := int(buffer[pos]); {
|
|
case firstByte < 128:
|
|
return 0, false, pos
|
|
case firstByte < 184:
|
|
return firstByte - 128, false, pos + 1
|
|
case firstByte < 192:
|
|
// Next byte is the length of the length + 183
|
|
lenEnd := pos + 1 + firstByte - 183
|
|
len := 0
|
|
for i := pos + 1; i < lenEnd; i++ {
|
|
len = (len << 8) + int(buffer[i])
|
|
}
|
|
return len, false, lenEnd
|
|
case firstByte < 248:
|
|
return firstByte - 192, true, pos + 1
|
|
default:
|
|
// Next byte is the length of the length + 247
|
|
lenEnd := pos + 1 + firstByte - 247
|
|
len := 0
|
|
for i := pos + 1; i < lenEnd; i++ {
|
|
len = (len << 8) + int(buffer[i])
|
|
}
|
|
return len, true, lenEnd
|
|
}
|
|
}
|