Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ func wireCoreWorkflow(ctx context.Context, life *lifecycle.Manager, conf Config,
) error {
// Convert and prep public keys and public shares
var (
builderRegistrations []clusterpkg.BuilderRegistration
builderRegistrations []*eth2api.VersionedSignedValidatorRegistration
eth2Pubkeys []eth2p0.BLSPubKey
pubshares []eth2p0.BLSPubKey
allPubSharesByKey = make(map[core.PubKey]map[int]tbls.PublicKey) // map[pubkey]map[shareIdx]pubshare
Expand Down Expand Up @@ -449,12 +449,12 @@ func wireCoreWorkflow(ctx context.Context, life *lifecycle.Manager, conf Config,
allPubSharesByKey[corePubkey] = allPubShares
feeRecipientAddrByCorePubkey[corePubkey] = val.GetFeeRecipientAddress()

var builderRegistration clusterpkg.BuilderRegistration
var builderRegistration eth2api.VersionedSignedValidatorRegistration
if err := json.Unmarshal(val.GetBuilderRegistrationJson(), &builderRegistration); err != nil {
return errors.Wrap(err, "unmarshal builder registration")
}

builderRegistrations = append(builderRegistrations, builderRegistration)
builderRegistrations = append(builderRegistrations, &builderRegistration)
}

peers, err := manifest.ClusterPeers(cluster)
Expand Down
34 changes: 3 additions & 31 deletions core/scheduler/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import (
"time"

eth2api "github.com/attestantio/go-eth2-client/api"
eth2v1 "github.com/attestantio/go-eth2-client/api/v1"
eth2spec "github.com/attestantio/go-eth2-client/spec"
eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/jonboulle/clockwork"
"github.com/stretchr/testify/require"
Expand All @@ -24,7 +22,6 @@ import (
"github.com/obolnetwork/charon/app/featureset"
"github.com/obolnetwork/charon/app/log"
"github.com/obolnetwork/charon/app/z"
"github.com/obolnetwork/charon/cluster"
"github.com/obolnetwork/charon/core"
)

Expand All @@ -38,7 +35,7 @@ type delayFunc func(duty core.Duty, deadline time.Time) <-chan time.Time
type schedSlotFunc func(ctx context.Context, slot core.Slot)

// NewForT returns a new scheduler for testing using a fake clock.
func NewForT(t *testing.T, clock clockwork.Clock, delayFunc delayFunc, builderRegistrations []cluster.BuilderRegistration,
func NewForT(t *testing.T, clock clockwork.Clock, delayFunc delayFunc, builderRegistrations []*eth2api.VersionedSignedValidatorRegistration,
eth2Cl eth2wrap.Client, schedSlotFunc schedSlotFunc, builderEnabled bool,
) *Scheduler {
t.Helper()
Expand All @@ -54,35 +51,10 @@ func NewForT(t *testing.T, clock clockwork.Clock, delayFunc delayFunc, builderRe
}

// New returns a new scheduler.
func New(builderRegistrations []cluster.BuilderRegistration, eth2Cl eth2wrap.Client, builderEnabled bool) (*Scheduler, error) {
registrations := make([]*eth2api.VersionedSignedValidatorRegistration, 0, len(builderRegistrations))

for _, builderRegistration := range builderRegistrations {
regMessage := &eth2v1.ValidatorRegistration{
Timestamp: builderRegistration.Message.Timestamp,
GasLimit: uint64(builderRegistration.Message.GasLimit),
}

copy(regMessage.FeeRecipient[:], builderRegistration.Message.FeeRecipient)
copy(regMessage.Pubkey[:], builderRegistration.Message.PubKey)

var signature eth2p0.BLSSignature
copy(signature[:], builderRegistration.Signature)

registration := &eth2v1.SignedValidatorRegistration{
Message: regMessage,
Signature: signature,
}

registrations = append(registrations, &eth2api.VersionedSignedValidatorRegistration{
Version: eth2spec.BuilderVersionV1,
V1: registration,
})
}

func New(builderRegistrations []*eth2api.VersionedSignedValidatorRegistration, eth2Cl eth2wrap.Client, builderEnabled bool) (*Scheduler, error) {
return &Scheduler{
eth2Cl: eth2Cl,
builderRegistrations: registrations,
builderRegistrations: builderRegistrations,
quit: make(chan struct{}),
duties: make(map[core.Duty]core.DutyDefinitionSet),
dutiesByEpoch: make(map[uint64][]core.Duty),
Expand Down
44 changes: 25 additions & 19 deletions core/scheduler/scheduler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

eth2api "github.com/attestantio/go-eth2-client/api"
eth2v1 "github.com/attestantio/go-eth2-client/api/v1"
eth2spec "github.com/attestantio/go-eth2-client/spec"
eth2p0 "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/jonboulle/clockwork"
"github.com/stretchr/testify/require"
Expand All @@ -23,7 +24,6 @@ import (
"github.com/obolnetwork/charon/app/eth2wrap"
"github.com/obolnetwork/charon/app/expbackoff"
"github.com/obolnetwork/charon/app/featureset"
"github.com/obolnetwork/charon/cluster"
"github.com/obolnetwork/charon/core"
"github.com/obolnetwork/charon/core/scheduler"
"github.com/obolnetwork/charon/testutil"
Expand All @@ -50,24 +50,30 @@ func TestIntegration(t *testing.T) {
require.NoError(t, err)

// Builder registrations for mainnet validators
valRegs := []cluster.BuilderRegistration{
valRegs := []*eth2api.VersionedSignedValidatorRegistration{
{
Message: cluster.Registration{
FeeRecipient: beaconmock.MustBytesFromHex("0x388c818ca8b9251b393131c08a736a67ccb19297"),
GasLimit: 36000000,
Timestamp: time.Unix(1606824023, 0),
PubKey: beaconmock.MustBytesFromHex("0x8f4ef114368b24863b369bbf597ace2eab5f77e4726f7931f988ba757fbd1dffd2f44270bbed42d5dfa72e10c79dcb6d"),
Version: eth2spec.BuilderVersionV1,
V1: &eth2v1.SignedValidatorRegistration{
Message: &eth2v1.ValidatorRegistration{
FeeRecipient: beaconmock.MustExecutionAddress("0x388c818ca8b9251b393131c08a736a67ccb19297"),
GasLimit: 36000000,
Timestamp: time.Unix(1606824023, 0),
Pubkey: beaconmock.MustBLSPubKey("0x8f4ef114368b24863b369bbf597ace2eab5f77e4726f7931f988ba757fbd1dffd2f44270bbed42d5dfa72e10c79dcb6d"),
},
Signature: beaconmock.MustBLSSignature("0xacc05896c51c57177306d3f1eb9de64a6a1fb50b88cf4afe276a3c53673ce1227af2337ef607c769624f45472968cbde15f87c355dfa43bca81c882ea2d89ad301a4ce1c4169874bf9f9b1bafe70838519af34741d774930edbad40a7fefc7e6"),
},
Signature: beaconmock.MustBytesFromHex("0xacc05896c51c57177306d3f1eb9de64a6a1fb50b88cf4afe276a3c53673ce1227af2337ef607c769624f45472968cbde15f87c355dfa43bca81c882ea2d89ad301a4ce1c4169874bf9f9b1bafe70838519af34741d774930edbad40a7fefc7e6"),
},
{
Message: cluster.Registration{
FeeRecipient: beaconmock.MustBytesFromHex("0x388c818ca8b9251b393131c08a736a67ccb19297"),
GasLimit: 36000000,
Timestamp: time.Unix(1606824023, 0),
PubKey: beaconmock.MustBytesFromHex("0xa0753f1bdb24b39441aee027a44af9ec5117a572678aa987944d26d92d332789208cf0733ca99f1d96fae50f7e889c22"),
Version: eth2spec.BuilderVersionV1,
V1: &eth2v1.SignedValidatorRegistration{
Message: &eth2v1.ValidatorRegistration{
FeeRecipient: beaconmock.MustExecutionAddress("0x388c818ca8b9251b393131c08a736a67ccb19297"),
GasLimit: 36000000,
Timestamp: time.Unix(1606824023, 0),
Pubkey: beaconmock.MustBLSPubKey("0xa0753f1bdb24b39441aee027a44af9ec5117a572678aa987944d26d92d332789208cf0733ca99f1d96fae50f7e889c22"),
},
Signature: beaconmock.MustBLSSignature("0x8de77931277c745c05879db7e57853a07c5d3bd45d4d5757f55bdf05de3266c6ddac81b3b0316552b2ceb77405aa5c701311db3cd6a6ca176c792a9f1814ede89907b8cd05061a15bfb6618c8390577b349b3b4a75693311f1c638f53c186c58"),
},
Signature: beaconmock.MustBytesFromHex("0x8de77931277c745c05879db7e57853a07c5d3bd45d4d5757f55bdf05de3266c6ddac81b3b0316552b2ceb77405aa5c701311db3cd6a6ca176c792a9f1814ede89907b8cd05061a15bfb6618c8390577b349b3b4a75693311f1c638f53c186c58"),
},
}

Expand Down Expand Up @@ -599,11 +605,11 @@ func TestSubmitValidatorRegistrations(t *testing.T) {

// Verify registration data matches BuilderRegistrationSetA
for i, reg := range registrations {
require.Equal(t, valRegs[i].Message.GasLimit, int(reg.V1.Message.GasLimit))
require.Equal(t, valRegs[i].Message.Timestamp.Unix(), reg.V1.Message.Timestamp.Unix())
require.Equal(t, valRegs[i].Message.FeeRecipient, reg.V1.Message.FeeRecipient[:])
require.Equal(t, valRegs[i].Message.PubKey, reg.V1.Message.Pubkey[:])
require.Equal(t, valRegs[i].Signature, reg.V1.Signature[:])
require.Equal(t, valRegs[i].V1.Message.GasLimit, reg.V1.Message.GasLimit)
require.Equal(t, valRegs[i].V1.Message.Timestamp.Unix(), reg.V1.Message.Timestamp.Unix())
require.Equal(t, valRegs[i].V1.Message.FeeRecipient, reg.V1.Message.FeeRecipient)
require.Equal(t, valRegs[i].V1.Message.Pubkey, reg.V1.Message.Pubkey)
require.Equal(t, valRegs[i].V1.Signature, reg.V1.Signature)
}
}

Expand Down
106 changes: 77 additions & 29 deletions testutil/beaconmock/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (
"github.com/obolnetwork/charon/app/errors"
"github.com/obolnetwork/charon/app/eth2wrap"
"github.com/obolnetwork/charon/app/log"
"github.com/obolnetwork/charon/cluster"
"github.com/obolnetwork/charon/core"
"github.com/obolnetwork/charon/testutil"
)
Expand Down Expand Up @@ -145,35 +144,39 @@ var ValidatorSetA = ValidatorSet{
},
}

// mustBuilderRegistration creates a builder registration, panicking on error.
func mustBuilderRegistration(feeRecipient, pubkey, signature string) *eth2api.VersionedSignedValidatorRegistration {
return &eth2api.VersionedSignedValidatorRegistration{
Version: eth2spec.BuilderVersionV1,
V1: &eth2v1.SignedValidatorRegistration{
Message: &eth2v1.ValidatorRegistration{
FeeRecipient: MustExecutionAddress(feeRecipient),
GasLimit: 30000000,
Timestamp: time.Unix(1609459200, 0), // 2021-01-01 00:00:00 UTC
Pubkey: MustBLSPubKey(pubkey),
},
Signature: MustBLSSignature(signature),
},
}
}

// BuilderRegistrationSetA defines a set of 3 deterministic builder registrations for ValidatorSetA.
var BuilderRegistrationSetA = []cluster.BuilderRegistration{
{
Message: cluster.Registration{
FeeRecipient: MustBytesFromHex("0x0000000000000000000000000000000000000001"),
GasLimit: 30000000,
Timestamp: time.Unix(1609459200, 0), // 2021-01-01 00:00:00 UTC
PubKey: MustBytesFromHex("0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490"),
},
Signature: MustBytesFromHex("0xa1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6"),
},
{
Message: cluster.Registration{
FeeRecipient: MustBytesFromHex("0x0000000000000000000000000000000000000002"),
GasLimit: 30000000,
Timestamp: time.Unix(1609459200, 0), // 2021-01-01 00:00:00 UTC
PubKey: MustBytesFromHex("0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea"),
},
Signature: MustBytesFromHex("0xb2b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6"),
},
{
Message: cluster.Registration{
FeeRecipient: MustBytesFromHex("0x0000000000000000000000000000000000000003"),
GasLimit: 30000000,
Timestamp: time.Unix(1609459200, 0), // 2021-01-01 00:00:00 UTC
PubKey: MustBytesFromHex("0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76"),
},
Signature: MustBytesFromHex("0xc3b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6"),
},
var BuilderRegistrationSetA = []*eth2api.VersionedSignedValidatorRegistration{
mustBuilderRegistration(
"0x0000000000000000000000000000000000000001",
"0x914cff835a769156ba43ad50b931083c2dadd94e8359ce394bc7a3e06424d0214922ddf15f81640530b9c25c0bc0d490",
"0xa1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6",
),
mustBuilderRegistration(
"0x0000000000000000000000000000000000000002",
"0x8dae41352b69f2b3a1c0b05330c1bf65f03730c520273028864b11fcb94d8ce8f26d64f979a0ee3025467f45fd2241ea",
"0xb2b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6",
),
mustBuilderRegistration(
"0x0000000000000000000000000000000000000003",
"0x8ee91545183c8c2db86633626f5074fd8ef93c4c9b7a2879ad1768f600c5b5906c3af20d47de42c3b032956fa8db1a76",
"0xc3b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6",
),
}

// WithValidatorSet configures the mock with the provided validator set.
Expand Down Expand Up @@ -802,6 +805,36 @@ func mustPKFromHex(pubkeyHex string) eth2p0.BLSPubKey {
return resp
}

// must20ByteArray converts a byte slice to a 20-byte array, panicking if wrong size.
func must20ByteArray(b []byte) [20]byte {
if len(b) != 20 {
panic(fmt.Sprintf("expected 20 bytes, got %d", len(b)))
}
var arr [20]byte
copy(arr[:], b)
return arr
}

// must48ByteArray converts a byte slice to a 48-byte array, panicking if wrong size.
func must48ByteArray(b []byte) [48]byte {
if len(b) != 48 {
panic(fmt.Sprintf("expected 48 bytes, got %d", len(b)))
}
var arr [48]byte
copy(arr[:], b)
return arr
}

// must96ByteArray converts a byte slice to a 96-byte array, panicking if wrong size.
func must96ByteArray(b []byte) [96]byte {
if len(b) != 96 {
panic(fmt.Sprintf("expected 96 bytes, got %d", len(b)))
}
var arr [96]byte
copy(arr[:], b)
return arr
}

// MustBytesFromHex converts a hex string to bytes, panicking on error.
func MustBytesFromHex(hexStr string) []byte {
hexStr = strings.TrimPrefix(hexStr, "0x")
Expand All @@ -813,3 +846,18 @@ func MustBytesFromHex(hexStr string) []byte {

return b
}

// MustExecutionAddress converts a hex string to an execution address (20 bytes), panicking on error.
func MustExecutionAddress(hexStr string) [20]byte {
return must20ByteArray(MustBytesFromHex(hexStr))
}

// MustBLSPubKey converts a hex string to a BLS public key (48 bytes), panicking on error.
func MustBLSPubKey(hexStr string) [48]byte {
return must48ByteArray(MustBytesFromHex(hexStr))
}

// MustBLSSignature converts a hex string to a BLS signature (96 bytes), panicking on error.
func MustBLSSignature(hexStr string) [96]byte {
return must96ByteArray(MustBytesFromHex(hexStr))
}
Loading