mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-03 08:37:37 +00:00
2dfe291cf9
* initial commit wip * setting protos for fee recipient * updating proto based on specs * updating apimiddleware * generated APIs * updating proto to fit spec * fixing naming of fields * fixing endpoint_factory and associated structs * fixing imports * adding in custom http types to grpc gateway * adding import options * changing package option * still testing protos * adding to bazel * testing dependency changes * more tests * more tests * more tests * more tests * more tests * more tests * testing changing repo dep * testing deps * testing deps * testing deps * testing deps * testing deps * testing deps * reverting * testing import * testing bazel * bazel test * testing * testing * testing import * updating generated proto code * wip set fee recipient by pubkey * adding list fee recipient logic * fixing thrown error * fixing bug with API * fee recipient delete function * updating generated proto logic * fixing deposit api and adding postman tests * fixing proto imports * fixing unit tests and checksums * fixing test * adding unit tests * fixing bazel * Update validator/rpc/standard_api.go Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> * Update validator/rpc/standard_api.go Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> * resolving review comments * fixing return * Update config/validator/service/proposer-settings.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Update validator/rpc/standard_api.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * Update validator/rpc/standard_api.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * updating proto * updating message name * fixing imports * updating based on review comments * adding middleware unit tests * capitalizing errors * using error instead of errorf * fixing missed unit test variable rename * fixing format variable * fixing unit test * Update validator/rpc/standard_api.go * Update validator/rpc/standard_api.go Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> Co-authored-by: Radosław Kapka <rkapka@wp.pl> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
180 lines
4.6 KiB
Go
180 lines
4.6 KiB
Go
package apimiddleware
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"fmt"
|
|
"math/big"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
"github.com/pkg/errors"
|
|
"github.com/wealdtech/go-bytesutil"
|
|
)
|
|
|
|
// processField calls each processor function on any field that has the matching tag set.
|
|
// It is a recursive function.
|
|
func processField(s interface{}, processors []fieldProcessor) error {
|
|
kind := reflect.TypeOf(s).Kind()
|
|
if kind != reflect.Ptr && kind != reflect.Slice && kind != reflect.Array {
|
|
return fmt.Errorf("processing fields of kind '%v' is unsupported", kind)
|
|
}
|
|
|
|
t := reflect.TypeOf(s).Elem()
|
|
v := reflect.Indirect(reflect.ValueOf(s))
|
|
|
|
for i := 0; i < t.NumField(); i++ {
|
|
switch v.Field(i).Kind() {
|
|
case reflect.Slice:
|
|
sliceElem := t.Field(i).Type.Elem()
|
|
kind := sliceElem.Kind()
|
|
// Recursively process slices to struct pointers.
|
|
switch {
|
|
case kind == reflect.Ptr && sliceElem.Elem().Kind() == reflect.Struct:
|
|
for j := 0; j < v.Field(i).Len(); j++ {
|
|
if err := processField(v.Field(i).Index(j).Interface(), processors); err != nil {
|
|
return errors.Wrapf(err, "could not process field '%s'", t.Field(i).Name)
|
|
}
|
|
}
|
|
// Process each string in string slices.
|
|
case kind == reflect.String:
|
|
for _, proc := range processors {
|
|
_, hasTag := t.Field(i).Tag.Lookup(proc.tag)
|
|
if !hasTag {
|
|
continue
|
|
}
|
|
for j := 0; j < v.Field(i).Len(); j++ {
|
|
if err := proc.f(v.Field(i).Index(j)); err != nil {
|
|
return errors.Wrapf(err, "could not process field '%s'", t.Field(i).Name)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Recursively process struct pointers.
|
|
case reflect.Ptr:
|
|
if v.Field(i).Elem().Kind() == reflect.Struct {
|
|
if err := processField(v.Field(i).Interface(), processors); err != nil {
|
|
return errors.Wrapf(err, "could not process field '%s'", t.Field(i).Name)
|
|
}
|
|
}
|
|
default:
|
|
field := t.Field(i)
|
|
for _, proc := range processors {
|
|
if _, hasTag := field.Tag.Lookup(proc.tag); hasTag {
|
|
if err := proc.f(v.Field(i)); err != nil {
|
|
return errors.Wrapf(err, "could not process field '%s'", t.Field(i).Name)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func hexToBase64Processor(v reflect.Value) error {
|
|
if v.String() == "0x" {
|
|
v.SetString("")
|
|
return nil
|
|
}
|
|
b, err := bytesutil.FromHexString(v.String())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
v.SetString(base64.StdEncoding.EncodeToString(b))
|
|
return nil
|
|
}
|
|
|
|
func base64ToHexProcessor(v reflect.Value) error {
|
|
if v.String() == "" {
|
|
// Empty hex values are represented as "0x".
|
|
v.SetString("0x")
|
|
return nil
|
|
}
|
|
b, err := base64.StdEncoding.DecodeString(v.String())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
v.SetString(hexutil.Encode(b))
|
|
return nil
|
|
}
|
|
|
|
func base64ToChecksumAddressProcessor(v reflect.Value) error {
|
|
if v.String() == "" {
|
|
// Empty hex values are represented as "0x".
|
|
v.SetString("0x")
|
|
return nil
|
|
}
|
|
b, err := base64.StdEncoding.DecodeString(v.String())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
v.SetString(common.BytesToAddress(b).Hex())
|
|
return nil
|
|
}
|
|
|
|
func base64ToUint256Processor(v reflect.Value) error {
|
|
if v.String() == "" {
|
|
return nil
|
|
}
|
|
littleEndian, err := base64.StdEncoding.DecodeString(v.String())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(littleEndian) != 32 {
|
|
return errors.New("invalid length for Uint256")
|
|
}
|
|
|
|
// Integers are stored as little-endian, but
|
|
// big.Int expects big-endian. So we need to reverse
|
|
// the byte order before decoding.
|
|
var bigEndian [32]byte
|
|
for i := 0; i < len(littleEndian); i++ {
|
|
bigEndian[i] = littleEndian[len(littleEndian)-1-i]
|
|
}
|
|
var uint256 big.Int
|
|
uint256.SetBytes(bigEndian[:])
|
|
v.SetString(uint256.String())
|
|
return nil
|
|
}
|
|
|
|
func uint256ToBase64Processor(v reflect.Value) error {
|
|
if v.String() == "" {
|
|
return nil
|
|
}
|
|
uint256, ok := new(big.Int).SetString(v.String(), 10)
|
|
if !ok {
|
|
return fmt.Errorf("could not parse Uint256")
|
|
}
|
|
bigEndian := uint256.Bytes()
|
|
if len(bigEndian) > 32 {
|
|
return fmt.Errorf("number too big for Uint256")
|
|
}
|
|
|
|
// Integers are stored as little-endian, but
|
|
// big.Int gives big-endian. So we need to reverse
|
|
// the byte order before encoding.
|
|
var littleEndian [32]byte
|
|
for i := 0; i < len(bigEndian); i++ {
|
|
littleEndian[i] = bigEndian[len(bigEndian)-1-i]
|
|
}
|
|
v.SetString(base64.StdEncoding.EncodeToString(littleEndian[:]))
|
|
return nil
|
|
}
|
|
|
|
func enumToLowercaseProcessor(v reflect.Value) error {
|
|
v.SetString(strings.ToLower(v.String()))
|
|
return nil
|
|
}
|
|
|
|
func timeToUnixProcessor(v reflect.Value) error {
|
|
t, err := time.Parse(time.RFC3339, v.String())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
v.SetString(strconv.FormatUint(uint64(t.Unix()), 10))
|
|
return nil
|
|
}
|