Skip to content

Commit

Permalink
validate deposit data without global withdrawal credentials
Browse files Browse the repository at this point in the history
  • Loading branch information
jdiuwe committed Dec 16, 2024
1 parent 52b47b3 commit 839c785
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 9 deletions.
43 changes: 35 additions & 8 deletions ethereum/staking/deposit_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (data *DepositData) VerifySignature() (bool, error) {
return sig.Verify(root[:], pubkey), nil
}

// Compute DepositMessage root to be signed
// SigningRoot computes DepositMessage root to be signed
func (data *DepositData) SigningRoot() beaconcommon.Root {
return beaconcommon.ComputeSigningRoot(
data.MessageRoot(),
Expand Down Expand Up @@ -139,7 +139,7 @@ func (data *DepositData) UnmarshalJSON(b []byte) error {
return nil
}

// Return the bls domain for deposit
// DepositDomain returns the bls domain for deposit
func DepositDomain(version beaconcommon.Version) beaconcommon.BLSDomain {
return beaconcommon.ComputeDomain(
beaconcommon.DOMAIN_DEPOSIT,
Expand All @@ -148,12 +148,7 @@ func DepositDomain(version beaconcommon.Version) beaconcommon.BLSDomain {
)
}

func ValidateDepositData(
expectedCreds beaconcommon.Root,
expectedVersion beaconcommon.Version,
expectedAmount beaconcommon.Gwei,
datas ...*DepositData,
) error {
func ValidateDepositData(expectedCreds beaconcommon.Root, expectedVersion beaconcommon.Version, expectedAmount beaconcommon.Gwei, datas ...*DepositData) error {
for i, data := range datas {
tmpData := new(DepositData)
*tmpData = *data
Expand Down Expand Up @@ -187,3 +182,35 @@ func ValidateDepositData(

return nil
}

// ValidateDepositDataWithoutGlobalWithdrawalCredentials validates deposit data without global withdrawal credentials
// this is used in SMS Interop Protocol where withdrawal credentials are not globally set
func ValidateDepositDataWithoutGlobalWithdrawalCredentials(expectedVersion beaconcommon.Version, expectedAmount beaconcommon.Gwei, datas ...*DepositData) error {
for i, data := range datas {
tmpData := new(DepositData)
*tmpData = *data

if (tmpData.Version == beaconcommon.Version{}) {
tmpData.Version = expectedVersion
} else if tmpData.Version != expectedVersion {
return fmt.Errorf("invalid `fork_version` %v at pos %v (expected %v)", data.Version, i, expectedVersion)
}

if tmpData.Amount == beaconcommon.Gwei(0) {
tmpData.Amount = expectedAmount
} else if tmpData.Amount != expectedAmount {
return fmt.Errorf("invalid `amount` %v at pos %v (expected %v)", tmpData.Amount, i, expectedAmount)
}

valid, err := tmpData.VerifySignature()
if err != nil {
return err
}

if !valid {
return fmt.Errorf("invalid `signature` for `pubkey` at pos %v", i)
}
}

return nil
}
97 changes: 96 additions & 1 deletion ethereum/staking/deposit_data_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build !integration
// +build !integration

package staking

Expand Down Expand Up @@ -305,3 +304,99 @@ func TestValidateDepositData(t *testing.T) {
})
}
}

func TestValidateDepositDataWithoutGlobalWithdrawalCredentials(t *testing.T) {
var tests = []struct {
desc string
raw []byte
version beaconcommon.Version
amount beaconcommon.Gwei
expectedErr error
}{
{
desc: "all fields - valid",
version: beaconcommon.Version{0x00, 0x00, 0x00, 0x00},
amount: beaconcommon.Gwei(32000000000),
raw: []byte(`{
"pubkey": "8ab1ee15397f8686d946a84479f58b16ea791a7817e923bc8567e6782f6797ca486b27bfbf1ae4f23d02d5aa54f1b021",
"withdrawal_credentials": "00ba9a5425d1bb1d6af8223664da5ff39ca2ff110f917a2b0dc73b8f206f28a4",
"amount": 32000000000,
"signature": "abe8918b786effebb667e592ef43790b83f54fe4fcc6163f03d1fdb08ff4a75ed67d804659bb4adb44605d00dafa7b910b294e815c6e19166457ee9c22dab6b5fcbc6fd092617e8f3b0a462831cfdda0560fc006569b28d76b5efbd226139674",
"fork_version": "00000000",
"network_name": "mainnet"
}`),
},
{
desc: "all fields - invalid version",
version: beaconcommon.Version{0x10, 0x00, 0x00, 0x20},
amount: beaconcommon.Gwei(32000000000),
raw: []byte(`{
"pubkey": "8ab1ee15397f8686d946a84479f58b16ea791a7817e923bc8567e6782f6797ca486b27bfbf1ae4f23d02d5aa54f1b021",
"withdrawal_credentials": "00ba9a5425d1bb1d6af8223664da5ff39ca2ff110f917a2b0dc73b8f206f28a4",
"amount": 32000000000,
"signature": "abe8918b786effebb667e592ef43790b83f54fe4fcc6163f03d1fdb08ff4a75ed67d804659bb4adb44605d00dafa7b910b294e815c6e19166457ee9c22dab6b5fcbc6fd092617e8f3b0a462831cfdda0560fc006569b28d76b5efbd226139674",
"fork_version": "10000000",
"network_name": "mainnet"
}`),
expectedErr: fmt.Errorf("invalid `fork_version` 0x10000000 at pos 0 (expected 0x10000020)"),
},
{
desc: "all fields - invalid amount",
version: beaconcommon.Version{0x00, 0x00, 0x00, 0x00},
amount: beaconcommon.Gwei(16000000000),
raw: []byte(`{
"pubkey": "8ab1ee15397f8686d946a84479f58b16ea791a7817e923bc8567e6782f6797ca486b27bfbf1ae4f23d02d5aa54f1b021",
"withdrawal_credentials": "00ba9a5425d1bb1d6af8223664da5ff39ca2ff110f917a2b0dc73b8f206f28a4",
"amount": 32000000000,
"signature": "abe8918b786effebb667e592ef43790b83f54fe4fcc6163f03d1fdb08ff4a75ed67d804659bb4adb44605d00dafa7b910b294e815c6e19166457ee9c22dab6b5fcbc6fd092617e8f3b0a462831cfdda0560fc006569b28d76b5efbd226139674",
"fork_version": "00000000",
"network_name": "mainnet"
}`),
expectedErr: fmt.Errorf("invalid `amount` 32000000000 at pos 0 (expected 16000000000)"),
},
{
desc: "all fields - invalid signature",
version: beaconcommon.Version{0x00, 0x00, 0x00, 0x00},
amount: beaconcommon.Gwei(32000000000),
raw: []byte(`{
"pubkey": "8ab1ee15397f8686d946a84479f58b16ea791a7817e923bc8567e6782f6797ca486b27bfbf1ae4f23d02d5aa54f1b021",
"withdrawal_credentials": "00ba9a5425d1bb1d6af8223664da5ff39ca2ff110f917a2b0dc73b8f206f28a4",
"amount": 32000000000,
"signature": "ae6e6a8b2ca8988a870e0ce9f4feff916e0c3bcae32ace785e24ea0b4e2a896c152e12a15405df7caeff7694fa993106025e787ebc9faec11b2ab4a1da1ef4268819606f08dfb78151cd900c82e0c119db8c07d7ee04cf2efe3aaccbfc2ec4a8",
"fork_version": "00000000",
"network_name": "mainnet"
}`),
expectedErr: fmt.Errorf("invalid `signature` for `pubkey` at pos 0"),
},
{
desc: "only pubkey and signature - invalid signature",
version: beaconcommon.Version{0x00, 0x00, 0x00, 0x00},
amount: beaconcommon.Gwei(32000000000),
raw: []byte(`{
"pubkey": "8ab1ee15397f8686d946a84479f58b16ea791a7817e923bc8567e6782f6797ca486b27bfbf1ae4f23d02d5aa54f1b021",
"signature": "ae6e6a8b2ca8988a870e0ce9f4feff916e0c3bcae32ace785e24ea0b4e2a896c152e12a15405df7caeff7694fa993106025e787ebc9faec11b2ab4a1da1ef4268819606f08dfb78151cd900c82e0c119db8c07d7ee04cf2efe3aaccbfc2ec4a8"
}`),
expectedErr: fmt.Errorf("invalid `signature` for `pubkey` at pos 0"),
},
}

for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
data := new(DepositData)
err := json.Unmarshal(tt.raw, data)
require.NoError(t, err)

err = ValidateDepositDataWithoutGlobalWithdrawalCredentials(
tt.version,
tt.amount,
data,
)
if tt.expectedErr == nil {
require.NoError(t, err)
} else {
require.Error(t, err)
assert.Equal(t, tt.expectedErr.Error(), err.Error())
}
})
}
}

0 comments on commit 839c785

Please sign in to comment.