Capella beacon state (#11141)

* fork

* types

* cloners

* getters

* remove CapellaBlind from fork

* hasher

* setters

* spec params, config tests

* generate ssz

* executionPayloadHeaderCapella

* proto state

* BeaconStateCapella SSZ

* saving state

* configfork

* BUILD files

* fix RealPosition

* fix hasher

* SetLatestExecutionPayloadHeaderCapella

* fix error message

* reduce complexity of saveStatesEfficientInternal

* add latestExecutionPayloadHeaderCapella to minimal state

* halway done interface

* remove withdrawal methods

* merge setters

* change signatures for v1 and v2

* fixing errors pt. 1

* paylod_test fixes

* fix everything

* remove unused func

* fix tests

* state_trie_test improvements

* in progress...

* hasher test

* fix configs

* simplify hashing

* Revert "fix configs"

This reverts commit bcae2825fc.

* remove capella from config test

* unify locking

* review

* hashing

* fixes

Co-authored-by: terencechain <terence@prysmaticlabs.com>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
This commit is contained in:
Radosław Kapka
2022-10-12 11:39:19 -05:00
committed by GitHub
parent ce7f042974
commit cafe0bd1f8
65 changed files with 4095 additions and 907 deletions

View File

@@ -17,6 +17,7 @@ go_library(
"//crypto/hash:go_default_library",
"//crypto/hash/htr:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"@com_github_minio_sha256_simd//:go_default_library",
"@com_github_pkg_errors//:go_default_library",
@@ -39,6 +40,8 @@ go_test(
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//crypto/hash:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",

View File

@@ -111,6 +111,16 @@ func (cf *VersionedUnmarshaler) UnmarshalBeaconState(marshaled []byte) (s state.
if err != nil {
return nil, errors.Wrapf(err, "failed to init state trie from state, detected fork=%s", forkName)
}
case version.Capella:
st := &ethpb.BeaconStateCapella{}
err = st.UnmarshalSSZ(marshaled)
if err != nil {
return nil, errors.Wrapf(err, "failed to unmarshal state, detected fork=%s", forkName)
}
s, err = state_native.InitializeFromProtoUnsafeCapella(st)
if err != nil {
return nil, errors.Wrapf(err, "failed to init state trie from state, detected fork=%s", forkName)
}
default:
return nil, fmt.Errorf("unable to initialize BeaconState for fork version=%s", forkName)
}

View File

@@ -55,6 +55,7 @@ func TestByState(t *testing.T) {
}()
bc := params.BeaconConfig()
altairSlot, err := slots.EpochStart(bc.AltairForkEpoch)
require.NoError(t, err)
bellaSlot, err := slots.EpochStart(bc.BellatrixForkEpoch)
require.NoError(t, err)
cases := []struct {
@@ -109,8 +110,10 @@ func stateForVersion(v int) (state.BeaconState, error) {
return util.NewBeaconStateAltair()
case version.Bellatrix:
return util.NewBeaconStateBellatrix()
case version.Capella:
return util.NewBeaconStateCapella()
default:
return nil, fmt.Errorf("unrecognoized version %d", v)
return nil, fmt.Errorf("unrecognized version %d", v)
}
}

View File

@@ -8,6 +8,7 @@ import (
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
"github.com/prysmaticlabs/prysm/v3/crypto/hash"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
)
@@ -117,6 +118,31 @@ func TransactionsRoot(txs [][]byte) ([32]byte, error) {
return MixInLength(bytesRoot, bytesRootBufRoot), nil
}
// WithdrawalSliceRoot computes the HTR of a slice of withdrawals.
// The limit parameter is used as input to the bitwise merkleization algorithm.
func WithdrawalSliceRoot(hasher HashFn, withdrawals []*enginev1.Withdrawal, limit uint64) ([32]byte, error) {
roots := make([][32]byte, len(withdrawals))
for i := 0; i < len(withdrawals); i++ {
r, err := withdrawalRoot(hasher, withdrawals[i])
if err != nil {
return [32]byte{}, err
}
roots[i] = r
}
bytesRoot, err := BitwiseMerkleize(hasher, roots, uint64(len(roots)), limit)
if err != nil {
return [32]byte{}, errors.Wrap(err, "could not compute merkleization")
}
bytesRootBuf := new(bytes.Buffer)
if err := binary.Write(bytesRootBuf, binary.LittleEndian, uint64(len(withdrawals))); err != nil {
return [32]byte{}, errors.Wrap(err, "could not marshal length")
}
bytesRootBufRoot := make([]byte, 32)
copy(bytesRootBufRoot, bytesRootBuf.Bytes())
return MixInLength(bytesRoot, bytesRootBufRoot), nil
}
func transactionRoot(tx []byte) ([32]byte, error) {
hasher := hash.CustomSHA256Hasher()
chunkedRoots, err := PackByChunk([][]byte{tx})
@@ -137,3 +163,17 @@ func transactionRoot(tx []byte) ([32]byte, error) {
copy(bytesRootBufRoot, bytesRootBuf.Bytes())
return MixInLength(bytesRoot, bytesRootBufRoot), nil
}
func withdrawalRoot(hasher HashFn, w *enginev1.Withdrawal) ([32]byte, error) {
fieldRoots := make([][32]byte, 3)
if w != nil {
indexBuf := make([]byte, 32)
binary.LittleEndian.PutUint64(indexBuf, w.WithdrawalIndex)
fieldRoots[0] = bytesutil.ToBytes32(indexBuf)
fieldRoots[1] = bytesutil.ToBytes32(w.ExecutionAddress)
amountBuf := make([]byte, 8)
binary.LittleEndian.PutUint64(amountBuf, w.Amount)
fieldRoots[2] = bytesutil.ToBytes32(amountBuf)
}
return BitwiseMerkleize(hasher, fieldRoots, uint64(len(fieldRoots)), uint64(len(fieldRoots)))
}

View File

@@ -2,11 +2,14 @@ package ssz_test
import (
"reflect"
"strconv"
"testing"
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
"github.com/prysmaticlabs/prysm/v3/crypto/hash"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v3/encoding/ssz"
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v3/testing/assert"
"github.com/prysmaticlabs/prysm/v3/testing/require"
@@ -123,6 +126,78 @@ func TestTransactionsRoot(t *testing.T) {
}
}
func TestWithdrawalQueueRoot(t *testing.T) {
const limit = 16
tests := []struct {
name string
ws []*enginev1.Withdrawal
want [32]byte
wantErr bool
}{
{
name: "nil",
ws: nil,
want: [32]byte{121, 41, 48, 187, 213, 186, 172, 67, 188, 199, 152, 238, 73, 170, 129, 133, 239, 118, 187, 59, 68, 186, 98, 185, 29, 134, 174, 86, 158, 75, 181, 53},
},
{
name: "empty",
ws: []*enginev1.Withdrawal{},
want: [32]byte{121, 41, 48, 187, 213, 186, 172, 67, 188, 199, 152, 238, 73, 170, 129, 133, 239, 118, 187, 59, 68, 186, 98, 185, 29, 134, 174, 86, 158, 75, 181, 53},
},
{
name: "one",
ws: []*enginev1.Withdrawal{{
WithdrawalIndex: 123,
ExecutionAddress: bytesutil.PadTo([]byte("address"), 20),
Amount: 123,
}},
want: [32]byte{242, 16, 137, 49, 219, 35, 236, 39, 191, 96, 52, 104, 35, 98, 250, 177, 189, 65, 113, 185, 51, 107, 115, 26, 229, 168, 40, 189, 200, 152, 225, 24},
},
{
name: "max withdrawals",
ws: func() []*enginev1.Withdrawal {
var ws []*enginev1.Withdrawal
for i := 0; i < limit; i++ {
ws = append(ws, &enginev1.Withdrawal{
WithdrawalIndex: uint64(i),
ExecutionAddress: bytesutil.PadTo([]byte("address"+strconv.Itoa(i)), 20),
Amount: uint64(i),
})
}
return ws
}(),
want: [32]byte{252, 43, 118, 69, 222, 73, 222, 196, 52, 234, 247, 49, 98, 54, 19, 146, 204, 246, 12, 139, 179, 167, 117, 216, 77, 159, 84, 154, 9, 103, 28, 226},
},
{
name: "exceed max withdrawals",
ws: func() []*enginev1.Withdrawal {
var ws []*enginev1.Withdrawal
for i := 0; i < limit+1; i++ {
ws = append(ws, &enginev1.Withdrawal{
WithdrawalIndex: uint64(i),
ExecutionAddress: bytesutil.PadTo([]byte("address"+strconv.Itoa(i)), 20),
Amount: uint64(i),
})
}
return ws
}(),
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ssz.WithdrawalSliceRoot(hash.CustomSHA256Hasher(), tt.ws, limit)
if (err != nil) != tt.wantErr {
t.Errorf("error = %v, wantErr = %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("got = %v, want %v", got, tt.want)
}
})
}
}
func TestPackByChunk_SingleList(t *testing.T) {
tests := []struct {
name string