Files
ethdo/cmd/validator/depositdata/output.go
2025-01-31 17:04:50 +00:00

194 lines
5.8 KiB
Go

// Copyright © 2019 - 2022 Weald Technology Trading.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package depositdata
import (
"fmt"
"strings"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/pkg/errors"
)
type dataOut struct {
format string
account string
path string
validatorPubKey *spec.BLSPubKey
withdrawalCredentials []byte
amount spec.Gwei
signature *spec.BLSSignature
forkVersion *spec.Version
depositDataRoot *spec.Root
depositMessageRoot *spec.Root
}
func output(data []*dataOut) (string, error) {
outputs := make([]string, 0)
for _, datum := range data {
if datum == nil {
continue
}
var output string
var err error
switch datum.format {
case "raw":
output, err = validatorDepositDataOutputRaw(datum)
case "launchpad":
output, err = validatorDepositDataOutputLaunchpad(datum)
default:
output, err = validatorDepositDataOutputJSON(datum)
}
if err != nil {
return "", err
}
outputs = append(outputs, output)
}
return fmt.Sprintf("[%s]", strings.Join(outputs, ",")), nil
}
func validatorDepositDataOutputRaw(datum *dataOut) (string, error) {
if datum.validatorPubKey == nil {
return "", errors.New("validator public key required")
}
if len(datum.withdrawalCredentials) != 32 {
return "", errors.New("withdrawal credentials must be 32 bytes")
}
if datum.amount == 0 {
return "", errors.New("missing amount")
}
if datum.signature == nil {
return "", errors.New("signature required")
}
if datum.depositDataRoot == nil {
return "", errors.New("deposit data root required")
}
output := fmt.Sprintf(
`"`+
// Function signature.
"0x22895118"+
// Pointer to validator public key.
"0000000000000000000000000000000000000000000000000000000000000080"+
// Pointer to withdrawal credentials.
"00000000000000000000000000000000000000000000000000000000000000e0"+
// Pointer to validator signature.
"0000000000000000000000000000000000000000000000000000000000000120"+
// Deposit data root.
"%x"+
// Validator public key (padded).
"0000000000000000000000000000000000000000000000000000000000000030"+
"%x00000000000000000000000000000000"+
// Withdrawal credentials.
"0000000000000000000000000000000000000000000000000000000000000020"+
"%x"+
// Deposit signature.
"0000000000000000000000000000000000000000000000000000000000000060"+
"%x"+
`"`,
*datum.depositDataRoot,
*datum.validatorPubKey,
datum.withdrawalCredentials,
*datum.signature,
)
return output, nil
}
func validatorDepositDataOutputLaunchpad(datum *dataOut) (string, error) {
// Map of fork version to network name.
forkVersionMap := map[spec.Version]string{
[4]byte{0x00, 0x00, 0x00, 0x00}: "mainnet",
[4]byte{0x00, 0x00, 0x20, 0x09}: "pyrmont",
[4]byte{0x00, 0x00, 0x10, 0x20}: "goerli",
[4]byte{0x80, 0x00, 0x00, 0x69}: "ropsten",
[4]byte{0x90, 0x00, 0x00, 0x69}: "sepolia",
[4]byte{0x01, 0x01, 0x70, 0x00}: "holesky",
}
if datum.validatorPubKey == nil {
return "", errors.New("validator public key required")
}
if len(datum.withdrawalCredentials) != 32 {
return "", errors.New("withdrawal credentials must be 32 bytes")
}
if datum.amount == 0 {
return "", errors.New("missing amount")
}
if datum.signature == nil {
return "", errors.New("signature required")
}
if datum.depositMessageRoot == nil {
return "", errors.New("deposit message root required")
}
if datum.depositDataRoot == nil {
return "", errors.New("deposit data root required")
}
networkName := "unknown"
if network, exists := forkVersionMap[*datum.forkVersion]; exists {
networkName = network
}
output := fmt.Sprintf(`{"pubkey":"%x","withdrawal_credentials":"%x","amount":%d,"signature":"%x","deposit_message_root":"%x","deposit_data_root":"%x","fork_version":"%x","network_name":"%s","deposit_cli_version":"2.7.0"}`,
*datum.validatorPubKey,
datum.withdrawalCredentials,
datum.amount,
*datum.signature,
*datum.depositMessageRoot,
*datum.depositDataRoot,
*datum.forkVersion,
networkName,
)
return output, nil
}
func validatorDepositDataOutputJSON(datum *dataOut) (string, error) {
if datum.account == "" {
return "", errors.New("missing account")
}
if datum.validatorPubKey == nil {
return "", errors.New("validator public key required")
}
if len(datum.withdrawalCredentials) != 32 {
return "", errors.New("withdrawal credentials must be 32 bytes")
}
if datum.signature == nil {
return "", errors.New("signature required")
}
if datum.amount == 0 {
return "", errors.New("missing amount")
}
if datum.depositDataRoot == nil {
return "", errors.New("deposit data root required")
}
if datum.depositMessageRoot == nil {
return "", errors.New("deposit message root required")
}
if datum.forkVersion == nil {
return "", errors.New("fork version required")
}
output := fmt.Sprintf(`{"name":"Deposit for %s","account":"%s","pubkey":"%#x","withdrawal_credentials":"%#x","signature":"%#x","amount":%d,"deposit_data_root":"%#x","deposit_message_root":"%#x","fork_version":"%#x","version":3}`,
datum.account,
datum.account,
*datum.validatorPubKey,
datum.withdrawalCredentials,
*datum.signature,
datum.amount,
*datum.depositDataRoot,
*datum.depositMessageRoot,
*datum.forkVersion,
)
return output, nil
}