├── .github ├── dependabot.yaml ├── pull_request_template.md └── workflows │ ├── checks.yml │ └── release.yml ├── .gitignore ├── .golangci.yaml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── bls ├── bls.go ├── bls_fuzz_test.go └── bls_test.go ├── fuzzing └── common.go ├── go.mod ├── go.sum ├── scripts └── fuzz.sh ├── ssz ├── ssz.go ├── ssz_fuzz_test.go └── ssz_test.go ├── staticcheck.conf ├── testdata ├── deposit │ ├── README.md │ └── case0.json ├── depositdata_case0.json ├── eth1data_case0.json ├── executionpayload │ ├── README.md │ ├── bellatrix-case0.json │ ├── capella-case0.json │ └── deneb-case0.json ├── kiln-signedBlindedBeaconBlock-899730.json ├── signed-beacon-block-case0.json ├── signed-beacon-block-case1.json ├── signed-beacon-block-case2.json ├── signed-beacon-block-case3.json ├── signed-beacon-block-case4.json └── signed-blinded-beacon-block-with-deposit.json ├── types ├── .gitignore ├── consts.go └── u256str.go └── utils ├── utils.go ├── utils_fuzz_test.go └── utils_test.go /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | # Please see the documentation for all configuration options: 2 | # https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 3 | 4 | version: 2 5 | updates: 6 | - package-ecosystem: gomod 7 | directory: / 8 | schedule: 9 | interval: daily 10 | reviewers: 11 | - "metachris" 12 | - "jtraglia" -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## 📝 Summary 2 | 3 | 4 | 5 | ## ⛱ Motivation and Context 6 | 7 | 8 | 9 | ## 📚 References 10 | 11 | 12 | 13 | --- 14 | 15 | ## ✅ I have run these commands 16 | 17 | * [ ] `make lint` 18 | * [ ] `make test` 19 | * [ ] `go mod tidy` 20 | -------------------------------------------------------------------------------- /.github/workflows/checks.yml: -------------------------------------------------------------------------------- 1 | name: Checks 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | jobs: 10 | test: 11 | name: Test 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Set up Go 1.x 15 | uses: actions/setup-go@v5 16 | with: 17 | go-version: ^1.24 18 | id: go 19 | 20 | - name: Check out code into the Go module directory 21 | uses: actions/checkout@v4 22 | 23 | - name: Run unit tests and generate the coverage report 24 | run: make test 25 | 26 | lint: 27 | name: Lint 28 | runs-on: ubuntu-latest 29 | steps: 30 | - name: Set up Go 1.x 31 | uses: actions/setup-go@v5 32 | with: 33 | go-version: ^1.24 34 | id: go 35 | 36 | - name: Check out code into the Go module directory 37 | uses: actions/checkout@v4 38 | 39 | - name: Install gofumpt 40 | run: go install mvdan.cc/gofumpt@v0.7.0 41 | 42 | - name: Install staticcheck 43 | run: go install honnef.co/go/tools/cmd/staticcheck@v0.6.0 44 | 45 | - name: Install golangci-lint 46 | run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.5 47 | 48 | - name: Lint 49 | run: make lint 50 | 51 | - name: Ensure go mod tidy runs without changes 52 | run: go mod tidy && git diff-index --quiet HEAD 53 | 54 | fuzz: 55 | name: Fuzz 56 | runs-on: ubuntu-latest 57 | steps: 58 | - name: Set up Go 1.x 59 | uses: actions/setup-go@v5 60 | with: 61 | go-version: ^1.24 62 | id: go 63 | 64 | - name: Check out code into the Go module directory 65 | uses: actions/checkout@v4 66 | 67 | - name: Fuzz each test for one second 68 | run: TERM=xterm FUZZTIME=1s make fuzz 69 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | jobs: 9 | github-release: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout sources 13 | uses: actions/checkout@v4 14 | 15 | - name: Create release 16 | id: create_release 17 | uses: actions/create-release@v1 18 | env: 19 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token 20 | with: 21 | tag_name: ${{ github.ref }} 22 | release_name: ${{ github.ref }} 23 | draft: true 24 | prerelease: false 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode 2 | .idea/ -------------------------------------------------------------------------------- /.golangci.yaml: -------------------------------------------------------------------------------- 1 | linters: 2 | enable-all: true 3 | disable: 4 | - depguard 5 | - dupl 6 | - exhaustruct 7 | - funlen 8 | - gochecknoglobals 9 | - gochecknoinits 10 | - gocritic 11 | - godot 12 | - godox 13 | - inamedparam 14 | - intrange 15 | - lll 16 | - mnd 17 | - musttag 18 | - nlreturn 19 | - nonamedreturns 20 | - paralleltest 21 | - perfsprint 22 | - revive 23 | - tenv 24 | - testifylint 25 | - testpackage 26 | - varnamelen 27 | - wrapcheck 28 | - wsl 29 | 30 | # 31 | # Disabled because of generics: 32 | # 33 | - contextcheck 34 | - rowserrcheck 35 | - sqlclosecheck 36 | - wastedassign 37 | 38 | linters-settings: 39 | cyclop: 40 | max-complexity: 20 41 | tagliatelle: 42 | case: 43 | rules: 44 | json: snake 45 | gofumpt: 46 | extra-rules: true 47 | gomoddirectives: 48 | replace-allow-list: 49 | - github.com/attestantio/go-builder-client 50 | - github.com/attestantio/go-eth2-client 51 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, caste, color, religion, or sexual 10 | identity and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the overall 26 | community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or advances of 31 | any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email address, 35 | without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement writing an 63 | email to leo@flashbots.net or contacting elopio#8526 in 64 | [Discord](https://discord.com/invite/7hvTycdNcK). 65 | All complaints will be reviewed and investigated promptly and fairly. 66 | 67 | All community leaders are obligated to respect the privacy and security of the 68 | reporter of any incident. 69 | 70 | ## Enforcement Guidelines 71 | 72 | Community leaders will follow these Community Impact Guidelines in determining 73 | the consequences for any action they deem in violation of this Code of Conduct: 74 | 75 | ### 1. Correction 76 | 77 | **Community Impact**: Use of inappropriate language or other behavior deemed 78 | unprofessional or unwelcome in the community. 79 | 80 | **Consequence**: A private, written warning from community leaders, providing 81 | clarity around the nature of the violation and an explanation of why the 82 | behavior was inappropriate. A public apology may be requested. 83 | 84 | ### 2. Warning 85 | 86 | **Community Impact**: A violation through a single incident or series of 87 | actions. 88 | 89 | **Consequence**: A warning with consequences for continued behavior. No 90 | interaction with the people involved, including unsolicited interaction with 91 | those enforcing the Code of Conduct, for a specified period of time. This 92 | includes avoiding interactions in community spaces as well as external channels 93 | like social media. Violating these terms may lead to a temporary or permanent 94 | ban. 95 | 96 | ### 3. Temporary Ban 97 | 98 | **Community Impact**: A serious violation of community standards, including 99 | sustained inappropriate behavior. 100 | 101 | **Consequence**: A temporary ban from any sort of interaction or public 102 | communication with the community for a specified period of time. No public or 103 | private interaction with the people involved, including unsolicited interaction 104 | with those enforcing the Code of Conduct, is allowed during this period. 105 | Violating these terms may lead to a permanent ban. 106 | 107 | ### 4. Permanent Ban 108 | 109 | **Community Impact**: Demonstrating a pattern of violation of community 110 | standards, including sustained inappropriate behavior, harassment of an 111 | individual, or aggression toward or disparagement of classes of individuals. 112 | 113 | **Consequence**: A permanent ban from any sort of public interaction within the 114 | community. 115 | 116 | ## Attribution 117 | 118 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 119 | version 2.1, available at 120 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. 121 | 122 | Community Impact Guidelines were inspired by 123 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. 124 | 125 | For answers to common questions about this code of conduct, see the FAQ at 126 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at 127 | [https://www.contributor-covenant.org/translations][translations]. 128 | 129 | [homepage]: https://www.contributor-covenant.org 130 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html 131 | [Mozilla CoC]: https://github.com/mozilla/diversity 132 | [FAQ]: https://www.contributor-covenant.org/faq 133 | [translations]: https://www.contributor-covenant.org/translations 134 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing guide 2 | 3 | Welcome to the Flashbots collective! We just ask you to be nice when you play with us. 4 | 5 | Please start by reading our [code of conduct](CODE_OF_CONDUCT.md). 6 | 7 | ## Set up 8 | 9 | Write here the instructions to set up the development environment. 10 | 11 | ## Test 12 | 13 | Write here the instructions to run the tests. 14 | 15 | ## Code style 16 | 17 | Start by making sure that your code is readable, consistent, and pretty. 18 | Follow the [Clean Code](https://flashbots.notion.site/Clean-Code-13016c5c7ca649fba31ae19d797d7304) recommendations. 19 | 20 | Write here the code style rules specific to the project. 21 | 22 | ## Send a pull request 23 | 24 | - Your proposed changes should be first described and discussed in an issue. 25 | - Open the branch in a personal fork, not in the team repository. 26 | - Every pull request should be small and represent a single change. If the problem is complicated, split it in multiple issues and pull requests. 27 | - Every pull request should be covered by unit tests. 28 | - TODO Contributors License Agreement. 29 | 30 | We appreciate you, friend <3. 31 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | FROM golang:1.17 as builder 3 | WORKDIR /build 4 | ADD . /build/ 5 | RUN --mount=type=cache,target=/root/.cache/go-build make build-for-docker 6 | 7 | FROM scratch 8 | WORKDIR /app 9 | COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ 10 | COPY --from=builder /build/your-project /app/your-project 11 | ENV LISTEN_ADDR=":8080" 12 | EXPOSE 8080 13 | CMD ["/app/your-project"] 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021-2022 Flashbots 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GIT_VER := $(shell git describe --tags --always --dirty="-dev") 2 | # ECR_URI := 223847889945.dkr.ecr.us-east-2.amazonaws.com/your-project-name 3 | 4 | all: clean build 5 | 6 | v: 7 | @echo "Version: ${GIT_VER}" 8 | 9 | clean: 10 | rm -rf your-project build/ 11 | 12 | build: 13 | go build -ldflags "-X main.version=${GIT_VER}" -v -o your-project main.go 14 | 15 | test: 16 | go test ./... 17 | 18 | bench: 19 | go test -benchmem -bench=. ./... 20 | 21 | fuzz: 22 | ./scripts/fuzz.sh 23 | 24 | lint: 25 | gofmt -d -s . 26 | gofumpt -d -extra . 27 | go vet ./... 28 | staticcheck ./... 29 | golangci-lint run 30 | 31 | gofumpt: 32 | gofumpt -l -w -extra . 33 | 34 | fmt: 35 | gofmt -s -w . 36 | gofumpt -extra -w . 37 | gci write . 38 | go mod tidy 39 | 40 | cover: 41 | go test -coverprofile=/tmp/go-sim-lb.cover.tmp ./... 42 | go tool cover -func /tmp/go-sim-lb.cover.tmp 43 | unlink /tmp/go-sim-lb.cover.tmp 44 | 45 | cover-html: 46 | go test -coverprofile=/tmp/go-sim-lb.cover.tmp ./... 47 | go tool cover -html=/tmp/go-sim-lb.cover.tmp 48 | unlink /tmp/go-sim-lb.cover.tmp 49 | 50 | build-for-docker: 51 | CGO_ENABLED=0 GOOS=linux go build -ldflags "-X main.version=${GIT_VER}" -v -o your-project main.go 52 | 53 | docker-image: 54 | DOCKER_BUILDKIT=1 docker build . -t your-project 55 | docker tag your-project:latest ${ECR_URI}:${GIT_VER} 56 | docker tag your-project:latest ${ECR_URI}:latest 57 | 58 | docker-push: 59 | docker push ${ECR_URI}:${GIT_VER} 60 | docker push ${ECR_URI}:latest 61 | 62 | k8s-deploy: 63 | @echo "Checking if Docker image ${ECR_URI}:${GIT_VER} exists..." 64 | @docker manifest inspect ${ECR_URI}:${GIT_VER} > /dev/null || (echo "Docker image not found" && exit 1) 65 | kubectl set image deploy/deployment-your-project app-your-project=${ECR_URI}:${GIT_VER} 66 | kubectl rollout status deploy/deployment-your-project 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-boost-utils 2 | 3 | [![Goreport status](https://goreportcard.com/badge/github.com/flashbots/go-boost-utils)](https://goreportcard.com/report/github.com/flashbots/go-boost-utils) 4 | [![Test status](https://github.com/flashbots/go-boost-utils/workflows/Checks/badge.svg)](https://github.com/flashbots/go-boost-utils/actions?query=workflow%3A%22Checks%22) 5 | 6 | General utilities (such as SSZ/BLS signing) needed for the [Ethereum Builder 7 | API](https://ethereum.github.io/builder-specs/) 8 | ([Github](https://github.com/ethereum/builder-specs)). 9 | 10 | This library primarily meant for 11 | [mev-boost](https://github.com/flashbots/mev-boost) and 12 | [mev-boost-relay](https://github.com/flashbots/mev-boost-relay). 13 | 14 | ## Contributing 15 | 16 | Useful commands: 17 | 18 | * `make lint` -- Perform linter fixes. 19 | * `make test` -- Run all of the tests. 20 | 21 | ## Contributors 22 | 23 | Maintainers: 24 | 25 | * [@metachris](https://twitter.com/metachris) 26 | * [@Ruteri](https://twitter.com/mmrosum) 27 | 28 | Special thanks to: 29 | 30 | * [@lightclient](https://twitter.com/lightclients) 31 | * [@terencechain](https://twitter.com/terencechain) 32 | * [@JustinTraglia](https://twitter.com/JustinTraglia) 33 | * [and everyone else](https://github.com/flashbots/go-boost-utils/graphs/contributors) 34 | -------------------------------------------------------------------------------- /bls/bls.go: -------------------------------------------------------------------------------- 1 | package bls 2 | 3 | import ( 4 | "errors" 5 | "math/big" 6 | 7 | bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" 8 | "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" 9 | ) 10 | 11 | const ( 12 | PublicKeyLength = bls12381.SizeOfG1AffineCompressed 13 | SecretKeyLength = fr.Bytes 14 | SignatureLength = bls12381.SizeOfG2AffineCompressed 15 | ) 16 | 17 | type ( 18 | PublicKey = bls12381.G1Affine 19 | SecretKey = fr.Element 20 | Signature = bls12381.G2Affine 21 | ) 22 | 23 | var ( 24 | g1OneJac, _, g1One, _ = bls12381.Generators() 25 | domain = []byte("BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_") 26 | ErrInvalidPubkeyLength = errors.New("invalid public key length") 27 | ErrInvalidSecretKeyLength = errors.New("invalid secret key length") 28 | ErrInvalidSignatureLength = errors.New("invalid signature length") 29 | ErrSecretKeyIsZero = errors.New("invalid secret key is zero") 30 | ) 31 | 32 | func PublicKeyToBytes(pk *PublicKey) []byte { 33 | pkBytes := pk.Bytes() 34 | return pkBytes[:] 35 | } 36 | 37 | func SecretKeyToBytes(sk *SecretKey) []byte { 38 | skBytes := sk.Bytes() 39 | return skBytes[:] 40 | } 41 | 42 | func SignatureToBytes(sig *Signature) []byte { 43 | sigBytes := sig.Bytes() 44 | return sigBytes[:] 45 | } 46 | 47 | func PublicKeyFromBytes(pkBytes []byte) (*PublicKey, error) { 48 | if len(pkBytes) != PublicKeyLength { 49 | return nil, ErrInvalidPubkeyLength 50 | } 51 | pk := new(PublicKey) 52 | err := pk.Unmarshal(pkBytes) 53 | return pk, err 54 | } 55 | 56 | func SecretKeyFromBytes(skBytes []byte) (*SecretKey, error) { 57 | if len(skBytes) != SecretKeyLength { 58 | return nil, ErrInvalidSecretKeyLength 59 | } 60 | sk := new(SecretKey).SetBytes(skBytes) 61 | if sk.IsZero() { 62 | return nil, ErrSecretKeyIsZero 63 | } 64 | return sk, nil 65 | } 66 | 67 | func SignatureFromBytes(sigBytes []byte) (*Signature, error) { 68 | if len(sigBytes) != SignatureLength { 69 | return nil, ErrInvalidSignatureLength 70 | } 71 | sig := new(Signature) 72 | err := sig.Unmarshal(sigBytes) 73 | return sig, err 74 | } 75 | 76 | func GenerateRandomSecretKey() (*SecretKey, error) { 77 | return new(SecretKey).SetRandom() 78 | } 79 | 80 | func PublicKeyFromSecretKey(sk *SecretKey) (*PublicKey, error) { 81 | if sk.IsZero() { 82 | return nil, ErrSecretKeyIsZero 83 | } 84 | skBigInt := new(big.Int) 85 | sk.BigInt(skBigInt) 86 | pkJac := new(bls12381.G1Jac).ScalarMultiplication(&g1OneJac, skBigInt) 87 | return new(bls12381.G1Affine).FromJacobian(pkJac), nil 88 | } 89 | 90 | func GenerateNewKeypair() (*SecretKey, *PublicKey, error) { 91 | sk, err := GenerateRandomSecretKey() 92 | if err != nil { 93 | return nil, nil, err 94 | } 95 | pk, err := PublicKeyFromSecretKey(sk) 96 | if err != nil { 97 | return nil, nil, err 98 | } 99 | return sk, pk, nil 100 | } 101 | 102 | func Sign(sk *SecretKey, msg []byte) *Signature { 103 | Q, err := bls12381.HashToG2(msg, domain) 104 | if err != nil { 105 | panic(err) 106 | } 107 | skBigInt := new(big.Int) 108 | sk.BigInt(skBigInt) 109 | QJac := new(bls12381.G2Jac).FromAffine(&Q) 110 | sigJac := new(bls12381.G2Jac).ScalarMultiplication(QJac, skBigInt) 111 | return new(bls12381.G2Affine).FromJacobian(sigJac) 112 | } 113 | 114 | func VerifySignature(sig *Signature, pk *PublicKey, msg []byte) (bool, error) { 115 | Q, err := bls12381.HashToG2(msg, domain) 116 | if err != nil { 117 | return false, err 118 | } 119 | var negP bls12381.G1Affine 120 | negP.Neg(&g1One) 121 | return bls12381.PairingCheck( 122 | []bls12381.G1Affine{*pk, negP}, 123 | []bls12381.G2Affine{Q, *sig}, 124 | ) 125 | } 126 | 127 | func VerifySignatureBytes(msg, sigBytes, pkBytes []byte) (bool, error) { 128 | pk, err := PublicKeyFromBytes(pkBytes) 129 | if err != nil { 130 | return false, err 131 | } 132 | sig, err := SignatureFromBytes(sigBytes) 133 | if err != nil { 134 | return false, err 135 | } 136 | return VerifySignature(sig, pk, msg) 137 | } 138 | -------------------------------------------------------------------------------- /bls/bls_fuzz_test.go: -------------------------------------------------------------------------------- 1 | package bls 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | go_fuzz_utils "github.com/trailofbits/go-fuzz-utils" 8 | ) 9 | 10 | func GetTypeProvider(data []byte) (*go_fuzz_utils.TypeProvider, error) { 11 | tp, err := go_fuzz_utils.NewTypeProvider(data) 12 | if err != nil { 13 | return nil, err 14 | } 15 | err = tp.SetParamsStringBounds(0, 1024) 16 | if err != nil { 17 | return nil, err 18 | } 19 | err = tp.SetParamsSliceBounds(0, 4096) 20 | if err != nil { 21 | return nil, err 22 | } 23 | err = tp.SetParamsBiases(0, 0, 0, 0) 24 | if err != nil { 25 | return nil, err 26 | } 27 | return tp, nil 28 | } 29 | 30 | func FuzzPublicKeyFromBytes(f *testing.F) { 31 | f.Fuzz(func(t *testing.T, data []byte) { 32 | _, _ = PublicKeyFromBytes(data) 33 | }) 34 | } 35 | 36 | func FuzzPublicKeyFromBytesValidLength(f *testing.F) { 37 | f.Fuzz(func(t *testing.T, data []byte) { 38 | tp, err := GetTypeProvider(data) 39 | if err != nil { 40 | return 41 | } 42 | bytes, err := tp.GetNBytes(PublicKeyLength) 43 | if err != nil { 44 | return 45 | } 46 | _, _ = PublicKeyFromBytes(bytes) 47 | }) 48 | } 49 | 50 | func FuzzPublicKeyFromSecretKey(f *testing.F) { 51 | f.Fuzz(func(t *testing.T, data []byte) { 52 | tp, err := GetTypeProvider(data) 53 | if err != nil { 54 | return 55 | } 56 | var sk SecretKey 57 | err = tp.Fill(&sk) 58 | if err != nil { 59 | return 60 | } 61 | pk, err := PublicKeyFromSecretKey(&sk) 62 | if err != nil { 63 | require.NotNil(t, pk) 64 | } 65 | }) 66 | } 67 | 68 | func FuzzSecretKeyFromBytes(f *testing.F) { 69 | f.Fuzz(func(t *testing.T, data []byte) { 70 | _, _ = SecretKeyFromBytes(data) 71 | }) 72 | } 73 | 74 | func FuzzSecretKeyFromBytesValidLength(f *testing.F) { 75 | f.Fuzz(func(t *testing.T, data []byte) { 76 | tp, err := GetTypeProvider(data) 77 | if err != nil { 78 | return 79 | } 80 | bytes, err := tp.GetNBytes(SecretKeyLength) 81 | if err != nil { 82 | return 83 | } 84 | _, _ = SecretKeyFromBytes(bytes) 85 | }) 86 | } 87 | 88 | func FuzzSignatureFromBytes(f *testing.F) { 89 | f.Fuzz(func(t *testing.T, data []byte) { 90 | _, _ = SignatureFromBytes(data) 91 | }) 92 | } 93 | 94 | func FuzzSignatureFromBytesValidLength(f *testing.F) { 95 | f.Fuzz(func(t *testing.T, data []byte) { 96 | tp, err := GetTypeProvider(data) 97 | if err != nil { 98 | return 99 | } 100 | bytes, err := tp.GetNBytes(SignatureLength) 101 | if err != nil { 102 | return 103 | } 104 | _, _ = SignatureFromBytes(bytes) 105 | }) 106 | } 107 | 108 | func FuzzSign(f *testing.F) { 109 | f.Fuzz(func(t *testing.T, data []byte) { 110 | tp, err := GetTypeProvider(data) 111 | if err != nil { 112 | return 113 | } 114 | var sk SecretKey 115 | err = tp.Fill(&sk) 116 | if err != nil { 117 | return 118 | } 119 | msg, err := tp.GetBytes() 120 | if err != nil { 121 | return 122 | } 123 | Sign(&sk, msg) 124 | }) 125 | } 126 | 127 | func FuzzVerifySignature(f *testing.F) { 128 | f.Fuzz(func(t *testing.T, data []byte) { 129 | tp, err := GetTypeProvider(data) 130 | if err != nil { 131 | return 132 | } 133 | var sig Signature 134 | err = tp.Fill(&sig) 135 | if err != nil { 136 | return 137 | } 138 | var pk PublicKey 139 | err = tp.Fill(&pk) 140 | if err != nil { 141 | return 142 | } 143 | msg, err := tp.GetBytes() 144 | if err != nil { 145 | return 146 | } 147 | _, _ = VerifySignature(&sig, &pk, msg) 148 | }) 149 | } 150 | 151 | func FuzzVerifySignatureBytes(f *testing.F) { 152 | f.Fuzz(func(t *testing.T, data []byte) { 153 | tp, err := GetTypeProvider(data) 154 | if err != nil { 155 | return 156 | } 157 | sigBytes, err := tp.GetBytes() 158 | if err != nil { 159 | return 160 | } 161 | pkBytes, err := tp.GetBytes() 162 | if err != nil { 163 | return 164 | } 165 | msg, err := tp.GetBytes() 166 | if err != nil { 167 | return 168 | } 169 | _, _ = VerifySignatureBytes(msg, sigBytes, pkBytes) 170 | }) 171 | } 172 | 173 | func FuzzVerifySignatureBytesValidLength(f *testing.F) { 174 | f.Fuzz(func(t *testing.T, data []byte) { 175 | tp, err := GetTypeProvider(data) 176 | if err != nil { 177 | return 178 | } 179 | sigBytes, err := tp.GetNBytes(SignatureLength) 180 | if err != nil { 181 | return 182 | } 183 | pkBytes, err := tp.GetNBytes(PublicKeyLength) 184 | if err != nil { 185 | return 186 | } 187 | msg, err := tp.GetBytes() 188 | if err != nil { 189 | return 190 | } 191 | _, _ = VerifySignatureBytes(msg, sigBytes, pkBytes) 192 | }) 193 | } 194 | -------------------------------------------------------------------------------- /bls/bls_test.go: -------------------------------------------------------------------------------- 1 | package bls 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/ethereum/go-ethereum/common/hexutil" 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestSecretToPubkey(t *testing.T) { 11 | for _, tc := range []struct { 12 | Input []byte 13 | Output []byte 14 | }{ 15 | {hexutil.MustDecode("0x263dbd792f5b1be47ed85f8938c0f29586af0d3ac7b977f21c278fe1462040e3"), hexutil.MustDecode("0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a")}, 16 | {hexutil.MustDecode("0x47b8192d77bf871b62e87859d653922725724a5c031afeabc60bcef5ff665138"), hexutil.MustDecode("0xb301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81")}, 17 | {hexutil.MustDecode("0x328388aff0d4a5b7dc9205abd374e7e98f3cd9f3418edb4eafda5fb16473d216"), hexutil.MustDecode("0xb53d21a4cfd562c469cc81514d4ce5a6b577d8403d32a394dc265dd190b47fa9f829fdd7963afdf972e5e77854051f6f")}, 18 | } { 19 | sk, err := SecretKeyFromBytes(tc.Input) 20 | require.NoError(t, err) 21 | pk, err := PublicKeyFromSecretKey(sk) 22 | require.NoError(t, err) 23 | require.Equal(t, PublicKeyToBytes(pk), tc.Output) 24 | } 25 | } 26 | 27 | // Stolen from Teku's BLSTest class: 28 | // https://github.com/ConsenSys/teku/blob/ce6e13e32f2c5029aa05895f400c00a9c72a3f38/infrastructure/bls/src/test/java/tech/pegasys/teku/bls/BLSTest.java#L318-L332 29 | func TestSignatureVerifyRealValues(t *testing.T) { 30 | signingRootBytes := hexutil.MustDecode("0x95b8e2ba063ab62f68ebe7db0a9669ab9e7906aa4e060e1cc0b67b294ce8c5e4") 31 | sigBytes := hexutil.MustDecode("0xab51f352e90509ca5085ec43af9ad3ea4ae42bf30c91af7dcdc113ef79cfc8601b756f18d8cf634436d8b6b0095fc5680066f382eb3728a7090c55c9afb66e8f94b44d2682db8ef5de4b89928d1744824df174e0c800b9e934b0ad14e6388163") 32 | pkBytes := hexutil.MustDecode("0xb5e8f551c28abd6ef8253581ffad0834bfd8fafa9948d09b337c9c5f21d6e7fd6065a1ee35ac5146ac17344f97490301") 33 | 34 | result, err := VerifySignatureBytes(signingRootBytes, sigBytes, pkBytes) 35 | require.NoError(t, err) 36 | require.Equal(t, result, true) 37 | } 38 | -------------------------------------------------------------------------------- /fuzzing/common.go: -------------------------------------------------------------------------------- 1 | package fuzzing 2 | 3 | import ( 4 | "encoding/json" 5 | "strings" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/require" 9 | go_fuzz_utils "github.com/trailofbits/go-fuzz-utils" 10 | ) 11 | 12 | func GetTypeProvider(data []byte) (*go_fuzz_utils.TypeProvider, error) { 13 | tp, err := go_fuzz_utils.NewTypeProvider(data) 14 | if err != nil { 15 | return nil, err 16 | } 17 | err = tp.SetParamsStringBounds(0, 1024) 18 | if err != nil { 19 | return nil, err 20 | } 21 | err = tp.SetParamsSliceBounds(0, 4096) 22 | if err != nil { 23 | return nil, err 24 | } 25 | err = tp.SetParamsBiases(0, 0, 0, 0) 26 | if err != nil { 27 | return nil, err 28 | } 29 | return tp, nil 30 | } 31 | 32 | func Fill[T interface{}](data []byte, value *T) bool { 33 | tp, err := GetTypeProvider(data) 34 | if err != nil { 35 | return false 36 | } 37 | err = tp.Fill(value) 38 | return err == nil 39 | } 40 | 41 | type MarshalableSSZ interface { 42 | MarshalSSZ() ([]byte, error) 43 | UnmarshalSSZ([]byte) error 44 | } 45 | 46 | func RoundTripSSZ[V MarshalableSSZ](t *testing.T, data []byte, decSSZ V) { 47 | t.Helper() 48 | value := *new(V) 49 | if !Fill(data, &value) { 50 | return 51 | } 52 | t.Log(value) 53 | 54 | encSSZ, err := value.MarshalSSZ() 55 | if err != nil { 56 | if strings.Contains(err.Error(), "list length is higher than max value") { 57 | return 58 | } 59 | if strings.Contains(err.Error(), "does not have the correct length") { 60 | return 61 | } 62 | } 63 | require.NoError(t, err) 64 | 65 | err = decSSZ.UnmarshalSSZ(encSSZ) 66 | if err != nil { 67 | if strings.Contains(err.Error(), "unexpected number of bytes") { 68 | return 69 | } 70 | if err.Error() == "bitlist empty, it does not have length bit" { 71 | return 72 | } 73 | if err.Error() == "trailing byte is zero" { 74 | return 75 | } 76 | if err.Error() == "too many bits" { 77 | return 78 | } 79 | } 80 | require.NoError(t, err) 81 | require.Equal(t, value, decSSZ) 82 | } 83 | 84 | func RoundTripJSON[V any](t *testing.T, data []byte, decJSON V) { 85 | t.Helper() 86 | value := *new(V) 87 | if !Fill(data, &value) { 88 | return 89 | } 90 | t.Log(value) 91 | 92 | encJSON, err := json.Marshal(value) 93 | require.NoError(t, err) 94 | 95 | err = json.Unmarshal(encJSON, &decJSON) 96 | if err != nil { 97 | if err.Error() == "incorrect byte length" { 98 | return 99 | } 100 | } 101 | require.NoError(t, err) 102 | require.Equal(t, value, decJSON) 103 | } 104 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/flashbots/go-boost-utils 2 | 3 | go 1.24 4 | 5 | require ( 6 | github.com/attestantio/go-builder-client v0.6.1 7 | github.com/attestantio/go-eth2-client v0.24.0 8 | github.com/consensys/gnark-crypto v0.16.0 9 | github.com/ethereum/go-ethereum v1.15.2 10 | github.com/stretchr/testify v1.10.0 11 | github.com/trailofbits/go-fuzz-utils v0.0.0-20240830175354-474de707d2aa 12 | ) 13 | 14 | require ( 15 | github.com/bits-and-blooms/bitset v1.20.0 // indirect 16 | github.com/consensys/bavard v0.1.29 // indirect 17 | github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect 18 | github.com/crate-crypto/go-kzg-4844 v1.1.0 // indirect 19 | github.com/davecgh/go-spew v1.1.1 // indirect 20 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect 21 | github.com/emicklei/dot v1.6.4 // indirect 22 | github.com/ethereum/c-kzg-4844 v1.0.3 // indirect 23 | github.com/ethereum/go-verkle v0.2.2 // indirect 24 | github.com/ferranbt/fastssz v0.1.4 // indirect 25 | github.com/go-ole/go-ole v1.3.0 // indirect 26 | github.com/goccy/go-yaml v1.15.23 // indirect 27 | github.com/gofrs/flock v0.12.1 // indirect 28 | github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect 29 | github.com/holiman/uint256 v1.3.2 // indirect 30 | github.com/klauspost/cpuid/v2 v2.2.9 // indirect 31 | github.com/mattn/go-runewidth v0.0.16 // indirect 32 | github.com/minio/sha256-simd v1.0.1 // indirect 33 | github.com/mitchellh/mapstructure v1.5.0 // indirect 34 | github.com/mmcloughlin/addchain v0.4.0 // indirect 35 | github.com/olekukonko/tablewriter v0.0.5 // indirect 36 | github.com/pkg/errors v0.9.1 // indirect 37 | github.com/pmezard/go-difflib v1.0.0 // indirect 38 | github.com/prysmaticlabs/go-bitfield v0.0.0-20240618144021-706c95b2dd15 // indirect 39 | github.com/rivo/uniseg v0.4.7 // indirect 40 | github.com/shirou/gopsutil v3.21.11+incompatible // indirect 41 | github.com/supranational/blst v0.3.14 // indirect 42 | github.com/tklauser/go-sysconf v0.3.14 // indirect 43 | github.com/tklauser/numcpus v0.9.0 // indirect 44 | github.com/yusufpapurcu/wmi v1.2.4 // indirect 45 | golang.org/x/crypto v0.33.0 // indirect 46 | golang.org/x/sync v0.11.0 // indirect 47 | golang.org/x/sys v0.30.0 // indirect 48 | gopkg.in/yaml.v2 v2.4.0 // indirect 49 | gopkg.in/yaml.v3 v3.0.1 // indirect 50 | rsc.io/tmplfunc v0.0.3 // indirect 51 | ) 52 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= 2 | github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= 3 | github.com/attestantio/go-builder-client v0.6.1 h1:fn6PC8aDWx2YbptstR1JKP8NyakiNJJTiOE5f9N0z5Q= 4 | github.com/attestantio/go-builder-client v0.6.1/go.mod h1:f8wi3HzuPxfJoi2PirpJK3yZhte4SavDgKJbRrKoB1Q= 5 | github.com/attestantio/go-eth2-client v0.24.0 h1:lGVbcnhlBwRglt1Zs56JOCgXVyLWKFZOmZN8jKhE7Ws= 6 | github.com/attestantio/go-eth2-client v0.24.0/go.mod h1:/KTLN3WuH1xrJL7ZZrpBoWM1xCCihnFbzequD5L+83o= 7 | github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU= 8 | github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= 9 | github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= 10 | github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 11 | github.com/consensys/bavard v0.1.29 h1:fobxIYksIQ+ZSrTJUuQgu+HIJwclrAPcdXqd7H2hh1k= 12 | github.com/consensys/bavard v0.1.29/go.mod h1:k/zVjHHC4B+PQy1Pg7fgvG3ALicQw540Crag8qx+dZs= 13 | github.com/consensys/gnark-crypto v0.16.0 h1:8Dl4eYmUWK9WmlP1Bj6je688gBRJCJbT8Mw4KoTAawo= 14 | github.com/consensys/gnark-crypto v0.16.0/go.mod h1:Ke3j06ndtPTVvo++PhGNgvm+lgpLvzbcE2MqljY7diU= 15 | github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg= 16 | github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM= 17 | github.com/crate-crypto/go-kzg-4844 v1.1.0 h1:EN/u9k2TF6OWSHrCCDBBU6GLNMq88OspHHlMnHfoyU4= 18 | github.com/crate-crypto/go-kzg-4844 v1.1.0/go.mod h1:JolLjpSff1tCCJKaJx4psrlEdlXuJEC996PL3tTAFks= 19 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 20 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 21 | github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8= 22 | github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= 23 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= 24 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= 25 | github.com/emicklei/dot v1.6.4 h1:cG9ycT67d9Yw22G+mAb4XiuUz6E6H1S0zePp/5Cwe/c= 26 | github.com/emicklei/dot v1.6.4/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= 27 | github.com/ethereum/c-kzg-4844 v1.0.3 h1:IEnbOHwjixW2cTvKRUlAAUOeleV7nNM/umJR+qy4WDs= 28 | github.com/ethereum/c-kzg-4844 v1.0.3/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= 29 | github.com/ethereum/go-ethereum v1.15.2 h1:CcU13w1IXOo6FvS60JGCTVcAJ5Ik6RkWoVIvziiHdTU= 30 | github.com/ethereum/go-ethereum v1.15.2/go.mod h1:wGQINJKEVUunCeoaA9C9qKMQ9GEOsEIunzzqTUO2F6Y= 31 | github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= 32 | github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= 33 | github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY= 34 | github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg= 35 | github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= 36 | github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= 37 | github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= 38 | github.com/goccy/go-yaml v1.15.23 h1:WS0GAX1uNPDLUvLkNU2vXq6oTnsmfVFocjQ/4qA48qo= 39 | github.com/goccy/go-yaml v1.15.23/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= 40 | github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= 41 | github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= 42 | github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= 43 | github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 44 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 45 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 46 | github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= 47 | github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= 48 | github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= 49 | github.com/huandu/go-clone v1.7.2 h1:3+Aq0Ed8XK+zKkLjE2dfHg0XrpIfcohBE1K+c8Usxoo= 50 | github.com/huandu/go-clone v1.7.2/go.mod h1:ReGivhG6op3GYr+UY3lS6mxjKp7MIGTknuU5TbTVaXE= 51 | github.com/huandu/go-clone/generic v1.6.0 h1:Wgmt/fUZ28r16F2Y3APotFD59sHk1p78K0XLdbUYN5U= 52 | github.com/huandu/go-clone/generic v1.6.0/go.mod h1:xgd9ZebcMsBWWcBx5mVMCoqMX24gLWr5lQicr+nVXNs= 53 | github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= 54 | github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= 55 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 56 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 57 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 58 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 59 | github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= 60 | github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= 61 | github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= 62 | github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= 63 | github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= 64 | github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= 65 | github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 66 | github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= 67 | github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= 68 | github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= 69 | github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 70 | github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= 71 | github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= 72 | github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= 73 | github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= 74 | github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= 75 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 76 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 77 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 78 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 79 | github.com/prysmaticlabs/go-bitfield v0.0.0-20240618144021-706c95b2dd15 h1:lC8kiphgdOBTcbTvo8MwkvpKjO0SlAgjv4xIK5FGJ94= 80 | github.com/prysmaticlabs/go-bitfield v0.0.0-20240618144021-706c95b2dd15/go.mod h1:8svFBIKKu31YriBG/pNizo9N0Jr9i5PQ+dFkxWg3x5k= 81 | github.com/prysmaticlabs/gohashtree v0.0.4-beta h1:H/EbCuXPeTV3lpKeXGPpEV9gsUpkqOOVnWapUyeWro4= 82 | github.com/prysmaticlabs/gohashtree v0.0.4-beta/go.mod h1:BFdtALS+Ffhg3lGQIHv9HDWuHS8cTvHZzrHWxwOtGOs= 83 | github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 84 | github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= 85 | github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= 86 | github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= 87 | github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= 88 | github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= 89 | github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= 90 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 91 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 92 | github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo= 93 | github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= 94 | github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU= 95 | github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY= 96 | github.com/tklauser/numcpus v0.9.0 h1:lmyCHtANi8aRUgkckBgoDk1nHCux3n2cgkJLXdQGPDo= 97 | github.com/tklauser/numcpus v0.9.0/go.mod h1:SN6Nq1O3VychhC1npsWostA+oW+VOQTxZrS604NSRyI= 98 | github.com/trailofbits/go-fuzz-utils v0.0.0-20240830175354-474de707d2aa h1:jXdW82tOv+Bvh6adpc4kqcV6yuy5KLw/xzJmZBtZIdw= 99 | github.com/trailofbits/go-fuzz-utils v0.0.0-20240830175354-474de707d2aa/go.mod h1:/7KgvY5ghyUsjocUh9dMkLCwKtNxqe0kWl5SIdpLtO8= 100 | github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= 101 | github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= 102 | golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= 103 | golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= 104 | golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= 105 | golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= 106 | golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= 107 | golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 108 | golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 109 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 110 | golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= 111 | golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 112 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 113 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 114 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 115 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 116 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 117 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 118 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 119 | gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= 120 | gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= 121 | rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= 122 | rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= 123 | -------------------------------------------------------------------------------- /scripts/fuzz.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | # By default, fuzz each test for one minute. 5 | FUZZTIME=${FUZZTIME:-1m} 6 | 7 | files=$(grep --recursive --include='**_test.go' --files-with-matches 'func Fuzz' .) 8 | 9 | bold=$(tput bold) 10 | normal=$(tput sgr0) 11 | 12 | for file in $files; do 13 | funcs=$(grep -o 'func Fuzz\w*' $file | awk '{print $2}') 14 | for func in $funcs; do 15 | echo "${bold}[+] fuzzing $func in $file for ${FUZZTIME}${normal}" 16 | parent=$(dirname $file) 17 | go test $parent -run=$func\$ -fuzz=$func\$ -fuzztime=${FUZZTIME} 18 | done 19 | done 20 | -------------------------------------------------------------------------------- /ssz/ssz.go: -------------------------------------------------------------------------------- 1 | package ssz 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/attestantio/go-eth2-client/spec/phase0" 7 | "github.com/flashbots/go-boost-utils/bls" 8 | ) 9 | 10 | var ( 11 | ErrLength = errors.New("invalid length") 12 | 13 | DomainBuilder = ComputeDomain(DomainTypeAppBuilder, phase0.Version{}, phase0.Root{}) 14 | 15 | DomainTypeBeaconProposer = phase0.DomainType{0x00, 0x00, 0x00, 0x00} 16 | DomainTypeAppBuilder = phase0.DomainType{0x00, 0x00, 0x00, 0x01} 17 | ) 18 | 19 | type ObjWithHashTreeRoot interface { 20 | HashTreeRoot() ([32]byte, error) 21 | } 22 | 23 | func ComputeDomain(dt phase0.DomainType, forkVersion phase0.Version, genesisValidatorsRoot phase0.Root) [32]byte { 24 | forkDataRoot, _ := (&phase0.ForkData{ 25 | CurrentVersion: forkVersion, 26 | GenesisValidatorsRoot: genesisValidatorsRoot, 27 | }).HashTreeRoot() 28 | 29 | var domain [32]byte 30 | copy(domain[0:4], dt[:]) 31 | copy(domain[4:], forkDataRoot[0:28]) 32 | 33 | return domain 34 | } 35 | 36 | func ComputeSigningRoot(obj ObjWithHashTreeRoot, d phase0.Domain) ([32]byte, error) { 37 | var zero [32]byte 38 | root, err := obj.HashTreeRoot() 39 | if err != nil { 40 | return zero, err 41 | } 42 | signingData := phase0.SigningData{ObjectRoot: root, Domain: d} 43 | msg, err := signingData.HashTreeRoot() 44 | if err != nil { 45 | return zero, err 46 | } 47 | return msg, nil 48 | } 49 | 50 | func SignMessage(obj ObjWithHashTreeRoot, d phase0.Domain, sk *bls.SecretKey) (phase0.BLSSignature, error) { 51 | root, err := ComputeSigningRoot(obj, d) 52 | if err != nil { 53 | return phase0.BLSSignature{}, err 54 | } 55 | 56 | signatureBytes := bls.SignatureToBytes(bls.Sign(sk, root[:])) 57 | 58 | var signature phase0.BLSSignature 59 | if len(signatureBytes) != 96 { 60 | return phase0.BLSSignature{}, ErrLength 61 | } 62 | 63 | copy(signature[:], signatureBytes) 64 | if err != nil { 65 | return phase0.BLSSignature{}, err 66 | } 67 | 68 | return signature, nil 69 | } 70 | 71 | func VerifySignature(obj ObjWithHashTreeRoot, d phase0.Domain, pkBytes, sigBytes []byte) (bool, error) { 72 | msg, err := ComputeSigningRoot(obj, d) 73 | if err != nil { 74 | return false, err 75 | } 76 | 77 | return bls.VerifySignatureBytes(msg[:], sigBytes, pkBytes) 78 | } 79 | 80 | func VerifySignatureRoot(root phase0.Root, d phase0.Domain, pkBytes, sigBytes []byte) (bool, error) { 81 | signingData := phase0.SigningData{ObjectRoot: root, Domain: d} 82 | msg, err := signingData.HashTreeRoot() 83 | if err != nil { 84 | return false, err 85 | } 86 | 87 | return bls.VerifySignatureBytes(msg[:], sigBytes, pkBytes) 88 | } 89 | -------------------------------------------------------------------------------- /ssz/ssz_fuzz_test.go: -------------------------------------------------------------------------------- 1 | package ssz 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/attestantio/go-eth2-client/spec/phase0" 8 | "github.com/flashbots/go-boost-utils/bls" 9 | "github.com/flashbots/go-boost-utils/fuzzing" 10 | ) 11 | 12 | func FuzzRoundTripSigningData(f *testing.F) { 13 | f.Fuzz(func(t *testing.T, data []byte) { 14 | fuzzing.RoundTripSSZ(t, data, &phase0.SigningData{}) 15 | fuzzing.RoundTripJSON(t, data, &phase0.SigningData{}) 16 | }) 17 | } 18 | 19 | func FuzzUnmarshalSigningData(f *testing.F) { 20 | f.Fuzz(func(t *testing.T, data []byte) { 21 | var value phase0.SigningData 22 | _ = json.Unmarshal(data, &value) 23 | _ = value.UnmarshalSSZ(data) 24 | }) 25 | } 26 | 27 | func FuzzRoundTripForkData(f *testing.F) { 28 | f.Fuzz(func(t *testing.T, data []byte) { 29 | fuzzing.RoundTripSSZ(t, data, &phase0.ForkData{}) 30 | fuzzing.RoundTripJSON(t, data, &phase0.ForkData{}) 31 | }) 32 | } 33 | 34 | func FuzzUnmarshalForkData(f *testing.F) { 35 | f.Fuzz(func(t *testing.T, data []byte) { 36 | var value phase0.ForkData 37 | _ = json.Unmarshal(data, &value) 38 | _ = value.UnmarshalSSZ(data) 39 | }) 40 | } 41 | 42 | func FuzzComputeDomain(f *testing.F) { 43 | f.Fuzz(func(t *testing.T, data []byte) { 44 | tp, err := fuzzing.GetTypeProvider(data) 45 | if err != nil { 46 | return 47 | } 48 | var domainType phase0.DomainType 49 | err = tp.Fill(&domainType) 50 | if err != nil { 51 | return 52 | } 53 | var forkVersion phase0.Version 54 | err = tp.Fill(&forkVersion) 55 | if err != nil { 56 | return 57 | } 58 | var genesisValidatorsRoot phase0.Root 59 | err = tp.Fill(&genesisValidatorsRoot) 60 | if err != nil { 61 | return 62 | } 63 | ComputeDomain(domainType, forkVersion, genesisValidatorsRoot) 64 | }) 65 | } 66 | 67 | func FuzzComputeSigningRoot(f *testing.F) { 68 | f.Fuzz(func(t *testing.T, data []byte) { 69 | tp, err := fuzzing.GetTypeProvider(data) 70 | if err != nil { 71 | return 72 | } 73 | var forkData phase0.ForkData 74 | err = tp.Fill(&forkData) 75 | if err != nil { 76 | return 77 | } 78 | var domain phase0.Domain 79 | err = tp.Fill(&domain) 80 | if err != nil { 81 | return 82 | } 83 | _, _ = ComputeSigningRoot(&forkData, domain) 84 | }) 85 | } 86 | 87 | func FuzzSignMessage(f *testing.F) { 88 | f.Fuzz(func(t *testing.T, data []byte) { 89 | tp, err := fuzzing.GetTypeProvider(data) 90 | if err != nil { 91 | return 92 | } 93 | var forkData phase0.ForkData 94 | err = tp.Fill(&forkData) 95 | if err != nil { 96 | return 97 | } 98 | var domain phase0.Domain 99 | err = tp.Fill(&domain) 100 | if err != nil { 101 | return 102 | } 103 | var pkBytes []byte 104 | err = tp.Fill(&pkBytes) 105 | if err != nil { 106 | return 107 | } 108 | var sk bls.SecretKey 109 | err = tp.Fill(&sk) 110 | if err != nil { 111 | return 112 | } 113 | _, _ = SignMessage(&forkData, domain, &sk) 114 | }) 115 | } 116 | 117 | func FuzzVerifySignature(f *testing.F) { 118 | f.Fuzz(func(t *testing.T, data []byte) { 119 | tp, err := fuzzing.GetTypeProvider(data) 120 | if err != nil { 121 | return 122 | } 123 | var forkData phase0.ForkData 124 | err = tp.Fill(&forkData) 125 | if err != nil { 126 | return 127 | } 128 | var domain phase0.Domain 129 | err = tp.Fill(&domain) 130 | if err != nil { 131 | return 132 | } 133 | var pkBytes []byte 134 | err = tp.Fill(&pkBytes) 135 | if err != nil { 136 | return 137 | } 138 | var sigBytes []byte 139 | err = tp.Fill(&sigBytes) 140 | if err != nil { 141 | return 142 | } 143 | _, _ = VerifySignature(&forkData, domain, pkBytes, sigBytes) 144 | }) 145 | } 146 | -------------------------------------------------------------------------------- /ssz/ssz_test.go: -------------------------------------------------------------------------------- 1 | package ssz 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "io" 7 | "os" 8 | "strings" 9 | "testing" 10 | "time" 11 | 12 | builderApiBellatrix "github.com/attestantio/go-builder-client/api/bellatrix" 13 | builderApiV1 "github.com/attestantio/go-builder-client/api/v1" 14 | apiV1Bellatrix "github.com/attestantio/go-eth2-client/api/v1/bellatrix" 15 | "github.com/attestantio/go-eth2-client/spec/bellatrix" 16 | "github.com/attestantio/go-eth2-client/spec/phase0" 17 | "github.com/ethereum/go-ethereum/common" 18 | "github.com/ethereum/go-ethereum/common/hexutil" 19 | "github.com/flashbots/go-boost-utils/bls" 20 | "github.com/flashbots/go-boost-utils/types" 21 | "github.com/flashbots/go-boost-utils/utils" 22 | "github.com/stretchr/testify/require" 23 | ) 24 | 25 | var ErrInvalidForkVersion = errors.New("invalid fork version passed") 26 | 27 | func TestVerifySignature(t *testing.T) { 28 | sk, pk, err := bls.GenerateNewKeypair() 29 | require.NoError(t, err) 30 | msg := &builderApiV1.ValidatorRegistration{ 31 | FeeRecipient: bellatrix.ExecutionAddress{0x42}, 32 | GasLimit: 15_000_000, 33 | Timestamp: time.Now(), 34 | Pubkey: phase0.BLSPubKey{0x0d}, 35 | } 36 | domain := ComputeDomain(phase0.DomainType{0x01, 0x00, 0x00, 0x00}, phase0.Version{}, phase0.Root{}) 37 | root, err := ComputeSigningRoot(msg, domain) 38 | require.NoError(t, err) 39 | 40 | sig := bls.Sign(sk, root[:]) 41 | sig2, err := SignMessage(msg, domain, sk) 42 | require.NoError(t, err) 43 | require.Equal(t, bls.SignatureToBytes(sig), sig2[:]) 44 | 45 | ok, err := VerifySignature(msg, domain, bls.PublicKeyToBytes(pk), bls.SignatureToBytes(sig)) 46 | require.NoError(t, err) 47 | require.True(t, ok) 48 | } 49 | 50 | func TestVerifySignatureRoot(t *testing.T) { 51 | sk, pk, err := bls.GenerateNewKeypair() 52 | require.NoError(t, err) 53 | msg := &builderApiV1.ValidatorRegistration{ 54 | FeeRecipient: bellatrix.ExecutionAddress{0x42}, 55 | GasLimit: 15_000_000, 56 | Timestamp: time.Now(), 57 | Pubkey: phase0.BLSPubKey{0x0d}, 58 | } 59 | domain := ComputeDomain(phase0.DomainType{0x01, 0x00, 0x00, 0x00}, phase0.Version{}, phase0.Root{}) 60 | root, err := ComputeSigningRoot(msg, domain) 61 | require.NoError(t, err) 62 | 63 | sig := bls.Sign(sk, root[:]) 64 | sig2, err := SignMessage(msg, domain, sk) 65 | require.NoError(t, err) 66 | require.Equal(t, bls.SignatureToBytes(sig), sig2[:]) 67 | root2, err := msg.HashTreeRoot() 68 | require.NoError(t, err) 69 | 70 | ok, err := VerifySignatureRoot(root2, domain, bls.PublicKeyToBytes(pk), bls.SignatureToBytes(sig)) 71 | require.NoError(t, err) 72 | require.True(t, ok) 73 | } 74 | 75 | func genValidatorRegistration(t require.TestingT, domain phase0.Domain) *builderApiV1.SignedValidatorRegistration { 76 | sk, pk, err := bls.GenerateNewKeypair() 77 | require.NoError(t, err) 78 | 79 | var pubKey phase0.BLSPubKey 80 | pubKeyBytes := bls.PublicKeyToBytes(pk) 81 | copy(pubKey[:], pubKeyBytes) 82 | 83 | msg := &builderApiV1.ValidatorRegistration{ 84 | FeeRecipient: bellatrix.ExecutionAddress{0x42}, 85 | GasLimit: 15_000_000, 86 | Timestamp: time.Now(), 87 | Pubkey: pubKey, 88 | } 89 | 90 | signature, err := SignMessage(msg, domain, sk) 91 | require.NoError(t, err) 92 | return &builderApiV1.SignedValidatorRegistration{ 93 | Message: msg, 94 | Signature: signature, 95 | } 96 | } 97 | 98 | func BenchmarkSignatureVerification(b *testing.B) { 99 | domain := ComputeDomain(phase0.DomainType{0x01, 0x00, 0x00, 0x00}, phase0.Version{}, phase0.Root{}) 100 | reg := genValidatorRegistration(b, domain) 101 | 102 | b.ResetTimer() 103 | for n := 0; n < b.N; n++ { 104 | ok, err := VerifySignature(reg.Message, domain, reg.Message.Pubkey[:], reg.Signature[:]) 105 | require.NoError(b, err) 106 | require.True(b, ok) 107 | } 108 | } 109 | 110 | func TestVerifySignatureManualPk(t *testing.T) { 111 | msg := &builderApiV1.ValidatorRegistration{ 112 | FeeRecipient: bellatrix.ExecutionAddress{0x42}, 113 | GasLimit: 15_000_000, 114 | Timestamp: time.Unix(1652369368, 0), 115 | Pubkey: phase0.BLSPubKey{0x0d}, 116 | } 117 | root2, err := msg.HashTreeRoot() 118 | require.NoError(t, err) 119 | 120 | // Verify expected signature with manual pk 121 | pkBytes := make([]byte, 32) 122 | pkBytes[0] = 0x01 123 | sk, err := bls.SecretKeyFromBytes(pkBytes) 124 | require.NoError(t, err) 125 | 126 | sig := bls.SignatureToBytes(bls.Sign(sk, root2[:])) 127 | sigHex := hexutil.Encode(sig) 128 | require.Equal(t, "0x8e09a0ae7af113da2043001cc19fb1b3b24bbe022c1b8050ba2297ad1186f4217dd7095edad1d16d83d10f3297883d9e1674c81da95f10d3358c5afdb2500279e720b32879219c9a3b33415239bf46a66cd92b9d1750a6dd7cc7ec936a357128", sigHex) 129 | } 130 | 131 | func bytesTo4(bytes []byte) (res [4]byte) { 132 | copy(res[:], bytes[:4]) 133 | return 134 | } 135 | 136 | func TestComputeDomainVector(t *testing.T) { 137 | for _, tc := range []struct { 138 | DomainType string 139 | ForkVersion string 140 | GenesisValidatorsRoot string 141 | ExpectedDomain string 142 | }{ 143 | {"0x07000000", "0x01000000", "0x0a08c27fe4ece2483f9e581f78c66379a06f96e9c24cd1390594ff939b26f95b", "0x07000000b503183cf3d26841cf4499d79f4387520811f5ed97776f0d5317f086"}, 144 | } { 145 | var genesisValidatorsRoot phase0.Root 146 | genesisValidatorsRootBytes := hexutil.MustDecode(tc.GenesisValidatorsRoot) 147 | copy(genesisValidatorsRoot[:], genesisValidatorsRootBytes[:]) 148 | var expectedDomain [32]byte 149 | copy(expectedDomain[:], hexutil.MustDecode(tc.ExpectedDomain)[:32]) 150 | require.Equal(t, expectedDomain, ComputeDomain(bytesTo4(hexutil.MustDecode(tc.DomainType)), bytesTo4(hexutil.MustDecode(tc.ForkVersion)), genesisValidatorsRoot)) 151 | } 152 | } 153 | 154 | func _ComputeDomain(domainType phase0.DomainType, forkVersionHex, genesisValidatorsRootHex string) (domain phase0.Domain, err error) { 155 | forkVersionBytes, err := hexutil.Decode(forkVersionHex) 156 | if err != nil || len(forkVersionBytes) > 4 { 157 | return domain, ErrInvalidForkVersion 158 | } 159 | var forkVersion [4]byte 160 | copy(forkVersion[:], forkVersionBytes[:4]) 161 | 162 | genesisValidatorsRoot := phase0.Root(common.HexToHash(genesisValidatorsRootHex)) 163 | return ComputeDomain(domainType, forkVersion, genesisValidatorsRoot), nil 164 | } 165 | 166 | func Test_ComputeDomain(t *testing.T) { 167 | builderDomainKiln, err := _ComputeDomain(DomainTypeAppBuilder, types.GenesisForkVersionKiln, phase0.Root{}.String()) 168 | require.NoError(t, err) 169 | require.Equal(t, "0x000000017acd69a9ede79f3eb3eaa814c09159eeaa3d004be62f3372d9b31e9c", hexutil.Encode(builderDomainKiln[:])) 170 | 171 | beaconProposerDomainKiln, err := _ComputeDomain(DomainTypeBeaconProposer, types.BellatrixForkVersionKiln, types.GenesisValidatorsRootKiln) 172 | require.NoError(t, err) 173 | require.Equal(t, "0x00000000e7acb21061790987fa1c1e745cccfb358370b33e8af2b2c18938e6c2", hexutil.Encode(beaconProposerDomainKiln[:])) 174 | } 175 | 176 | func TestVerifySignedBuilderBidSignature(t *testing.T) { 177 | // SignedBuilderBid from Kiln 178 | bidStr := `{"message":{"header":{"parent_hash":"0x0544e2170998060d9560fdbf8f263a08c0a209211569a0560138522b84805abc","fee_recipient":"0x0000000000000000000000000000000000000000","state_root":"0xcded53d652660a91bfe6f5dfb017204a4cdd1598a07116b2cdea1586d603d01c","receipts_root":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logs_bloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","prev_randao":"0xd60955dc7f0cc7bf28d7e6c6f4859081f3a6df5ef4f70e05d70d8282bac20c6c","block_number":"960335","gas_limit":"30000000","gas_used":"0","timestamp":"1659720144","extra_data":"0x466c617368626f747320666c617368626c6f636b","base_fee_per_gas":"7","block_hash":"0xea33078b00e6b2926f45ed6d3190a3a6ada75cee342f600cf22fa02a9a2edcb7","transactions_root":"0x7ffe241ea60187fdb0187bfa22de35d1f9bed7ab061d9401fd47e34a54fbede1"},"value":"0","pubkey":"0xb5246e299aeb782fbc7c91b41b3284245b1ed5206134b0028b81dfb974e5900616c67847c2354479934fc4bb75519ee1"},"signature":"0xa775df980d589a87b234cf36b94fbcd40540ab1dffb752a013c02f636d85db60023f7e9d883de8cfdbfd94e0e3b598c01429fee50a5cb8d9fce50557baec2e9f81268f14f4f044b44b1238b7945201f036036d1a25d60e681f3737d4ef3b54b6"}` 179 | 180 | // Decode the bid 181 | bid := new(builderApiBellatrix.SignedBuilderBid) 182 | require.NoError(t, utils.DecodeJSON(strings.NewReader(bidStr), bid)) 183 | 184 | // Verify signature 185 | builderDomainKiln, err := _ComputeDomain(DomainTypeAppBuilder, types.GenesisForkVersionKiln, phase0.Root{}.String()) 186 | require.NoError(t, err) 187 | ok, err := VerifySignature(bid.Message, builderDomainKiln, bid.Message.Pubkey[:], bid.Signature[:]) 188 | require.NoError(t, err) 189 | require.True(t, ok) 190 | } 191 | 192 | func TestVerifySignedBuilderBidRootSignature(t *testing.T) { 193 | // SignedBuilderBid from Kiln 194 | bidStr := `{"message":{"header":{"parent_hash":"0x0544e2170998060d9560fdbf8f263a08c0a209211569a0560138522b84805abc","fee_recipient":"0x0000000000000000000000000000000000000000","state_root":"0xcded53d652660a91bfe6f5dfb017204a4cdd1598a07116b2cdea1586d603d01c","receipts_root":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logs_bloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","prev_randao":"0xd60955dc7f0cc7bf28d7e6c6f4859081f3a6df5ef4f70e05d70d8282bac20c6c","block_number":"960335","gas_limit":"30000000","gas_used":"0","timestamp":"1659720144","extra_data":"0x466c617368626f747320666c617368626c6f636b","base_fee_per_gas":"7","block_hash":"0xea33078b00e6b2926f45ed6d3190a3a6ada75cee342f600cf22fa02a9a2edcb7","transactions_root":"0x7ffe241ea60187fdb0187bfa22de35d1f9bed7ab061d9401fd47e34a54fbede1"},"value":"0","pubkey":"0xb5246e299aeb782fbc7c91b41b3284245b1ed5206134b0028b81dfb974e5900616c67847c2354479934fc4bb75519ee1"},"signature":"0xa775df980d589a87b234cf36b94fbcd40540ab1dffb752a013c02f636d85db60023f7e9d883de8cfdbfd94e0e3b598c01429fee50a5cb8d9fce50557baec2e9f81268f14f4f044b44b1238b7945201f036036d1a25d60e681f3737d4ef3b54b6"}` 195 | 196 | // Decode the bid 197 | bid := new(builderApiBellatrix.SignedBuilderBid) 198 | require.NoError(t, utils.DecodeJSON(strings.NewReader(bidStr), bid)) 199 | 200 | // Verify signature 201 | builderDomainKiln, err := _ComputeDomain(DomainTypeAppBuilder, types.GenesisForkVersionKiln, phase0.Root{}.String()) 202 | require.NoError(t, err) 203 | root, err := bid.Message.HashTreeRoot() 204 | require.NoError(t, err) 205 | ok, err := VerifySignatureRoot(root, builderDomainKiln, bid.Message.Pubkey[:], bid.Signature[:]) 206 | require.NoError(t, err) 207 | require.True(t, ok) 208 | } 209 | 210 | func TestKilnSignedBlindedBeaconBlockSignature(t *testing.T) { 211 | jsonFile, err := os.Open("../testdata/kiln-signedBlindedBeaconBlock-899730.json") 212 | require.NoError(t, err) 213 | defer jsonFile.Close() 214 | 215 | byteValue, err := io.ReadAll(jsonFile) 216 | require.NoError(t, err) 217 | 218 | payload := new(apiV1Bellatrix.SignedBlindedBeaconBlock) 219 | require.NoError(t, utils.DecodeJSON(bytes.NewReader(byteValue), payload)) 220 | 221 | root, err := payload.Message.HashTreeRoot() 222 | require.NoError(t, err) 223 | require.Equal(t, "4ada338ce48190c9d2169ca2484de507140b1bfeff2a8f820611dedcdc102d63", common.Bytes2Hex(root[:])) 224 | 225 | pk, err := utils.HexToPubkey("0xa04fe993de82bc878039bba5212a9fa750abf2293195cd55cbbce4827f56799cc67b5f66cf33bb1cec92dabcbcc0a0a9") 226 | require.NoError(t, err) 227 | require.Equal(t, "0xa04fe993de82bc878039bba5212a9fa750abf2293195cd55cbbce4827f56799cc67b5f66cf33bb1cec92dabcbcc0a0a9", pk.String()) 228 | 229 | domain, err := _ComputeDomain(DomainTypeBeaconProposer, types.BellatrixForkVersionKiln, types.GenesisValidatorsRootKiln) 230 | require.NoError(t, err) 231 | ok, err := VerifySignature(payload.Message, domain, pk[:], payload.Signature[:]) 232 | require.NoError(t, err) 233 | require.True(t, ok) 234 | } 235 | 236 | func TestKilnSignedBlindedBeaconBlockSignature2(t *testing.T) { 237 | jsonFile, err := os.Open("../testdata/kiln-signedBlindedBeaconBlock-899730.json") 238 | require.NoError(t, err) 239 | defer jsonFile.Close() 240 | 241 | byteValue, err := io.ReadAll(jsonFile) 242 | require.NoError(t, err) 243 | 244 | payload := new(apiV1Bellatrix.SignedBlindedBeaconBlock) 245 | require.NoError(t, utils.DecodeJSON(bytes.NewReader(byteValue), payload)) 246 | 247 | proof := make([][]byte, 33) 248 | for i := 0; i < 33; i++ { 249 | hash := phase0.Hash32{0x01} 250 | proof[i] = hash[:] 251 | } 252 | 253 | withdrawalCredentials := [32]byte{0x03} 254 | payload.Message.Body.Deposits = []*phase0.Deposit{ 255 | { 256 | Proof: proof, 257 | Data: &phase0.DepositData{ 258 | PublicKey: phase0.BLSPubKey{0x02}, 259 | WithdrawalCredentials: withdrawalCredentials[:], 260 | Amount: 1234, 261 | Signature: phase0.BLSSignature{0x04}, 262 | }, 263 | }, 264 | } 265 | 266 | root, err := payload.Message.HashTreeRoot() 267 | require.NoError(t, err) 268 | htrHex := common.Bytes2Hex(root[:]) 269 | require.Equal(t, "da469dcc55560d3f8ae26ea6c3910efce3e3b1c4cecc988c3ebafe71e81ad077", htrHex, htrHex) 270 | } 271 | -------------------------------------------------------------------------------- /staticcheck.conf: -------------------------------------------------------------------------------- 1 | checks = ["all", "-ST1000"] 2 | # checks = ["all", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022", "-ST1023"] 3 | initialisms = ["ACL", "API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "QPS", "RAM", "RPC", "SLA", "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", "UDP", "UI", "GID", "UID", "UUID", "URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS", "SIP", "RTP", "AMQP", "DB", "TS"] 4 | dot_import_whitelist = ["github.com/mmcloughlin/avo/build", "github.com/mmcloughlin/avo/operand", "github.com/mmcloughlin/avo/reg"] 5 | http_status_code_whitelist = ["200", "400", "404", "500"] 6 | -------------------------------------------------------------------------------- /testdata/deposit/README.md: -------------------------------------------------------------------------------- 1 | https://github.com/ethereum/consensus-spec-tests/tree/master/tests/mainnet/bellatrix/ssz_static/Deposit/ssz_random -------------------------------------------------------------------------------- /testdata/deposit/case0.json: -------------------------------------------------------------------------------- 1 | { 2 | "proof": [ 3 | "0x813b05d7c10dc4bdf45201a3539ec805ff4e016fbadd98a8b24cbf1f428ec799", 4 | "0xe0eeb767ee187803ca5312469e403dff943cbb8994fe6830532fe8daa1a5fcfd", 5 | "0xfa176b9aec52b0bfc8d2f955e6402346ab902fc6e31d39c4c01daa6062dc08aa", 6 | "0x9195d82364edf1d266335c6f6b1d4d3851c7ca641f3bfd5b4d2061d6c5c3675b", 7 | "0x2e4fec4c43adbd95c1f040af1587d0ec8d902d04939f116449e34c517d340af6", 8 | "0xfd19b47019a2506774090b71fd8e99257eb3d8cacbc664d15850869303f689e1", 9 | "0x72a24922706f48f9bb14aa13ce67d12ed803ff24cbd281485d008afb346a2ce1", 10 | "0x4033fdaee370c015fd4ddcd3f24c4a247d08203a1472e8d38e100b1b02fff5e6", 11 | "0xb18b590bea987e1ec3a3f5f16e52502d1c4344b8421c78da601d73e2523d2188", 12 | "0x7dee08accf96124accd084219c28717d0f6ae1b016c6b413c385fbb55f5f2794", 13 | "0x3b75b38f7b08d08018b363fb3508e8b2d30dd54dd077ad29b21739a39077c1bb", 14 | "0x0db53014f5044beb95863952f736c05a3d64ca6f9eeb8a21fecb903c8d1441b4", 15 | "0xdb1c0040f5d2fd7a54ad3e0c42aa3658db626f32935f23ccc54cb032708c6607", 16 | "0x7056387d1e7e966f44f8fbf215667f1f9edd8e220b369fe767fb681e998621c9", 17 | "0x71d33c0f63e2d6a740427c3b663a7daf790e988e89350e7e4d34d80745f61084", 18 | "0xdde0475b54e32f4e7311ba4d98071ca35e0622e21940cfb6a6a4cf9ba3459f9b", 19 | "0x6998a0f7f87c035979453e62799e12c1d82864d04b7ee1dac61b0dcdd50fd7eb", 20 | "0xdd9cc9a5be088bfd47b8d093d76a50044dbc8068790b1b7b820fec89b3dad90e", 21 | "0xb51c23d41d79a4d59013a2addf622bf76564d0499e4d03cc590ce2e4e920b695", 22 | "0xd4e0771b7fdf40e2672cd9cd29f8f2fab2f28706a12f6b332f89d7e84e076cd9", 23 | "0xefe6dd1416672d6e0eef3ff98952bacd6b237eff827baa54456e5b0a4369083f", 24 | "0x982d8d83f22db5b370c71c9467dec51de1266a7ad6090abcdbd7b8faf1927399", 25 | "0xc0045d7fda0002ef9b91044e7be792a78be20d6cc50cae356ba946f0788087c0", 26 | "0xd12452893e45f3e90f9f6bec0ef2de8a8a063f2757f6d4c2db6d10a0643a2519", 27 | "0x7472c802d83df921176269537ea90376a3b05fb3c5c897c502b18583d0d57bd2", 28 | "0x030e1f668f0c8e08fde2ab1eb2a1c4dab35c5ff06526c5db0e756341d5b3f995", 29 | "0xa9fe2906955996cf2be26e970ee32dd85f56794cfbafa6587bfa76aaac9d643b", 30 | "0x985c23aa6eb75f95d31a639b0407140364f4dd9df67adc0832787b3defbd19b3", 31 | "0x79c773654c20475a235e63163189fe15c3fa13f16cdc943cf507782f9c80a6e4", 32 | "0x3b068998394e2847dd22ad4b189ad30aad7b179f3534521355d65d49cb767474", 33 | "0x7d28912eb60f2537013a63f349b5cb8f677275d63be684cc29dff31f787757a3", 34 | "0xbf7488d1eb62d8c9ab9593b54b043c3aa8c21629f9600de537046950c73bc10e", 35 | "0xd435a863b9eaf1abd84961a1ff10ad19d86be440740a963fec4e453c045616f9" 36 | ], 37 | "data": { 38 | "pubkey": "0x39a316dc4e09c8c93d85347f98e5b14fdeae0cd647b2cd7fdb3a8cd6d78ba0de18ebdf7de4dc7c750705f0a6cc2c41f0", 39 | "withdrawal_credentials": "0x1ead7f2dd7a29f516be612cbe699646b28651480cbbef58854f7c11f19d28d40", 40 | "amount": "7745534145044315000", 41 | "signature": "0xfd26f225e5864c43bc79b5315bfaefcc402d424647a3e3c4d12be0c1d810f4e984b0e03b2c1ab0036cb470becc9f9bf02813a0f8d7cb1dada3f556647961cdd0fcb170a032af62d59f0d7c647a166c2101f38165c67e77378e702048addb0e28" 42 | } 43 | } -------------------------------------------------------------------------------- /testdata/depositdata_case0.json: -------------------------------------------------------------------------------- 1 | { 2 | "pubkey": "0x3c1820c62034fc45c10abc983dbce08de28f303192dea32371a902b3e6a1fc297876d3a3f602e0cecbb8a96122de86ed", 3 | "withdrawal_credentials": "0xc38dc56c4255cba641c83251a2a2dcc7535e773c9a2fb2e8b73758a476e021ea", 4 | "amount": "5538940938369409000", 5 | "signature": "0xe73b7e56672d0ec530631382d6a42819a10bb692f6faf63412f29705163695f953fc94986e1f1fdc2d1242bfc2019f55bb8386bc01ab80a36ce46b416260e5c9a5da214de8bfb55d1a0a579a25ac3103a01bd8e0639d779b8906dedc032b530b" 6 | } -------------------------------------------------------------------------------- /testdata/eth1data_case0.json: -------------------------------------------------------------------------------- 1 | { 2 | "deposit_root": "0x14a6c9f4c95d7dbb007e18cdbff3de3e3abb7d67e27e4acfaa9ae216c6ef16e5", 3 | "deposit_count": "2835981034321144300", 4 | "block_hash": "0x515b55e598ff6cfc96604741929c7943adf230a16dd42282658064a4336f6910" 5 | } -------------------------------------------------------------------------------- /testdata/executionpayload/README.md: -------------------------------------------------------------------------------- 1 | https://github.com/ethereum/consensus-spec-tests/tree/master/tests/mainnet/bellatrix/ssz_static/ExecutionPayload/ssz_random -------------------------------------------------------------------------------- /testdata/executionpayload/bellatrix-case0.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent_hash": "0x89236ba32cb76b3f17cbba7620d956d561a08a42a22145bb5705099ed94eaddf", 3 | "fee_recipient": "0x0000000000000000000000000000000000000000", 4 | "state_root": "0x44f451f33692bc78735f7836ad9c25761ba15609155e7bfcb38ded400d95d500", 5 | "receipts_root": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2", 6 | "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 7 | "prev_randao": "0x0000000000000000000000000000000000000000000000000000000000000000", 8 | "block_number": "11", 9 | "gas_limit": "4707788", 10 | "gas_used": "21000", 11 | "timestamp": "9155", 12 | "extra_data": "0x", 13 | "base_fee_per_gas": "233138867", 14 | "block_hash": "0x6662fb418aa7b5c5c80e2e8bc87be48db82e799c4704368d34ddeb3b12549655", 15 | "transactions": [ 16 | "0xf8670a843b9aca008252089400000000000000000000000000000000000000008203e880820a95a0ee3d06deddd2465aaa24bac5d329d3c40571c156c18d35c09a7c1daef2e95755a063e676889bbbdd27ab4e798b570f14ed8db32e4be22db15ab9f869c353b21f19" 17 | ] 18 | } -------------------------------------------------------------------------------- /testdata/executionpayload/capella-case0.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent_hash": "0x40d276c614b86013c95bbe59698628940b6c62ef63d50a528c24e9eaab591198", 3 | "fee_recipient": "0x13cb6ae34a13a0977f4d7101ebc24b87bb23f0d5", 4 | "state_root": "0x0e5a097fa89d985392014b37b23e7f69286ed8dc8c06e2e55dada849d331c2e1", 5 | "receipts_root": "0x1ddeeef0faf8c796762027d9ac55de825894985b18d6640cac1cc29041d50b7d", 6 | "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 7 | "prev_randao": "0xf5af8152556568891bc536bdd0ccfa2e37b7c951dd57af0e9f8bd552b7426c53", 8 | "block_number": "139225", 9 | "gas_limit": "30000000", 10 | "gas_used": "551506", 11 | "timestamp": "1677021756", 12 | "extra_data": "0x496c6c756d696e61746520446d6f63726174697a6520447374726962757465", 13 | "base_fee_per_gas": "7", 14 | "block_hash": "0x08751ea2076d3ecc606231495a90ba91a66a9b8fb1a2b76c333f1957a1c667c3", 15 | "transactions": [ 16 | "0xf875821054851010b87200830186a094f9aec40f2a2b2effe691491d7cfe3c90ddf6bbd8872386f26fc10000841998aeef8328d3b9a0ac092d4e961e6382b8b3a80e60b4d55a52157ebda53a9183326f4dc3f1d1302ea062e966f7c072a22699fff9eaffe4893fa41d1fb72cd9382fc43fb083d299d8a7", 17 | "0xf86e821055850dbcac8e00830186a094f9aec40f2a2b2effe691491d7cfe3c90ddf6bbd880844e71d92d8328d3b9a03cb8c728f77b35a07507b70aa922b6e31bae0fc870b0de7fba0d50dc6eb9ceefa0513ea444fb4133e923fc530c3a34a3de84623fa1a860761b2275e94a4801d757", 18 | "0xf875821054850ee6b28000830186a094f9aec40f2a2b2effe691491d7cfe3c90ddf6bbd8872386f399c6f200841998aeef8328d3baa005822bca0d7104540eae5db2b6b1c6269bca65510f44f769b2a9a1458be6397da04ea1f2d874c9effa336099ae5f2bd626887675a5ce9fb8847ecc2722131a0130", 19 | "0xf86e821055850dbcac8e00830186a094f9aec40f2a2b2effe691491d7cfe3c90ddf6bbd880844e71d92d8328d3baa07925e78c3ac04877525a917beee6e24128356a63f3cd7c6ec221771cb405be8da05be8386defe14eef922fbba7c949f6404882a0d123e467ff11a55d6a9e4c18c1", 20 | "0xf875821054850eab17b600830186a094f9aec40f2a2b2effe691491d7cfe3c90ddf6bbd8872386f3d561bc00841998aeef8328d3b9a0cd6b92b536ec40391285420feb8248bc129b80345a9ba19fc33f5653823a7706a0646f8ce3664772820240cabd6f6f9c1248e3017fdf4d5c5fb72763e61f78d446", 21 | "0xf86e821055850dbcac8e00830186a094f9aec40f2a2b2effe691491d7cfe3c90ddf6bbd880844e71d92d8328d3baa05bf1ba6fac6f621ec8528d3f6b5abbae72e3f9c8a212ddaad551f29427c30a49a05a33b94218db9e44ffbdf068d63be62475719a0029dcd652437344608d583d04", 22 | "0xf875821054850e6f7cec00830186a094f9aec40f2a2b2effe691491d7cfe3c90ddf6bbd8872386f410fc8600841998aeef8328d3baa00358efcdf94fee3b7736a1acde54bdaba1dcde70d028acb26e8a658a3a4e8395a00a24ea2c5d9f398ff9747e43c896096ea770fb9ecd09c0979229198cd08dbde8", 23 | "0xf86e821055850dbcac8e00830186a094f9aec40f2a2b2effe691491d7cfe3c90ddf6bbd880844e71d92d8328d3b9a0d03940e5d6f837663e31647492cbdb78d6682838d88522f939c8f67737ff435fa07747a35e473163a7fa8ddeae5a1c04b7ff93881170940758dc2e09eb4a704d4e", 24 | "0xf875821054850e33e22200830186a094f9aec40f2a2b2effe691491d7cfe3c90ddf6bbd8872386f44c975000841998aeef8328d3baa070381fcd0adb9c49e68fe861c7badc5d644d7140db3e2235b61e22eb9a023e1ba02fe84ed44efd953759c6c4892077acc571a8798d0afe84552e70be2298e717bb", 25 | "0xf86e821055850dbcac8e00830186a094f9aec40f2a2b2effe691491d7cfe3c90ddf6bbd880844e71d92d8328d3b9a07a1e1c837de4d9e5797c0d76fd1b8dd4b768893e6990d4320063636230cc9b47a018d81eb0e8a82de9e5ee9eb886c8b0a6fcde6d52ee5d2f1fe9e472499d8d7828", 26 | "0xf875821054850df8475800830186a094f9aec40f2a2b2effe691491d7cfe3c90ddf6bbd8872386f488321a00841998aeef8328d3b9a0cff9e433b2df74270efe3bed7b19e9eb845c0b51da98cf235db283b05a4c52eea066302c9e70d910b3b97caa4d9f4e7d884af346f26e7ef25925009e93844da676", 27 | "0xf86e821055850dbcac8e00830186a094f9aec40f2a2b2effe691491d7cfe3c90ddf6bbd880844e71d92d8328d3baa02aa3cb1e8b51a9080ec3b92f8978995f0b794fd8db0614d5a384711cc1db3259a012351f30cffed3adc0d2c89b71d2fecbdcc2133cfeb7b1058532bbb0e53e45e9", 28 | "0x02f877831469cb82cbe48405f5e1008405f5e10e825208948aa2b8622c1223a62fbc1119fa2b483ab41b250b88016345785d8a000080c080a0600fd64f4b97683e7b1130f5bc9e9860e0bb9f6dc6c3bf13ecdb6554cc6596c1a02682d446b692d0d8e2a7e4d15ba9fd259230bea211fc40ee056629ede5093811", 29 | "0x02f877831469cb82cbe58405f5e1008405f5e10e82520894388979a907fee4c8083aaffb9f66bc33001c1d4d88016345785d8a000080c001a0b242a130a0e7976a70766124772c6bc7a01c11e08bb1af134ae7d077b45c1528a03adc5e74af9304312fa53bf858babe795bcfe06ab5188873b6fe7623c08b7b57", 30 | "0x02f877831469cb82cbe58405f5e1008405f5e10e825208948aa2b8622c1223a62fbc1119fa2b483ab41b250b88016345785d8a000080c001a05defd8d136d031e2c9afcc1bd590dc6e3fda7863a641771f6d0d168cbf610f02a03b2a491394fc5702ce911a312324660018e4421084f53b965d8b3f238143ad63", 31 | "0x02f877831469cb82cbe68405f5e1008405f5e10e82520894388979a907fee4c8083aaffb9f66bc33001c1d4d88016345785d8a000080c001a0dc74824467ca640cdeae147a837e867b92548ea2e1ca739a865e022dc27b8a7aa062f6d55d06030a6a90e57b2086336cf33a00fa4ac1a08ba9a14b7c1b83e51647", 32 | "0x02f86e831469cb8209aa800782520894f97e180c050e5ab072211ad2c213eb5aee4df13487614fca865658a280c080a011f98172aa018c80ff382d7d4c51534fd78fa29254dac91746e3d0c6ef7010dea04cbc906ab1c898206d3b084cd38066d9d1e671bf11cc98d41ceb93a20cc8d5e3" 33 | ], 34 | "withdrawals": [ 35 | { 36 | "index": "1530173", 37 | "validator_index": "48240", 38 | "address": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", 39 | "amount": "188209" 40 | }, 41 | { 42 | "index": "1530174", 43 | "validator_index": "48241", 44 | "address": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", 45 | "amount": "188209" 46 | }, 47 | { 48 | "index": "1530175", 49 | "validator_index": "48242", 50 | "address": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", 51 | "amount": "188209" 52 | }, 53 | { 54 | "index": "1530176", 55 | "validator_index": "48243", 56 | "address": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", 57 | "amount": "188209" 58 | }, 59 | { 60 | "index": "1530177", 61 | "validator_index": "48244", 62 | "address": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", 63 | "amount": "188209" 64 | }, 65 | { 66 | "index": "1530178", 67 | "validator_index": "48245", 68 | "address": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", 69 | "amount": "188209" 70 | }, 71 | { 72 | "index": "1530179", 73 | "validator_index": "48246", 74 | "address": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", 75 | "amount": "188209" 76 | }, 77 | { 78 | "index": "1530180", 79 | "validator_index": "48247", 80 | "address": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", 81 | "amount": "178988" 82 | }, 83 | { 84 | "index": "1530181", 85 | "validator_index": "48248", 86 | "address": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", 87 | "amount": "188209" 88 | }, 89 | { 90 | "index": "1530182", 91 | "validator_index": "48249", 92 | "address": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", 93 | "amount": "178988" 94 | }, 95 | { 96 | "index": "1530183", 97 | "validator_index": "48250", 98 | "address": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", 99 | "amount": "188209" 100 | }, 101 | { 102 | "index": "1530184", 103 | "validator_index": "48251", 104 | "address": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", 105 | "amount": "188209" 106 | }, 107 | { 108 | "index": "1530185", 109 | "validator_index": "48252", 110 | "address": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", 111 | "amount": "188209" 112 | }, 113 | { 114 | "index": "1530186", 115 | "validator_index": "48253", 116 | "address": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", 117 | "amount": "188209" 118 | }, 119 | { 120 | "index": "1530187", 121 | "validator_index": "48254", 122 | "address": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", 123 | "amount": "188209" 124 | }, 125 | { 126 | "index": "1530188", 127 | "validator_index": "48255", 128 | "address": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", 129 | "amount": "188209" 130 | } 131 | ] 132 | } 133 | -------------------------------------------------------------------------------- /testdata/executionpayload/deneb-case0.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent_hash": "0xc2209759cf577fc467798ba2fc686b2b66570d1fe717ca0e012afb7cb27da452", 3 | "fee_recipient": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", 4 | "state_root": "0xf70701c309633bb1bd26bad3d39a8114270911adee83f04919aa3bbb4a078cb2", 5 | "receipts_root": "0x592c3cfac2ec01e970de0459f6789d532468a15c7facd880c71af056e59f8490", 6 | "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 7 | "prev_randao": "0xac912dabb21238750ff741f21bc2f91e42751e9834fff9c138d6ac6bebb0e637", 8 | "block_number": "297164", 9 | "gas_limit": "30000000", 10 | "gas_used": "2142000", 11 | "timestamp": "1704997008", 12 | "extra_data": "0xd883010d09846765746888676f312e32312e36856c696e7578", 13 | "base_fee_per_gas": "7", 14 | "block_hash": "0xd9491c8ae79611d0f08806f29b1e2e86cb8f64512aa381e543dcae257dda80d6", 15 | "transactions": [ 16 | "0xf87283b2ca0f8477359407825208946177843db3138ae69679a54b95cf345ed759450d870e35fa931a000080850343e1feb0a0232f671cda17e58ee3e6a4bcc22e42595bd158e5ee8ebd6ecf19cbc5b6e4002ba063d962968cd08a134d6da2adea6f99502c3ac0779a10b25beae8c46d7fc85d02", 17 | "0xf87283b2ca10847735940782520894687704db07e902e9a8b3754031d168d46e3d586e870e35fa931a000080850343e1feafa0c5e5914d867866d1273d46b579716468e786d4c80aca426faffdc364b413a98ba069c4bf7e84f637f0d0ee1dd2f829b36e88903594d23c94057fe013d1e8b350fd", 18 | "0xf87283b2ca1184773594078252089415e6a5a2e131dd5467fa1ff3acd104f45ee5940b870e35fa931a000080850343e1feafa0c955abbd72f47cc67c217b89272e8d497042afed0d29b005c36774d76ab80dfaa04dd80f4235cd12899d9d5d66d88bd34b707aa3587d7dfde57d975a04ddcf512a", 19 | "0xf87283b2ca1284773594078252089480c4c7125967139acaa931ee984a9db4100e0f3b870e35fa931a000080850343e1feafa0ee0a0d1a7b937dbd624b182697cd4b484127962367be1a4d900e7740ee078015a0534e89aa85da711f9003e7fffd1d2589964c16a74696afe8cb341c501995206c", 20 | "0xf87283b2ca13847735940782520894d08a63244fcd28b0aec5075052cdce31ba04fead870e35fa931a000080850343e1feafa070a70e108545db07da5366e9bce96e9b2b798ae6b61010b317a67b912c33f655a02ce9b1ebda0ecd9a8e783a252f54e3f3de6696fba2e9fc790c9214db7459be8d", 21 | "0xf87283b2ca148477359407825208940b06ef8be65fcda88f2dbae5813480f997ee8e35870e35fa931a000080850343e1feafa09c7c9f770758e04a772b82c6a9c8ed43cffba066327a01d2623d6578efba59caa017961cce26d31441091599d6e473c1813b0b1bf0ca76344cbc32cb1e7ba5ceb0", 22 | "0xf87283b2ca158477359407825208941cb96c5809da5977f99f69c11ee58bae5711c5f1870e35fa931a000080850343e1feafa055cbf0ac7924fb36ddf37b083c0f0e3136fe862e40448f6f012190ace6453594a06b7e68ffc18ebc6cf3c9f22d767295c34ef25895fd3da939cd33908d2a432b4e", 23 | "0xf87283b2ca168477359407825208942aa48ee899410a6d97c01b0bb0eeaf1771cc435b870e35fa931a000080850343e1feb0a002becdde6f3a450322c19de954654f3243943a49ba27255ad78bd46ffdc4f4a7a050a0e0edeaf11a4faed0799bf535d59651fda773d2092b266495fe4a06256c29", 24 | "0xf87283b2ca1784773594078252089407b9d920dd8e8d83dc1125c94fc0b3cdcdf602fb870e35fa931a000080850343e1feb0a0720ff20485bbd392745bcf0a2d03cd0634278976b44a79a4b87d84f582e916cba0797e26992c2c8b0c7c18ba8fa650d1e9191087066b644c0c6d4f413bb9646ed9", 25 | "0xf87283b2ca18847735940782520894fcb6e353ad4f79245c7cb704abcffe2f48684241870e35fa931a000080850343e1feafa0f34fd6a78e783da2ae1b44cd55f139ccb0173ea0e7167abcf6415cd7be6c81baa00598881b2deb805568720cd788f0fb4a5c9af23beccf420a2579f96efc310bd0", 26 | "0xf87283b2ca198477359407825208940d3de4256d6322683fdea9ee23765ccbfcb83da4870e35fa931a000080850343e1feafa0fc096a77fa2fe301f3a14f34138592a2e66cee93087663186eba3781dac38858a0359d767d079cff952fef59fddbea5c67ac5376d5002bdc05b6d055f8eb774ccd", 27 | "0xf87283b2ca1a8477359407825208946021752d8d9b2f221d4fea4349dea34ddbcfce50870e35fa931a000080850343e1feb0a0a3f4d571334ccc23448af71e9c1abb32c3d88cf2e529fc79c1a034d335d82908a007ef42156c784a198f34385e1e0d0756f6cd53fbf27fcb9854855ef4913b60e6", 28 | "0xf87283b2ca1b84773594078252089461e296d527edc89e831cf593ec341f16197eeafb870e35fa931a000080850343e1feafa0520d8cfd1db39a7d3b243ba9d62db793838b168118230c96999b91dfbac6045da0783852f06a27b42fbdb7188813fedfe223774d259c1587c1940137d28d234407", 29 | "0xf87283b2ca1c847735940782520894cf7317ee7a3b497ecf634b94bff60ff91b925747870e35fa931a000080850343e1feb0a019b02287fad94f6aeca7489a8123e4bcf9ab70f5388926e80e98a0216f512f5ca0125160a3fd03d61d93b7db3c773d71f4e1dc00ccc1f1266666beef2cfc01d558", 30 | "0xf87283b2ca1d8477359407825208947e7b519df31f77ced83eea1b16aedb6dcb0f0b24870e35fa931a000080850343e1feb0a0a532259c3e2f94983cef203ebf45ef790d2c534cfe319f9d67efa89d5959ac3aa0410923dface7953f5679eb67f19bff37dbc8357c0887f89051d7be7adfe11812", 31 | "0xf87283b2ca1e84773594078252089488a075e0fb1c9309a200a8bf0a88b214bf7ceb8d870e35fa931a000080850343e1feafa0be569c9e097589df0647ad61d0bc9cb9de1ea358718877e05883a0404fed32b9a02821efb1766a325c08417f5a186797776325a1e666cd3e386b89d284e210a5ac", 32 | "0xf87283b2ca1f847735940782520894c8d7cfb58f3ac02568e6505bf3fb5eb6f0807039870e35fa931a000080850343e1feb0a03f52fd1f9d38d20a618f4d896a9dce54dda51ccce1558df625ac19e9c05a0faba02de2de155588a35a527370c5d9ac33d1195e670bced9133bfc263cce3a3f50e3", 33 | "0xf87283b2ca20847735940782520894e0132e8d7b1b766e0ade5543d6c6c0b2d5a2f01d870e35fa931a000080850343e1feb0a084fb4f3725298a31db9fc4b2dfd953dbda3a97eb3a92365a69ec1230b4a75227a023b6d656447cc12759d47101c9103dd73bfaf65b203724b74345378c258fd221", 34 | "0xf87283b2ca21847735940782520894eb674c0411db79654afdc1e131f3b6e734baee6c870e35fa931a000080850343e1feafa0bf15d38f7e79e0960c36ca74af4e1bbd8772a62255ee19276eb18e41ee70a34ea07c50fbe6802a3d60aa84e89c805ef7816a83cec793fbd9bf7e3ab1ac662ba02f", 35 | "0xf87283b2ca22847735940782520894dc07c60993cf689438b8c85f86b0ed938dca77ea870e35fa931a000080850343e1feb0a01b9c81df7d9134acc80f5cf2e692968567b03e289b1f4df2c624062cfc2df9dca04b9e21222c3d4ed50ab082c0dae22a7cf9efd24543df952616f2cf503d414293", 36 | "0xf87283b2ca23847735940782520894110ddc93db59ed31a03518510221ec2f35d28f2f870e35fa931a000080850343e1feb0a07f8ef8175043b631fedd9d72de45e96a693b778f73573f30b60b03fc6f8cb365a06608f3a89d7baf0e39b8e7813611282c0bd1de80c9fdb7c940b4be15db6b8e99", 37 | "0xf87283b2ca24847735940782520894b599a876aaac824cfce21bdf15627c9fd8634c30870e35fa931a000080850343e1feb0a07edb8421bd20f16e534f6c29b76ba38afe29433f0c70de4ffeeea040009d0b5ca0483a80c5b85b48c721c1bc9662e966408cbc3844bfb40e6d839151c1dea3e54a", 38 | "0xf87283b2ca25847735940782520894d36e5540dd71acbd6416d60252c4d7c34a3c8245870e35fa931a000080850343e1feafa0f78ac8bf770b81b2942ece8bbf94bcfb660c406bcdece24e5e5441bc8e81996aa0383441f7a3f938ebe2757974d594105781e9b3d215da60e4c2b224342840e224", 39 | "0xf87283b2ca268477359407825208943adeca35af56206a74987a8fe13c669365c770cf870e35fa931a000080850343e1feb0a069d54c6d92b31245eeaab0cbdc3c0010dbc5f9ae9b94eee9a929f1ba606d9825a0596a765de29b8423c5b0645942482bf6b140d55ee32b85b1b25d08a665eb9068", 40 | "0xf87183b2ca27847735940782520894d77b95acd12f7b4b5692b55717b7bbca11651954870e35fa931a000080850343e1feaf9fac6d65c95332569e9f9c64eb6b0721d7017d66dbf645227d57db01aba2903aa07ba9d73969e8cbd1bbb4907b0139a7d1967a130aa0b9d755988f7ee395c76f4a", 41 | "0xf87283b2ca28847735940782520894f388bf5766b5ed5d4e1cbf15772e677dbfa80b00870e35fa931a000080850343e1feb0a0f641653544d7ecdef834e47d6b75c2864d1083c7f2410286d02ab50232c79ae9a0304f16db7e99d956da655f615b1b55a16b07b6f4abb49cec967e1f9a31d799a7", 42 | "0xf87283b2ca2984773594078252089435d4996296e58560e6ef47787d51b55f1e2bd92a870e35fa931a000080850343e1feafa0b5501a2f3d9591fdad84883d3f7b1f863765f7c5cd1105812bcd925da581f999a052201608e0e780ef773cdd52722e00abb75bf62ed819dbe467905f1ecc34e69d", 43 | "0xf87283b2ca2a847735940782520894a4c3b77b898e53d6095f11c53a1ce272cff9af31870e35fa931a000080850343e1feafa0c8522a33db78a306e1ba08e3d02d58644de3c057f02d4b09f8d71d5cd30924d3a05d639a640f163b13f5fda66a116ba6653dab2769fea6cf627d4f43506c7d6bdb", 44 | "0xf87283b2ca2b8477359407825208946e84f6113fc1919714f0266705813fb81a17181f870e35fa931a000080850343e1feb0a03d7d83fe6c67520c038b7ab5e54e323b71238ead8d23be5d8ae3d2806176e412a05ab8c4a341fd1ff343b045d491ff58a02ec222866f762e2d753c7142678a345a", 45 | "0xf87183b2ca2c847735940782520894e9ae1a806004e1452baae0493920815aadd84798870e35fa931a000080850343e1feb0a0bae01fbd421b4867be2703267d54589135e2befb91a85f4e60652084137f4e739fb11761069bf01930f2dc102a23f7c767d5cb463283c92c3236662a4be58b47", 46 | "0xf87283b2ca2d847735940782520894fe1905d8ebd20e037274eef441283c811ea82c16870e35fa931a000080850343e1feafa039c42f2963bf66deca076d981a9851fc932d445f0528c70d544a3e5a3077b86ea0326ee1251bb86cc43aabe95653e6d188641e6f229d5e3abff8407dbb579b535a", 47 | "0xf87283b2ca2e8477359407825208946adece88e477f53a143a4c29d97940df2ec768e0870e35fa931a000080850343e1feb0a018ae4840d3c615c217bb83a44cbc508209ea7fbf93f90302d6e5831847423e8da058ba46567d6d2051dbe2f936ad0ce69c682f0f9e3d5bf0d310cb7bf6819a71cf", 48 | "0xf87283b2ca2f8477359407825208940d34d140a7376892c4593fcea3ae26f5d6f202d7870e35fa931a000080850343e1feafa07b923f2c17a76f1d22da7c562edcc008738c45570430e552e9c231572c3abbd2a0582cb8258df9f2688860892339e4bbd9742403853aeec78db0dee5a1d94af8b6", 49 | "0xf87283b2ca30847735940782520894d1c7fa75b9bc55d041fcdf215f3e3a351c9f9edc870e35fa931a000080850343e1feb0a0781db8b5130b5ca1b60a0f4c62a402774d3e108e64e26aab31667537e345684fa046d10c31efaf6e6c4bb87a8a790bb5981760aa6e4da557b65d2c6b7d54a05351", 50 | "0xf87283b2ca31847735940782520894418ebe350a8c6387bf5e42f3502742af8e0781f1870e35fa931a000080850343e1feb0a0d455c6bf7482003643ed2165fafdd3102b9fc95c838646c9ab05e4f997eb7500a05898d44175872173d320e0c1b8cbd79a23b0fbb4c6a6be3ad6f7922842703f10", 51 | "0xf87283b2ca3284773594078252089484914d2770c711d27888c775c547b1d933b48c47870e35fa931a000080850343e1feb0a0bcf8de651d81fbfcd4d368173d74ba18c00ffe736abd9d08227efdb781bd9e79a060619e34c1d4f3451f988ec2b26c73b7998b13c22bb1a44dfcb29ea3e60e415c", 52 | "0xf87283b2ca338477359407825208948f51e560b85edf2e653c689c4e9fac02ce0556b8870e35fa931a000080850343e1feafa0dec3a0ec938c81a3c352bd2f24e4385a5db10294975b00ea5084cfc1227de714a0518d2e5113cdea9cf38ed730995460dd8c27d530e50331579026ad647720704b", 53 | "0xf87283b2ca34847735940782520894ee2503205c24dc66346e356f13f333fb8782d358870e35fa931a000080850343e1feafa01a777ef51abf54680c8e458a85f5272bc56a32049e7fb1b3f8c03d8c24bb8ef6a02607c211e587680030456b34c93a3dc9f337e7d72ba8cc4ef18f9efef823a793", 54 | "0xf87283b2ca35847735940782520894096ba6c59bd667a0fea9a356bcc988e4d9f2d8eb870e35fa931a000080850343e1feafa01128eeb14e0284b587284ef9b6abc408414f271d9104f20b7f06df4e57b869c2a05f713934d3e343f12a345caa3e90f3e5fc66c5914cddabe120cce8a6e93eb4a7", 55 | "0xf87283b2ca36847735940782520894da0adce4f1dc7debe7b2b52e8fe9ace6c7ea9c66870e35fa931a000080850343e1feafa0cd891d5f4085cf36554d2e3da56af2fcc6926af19c1730e5b0afb62369c0a11ea03c9fe6fa610de7047d066bdeb672cbd2914ccf191351af843c9c091e14e9f770", 56 | "0xf87283b2ca37847735940782520894af7d412aeab7525c0541dc3aa6c1085cfb8c9099870e35fa931a000080850343e1feafa0e0ccc70c1ca5e04c94f1234850eddb05b085e1e01c4bd7c97ebb4863bda6b763a029bd2de58dffa4796119e6195ead233f275cc4ca4fc050bd1325900da650933e", 57 | "0xf87283b2ca388477359407825208943cf8c0d567261eaf4ac0872d33a9f48af361769f870e35fa931a000080850343e1feb0a07af283307e8d1bf27baafbacf94196e55e047101052ac573e5fcc87e7eb6e2cea06f2b5b7a0bb6ebc78eadfed2b3c149e482759d7371959b75115f1f4db00e1fb7", 58 | "0xf87283b2ca398477359407825208944779242587ba9e828999249eadd82984430f4843870e35fa931a000080850343e1feafa01214e6f99a7571b3e7ab860f162389fcc42a5cfd7ddfa52a2561339428c98074a03358448c69fbb0aacc21d69ea32c90efd3d23a51037a4268cc015eadf1bde318", 59 | "0xf87283b2ca3a847735940782520894ea531cfe2de357ecff3855b88dbd07f60b03cdca870e35fa931a000080850343e1feb0a054f3fcdc61bcdb829789113e529a1c5d30c92b2316263c563d61c0e441190856a065f1a017a33f86fde74cca0b58c32b5a740cac2db10b1a8a340d24f4a79d8bd8", 60 | "0xf87283b2ca3b847735940782520894d00b5f53ea2a66ad33c3fee304bb22857dfb8a87870e35fa931a000080850343e1feb0a073309bd39bcde633947c863113cd66959d849113c1c40326c4fd779e980ba868a0345025d2863c04212fd6d949e18b2456e2e732c74eb20da251863e241fbff1d7", 61 | "0xf87283b2ca3c8477359407825208947ead29f6616f78f21a951c9686dd257be7b8efe4870e35fa931a000080850343e1feafa08ca2d7c5678210e30a304e650131dd19b2a9bce96979c1a548d78cb5e74dd851a05c3077cba3c44d8cd94c0b45f44eecc9d55ae4ec3d50663fd5623fcf24045bb9", 62 | "0xf87283b2ca3d847735940782520894d503c13ee55c1ea128357d4018ec58d0d5e5c3db870e35fa931a000080850343e1feb0a068bdf5f3c8b9777e84ca44fc1ad973d25c876d43fbd0c49051bedb80372940eea00ed7951529740e7dcd348698c9c7fec08062f72b43f55e5fa46ffda1d4eeb6d1", 63 | "0xf87283b2ca3e8477359407825208944ac670d8760faf780468638ef80034876ed8918d870e35fa931a000080850343e1feb0a043549d94f55bd35e7adf97af4c8f5032c510d9ee23aab159bd5f678627f6e8c7a02759974379335b215c72dcdebb2613d60b9355be0d2878792c3f7f979170963d", 64 | "0xf87283b2ca3f84773594078252089424ffb8c97ce443f8d3265ba3316defcfc07c659c870e35fa931a000080850343e1feafa0f91a15f02f15dabc13f35460cd888caf70b56a373de0e796e00e870a1fe57ab5a024f0e6d0ebe5b0e4f67d65095a263320055ca23e711f6030dc5f47182458b4c6", 65 | "0xf87283b2ca408477359407825208940c5cafc547ab98c9ceaa1c07fdd6bf7820aeb954870e35fa931a000080850343e1feafa0716afd885054db1ea6c6e6defbe66fb62ddc8fe993e8a6014104e252922e77d5a00f4818bab49844de73fe28887ec8881c6dd462924a8cb68ec30f819afdb2b487", 66 | "0xf87283b2ca41847735940782520894db8d964741c53e55df9c2d4e9414c6c96482874e870e35fa931a000080850343e1feafa033b647be0c59bbaed1bb0f995007f86a7b650ad32ff5ae421e78a23624d4548aa044321613820305ab64ecbadaab1562f9dbd78ecfe9f366f3729d1c5b461b8a9f", 67 | "0xf87283b2ca42847735940782520894ba85bb35ae6ff7a34745993fcf92b9afd34124f1870e35fa931a000080850343e1feafa0c3c3271016649caaac7df0e9a2543badc0ff1c5b9d9d8d6dd70faec8b450890ca005960b5204a2329f8d274cf7e457b095bc371d3851809fa651ce9c02063e2100", 68 | "0xf87283b2ca4384773594078252089458871015f5a2d3948264f7c16ad194c80ffd531d870e35fa931a000080850343e1feafa062bc239f09834b88fc6c3ec9568b2a17dbb95f1750ce5da64d6ba2320aae6376a044367552953846b53137586f6183a15e86eebee779237d28e654c35cffbc952e", 69 | "0xf87283b2ca448477359407825208942a90af45df70b0031f218cc122598ddf3e10469f870e35fa931a000080850343e1feafa05a42a11507d7a5562f0f59695da017cb9cc71c57c9c8aa1482189e989f1524a1a02c91dc11d04a6eea954accfdc785633c92ec18a964577f57e03a452c4f0a89db", 70 | "0xf87283b2ca45847735940782520894761bbaaea6ceb265f5262c3b559adc2ad3ed2f09870e35fa931a000080850343e1feafa039d29e4590b51ff8cfec9d0e5f184c756e18d7607377cd117e454e81587ed888a04d5308a90dd4f5725caf97df20f60d6c838d32243e1ecd214ae7dc0b9e508b9c", 71 | "0xf87283b2ca46847735940782520894dfe86f51c5e603f1420d1f0ab366bd3bfe23d2a7870e35fa931a000080850343e1feb0a04392ac4309de3f1de55af346511f8ec72767e0ca42b9a6a2e5e73725a3aa3b0ca0144158ec8215d503eb295a177f28e24586d1b0230330499fda0bf71df7b9c07f", 72 | "0xf87283b2ca47847735940782520894d616547158b05ab5079106dc0336d72763a72871870e35fa931a000080850343e1feb0a0a7d58d7a5562ac985fb9bd3b1345be2cc82f91896ba0f56deb755945127c1093a00c973033cb96bdb63e065151a88f21a9ddb1b5aac28da09f0b6cb40b69b5beb0", 73 | "0xf87283b2ca48847735940782520894dc68cd278cb7f5f666ce7b0a3a214a8540ed4dfa870e35fa931a000080850343e1feafa0ce9d683746ae919212073b51be72b5677274d7a5fffc75bbd38adb2a4bdb3cd8a06d33c96bcda7828f9a6bab6069ebbe9b591717b92eaf9b6d8a532043c78013e6", 74 | "0xf87283b2ca4984773594078252089411f8107da05b6905e8cc0227ca3b0c6eb764fac0870e35fa931a000080850343e1feafa08b342274bbff60e2d3a2f580ac22a6f580a6e46cac0ae193af985c8321d77413a017390dd6aa0c2f3783592bb05f8c0e2d165fdb6e4519cd720e8d408ffdb8213b", 75 | "0xf87283b2ca4a84773594078252089404da906545679850a7ee0ef6836e183031bedc88870e35fa931a000080850343e1feafa013ef4954ad7866e0d34d526acadcd276bc1d99b4a1402bf9d79eb5bc74211336a06d38c764c38e3a4f920a23e92b6b88cec93284788c95ecb4a52cf46d336b3b71", 76 | "0xf87283b2ca4b8477359407825208948bdc25c43c010fd3db6281fcd8f7a0bed18838e3870e35fa931a000080850343e1feafa03947d852b7715cd3439339491143eb3608bcb66f55098dff59412c7dbd338b4ba06cf19ec280ee1bf31544107382afd721bae389dab865c91202e9ebb8130e1b52", 77 | "0xf87183b2ca4c847735940782520894af16f746b8a834a383fd0597d941fee52b7791eb870e35fa931a000080850343e1feb0a0dd4b05f33647254a3fe524bb87b78f5d07f2da07d45c93a516c3596d11996f1b9f13486308ceb7a0a5d0d54d1f75fd673b8755439c9e6987b495081aa2e1a043", 78 | "0xf87283b2ca4d8477359407825208940c5c736600f8ea58ccb89aa72e3f3634651fd551870e35fa931a000080850343e1feafa02bedac70c35bfcd2e311b60730926d942d567eab0d3fce68c60a551d3951f56ea016e3100ee3ebf179ea3253bcb493883a0b124db18df108c3eab6a5fef90abb5b", 79 | "0xf87283b2ca4e8477359407825208946f475e0f0e9eda58556fddc04de9b1a9b6a4cfb4870e35fa931a000080850343e1feafa0eef87d4e6b018e4a38b649b15ecda079cca7957cb4d3863e01ca61ded09a76a2a028f6458e7755aeeba2c21104a0605dfb94cadbd9c8e4f1f9b971201f5fd925f2", 80 | "0xf87283b2ca4f8477359407825208949b2e76498a695c4dc7d0890069cffa84a9581d24870e35fa931a000080850343e1feafa0c3255cc7aef487e5ab9d931a259b831e2fd74f8a23ef523b87b17e20a00a80e6a07ecdf24edf74b2d7bb9ba74c6124320c1c673480dbc3897a1838a7486bfbe624", 81 | "0xf87283b2ca50847735940782520894e2d2b2069f4a54fcc171223ff0c17adbd743c285870e35fa931a000080850343e1feafa0227ed6dfc5bf27ffc152d145c64fa108b964d56e9b3c118d3dc6c2909344e6e4a0633a165999e15ec506cf89063338f9857180bb8c163d252233b4306996240ea7", 82 | "0xf87283b2ca51847735940782520894386bd49f04322544f3c7178fa5ae1a24b947b454870e35fa931a000080850343e1feb0a082d510950cc6246f7fc969e92def81b18d63d6b547a99ebc30e4897ab3342724a01dce6f14dbeb5b3bedc273ab9e244f62fa7df2bcf518a85ec1b6544f18244fcf", 83 | "0xf87183b2ca5284773594078252089400af839c3fc067fafc2e0a205858d6957f0dd18d870e35fa931a000080850343e1feb0a0908e55d774b8264736b283d848bb2f799c71a1cfbb1dddb304dad8eefc4685389f6a1da60e6fc82ae4713c84ba99e8bfbafb35191c4563ba64af5fd0ce002d50", 84 | "0xf87283b2ca53847735940782520894ebb6d32a650afa9221b55a11c6a6de52b6f07cd7870e35fa931a000080850343e1feafa06c35791de05fe59e5a94fb3e981b0c4b095927535fb41b01209b4ed85a611676a050b7eaedd0c887c86f23419e192c9d077e3d97fdf01d3ff8808cd41acd84f41e", 85 | "0xf87283b2ca54847735940782520894011d26a3a9adc9203c8943a6a77aa8657af52420870e35fa931a000080850343e1feb0a0be0a8e72b046c792992f2954e3386b29891f38302d55b0677bc8e953076aaa5ba03a41c430059e43b0db1a4f86e647b100d455b8d2a9691bbf22b609a4caaa2866", 86 | "0xf87283b2ca558477359407825208949c85bc61a89fb5abd957e6c819c653fc1aa0d11b870e35fa931a000080850343e1feb0a0c93b731af016e9f08877512ae4d07ab8befd333c0736373fe68916b3045a3f5ca055caed9ee7e794c05f4d36bc6b75a617120f5de9d16243c6760fc97b7feff1df", 87 | "0xf87283b2ca56847735940782520894bd8e8435b7897d87cf7cedb5cf8c5dd865dbf720870e35fa931a000080850343e1feafa044276922dcd7957054e067ae806a4e7d2b430bb307c7b845a2f5133a5fdb8c7ba00cef595bce18815b382533b9e4c8a3fa1473e5354baad59300e4a9b5f4d41bd1", 88 | "0xf87283b2ca57847735940782520894adebee2e3ff041078b62380d001c6e51b4f15598870e35fa931a000080850343e1feb0a0551e6ca15c83a2680873aeb33fccf1337666d6a420c91a02648c2192cfac5fb0a007c9af16b3893662c63da9569eb79d53d7dd38ea4c316fc413e708cc0aea5adb", 89 | "0xf87283b2ca5884773594078252089471e94c459c9f05085fc0d34b5f21e648e05dc6b3870e35fa931a000080850343e1feafa0fa835fb15e28a55143f8ed2dfb179841126abaff9afcfedfa593b8bd506a6789a03fe24cfd2c20f9dc571ad90950d9af214fc310799503210a141cf48b5859b3ff", 90 | "0xf87283b2ca598477359407825208947c1fe317db82c9298b87c56c3194178271b621e1870e35fa931a000080850343e1feb0a0cf5b615d8d2233efcb152127ca8f940f8724184c5f2326077f297d91efc63fada0053c796c6c330530c0a04afbaab7ac72825ccfa74f74ca5b86d0546d19ee7b0c", 91 | "0xf87283b2ca5a847735940782520894e069d1c9abf5127bdc3a164fb93b96bfa9f74ce0870e35fa931a000080850343e1feafa0ac4eb8d4437ac45d2a2673654b0b9a69c31917d1a09be66dee2010bac2cd128aa019b3dcda289a8d7ab95d573987e4197cb89645bf2f4bbfb95dfffd8890554628", 92 | "0xf87283b2ca5b847735940782520894b9bbddd1eb6ef8fb1bdc6a853d5ad7486a9487dd870e35fa931a000080850343e1feb0a011e089873bcde117d4c4bbfc057f64275e18ab6e75175fc90c20693de7f0549ea03682fbbcb36ef87a033aa4d183c5716f5bdbe74fa04ff73c96817269683a014a", 93 | "0xf87283b2ca5c847735940782520894a804387cdaf986d45831e8074efb2115af053f7a870e35fa931a000080850343e1feb0a044728ef6764e6d1d561979aac58024077406aeefebfc3e4fe103127c3793bfada057fd99cfa269c6ce10f97dffb575f38bd0d1d1970ef19648c5ede04c817a7986", 94 | "0xf87283b2ca5d847735940782520894f23501d784a041fc911b4c86c2bfb1f63ec170ea870e35fa931a000080850343e1feb0a0bf2fd5822fac3c756284e07e487f7aa0e25f2aae051f6966bf1723d9aff4d713a07faac8a1050efbf9c1b7f061ce90abeddedf9d7f59f13f29702861470f6310c4", 95 | "0xf87283b2ca5e8477359407825208943928be2a7058088313c0fb3294014e88a3c5ed4a870e35fa931a000080850343e1feb0a07073b1c53c64d977f43e5045f136aa22766664f5029c51d0f9f6e9562ade0056a017b0fa41efdcf364b40b65f09a00ee97e491a318844c62bc984fb17899f84daa", 96 | "0xf87283b2ca5f847735940782520894196aa07204141478459c14106ef5e5282efe9957870e35fa931a000080850343e1feafa0dc23d116f1dc7833274484bcb750f8fde476d0f65980d2fb65ef422a2db6b342a0022af2882c4da8ea6e7439744c79f560fe47b5dacc6acf0e490859ebd6e7f90a", 97 | "0xf87283b2ca60847735940782520894763cbf89560e2da270000822abda9584db693fa3870e35fa931a000080850343e1feb0a0cbd30950702cdd8fd9a2b6f3032107190402aeacded447d9e4ddca0be8f4a0a2a0327a730029720e5d40d64e59d6583ac054d22c9a54f3efbb8c4ae800c5f65b36", 98 | "0xf87283b2ca618477359407825208947feaea0ff70ffc9eec2104f57f7136aff4dea680870e35fa931a000080850343e1feb0a077c86f7c3d82fe0b45c9468170fc7b9d31b29d6ab5d971be78eb9a58e9b3d14da0782285c77fa8ebc436d8b397a30f1a8a9169c9abf7df6a09d11546a66205ed5d", 99 | "0xf87283b2ca62847735940782520894e5466aacd9dd6d3bb35060a1ccc76a438de88ca1870e35fa931a000080850343e1feb0a0ab09d576a36d217d08cc8eda52b35d510d6b834c32522ef99b55b76d9c8b8981a0758a5f42f92a59fe0fb0307f93418208cfb1267e348985172d62732739f84b2c", 100 | "0xf87283b2ca63847735940782520894f670980415cfe8c4f8d10645ecf974c9a2fea00e870e35fa931a000080850343e1feafa04e6478a23686f9b3de241b2b9f55245db83c250588e26ad58345b29c39bbbd27a07436fe4148f284697f14e7896653f85aa86c4823dae35a09f55d7bbaa9f8d335", 101 | "0xf87283b2ca64847735940782520894a29115bce7829ffdd989b7cf1bdd1eac06a2cb36870e35fa931a000080850343e1feb0a049373772d3078c96956c11a57a64406eaa8db802d9ff43d53ba9245a54729ad8a02f0379117dcf2a472b70aaa032fa6eeceaadee1573bc68bdfdb456238e2b25c4", 102 | "0xf87283b2ca658477359407825208948f528aa67dc1846c893465fa1c8c26556bc5fe19870e35fa931a000080850343e1feb0a04a9206b2c7283b48c9eeac91626b8ecfcdd75954244771029635f4dab641ef83a013bd39a1bee8a2c22d41fd6d6f1d840c32ef000f2dad466014177e5d0263e866", 103 | "0xf87283b2ca668477359407825208944dc4ec6ac43c8c45777292db987203c0248e17b7870e35fa931a000080850343e1feb0a0bdac2f6689e71fd20c81ab3ed3eb589481faded73989c5ee3b301abdf0df4b53a0578183bf6312dfe8b2719108accbb232f8e51483b25dfd7d3ecd1c610439956c", 104 | "0xf87283b2ca678477359407825208940d2f39f251cb547cba567a31e5e9f93c19dffa85870e35fa931a000080850343e1feafa0f30cc48dba1051f2fd9819c4b02eece9570f10d41ae8b452aad94f5c42b82576a06426cf9fbfd3773ef5f393028b15eed015a6706e31f0240ca17c19b2351e7414", 105 | "0xf87283b2ca688477359407825208949eb31fb94ce5111e2a04cb9d156b513887ccbd00870e35fa931a000080850343e1feafa0d9f46a2689133b09f2a2ea0ee95d1ef5aba6b1f5c004d6920e21a3b90341e065a050a5e2b5684ea9970890351a7a15677fc08aa9a5d00003a5c452c6662cd42852", 106 | "0xf87283b2ca6984773594078252089404b88ef83f8c41b1465d360a1e82f07ae190892a870e35fa931a000080850343e1feafa051958bd1fe58327a52aa6a82e58821d55402f482b97328c60c4cfe01b8e36b3fa0539cd419d4cdd5c7c629820dfe8b71eb58ae568524e97b91a24731e521d2111b", 107 | "0xf87283b2ca6a847735940782520894af23e04b04fbe15630eadd32a6f27a5a65ea554a870e35fa931a000080850343e1feafa0381d17559d00a1b6325c610bddfc9bd062f1b12057ded89955ab7ed5cccd4d09a010fd329e705cd269278c9b5cde9b779ecaa8e358a337f8add40ecfbd75dc4499", 108 | "0xf87283b2ca6b847735940782520894746cdff371e3f1e905b3ac52280078bac2dec7dd870e35fa931a000080850343e1feafa0759d0869520d18b5358f314e05b69b1a90a326187da6a8008063d1432f5ffb22a0245f02da5d9697a34e53c312886257805f2b3bdfd840dc96322cb81e35823659", 109 | "0xf87283b2ca6c847735940782520894c33e5155bdbf1a0a7ceb1b80f8586c5cda5c3781870e35fa931a000080850343e1feafa0c252b122d4a06b7aaf7bf78cd11f4e1399f7b250c1d865582e9e08e4bd9105dea015b154437cb829de566ba07b719034333ac218d9854e4389f8ba2046bec844ea", 110 | "0xf87283b2ca6d847735940782520894e7fdef5f5219068f3d0f88a7445005574c662798870e35fa931a000080850343e1feafa0eda15bdec45215a52b664c11159ef2beaa944690a8f79717ac0ed1f0035f829ca07529a85f7eb5bd384bbb3b4d65542c49da763e1f897cab7a45cc6a47645b8673", 111 | "0xf87283b2ca6e847735940782520894f0a81a63c5e09b0bd08e027de48058e377d3732d870e35fa931a000080850343e1feafa00bbf6ac00d963d190c05442699a841f9c80ec9945931e6adbe253354c99a1182a050e0fd4171c350df604d418a7e4837e7b8796ba7429fe32f436a21bccb645187", 112 | "0xf87283b2ca6f8477359407825208949878ab34dc3b4a63c80fdb733491472c11d59a56870e35fa931a000080850343e1feb0a048e27126c94bbbc5405cc8375e1b7ad465c27d6c0bd76cb92d33d4040b22eb70a07f2c95cf62ea907537fda9c7b4f50478b0bd589af000a8040d579a170396915b", 113 | "0xf87283b2ca70847735940782520894912859bebae3086ac7a062dee5d68aa8ed2d71ec870e35fa931a000080850343e1feb0a0295f18dad24c898d1bfb52a5ebc66cf9969f51a93466af8f58f5f40bb39f7e71a00ebec2985dfe0273b9efe27b62a40d1b09c9b34d15d79e57ba410f9465020c1a", 114 | "0xf87283b2ca718477359407825208945a0b737ed85049410e5ea61f444d07d5c8c0359f870e35fa931a000080850343e1feafa04d86fff68888228429ec758044b01c250d411adb6deb1b0037ea8a82a72c2c69a0327aa62e850c6e885d0400921ce640bf774d5dfaec47cb6591c6f052b06ac168", 115 | "0xf87283b2ca72847735940782520894305a5dfd46e6128abce28c03b3ad971f4e4915ff870e35fa931a000080850343e1feb0a02e8f17f15ac2086ab70089d77b903b123b868bac1b3cec813f676f77e31f24aba06cb86cccf93c88eaeb1494896a199741aa20bd479f63e23df92301af6d812996", 116 | "0x03f89a8501a1f0ff4682775084773594008504a817c8008252089445fd980a780887e4fc4ae9f8d042d112d0802ac28080c08504a817c800e1a0015c8bc10440f3b13981c8eca320a2592d8af8fb6aa30a2b48dab94992d3f0eb01a0312cb2215fdc073c3861315c54aa152f685e45df0921003867bad8bee65aa107a05b49e2208d9e902d649c218d388ef46f1deb8dae206c7b6d719bff35dd53c023", 117 | "0x03f89a8501a1f0ff4682765184773594008504a817c80082520894807381ff50bf094ed69ce4e16d393a63af21d8428080c08504a817c800e1a0012084b96d7bdc4d3f8fc1689150593e498063b67fdcc8028bb0191c6d521abb01a0fd9b96ec6f6eb1e24eacaf9e0c69faa87a3c6d72349a7566d226c575b0faf4a4a04b493a211a7b6e46889876ad198212960148dc8e0af2b7a745941d49a60934c0" 118 | ], 119 | "withdrawals": [ 120 | { 121 | "index": "3969157", 122 | "validator_index": "2760", 123 | "address": "0x388ea662ef2c223ec0b047d41bf3c0f362142ad5", 124 | "amount": "2598" 125 | }, 126 | { 127 | "index": "3969158", 128 | "validator_index": "2761", 129 | "address": "0x388ea662ef2c223ec0b047d41bf3c0f362142ad5", 130 | "amount": "1299" 131 | }, 132 | { 133 | "index": "3969159", 134 | "validator_index": "2768", 135 | "address": "0x388ea662ef2c223ec0b047d41bf3c0f362142ad5", 136 | "amount": "1299" 137 | }, 138 | { 139 | "index": "3969160", 140 | "validator_index": "2784", 141 | "address": "0x388ea662ef2c223ec0b047d41bf3c0f362142ad5", 142 | "amount": "1299" 143 | }, 144 | { 145 | "index": "3969161", 146 | "validator_index": "2786", 147 | "address": "0x388ea662ef2c223ec0b047d41bf3c0f362142ad5", 148 | "amount": "1299" 149 | }, 150 | { 151 | "index": "3969162", 152 | "validator_index": "2787", 153 | "address": "0x388ea662ef2c223ec0b047d41bf3c0f362142ad5", 154 | "amount": "1299" 155 | }, 156 | { 157 | "index": "3969163", 158 | "validator_index": "2794", 159 | "address": "0x388ea662ef2c223ec0b047d41bf3c0f362142ad5", 160 | "amount": "1299" 161 | }, 162 | { 163 | "index": "3969164", 164 | "validator_index": "2798", 165 | "address": "0x388ea662ef2c223ec0b047d41bf3c0f362142ad5", 166 | "amount": "1299" 167 | }, 168 | { 169 | "index": "3969165", 170 | "validator_index": "2811", 171 | "address": "0x388ea662ef2c223ec0b047d41bf3c0f362142ad5", 172 | "amount": "1299" 173 | }, 174 | { 175 | "index": "3969166", 176 | "validator_index": "2813", 177 | "address": "0x388ea662ef2c223ec0b047d41bf3c0f362142ad5", 178 | "amount": "1299" 179 | }, 180 | { 181 | "index": "3969167", 182 | "validator_index": "2827", 183 | "address": "0x388ea662ef2c223ec0b047d41bf3c0f362142ad5", 184 | "amount": "1299" 185 | }, 186 | { 187 | "index": "3969168", 188 | "validator_index": "2841", 189 | "address": "0x388ea662ef2c223ec0b047d41bf3c0f362142ad5", 190 | "amount": "1299" 191 | }, 192 | { 193 | "index": "3969169", 194 | "validator_index": "2845", 195 | "address": "0x388ea662ef2c223ec0b047d41bf3c0f362142ad5", 196 | "amount": "1299" 197 | }, 198 | { 199 | "index": "3969170", 200 | "validator_index": "2710", 201 | "address": "0x388ea662ef2c223ec0b047d41bf3c0f362142ad5", 202 | "amount": "1299" 203 | }, 204 | { 205 | "index": "3969171", 206 | "validator_index": "2724", 207 | "address": "0x388ea662ef2c223ec0b047d41bf3c0f362142ad5", 208 | "amount": "1299" 209 | }, 210 | { 211 | "index": "3969172", 212 | "validator_index": "2738", 213 | "address": "0x388ea662ef2c223ec0b047d41bf3c0f362142ad5", 214 | "amount": "1299" 215 | } 216 | ], 217 | "blob_gas_used": "262144", 218 | "excess_blob_gas": "46399488" 219 | } 220 | -------------------------------------------------------------------------------- /testdata/signed-beacon-block-case3.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": { 3 | "slot": "9842336414825654000", 4 | "proposer_index": "14482319579077984000", 5 | "parent_root": "0x46d5fc7e8ad3bbcb35f160f0ef976a69645891791f9549cc8a5a8b40e3db1517", 6 | "state_root": "0x05bca08eb901ddacefaf6b3ac8e8dd11ebefc1fa35808b12a73308fa64f65478", 7 | "body": { 8 | "randao_reveal": "0x5fad44e6a16a4728fd0202f4b3c3aafd064137c2e5e7b5981e280edb4056cf7de3851e7312fcd382d9ab6c53881eac66c311f758e45d726bd5469f2f90472df658b84a90b28e02cc7f89fdb3e3d7ff215093ad06d2d7d6e1e0020a58270092a9", 9 | "eth1_data": { 10 | "deposit_root": "0xc47a4ef5b672cf83c25177cc1f503c598e0549ebbf406addc11a254bf2219ee4", 11 | "deposit_count": "762363676305402100", 12 | "block_hash": "0x9c4f0aba9de196bb2a8dbbb101093af75cc0c41d9ff9f177cb8cda73dc93f36a" 13 | }, 14 | "graffiti": "0x65ccd1eff7b49f188a339e2b2b6712a1ce93ecae879cb3eb8e401e57f9976cd1", 15 | "proposer_slashings": [ 16 | { 17 | "signed_header_1": { 18 | "message": { 19 | "slot": "3629487705303215600", 20 | "proposer_index": "17830448421432040000", 21 | "parent_root": "0xfbff38988ff28009a6179410d41bc5b5b99ca1234b568de27a6122b775e630c0", 22 | "state_root": "0x56e13388772500e3696fb442df30e9d09b1bad28bdbb41563751a7a019b0d806", 23 | "body_root": "0xa6ee432f607e91b892263bdd6be15eda02969f87ccbf67725e6e84ff76dd0a64" 24 | }, 25 | "signature": "0x1ab36d5399ddd1035bbcd6538d66c86803a5373dca8fba228773750ff76fb250a0050b01b07a418b447e73075e9d1a45c5aaf4e9b31aae931c08de1416b810258547a765e5e1e918e2287c2a994a1ad22039e18640cbb8732d9b4b44d09d470e" 26 | }, 27 | "signed_header_2": { 28 | "message": { 29 | "slot": "10422112460255273000", 30 | "proposer_index": "10854318824984414000", 31 | "parent_root": "0xfaa90a63712c986ef75adfd1ddde81cc84fff597b240580d24519a5eb91719fe", 32 | "state_root": "0x5b9f2749def45f88fa17f66ce522954285e645189fc9b1d718ea678bffce4280", 33 | "body_root": "0xd3156cba30c191d2259a88ade82a984d051bd7808d73fe8a3bdcd53da6bfee1f" 34 | }, 35 | "signature": "0x539612049fa0ecbfc17397f9f27c0015eddb61f2b65f215eb2fac7fc6730960f06b12c1d0eb6e34d427a5f68b8de9fbc11c56bb693628f4d16ba821e73c3743702670771c1c7e94760f59f9de8e39045c7125e4a348078642fe17c46217ba757" 36 | } 37 | }, 38 | { 39 | "signed_header_1": { 40 | "message": { 41 | "slot": "17853242742281853000", 42 | "proposer_index": "6594206035628208000", 43 | "parent_root": "0x06847073e46638c4ce0ac9787840e5d6728d6f15ab58b1912f7c6c647ee82c9e", 44 | "state_root": "0x9698876e9743845b13eb741d88afe39ee2a8dd3d69172b6f376d7e7cb53a1e2c", 45 | "body_root": "0x335337b6f203eaad02fcd22afa17baf90ecf45d216faaf09620f8bc62f95012f" 46 | }, 47 | "signature": "0x82834913e2db60e9b7baf3f2f9622fe1b0966f029e2cb958ccf2d61d13d426d9a1beccdffe88c83aa7e9fd96560a85ca12b143f36369eb86835140733fcdb0cd6567a59800ee55bbcb41df0477fba351ab61fbcbdbc7226e4621170b707128ea" 48 | }, 49 | "signed_header_2": { 50 | "message": { 51 | "slot": "3025711350364878300", 52 | "proposer_index": "13349847187119786000", 53 | "parent_root": "0x0d407babf6c53e72131b1eb3c2f4aa483594569d437cdb43b382bb0fbfe72044", 54 | "state_root": "0xb513b93df4125388b07251fc071320a704c96dd46531b75799ce8576f9abd2e7", 55 | "body_root": "0x9645365335dec6cadd27464ede134a3b7337a4adff5672ec609c660c6289272f" 56 | }, 57 | "signature": "0x9176cd73ff061c3c050730e0601c64bfd04c5720b70db87eb21b19c4f24f09285bd9ab8941106927bfbbec45267833b29c2d8a1900cc2801b822a03ed88cbd836c9cb3afc353d6f41cc1babd1a5156fd7018d49a0586fbfb233591f536345f4c" 58 | } 59 | }, 60 | { 61 | "signed_header_1": { 62 | "message": { 63 | "slot": "10330457995430128000", 64 | "proposer_index": "7306091100403169000", 65 | "parent_root": "0xeac3f6a34ff86906584b0475f7401e1ffae70572f5306efcba2299ad875df18e", 66 | "state_root": "0xa95d0b8d3587557640c9e4122e0a40e1fc4eaca679edc2daf1a389f78a353cb3", 67 | "body_root": "0x5dd6457961783188a962fc7fb8a0709c9bce86555faa20076752eaf6cfbbb3dc" 68 | }, 69 | "signature": "0x18721799ba785f8f5547d8e0e55299622936950f47041841c7c983db31c68817b029833e63f2c89754dcb7bc7dcd9d2142a15ad353203ad0bb18a6c858c4f4bb6b4e3ca31c85d69d5c2d317f1afa337d4ed9a1c05ea1015430907a2375a59206" 70 | }, 71 | "signed_header_2": { 72 | "message": { 73 | "slot": "7293941704353551000", 74 | "proposer_index": "3383975554034935300", 75 | "parent_root": "0xa957ec7fa712a2402634f064ff233f443af5bbb926b3f70db3a0d31086afa6f6", 76 | "state_root": "0x363558457e22cd6ffd11ae1cfc85cfe91556b97f0ada34395171d377f0eaa684", 77 | "body_root": "0x02f6094b5d8a2cb23e5a979b27beb25688d0a44b02d5f6e109fc686570981451" 78 | }, 79 | "signature": "0x35285b8373626457ead8f1b1bab69d9b396db5d651881d200ffad7a8a921166302959bc92d9058f5e1d59806ca6983910796ae6b88bafbdc8a202f296a311c1ed8c2ecc94208a1bf8e20362f032bd3cb7d51229c00ec54bf65fbd97061e1c4cb" 80 | } 81 | } 82 | ], 83 | "attester_slashings": [], 84 | "attestations": [ 85 | { 86 | "aggregation_bits": "0x02", 87 | "data": { 88 | "slot": "9602013141333477000", 89 | "index": "14154051867242856000", 90 | "beacon_block_root": "0x5e103b3418cece6c30b209816c60b973fcb5f136fa954f48697ab0101b613454", 91 | "source": { 92 | "epoch": "15473319409706748000", 93 | "root": "0x5dc240e8cdcd90ff2eb98f426524b708b2851e3b324694eb4e34dd6781a5dd75" 94 | }, 95 | "target": { 96 | "epoch": "15186970683220564000", 97 | "root": "0xb7816a7c8caaeceab13e3714336608ea1efd417231abb338cce4124b10659b57" 98 | } 99 | }, 100 | "signature": "0x6a8d1c8193af85ae310d896f7f2c2cb1bfea9f780606e971e04a5d1f5661779b883f9914f3d6c875b1bc48833969b41638f98dd3b01c611dbc70dffbc67388bfaab782db03b168f10f7bf8e47592e6807e149b5f15a9b251021cfab8b43ba29c" 101 | }, 102 | { 103 | "aggregation_bits": "0x07", 104 | "data": { 105 | "slot": "6822863000289142000", 106 | "index": "9193260906720932000", 107 | "beacon_block_root": "0xe6d723d1bf99bfd7110d6e10987a3ada9c99805bb8df2b6142e069a9799d0f8f", 108 | "source": { 109 | "epoch": "405508449426527740", 110 | "root": "0xf322de660523885dba3b90e401849711ef5f368942f16b7ea90c0c5df6e38e31" 111 | }, 112 | "target": { 113 | "epoch": "5220197178836429000", 114 | "root": "0x830d277e488cdeddcc60e34df85edfb5e74c73c2654fae25cefa358a78464042" 115 | } 116 | }, 117 | "signature": "0x0344e653207849557c448580030b1c61249b875fc040b9022a013cfe7cc28f55c97568624cbc4d5555fe0469ec6cc3d463c4bff12ab962e00fbed28aec3bbe51ba39a747d4b014db8a81d80ee4aa2eec681220085069129a67a09b7fdf2bc3c5" 118 | }, 119 | { 120 | "aggregation_bits": "0x1e", 121 | "data": { 122 | "slot": "13462428366060646000", 123 | "index": "2150899684031399700", 124 | "beacon_block_root": "0x024a49d4b14aab6091cc97720b8fc487c72e403509ed5adcdb41a40a1c2d4763", 125 | "source": { 126 | "epoch": "5995828484674395000", 127 | "root": "0x9377cb16b288a48464a6d39609a8801bfb7aa146bf409696a3aadde97a9c1fd5" 128 | }, 129 | "target": { 130 | "epoch": "14772275929992958000", 131 | "root": "0xfacfbd55877cef97710727fa201d71e5888e8fecce0872fe5f50701f0bdb4e06" 132 | } 133 | }, 134 | "signature": "0xd69b0f47f2b740897cd3cd501d7bd658e1312ac5fa8e5d5a9eb687a7e7ce83c0175b744a90592ef78bbab05879e3576edc4967e5b60b90ba5f98d0fbcd18909ab97fce2f30e724b297b1d1a54e7aff4a39e767825021ac965c686380d92643e1" 135 | }, 136 | { 137 | "aggregation_bits": "0x01", 138 | "data": { 139 | "slot": "12958554935869755000", 140 | "index": "14158142389716894000", 141 | "beacon_block_root": "0x965815102ade878cc68e47695e66d454186bde71294f61a5e7f3026dec591f80", 142 | "source": { 143 | "epoch": "8094044670891228000", 144 | "root": "0xf789f259b33b0040605cac9b6e2694e6b417c9ecb6414dcef1ac7070453f273c" 145 | }, 146 | "target": { 147 | "epoch": "16155358867310810000", 148 | "root": "0xcfd19f4d4fc80a6359ed3be382b3f2a7e824f156e37059fd56b426cf152f9d67" 149 | } 150 | }, 151 | "signature": "0xc5535adae2f982e693e6dba954cac25c0ab5a6c1ccef8efdc3b0132b5bc55a02cb811dcefba6c7951da59107818471d6534f3298bdad665dd1808308b4f2b6a88f8353e752f3eecfe48ca8fb34b8ad164e224c4fd2f4c99e4d9254f08da422d2" 152 | }, 153 | { 154 | "aggregation_bits": "0x3105", 155 | "data": { 156 | "slot": "13805827155749542000", 157 | "index": "4179967092375045000", 158 | "beacon_block_root": "0x223c40b9eba30c7754622ed88a31510ff7367bd290c4eb53cfb1b6b8991d47c1", 159 | "source": { 160 | "epoch": "11318720328327590000", 161 | "root": "0x36d8a656a2dde64b19f60a203861786afa06e41bfa9ebc841f877869ab5aa26c" 162 | }, 163 | "target": { 164 | "epoch": "3044679531883020300", 165 | "root": "0xbf6c6de9c50d42684fe9d763fbcb7d237053097f60e89268ea0f08bab38bc286" 166 | } 167 | }, 168 | "signature": "0x8605639b39374c578d6abf3011c2124966578496ad2caecea800364f16b61b4f6953a3354a07d0358a59bc000d780530af582a8e6ddc64dd40e6818a32124c1c564a16646b31a5ce7206d84617ce5bf71807ed94f49cf9e96c083876cd5d9eb0" 169 | } 170 | ], 171 | "deposits": [ 172 | { 173 | "proof": [ 174 | "0xde2f4e57da0453a7aeaf9716c8457ff4d63d44fa7e06e57dbbdf8fa579d00a8b", 175 | "0x2269289c204e74aaefda91ab80f8e868600e168173b8caf48ae40bd5b849c1d6", 176 | "0xe1ede8f652a8f39ad4b5f726c4d3af19115f0f005dd4decd7f9e7d3114bb271d", 177 | "0x7ac0c394793d544f3950f14d0568d87b1f41ab4b17ecee4687344384988dd286", 178 | "0x054dd78b6b036363c65fc26d9f2c1c0523e24142d158f55b3c5f5b4918b9ada1", 179 | "0x169f8c45f8ca4bd25faf867069dc21aa9ba710e03ac494ebfa317fb3db5919d9", 180 | "0xd704c07f6812ebef941b8b3cfe337b8b62e954c9952e1618d81572a71cce2384", 181 | "0x0bb90ca1366627de028ef5ad7a19674117198eb96eab6620fd911216239a9ad1", 182 | "0xffb85dc825748bfa1525b2c785707d81ce5176cdd545665739d1acde12f91436", 183 | "0x003b8e1a5a9f8b1272aa8472b0996da95bebb7ecbfa05230ac8de55d99ea3d62", 184 | "0x03b8719c4d5aab1b921937ac4a679ed6d07a14b5a29794eca09431f32cbd701b", 185 | "0x5d529129a96a5277f213375d58992dfa99d6465e34cb88738be5753dd86933ec", 186 | "0x3da1f2dc652656f16df4dcaf28baad64ca1bb57cfcacba7d301a396927ae536f", 187 | "0xe75deadda2fa9bdd0ba0d3b16b7aa9fab4c7ab0c53c768e9938defb4d1c30643", 188 | "0x77c71474ae9733aa7adeab302e56501d0a539f0b0bd36a9c17def0c692f85634", 189 | "0x4c8a1313c0d2915d2f4734ee7429c070005c0bb66d88aee01b8d08822e9d3c33", 190 | "0x0a0a79d9212750210eb164eff1b4abbf9ceccbea74e4e59bc528895ca8d8efda", 191 | "0x8fc992bdba805f8b75b8b66898e7fb9151dce868f4164788055a48a451413e25", 192 | "0xe34f574468d61340ee6e9cc3f87b817a1de8876d71508184d3b664e90fffa0bc", 193 | "0x1e0e82d19e8fa5635e778fd4963ac79e56cdcbf4c3112afe52271604ae9b696a", 194 | "0x0485150499138afe5427850ef856f379ff482e341ea870be5090e3fdda48d206", 195 | "0xcfabfdab36a62f356d91737b3e31dbf0769c6e916543632a2dd890e05e93df1e", 196 | "0x822c8f46061b2ee7191ad61c5d7e7849414b4fb1ee501d73cecdb64c0d490f4e", 197 | "0x05575d3faa7230e8583966b15afcc79515cd6a654439931342bbacfa9ddce9a4", 198 | "0x2b4d8c1eee497125586c9370501295163c55857a00ddfb67207e351d7680a953", 199 | "0xcd521793c3098c93dfae946f6c3cc4680bcc297c8417a99c7b0ffe0c0ab2da79", 200 | "0x4d8c8f247fbe1dfeb4ece36f0db131ab9a33afa1b6b8e763c823d640a2f2642b", 201 | "0x073c7f5f14a0bb5618a3e4b58f77c806bcca69b202e51e814b102eff8d07137a", 202 | "0x6d4943e7ef21afb75aa84a6e920a5c98bd275104e17f42fc87466aa44b8b7729", 203 | "0x2ee8bd521352ecddfee6c25c238d96dea2d9df9b4c6e6ee802c85a0679e2c525", 204 | "0xcab1419f8294934c2c663706bcad664e2074bcefd285f0eee85a0c5c5ed9b110", 205 | "0xb8f1c74dce6aaac661c69d17dda26a81704548e22af32cd34e3e5b6a67f5fb33", 206 | "0x932c10a5cf3475db57663896dec11c77595002f3f5ec0e8f5d602c40efe60f22" 207 | ], 208 | "data": { 209 | "pubkey": "0x1ad68af8db4a9fe854dcbfebbc57cab98329d5b3502a94dc3d71cf57e6bf6b3260368716def8bf969735659edf63175c", 210 | "withdrawal_credentials": "0x8610d98d5f878b48b0895d6956cd2adde3fcfa113e1e617fbf4f78e5c6f35aba", 211 | "amount": "6506381767954058000", 212 | "signature": "0xeabc2c61161b286df567bef07ffcde27308e4df3a3b0401759c20688a56ad48b587256ba57920f9ad32c1e79b3002b75245114a2b49d310ca1043665fe2871be2610b8e3a37d04c428b38b8d711d1f84410a8bdd488f621368925db6374164a6" 213 | } 214 | }, 215 | { 216 | "proof": [ 217 | "0x0eb735e557c6e6e292bf30dcf1927d24e07ecd03350fc800f9cf5ddc385636ea", 218 | "0x9613e1bb7e9f58be006d609b194884d9e0fe3c8d71aec6003acfd1e7a65702d4", 219 | "0x9a21ac430fe8e05939d9d7f28dcf81d5caa700da73229dd2f0d2899275bcee7a", 220 | "0x5537fc191f88f50bcb6462ab31a33013afcf55eaee6c2721b4a01ce94d62e2ad", 221 | "0xfa91c79b48f5b3fcaca39532dc74e25a08e4c1dde74a360af9f226f3c256e3ca", 222 | "0x99a68bab8d11159d6913e84f23a3b98d34dee1a46b0d23ea48862c211e6fddec", 223 | "0x439c6e09ddb6a73e073619c06c4fc1c47b7f028e33149af6b0c2a6f3216c7c79", 224 | "0x9c27c610b99345280f0c18a2f0ae1f66ea6f0d928c2ef4be3b759cd2fb8559c9", 225 | "0x1ff04bacb3ebf6d8ec772cf1ce9470b10ce5acbf62016a8974b378485d4e1dff", 226 | "0x3cd7d075b8dce00d5129472222f83fdb8356d470e24f25c36b5ad3feda285845", 227 | "0x5fd4f08de58e993c529173f55f99f934f50977171a4172e847bc17628c2df6a5", 228 | "0xb43165ca2b18ed55325ca04a05e614cf7b4574e8b8402d4dd33b7fcc16595540", 229 | "0xa28916b4550044c3bffbecf2c79d6141185fa599e526da5b421faaa6cf02c192", 230 | "0x3c77315b781e747dd8186c3887789739e7254eb51630a4866e4cfebd1d641594", 231 | "0x2787a7e755a0c4229e60a8e587a63f56cec5154bec0b6178e2602e9598cb49f5", 232 | "0x44be1971359674531a2bcbf9fe15fd7444a31c59f6e55be5e5f5796bee4ff091", 233 | "0x71a317bb0e72888e0cd513de98cc78c714f2abd67e458905b1c5844f0a6bccd1", 234 | "0x6b9cd548d8d9f07f9690fc4290a629988ee9b0516040a1c847be9cdd4510766f", 235 | "0xa475b9d1f16b3d7517f09a383ca84467a866c59b645ae1eaf26127ee41178537", 236 | "0x7352115e5b394d78d9a9c577dce7dbe69f0f4ffcd0a7dec5491b1afb0767f474", 237 | "0xcb620c15a827c393523cb1f9b1d73d671ef6d39202ecac7a93b195b649d6c520", 238 | "0xf143e64725064b5872efa8bc8f09b8620573fe266848a27c66d181bd9d6a5d1d", 239 | "0x0a02dca36086f4e97fa6ca0855f2d6d0ca2fdce2d4a3720c01d94637d42add1e", 240 | "0x14b5e3ec5a418b40f4a0f55756bb50bb61e93bd02e59f24c3c9bc3550130e921", 241 | "0x1cf75f3308cb69538f7e73f80b0f8c1104c8002a416ce9636cf941a7f51f9df9", 242 | "0x076da0c2c67806184675f170b7db9149789e54a7bd8e3e9f488ffd8411bee4c9", 243 | "0x37559325b69a2454e87da6d62a2a3b0a39d43173015b63658799a7a2cc26bc8e", 244 | "0xa7f7d386dfbf3e3722444cb347598c826d15ebcd469ed644bb4c32c417a3568f", 245 | "0x72e49563a33010a218cd705015b75d2314c27978d64ddd442ec50382efd0e36d", 246 | "0xa891b93a9e9c7aac821f66064d6e35067e4c2a00efbde07adb9b22bd78ef7b95", 247 | "0x13f1006d53d71215d84ca9fd45c4a5f849617ffb7949210bf4cc0c8240385f67", 248 | "0x19fda21a2177cdf14ede221056e851fa028b116c2eae08b5301fc39551d163da", 249 | "0x7d331125c7742e56acbfa104eb2d00a442cb5896adf643fa378f15b4761b4875" 250 | ], 251 | "data": { 252 | "pubkey": "0xbb7d19d26b5d0ca1963b3e4bceaa7004da30b1b2e88ecf719047c1ab1e9a63acc8a80b5f2fd4a514527c5c6d913a9216", 253 | "withdrawal_credentials": "0x0461117d5dec33d0a968ce4d68b04e2634bdd12aef8e2f8a179eb218e2e90cc9", 254 | "amount": "9870014802548984000", 255 | "signature": "0x6eab6a15de21721c6464536659f131f9a3dc1535809f766eb9847c48a7a0c8a43aabb98b92a73347715ff8b7814bec0a79e9df5a640817cdcc40bb3a7bd3504fb779edf857918b6aebb8b8fcd340de8a547b3e188f3c765107a166d6d40671da" 256 | } 257 | } 258 | ], 259 | "voluntary_exits": [ 260 | { 261 | "message": { 262 | "epoch": "18280873552634216000", 263 | "validator_index": "1907784727745265400" 264 | }, 265 | "signature": "0xef35a9c3473f09d429f77608d22917ec9b20011bc93a9d2c5ca10cc3bda5ea83c5aadfff318a7bd325178edcce9c3d2f8fccb1fecfe4705fda3414f0586261d4b310465ceb4753419854bf75edb223faac484ab339507b490ee15e0b3bf5c6bb" 266 | }, 267 | { 268 | "message": { 269 | "epoch": "1654766769221751300", 270 | "validator_index": "725716387937302300" 271 | }, 272 | "signature": "0xabe03f8b391e96f57a523612397141e0bcda64d353b69c9cb5274a0fd06f3702b3f3076abc70edee3dad7948a6bc2dd9ba1aeb0c0ca76893d6c7bd2a4c6a5b375242915749b8dd3b66503417e0e59e42f13eef7af1bd2e46b84bdccdee540057" 273 | }, 274 | { 275 | "message": { 276 | "epoch": "4795469429484190000", 277 | "validator_index": "4461919675827097000" 278 | }, 279 | "signature": "0xd2a1f97f3ed61a019eb60b6ce2d27496429fe7b6304c9c304e55f4464e2a4bd3f99b76bac01756cfc27355e62255bdd4f395b80bb66c231f20d056e2519cf8f465e1d0d625646b1f3e98b59f6736e3764630ae809e27499dbdd224901fadff88" 280 | }, 281 | { 282 | "message": { 283 | "epoch": "2422866004015034400", 284 | "validator_index": "13712696795854428000" 285 | }, 286 | "signature": "0xfdcf1eb37a3ec77cadeb1b92d845f699dcbc6c9b62ad16abbb022a01f7fcf36f2b4fff0123c8f00390295703aa8a06b5e49a8bda16e118f15c548ddb317af9b59373ff371cac0ad6c824fc2cf30f46748f034e17db9c77cb40eaa754fe71f80d" 287 | }, 288 | { 289 | "message": { 290 | "epoch": "15924116691295400000", 291 | "validator_index": "1997370851126592000" 292 | }, 293 | "signature": "0xd70594483334d9dcd64e01ec3a1ee54a40993ce88a1943ff3d1dda3676c1903bd6c3ebd85181c7964158a75775a2503656a7bf74df75705e101f587e8f008010c2b2cbf3392c10002c0baf8b043dc4854b25ea28ac97287077fb6f1a0a341291" 294 | }, 295 | { 296 | "message": { 297 | "epoch": "9275141981770482000", 298 | "validator_index": "17637239179037960000" 299 | }, 300 | "signature": "0xf0af5213f5eeb34c5a7a58c709ddc0112a8f39ab3cd058a19ff98b8860cacd9cfc13f576259c104566ae1ae28c906bdee6060aef4ea7d86733c6659cb1e81e49ae3b0916c02e17e8c5ccf3459dc065668e9c22c0a71dcf37199a97b912f864b5" 301 | }, 302 | { 303 | "message": { 304 | "epoch": "9679144972422396000", 305 | "validator_index": "10219099784385737000" 306 | }, 307 | "signature": "0xcbab23343ffd5013355da5a166357652d0f75cb5d0b036d2f41ada593e2bd635f6f87d3191bcc84101e08b41b8545d8204ca82424ffdce6954f39f2b8805647822737a2f7653ed6a2f9191c48b6bf55167b22606408a36610e8213029aa4c49c" 308 | }, 309 | { 310 | "message": { 311 | "epoch": "13749984235248785000", 312 | "validator_index": "1482453940518935000" 313 | }, 314 | "signature": "0xad8f4ca8a000c7faeb8943a5c71d6954849bfff9f53b3049774b1e1162d93b8fe89fd979a46186f62a5b8a40461c5034f37576fe55166cff19d7e28612547b03cde9ff4a50a3d1e51bdc424c9f18a87aa7405bf095a00644f2c9875957f17d74" 315 | }, 316 | { 317 | "message": { 318 | "epoch": "8481737146599469000", 319 | "validator_index": "1649916858439130600" 320 | }, 321 | "signature": "0xb53245bf598cb2af52158ca5b38145eeeab761fa0ae7a02361d900f7829d5e781c71eed57c60a134cc0e8ac45464812f311b2469d2b1af68dfb2e5a9a986cda34b42b3ee856aef7c8b7b1ac182e6e3361f34f47436ae3eb4fb48d32d31d56bee" 322 | } 323 | ], 324 | "sync_aggregate": { 325 | "sync_committee_bits": "0x0f0c865fe755385689a5b7f6499647eea0b208f0efb7c2c93298f958bafbc9a9d97e86d8ae45e27610ac6eae355866ba2edffddf475958bf990f6d816bf93e8a", 326 | "sync_committee_signature": "0x04723e73813f895f7799188e8500df99805e5abe86937f634ee7f6073002390746d1ddf55d1029fcd344571719d5ba0566da843793bac91b499061377a548747dc7f3cec31e400b7d7e0e651b514c985ee45c261b2f12f6b04ec4200a4bd9eb2" 327 | }, 328 | "execution_payload": { 329 | "parent_hash": "0x3972fde47aea48038daad866eef8f1996113001f3532d47ec122c8c66a2c731a", 330 | "fee_recipient": "0xb020b67fc2b79b832eb2194c1d7b898e21d56ba5", 331 | "state_root": "0x1df90d8ce12d58345515327b73a9a0779eef1570784f6e24f913c93a75833ea8", 332 | "receipts_root": "0x7493886757da0af9f40348b7959aa2c5891cc04cc04ac3883bc697e2eb37607f", 333 | "logs_bloom": "0xe3ae07f94fde65d2cbb9b92cc76bd0f4a62c0efbe26567365c61e16f9ed9ee52d2981eec2f48ccabf9259d4100008dea6c68cd96ffe0ac3b082d0d5265c0ef73162c848c322c19007c8528272c7af54bea88b75e5d73fc0fc0e10e8b9f4018fb8c7dc78293db4237c968f02b42f3b81b1c362ec70603d8bd15c290650a30aeecaab1a812e31acf2a1406ee2e7c9d7058f9a2b4a38673488bcc0657d4c1802a12cbd118b4ef7f1cafd808acd74d77079986d04ad4df8c1d6052e809138769b2cd72ac4647113150a5c611770441fde22c993fb07c77dac20a9d62951054849ec41bf2ff804a248a949f166113b8fdcb21c34f5298b4aeb4c58115ad335daa2289", 334 | "prev_randao": "0xeb5fe3b97931d1b12804bf8ee3216dec916545fd9c106960f81f979bafe72f80", 335 | "block_number": "8442873866509341000", 336 | "gas_limit": "10300611846829949000", 337 | "gas_used": "11767778142767878000", 338 | "timestamp": "5652674190906429000", 339 | "extra_data": "0x2b96e37d0a7238e254831c89b9c7ff63bb7f", 340 | "base_fee_per_gas": "113633488520309979483915179673161634792525607390229707058937431146782100115229", 341 | "block_hash": "0x1d3e3cc612efe16725ba15e19eb9aa42afda85198f15d1dde094167ec14cc4ff", 342 | "transactions": [ 343 | "0x8a1df8fbb54719c62b42e7379c54b622aafc526cf84db305f1df35bdbbb6b8cab76ca95aa44f83ae47c00c5fd0cf67b12738583b9f8a8003f20243aa111ee1664999accb3bb0b7089b3d333729ca7a79b243725f77c24a99afc0d3e8e33f2c16286cda4410f00e60be15c06657117f34c2d8583fb67804c081052539afa03535aa87a5ca577ed3e5c33446ab6f39cf51d432de31974221edf169ea4e33d6c706ba4cb8f7279365aa1233e63debeedf4902c36de9c68b5bbac0f4279685b8f91dad69b77bfa912d0380e0df68c2642f9564c0c9405132d519fa98dfcb72c364ec55406a6fad68cece560dc21ee7ee963b58dc6559dbcd583781855d693f9e971245fd98ce86934d3733db324a326a6b2eb9606b13da4298b731f22ecc49bfcc48c3974d10db8cf9fe9fa5f53bf48015ca5b3250b0b102182f033f5c65a9fd660b0449d40bdd102e94d55d2db22f21ff327091c914e052329068e0dd5bd67a4d93015978aa9d2e5be8965a3a09a0e47666084e736d81723c5e2c4a819314f4d1261b180ad77cdd7b343112bf1a4a5f47d239c56e1091ea3aaa9ed014f64990b5c064b2913eb21f8b6082f35f397921df5fbb4624cb3f5d54c90855b566ef554fc0e01b68561cf93353a59f24e5d59fc0f8c5232480fdcc6c08e446a967d1a9507518876a1b7a57890cb570525e3fbda90e2e044366270697b733c3967c02234eeb7bd83ec49da59a0cf1b66c633211cd5ae904f0f8bb200b7ef47b31d0aac234d150051a1c388c6e0d76b6a06e258a3ddf0a8deec1a05fc2552f63d1bee79776894ef64fed47108cb6b6d1e2bb45929eea23db3053a00d8a9f77af638090dc04abd181abdc71dc2f2ddcf120263074719243ed8e459ba845f1cf16a1a657e91af5aa2962534abc3ae4a8d86d41abae1725fa35439ad6e6f411a27d659b25dc54af0f328261aab4ebc18034471f198925ceeae8f2ac6837588ccfb1f62f81d2e0b4d5db1d7232544a76df5c12875e8c4cfd4529fcd734c213c5d35abc59c716f0b0f052d977b5591efd3deb5b4cc8bd3359aa30de55ec58234a836572a7cbaf0b943c91c49e0d17857465f44916133807b1aeb8e7bab08dc0669fd93a534d7883adc04ea321935835b8f20983a51dee8495a2e52dad158b05ce16f771d7864d794d3d966f43c63f847a200f246dedca46145ed1836c888e555771823042f2a92dfb8a44b75624b0876d4856b600b76f4bf691fe83900a250e2a3e86497369a23396806efd79d009d9d91f26da987819ff2e1ab0787c94a8274ec782add3b21d80588f2d940ad89f09fcc1a2c561e36cb78cb3d4d75dc73dcd18b668f19f9fc078988067", 344 | "0x2ec780597c7a8da53ca045d53631c7a9b54f85de37c0292a55d8045dfee5b8d90685febbad505ea32375a335c9d6bd9e6cef4c55bc79c5bd09f66fd5c46430d95a49c9ccbce24c47e52444a87d97ba447a3874616d9b713bdc393753a98a443bc98196c13bb268672921c0cdac310ea82dc7efcb9687429d9555032155a62f12993ec3db1608cd424fac11a8da5bf9b38f0b4349d3030b531c278039b1723d3fe0035b284ee0545326035664a32f93d5752ee2b058b6b16ae549fc7fa292d8384547a6d22c9f93306f60334e8dfdbe79bddb1c3eab8bc3b2624f6897ab790e53f18d9b59f36f306577a886737e16b68a500286d0300a055a15ad545abe3206ac2357b5de218fcf38c09cb889acaeb5453e6e300396747a5931fac09309cec2375614c0b0fcbcca7b628b3bfa7485bfeeb2ccaf177f3ea20d487f462b81989927ee21d188a03e2d73242fe55abb504191baa156961d1f778797d9d8963dbe46cd08e88806e1d235b67ada49ef4974b98dcdb6f7d8c213dbba2c1385e71bd354a2f3ffe02173aa3d362e067da0aeaf26cd61296d4a93035dd087942e5fc37666f8cea557d078306bff96d71a83c8c077b27eff22f233a0fe6ab9b559cd13b9bff0b9e188798c1b2f940c6358944ea48bd8966e55a6920f22baee1c89ed94b62a9e9736a29397037c3b7a68d7ba2b24b53665372cbbfbda80dc0a33debd58e93db11795c97bdae7f0b6cda18ff05e6ab14a", 345 | "0x67bb5b773de5700bc60e7b77780afcb51b778efd095bd2f8192b3d3ce8e7a62affd226f8be1c2438f097be5e8cdc75ba94af1b29a8d7808d7147595161c531195c4406700585d8cd6ce73b01e7a54cc0d3833481fb7b8e166950daf9303f932266b638e4774e3dc69373fb65b23435bbc00b1619a81ac691caf328d75c4a88463307d87987fcc48f3a48b8dc80bc265e2e0428254b3b33ad0d8e6d3dcef695b2409460a526cc8f9b9a7d4128fc3e5ae3b3107e14d22b6b9fd51651f1b589d5f52fdd194bffe5aaa264ff8822fb045f4294b56e13c0a706e5fdfb4645e956439aaf93b69078eee6ebfd768c75e1cd5c4ce1b92ebdf54820e4aeaace0975c40e17716e4692bf7a3773db8bb76118258c5f3cb536c2791aee4514140f2555c121eb65ba4d455ad533e6f2e0854d0aa8f2cf1e2be112ea8b75af4ce870690f05f365994fcb8012d944b4507d371dbe1cb2be8ec1183074dec2360214ba610d312f3b9d8903d052ba32ac7b3e4c317a63147f75dafecf86bd683ee7d04eee9d96be0b2f01340be0cef2f4465280daa04c8e94094c65936234c244fbd8cbb67746a910b0c8fcb45892d2c64a8b3ae005d932d8a7d5029a7a68a73163f24aa2eaf3359d1876314b8b173a39a00cf745c89313145087cfcb0914d7b84c23bbf2561af42a5c55b603a12d7de490c09465ea7fc8e504ab5c8371cecadef93d7fe2546070701ee0381ce4c7e884fca40c6f127a6705936d6485f8eee863c31cff0f4bb180d87209ccf59dbc353718fcd8d94cd5047986bbae4f2fab0224f89a27c0c177427bf3e0b5a7ce16c3076a530e6870be8be8d713906ba3d802010aa3df2f076e79b52cdbf2493c94d2a3b981411bf7e6bbe12479c8b21460f7e327a453d42f6e7c60716dd354f959c23861d5569c461f26608d3c49dc820dbdd7c598da5e22e18a1c48fc4ed8b51ade1ac7f316e44d80c0b839c4db46a9b40dc7fa2098e035c808839a1e1a1aa2b39117a97f8ec4a1db937d15dac2412dfc767e867d415ac36c9561bf3d9d8ca5d4f5a224c338c8f59b8f1fd79b9cb737f754aab545e9f251e9cce2b225b4f164c5ed9ad6c1ce00387e9af0c34a51fb6573f9f502eadbdd2f7f653d1f7f7a3c296f3a5155190b8c181d059853", 346 | "0x528cb43ff90eba56dd70ed1a6d642991630b66257304864062c0898b12f7b3dcd0481e2fd6925e473b6ef7430c6c6a230bfc187edc69ec949fa7ac248ad7d80efa79148624c4be7dd1c119c388d88cc65eddeb5360a6768a7b85cf9da858888a1e8250f53c157d98165fe413f8ffc0db6399325ab67907cf80e3e0ed4a6d4c0fdd5114455516b98ca62389c861653cc678d955f7880d6996c46563dbe52e1126a9d39f1ce419cc95ab053249f0ee2db843eaf494a289d73f05cefcb7afbfc06c7612fd560763c41d11dbfca7499c46e1e5e27888a10716ad96204fefcbaff625d6a0519549463ab8374b28e06186cb22a1d5e94b78cc0be2d32797cfc30eee344ae83292854dcd50830b3b83c43c192324c3af2c2b1f556347725b65f61de7cfb7fd86162d13935e6f74f20b52c4a0aa8ff04f60bdb2ae570591e11692aa3da2d06f42ac0ecfb94b7b6afbabc3e31e866d54009fd462acff20a80abef577710974fa51f9f6324383fb35dd71a81b18ad53ea5765c4bbf0d0c09d71bba311e439eef1e8a4319735941dc7506fddc378401e27f2853385d73ce70285992a7bfa4f982df3305b0fb93af2b90dad52c5ee9d35a349d2fbf633a7e25c84ffa3dead02104b01b5738a344e221b5ade3d5a5b7e2c19552d200c39195a205fd6ad7e532e3e0bdc04a601af9dfbd76da08649be75a5f12624181b48c301d4d19849ddfe8f218a9e3e4ffa216001c42fc162539e11ecf40e97bd165c634a9166ca0df3c52a337cd4eacc8042c6f016f8bf350e60ddbe36f385d18d9fd341e585cf224907d34168fa2f1672ace093cee9514c53b54d6a9375311aef654ace876526455ed947d3a22ef84ae760f5eddacbffc7871ea0b08a6d3f48ce5e8efeb1649fc5505bc674d20bc65e9628029ae1194eb6ffc820420346f63b3cc6e1183203fcb6b551dae090a5f2f468d52f72d117c7c9f86d4fa12e90c0f815fd75c965f3798fe3a13027b2173009acedc74c3b22faee93b07955d507e4dbd51ca097e2af01ac9becb8df72f715ebe86c8e2ee630f6c8d679b3d399a71bac3cb98019e901869c2679c1d190c1ac0360b4d55a55a3fb158ca7272273a5598857c818855c7de7", 347 | "0xe9202769b752b71a4224f3e4a5b955c14deb246f982cea96cca7540cecf508c4cb20e717d52e7a7ebcee4a9abf78ff629be8e7b1852b3aab4bad1489e027ef419bdd99c68af117ffaf72b50a7354eb2a7ddf99e1d81f4e844427b8644c0efccc81b68f04f3db7c7b2dc55735db3f4926ac139a36634bf76cee0b13cb62325f69b3eff1cfd5ef68b6f7c4b92bfbfa1cce4a3ed9772767c80ea32eb348d2749737eb8b36853830c0446f99a0de6badf2a15a0d835e2f8192374f32c17f9d7aa8eb3c2e71d4a08a298978f07385e48c75c94aeef40afa811b366a61d5c00af6ec510a0de564e95121b91e12190dc947cd3fa02765d57b7922b80c20b17efc90a99b68f07312be4e3fecea750eac115f4bf2fe22af77e680cc1362cab93a0b079132eccc5899db01f60afadb990bf28f5218c692e4729552f675f829cb3061ec6a5dd55dd3449cad33874cdd1e191f12bac8346a7e4bc531256720e0daacd17e26a08127e23d8a8aaa54b6c47604955cedc08c4278359ecaaf2bf8dae0f025135e7e1943dd4ee8b5da714ca9190ea5838834d48b93f1509646d0e17a8c85b0a8a9e2ea96fa09a3293ce62a4feda61c9b3f1829df751e6c99f99bdc938166dfbc7e2c18d6d6d760a6394b076ed6d76732a110f50efc2db9306bbf5f8df465328f1fc3a4dcaa722e429619a489d2fd398c5fc2e424e663cc1e157a0bc1b6bf4a724020568f933d9691f6d4d2fa316632ff4bab9739c0309c90be087c95678ab23d946b8ab78de4e4e9ef3c3245838917813c025d25fa2cabe03d6684d7357c1dfdc7ff50e1e25bfaa5c07d2370af10a5513b985fc383b5975e78ccf20819bbe13b96475e4dac6977ab04cfa91c93cc8bc708ae66dafa86eecdfa8bb0a3ca4bcb5b607152082240cfa42f5b2408b92f5a2e84f278719679bac4f996b62946a582bc8a99a3791a3c61a4170fb64d554cac92480cc3a8305ac9a87757b61b79e08076fc45b4d44db877db99da576bae729a4b5423c164c817440e5e07723be167bade452ab056da0d2936092a2ec2cb1623e1ec4311f9236e79d64b077db67c36a5338cc4954a67bb0febddc864bf86d90bba8c56a39a211ba6fbf7d5058264cbc1472fec29976d4af9d6bc34d647fdb0491ccc9d8b11920774b69b53de65f2c378065ba6881ddb3788faec0fa1c92f9b09d1f3fb81cbf502b918e574f97e0b7f93cfbbe71f8aea35714d36fd822ec51b3e78567dddfe6e25ef406dbff8a08f223e6be98b18ad06c37ccdfb3c98aa5c7a255b86775d9772f3ada51024e746e74645c81a3f0c44b7281d4ab53d726294da9e91b709697f0c33f32a4235daa9cd6a279cd463ff", 348 | "0x54cdd644f421a29eb737db2c0125ef0bb4ff5980fbb3876368a1b762e864ac5b26e8d1500be69e30a6ddb30f8432cb28fabbb13fb292709b" 349 | ] 350 | } 351 | } 352 | }, 353 | "signature": "0x364cae61532d2cd1e04d98580a723a94a47588a690a1f3fa09a4cd38e5c981e3079f5890c553badf056aff6ce3a15f20bf0fb3f5c9429cacc03aa6fe1fc219b31f161215a53de08358c250b0da0d034ec9345667805a738503828b1a6b533b7d" 354 | } -------------------------------------------------------------------------------- /testdata/signed-blinded-beacon-block-with-deposit.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": { 3 | "slot": "1024716467251563373", 4 | "proposer_index": "9821443871061890312", 5 | "parent_root": "0x8cee48850ca0c517c79a07f4c45e403427b484ef8db321052a1d69762190eba6", 6 | "state_root": "0xd28035bc142a55cdc81784bf364479a57fe261e43b91664c1d64554d181833b2", 7 | "body": { 8 | "randao_reveal": "0x03438a62cb0e6689f9b0bebb5d87e4547b3a3ad768cfd7d5cb4f1ad00a3b481f83d0625a49e185021a9115f66e070ed725618328d0eebe20edcaa6697a229be26a7a30b5251a0d19862592f3a3129290b9960e19a4e0721b76ec057ee4616499", 9 | "eth1_data": { 10 | "deposit_root": "0x261098a77c8cf3f0984b21ebe13a0782ac28d401e9544b4f92526024c92ac8da", 11 | "deposit_count": "16829287941910761280", 12 | "block_hash": "0xe382cb68f37f0a70ce917a44942ed96410f2987195d4087e608d3ea3c5030ada" 13 | }, 14 | "graffiti": "0x035d6e107958843dc805e7094b9843a30a1afd56d0df2e2b8ad1a907d56961e3", 15 | "proposer_slashings": [ 16 | { 17 | "signed_header_1": { 18 | "message": { 19 | "slot": "7146199724972185376", 20 | "proposer_index": "18118756251847292973", 21 | "parent_root": "0xf545b0ec89048983818bcee1c61f29c21d7021cfaaef11189366263dc42d4c21", 22 | "state_root": "0x06c202afcc4533af720fe4c7a8d98f3bbbbd8e38a66c4e9af291477b99e13eec", 23 | "body_root": "0xf1d8b6e92350ece3ccd1b544ae53c12ea8ca21adc144d8acc0c1b6e36b0fe289" 24 | }, 25 | "signature": "0xc3549281d4ea7ba5f837bebfb74ce5fc3ea3a4bac0e20cda9a099dba4fcb4bb7d70cb520cc9172b1a62cadcf30e9cdcf4146eb3976410182ad919cac5e8047832391547506d0af5cff95b15891ae15646dff4534507019783038b9dfcf5275c0" 26 | }, 27 | "signed_header_2": { 28 | "message": { 29 | "slot": "6357843430019023762", 30 | "proposer_index": "9382854559892943115", 31 | "parent_root": "0xdb45e9f3cb0f36103c4aa01c7286eed1b27b6886b04d30535853503fdc1ba336", 32 | "state_root": "0x58eeafe39a1d42e4464451cd7123fd47ca050536352433d48597450a9377b6c3", 33 | "body_root": "0xb7df00faa1bcf40832564c30c51ce58ca1cf03bb19b598d21a1f0ddba7be69cb" 34 | }, 35 | "signature": "0x50c43c26b8ea9b8c00fbbe16d2d61ea91abdeab72e9b3a84495b25c027dd7b93a8964fb5f1821617aed572a964baf470778a662a74a5b06f8f983bc107ed5b387cb324fa08355f30979878c3c7a0b98b0f3a1a2855a11387e98c0d730f88fa0b" 36 | } 37 | }, 38 | { 39 | "signed_header_1": { 40 | "message": { 41 | "slot": "18095797905134499939", 42 | "proposer_index": "16979488562829736813", 43 | "parent_root": "0x0e18a16dc5b92d869ada655d8232788354409fec22af5942868ac21249620ec8", 44 | "state_root": "0x0aa7477a082c0418dc37853ead552fc83b27296859fb8be709a75f6b4ee8909f", 45 | "body_root": "0x0c996e91463f1814f43aee9afc5ee849187462b66fc8705ac4690fdffc60f85f" 46 | }, 47 | "signature": "0x48d11ee4836848af8e49a7c5bed42c20e315fc6f54c9d6a383c96e127744c62b93e8741b284656097b1224eeddb832e30c5baa8072c16da23f8c6c63bfc1c54ec21b00fe7e45f7317e10fd26b67fcd37a02b793f232021f45b5287056865b786" 48 | }, 49 | "signed_header_2": { 50 | "message": { 51 | "slot": "496970746177864272", 52 | "proposer_index": "17662340631248619935", 53 | "parent_root": "0xc63178a457711b5e38e0b49e6ac36cf2c6447523369bee3c65991b39eb916627", 54 | "state_root": "0xff23bcb2b30ac8c304d0d58e503d9aa9e717bcb854dfaf1cf83983d10da5314e", 55 | "body_root": "0x883799b4dabfee49ea989d837f47686bf0c9cf29800cc81a8837e45485878254" 56 | }, 57 | "signature": "0x9a5c16908b7af2febfb3f907ef7580a7efdb200685c9383ace2c21afb94963db242c56c63da32b21e63b8ab602266593dbfe7f714891c5fed225e09c214bda8281c86ceddb6ee10727a854f213d33be1f032399e0044db6fa30368b6dc857fa8" 58 | } 59 | }, 60 | { 61 | "signed_header_1": { 62 | "message": { 63 | "slot": "3388828878202104959", 64 | "proposer_index": "4228944676767914508", 65 | "parent_root": "0x9cefeb11758fb01a9939950e127d71dc9c54a26aec63ef024b6620e6d32e4485", 66 | "state_root": "0xa118e09411d7dca978b5ffd06c0ddcb484b79e9d2504374d4c8ce4694c19f426", 67 | "body_root": "0x58d7a27577160e755acec8761e9bc18752767b456416a13eefab6d89952661be" 68 | }, 69 | "signature": "0x006b6c85cae1be76807649288d4d80a812b60071047a23ad0f1f6f539fe1fe5875eb89bb1e076577fe31e3c164b76ac00f640f625926bd6431d2f16b3f9f135e7ff450100ce39bf0f243b947174c8131543f6de7836d64b9f671732d94e5c078" 70 | }, 71 | "signed_header_2": { 72 | "message": { 73 | "slot": "11942027630322640715", 74 | "proposer_index": "1318727836741514827", 75 | "parent_root": "0x9695481495caa852d0e2efe4f6d21727c02fa1b934566ec88b0188254240f8a0", 76 | "state_root": "0x6c005a13e23c6c58b3cd94d00273ddc442390260ee83e0c389c3f659a88a75b1", 77 | "body_root": "0x54b8c77e86e04c8c9a2bad0b6df37421a82cf154f25bfc908d27c43e1e6dbed2" 78 | }, 79 | "signature": "0xfacad8d3be491c6db03f05f4bb65c31131a9ce8bf1281f0afe3a418c0fb54020050367b531a00395a465ea49253761953af03a8af3cce6ec2186933e9ed46cae930f9b820a26ede839a66d6c249c264c0876592d04d254007fa7490b911a4c4a" 80 | } 81 | }, 82 | { 83 | "signed_header_1": { 84 | "message": { 85 | "slot": "17564303113553003053", 86 | "proposer_index": "7427802066995612283", 87 | "parent_root": "0x9f28ab8105724cebf5157312439fd47f198d9e54f6caeaba407ecf95cb50bccb", 88 | "state_root": "0x3b350aee259befd3cfa104dc314eefb03b9765740e8825c8265be88b713c273b", 89 | "body_root": "0x9732b6abdc66ac0cee7067c89c871a9cc01ca0aebe3cb7044909ccb54d7553c0" 90 | }, 91 | "signature": "0x58465080b86b3fd2b86981f39cc572dc23cc4d8290a1c195fcb13a67d79a8165a8cd82f4b67f8904a3114b9dc2df7a477bb938e80dfe2a5af6cd1f78c4179cfd9058ec19b961a587d95399726996952b46449c20d19eb6a92dbce8b1f704b131" 92 | }, 93 | "signed_header_2": { 94 | "message": { 95 | "slot": "4575698239415281991", 96 | "proposer_index": "17394135477428691718", 97 | "parent_root": "0x5c83254160a5a7241d68e8d75123aa6e71782496c33e3cdbf87a8805486db629", 98 | "state_root": "0x4ba5eedc67f11db0cabb3185229ca6f1768aaa1ddcd39a1b1ee9691f10c52ff7", 99 | "body_root": "0xab6344d78dde89b181abd64dcd1c47e2c77dc40fa06d7d5edad841cee42e8ab8" 100 | }, 101 | "signature": "0x26cdc75a28f86a825c0a0464166d7cf36200185b69893fad47a42a4f3a298cffdff8deacaee20a84d7b0614781e86d504bd075782a4c4c651ea163313d3491ca77b1c2af229c93c69ef02ba8d5a15d646cd09f061b05bc55e4a94bb3f235d132" 102 | } 103 | }, 104 | { 105 | "signed_header_1": { 106 | "message": { 107 | "slot": "16802317519434814569", 108 | "proposer_index": "15008265675794388443", 109 | "parent_root": "0x42e0d04fd0dbd4d211d12dede410f7d30d6de6d1e7031a9a9cbea00fc5b6e6a2", 110 | "state_root": "0x01fedb9d19eb9d0a862fbee257f9e9487113ac2d4a894dad42cb98f0a38cba0d", 111 | "body_root": "0xd8c0d5ebe594f09ed5adc5c900fdeeb672967815ea2bb2df954d8af3fd701740" 112 | }, 113 | "signature": "0xed37d6f601eda763683bae0ec163788aa2ea949b1793ae8d9ea43a49da9f320766c023c8eef83db29eaf735018385efc7f369ebfed0dcb12da5aef53069592f8b207e312172a8e0f6e792945e857bd253321dd1a9bb70448a7773059d4bdadf7" 114 | }, 115 | "signed_header_2": { 116 | "message": { 117 | "slot": "8760927850735165927", 118 | "proposer_index": "12112563613797299828", 119 | "parent_root": "0xa304c7e27918322ae5ef5b31169249d24d590d28b689c4b6a71710d4c56ad33f", 120 | "state_root": "0x05a7823970bd939bc53f055047d1afbbfe69e1b1aa9999c209f0a432837bbeed", 121 | "body_root": "0xe8b0b55642447b55d321ef0de0bdd3f491161aa75f85bc44085ce9c1434c38a2" 122 | }, 123 | "signature": "0x2a80ab254b179d0a53834e9ec0b6318ee80e6129f4f0e1dc38dcf55f20b3e006c0f7cd9bc8b5916c36eb7e3cda07d32a6881d881d46db658b6ed27d3e3cd627febe4203f40add3fbe85f4ac964d0a4e21cbc650a5d3cf8cf9aa60ddae612e952" 124 | } 125 | } 126 | ], 127 | "attester_slashings": [ 128 | { 129 | "attestation_1": { 130 | "attesting_indices": [ 131 | "14568567205229856856", 132 | "13969214871100218988", 133 | "15891927455388920954", 134 | "13840453242631960415", 135 | "5132025723959407541", 136 | "14552288949359483220", 137 | "15828637334706297838", 138 | "13770787656422348263", 139 | "155786865858172328", 140 | "4937828727600459627" 141 | ], 142 | "data": { 143 | "slot": "917664958032962249", 144 | "index": "17863498554647337959", 145 | "beacon_block_root": "0xd4afdcfaef44e26c060a1c8cfd7f188a90165c6c3833e84bc505353253cd4113", 146 | "source": { 147 | "epoch": "15519149482606895676", 148 | "root": "0xc40bea72b4d8f8cbe097c2ac2b60f52dca4e803021ecd0e29396ec86cd687c60" 149 | }, 150 | "target": { 151 | "epoch": "13555922008947788292", 152 | "root": "0xf338451b359a97b57293aa481ac597f8ebcf8bf8c8c1d499412a867ee6c5900c" 153 | } 154 | }, 155 | "signature": "0x2b454b02b4413a89a19b63e8e8486912117ded65056ca3d3fe3603c4bae31af7dd60955a97dcc7de05bc8565ffe4c53376adcaed5afd0cfa19fefcb27b026983c0661e6dccf9ca78b3ee9e16aa499656375787f5688183b988af87d2e5684e77" 156 | }, 157 | "attestation_2": { 158 | "attesting_indices": [], 159 | "data": { 160 | "slot": "16841145555214976800", 161 | "index": "150091166927935006", 162 | "beacon_block_root": "0x43b4bb434ea798d5d0ff0815255e61d42f0b4564757522e2c14c2c9893444589", 163 | "source": { 164 | "epoch": "6807633118981829517", 165 | "root": "0x6422617742ad3280dd7f9724bf8e350fff68e517e397ae3c656e3b0bba897549" 166 | }, 167 | "target": { 168 | "epoch": "9753925480990625401", 169 | "root": "0x6ccb155527ad0386eed9abd27221a6261f44b7875690bebf6cb027c1789c4c92" 170 | } 171 | }, 172 | "signature": "0xa859f980d06d83f8d117838d11aae109cc3a2c928f738b6a2d8822448942d83ab30000f813ccb376e029306aafd9355d721689d69d28ec8797a5490217295c5f07b4a18fcc1e592fbd4dc3f2207c7fb47969fe19f53254cc456666a9fc3f4e06" 173 | } 174 | } 175 | ], 176 | "attestations": [ 177 | { 178 | "aggregation_bits": "0x42", 179 | "data": { 180 | "slot": "14646160024808704478", 181 | "index": "15441789122145521845", 182 | "beacon_block_root": "0xfcfc9f4ccfefefa4f3976d1c25c411923c51977811295876c05fd5712e295f0c", 183 | "source": { 184 | "epoch": "4293739339065186026", 185 | "root": "0xc71fc51f082a5b9f501bd58d89f18946db846e5e04153f66d9b5853b10afd134" 186 | }, 187 | "target": { 188 | "epoch": "12034623642366551431", 189 | "root": "0xbc7edb04c3f242b8ffda2a361c9204d0b933befddc907b8b19d203b9425c90d9" 190 | } 191 | }, 192 | "signature": "0x39981ba6631219319549d7bed9a7efecb43038cd0fba3b5ee8c9aa5d72cfd2d32dfef9dc65bc52880d6c645ff3376a88aacf3da4db035d41d52e07a06d2face2c08fa31756f859419fb50f7b6b33272550a60e046f8665cc07bb52d0a2c40dd8" 193 | }, 194 | { 195 | "aggregation_bits": "0x08", 196 | "data": { 197 | "slot": "3454365187168235053", 198 | "index": "3433068656822917893", 199 | "beacon_block_root": "0xd7d159760d3c7fb23e37e7c0ea7ff2daf73ca0dc4754574f60a596c7e64c99ce", 200 | "source": { 201 | "epoch": "7580673316190214946", 202 | "root": "0x72afca489c310d2c2f626fea32d52ae385aaec13ee7e2c8a30d0890c50032fa1" 203 | }, 204 | "target": { 205 | "epoch": "1318585738845796485", 206 | "root": "0xdb70abc18744b842d84d4becbce06ea0fa7c06545b92e334a79a3e75da4dc319" 207 | } 208 | }, 209 | "signature": "0x53c7d710a534c87ba5b74fcef4785ffddc3c258df894e2cd68674c8c9ddab1bb59e9806958b45c862dcbccf97e8120e7122ce4cadb2bbfa8d18da582509e37505fd3566d0c41a8a749fd46560e92c69a6268169a17e227897609626cd250d5f2" 210 | }, 211 | { 212 | "aggregation_bits": "0x5f05", 213 | "data": { 214 | "slot": "6669201272138010235", 215 | "index": "8251332687725493089", 216 | "beacon_block_root": "0xefe6ad9837f80391171ded68a86ec7a88a799ad02b511bc58e484c806dd67442", 217 | "source": { 218 | "epoch": "1916272347686843806", 219 | "root": "0x7878c6e62896d1e18d09c5d8e001eb1613e0734abe26bde780c76ce2574cfd5e" 220 | }, 221 | "target": { 222 | "epoch": "2800199240778336856", 223 | "root": "0xc81ba6c39bef3d400273e0c210fd1418ebd2ffbc8f42fbc8e151b28865bda8aa" 224 | } 225 | }, 226 | "signature": "0xbbc0f899e5abe4d6d92d52765028dc429737060019c33826bebf0e198d4b2b9195abf9b75a4e6ae8225ef1a35cf90d40f79ba15dbeeb79a55aa3f60904ea6a9efaf510a311210b47425449c224afd7da3197da9023a49c324d4f99c07ccb8e57" 227 | }, 228 | { 229 | "aggregation_bits": "0x01", 230 | "data": { 231 | "slot": "533475137122035407", 232 | "index": "15745989169700340645", 233 | "beacon_block_root": "0x21473290cf46850e95e3e74ccbdb778861d314c1da56530911d66dcd18bf037c", 234 | "source": { 235 | "epoch": "18241743601753980648", 236 | "root": "0xd0833a52c7a15db21877823bdd7f4c73f61b6fc96bf02a2f92b57afb243c5c2c" 237 | }, 238 | "target": { 239 | "epoch": "1855527076716723365", 240 | "root": "0x308171395f54637e514f3f382d71146af027a337dfc045701d37007429ff9cb0" 241 | } 242 | }, 243 | "signature": "0x844a1fd01eec6417ac1abe3c9936516d39542d6caa85c90c59485636500e1b435755ea53ef7c01eed4027076037373f60225fcef5ddf98c1b73bfd53d894f758c51606e6ddee4548e25277472271f8bd11352f8e4750d3fa06f509c338f84757" 244 | } 245 | ], 246 | "deposits": [ 247 | { 248 | "proof": [ 249 | "0xcd5a13caadcac56ae4acdabbe37bcd12348b3dbd728a703cc8c7fd641a765a23", 250 | "0x11e283b8e45f0864817a125f630afa79e57a7093ccabb9a7dfec9b7cfc50b5b0", 251 | "0x1c7dbcb2c3ff23e0867512b2f5cf4ff300fd95f6654c721a29e30a188d177acb", 252 | "0x26777a9e610b55549f1d0fec6bc47049073ebd03a74c3d308dd4633ac156db43", 253 | "0xd2253d9472594a826ac081ae7847d8ff776fccc8eccf044395fcdf4fe9357351", 254 | "0x95faeee7cf2b494d0808fb6abcea11e0fb98e92d268f30bb0295f56ef624de48", 255 | "0x128cb49cac29a390f096dd95b7ce97b0465bce89fd003f48e8b349cb7f70aeeb", 256 | "0x9335cff8f4423727a09c097611113bd2a9b94af5bde89254163ff30cb448bd59", 257 | "0x493e981118edb12e7fcb78ff0c90c8a365a813e272a96e648b2dd38a2424247e", 258 | "0x8792492a88df0902cb407250b0149e8389a7b1d3f772094669bd0a75a054c5ff", 259 | "0xbad3cf3f2f110d3af7ffd1157ca8d313f3564b208c854c24b9b8249371b00495", 260 | "0x9aa7d4e7a9fc2c9ceaf6b475f2975c580b53f5c076988cdc2dfe20798ff85df3", 261 | "0x67ee9b8565b885c424e7c0e17d4722e26baef4e086b863e7cb1a1eb50f95450e", 262 | "0xe19199724ac00c727d30773c6d2e310de0ea5298be1af27f931ff265873c54ea", 263 | "0x7ca1e29efdde8c316c55b06a4854df3f0e2c6061e9d37eaf59a5310b0fc63600", 264 | "0xfb048c607eafa7ce08251b7bad7f4cdc9671fad7bd32b9a879c9705a25367a33", 265 | "0xa545e0beb4b0e9f62b3e4718684ee7bb5b471ea1e6c00f4f39d464d819c789bb", 266 | "0xac2587b5e376276c0fe6fec5b99538c64cac6fd7178495dc83f76cb71a4e04a8", 267 | "0x7583c07a2c06f98d37f7e9f8c8a336a78814c96b85a5ca8e2b46d2ef42c3274a", 268 | "0xa5ea145810ea5cb3af54f5022127d86190d1c3812037a7475b63d1da36d0deca", 269 | "0x5e6ab651c5244c2701c655ab18a6098f6a6e0fab9c5ad68e8fd2fe40c4d74740", 270 | "0xde9fd756dbfece4ef84d7491a405ae1a955adb3cf00465a6ac102fc273ae6c2c", 271 | "0x2087c35f0207f9b2e2868314ad78b33b079e477b86b76ecbb007af9ac6f527a4", 272 | "0xba70fa1d351ad45fff13e571827e9abd07c16928c097eaab7b465c9a2c3962d7", 273 | "0x6b6ce93bbfa3c460dfb8d19feed44dfd8b27dc6f462161c341ce1a8e30c1e4f5", 274 | "0xa274b195993d5b91c9f1bba9e0ebedf11a5558e03d4f8b90eef701e043f95d11", 275 | "0xafc6eb3ff05c7254e544a201f7c47518c1cf0c7905e06c87648dab6a0cde515d", 276 | "0xb4ab300a00ef3654766c11fe8ab92a3af548a652e7785e9b315d688ab72d0d2e", 277 | "0xac00ad809a1a95d3585c776584f79949b556c87c894bb75dd57deac3da8dd786", 278 | "0x683e1d65ed20b4bd6895e2d7e33fcac13e7a38316f4cdc0ac793e0c10e846a26", 279 | "0xdaf19d17403f7067798652ef62326c928e7caae1dc65af119364cea9651847c5", 280 | "0x2f68b4a365337404e1fc611bbfc3e841d603af623630a82586c7a26fbd2335d7", 281 | "0x080cad38549e8609d5422fdf547c1dc12dccd045f369d8a4ca288bfeba35eeec" 282 | ], 283 | "data": { 284 | "pubkey": "0xef0be45aadfc87b05ca070dc13fc084e6c052061b150d964cfa80fa28521b19652995e79c83bf8c003b0cc747aed3a00", 285 | "withdrawal_credentials": "0x2f1d00521985495759b827e4519314dd8600dafc523d7c451d6112d33fd8fbad", 286 | "amount": "10289442765447130569", 287 | "signature": "0xfbf186a3bd73e2ffa5be22a6b41c302a7e9ba3ed876dd7ccf3b144152aba5c4b4b9ab5ce75a9d5db370c945697f5bfdeac5d412479f54492bab185af962b944f2c676bfda27c49100dad64ab12b19d13db788d098159fea9dbe1e46e5d30bbb8" 288 | } 289 | }, 290 | { 291 | "proof": [ 292 | "0x8ad795b90360135d5e0da600dbe5c6f6194571f7a5533b59b8194f114eff53af", 293 | "0x02822d8fc404f9c45cc8538cc2fabe03678a10e19ee1fc1ad101e9f95f8dcfb1", 294 | "0xc3df1f5733d4949064260c6d16fe1d971ea32b36ba01c6c1a4cbd41249810e55", 295 | "0x56737736451c83b7c5263d5c1a92fef53040a77be0450fefd4de02f98ed47c75", 296 | "0x82926c8ae6f2164a07f392dda89f30badaff01e9fb5bc9f9f05d8723de50650c", 297 | "0x09d39a2cdb5dd5e0173a80061af2eee20a1b70ff51d4789a79be96c2ded9ce6c", 298 | "0x39a761af41b53d4cf8a05c8cea7eb784cde80ab0bb22b4c5b3391ea3712eb943", 299 | "0x226ac01966169418d761006ea5bfc190d0f0c4ced75a266ceacef35843e658d3", 300 | "0xf3e931aec50d8b8ba730f49c43dddcd1bf3e2cbf5a0f6d3742f061698582715e", 301 | "0x57b87bb73e694ac443b001b394b541618408d7b4d5df4489bd9cd1c960bbdae6", 302 | "0x97033ab5303ac527c1b9c44717b7626885793308bd6b9f5548e7b39f348ed819", 303 | "0xf2851329d8a0d8824be0c0cb107397a55b65ecd0741f65706cf2cf8eb10f6c2d", 304 | "0x4ea36f476fc27dffc4928c4ae959875c7a7d9297f341789146ecb25029578c0d", 305 | "0xfbe84d5c625a30e330e593e83c4a4c7d21634a82b20621fb04fe24ace314192a", 306 | "0xac5d97f34222ec13712a0ee11c06f0b052d028931da223971fa55e2947c7ebe3", 307 | "0x6ee14e36bb6e61e619cfa8c561a48f27e5cb55b023f6c8ac90700f3e0dfb341c", 308 | "0xb7c3323dd3587dda04beb104c9c14b955fee1dfd285b926face02dd681db78b8", 309 | "0xe01a0c58a2e21ec85bd27d2d27577d61a3583cad24b07c316534b3a81b67f79c", 310 | "0xc8ff28f10f9062435bc4eca0415d6644cbd59b583a21cecb3b0ecd5dd3a69f38", 311 | "0x72df9fe1f203c04260e956d70a10ec33a79936232701861d2fba760fa0aa98f1", 312 | "0x8cb07dce61089c4079293f55da825c55978f660073ebc058363b746801f57d2d", 313 | "0xe2c7fcdca6bd196b1665969cc9cd2722e834acf0417febd2389b39ccb73289fc", 314 | "0x41795d37ec87aaffe6db868d5a1178e4f449984faabc7ebbdc0416e5cce074ad", 315 | "0x673040f267d6205db2b8e9dca79c5ef362f9ac611e1eda2887fc8ce08edb3290", 316 | "0xd1787f5d47104bf1fd00199752b6c89c43989fd6a872ef61d3b5c222390f83a5", 317 | "0x971549e8ed05bbd498ecff21a5a4ba0fdfdc320cc4d090b774724ecfc783a227", 318 | "0x672b3ccd64ce1be31c38dd135c5c69ff4d1c35d5604f414913297b0c8aeae092", 319 | "0x867f242a23e8b12afd4d1835e8f25e8fba6ec51bddcfea63e2589b344be2a9e9", 320 | "0xdd8e73096603ac29162f46e790c652e1bfaa2c73c2c88a94764daf1051d3f29d", 321 | "0x1e021f5602bea9ab274800595378fca01d5e1a385ef505a2f2088729d0d80fd7", 322 | "0x79fff9bc0d75b64bc2ba53571e59321918ea5d4105314ce74a65aa0ef6906f21", 323 | "0x37fc5d53b1590b19f6a2cbbcf961b37fbc0ae6c066f836e19d9dd79eec044203", 324 | "0xdbae8c94dbff1a4e299085a51c6c2f726291dc8bea5285b748fbd481b9e80cd8" 325 | ], 326 | "data": { 327 | "pubkey": "0x321e7aa3f73b52719bc06922d0efecf439ed51ff8e5e8fcb89626591fbe1b7a0c03c9168f2f2271e22a24cac56b409a6", 328 | "withdrawal_credentials": "0x4d5da0fa7fcd6bf4532412b7f4f0a9a7872acc527a3895eaf7d4f573ac4905ea", 329 | "amount": "18092335273045870090", 330 | "signature": "0xdfc6b80438480361cc6b40fe1a3f2e24989fa5cb9986b1b2cad4c23393ed874fcac67ee7a800df87cbae68b8666331ea12d273c439efbe55840c78939f6498b62f16b7d6a3d8efad005b200bca841dd77de6bddbd72fbe4261d1ebc301d5cfe9" 331 | } 332 | } 333 | ], 334 | "voluntary_exits": [ 335 | { 336 | "message": { 337 | "epoch": "10492440762261293591", 338 | "validator_index": "11936809557182251833" 339 | }, 340 | "signature": "0xc2de2e86b53f2900befb7bc7025b542990391c06b1c739e34347fe29346d2b63fcabfe3fcad9fa13e6475b2d58f5cb390d6ca4b5ad68b3325b38f20745a4e58050363dd233b2504f398e64ec4738e209c73c62a2a230a9b94e37094f652be324" 341 | }, 342 | { 343 | "message": { 344 | "epoch": "17366936562490929545", 345 | "validator_index": "16956982536014447091" 346 | }, 347 | "signature": "0x41135fc5b1a345aeb9dbcbb6b8f057b14ee81e427f7ff2b6dcb957a151268dea1bc0ca38a974f331d91ae5a31b562a089134110998f76f3cde0538040fc4c660be51c3884c7b1a75ce6dcc52d1766ad40a32cf3eddf7bb87713cf0cf17016e5f" 348 | }, 349 | { 350 | "message": { 351 | "epoch": "11750469314534721701", 352 | "validator_index": "2334812252493519711" 353 | }, 354 | "signature": "0xcbf16cf6486aa17910a32f9d5779486e714789aa59e146c739b938cb42dd783452916a216f121d578eee1500bd952a4f7361e2f5273f7e5e7a2875a9a44e869721cb517c098e8e18dad5438c821da6ce157cdb6382ab050fee3a8c191c26587d" 355 | }, 356 | { 357 | "message": { 358 | "epoch": "16867138336075208986", 359 | "validator_index": "12500795926942359051" 360 | }, 361 | "signature": "0x0a608c6c1ab91cd0ac523a1b0ae99dc42b4a09ec308530527a45fbe470989ae2aa0be082c8891082f5c0ffa9f6930f271dfb15f941b6f093172fd879423557f2ca568e66da2f963df811dee6edef9f84902a675d3bb9eeea173946a2014268ad" 362 | }, 363 | { 364 | "message": { 365 | "epoch": "7445868187784720708", 366 | "validator_index": "7442771571183374564" 367 | }, 368 | "signature": "0xdae03962601f1fa865166846ea12a0cf294876a9bed1f7836b2897848c75d05e52650ac2ed8f61109f8ef2a5b47cc9280301ddcc58f4c170b7a7b8c379f6db8936f7acdfc4b533647c3a8878780ba8e56784f755b38afefc7386487798c694a7" 369 | }, 370 | { 371 | "message": { 372 | "epoch": "17597222123134178251", 373 | "validator_index": "10285267452181335616" 374 | }, 375 | "signature": "0x614f72006043a96e95212d5140f3b00da3c4fb521e99847caa927c0c9df032d69ccfecff9a9580cc530ab552f62b7c1a1b3988e3aca4eeed8a388c8b861bfdcdb906a6a24a8878e03862faca3d5e08c0a815a9498df54587c48e00fdb8af8fec" 376 | }, 377 | { 378 | "message": { 379 | "epoch": "3955838062322020638", 380 | "validator_index": "9796258122639767866" 381 | }, 382 | "signature": "0xdd234e3d76b1500cce12898b02f3327de7093720f854228d08cd819ba412d6cdbd29006c30f162cabab777ecc5a9c7de82124dac6a4c3e685ad61af44e7b1fc30d1018587d330cd9cdb60abd2763b4945e2e989d4dd1982c575a48e3ea0b9cbf" 383 | }, 384 | { 385 | "message": { 386 | "epoch": "6654150523531825253", 387 | "validator_index": "5960394442255703868" 388 | }, 389 | "signature": "0x04ad9fa663542d2e049e49fbb9d786b73ef06503e1ec5461d740df072c3b52c7c112efde8ef6e7d0a90fbafb5214b50be06ed1b2c162263aaa8532e73ac4672aae8f26ea0f9c513070fca19063096d98fe02de3829cd5a73686051dd252b6083" 390 | }, 391 | { 392 | "message": { 393 | "epoch": "16611686498244946681", 394 | "validator_index": "8062483453448808874" 395 | }, 396 | "signature": "0xdaa84e6b0987b7c9834b9bbfad41918736863ce0122912987224bb7774fff3913a9f45582f419894b9c182340edf0e98526f187da17774ad2bb0bff5e758c1979be20c0bca55ff66ba935893214eb4569e44be0aed7f53033b26688bcb451e72" 397 | }, 398 | { 399 | "message": { 400 | "epoch": "2906505601866276086", 401 | "validator_index": "14601161714998215671" 402 | }, 403 | "signature": "0xb961473a0e60c279ed30677fb256bc8cf5db433af4bd5cfd2434683f64af12ed5ac76a459a14f647a4c73efa9bfd0e113d4bc0e8b7871529dbddda6ac911aed2caf75200dbd1b7dc90861296a97d9bcdd23b7752e71120f486062e8d7968a351" 404 | } 405 | ], 406 | "sync_aggregate": { 407 | "sync_committee_bits": "0x41157a77520bb661f0763f70142fba246e4c46983310145ff9e0b417bbff29f3ede7f957eb00c50ef39dec4e9172f800b58e2b7d79e5757d47655699a19253d5", 408 | "sync_committee_signature": "0xb1857dbd49a4c34e059695aef60a105ecd2043201cd19a5d3327af8053fdd787fb820f3204a4356fb0bf589c4a65e4995d347845e1e67e1902c0de837f3f2524c096d395812c29eef5e80d076870608f57b4642d588faa65896f0500e374aa33" 409 | }, 410 | "execution_payload_header": { 411 | "parent_hash": "0xe635221c90f91883210a817dcbf27aa429bc9b90fe4d19cadd1c7b2dd2f5ee47", 412 | "fee_recipient": "0x3f8ab82f302e08ac9cf75461a633042ce080a676", 413 | "state_root": "0xd0c78fed81db972df78cd9b19ece7daaf44551323735630e36c39c3f73061a92", 414 | "receipts_root": "0xe346c5688050aaa3f2edeefc7b5474789955e5342b72e6d30dfba38b3c3f412e", 415 | "logs_bloom": "0xe6a8bd64f97fdb710997dc0d847760206e7d2858c5b91273e9711cf24fcbd8515781ef22cc282fb803288ca115d05d419dd50de20066d3f0aaff8f1acd67aae37c18ddae1f52219e2446a589cefd630a36ecd660c5a78ee542a981ccf82faf30d97e1fc3f9414becb9c0687316aeda322ee04b564a8020fa5eb56458ca1ea148ce6c813ce3ab00320035e629aaa2af2aa677051dc4feaba9cabddedc3d4076f08577a44379169dba6c11c50b9d26798a53456f45f51cafeaf5a38f6ac66dba38f4487cab31fa1b32a005a423f7b21acb7510ad768bb4d47b22b57dec09bc7d540210f620d3e30b2064943657453d604b7eda5f1cdcaa51ad5b665a7dd3bd6e88", 416 | "prev_randao": "0x69e2108cdf27ec09a2de91bd48ca55fd3165c6fac44d9aefd185aec80fdf855b", 417 | "block_number": "12272306425938097878", 418 | "gas_limit": "17918152272398866133", 419 | "gas_used": "7400854929170431915", 420 | "timestamp": "14230531789619863716", 421 | "extra_data": "0x9e77893544036bc8d6786f67df3aea978e555b4de171655cc3159fd49a7e", 422 | "base_fee_per_gas": "11436536991889132398460509120165895053863255550135484073681194675822208391220", 423 | "block_hash": "0x17eb919d10a2f78ba53470df6934f8f3b964abe565ecabf0161eb173a8cf66d8", 424 | "transactions_root": "0xdf88d2d8cc3602bcc9b949c65308225bf336802ddd0ac4452a60950346be1b4b" 425 | } 426 | } 427 | }, 428 | "signature": "0xafcf514468d1fa9dbe605d9bf0211853bb07d266805199011bdfd0031def6274ef539309f997c9e6fb2adb34f02e98a5d07c918a446e27914672dce9e0e54a2a5557020295e17a131ad500e27201698add1794302d159fb5a5d86fac57f8e2a3" 429 | } -------------------------------------------------------------------------------- /types/.gitignore: -------------------------------------------------------------------------------- 1 | testdata 2 | -------------------------------------------------------------------------------- /types/consts.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | DepositContractTreeDepth = 32 5 | 6 | GenesisValidatorsRootKiln = "0x99b09fcd43e5905236c370f184056bec6e6638cfc31a323b304fc4aa789cb4ad" 7 | GenesisValidatorsRootRopsten = "0x44f1e56283ca88b35c789f7f449e52339bc1fefe3a45913a43a6d16edcd33cf1" 8 | GenesisValidatorsRootSepolia = "0xd8ea171f3c94aea21ebc42a1ed61052acf3f9209c00e4efbaaddac09ed9b8078" 9 | GenesisValidatorsRootGoerli = "0x043db0d9a83813551ee2f33450d23797757d430911a9320530ad8a0eabc43efb" 10 | GenesisValidatorsRootMainnet = "0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95" 11 | 12 | GenesisForkVersionKiln = "0x70000069" 13 | GenesisForkVersionRopsten = "0x80000069" 14 | GenesisForkVersionSepolia = "0x90000069" 15 | GenesisForkVersionGoerli = "0x00001020" 16 | GenesisForkVersionMainnet = "0x00000000" 17 | 18 | BellatrixForkVersionKiln = "0x70000071" 19 | BellatrixForkVersionRopsten = "0x80000071" 20 | BellatrixForkVersionSepolia = "0x90000071" 21 | BellatrixForkVersionGoerli = "0x02001020" 22 | BellatrixForkVersionMainnet = "0x02000000" 23 | ) 24 | -------------------------------------------------------------------------------- /types/u256str.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "math/big" 7 | ) 8 | 9 | var ( 10 | ErrSign = errors.New("invalid sign") 11 | ErrLength = errors.New("invalid length") 12 | ) 13 | 14 | type U256Str [32]byte 15 | 16 | func reverse(src []byte) []byte { 17 | dst := make([]byte, len(src)) 18 | copy(dst, src) 19 | for i := len(dst)/2 - 1; i >= 0; i-- { 20 | opp := len(dst) - 1 - i 21 | dst[i], dst[opp] = dst[opp], dst[i] 22 | } 23 | return dst 24 | } 25 | 26 | func (n *U256Str) MarshalText() ([]byte, error) { 27 | return []byte(new(big.Int).SetBytes(reverse(n[:])).String()), nil 28 | } 29 | 30 | func (n *U256Str) UnmarshalJSON(input []byte) error { 31 | if len(input) < 2 { 32 | return ErrLength 33 | } 34 | x := new(big.Int) 35 | err := x.UnmarshalJSON(input[1 : len(input)-1]) 36 | if err != nil { 37 | return err 38 | } 39 | return n.FromBig(x) 40 | } 41 | 42 | func (n *U256Str) UnmarshalText(input []byte) error { 43 | x := new(big.Int) 44 | err := x.UnmarshalText(input) 45 | if err != nil { 46 | return err 47 | } 48 | return n.FromBig(x) 49 | } 50 | 51 | func (n *U256Str) String() string { 52 | return new(big.Int).SetBytes(reverse(n[:])).String() 53 | } 54 | 55 | func (n *U256Str) FromSlice(x []byte) error { 56 | if len(x) > 32 { 57 | return ErrLength 58 | } 59 | copy(n[:], x) 60 | return nil 61 | } 62 | 63 | func (n *U256Str) FromBig(x *big.Int) error { 64 | if x.BitLen() > 256 { 65 | return ErrLength 66 | } 67 | if x.Sign() == -1 { 68 | return ErrSign 69 | } 70 | copy(n[:], reverse(x.FillBytes(n[:]))) 71 | return nil 72 | } 73 | 74 | func IntToU256(i uint64) (ret U256Str) { 75 | s := fmt.Sprint(i) 76 | _ = ret.UnmarshalText([]byte(s)) 77 | return ret 78 | } 79 | 80 | func (n *U256Str) BigInt() *big.Int { 81 | return new(big.Int).SetBytes(reverse(n[:])) 82 | } 83 | 84 | // Cmp compares one U256Str to another and returns an integer indicating whether a > b. 85 | // The result will be 0 if a == b, -1 if a < b, and +1 if a > b. 86 | func (n *U256Str) Cmp(b *U256Str) int { 87 | _a := n.BigInt() 88 | _b := b.BigInt() 89 | return _a.Cmp(_b) 90 | } 91 | -------------------------------------------------------------------------------- /utils/utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "fmt" 7 | "io" 8 | "math/big" 9 | 10 | "github.com/attestantio/go-builder-client/api" 11 | "github.com/attestantio/go-eth2-client/spec" 12 | "github.com/attestantio/go-eth2-client/spec/bellatrix" 13 | "github.com/attestantio/go-eth2-client/spec/capella" 14 | "github.com/attestantio/go-eth2-client/spec/deneb" 15 | "github.com/attestantio/go-eth2-client/spec/phase0" 16 | utilbellatrix "github.com/attestantio/go-eth2-client/util/bellatrix" 17 | utilcapella "github.com/attestantio/go-eth2-client/util/capella" 18 | bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" 19 | "github.com/ethereum/go-ethereum/common" 20 | "github.com/ethereum/go-ethereum/common/hexutil" 21 | "github.com/ethereum/go-ethereum/core/types" 22 | "github.com/ethereum/go-ethereum/trie" 23 | "github.com/flashbots/go-boost-utils/bls" 24 | ) 25 | 26 | var ( 27 | ErrInvalidTransaction = errors.New("invalid transaction") 28 | ErrLength = errors.New("invalid length") 29 | ErrNilPayload = errors.New("nil payload") 30 | ErrUnsupportedVersion = errors.New("unsupported version") 31 | ErrUnknownVersion = errors.New("unknown version") 32 | ErrInvalidPubkey = errors.New("invalid pubkey") 33 | ErrInvalidSignature = errors.New("invalid signature") 34 | ) 35 | 36 | func BlsPublicKeyToPublicKey(blsPubKey *bls.PublicKey) (ret phase0.BLSPubKey, err error) { 37 | return HexToPubkey(hexutil.Encode(bls.PublicKeyToBytes(blsPubKey))) 38 | } 39 | 40 | func BlsSignatureToSignature(blsSignature *bls.Signature) (ret phase0.BLSSignature, err error) { 41 | return HexToSignature(hexutil.Encode(bls.SignatureToBytes(blsSignature))) 42 | } 43 | 44 | // HexToHash takes a hex string and returns a Hash 45 | func HexToHash(s string) (ret phase0.Hash32, err error) { 46 | bytes, err := hexutil.Decode(s) 47 | if len(bytes) != len(ret) { 48 | return phase0.Hash32{}, ErrLength 49 | } 50 | copy(ret[:], bytes) 51 | return 52 | } 53 | 54 | // HexToAddress takes a hex string and returns an Address 55 | func HexToAddress(s string) (ret bellatrix.ExecutionAddress, err error) { 56 | bytes, err := hexutil.Decode(s) 57 | if len(bytes) != len(ret) { 58 | return bellatrix.ExecutionAddress{}, ErrLength 59 | } 60 | copy(ret[:], bytes) 61 | return 62 | } 63 | 64 | // HexToPubkey takes a hex string and returns a PublicKey 65 | func HexToPubkey(s string) (ret phase0.BLSPubKey, err error) { 66 | bytes, err := hexutil.Decode(s) 67 | if err != nil { 68 | return phase0.BLSPubKey{}, err 69 | } 70 | if len(bytes) != len(ret) { 71 | return phase0.BLSPubKey{}, ErrLength 72 | } 73 | _, err = new(bls12381.G1Affine).SetBytes(bytes) 74 | if err != nil { 75 | return phase0.BLSPubKey{}, ErrInvalidPubkey 76 | } 77 | copy(ret[:], bytes) 78 | return 79 | } 80 | 81 | // HexToSignature takes a hex string and returns a Signature 82 | func HexToSignature(s string) (ret phase0.BLSSignature, err error) { 83 | bytes, err := hexutil.Decode(s) 84 | if err != nil { 85 | return phase0.BLSSignature{}, err 86 | } 87 | if len(bytes) != len(ret) { 88 | return phase0.BLSSignature{}, ErrLength 89 | } 90 | _, err = new(bls12381.G2Affine).SetBytes(bytes) 91 | if err != nil { 92 | return phase0.BLSSignature{}, ErrInvalidSignature 93 | } 94 | copy(ret[:], bytes) 95 | return 96 | } 97 | 98 | // DecodeJSON decodes a JSON string into a struct while disallowing unknown fields 99 | func DecodeJSON(r io.Reader, dst any) error { 100 | decoder := json.NewDecoder(r) 101 | decoder.DisallowUnknownFields() 102 | return decoder.Decode(dst) 103 | } 104 | 105 | // PayloadToPayloadHeader converts an ExecutionPayload to ExecutionPayloadHeader 106 | func PayloadToPayloadHeader(payload *api.VersionedExecutionPayload) (*api.VersionedExecutionPayloadHeader, error) { 107 | if payload == nil { 108 | return nil, ErrNilPayload 109 | } 110 | 111 | switch payload.Version { 112 | case spec.DataVersionBellatrix: 113 | header, err := bellatrixPayloadToPayloadHeader(payload.Bellatrix) 114 | if err != nil { 115 | return nil, err 116 | } 117 | 118 | return &api.VersionedExecutionPayloadHeader{ 119 | Version: spec.DataVersionBellatrix, 120 | Bellatrix: header, 121 | }, nil 122 | case spec.DataVersionCapella: 123 | header, err := capellaPayloadToPayloadHeader(payload.Capella) 124 | if err != nil { 125 | return nil, err 126 | } 127 | 128 | return &api.VersionedExecutionPayloadHeader{ 129 | Version: spec.DataVersionCapella, 130 | Capella: header, 131 | }, nil 132 | case spec.DataVersionDeneb: 133 | header, err := denebPayloadToPayloadHeader(payload.Deneb) 134 | if err != nil { 135 | return nil, err 136 | } 137 | 138 | return &api.VersionedExecutionPayloadHeader{ 139 | Version: spec.DataVersionDeneb, 140 | Deneb: header, 141 | }, nil 142 | case spec.DataVersionElectra: 143 | // Electra uses the same ExecutionPayload as Deneb 144 | header, err := denebPayloadToPayloadHeader(payload.Electra) 145 | if err != nil { 146 | return nil, err 147 | } 148 | 149 | return &api.VersionedExecutionPayloadHeader{ 150 | Version: spec.DataVersionElectra, 151 | Electra: header, 152 | }, nil 153 | case spec.DataVersionUnknown, spec.DataVersionPhase0, spec.DataVersionAltair: 154 | return nil, fmt.Errorf("%w: %d", ErrUnsupportedVersion, payload.Version) 155 | default: 156 | return nil, fmt.Errorf("%w: %d", ErrUnknownVersion, payload.Version) 157 | } 158 | } 159 | 160 | func bellatrixPayloadToPayloadHeader(payload *bellatrix.ExecutionPayload) (*bellatrix.ExecutionPayloadHeader, error) { 161 | if payload == nil { 162 | return nil, ErrNilPayload 163 | } 164 | 165 | txRoot, err := deriveTransactionsRoot(payload.Transactions) 166 | if err != nil { 167 | return nil, fmt.Errorf("failed to derive transactions root: %w", err) 168 | } 169 | 170 | return &bellatrix.ExecutionPayloadHeader{ 171 | ParentHash: payload.ParentHash, 172 | FeeRecipient: payload.FeeRecipient, 173 | StateRoot: payload.StateRoot, 174 | ReceiptsRoot: payload.ReceiptsRoot, 175 | LogsBloom: payload.LogsBloom, 176 | PrevRandao: payload.PrevRandao, 177 | BlockNumber: payload.BlockNumber, 178 | GasLimit: payload.GasLimit, 179 | GasUsed: payload.GasUsed, 180 | Timestamp: payload.Timestamp, 181 | ExtraData: payload.ExtraData, 182 | BaseFeePerGas: payload.BaseFeePerGas, 183 | BlockHash: payload.BlockHash, 184 | TransactionsRoot: txRoot, 185 | }, nil 186 | } 187 | 188 | func capellaPayloadToPayloadHeader(payload *capella.ExecutionPayload) (*capella.ExecutionPayloadHeader, error) { 189 | if payload == nil { 190 | return nil, ErrNilPayload 191 | } 192 | 193 | txRoot, err := deriveTransactionsRoot(payload.Transactions) 194 | if err != nil { 195 | return nil, fmt.Errorf("failed to derive transactions root: %w", err) 196 | } 197 | 198 | wdRoot, err := deriveWithdrawalsRoot(payload.Withdrawals) 199 | if err != nil { 200 | return nil, fmt.Errorf("failed to derive withdrawals root: %w", err) 201 | } 202 | 203 | return &capella.ExecutionPayloadHeader{ 204 | ParentHash: payload.ParentHash, 205 | FeeRecipient: payload.FeeRecipient, 206 | StateRoot: payload.StateRoot, 207 | ReceiptsRoot: payload.ReceiptsRoot, 208 | LogsBloom: payload.LogsBloom, 209 | PrevRandao: payload.PrevRandao, 210 | BlockNumber: payload.BlockNumber, 211 | GasLimit: payload.GasLimit, 212 | GasUsed: payload.GasUsed, 213 | Timestamp: payload.Timestamp, 214 | ExtraData: payload.ExtraData, 215 | BaseFeePerGas: payload.BaseFeePerGas, 216 | BlockHash: payload.BlockHash, 217 | TransactionsRoot: txRoot, 218 | WithdrawalsRoot: wdRoot, 219 | }, nil 220 | } 221 | 222 | func denebPayloadToPayloadHeader(payload *deneb.ExecutionPayload) (*deneb.ExecutionPayloadHeader, error) { 223 | if payload == nil { 224 | return nil, ErrNilPayload 225 | } 226 | 227 | txRoot, err := deriveTransactionsRoot(payload.Transactions) 228 | if err != nil { 229 | return nil, fmt.Errorf("failed to derive transactions root: %w", err) 230 | } 231 | 232 | wdRoot, err := deriveWithdrawalsRoot(payload.Withdrawals) 233 | if err != nil { 234 | return nil, fmt.Errorf("failed to derive withdrawals root: %w", err) 235 | } 236 | 237 | return &deneb.ExecutionPayloadHeader{ 238 | ParentHash: payload.ParentHash, 239 | FeeRecipient: payload.FeeRecipient, 240 | StateRoot: payload.StateRoot, 241 | ReceiptsRoot: payload.ReceiptsRoot, 242 | LogsBloom: payload.LogsBloom, 243 | PrevRandao: payload.PrevRandao, 244 | BlockNumber: payload.BlockNumber, 245 | GasLimit: payload.GasLimit, 246 | GasUsed: payload.GasUsed, 247 | Timestamp: payload.Timestamp, 248 | ExtraData: payload.ExtraData, 249 | BaseFeePerGas: payload.BaseFeePerGas, 250 | BlockHash: payload.BlockHash, 251 | TransactionsRoot: txRoot, 252 | WithdrawalsRoot: wdRoot, 253 | BlobGasUsed: payload.BlobGasUsed, 254 | ExcessBlobGas: payload.ExcessBlobGas, 255 | }, nil 256 | } 257 | 258 | func deriveTransactionsRoot(transactions []bellatrix.Transaction) (phase0.Root, error) { 259 | txs := utilbellatrix.ExecutionPayloadTransactions{Transactions: transactions} 260 | txRoot, err := txs.HashTreeRoot() 261 | if err != nil { 262 | return phase0.Root{}, err 263 | } 264 | return txRoot, nil 265 | } 266 | 267 | func deriveWithdrawalsRoot(withdrawals []*capella.Withdrawal) (phase0.Root, error) { 268 | wd := utilcapella.ExecutionPayloadWithdrawals{Withdrawals: withdrawals} 269 | wdRoot, err := wd.HashTreeRoot() 270 | if err != nil { 271 | return phase0.Root{}, err 272 | } 273 | return wdRoot, nil 274 | } 275 | 276 | // ComputeBlockHash computes the block hash for a given execution payload. 277 | func ComputeBlockHash(payload *api.VersionedExecutionPayload, parentBeaconRoot *phase0.Root) (phase0.Hash32, error) { 278 | switch payload.Version { 279 | case spec.DataVersionBellatrix: 280 | header, err := bellatrixExecutionPayloadToBlockHeader(payload.Bellatrix) 281 | if err != nil { 282 | return phase0.Hash32{}, err 283 | } 284 | return phase0.Hash32(header.Hash()), nil 285 | case spec.DataVersionCapella: 286 | header, err := capellaExecutionPayloadToBlockHeader(payload.Capella) 287 | if err != nil { 288 | return phase0.Hash32{}, err 289 | } 290 | return phase0.Hash32(header.Hash()), nil 291 | case spec.DataVersionDeneb: 292 | header, err := denebExecutionPayloadToBlockHeader(payload.Deneb, parentBeaconRoot) 293 | if err != nil { 294 | return phase0.Hash32{}, err 295 | } 296 | return phase0.Hash32(header.Hash()), nil 297 | case spec.DataVersionElectra: 298 | // Electra uses the same ExecutionPayload as Deneb 299 | header, err := denebExecutionPayloadToBlockHeader(payload.Electra, parentBeaconRoot) 300 | if err != nil { 301 | return phase0.Hash32{}, err 302 | } 303 | return phase0.Hash32(header.Hash()), nil 304 | case spec.DataVersionPhase0, spec.DataVersionAltair: 305 | return phase0.Hash32{}, fmt.Errorf("%w: %d", ErrUnsupportedVersion, payload.Version) 306 | case spec.DataVersionUnknown: 307 | fallthrough 308 | default: 309 | return phase0.Hash32{}, fmt.Errorf("%w: %d", ErrUnknownVersion, payload.Version) 310 | } 311 | } 312 | 313 | func bellatrixExecutionPayloadToBlockHeader(payload *bellatrix.ExecutionPayload) (*types.Header, error) { 314 | transactionHash, err := deriveTransactionsHash(payload.Transactions) 315 | if err != nil { 316 | return nil, err 317 | } 318 | baseFeePerGas := deriveBaseFeePerGas(payload.BaseFeePerGas) 319 | return &types.Header{ 320 | ParentHash: common.Hash(payload.ParentHash), 321 | UncleHash: types.EmptyUncleHash, 322 | Coinbase: common.Address(payload.FeeRecipient), 323 | Root: payload.StateRoot, 324 | TxHash: transactionHash, 325 | ReceiptHash: payload.ReceiptsRoot, 326 | Bloom: payload.LogsBloom, 327 | Difficulty: common.Big0, 328 | Number: new(big.Int).SetUint64(payload.BlockNumber), 329 | GasLimit: payload.GasLimit, 330 | GasUsed: payload.GasUsed, 331 | Time: payload.Timestamp, 332 | Extra: payload.ExtraData, 333 | MixDigest: payload.PrevRandao, 334 | BaseFee: baseFeePerGas, 335 | }, nil 336 | } 337 | 338 | func capellaExecutionPayloadToBlockHeader(payload *capella.ExecutionPayload) (*types.Header, error) { 339 | transactionHash, err := deriveTransactionsHash(payload.Transactions) 340 | if err != nil { 341 | return nil, err 342 | } 343 | withdrawalsHash := deriveWithdrawalsHash(payload.Withdrawals) 344 | baseFeePerGas := deriveBaseFeePerGas(payload.BaseFeePerGas) 345 | return &types.Header{ 346 | ParentHash: common.Hash(payload.ParentHash), 347 | UncleHash: types.EmptyUncleHash, 348 | Coinbase: common.Address(payload.FeeRecipient), 349 | Root: payload.StateRoot, 350 | TxHash: transactionHash, 351 | ReceiptHash: payload.ReceiptsRoot, 352 | Bloom: payload.LogsBloom, 353 | Difficulty: common.Big0, 354 | Number: new(big.Int).SetUint64(payload.BlockNumber), 355 | GasLimit: payload.GasLimit, 356 | GasUsed: payload.GasUsed, 357 | Time: payload.Timestamp, 358 | Extra: payload.ExtraData, 359 | MixDigest: payload.PrevRandao, 360 | BaseFee: baseFeePerGas, 361 | WithdrawalsHash: &withdrawalsHash, 362 | }, nil 363 | } 364 | 365 | func denebExecutionPayloadToBlockHeader(payload *deneb.ExecutionPayload, parentBeaconRoot *phase0.Root) (*types.Header, error) { 366 | transactionHash, err := deriveTransactionsHash(payload.Transactions) 367 | if err != nil { 368 | return nil, err 369 | } 370 | baseFeePerGas := payload.BaseFeePerGas.ToBig() 371 | withdrawalsHash := deriveWithdrawalsHash(payload.Withdrawals) 372 | var beaconRootHash *common.Hash 373 | if parentBeaconRoot != nil { 374 | root := common.Hash(*parentBeaconRoot) 375 | beaconRootHash = &root 376 | } 377 | return &types.Header{ 378 | ParentHash: common.Hash(payload.ParentHash), 379 | UncleHash: types.EmptyUncleHash, 380 | Coinbase: common.Address(payload.FeeRecipient), 381 | Root: common.Hash(payload.StateRoot), 382 | TxHash: transactionHash, 383 | ReceiptHash: common.Hash(payload.ReceiptsRoot), 384 | Bloom: payload.LogsBloom, 385 | Difficulty: common.Big0, 386 | Number: new(big.Int).SetUint64(payload.BlockNumber), 387 | GasLimit: payload.GasLimit, 388 | GasUsed: payload.GasUsed, 389 | Time: payload.Timestamp, 390 | Extra: payload.ExtraData, 391 | MixDigest: payload.PrevRandao, 392 | BaseFee: baseFeePerGas, 393 | WithdrawalsHash: &withdrawalsHash, 394 | BlobGasUsed: &payload.BlobGasUsed, 395 | ExcessBlobGas: &payload.ExcessBlobGas, 396 | ParentBeaconRoot: beaconRootHash, 397 | }, nil 398 | } 399 | 400 | func deriveTransactionsHash(transactions []bellatrix.Transaction) (common.Hash, error) { 401 | transactionData := make([]*types.Transaction, len(transactions)) 402 | for i, encTx := range transactions { 403 | var tx types.Transaction 404 | 405 | if err := tx.UnmarshalBinary(encTx); err != nil { 406 | return common.Hash{}, ErrInvalidTransaction 407 | } 408 | transactionData[i] = &tx 409 | } 410 | return types.DeriveSha(types.Transactions(transactionData), trie.NewStackTrie(nil)), nil 411 | } 412 | 413 | func deriveWithdrawalsHash(withdrawals []*capella.Withdrawal) common.Hash { 414 | withdrawalData := make([]*types.Withdrawal, len(withdrawals)) 415 | for i, w := range withdrawals { 416 | withdrawalData[i] = &types.Withdrawal{ 417 | Index: uint64(w.Index), 418 | Validator: uint64(w.ValidatorIndex), 419 | Address: common.Address(w.Address), 420 | Amount: uint64(w.Amount), 421 | } 422 | } 423 | return types.DeriveSha(types.Withdrawals(withdrawalData), trie.NewStackTrie(nil)) 424 | } 425 | 426 | func deriveBaseFeePerGas(baseFeePerGas [32]byte) *big.Int { 427 | // base fee per gas is stored little-endian but we need it 428 | // big-endian for big.Int. 429 | var arr [32]byte 430 | for i := 0; i < 32; i++ { 431 | arr[i] = baseFeePerGas[32-1-i] 432 | } 433 | return new(big.Int).SetBytes(arr[:]) 434 | } 435 | -------------------------------------------------------------------------------- /utils/utils_fuzz_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func FuzzHexToAddress(f *testing.F) { 8 | f.Fuzz(func(t *testing.T, str string) { 9 | _, _ = HexToAddress(str) 10 | }) 11 | } 12 | 13 | func FuzzHexToPubkey(f *testing.F) { 14 | f.Fuzz(func(t *testing.T, str string) { 15 | _, _ = HexToPubkey(str) 16 | }) 17 | } 18 | 19 | func FuzzHexToSignature(f *testing.F) { 20 | f.Fuzz(func(t *testing.T, str string) { 21 | _, _ = HexToSignature(str) 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /utils/utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | 7 | "github.com/attestantio/go-builder-client/api" 8 | "github.com/attestantio/go-eth2-client/spec" 9 | "github.com/attestantio/go-eth2-client/spec/bellatrix" 10 | "github.com/attestantio/go-eth2-client/spec/capella" 11 | "github.com/attestantio/go-eth2-client/spec/deneb" 12 | "github.com/attestantio/go-eth2-client/spec/phase0" 13 | "github.com/stretchr/testify/require" 14 | ) 15 | 16 | func TestHexToHash(t *testing.T) { 17 | _, err := HexToHash("0x01") 18 | require.Error(t, err) 19 | 20 | a, err := HexToHash("0x0100000000000000000000000000000000000000000000000000000000000000") 21 | require.NoError(t, err) 22 | require.Equal(t, "0x0100000000000000000000000000000000000000000000000000000000000000", a.String()) 23 | } 24 | 25 | func TestHexToAddress(t *testing.T) { 26 | _, err := HexToAddress("0x01") 27 | require.Error(t, err) 28 | 29 | a, err := HexToAddress("0x0100000000000000000000000000000000000000") 30 | require.NoError(t, err) 31 | require.Equal(t, "0x0100000000000000000000000000000000000000", a.String()) 32 | } 33 | 34 | func TestHexToPubkey(t *testing.T) { 35 | testCases := []struct { 36 | name string 37 | pubkey string 38 | expectedErr string 39 | }{ 40 | { 41 | name: "Valid pubkey", 42 | pubkey: "0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae", 43 | }, 44 | { 45 | name: "Invalid pubkey (wrong length)", 46 | pubkey: "0x123456", 47 | expectedErr: "invalid length", 48 | }, 49 | { 50 | name: "Invalid pubkey (not on the curve)", 51 | pubkey: "0xed7f862045422bd51ba732730ce993c94d2545e5db1112102026343904fcdf6f5cf37926a3688444703772ed80fa223f", 52 | expectedErr: "invalid pubkey", 53 | }, 54 | { 55 | name: "Invalid pubkey (no 0x prefix)", 56 | pubkey: "this is not hex", 57 | expectedErr: "hex string without 0x prefix", 58 | }, 59 | { 60 | name: "Invalid pubkey (not hex)", 61 | pubkey: "0xthisisnothex", 62 | expectedErr: "invalid hex string", 63 | }, 64 | } 65 | 66 | for _, tt := range testCases { 67 | t.Run(tt.name, func(t *testing.T) { 68 | result, err := HexToPubkey(tt.pubkey) 69 | if tt.expectedErr != "" { 70 | require.EqualError(t, err, tt.expectedErr) 71 | } else { 72 | require.NoError(t, err) 73 | require.Equal(t, tt.pubkey, result.String()) 74 | } 75 | }) 76 | } 77 | } 78 | 79 | func TestHexToSignature(t *testing.T) { 80 | testCases := []struct { 81 | name string 82 | signature string 83 | expectedErr string 84 | }{ 85 | { 86 | name: "Valid signature", 87 | signature: "0x8069aa021666163aae46d353c348aa913fb5050062e05ab764c8eef99407a8befcd46190b30cc40e40ee8c197356959816799d62e85f640ef76b4be1b08a741949230fbde49589125537daad06c23a66838725d89e3504bc21559a91534f6712", 88 | }, 89 | { 90 | name: "Invalid signature (wrong length)", 91 | signature: "0x123456", 92 | expectedErr: "invalid length", 93 | }, 94 | { 95 | name: "Invalid signature (not on the curve)", 96 | signature: "0xb8f03e639b91fa8e9892f66c798f07f6e7b3453234f643b2c06a35c5149cf6d85e4e1572c33549fe749292445fbff9e0739c78159324c35dc1a90e5745ca70c8caf1b63fb6678d81bd2d5cb6baeb1462df7a93877d0e22a31dd6438334536d9a", 97 | expectedErr: "invalid signature", 98 | }, 99 | { 100 | name: "Invalid signature (no 0x prefix)", 101 | signature: "this is not hex", 102 | expectedErr: "hex string without 0x prefix", 103 | }, 104 | { 105 | name: "Invalid signature (not hex)", 106 | signature: "0xthisisnothex", 107 | expectedErr: "invalid hex string", 108 | }, 109 | } 110 | 111 | for _, tt := range testCases { 112 | t.Run(tt.name, func(t *testing.T) { 113 | result, err := HexToSignature(tt.signature) 114 | if tt.expectedErr != "" { 115 | require.EqualError(t, err, tt.expectedErr) 116 | } else { 117 | require.NoError(t, err) 118 | require.Equal(t, tt.signature, result.String()) 119 | } 120 | }) 121 | } 122 | } 123 | 124 | func TestComputeHash(t *testing.T) { 125 | t.Run("Should compute bellatrix hash", func(t *testing.T) { 126 | jsonFile, err := os.Open("../testdata/executionpayload/bellatrix-case0.json") 127 | require.NoError(t, err) 128 | defer jsonFile.Close() 129 | 130 | payload := new(bellatrix.ExecutionPayload) 131 | require.NoError(t, DecodeJSON(jsonFile, payload)) 132 | versionedPayload := &api.VersionedExecutionPayload{ 133 | Version: spec.DataVersionBellatrix, 134 | Bellatrix: payload, 135 | } 136 | 137 | hash, err := ComputeBlockHash(versionedPayload, nil) 138 | require.NoError(t, err) 139 | require.Equal(t, "0x6662fb418aa7b5c5c80e2e8bc87be48db82e799c4704368d34ddeb3b12549655", hash.String()) 140 | }) 141 | 142 | t.Run("Should compute capella hash", func(t *testing.T) { 143 | jsonFile, err := os.Open("../testdata/executionpayload/capella-case0.json") 144 | require.NoError(t, err) 145 | defer jsonFile.Close() 146 | 147 | payload := new(capella.ExecutionPayload) 148 | require.NoError(t, DecodeJSON(jsonFile, payload)) 149 | versionedPayload := &api.VersionedExecutionPayload{ 150 | Version: spec.DataVersionCapella, 151 | Capella: payload, 152 | } 153 | 154 | hash, err := ComputeBlockHash(versionedPayload, nil) 155 | require.NoError(t, err) 156 | require.Equal(t, "0x08751ea2076d3ecc606231495a90ba91a66a9b8fb1a2b76c333f1957a1c667c3", hash.String()) 157 | }) 158 | 159 | t.Run("Should compute deneb hash", func(t *testing.T) { 160 | jsonFile, err := os.Open("../testdata/executionpayload/deneb-case0.json") 161 | require.NoError(t, err) 162 | defer jsonFile.Close() 163 | 164 | payload := new(deneb.ExecutionPayload) 165 | require.NoError(t, DecodeJSON(jsonFile, payload)) 166 | versionedPayload := &api.VersionedExecutionPayload{ 167 | Version: spec.DataVersionDeneb, 168 | Deneb: payload, 169 | } 170 | h, _ := HexToHash("0xa119064ee9c03e2c7ad5821b6077606c64f36542eda12ed61a1edc5f898a17fc") 171 | r := phase0.Root(h) 172 | hash, err := ComputeBlockHash(versionedPayload, &r) 173 | require.NoError(t, err) 174 | require.Equal(t, "0xd9491c8ae79611d0f08806f29b1e2e86cb8f64512aa381e543dcae257dda80d6", hash.String()) 175 | }) 176 | 177 | t.Run("Should error on unknown version", func(t *testing.T) { 178 | payload := new(capella.ExecutionPayload) 179 | versionedPayload := &api.VersionedExecutionPayload{ 180 | Version: spec.DataVersionAltair, 181 | Capella: payload, 182 | } 183 | 184 | _, err := ComputeBlockHash(versionedPayload, nil) 185 | require.Error(t, err) 186 | }) 187 | } 188 | --------------------------------------------------------------------------------