Compare commits
376 Commits
45a272c7b9
...
ce19466f47
Author | SHA1 | Date | |
---|---|---|---|
|
ce19466f47 | ||
1fa7d1736d | |||
8907a1bc80 | |||
e9c8a528d4 | |||
|
1a89183720 | ||
|
e7eb23251f | ||
|
2bd6bd01d2 | ||
|
9038ba6942 | ||
|
51b479e564 | ||
|
5a0f468f8c | ||
|
bd9dd1b3ce | ||
|
7f131dcbc9 | ||
|
d45248db7a | ||
|
7e8ed6b43d | ||
|
02eb36afc2 | ||
|
5065089c3d | ||
|
2e29160068 | ||
|
b2768769d1 | ||
|
8722e19c77 | ||
|
48be241dbf | ||
|
8f7eb9ccd9 | ||
|
432bfa1e0e | ||
|
a04235be6e | ||
|
ce300f6722 | ||
|
84dd8855de | ||
|
a0fa38c499 | ||
|
04f88e3356 | ||
|
77fa5997de | ||
|
9874566daf | ||
|
d784d35249 | ||
|
bc0be1b106 | ||
|
c2fa267503 | ||
|
dd938d103d | ||
|
b2d3b18e53 | ||
|
b4a5cf811e | ||
|
b20b4a7159 | ||
|
413e9fc429 | ||
|
c01da155be | ||
|
d0d5d38a59 | ||
|
c3d9ca62c1 | ||
|
ac499a7ff1 | ||
|
da6cdaf635 | ||
|
5ba3d578ee | ||
|
c7efabf8d6 | ||
|
bc14d12fd7 | ||
|
892f98ad6a | ||
|
e591342994 | ||
|
0961ecb69f | ||
|
406ad4d1fb | ||
|
916d6a441a | ||
|
703c3b6b74 | ||
|
11733e92ff | ||
|
210c889297 | ||
|
4e936546a3 | ||
|
9974ce6f92 | ||
|
336d39d238 | ||
|
9aec954185 | ||
|
325fc8351e | ||
|
7dd3c9d233 | ||
|
20a51847a8 | ||
|
cd9d109d65 | ||
|
e42a4cb944 | ||
|
1dd00d2452 | ||
|
8df3b1a5ca | ||
|
ace421d033 | ||
|
771c2e7cc3 | ||
|
39b5250f63 | ||
|
e35d5eb3fe | ||
|
0bb80e6be1 | ||
|
3184027a2c | ||
|
e43bc1774d | ||
|
a6ee75999b | ||
|
63f8d10434 | ||
|
c0210061c8 | ||
|
5d2d49229b | ||
|
d9de580d74 | ||
|
051e5f5534 | ||
|
00ce5674f7 | ||
|
f912a2192d | ||
|
cb62de132c | ||
|
052b705632 | ||
|
3d2f81a30c | ||
|
6781ee2a5c | ||
|
07e9739871 | ||
|
f7ad35eae9 | ||
|
38ea6101de | ||
|
31ada7d3e3 | ||
|
5be3014e0b | ||
|
b549624096 | ||
|
9d34721d46 | ||
|
18be67b3a3 | ||
|
4b4fa9b09d | ||
|
040657d0bf | ||
|
399cbbc8fd | ||
|
5d773a540d | ||
|
fadf28c4b5 | ||
|
c47808fb91 | ||
|
eaf3fe14cc | ||
|
4641b6e012 | ||
|
54b4a7d9c7 | ||
|
461422d52e | ||
|
51c041850b | ||
|
bdc42a9128 | ||
|
3993f2f870 | ||
|
67819b62c8 | ||
|
5912cf69a9 | ||
|
8d626683a5 | ||
|
b6e2fadd73 | ||
|
bb33c798de | ||
|
f5f285379a | ||
|
8fa170d988 | ||
|
3ca53046eb | ||
|
8409cfd6b4 | ||
|
6814eed657 | ||
|
7a99cf6bf0 | ||
|
bb43b2cbc4 | ||
bf0041eebe | |||
1d8f2a28e8 | |||
20ea16310e | |||
|
477985fdcd | ||
|
24f8b776c9 | ||
|
63e1ad633c | ||
|
ba7a166608 | ||
|
e9630a85f4 | ||
|
5822e2e15f | ||
|
0747e800de | ||
|
f22b6f3e8e | ||
|
6ed9390f9b | ||
|
dc56f2a361 | ||
|
e516d5842c | ||
|
54899440d2 | ||
|
4ca9210d59 | ||
|
b3f1d35171 | ||
|
8a33d8e506 | ||
|
b19d7f9f9e | ||
|
fee25089a9 | ||
|
366f480bc1 | ||
|
1bf1a5634e | ||
|
23c0ca58af | ||
|
a20fadc454 | ||
|
80956ac723 | ||
|
d8d864768a | ||
|
7434ccb8c8 | ||
f7ff01fd54 | |||
a9c2d243c5 | |||
|
12336c753f | ||
|
02d22a5aad | ||
|
5dc7541135 | ||
|
679d028484 | ||
|
9badeb2b93 | ||
|
829b8c4821 | ||
|
bdda4b3863 | ||
|
923254af05 | ||
|
6e8c38b994 | ||
|
1b5aa6c570 | ||
|
c3e91ce1af | ||
|
e986bbfa6f | ||
|
86b30777b8 | ||
|
60838d43f9 | ||
|
d4c0064e7c | ||
|
5470afdeb8 | ||
|
f92264d342 | ||
|
aee14ebee9 | ||
|
c3924a529e | ||
|
b1dd4f79f3 | ||
|
7f1b5c5f9b | ||
|
4cfa8704a9 | ||
|
9ee93f1e26 | ||
|
d2d3490abc | ||
|
9aba661554 | ||
|
fc577b80aa | ||
|
f3e558d4e0 | ||
|
c63fe40e29 | ||
|
34191cb50a | ||
|
3527a74333 | ||
|
e2c33f60c4 | ||
|
27810f60ad | ||
|
76dbcfb723 | ||
|
50a295b789 | ||
|
6e40cd7920 | ||
|
2c03e88687 | ||
|
89bc9e0ee6 | ||
|
2c14e954cf | ||
|
7bf0c614f6 | ||
|
4415e7c7b8 | ||
|
78e00bf68d | ||
|
aee0d470b1 | ||
|
0186a12412 | ||
|
bff86afa0c | ||
|
ef92d21d25 | ||
|
2f6b8d86f1 | ||
|
94d0740fd0 | ||
|
294066e632 | ||
|
27dce1a2a2 | ||
|
0882b7b09d | ||
|
08b8ddc42d | ||
|
026f9ef80c | ||
|
afba49ee05 | ||
|
c0530b8313 | ||
|
e3080c170c | ||
|
1805f477ae | ||
|
db52b5e61d | ||
|
e5eb32acee | ||
|
211dbb7197 | ||
|
27600a5b84 | ||
|
99bbb33701 | ||
|
a32e69a28c | ||
|
937ea491f9 | ||
|
85e469f787 | ||
|
f22cdb8b36 | ||
|
e4d2025741 | ||
|
603cf55aca | ||
|
7792c000b0 | ||
|
69568c5548 | ||
|
8f61fc8b73 | ||
|
b8399771db | ||
|
972007a517 | ||
|
3b41be695e | ||
|
d0dc349fd3 | ||
|
9674fe3f90 | ||
|
c08f3e1034 | ||
|
5a88b67e6f | ||
|
c6de31049b | ||
|
a2de453fd1 | ||
|
79609688a5 | ||
|
967626b075 | ||
|
59a823409e | ||
|
1dfed7aed8 | ||
|
b45c9e8e03 | ||
|
2ef96afe2a | ||
|
81a8106bc6 | ||
|
66a0d514c4 | ||
|
80ee3f61e6 | ||
|
2f93e2ae10 | ||
|
9b75b91e74 | ||
|
2f1f3e88ae | ||
|
e87859e9ab | ||
|
a74109ae46 | ||
|
011619ec82 | ||
|
fd0aaa1d6b | ||
|
4211c5c401 | ||
|
48f1bf8c4c | ||
|
0b5c23e739 | ||
|
4a33bc66c5 | ||
|
ec965607cd | ||
|
4549968e8e | ||
|
b404517691 | ||
|
d3268003ac | ||
|
adcf21f453 | ||
|
47c68a82e2 | ||
|
3dde685942 | ||
|
aaf9446523 | ||
|
ec68600e56 | ||
|
627f95403f | ||
|
47e8d073da | ||
|
a88d316b0a | ||
|
9f28e94d66 | ||
|
1201e7c4f8 | ||
|
13009f4c51 | ||
|
3c32c1f732 | ||
|
f612829c47 | ||
|
3cbece6224 | ||
|
5aaee91799 | ||
|
f9b0ce4e41 | ||
|
c16c02785d | ||
|
9a4172189d | ||
|
007ba02e4b | ||
|
15b7e55b50 | ||
|
968e79b705 | ||
|
63d3eb06c4 | ||
|
6030087970 | ||
|
3c7e5a0045 | ||
|
826327a8e7 | ||
|
5352d44915 | ||
|
cc416746a1 | ||
|
72b7820579 | ||
|
6060d4adc9 | ||
|
4fc1f8f6b9 | ||
|
a4c88337eb | ||
|
d96772ce6b | ||
|
c56312cd2f | ||
|
9ac78685b3 | ||
|
75b4d1f625 | ||
|
efb6546a11 | ||
|
80ae5b46d4 | ||
|
191a31a9ff | ||
|
4acf8d22df | ||
|
27b3d2d74a | ||
|
f18c3be78f | ||
|
fe20d6aa05 | ||
|
1bca34f157 | ||
|
1d3c13f87e | ||
|
6cb2477e5f | ||
|
df8b824e2e | ||
|
34aa5df84d | ||
|
4e93a957d2 | ||
|
99fedadd4e | ||
|
11a11e38ac | ||
|
9011356e45 | ||
|
c8e3e83641 | ||
|
81f2c2023a | ||
|
09d3d9bd1b | ||
|
625d2c0e98 | ||
|
a8c42dc388 | ||
|
149b5220ad | ||
|
3df75af219 | ||
|
5d4d973cc4 | ||
|
9497293e26 | ||
|
416ff11059 | ||
|
299b5cb05c | ||
|
52f4791779 | ||
|
6a86c8934a | ||
|
956eef4abe | ||
|
ff201f92c1 | ||
|
b7c57d47ec | ||
|
5b9e5f56e2 | ||
|
a693104bcb | ||
|
97c44a8fe6 | ||
|
2e20863400 | ||
|
1b06b9762a | ||
|
65f00aad1c | ||
|
9249a67e45 | ||
|
4f6c8eacb3 | ||
|
9446654386 | ||
|
3e05a986b1 | ||
|
3af3c8c951 | ||
|
a03c9e1324 | ||
|
88f38674d1 | ||
|
e6f05fcca9 | ||
|
f7307d527d | ||
|
25af69b8e2 | ||
|
7d7fad0988 | ||
|
86fd4f27e2 | ||
|
ea0f27c92d | ||
|
1b4eded9c5 | ||
|
b8928b1e57 | ||
|
1ed3de57d4 | ||
|
7b33b6e821 | ||
|
411a43e378 | ||
|
b36e63f184 | ||
|
c36c999383 | ||
|
0d5af1c7dc | ||
|
f615e3813d | ||
|
8291edc416 | ||
|
820a0af71c | ||
|
d9d51dd345 | ||
|
40377543bf | ||
|
6f375ae627 | ||
|
c3328b6042 | ||
|
41851f5ba5 | ||
|
d2df0b4c5f | ||
|
5f0574bbc4 | ||
|
2e7254e737 | ||
|
c58a596a53 | ||
|
7ed35c32bd | ||
|
5b7da7301f | ||
|
328756dc00 | ||
|
16cc5314cf | ||
|
75ad936fbb | ||
|
7a8bb87257 | ||
|
c45774b74b | ||
|
6e4c285ed1 | ||
|
875e506148 | ||
|
c89b72ed5c | ||
|
a5f4ba4efd | ||
|
e4e1add4af | ||
|
2d0526478d | ||
|
d4f030e273 | ||
|
4dd3527541 | ||
|
b821bd9948 | ||
|
03808de29a | ||
|
091a2f4884 | ||
|
ad8719a64a | ||
|
97cf240fe0 | ||
|
5c55657c54 | ||
|
ff46e3c7f8 |
108
.circleci/config.yml
Normal file
108
.circleci/config.yml
Normal file
@ -0,0 +1,108 @@
|
||||
orbs:
|
||||
aws-cli: circleci/aws-cli@1.0.0 #See: https://circleci.com/orbs/registry/orb/circleci/aws-cli
|
||||
|
||||
|
||||
version: 2.1
|
||||
jobs:
|
||||
test:
|
||||
docker:
|
||||
- image: cimg/go:1.21.0
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Prep env
|
||||
command: |
|
||||
mkdir -p /home/circleci/go/src
|
||||
mkdir artifacts
|
||||
go mod tidy
|
||||
- run:
|
||||
name: test rpc
|
||||
command: go test ./rpc/
|
||||
- run:
|
||||
name: test eth
|
||||
command: go test ./eth/
|
||||
- run:
|
||||
name: test eth/tracers
|
||||
command: go test ./eth/tracers/
|
||||
- run:
|
||||
name: test core
|
||||
command: go test ./core/
|
||||
- run:
|
||||
name: test core/vm
|
||||
command: go test ./core/vm/
|
||||
- run:
|
||||
name: test core/state
|
||||
command: go test ./core/state/
|
||||
- run:
|
||||
name: test core/rawdb
|
||||
command: go test ./core/rawdb/
|
||||
build_geth_push:
|
||||
docker: # run the steps with Docker
|
||||
- image: cimg/go:1.21.0 # ...with this image as the primary container
|
||||
# this is where all `steps` will run
|
||||
steps:
|
||||
- checkout
|
||||
- setup_remote_docker
|
||||
- run:
|
||||
name: Prep env
|
||||
command: |
|
||||
mkdir -p /home/circleci/go/src
|
||||
mkdir artifacts
|
||||
go mod tidy
|
||||
- run:
|
||||
name: build geth binaries
|
||||
command: |
|
||||
sudo apt update
|
||||
sudo apt install gcc-aarch64-linux-gnu libc6-dev-arm64-cross wget -y
|
||||
PLUGETH_UTILS_VERSION=$(grep "github.com/openrelayxyz/plugeth-utils v" go.mod | cut -d ' ' -f 2)
|
||||
export GOPATH=$HOME/go
|
||||
export GOARCH=amd64
|
||||
export PLUGETH_UTILS_VERSION=$(grep "github.com/openrelayxyz/plugeth-utils v" go.mod | cut -d ' ' -f 2)
|
||||
go build -o ./artifacts/geth-linux-amd64-$PLUGETH_UTILS_VERSION-${CIRCLE_TAG} ./cmd/geth
|
||||
CC=aarch64-linux-gnu-gcc CGO_ENABLED=1 GOARCH=arm64 go build -o ./artifacts/geth-linux-arm64-$PLUGETH_UTILS_VERSION-${CIRCLE_TAG} ./cmd/geth
|
||||
- run:
|
||||
name: "Publish Release on GitHub"
|
||||
command: |
|
||||
go install github.com/tcnksm/ghr@v0.14.0
|
||||
PLUGETH_UTILS_VERSION=$(grep "github.com/openrelayxyz/plugeth-utils v" go.mod | cut -d ' ' -f 2)
|
||||
NAME=plugeth-$PLUGETH_UTILS_VERSION-${CIRCLE_TAG}
|
||||
VERSION=${CIRCLE_TAG}
|
||||
ghr -draft -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -name $NAME -delete ${VERSION} ./artifacts/
|
||||
- aws-cli/setup: #See: https://circleci.com/orbs/registry/orb/circleci/aws-cli
|
||||
aws-access-key-id: ACCESS_KEY
|
||||
aws-secret-access-key: SECRET_ACCESS_KEY
|
||||
aws-region: AWS_REGION
|
||||
- run:
|
||||
name: push to s3
|
||||
command: |
|
||||
export PLUGETH_UTILS_VERSION=$(grep "github.com/openrelayxyz/plugeth-utils v" go.mod | cut -d ' ' -f 2)
|
||||
aws s3 cp ./artifacts/geth-linux-amd64-$PLUGETH_UTILS_VERSION-${CIRCLE_TAG} s3://ethercattle-binaries/plugeth/$CIRCLE_TAG/geth-linux-amd64 --acl=public-read
|
||||
aws s3 cp ./artifacts/geth-linux-arm64-$PLUGETH_UTILS_VERSION-${CIRCLE_TAG} s3://ethercattle-binaries/plugeth/$CIRCLE_TAG/geth-linux-arm64 --acl=public-read
|
||||
- run:
|
||||
name: Message Slack
|
||||
command: |
|
||||
./slack-post.sh -w $SLACK_WEBHOOK -m "*plugeth*:\nTag: $CIRCLE_TAG \n"
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
test:
|
||||
jobs:
|
||||
- test:
|
||||
filters:
|
||||
tags:
|
||||
ignore: /^v.*/
|
||||
build_and_test:
|
||||
jobs:
|
||||
- test:
|
||||
filters:
|
||||
tags:
|
||||
only: /^v.*/
|
||||
branches:
|
||||
ignore: /.*/
|
||||
- build_geth_push:
|
||||
context: Rivet
|
||||
requires:
|
||||
- test
|
||||
filters:
|
||||
tags:
|
||||
only: /^v.*/
|
7
.github/ISSUE_TEMPLATE/bug.md
vendored
7
.github/ISSUE_TEMPLATE/bug.md
vendored
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: Report a bug
|
||||
about: Something with go-ethereum is not working as expected
|
||||
about: Something with PluGeth is not working as expected
|
||||
title: ''
|
||||
labels: 'type:bug'
|
||||
assignees: ''
|
||||
@ -8,9 +8,8 @@ assignees: ''
|
||||
|
||||
#### System information
|
||||
|
||||
Geth version: `geth version`
|
||||
CL client & version: e.g. lighthouse/nimbus/prysm@v1.0.0
|
||||
OS & Version: Windows/Linux/OSX
|
||||
PluGeth version: `Geth version`
|
||||
OS & Version: Linux/OSX
|
||||
Commit hash : (if `develop`)
|
||||
|
||||
#### Expected behaviour
|
||||
|
3
.github/ISSUE_TEMPLATE/feature.md
vendored
3
.github/ISSUE_TEMPLATE/feature.md
vendored
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: Request a feature
|
||||
about: Report a missing feature - e.g. as a step before submitting a PR
|
||||
about: Are you looking for data this is not currently exposed through plugin hooks? Let us know.
|
||||
title: ''
|
||||
labels: 'type:feature'
|
||||
assignees: ''
|
||||
@ -15,3 +15,4 @@ What are the use-cases?
|
||||
|
||||
Do you have ideas regarding the implementation of this feature?
|
||||
Are you willing to implement this feature?
|
||||
|
||||
|
2
.github/ISSUE_TEMPLATE/question.md
vendored
2
.github/ISSUE_TEMPLATE/question.md
vendored
@ -6,4 +6,4 @@ labels: 'type:docs'
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
This should only be used in very rare cases e.g. if you are not 100% sure if something is a bug or asking a question that leads to improving the documentation. For general questions please use [discord](https://discord.gg/nthXNEv) or the Ethereum stack exchange at https://ethereum.stackexchange.com.
|
||||
For questions about PluGeth you will likely get faster responses by reaching out to us on at #plugeth channel on [discord](https://discord.gg/J3tQMWCVPn).
|
||||
|
22
Dockerfile
22
Dockerfile
@ -6,18 +6,26 @@ ARG BUILDNUM=""
|
||||
# Build Geth in a stock Go builder container
|
||||
FROM golang:1.21-alpine as builder
|
||||
|
||||
RUN apk add --no-cache gcc musl-dev linux-headers git
|
||||
RUN apk add --no-cache gcc musl-dev binutils-gold linux-headers git
|
||||
|
||||
# Configure creds for gitea
|
||||
ARG GIT_VDBTO_TOKEN
|
||||
|
||||
# Get dependencies - will also be cached if we won't change go.mod/go.sum
|
||||
COPY go.mod /go-ethereum/
|
||||
COPY go.sum /go-ethereum/
|
||||
RUN cd /go-ethereum && go mod download
|
||||
WORKDIR /go-ethereum/
|
||||
COPY go.mod .
|
||||
COPY go.sum .
|
||||
COPY wrapmain wrapmain
|
||||
RUN if [ -n "$GIT_VDBTO_TOKEN" ]; then git config --global url."https://$GIT_VDBTO_TOKEN:@git.vdb.to/".insteadOf "https://git.vdb.to/"; fi && \
|
||||
cd wrapmain && \
|
||||
go mod download && \
|
||||
rm -f ~/.gitconfig
|
||||
|
||||
ADD . /go-ethereum
|
||||
RUN cd /go-ethereum && go run build/ci.go install -static ./cmd/geth
|
||||
COPY . .
|
||||
RUN cd wrapmain && go build --trimpath -o /go-ethereum/build/bin/geth .
|
||||
|
||||
# Pull Geth into a second stage deploy alpine container
|
||||
FROM alpine:latest
|
||||
FROM alpine:3.18
|
||||
|
||||
RUN apk add --no-cache ca-certificates
|
||||
COPY --from=builder /go-ethereum/build/bin/geth /usr/local/bin/
|
||||
|
382
README.md
382
README.md
@ -1,358 +1,60 @@
|
||||
## Go Ethereum
|
||||
# PluGeth
|
||||
|
||||
Golang execution layer implementation of the Ethereum protocol.
|
||||
PluGeth is a fork of the [Go Ethereum Client](https://github.com/ethereum/go-ethereum)
|
||||
(Geth) that implements a plugin architecture, allowing developers to extend
|
||||
Geth's capabilities in a number of different ways using plugins, rather than
|
||||
having to create additional, new forks of Geth.
|
||||
|
||||
[![API Reference](
|
||||
https://pkg.go.dev/badge/github.com/ethereum/go-ethereum
|
||||
)](https://pkg.go.dev/github.com/ethereum/go-ethereum?tab=doc)
|
||||
[![Go Report Card](https://goreportcard.com/badge/github.com/ethereum/go-ethereum)](https://goreportcard.com/report/github.com/ethereum/go-ethereum)
|
||||
[![Travis](https://app.travis-ci.com/ethereum/go-ethereum.svg?branch=master)](https://app.travis-ci.com/github/ethereum/go-ethereum)
|
||||
[![Discord](https://img.shields.io/badge/discord-join%20chat-blue.svg)](https://discord.gg/nthXNEv)
|
||||
Documentation can be found [here](https://plugeth.org).
|
||||
|
||||
Automated builds are available for stable releases and the unstable master branch. Binary
|
||||
archives are published at https://geth.ethereum.org/downloads/.
|
||||
## Design Goals
|
||||
|
||||
## Building the source
|
||||
The upstream Geth client exists primarily to serve as a client for the Ethereum
|
||||
mainnet, though it also supports a number of popular testnets. Supporting the
|
||||
Ethereum mainnet is a big enough challenge in its own right that the Geth team
|
||||
generally avoids changes to support other networks, or to provide features only
|
||||
a small handful of users would be interested in.
|
||||
|
||||
For prerequisites and detailed build instructions please read the [Installation Instructions](https://geth.ethereum.org/docs/getting-started/installing-geth).
|
||||
The result is that many projects have forked Geth. Some implement their own
|
||||
consensus protocols or alter the behavior of the EVM to support other networks.
|
||||
Others are designed to extract information from the Ethereum mainnet in ways
|
||||
the standard Geth client does not support.
|
||||
|
||||
Building `geth` requires both a Go (version 1.19 or later) and a C compiler. You can install
|
||||
them using your favourite package manager. Once the dependencies are installed, run
|
||||
PluGeth aims to provide a single Geth fork that developers can choose to extend
|
||||
rather than forking the Geth project. Out of the box, PluGeth behaves exactly
|
||||
like upstream Geth, but by installing plugins written in Golang, developers can
|
||||
extend its functionality in a wide variety of way.
|
||||
|
||||
```shell
|
||||
make geth
|
||||
```
|
||||
### Submitting Pull Requests
|
||||
|
||||
or, to build the full suite of utilities:
|
||||
We are eager to include contributions from the community into the project. We ask that pull requests which include new features to be covered by our test plugin found in: `/plugins/test-plugin`. The test design and instructions for use are documented there. If further assistance is needed please get in touch with us.
|
||||
|
||||
```shell
|
||||
make all
|
||||
```
|
||||
### Contact Us
|
||||
|
||||
## Executables
|
||||
If you're trying to do something that isn't supported by the current plugin system, Reach out to us on [Discord](https://discord.gg/Epf7b7Gr) and we'll help you figure out how to make it work.
|
||||
|
||||
The go-ethereum project comes with several wrappers/executables found in the `cmd`
|
||||
directory.
|
||||
## System Requirements
|
||||
|
||||
| Command | Description |
|
||||
| :--------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`geth`** | Our main Ethereum CLI client. It is the entry point into the Ethereum network (main-, test- or private net), capable of running as a full node (default), archive node (retaining all historical state) or a light node (retrieving data live). It can be used by other processes as a gateway into the Ethereum network via JSON RPC endpoints exposed on top of HTTP, WebSocket and/or IPC transports. `geth --help` and the [CLI page](https://geth.ethereum.org/docs/fundamentals/command-line-options) for command line options. |
|
||||
| `clef` | Stand-alone signing tool, which can be used as a backend signer for `geth`. |
|
||||
| `devp2p` | Utilities to interact with nodes on the networking layer, without running a full blockchain. |
|
||||
| `abigen` | Source code generator to convert Ethereum contract definitions into easy-to-use, compile-time type-safe Go packages. It operates on plain [Ethereum contract ABIs](https://docs.soliditylang.org/en/develop/abi-spec.html) with expanded functionality if the contract bytecode is also available. However, it also accepts Solidity source files, making development much more streamlined. Please see our [Native DApps](https://geth.ethereum.org/docs/developers/dapp-developer/native-bindings) page for details. |
|
||||
| `bootnode` | Stripped down version of our Ethereum client implementation that only takes part in the network node discovery protocol, but does not run any of the higher level application protocols. It can be used as a lightweight bootstrap node to aid in finding peers in private networks. |
|
||||
| `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow isolated, fine-grained debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug run`). |
|
||||
| `rlpdump` | Developer utility tool to convert binary RLP ([Recursive Length Prefix](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp)) dumps (data encoding used by the Ethereum protocol both network as well as consensus wise) to user-friendlier hierarchical representation (e.g. `rlpdump --hex CE0183FFFFFFC4C304050583616263`). |
|
||||
System requirements will vary depending on which network you are connecting to.
|
||||
On the Ethereum mainnet, you should have at least 8 GB RAM, 2 CPUs, and 350 GB
|
||||
of SSD disks.
|
||||
|
||||
## Running `geth`
|
||||
PluGeth relies on Golang's Plugin implementation, which is only supported on
|
||||
Linux, FreeBSD, and macOS. Windows support is unlikely to be added in the
|
||||
foreseeable future.
|
||||
|
||||
Going through all the possible command line flags is out of scope here (please consult our
|
||||
[CLI Wiki page](https://geth.ethereum.org/docs/fundamentals/command-line-options)),
|
||||
but we've enumerated a few common parameter combos to get you up to speed quickly
|
||||
on how you can run your own `geth` instance.
|
||||
# Licensing Considerations
|
||||
|
||||
### Hardware Requirements
|
||||
The Geth codebase is licensed under the LGPL. By linking with Geth, you have an
|
||||
obligation to enable anyone you provide your plugin binaries to run against
|
||||
their own modified versions of Geth. Because of how Golang plugins work
|
||||
running against updated versions of Geth may require recompiling the plugin.
|
||||
|
||||
Minimum:
|
||||
If you plan to license your plugin under the LGPL or a more permissive license,
|
||||
you should be able to meet these requirements. If you plan to use your plugin
|
||||
privately without distributing it, you should be fine. If you plan to release
|
||||
your plugin without making the source available, you may find yourself in
|
||||
violation of Geth's license unless you can provide a way to relink it against
|
||||
more recent versions of Geth.
|
||||
|
||||
* CPU with 2+ cores
|
||||
* 4GB RAM
|
||||
* 1TB free storage space to sync the Mainnet
|
||||
* 8 MBit/sec download Internet service
|
||||
|
||||
Recommended:
|
||||
|
||||
* Fast CPU with 4+ cores
|
||||
* 16GB+ RAM
|
||||
* High-performance SSD with at least 1TB of free space
|
||||
* 25+ MBit/sec download Internet service
|
||||
|
||||
### Full node on the main Ethereum network
|
||||
|
||||
By far the most common scenario is people wanting to simply interact with the Ethereum
|
||||
network: create accounts; transfer funds; deploy and interact with contracts. For this
|
||||
particular use case, the user doesn't care about years-old historical data, so we can
|
||||
sync quickly to the current state of the network. To do so:
|
||||
|
||||
```shell
|
||||
$ geth console
|
||||
```
|
||||
|
||||
This command will:
|
||||
* Start `geth` in snap sync mode (default, can be changed with the `--syncmode` flag),
|
||||
causing it to download more data in exchange for avoiding processing the entire history
|
||||
of the Ethereum network, which is very CPU intensive.
|
||||
* Start the built-in interactive [JavaScript console](https://geth.ethereum.org/docs/interacting-with-geth/javascript-console),
|
||||
(via the trailing `console` subcommand) through which you can interact using [`web3` methods](https://github.com/ChainSafe/web3.js/blob/0.20.7/DOCUMENTATION.md)
|
||||
(note: the `web3` version bundled within `geth` is very old, and not up to date with official docs),
|
||||
as well as `geth`'s own [management APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc).
|
||||
This tool is optional and if you leave it out you can always attach it to an already running
|
||||
`geth` instance with `geth attach`.
|
||||
|
||||
### A Full node on the Görli test network
|
||||
|
||||
Transitioning towards developers, if you'd like to play around with creating Ethereum
|
||||
contracts, you almost certainly would like to do that without any real money involved until
|
||||
you get the hang of the entire system. In other words, instead of attaching to the main
|
||||
network, you want to join the **test** network with your node, which is fully equivalent to
|
||||
the main network, but with play-Ether only.
|
||||
|
||||
```shell
|
||||
$ geth --goerli console
|
||||
```
|
||||
|
||||
The `console` subcommand has the same meaning as above and is equally
|
||||
useful on the testnet too.
|
||||
|
||||
Specifying the `--goerli` flag, however, will reconfigure your `geth` instance a bit:
|
||||
|
||||
* Instead of connecting to the main Ethereum network, the client will connect to the Görli
|
||||
test network, which uses different P2P bootnodes, different network IDs and genesis
|
||||
states.
|
||||
* Instead of using the default data directory (`~/.ethereum` on Linux for example), `geth`
|
||||
will nest itself one level deeper into a `goerli` subfolder (`~/.ethereum/goerli` on
|
||||
Linux). Note, on OSX and Linux this also means that attaching to a running testnet node
|
||||
requires the use of a custom endpoint since `geth attach` will try to attach to a
|
||||
production node endpoint by default, e.g.,
|
||||
`geth attach <datadir>/goerli/geth.ipc`. Windows users are not affected by
|
||||
this.
|
||||
|
||||
*Note: Although some internal protective measures prevent transactions from
|
||||
crossing over between the main network and test network, you should always
|
||||
use separate accounts for play and real money. Unless you manually move
|
||||
accounts, `geth` will by default correctly separate the two networks and will not make any
|
||||
accounts available between them.*
|
||||
|
||||
### Configuration
|
||||
|
||||
As an alternative to passing the numerous flags to the `geth` binary, you can also pass a
|
||||
configuration file via:
|
||||
|
||||
```shell
|
||||
$ geth --config /path/to/your_config.toml
|
||||
```
|
||||
|
||||
To get an idea of how the file should look like you can use the `dumpconfig` subcommand to
|
||||
export your existing configuration:
|
||||
|
||||
```shell
|
||||
$ geth --your-favourite-flags dumpconfig
|
||||
```
|
||||
|
||||
*Note: This works only with `geth` v1.6.0 and above.*
|
||||
|
||||
#### Docker quick start
|
||||
|
||||
One of the quickest ways to get Ethereum up and running on your machine is by using
|
||||
Docker:
|
||||
|
||||
```shell
|
||||
docker run -d --name ethereum-node -v /Users/alice/ethereum:/root \
|
||||
-p 8545:8545 -p 30303:30303 \
|
||||
ethereum/client-go
|
||||
```
|
||||
|
||||
This will start `geth` in snap-sync mode with a DB memory allowance of 1GB, as the
|
||||
above command does. It will also create a persistent volume in your home directory for
|
||||
saving your blockchain as well as map the default ports. There is also an `alpine` tag
|
||||
available for a slim version of the image.
|
||||
|
||||
Do not forget `--http.addr 0.0.0.0`, if you want to access RPC from other containers
|
||||
and/or hosts. By default, `geth` binds to the local interface and RPC endpoints are not
|
||||
accessible from the outside.
|
||||
|
||||
### Programmatically interfacing `geth` nodes
|
||||
|
||||
As a developer, sooner rather than later you'll want to start interacting with `geth` and the
|
||||
Ethereum network via your own programs and not manually through the console. To aid
|
||||
this, `geth` has built-in support for a JSON-RPC based APIs ([standard APIs](https://ethereum.github.io/execution-apis/api-documentation/)
|
||||
and [`geth` specific APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc)).
|
||||
These can be exposed via HTTP, WebSockets and IPC (UNIX sockets on UNIX based
|
||||
platforms, and named pipes on Windows).
|
||||
|
||||
The IPC interface is enabled by default and exposes all the APIs supported by `geth`,
|
||||
whereas the HTTP and WS interfaces need to manually be enabled and only expose a
|
||||
subset of APIs due to security reasons. These can be turned on/off and configured as
|
||||
you'd expect.
|
||||
|
||||
HTTP based JSON-RPC API options:
|
||||
|
||||
* `--http` Enable the HTTP-RPC server
|
||||
* `--http.addr` HTTP-RPC server listening interface (default: `localhost`)
|
||||
* `--http.port` HTTP-RPC server listening port (default: `8545`)
|
||||
* `--http.api` API's offered over the HTTP-RPC interface (default: `eth,net,web3`)
|
||||
* `--http.corsdomain` Comma separated list of domains from which to accept cross origin requests (browser enforced)
|
||||
* `--ws` Enable the WS-RPC server
|
||||
* `--ws.addr` WS-RPC server listening interface (default: `localhost`)
|
||||
* `--ws.port` WS-RPC server listening port (default: `8546`)
|
||||
* `--ws.api` API's offered over the WS-RPC interface (default: `eth,net,web3`)
|
||||
* `--ws.origins` Origins from which to accept WebSocket requests
|
||||
* `--ipcdisable` Disable the IPC-RPC server
|
||||
* `--ipcapi` API's offered over the IPC-RPC interface (default: `admin,debug,eth,miner,net,personal,txpool,web3`)
|
||||
* `--ipcpath` Filename for IPC socket/pipe within the datadir (explicit paths escape it)
|
||||
|
||||
You'll need to use your own programming environments' capabilities (libraries, tools, etc) to
|
||||
connect via HTTP, WS or IPC to a `geth` node configured with the above flags and you'll
|
||||
need to speak [JSON-RPC](https://www.jsonrpc.org/specification) on all transports. You
|
||||
can reuse the same connection for multiple requests!
|
||||
|
||||
**Note: Please understand the security implications of opening up an HTTP/WS based
|
||||
transport before doing so! Hackers on the internet are actively trying to subvert
|
||||
Ethereum nodes with exposed APIs! Further, all browser tabs can access locally
|
||||
running web servers, so malicious web pages could try to subvert locally available
|
||||
APIs!**
|
||||
|
||||
### Operating a private network
|
||||
|
||||
Maintaining your own private network is more involved as a lot of configurations taken for
|
||||
granted in the official networks need to be manually set up.
|
||||
|
||||
#### Defining the private genesis state
|
||||
|
||||
First, you'll need to create the genesis state of your networks, which all nodes need to be
|
||||
aware of and agree upon. This consists of a small JSON file (e.g. call it `genesis.json`):
|
||||
|
||||
```json
|
||||
{
|
||||
"config": {
|
||||
"chainId": <arbitrary positive integer>,
|
||||
"homesteadBlock": 0,
|
||||
"eip150Block": 0,
|
||||
"eip155Block": 0,
|
||||
"eip158Block": 0,
|
||||
"byzantiumBlock": 0,
|
||||
"constantinopleBlock": 0,
|
||||
"petersburgBlock": 0,
|
||||
"istanbulBlock": 0,
|
||||
"berlinBlock": 0,
|
||||
"londonBlock": 0
|
||||
},
|
||||
"alloc": {},
|
||||
"coinbase": "0x0000000000000000000000000000000000000000",
|
||||
"difficulty": "0x20000",
|
||||
"extraData": "",
|
||||
"gasLimit": "0x2fefd8",
|
||||
"nonce": "0x0000000000000042",
|
||||
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"timestamp": "0x00"
|
||||
}
|
||||
```
|
||||
|
||||
The above fields should be fine for most purposes, although we'd recommend changing
|
||||
the `nonce` to some random value so you prevent unknown remote nodes from being able
|
||||
to connect to you. If you'd like to pre-fund some accounts for easier testing, create
|
||||
the accounts and populate the `alloc` field with their addresses.
|
||||
|
||||
```json
|
||||
"alloc": {
|
||||
"0x0000000000000000000000000000000000000001": {
|
||||
"balance": "111111111"
|
||||
},
|
||||
"0x0000000000000000000000000000000000000002": {
|
||||
"balance": "222222222"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
With the genesis state defined in the above JSON file, you'll need to initialize **every**
|
||||
`geth` node with it prior to starting it up to ensure all blockchain parameters are correctly
|
||||
set:
|
||||
|
||||
```shell
|
||||
$ geth init path/to/genesis.json
|
||||
```
|
||||
|
||||
#### Creating the rendezvous point
|
||||
|
||||
With all nodes that you want to run initialized to the desired genesis state, you'll need to
|
||||
start a bootstrap node that others can use to find each other in your network and/or over
|
||||
the internet. The clean way is to configure and run a dedicated bootnode:
|
||||
|
||||
```shell
|
||||
$ bootnode --genkey=boot.key
|
||||
$ bootnode --nodekey=boot.key
|
||||
```
|
||||
|
||||
With the bootnode online, it will display an [`enode` URL](https://ethereum.org/en/developers/docs/networking-layer/network-addresses/#enode)
|
||||
that other nodes can use to connect to it and exchange peer information. Make sure to
|
||||
replace the displayed IP address information (most probably `[::]`) with your externally
|
||||
accessible IP to get the actual `enode` URL.
|
||||
|
||||
*Note: You could also use a full-fledged `geth` node as a bootnode, but it's the less
|
||||
recommended way.*
|
||||
|
||||
#### Starting up your member nodes
|
||||
|
||||
With the bootnode operational and externally reachable (you can try
|
||||
`telnet <ip> <port>` to ensure it's indeed reachable), start every subsequent `geth`
|
||||
node pointed to the bootnode for peer discovery via the `--bootnodes` flag. It will
|
||||
probably also be desirable to keep the data directory of your private network separated, so
|
||||
do also specify a custom `--datadir` flag.
|
||||
|
||||
```shell
|
||||
$ geth --datadir=path/to/custom/data/folder --bootnodes=<bootnode-enode-url-from-above>
|
||||
```
|
||||
|
||||
*Note: Since your network will be completely cut off from the main and test networks, you'll
|
||||
also need to configure a miner to process transactions and create new blocks for you.*
|
||||
|
||||
#### Running a private miner
|
||||
|
||||
|
||||
In a private network setting a single CPU miner instance is more than enough for
|
||||
practical purposes as it can produce a stable stream of blocks at the correct intervals
|
||||
without needing heavy resources (consider running on a single thread, no need for multiple
|
||||
ones either). To start a `geth` instance for mining, run it with all your usual flags, extended
|
||||
by:
|
||||
|
||||
```shell
|
||||
$ geth <usual-flags> --mine --miner.threads=1 --miner.etherbase=0x0000000000000000000000000000000000000000
|
||||
```
|
||||
|
||||
Which will start mining blocks and transactions on a single CPU thread, crediting all
|
||||
proceedings to the account specified by `--miner.etherbase`. You can further tune the mining
|
||||
by changing the default gas limit blocks converge to (`--miner.targetgaslimit`) and the price
|
||||
transactions are accepted at (`--miner.gasprice`).
|
||||
|
||||
## Contribution
|
||||
|
||||
Thank you for considering helping out with the source code! We welcome contributions
|
||||
from anyone on the internet, and are grateful for even the smallest of fixes!
|
||||
|
||||
If you'd like to contribute to go-ethereum, please fork, fix, commit and send a pull request
|
||||
for the maintainers to review and merge into the main code base. If you wish to submit
|
||||
more complex changes though, please check up with the core devs first on [our Discord Server](https://discord.gg/invite/nthXNEv)
|
||||
to ensure those changes are in line with the general philosophy of the project and/or get
|
||||
some early feedback which can make both your efforts much lighter as well as our review
|
||||
and merge procedures quick and simple.
|
||||
|
||||
Please make sure your contributions adhere to our coding guidelines:
|
||||
|
||||
* Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting)
|
||||
guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
* Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary)
|
||||
guidelines.
|
||||
* Pull requests need to be based on and opened against the `master` branch.
|
||||
* Commit messages should be prefixed with the package(s) they modify.
|
||||
* E.g. "eth, rpc: make trace configs optional"
|
||||
|
||||
Please see the [Developers' Guide](https://geth.ethereum.org/docs/developers/geth-developer/dev-guide)
|
||||
for more details on configuring your environment, managing project dependencies, and
|
||||
testing procedures.
|
||||
|
||||
### Contributing to geth.ethereum.org
|
||||
|
||||
For contributions to the [go-ethereum website](https://geth.ethereum.org), please checkout and raise pull requests against the `website` branch.
|
||||
For more detailed instructions please see the `website` branch [README](https://github.com/ethereum/go-ethereum/tree/website#readme) or the
|
||||
[contributing](https://geth.ethereum.org/docs/developers/geth-developer/contributing) page of the website.
|
||||
|
||||
## License
|
||||
|
||||
The go-ethereum library (i.e. all code outside of the `cmd` directory) is licensed under the
|
||||
[GNU Lesser General Public License v3.0](https://www.gnu.org/licenses/lgpl-3.0.en.html),
|
||||
also included in our repository in the `COPYING.LESSER` file.
|
||||
|
||||
The go-ethereum binaries (i.e. all code inside of the `cmd` directory) are licensed under the
|
||||
[GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html), also
|
||||
included in our repository in the `COPYING` file.
|
||||
|
172
SECURITY.md
172
SECURITY.md
@ -1,175 +1,9 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Please see [Releases](https://github.com/ethereum/go-ethereum/releases). We recommend using the [most recently released version](https://github.com/ethereum/go-ethereum/releases/latest).
|
||||
|
||||
## Audit reports
|
||||
Please see [Releases](https://github.com/openrelayxyz/plugeth/releases) for notes on each release. We recommend using the most recently released version.
|
||||
|
||||
Audit reports are published in the `docs` folder: https://github.com/ethereum/go-ethereum/tree/master/docs/audits
|
||||
To report security issues in the underlying Geth code code please see Geth's security policy [here](https://github.com/ethereum/go-ethereum/security/policy).
|
||||
|
||||
| Scope | Date | Report Link |
|
||||
| ------- | ------- | ----------- |
|
||||
| `geth` | 20170425 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2017-04-25_Geth-audit_Truesec.pdf) |
|
||||
| `clef` | 20180914 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2018-09-14_Clef-audit_NCC.pdf) |
|
||||
| `Discv5` | 20191015 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2019-10-15_Discv5_audit_LeastAuthority.pdf) |
|
||||
| `Discv5` | 20200124 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2020-01-24_DiscV5_audit_Cure53.pdf) |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
**Please do not file a public ticket** mentioning the vulnerability.
|
||||
|
||||
To find out how to disclose a vulnerability in Ethereum visit [https://bounty.ethereum.org](https://bounty.ethereum.org) or email bounty@ethereum.org. Please read the [disclosure page](https://github.com/ethereum/go-ethereum/security/advisories?state=published) for more information about publicly disclosed security vulnerabilities.
|
||||
|
||||
Use the built-in `geth version-check` feature to check whether the software is affected by any known vulnerability. This command will fetch the latest [`vulnerabilities.json`](https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities.json) file which contains known security vulnerabilities concerning `geth`, and cross-check the data against its own version number.
|
||||
|
||||
The following key may be used to communicate sensitive information to developers.
|
||||
|
||||
Fingerprint: `AE96 ED96 9E47 9B00 84F3 E17F E88D 3334 FA5F 6A0A`
|
||||
|
||||
```
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: SKS 1.1.6
|
||||
Comment: Hostname: pgp.mit.edu
|
||||
|
||||
mQINBFgl3tgBEAC8A1tUBkD9YV+eLrOmtgy+/JS/H9RoZvkg3K1WZ8IYfj6iIRaYneAk3Bp1
|
||||
82GUPVz/zhKr2g0tMXIScDR3EnaDsY+Qg+JqQl8NOG+Cikr1nnkG2on9L8c8yiqry1ZTCmYM
|
||||
qCa2acTFqnyuXJ482aZNtB4QG2BpzfhW4k8YThpegk/EoRUim+y7buJDtoNf7YILlhDQXN8q
|
||||
lHB02DWOVUihph9tUIFsPK6BvTr9SIr/eG6j6k0bfUo9pexOn7LS4SojoJmsm/5dp6AoKlac
|
||||
48cZU5zwR9AYcq/nvkrfmf2WkObg/xRdEvKZzn05jRopmAIwmoC3CiLmqCHPmT5a29vEob/y
|
||||
PFE335k+ujjZCPOu7OwjzDk7M0zMSfnNfDq8bXh16nn+ueBxJ0NzgD1oC6c2PhM+XRQCXCho
|
||||
yI8vbfp4dGvCvYqvQAE1bWjqnumZ/7vUPgZN6gDfiAzG2mUxC2SeFBhacgzDvtQls+uuvm+F
|
||||
nQOUgg2Hh8x2zgoZ7kqV29wjaUPFREuew7e+Th5BxielnzOfVycVXeSuvvIn6cd3g/s8mX1c
|
||||
2kLSXJR7+KdWDrIrR5Az0kwAqFZt6B6QTlDrPswu3mxsm5TzMbny0PsbL/HBM+GZEZCjMXxB
|
||||
8bqV2eSaktjnSlUNX1VXxyOxXA+ZG2jwpr51egi57riVRXokrQARAQABtDRFdGhlcmV1bSBG
|
||||
b3VuZGF0aW9uIEJ1ZyBCb3VudHkgPGJvdW50eUBldGhlcmV1bS5vcmc+iQIcBBEBCAAGBQJa
|
||||
FCY6AAoJEHoMA3Q0/nfveH8P+gJBPo9BXZL8isUfbUWjwLi81Yi70hZqIJUnz64SWTqBzg5b
|
||||
mCZ69Ji5637THsxQetS2ARabz0DybQ779FhD/IWnqV9T3KuBM/9RzJtuhLzKCyMrAINPMo28
|
||||
rKWdunHHarpuR4m3tL2zWJkle5QVYb+vkZXJJE98PJw+N4IYeKKeCs2ubeqZu636GA0sMzzB
|
||||
Jn3m/dRRA2va+/zzbr6F6b51ynzbMxWKTsJnstjC8gs8EeI+Zcd6otSyelLtCUkk3h5sTvpV
|
||||
Wv67BNSU0BYsMkxyFi9PUyy07Wixgeas89K5jG1oOtDva/FkpRHrTE/WA5OXDRcLrHJM+SwD
|
||||
CwqcLQqJd09NxwUW1iKeBmPptTiOGu1Gv2o7aEyoaWrHRBO7JuYrQrj6q2B3H1Je0zjAd2qt
|
||||
09ni2bLwLn4LA+VDpprNTO+eZDprv09s2oFSU6NwziHybovu0y7X4pADGkK2evOM7c86PohX
|
||||
QRQ1M1T16xLj6wP8/Ykwl6v/LUk7iDPXP3GPILnh4YOkwBR3DsCOPn8098xy7FxEELmupRzt
|
||||
Cj9oC7YAoweeShgUjBPzb+nGY1m6OcFfbUPBgFyMMfwF6joHbiVIO+39+Ut2g2ysZa7KF+yp
|
||||
XqVDqyEkYXsOLb25OC7brt8IJEPgBPwcHK5GNag6RfLxnQV+iVZ9KNH1yQgSiQI+BBMBAgAo
|
||||
AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAUCWglh+gUJBaNgWAAKCRDojTM0+l9qCgQ2
|
||||
D/4udJpV4zGIZW1yNaVvtd3vfKsTLi7GIRJLUBqVb2Yx/uhnN8jTl/tAhCVosCQ1pzvi9kMl
|
||||
s8qO1vu2kw5EWFFkwK96roI8pTql3VIjwhRVQrCkR7oAk/eUd1U/nt2q6J4UTYeVgqbq4dsI
|
||||
ZZTRyPJMD667YpuAIcaah+w9j/E5xksYQdMeprnDrQkkBCb4FIMqfDzBPKvEa8DcQr949K85
|
||||
kxhr6LDq9i5l4Egxt2JdH8DaR4GLca6+oHy0MyPs/bZOsfmZUObfM2oZgPpqYM96JanhzO1j
|
||||
dpnItyBii2pc+kNx5nMOf4eikE/MBv+WUJ0TttWzApGGmFUzDhtuEvRH9NBjtJ/pMrYspIGu
|
||||
O/QNY5KKOKQTvVIlwGcm8dTsSkqtBDSUwZyWbfKfKOI1/RhM9dC3gj5/BOY57DYYV4rdTK01
|
||||
ZtYjuhdfs2bhuP1uF/cgnSSZlv8azvf7Egh7tHPnYxvLjfq1bJAhCIX0hNg0a81/ndPAEFky
|
||||
fSko+JPKvdSvsUcSi2QQ4U2HX//jNBjXRfG4F0utgbJnhXzEckz6gqt7wSDZH2oddVuO8Ssc
|
||||
T7sK+CdXthSKnRyuI+sGUpG+6glpKWIfYkWFKNZWuQ+YUatY3QEDHXTIioycSmV8p4d/g/0S
|
||||
V6TegidLxY8bXMkbqz+3n6FArRffv5MH7qt3cYkCPgQTAQIAKAUCWCXhOwIbAwUJAeEzgAYL
|
||||
CQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ6I0zNPpfagrN/w/+Igp3vtYdNunikw3yHnYf
|
||||
Jkm0MmaMDUM9mtsaXVN6xb9n25N3Xa3GWCpmdsbYZ8334tI/oQ4/NHq/bEI5WFH5F1aFkMkm
|
||||
5AJVLuUkipCtmCZ5NkbRPJA9l0uNUUE6uuFXBhf4ddu7jb0jMetRF/kifJHVCCo5fISUNhLp
|
||||
7bwcWq9qgDQNZNYMOo4s9WX5Tl+5x4gTZdd2/cAYt49h/wnkw+huM+Jm0GojpLqIQ1jZiffm
|
||||
otf5rF4L+JhIIdW0W4IIh1v9BhHVllXw+z9oj0PALstT5h8/DuKoIiirFJ4DejU85GR1KKAS
|
||||
DeO19G/lSpWj1rSgFv2N2gAOxq0X+BbQTua2jdcY6JpHR4H1JJ2wzfHsHPgDQcgY1rGlmjVF
|
||||
aqU73WV4/hzXc/HshK/k4Zd8uD4zypv6rFsZ3UemK0aL2zXLVpV8SPWQ61nS03x675SmDlYr
|
||||
A80ENfdqvsn00JQuBVIv4Tv0Ub7NfDraDGJCst8rObjBT/0vnBWTBCebb2EsnS2iStIFkWdz
|
||||
/WXs4L4Yzre1iJwqRjiuqahZR5jHsjAUf2a0O29HVHE7zlFtCFmLPClml2lGQfQOpm5klGZF
|
||||
rmvus+qZ9rt35UgWHPZezykkwtWrFOwspwuCWaPDto6tgbRJZ4ftitpdYYM3dKW9IGJXBwrt
|
||||
BQrMsu+lp0vDF+yJAlUEEwEIAD8CGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAFiEErpbt
|
||||
lp5HmwCE8+F/6I0zNPpfagoFAmEAEJwFCQycmLgACgkQ6I0zNPpfagpWoBAAhOcbMAUw6Zt0
|
||||
GYzT3sR5/c0iatezPzXEXJf9ebzR8M5uPElXcxcnMx1dvXZmGPXPJKCPa99WCu1NZYy8F+Wj
|
||||
GTOY9tfIkvSxhys1p/giPAmvid6uQmD+bz7ivktnyzCkDWfMA+l8lsCSEqVlaq6y5T+a6SWB
|
||||
6TzC2S0MPb/RrC/7DpwyrNYWumvyVJh09adm1Mw/UGgst/sZ8eMaRYEd3X0yyT1CBpX4zp2E
|
||||
qQj9IEOTizvzv1x2jkHe5ZUeU3+nTBNlhSA+WFHUi0pfBdo2qog3Mv2EC1P2qMKoSdD5tPbA
|
||||
zql1yKoHHnXOMsqdftGwbiv2sYXWvrYvmaCd3Ys/viOyt3HOy9uV2ZEtBd9Yqo9x/NZj8QMA
|
||||
nY5k8jjrIXbUC89MqrJsQ6xxWQIg5ikMT7DvY0Ln89ev4oJyVvwIQAwCm4jUzFNm9bZLYDOP
|
||||
5lGJCV7tF5NYVU7NxNM8vescKc40mVNK/pygS5mxhK9QYOUjZsIv8gddrl1TkqrFMuxFnTyN
|
||||
WvzE29wFu/n4N1DkF+ZBqS70SlRvB+Hjz5LrDgEzF1Wf1eA/wq1dZbvMjjDVIc2VGlYp8Cp2
|
||||
8ob23c1seTtYXTNYgSR5go4EpH+xi+bIWv01bQQ9xGwBbT5sm4WUeWOcmX4QewzLZ3T/wK9+
|
||||
N4Ye/hmU9O34FwWJOY58EIe0OUV0aGVyZXVtIEZvdW5kYXRpb24gU2VjdXJpdHkgVGVhbSA8
|
||||
c2VjdXJpdHlAZXRoZXJldW0ub3JnPokCHAQRAQgABgUCWhQmOgAKCRB6DAN0NP5372LSEACT
|
||||
wZk1TASWZj5QF7rmkIM1GEyBxLE+PundNcMgM9Ktj1315ED8SmiukNI4knVS1MY99OIgXhQl
|
||||
D1foF2GKdTomrwwC4012zTNyUYCY60LnPZ6Z511HG+rZgZtZrbkz0IiUpwAlhGQND77lBqem
|
||||
J3K+CFX2XpDA/ojui/kqrY4cwMT5P8xPJkwgpRgw/jgdcZyJTsXdHblV9IGU4H1Vd1SgcfAf
|
||||
Db3YxDUlBtzlp0NkZqxen8irLIXUQvsfuIfRUbUSkWoK/n3U/gOCajAe8ZNF07iX4OWjH4Sw
|
||||
NDA841WhFWcGE+d8+pfMVfPASU3UPKH72uw86b2VgR46Av6voyMFd1pj+yCA+YAhJuOpV4yL
|
||||
QaGg2Z0kVOjuNWK/kBzp1F58DWGh4YBatbhE/UyQOqAAtR7lNf0M3QF9AdrHTxX8oZeqVW3V
|
||||
Fmi2mk0NwCIUv8SSrZr1dTchp04OtyXe5gZBXSfzncCSRQIUDC8OgNWaOzAaUmK299v4bvye
|
||||
uSCxOysxC7Q1hZtjzFPKdljS81mRlYeUL4fHlJU9R57bg8mriSXLmn7eKrSEDm/EG5T8nRx7
|
||||
TgX2MqJs8sWFxD2+bboVEu75yuFmZ//nmCBApAit9Hr2/sCshGIEpa9MQ6xJCYUxyqeJH+Cc
|
||||
Aja0UfXhnK2uvPClpJLIl4RE3gm4OXeE1IkCPgQTAQIAKAIbAwYLCQgHAwIGFQgCCQoLBBYC
|
||||
AwECHgECF4AFAloJYfoFCQWjYFgACgkQ6I0zNPpfagr4MQ//cfp3GSbSG8dkqgctW67Fy7cQ
|
||||
diiTmx3cwxY+tlI3yrNmdjtrIQMzGdqtY6LNz7aN87F8mXNf+DyVHX9+wd1Y8U+E+hVCTzKC
|
||||
sefUfxTz6unD9TTcGqaoelgIPMn4IiKz1RZE6eKpfDWe6q78W1Y6x1bE0qGNSjqT/QSxpezF
|
||||
E/OAm/t8RRxVxDtqz8LfH2zLea5zaC+ADj8EqgY9vX9TQa4DyVV8MgOyECCCadJQCD5O5hIA
|
||||
B2gVDWwrAUw+KBwskXZ7Iq4reJTKLEmt5z9zgtJ/fABwaCFt66ojwg0/RjbO9cNA3ZwHLGwU
|
||||
C6hkb6bRzIoZoMfYxVS84opiqf/Teq+t/XkBYCxbSXTJDA5MKjcVuw3N6YKWbkGP/EfQThe7
|
||||
BfAKFwwIw5YmsWjHK8IQj6R6hBxzTz9rz8y1Lu8EAAFfA7OJKaboI2qbOlauH98OuOUmVtr1
|
||||
TczHO+pTcgWVN0ytq2/pX5KBf4vbmULNbg3HFRq+gHx8CW+jyXGkcqjbgU/5FwtDxeqRTdGJ
|
||||
SyBGNBEU6pBNolyynyaKaaJjJ/biY27pvjymL5rlz95BH3Dn16Z4RRmqwlT6eq/wFYginujg
|
||||
CCE1icqOSE+Vjl7V8tV8AcgANkXKdbBE+Q8wlKsGI/kS1w4XFAYcaNHFT8qNeS8TSFXFhvU8
|
||||
HylYxO79t56JAj4EEwECACgFAlgl3tgCGwMFCQHhM4AGCwkIBwMCBhUIAgkKCwQWAgMBAh4B
|
||||
AheAAAoJEOiNMzT6X2oKmUMP/0hnaL6bVyepAq2LIdvIUbHfagt/Oo/KVfZs4bkM+xJOitJR
|
||||
0kwZV9PTihXFdzhL/YNWc2+LtEBtKItqkJZKmWC0E6OPXGVuU6hfFPebuzVccYJfm0Q3Ej19
|
||||
VJI9Uomf59Bpak8HYyEED7WVQjoYn7XVPsonwus/9+LDX+c5vutbrUdbjga3KjHbewD93X4O
|
||||
wVVoXyHEmU2Plyg8qvzFbNDylCWO7N2McO6SN6+7DitGZGr2+jO+P2R4RT1cnl2V3IRVcWZ0
|
||||
OTspPSnRGVr2fFiHN/+v8G/wHPLQcJZFvYPfUGNdcYbTmhWdiY0bEYXFiNrgzCCsyad7eKUR
|
||||
WN9QmxqmyqLDjUEDJCAh19ES6Vg3tqGwXk+uNUCoF30ga0TxQt6UXZJDEQFAGeASQ/RqE/q1
|
||||
EAuLv8IGM8o7IqKO2pWfLuqsY6dTbKBwDzz9YOJt7EOGuPPQbHxaYStTushZmJnm7hi8lhVG
|
||||
jT7qsEJdE95Il+I/mHWnXsCevaXjZugBiyV9yvOq4Hwwe2s1zKfrnQ4u0cadvGAh2eIqum7M
|
||||
Y3o6nD47aJ3YmEPX/WnhI56bACa2GmWvUwjI4c0/er3esSPYnuHnM9L8Am4qQwMVSmyU80tC
|
||||
MI7A9e13Mvv+RRkYFLJ7PVPdNpbW5jqX1doklFpKf6/XM+B+ngYneU+zgCUBiQJVBBMBCAA/
|
||||
AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgBYhBK6W7ZaeR5sAhPPhf+iNMzT6X2oKBQJh
|
||||
ABCQBQkMnJi4AAoJEOiNMzT6X2oKAv0P+gJ3twBp5efNWyVLcIg4h4cOo9uD0NPvz8/fm2gX
|
||||
FoOJL3MeigtPuSVfE9kuTaTuRbArzuFtdvH6G/kcRQvOlO4zyiIRHCk1gDHoIvvtn6RbRhVm
|
||||
/Xo4uGIsFHst7n4A7BjicwEK5Op6Ih5Hoq19xz83YSBgBVk2fYEJIRyJiKFbyPjH0eSYe8v+
|
||||
Ra5/F85ugLx1P6mMVkW+WPzULns89riW7BGTnZmXFHZp8nO2pkUlcI7F3KRG7l4kmlC50ox6
|
||||
DiG/6AJCVulbAClky9C68TmJ/R1RazQxU/9IqVywsydq66tbJQbm5Z7GEti0C5jjbSRJL2oT
|
||||
1xC7Rilr85PMREkPL3vegJdgj5PKlffZ/MocD/0EohiQ7wFpejFD4iTljeh0exRUwCRb6655
|
||||
9ib34JSQgU8Hl4JJu+mEgd9v0ZHD0/1mMD6fnAR84zca+O3cdASbnQmzTOKcGzLIrkE8TEnU
|
||||
+2UZ8Ol7SAAqmBgzY1gKOilUho6dkyCAwNL+QDpvrITDPLEFPsjyB/M2KudZSVEn+Rletju1
|
||||
qkMW31qFMNlsbwzMZw+0USeGcs31Cs0B2/WQsro99CExlhS9auUFkmoVjJmYVTIYOM0zuPa4
|
||||
OyGspqPhRu5hEsmMDPDWD7Aad5k4GTqogQNnuKyRliZjXXrDZqFD5nfsJSL8Ky/sJGEMuQIN
|
||||
BFgl3tgBEACbgq6HTN5gEBi0lkD/MafInmNi+59U5gRGYqk46WlfRjhHudXjDpgD0lolGb4h
|
||||
YontkMaKRlCg2Rvgjvk3Zve0PKWjKw7gr8YBa9fMFY8BhAXI32OdyI9rFhxEZFfWAfwKVmT1
|
||||
9BdeAQRFvcfd+8w8f1XVc+zddULMJFBTr+xKDlIRWwTkdLPQeWbjo0eHl/g4tuLiLrTxVbnj
|
||||
26bf+2+1DbM/w5VavzPrkviHqvKe/QP/gay4QDViWvFgLb90idfAHIdsPgflp0VDS5rVHFL6
|
||||
D73rSRdIRo3I8c8mYoNjSR4XDuvgOkAKW9LR3pvouFHHjp6Fr0GesRbrbb2EG66iPsR99MQ7
|
||||
FqIL9VMHPm2mtR+XvbnKkH2rYyEqaMbSdk29jGapkAWle4sIhSKk749A4tGkHl08KZ2N9o6G
|
||||
rfUehP/V2eJLaph2DioFL1HxRryrKy80QQKLMJRekxigq8greW8xB4zuf9Mkuou+RHNmo8Pe
|
||||
bHjFstLigiD6/zP2e+4tUmrT0/JTGOShoGMl8Rt0VRxdPImKun+4LOXbfOxArOSkY6i35+gs
|
||||
gkkSy1gTJE0BY3S9auT6+YrglY/TWPQ9IJxWVOKlT+3WIp5wJu2bBKQ420VLqDYzkoWytel/
|
||||
bM1ACUtipMiIVeUs2uFiRjpzA1Wy0QHKPTdSuGlJPRrfcQARAQABiQIlBBgBAgAPAhsMBQJa
|
||||
CWIIBQkFo2BYAAoJEOiNMzT6X2oKgSwQAKKs7BGF8TyZeIEO2EUK7R2bdQDCdSGZY06tqLFg
|
||||
3IHMGxDMb/7FVoa2AEsFgv6xpoebxBB5zkhUk7lslgxvKiSLYjxfNjTBltfiFJ+eQnf+OTs8
|
||||
KeR51lLa66rvIH2qUzkNDCCTF45H4wIDpV05AXhBjKYkrDCrtey1rQyFp5fxI+0IQ1UKKXvz
|
||||
ZK4GdxhxDbOUSd38MYy93nqcmclGSGK/gF8XiyuVjeifDCM6+T1NQTX0K9lneidcqtBDvlgg
|
||||
JTLJtQPO33o5EHzXSiud+dKth1uUhZOFEaYRZoye1YE3yB0TNOOE8fXlvu8iuIAMBSDL9ep6
|
||||
sEIaXYwoD60I2gHdWD0lkP0DOjGQpi4ouXM3Edsd5MTi0MDRNTij431kn8T/D0LCgmoUmYYM
|
||||
BgbwFhXr67axPZlKjrqR0z3F/Elv0ZPPcVg1tNznsALYQ9Ovl6b5M3cJ5GapbbvNWC7yEE1q
|
||||
Scl9HiMxjt/H6aPastH63/7wcN0TslW+zRBy05VNJvpWGStQXcngsSUeJtI1Gd992YNjUJq4
|
||||
/Lih6Z1TlwcFVap+cTcDptoUvXYGg/9mRNNPZwErSfIJ0Ibnx9wPVuRN6NiCLOt2mtKp2F1p
|
||||
M6AOQPpZ85vEh6I8i6OaO0w/Z0UHBwvpY6jDUliaROsWUQsqz78Z34CVj4cy6vPW2EF4iQIl
|
||||
BBgBAgAPBQJYJd7YAhsMBQkB4TOAAAoJEOiNMzT6X2oKTjgP/1ojCVyGyvHMLUgnX0zwrR5Q
|
||||
1M5RKFz6kHwKjODVLR3Isp8I935oTQt3DY7yFDI4t0GqbYRQMtxcNEb7maianhK2trCXfhPs
|
||||
6/L04igjDf5iTcmzamXN6xnh5xkz06hZJJCMuu4MvKxC9MQHCVKAwjswl/9H9JqIBXAY3E2l
|
||||
LpX5P+5jDZuPxS86p3+k4Rrdp9KTGXjiuEleM3zGlz5BLWydqovOck7C2aKh27ETFpDYY0z3
|
||||
yQ5AsPJyk1rAr0wrH6+ywmwWlzuQewavnrLnJ2M8iMFXpIhyHeEIU/f7o8f+dQk72rZ9CGzd
|
||||
cqig2za/BS3zawZWgbv2vB2elNsIllYLdir45jxBOxx2yvJvEuu4glz78y4oJTCTAYAbMlle
|
||||
5gVdPkVcGyvvVS9tinnSaiIzuvWrYHKWll1uYPm2Q1CDs06P5I7bUGAXpgQLUh/XQguy/0sX
|
||||
GWqW3FS5JzP+XgcR/7UASvwBdHylubKbeqEpB7G1s+m+8C67qOrc7EQv3Jmy1YDOkhEyNig1
|
||||
rmjplLuir3tC1X+D7dHpn7NJe7nMwFx2b2MpMkLA9jPPAGPp/ekcu5sxCe+E0J/4UF++K+CR
|
||||
XIxgtzU2UJfp8p9x+ygbx5qHinR0tVRdIzv3ZnGsXrfxnWfSOaB582cU3VRN9INzHHax8ETa
|
||||
QVDnGO5uQa+FiQI8BBgBCAAmAhsMFiEErpbtlp5HmwCE8+F/6I0zNPpfagoFAmEAELYFCQyc
|
||||
mN4ACgkQ6I0zNPpfagoqAQ/+MnDjBx8JWMd/XjeFoYKx/Oo0ntkInV+ME61JTBls4PdVk+TB
|
||||
8PWZdPQHw9SnTvRmykFeznXIRzuxkowjrZYXdPXBxY2b1WyD5V3Ati1TM9vqpaR4osyPs2xy
|
||||
I4dzDssh9YvUsIRL99O04/65lGiYeBNuACq+yK/7nD/ErzBkDYJHhMCdadbVWUACxvVIDvro
|
||||
yQeVLKMsHqMCd8BTGD7VDs79NXskPnN77pAFnkzS4Z2b8SNzrlgTc5pUiuZHIXPIpEYmsYzh
|
||||
ucTU6uI3dN1PbSFHK5tG2pHb4ZrPxY3L20Dgc2Tfu5/SDApZzwvvKTqjdO891MEJ++H+ssOz
|
||||
i4O1UeWKs9owWttan9+PI47ozBSKOTxmMqLSQ0f56Np9FJsV0ilGxRKfjhzJ4KniOMUBA7mP
|
||||
+m+TmXfVtthJred4sHlJMTJNpt+sCcT6wLMmyc3keIEAu33gsJj3LTpkEA2q+V+ZiP6Q8HRB
|
||||
402ITklABSArrPSE/fQU9L8hZ5qmy0Z96z0iyILgVMLuRCCfQOMWhwl8yQWIIaf1yPI07xur
|
||||
epy6lH7HmxjjOR7eo0DaSxQGQpThAtFGwkWkFh8yki8j3E42kkrxvEyyYZDXn2YcI3bpqhJx
|
||||
PtwCMZUJ3kc/skOrs6bOI19iBNaEoNX5Dllm7UHjOgWNDQkcCuOCxucKano=
|
||||
=arte
|
||||
-----END PGP PUBLIC KEY BLOCK------
|
||||
```
|
||||
To report PluGeth specific issues please email [security@rivet.cloud](mailto:security@rivet.cloud).
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
|
152
cmd/geth/dao_test.go
Normal file
152
cmd/geth/dao_test.go
Normal file
@ -0,0 +1,152 @@
|
||||
// Copyright 2016 The go-ethereum Authors
|
||||
// This file is part of go-ethereum.
|
||||
//
|
||||
// go-ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// go-ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
// Genesis block for nodes which don't care about the DAO fork (i.e. not configured)
|
||||
var daoOldGenesis = `{
|
||||
"alloc" : {},
|
||||
"coinbase" : "0x0000000000000000000000000000000000000000",
|
||||
"difficulty" : "0x20000",
|
||||
"extraData" : "",
|
||||
"gasLimit" : "0x2fefd8",
|
||||
"nonce" : "0x0000000000000042",
|
||||
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"timestamp" : "0x00",
|
||||
"config" : {
|
||||
"homesteadBlock" : 0
|
||||
}
|
||||
}`
|
||||
|
||||
// Genesis block for nodes which actively oppose the DAO fork
|
||||
var daoNoForkGenesis = `{
|
||||
"alloc" : {},
|
||||
"coinbase" : "0x0000000000000000000000000000000000000000",
|
||||
"difficulty" : "0x20000",
|
||||
"extraData" : "",
|
||||
"gasLimit" : "0x2fefd8",
|
||||
"nonce" : "0x0000000000000042",
|
||||
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"timestamp" : "0x00",
|
||||
"config" : {
|
||||
"homesteadBlock" : 0,
|
||||
"daoForkBlock" : 314,
|
||||
"daoForkSupport" : false
|
||||
}
|
||||
}`
|
||||
|
||||
// Genesis block for nodes which actively support the DAO fork
|
||||
var daoProForkGenesis = `{
|
||||
"alloc" : {},
|
||||
"coinbase" : "0x0000000000000000000000000000000000000000",
|
||||
"difficulty" : "0x20000",
|
||||
"extraData" : "",
|
||||
"gasLimit" : "0x2fefd8",
|
||||
"nonce" : "0x0000000000000042",
|
||||
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"timestamp" : "0x00",
|
||||
"config" : {
|
||||
"homesteadBlock" : 0,
|
||||
"daoForkBlock" : 314,
|
||||
"daoForkSupport" : true
|
||||
}
|
||||
}`
|
||||
|
||||
var daoGenesisHash = common.HexToHash("5e1fc79cb4ffa4739177b5408045cd5d51c6cf766133f23f7cd72ee1f8d790e0")
|
||||
var daoGenesisForkBlock = big.NewInt(314)
|
||||
|
||||
// TestDAOForkBlockNewChain tests that the DAO hard-fork number and the nodes support/opposition is correctly
|
||||
// set in the database after various initialization procedures and invocations.
|
||||
func TestDAOForkBlockNewChain(t *testing.T) {
|
||||
for i, arg := range []struct {
|
||||
genesis string
|
||||
expectBlock *big.Int
|
||||
expectVote bool
|
||||
}{
|
||||
// Test DAO Default Mainnet
|
||||
{"", params.MainnetChainConfig.DAOForkBlock, true},
|
||||
// test DAO Init Old Privnet
|
||||
{daoOldGenesis, nil, false},
|
||||
// test DAO Default No Fork Privnet
|
||||
{daoNoForkGenesis, daoGenesisForkBlock, false},
|
||||
// test DAO Default Pro Fork Privnet
|
||||
{daoProForkGenesis, daoGenesisForkBlock, true},
|
||||
} {
|
||||
testDAOForkBlockNewChain(t, i, arg.genesis, arg.expectBlock, arg.expectVote)
|
||||
}
|
||||
}
|
||||
|
||||
func testDAOForkBlockNewChain(t *testing.T, test int, genesis string, expectBlock *big.Int, expectVote bool) {
|
||||
// Create a temporary data directory to use and inspect later
|
||||
datadir := t.TempDir()
|
||||
|
||||
// Start a Geth instance with the requested flags set and immediately terminate
|
||||
if genesis != "" {
|
||||
json := filepath.Join(datadir, "genesis.json")
|
||||
if err := os.WriteFile(json, []byte(genesis), 0600); err != nil {
|
||||
t.Fatalf("test %d: failed to write genesis file: %v", test, err)
|
||||
}
|
||||
runGeth(t, "--datadir", datadir, "--networkid", "1337", "init", json).WaitExit()
|
||||
} else {
|
||||
// Force chain initialization
|
||||
args := []string{"--port", "0", "--networkid", "1337", "--maxpeers", "0", "--nodiscover", "--nat", "none", "--ipcdisable", "--datadir", datadir}
|
||||
runGeth(t, append(args, []string{"--exec", "2+2", "console"}...)...).WaitExit()
|
||||
}
|
||||
// Retrieve the DAO config flag from the database
|
||||
path := filepath.Join(datadir, "geth", "chaindata")
|
||||
db, err := rawdb.NewLevelDBDatabase(path, 0, 0, "", false)
|
||||
if err != nil {
|
||||
t.Fatalf("test %d: failed to open test database: %v", test, err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
genesisHash := common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
|
||||
if genesis != "" {
|
||||
genesisHash = daoGenesisHash
|
||||
}
|
||||
config := rawdb.ReadChainConfig(db, genesisHash)
|
||||
if config == nil {
|
||||
t.Errorf("test %d: failed to retrieve chain config: %v", test, err)
|
||||
return // we want to return here, the other checks can't make it past this point (nil panic).
|
||||
}
|
||||
// Validate the DAO hard-fork block number against the expected value
|
||||
if config.DAOForkBlock == nil {
|
||||
if expectBlock != nil {
|
||||
t.Errorf("test %d: dao hard-fork block mismatch: have nil, want %v", test, expectBlock)
|
||||
}
|
||||
} else if expectBlock == nil {
|
||||
t.Errorf("test %d: dao hard-fork block mismatch: have %v, want nil", test, config.DAOForkBlock)
|
||||
} else if config.DAOForkBlock.Cmp(expectBlock) != 0 {
|
||||
t.Errorf("test %d: dao hard-fork block mismatch: have %v, want %v", test, config.DAOForkBlock, expectBlock)
|
||||
}
|
||||
if config.DAOForkSupport != expectVote {
|
||||
t.Errorf("test %d: dao hard-fork support mismatch: have %v, want %v", test, config.DAOForkSupport, expectVote)
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
205
cmd/geth/les_test.go
Normal file
205
cmd/geth/les_test.go
Normal file
@ -0,0 +1,205 @@
|
||||
// Copyright 2020 The go-ethereum Authors
|
||||
// This file is part of go-ethereum.
|
||||
//
|
||||
// go-ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// go-ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
type gethrpc struct {
|
||||
name string
|
||||
rpc *rpc.Client
|
||||
geth *testgeth
|
||||
nodeInfo *p2p.NodeInfo
|
||||
}
|
||||
|
||||
func (g *gethrpc) killAndWait() {
|
||||
g.geth.Kill()
|
||||
g.geth.WaitExit()
|
||||
}
|
||||
|
||||
func (g *gethrpc) callRPC(result interface{}, method string, args ...interface{}) {
|
||||
if err := g.rpc.Call(&result, method, args...); err != nil {
|
||||
g.geth.Fatalf("callRPC %v: %v", method, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *gethrpc) addPeer(peer *gethrpc) {
|
||||
g.geth.Logf("%v.addPeer(%v)", g.name, peer.name)
|
||||
enode := peer.getNodeInfo().Enode
|
||||
peerCh := make(chan *p2p.PeerEvent)
|
||||
sub, err := g.rpc.Subscribe(context.Background(), "admin", peerCh, "peerEvents")
|
||||
if err != nil {
|
||||
g.geth.Fatalf("subscribe %v: %v", g.name, err)
|
||||
}
|
||||
defer sub.Unsubscribe()
|
||||
g.callRPC(nil, "admin_addPeer", enode)
|
||||
dur := 14 * time.Second
|
||||
timeout := time.After(dur)
|
||||
select {
|
||||
case ev := <-peerCh:
|
||||
g.geth.Logf("%v received event: type=%v, peer=%v", g.name, ev.Type, ev.Peer)
|
||||
case err := <-sub.Err():
|
||||
g.geth.Fatalf("%v sub error: %v", g.name, err)
|
||||
case <-timeout:
|
||||
g.geth.Error("timeout adding peer after", dur)
|
||||
}
|
||||
}
|
||||
|
||||
// Use this function instead of `g.nodeInfo` directly
|
||||
func (g *gethrpc) getNodeInfo() *p2p.NodeInfo {
|
||||
if g.nodeInfo != nil {
|
||||
return g.nodeInfo
|
||||
}
|
||||
g.nodeInfo = &p2p.NodeInfo{}
|
||||
g.callRPC(&g.nodeInfo, "admin_nodeInfo")
|
||||
return g.nodeInfo
|
||||
}
|
||||
|
||||
// ipcEndpoint resolves an IPC endpoint based on a configured value, taking into
|
||||
// account the set data folders as well as the designated platform we're currently
|
||||
// running on.
|
||||
func ipcEndpoint(ipcPath, datadir string) string {
|
||||
// On windows we can only use plain top-level pipes
|
||||
if runtime.GOOS == "windows" {
|
||||
if strings.HasPrefix(ipcPath, `\\.\pipe\`) {
|
||||
return ipcPath
|
||||
}
|
||||
return `\\.\pipe\` + ipcPath
|
||||
}
|
||||
// Resolve names into the data directory full paths otherwise
|
||||
if filepath.Base(ipcPath) == ipcPath {
|
||||
if datadir == "" {
|
||||
return filepath.Join(os.TempDir(), ipcPath)
|
||||
}
|
||||
return filepath.Join(datadir, ipcPath)
|
||||
}
|
||||
return ipcPath
|
||||
}
|
||||
|
||||
// nextIPC ensures that each ipc pipe gets a unique name.
|
||||
// On linux, it works well to use ipc pipes all over the filesystem (in datadirs),
|
||||
// but windows require pipes to sit in "\\.\pipe\". Therefore, to run several
|
||||
// nodes simultaneously, we need to distinguish between them, which we do by
|
||||
// the pipe filename instead of folder.
|
||||
var nextIPC = uint32(0)
|
||||
|
||||
func startGethWithIpc(t *testing.T, name string, args ...string) *gethrpc {
|
||||
ipcName := fmt.Sprintf("geth-%d.ipc", atomic.AddUint32(&nextIPC, 1))
|
||||
args = append([]string{"--networkid=42", "--port=0", "--authrpc.port", "0", "--ipcpath", ipcName}, args...)
|
||||
t.Logf("Starting %v with rpc: %v", name, args)
|
||||
|
||||
g := &gethrpc{
|
||||
name: name,
|
||||
geth: runGeth(t, args...),
|
||||
}
|
||||
ipcpath := ipcEndpoint(ipcName, g.geth.Datadir)
|
||||
// We can't know exactly how long geth will take to start, so we try 10
|
||||
// times over a 5 second period.
|
||||
var err error
|
||||
for i := 0; i < 10; i++ {
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
if g.rpc, err = rpc.Dial(ipcpath); err == nil {
|
||||
return g
|
||||
}
|
||||
}
|
||||
t.Fatalf("%v rpc connect to %v: %v", name, ipcpath, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
// func initGeth(t *testing.T) string {
|
||||
// args := []string{"--networkid=42", "init", "./testdata/clique.json"}
|
||||
// t.Logf("Initializing geth: %v ", args)
|
||||
// g := runGeth(t, args...)
|
||||
// datadir := g.Datadir
|
||||
// g.WaitExit()
|
||||
// return datadir
|
||||
// }
|
||||
|
||||
func startLightServer(t *testing.T) *gethrpc {
|
||||
datadir := initGeth(t)
|
||||
t.Logf("Importing keys to geth")
|
||||
runGeth(t, "account", "import", "--datadir", datadir, "--password", "./testdata/password.txt", "--lightkdf", "./testdata/key.prv").WaitExit()
|
||||
account := "0x02f0d131f1f97aef08aec6e3291b957d9efe7105"
|
||||
server := startGethWithIpc(t, "lightserver", "--allow-insecure-unlock", "--datadir", datadir, "--password", "./testdata/password.txt", "--unlock", account, "--miner.etherbase=0x02f0d131f1f97aef08aec6e3291b957d9efe7105", "--mine", "--light.serve=100", "--light.maxpeers=1", "--nodiscover", "--nat=extip:127.0.0.1", "--verbosity=4")
|
||||
return server
|
||||
}
|
||||
|
||||
func startClient(t *testing.T, name string) *gethrpc {
|
||||
datadir := initGeth(t)
|
||||
return startGethWithIpc(t, name, "--datadir", datadir, "--nodiscover", "--syncmode=light", "--nat=extip:127.0.0.1", "--verbosity=4")
|
||||
}
|
||||
|
||||
func TestPriorityClient(t *testing.T) {
|
||||
lightServer := startLightServer(t)
|
||||
defer lightServer.killAndWait()
|
||||
|
||||
// Start client and add lightServer as peer
|
||||
freeCli := startClient(t, "freeCli")
|
||||
defer freeCli.killAndWait()
|
||||
freeCli.addPeer(lightServer)
|
||||
|
||||
var peers []*p2p.PeerInfo
|
||||
freeCli.callRPC(&peers, "admin_peers")
|
||||
if len(peers) != 1 {
|
||||
t.Errorf("Expected: # of client peers == 1, actual: %v", len(peers))
|
||||
return
|
||||
}
|
||||
|
||||
// Set up priority client, get its nodeID, increase its balance on the lightServer
|
||||
prioCli := startClient(t, "prioCli")
|
||||
defer prioCli.killAndWait()
|
||||
// 3_000_000_000 once we move to Go 1.13
|
||||
tokens := uint64(3000000000)
|
||||
lightServer.callRPC(nil, "les_addBalance", prioCli.getNodeInfo().ID, tokens)
|
||||
prioCli.addPeer(lightServer)
|
||||
|
||||
// Check if priority client is actually syncing and the regular client got kicked out
|
||||
prioCli.callRPC(&peers, "admin_peers")
|
||||
if len(peers) != 1 {
|
||||
t.Errorf("Expected: # of prio peers == 1, actual: %v", len(peers))
|
||||
}
|
||||
|
||||
nodes := map[string]*gethrpc{
|
||||
lightServer.getNodeInfo().ID: lightServer,
|
||||
freeCli.getNodeInfo().ID: freeCli,
|
||||
prioCli.getNodeInfo().ID: prioCli,
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
lightServer.callRPC(&peers, "admin_peers")
|
||||
peersWithNames := make(map[string]string)
|
||||
for _, p := range peers {
|
||||
peersWithNames[nodes[p.ID].name] = p.ID
|
||||
}
|
||||
if _, freeClientFound := peersWithNames[freeCli.name]; freeClientFound {
|
||||
t.Error("client is still a peer of lightServer", peersWithNames)
|
||||
}
|
||||
if _, prioClientFound := peersWithNames[prioCli.name]; !prioClientFound {
|
||||
t.Error("prio client is not among lightServer peers", peersWithNames)
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
|
@ -16,7 +16,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
@ -16,7 +16,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import "github.com/urfave/cli/v2"
|
||||
|
||||
|
@ -14,12 +14,13 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// geth is a command-line client for Ethereum.
|
||||
package main
|
||||
// geth is the official command-line client for Ethereum.
|
||||
package geth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -41,6 +42,9 @@ import (
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"go.uber.org/automaxprocs/maxprocs"
|
||||
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
"github.com/ethereum/go-ethereum/plugins/wrappers/backendwrapper"
|
||||
|
||||
// Force-load the tracer engines to trigger registration
|
||||
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
|
||||
_ "github.com/ethereum/go-ethereum/eth/tracers/native"
|
||||
@ -55,6 +59,9 @@ const (
|
||||
var (
|
||||
// flags that configure the node
|
||||
nodeFlags = flags.Merge([]cli.Flag{
|
||||
//begin PluGeth code injection
|
||||
utils.PluginsDirFlag,
|
||||
//end PluGeth code injection
|
||||
utils.IdentityFlag,
|
||||
utils.UnlockedAccountFlag,
|
||||
utils.PasswordFileFlag,
|
||||
@ -266,7 +273,10 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// FIXME workaround https://github.com/golang/go/issues/31354 by wrapping main
|
||||
func main() { Main() }
|
||||
|
||||
func Main() {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
@ -332,15 +342,38 @@ func prepare(ctx *cli.Context) {
|
||||
// It creates a default node based on the command line arguments and runs it in
|
||||
// blocking mode, waiting for it to be shut down.
|
||||
func geth(ctx *cli.Context) error {
|
||||
if args := ctx.Args().Slice(); len(args) > 0 {
|
||||
return fmt.Errorf("invalid command: %q", args[0])
|
||||
//begin PluGeth code injection
|
||||
var pluginsDir string
|
||||
if ctx.IsSet(utils.PluginsDirFlag.Name) {
|
||||
pluginsDir = ctx.String(utils.PluginsDirFlag.Name)
|
||||
} else {
|
||||
pluginsDir = filepath.Join(ctx.String(utils.DataDirFlag.Name), "plugins")
|
||||
}
|
||||
|
||||
if err := plugins.Initialize(pluginsDir, ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
prepare(ctx)
|
||||
stack, backend := makeFullNode(ctx)
|
||||
defer stack.Close()
|
||||
if !plugins.ParseFlags(ctx.Args().Slice()) {
|
||||
if args := ctx.Args().Slice(); len(args) > 0 {
|
||||
return fmt.Errorf("invalid command: %q", args[0])
|
||||
}
|
||||
}
|
||||
|
||||
stack, backend := makeFullNode(ctx)
|
||||
wrapperBackend := backendwrapper.NewBackend(backend)
|
||||
|
||||
pluginsInitializeNode(stack, wrapperBackend)
|
||||
if ok, err := plugins.RunSubcommand(ctx); ok {
|
||||
stack.Close()
|
||||
return err
|
||||
}
|
||||
defer stack.Close()
|
||||
defer pluginsOnShutdown()
|
||||
stack.RegisterAPIs(pluginGetAPIs(stack, wrapperBackend))
|
||||
startNode(ctx, stack, backend, false)
|
||||
pluginBlockChain()
|
||||
//end PluGeth code injection
|
||||
stack.Wait()
|
||||
return nil
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
124
cmd/geth/plugin_hooks.go
Normal file
124
cmd/geth/plugin_hooks.go
Normal file
@ -0,0 +1,124 @@
|
||||
package geth
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
"github.com/ethereum/go-ethereum/plugins/wrappers"
|
||||
|
||||
"github.com/openrelayxyz/plugeth-utils/core"
|
||||
"github.com/openrelayxyz/plugeth-utils/restricted"
|
||||
)
|
||||
|
||||
func apiTranslate(apis []core.API) []rpc.API {
|
||||
result := make([]rpc.API, len(apis))
|
||||
for i, api := range apis {
|
||||
result[i] = rpc.API{
|
||||
Namespace: api.Namespace,
|
||||
Version: api.Version,
|
||||
Service: api.Service,
|
||||
Public: api.Public,
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func GetAPIsFromLoader(pl *plugins.PluginLoader, stack *node.Node, backend restricted.Backend) []rpc.API {
|
||||
result := []core.API{}
|
||||
fnList := pl.Lookup("GetAPIs", func(item interface{}) bool {
|
||||
switch item.(type) {
|
||||
case func(core.Node, restricted.Backend) []core.API:
|
||||
return true
|
||||
case func(core.Node, core.Backend) []core.API:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
switch fn := fni.(type) {
|
||||
case func(core.Node, restricted.Backend) []core.API:
|
||||
result = append(result, fn(wrappers.NewNode(stack), backend)...)
|
||||
case func(core.Node, core.Backend) []core.API:
|
||||
result = append(result, fn(wrappers.NewNode(stack), backend)...)
|
||||
default:
|
||||
}
|
||||
}
|
||||
return apiTranslate(result)
|
||||
}
|
||||
|
||||
func pluginGetAPIs(stack *node.Node, backend restricted.Backend) []rpc.API {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting GetAPIs, but default PluginLoader has not been initialized")
|
||||
return []rpc.API{}
|
||||
}
|
||||
return GetAPIsFromLoader(plugins.DefaultPluginLoader, stack, backend)
|
||||
}
|
||||
|
||||
func InitializeNode(pl *plugins.PluginLoader, stack *node.Node, backend restricted.Backend) {
|
||||
fnList := pl.Lookup("InitializeNode", func(item interface{}) bool {
|
||||
switch item.(type) {
|
||||
case func(core.Node, restricted.Backend):
|
||||
return true
|
||||
case func(core.Node, core.Backend):
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
switch fn := fni.(type) {
|
||||
case func(core.Node, restricted.Backend):
|
||||
fn(wrappers.NewNode(stack), backend)
|
||||
case func(core.Node, core.Backend):
|
||||
fn(wrappers.NewNode(stack), backend)
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func pluginsInitializeNode(stack *node.Node, backend restricted.Backend) {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting InitializeNode, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
InitializeNode(plugins.DefaultPluginLoader, stack, backend)
|
||||
}
|
||||
|
||||
func OnShutdown(pl *plugins.PluginLoader) {
|
||||
fnList := pl.Lookup("OnShutdown", func(item interface{}) bool {
|
||||
_, ok := item.(func())
|
||||
return ok
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
fni.(func())()
|
||||
}
|
||||
}
|
||||
|
||||
func pluginsOnShutdown() {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting OnShutdown, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
OnShutdown(plugins.DefaultPluginLoader)
|
||||
}
|
||||
|
||||
func BlockChain(pl *plugins.PluginLoader) {
|
||||
fnList := pl.Lookup("BlockChain", func(item interface{}) bool {
|
||||
_, ok := item.(func())
|
||||
return ok
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
fni.(func())()
|
||||
}
|
||||
}
|
||||
|
||||
func pluginBlockChain() {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting BlockChain, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
BlockChain(plugins.DefaultPluginLoader)
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package geth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
@ -86,6 +86,14 @@ import (
|
||||
|
||||
var (
|
||||
// General settings
|
||||
//begin PluGeth code injection
|
||||
PluginsDirFlag = &flags.DirectoryFlag{
|
||||
Name: "pluginsdir",
|
||||
Usage: "Directory for plugins",
|
||||
Value: flags.DirectoryString(filepath.Join("<datadir>", "plugins")),
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
//end PluGeth code injection
|
||||
DataDirFlag = &flags.DirectoryFlag{
|
||||
Name: "datadir",
|
||||
Usage: "Data directory for the databases and keystore",
|
||||
@ -994,7 +1002,12 @@ func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
|
||||
// 4. default to mainnet nodes
|
||||
func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
|
||||
urls := params.MainnetBootnodes
|
||||
if ctx.IsSet(BootnodesFlag.Name) {
|
||||
// begin PluGeth injection
|
||||
if pluginUrls := pluginSetBootstrapNodes(); pluginUrls != nil {
|
||||
urls = pluginUrls
|
||||
}
|
||||
// end PluGeth injection
|
||||
if ctx.IsSet(BootnodesFlag.Name) {
|
||||
urls = SplitAndTrim(ctx.String(BootnodesFlag.Name))
|
||||
} else {
|
||||
if cfg.BootstrapNodes != nil {
|
||||
@ -1423,7 +1436,13 @@ func setSmartCard(ctx *cli.Context, cfg *node.Config) {
|
||||
}
|
||||
|
||||
func SetDataDir(ctx *cli.Context, cfg *node.Config) {
|
||||
// begin PluGeth injection
|
||||
pluginPath := pluginDefaultDataDir(node.DefaultDataDir())
|
||||
switch {
|
||||
case pluginPath != "" && ctx.String(DataDirFlag.Name) == node.DefaultDataDir():
|
||||
log.Error("Inside datdir injection number two")
|
||||
cfg.DataDir = pluginPath
|
||||
// end PluGeth injection
|
||||
case ctx.IsSet(DataDirFlag.Name):
|
||||
cfg.DataDir = ctx.String(DataDirFlag.Name)
|
||||
case ctx.Bool(DeveloperFlag.Name):
|
||||
@ -1596,6 +1615,20 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||
setRequiredBlocks(ctx, cfg)
|
||||
setLes(ctx, cfg)
|
||||
|
||||
// beginPluGethInjection
|
||||
if pluginNetworkId := pluginNetworkId(); pluginNetworkId != nil {
|
||||
cfg.NetworkId = *pluginNetworkId
|
||||
}
|
||||
if cfg.EthDiscoveryURLs == nil {
|
||||
var lightMode bool
|
||||
if cfg.SyncMode == downloader.LightSync {
|
||||
lightMode = true
|
||||
}
|
||||
cfg.EthDiscoveryURLs = pluginETHDiscoveryURLs(lightMode)
|
||||
cfg.SnapDiscoveryURLs = pluginSnapDiscoveryURLs()
|
||||
}
|
||||
//end PluGeth injection
|
||||
|
||||
// Cap the cache allowance and tune the garbage collector
|
||||
mem, err := gopsutil.VirtualMemory()
|
||||
if err == nil {
|
||||
@ -1834,6 +1867,16 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||
SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash)
|
||||
}
|
||||
}
|
||||
|
||||
//begin plugeth injection
|
||||
if genesis := pluginGenesisBlock(); genesis != nil {
|
||||
chaindb := MakeChainDatabase(ctx, stack, false)
|
||||
cfg.Genesis = genesis
|
||||
rawdb.WriteChainConfig(chaindb, genesis.ToBlock().Hash(), genesis.Config)
|
||||
chaindb.Close()
|
||||
}
|
||||
//end plugeth injection
|
||||
|
||||
// Set any dangling config values
|
||||
if ctx.String(CryptoKZGFlag.Name) != "gokzg" && ctx.String(CryptoKZGFlag.Name) != "ckzg" {
|
||||
Fatalf("--%s flag must be 'gokzg' or 'ckzg'", CryptoKZGFlag.Name)
|
||||
@ -2066,6 +2109,11 @@ func MakeGenesis(ctx *cli.Context) *core.Genesis {
|
||||
case ctx.Bool(DeveloperFlag.Name):
|
||||
Fatalf("Developer chains are ephemeral")
|
||||
}
|
||||
//begin plugeth injection
|
||||
if genesis == nil {
|
||||
genesis = pluginGenesisBlock()
|
||||
}
|
||||
//end plugeth injection
|
||||
return genesis
|
||||
}
|
||||
|
||||
|
139
cmd/utils/plugin_hooks.go
Normal file
139
cmd/utils/plugin_hooks.go
Normal file
@ -0,0 +1,139 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
)
|
||||
|
||||
func DefaultDataDir(pl *plugins.PluginLoader, path string) string {
|
||||
dataDirPath := ""
|
||||
fnList := pl.Lookup("SetDefaultDataDir", func(item interface{}) bool {
|
||||
_, ok := item.(func(string) string)
|
||||
return ok
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func(string) string); ok {
|
||||
dataDirPath = fn(path)
|
||||
}
|
||||
}
|
||||
return dataDirPath
|
||||
}
|
||||
|
||||
func pluginDefaultDataDir(path string) string {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting DefaultDataDir, but default PluginLoader has not been initialized")
|
||||
return ""
|
||||
}
|
||||
return DefaultDataDir(plugins.DefaultPluginLoader, path)
|
||||
}
|
||||
|
||||
func PluginSetBootStrapNodes(pl *plugins.PluginLoader) []string {
|
||||
var urls []string
|
||||
fnList := pl.Lookup("SetBootstrapNodes", func(item interface{}) bool {
|
||||
_, ok := item.(func() []string)
|
||||
return ok
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func() []string); ok {
|
||||
urls = fn()
|
||||
}
|
||||
}
|
||||
return urls
|
||||
}
|
||||
|
||||
func pluginSetBootstrapNodes() []string {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting pluginSetBootStrapNodes, but default PluginLoader has not been initialized")
|
||||
return nil
|
||||
}
|
||||
return PluginSetBootStrapNodes(plugins.DefaultPluginLoader)
|
||||
}
|
||||
|
||||
func PluginNetworkId(pl *plugins.PluginLoader) *uint64 {
|
||||
var networkId *uint64
|
||||
fnList := pl.Lookup("SetNetworkId", func(item interface{}) bool {
|
||||
_, ok := item.(func() *uint64)
|
||||
return ok
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func() *uint64); ok {
|
||||
networkId = fn()
|
||||
}
|
||||
}
|
||||
return networkId
|
||||
}
|
||||
|
||||
func pluginNetworkId() *uint64 {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting pluginNetworkID, but default PluginLoader has not been initialized")
|
||||
return nil
|
||||
}
|
||||
return PluginNetworkId(plugins.DefaultPluginLoader)
|
||||
}
|
||||
|
||||
func PluginETHDiscoveryURLs(pl *plugins.PluginLoader, mode bool) []string {
|
||||
var ethDiscoveryURLs []string
|
||||
fnList := pl.Lookup("SetETHDiscoveryURLs", func(item interface{}) bool {
|
||||
_, ok := item.(func(bool) []string)
|
||||
return ok
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func(bool) []string); ok {
|
||||
ethDiscoveryURLs = fn(mode)
|
||||
}
|
||||
}
|
||||
return ethDiscoveryURLs
|
||||
}
|
||||
|
||||
func pluginETHDiscoveryURLs(mode bool) []string {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting pluginETHDiscoveryURLs, but default PluginLoader has not been initialized")
|
||||
return nil
|
||||
}
|
||||
return PluginETHDiscoveryURLs(plugins.DefaultPluginLoader, mode)
|
||||
}
|
||||
|
||||
func PluginSnapDiscoveryURLs(pl *plugins.PluginLoader) []string {
|
||||
var snapDiscoveryURLs []string
|
||||
fnList := pl.Lookup("SetSnapDiscoveryURLs", func(item interface{}) bool {
|
||||
_, ok := item.(func() []string)
|
||||
return ok
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func() []string); ok {
|
||||
snapDiscoveryURLs = fn()
|
||||
}
|
||||
}
|
||||
return snapDiscoveryURLs
|
||||
}
|
||||
|
||||
func pluginSnapDiscoveryURLs() []string {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting PluginSnapDiscoveryURLs, but default PluginLoader has not been initialized")
|
||||
return nil
|
||||
}
|
||||
return PluginSnapDiscoveryURLs(plugins.DefaultPluginLoader)
|
||||
}
|
||||
|
||||
func PluginGenesisBlock(pl *plugins.PluginLoader) *core.Genesis {
|
||||
genesisJSON, ok := plugins.LookupOne[func() []byte](pl, "GenesisBlock")
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
var genesis core.Genesis
|
||||
if err := json.Unmarshal(genesisJSON(), &genesis); err != nil {
|
||||
log.Warn("Error unmarshalling genesis", "err", err)
|
||||
return nil
|
||||
}
|
||||
return &genesis
|
||||
}
|
||||
|
||||
func pluginGenesisBlock() *core.Genesis {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting PluginGenesisBlock, but default PluginLoader has not been initialized")
|
||||
return nil
|
||||
}
|
||||
return PluginGenesisBlock(plugins.DefaultPluginLoader)
|
||||
}
|
@ -34,7 +34,9 @@ import (
|
||||
func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Header) error {
|
||||
// Verify that the gas limit remains within allowed bounds
|
||||
parentGasLimit := parent.GasLimit
|
||||
if !config.IsLondon(parent.Number) {
|
||||
// begin PluGeth injection
|
||||
if !config.Is1559(parent.Number) {
|
||||
// end PluGeth injection
|
||||
parentGasLimit = parent.GasLimit * config.ElasticityMultiplier()
|
||||
}
|
||||
if err := misc.VerifyGaslimit(parentGasLimit, header.GasLimit); err != nil {
|
||||
@ -56,7 +58,9 @@ func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Heade
|
||||
// CalcBaseFee calculates the basefee of the header.
|
||||
func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
|
||||
// If the current block is the first EIP-1559 block, return the InitialBaseFee.
|
||||
if !config.IsLondon(parent.Number) {
|
||||
// begin PluGeth injection
|
||||
if !config.Is1559(parent.Number) {
|
||||
// end PluGeth injection
|
||||
return new(big.Int).SetUint64(params.InitialBaseFee)
|
||||
}
|
||||
|
||||
|
@ -1344,6 +1344,11 @@ func (bc *BlockChain) writeKnownBlock(block *types.Block) error {
|
||||
// writeBlockWithState writes block, metadata and corresponding state data to the
|
||||
// database.
|
||||
func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.Receipt, state *state.StateDB) error {
|
||||
//begin PluGeth injection
|
||||
var interval time.Duration
|
||||
_ = pluginSetTrieFlushIntervalClone(interval) // this is being called here to engage a testing scenario
|
||||
//end PluGeth injection
|
||||
|
||||
// Calculate the total difficulty of the block
|
||||
ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1)
|
||||
if ptd == nil {
|
||||
@ -1399,6 +1404,11 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||
chosen := current - TriesInMemory
|
||||
flushInterval := time.Duration(bc.flushInterval.Load())
|
||||
// If we exceeded time allowance, flush an entire trie to disk
|
||||
|
||||
// begin PluGeth code injection
|
||||
flushInterval = pluginSetTrieFlushIntervalClone(flushInterval)
|
||||
// end PluGeth code injection
|
||||
|
||||
if bc.gcproc > flushInterval {
|
||||
// If the header is missing (canonical chain behind), we're reorging a low
|
||||
// diff sidechain. Suspend committing until this operation is completed.
|
||||
@ -1468,7 +1478,17 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
|
||||
}
|
||||
bc.futureBlocks.Remove(block.Hash())
|
||||
|
||||
// ptd and externTd are both PluGeth injections
|
||||
ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1)
|
||||
if ptd == nil {
|
||||
return NonStatTy, consensus.ErrUnknownAncestor
|
||||
}
|
||||
// Make sure no inconsistent state is leaked during insertion
|
||||
externTd := new(big.Int).Add(block.Difficulty(), ptd)
|
||||
|
||||
if status == CanonStatTy {
|
||||
//begin PluGeth code injection
|
||||
pluginNewHead(block, block.Hash(), logs, externTd)
|
||||
bc.chainFeed.Send(ChainEvent{Block: block, Hash: block.Hash(), Logs: logs})
|
||||
if len(logs) > 0 {
|
||||
bc.logsFeed.Send(logs)
|
||||
@ -1482,8 +1502,10 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
|
||||
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
|
||||
}
|
||||
} else {
|
||||
pluginNewSideBlock(block, block.Hash(), logs)
|
||||
bc.chainSideFeed.Send(ChainSideEvent{Block: block})
|
||||
}
|
||||
// end PluGeth code injection
|
||||
}
|
||||
return status, nil
|
||||
}
|
||||
|
||||
@ -2173,6 +2195,9 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
|
||||
msg = "Large chain reorg detected"
|
||||
logFn = log.Warn
|
||||
}
|
||||
//begin PluGeth code injection
|
||||
pluginReorg(commonBlock, oldChain, newChain)
|
||||
//end PluGeth code injection
|
||||
logFn(msg, "number", commonBlock.Number(), "hash", commonBlock.Hash(),
|
||||
"drop", len(oldChain), "dropfrom", oldChain[0].Hash(), "add", len(newChain), "addfrom", newChain[0].Hash())
|
||||
blockReorgAddMeter.Mark(int64(len(newChain)))
|
||||
@ -2319,6 +2344,14 @@ func (bc *BlockChain) SetCanonical(head *types.Block) (common.Hash, error) {
|
||||
if len(logs) > 0 {
|
||||
bc.logsFeed.Send(logs)
|
||||
}
|
||||
// begin PluGeth code injection
|
||||
ptd := bc.GetTd(head.ParentHash(), head.NumberU64()-1)
|
||||
externTd := ptd
|
||||
if ptd != nil {
|
||||
externTd = new(big.Int).Add(head.Difficulty(), ptd)
|
||||
}
|
||||
pluginNewHead(head, head.Hash(), logs, externTd)
|
||||
// end PluGeth code injection
|
||||
bc.chainHeadFeed.Send(ChainHeadEvent{Block: head})
|
||||
|
||||
context := []interface{}{
|
||||
|
29
core/blockchain_hooks_test.go
Normal file
29
core/blockchain_hooks_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"math/big"
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
"github.com/openrelayxyz/plugeth-utils/core"
|
||||
)
|
||||
|
||||
func TestReorgLongHeadersHook(t *testing.T) {
|
||||
invoked := false
|
||||
done := plugins.HookTester("NewHead", func(b []byte, h core.Hash, logs [][]byte, td *big.Int) {
|
||||
invoked = true
|
||||
if b == nil {
|
||||
t.Errorf("Expected block to be non-nil")
|
||||
}
|
||||
if h == (core.Hash{}) {
|
||||
t.Errorf("Expected hash to be non-empty")
|
||||
}
|
||||
if len(logs) > 0 {
|
||||
t.Errorf("Expected some logs")
|
||||
}
|
||||
})
|
||||
defer done()
|
||||
testReorgLong(t, true, "")
|
||||
if !invoked {
|
||||
t.Errorf("Expected plugin invocation")
|
||||
}
|
||||
}
|
@ -240,6 +240,7 @@ func checksumToBytes(hash uint32) [4]byte {
|
||||
// gatherForks gathers all the known forks and creates two sorted lists out of
|
||||
// them, one for the block number based forks and the second for the timestamps.
|
||||
func gatherForks(config *params.ChainConfig, genesis uint64) ([]uint64, []uint64) {
|
||||
|
||||
// Gather all the fork block numbers via reflection
|
||||
kind := reflect.TypeOf(params.ChainConfig{})
|
||||
conf := reflect.ValueOf(config).Elem()
|
||||
@ -293,5 +294,10 @@ func gatherForks(config *params.ChainConfig, genesis uint64) ([]uint64, []uint64
|
||||
for len(forksByTime) > 0 && forksByTime[0] <= genesis {
|
||||
forksByTime = forksByTime[1:]
|
||||
}
|
||||
// begin PluGeth injection
|
||||
if byBlock, byTime, ok := pluginForkIDs(forksByBlock, forksByTime); ok {
|
||||
return byBlock, byTime
|
||||
}
|
||||
// end PluGeth injection
|
||||
return forksByBlock, forksByTime
|
||||
}
|
||||
|
25
core/forkid/plugin_hooks.go
Normal file
25
core/forkid/plugin_hooks.go
Normal file
@ -0,0 +1,25 @@
|
||||
package forkid
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
)
|
||||
|
||||
func PluginForkIDs(pl *plugins.PluginLoader, byBlock, byTime []uint64) ([]uint64, []uint64, bool) {
|
||||
f, ok := plugins.LookupOne[func([]uint64, []uint64) ([]uint64, []uint64)](pl, "ForkIDs")
|
||||
if !ok {
|
||||
return nil, nil, false
|
||||
}
|
||||
pluginByBlock, pluginByTime := f(byBlock, byTime)
|
||||
|
||||
return pluginByBlock, pluginByTime, ok
|
||||
|
||||
}
|
||||
|
||||
func pluginForkIDs(byBlock, byTime []uint64) ([]uint64, []uint64, bool) {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting PluginForkIDs, but default PluginLoader has not been initialized")
|
||||
return nil, nil, false
|
||||
}
|
||||
return PluginForkIDs(plugins.DefaultPluginLoader, byBlock, byTime)
|
||||
}
|
150
core/plugeth_injection_test.go
Normal file
150
core/plugeth_injection_test.go
Normal file
@ -0,0 +1,150 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"hash"
|
||||
"fmt"
|
||||
"testing"
|
||||
"math/big"
|
||||
"crypto/ecdsa"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
var (
|
||||
config = ¶ms.ChainConfig{
|
||||
ChainID: big.NewInt(1),
|
||||
HomesteadBlock: big.NewInt(0),
|
||||
EIP150Block: big.NewInt(0),
|
||||
EIP155Block: big.NewInt(0),
|
||||
EIP158Block: big.NewInt(0),
|
||||
ByzantiumBlock: big.NewInt(0),
|
||||
ConstantinopleBlock: big.NewInt(0),
|
||||
PetersburgBlock: big.NewInt(0),
|
||||
IstanbulBlock: big.NewInt(0),
|
||||
MuirGlacierBlock: big.NewInt(0),
|
||||
BerlinBlock: big.NewInt(0),
|
||||
LondonBlock: big.NewInt(0),
|
||||
Ethash: new(params.EthashConfig),
|
||||
}
|
||||
signer = types.LatestSigner(config)
|
||||
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
key2, _ = crypto.HexToECDSA("0202020202020202020202020202020202020202020202020202002020202020")
|
||||
)
|
||||
|
||||
var makeTx = func(key *ecdsa.PrivateKey, nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *types.Transaction {
|
||||
tx, _ := types.SignTx(types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data), signer, key)
|
||||
return tx
|
||||
}
|
||||
|
||||
var (
|
||||
db = rawdb.NewMemoryDatabase()
|
||||
gspec = &Genesis{
|
||||
Config: config,
|
||||
Alloc: GenesisAlloc{
|
||||
common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{
|
||||
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||
Nonce: 0,
|
||||
},
|
||||
common.HexToAddress("0xfd0810DD14796680f72adf1a371963d0745BCc64"): GenesisAccount{
|
||||
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||
Nonce: math.MaxUint64,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
type testHasher struct {
|
||||
hasher hash.Hash
|
||||
}
|
||||
|
||||
func newHasher() *testHasher {
|
||||
return &testHasher{hasher: sha3.NewLegacyKeccak256()}
|
||||
}
|
||||
|
||||
func (h *testHasher) Reset() {
|
||||
h.hasher.Reset()
|
||||
}
|
||||
|
||||
func (h *testHasher) Update(key, val []byte) {
|
||||
h.hasher.Write(key)
|
||||
h.hasher.Write(val)
|
||||
}
|
||||
|
||||
func (h *testHasher) Hash() common.Hash {
|
||||
return common.BytesToHash(h.hasher.Sum(nil))
|
||||
}
|
||||
|
||||
|
||||
func TestPlugethInjections(t *testing.T) {
|
||||
|
||||
|
||||
blockchain, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
|
||||
|
||||
engine := ethash.NewFaker()
|
||||
|
||||
sp := NewStateProcessor(config, blockchain, engine)
|
||||
|
||||
txns := []*types.Transaction{
|
||||
makeTx(key1, 0, common.Address{}, big.NewInt(1000), params.TxGas-1000, big.NewInt(875000000), nil),
|
||||
}
|
||||
|
||||
block := GenerateBadBlock(gspec.ToBlock(), engine, txns, gspec.Config)
|
||||
|
||||
statedb, _ := state.New(blockchain.GetBlockByHash(block.ParentHash()).Root(), blockchain.stateCache, nil)
|
||||
|
||||
t.Run(fmt.Sprintf("test BlockProcessingError"), func(t *testing.T) {
|
||||
called := false
|
||||
injectionCalled = &called
|
||||
metaInjectionCalled = &called
|
||||
|
||||
_, _, _, _ = sp.Process(block, statedb, vm.Config{})
|
||||
|
||||
if *injectionCalled != true {
|
||||
t.Fatalf("pluginBlockProcessingError injection in stateProcessor.Process() not called")
|
||||
}
|
||||
if *metaInjectionCalled != true {
|
||||
t.Fatalf("metaTracer.BlockProcessingError injection in stateProcessor.Process() not called")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run(fmt.Sprintf("test Reorg"), func(t *testing.T) {
|
||||
called := false
|
||||
injectionCalled = &called
|
||||
|
||||
// the transaction has to be initialized with a different gas price than the previous tx in order to trigger a reorg
|
||||
txns2 := []*types.Transaction{
|
||||
makeTx(key1, 0, common.Address{}, big.NewInt(1000), params.TxGas-1000, big.NewInt(875000001), nil),
|
||||
}
|
||||
block2 := GenerateBadBlock(gspec.ToBlock(), engine, txns2, gspec.Config)
|
||||
|
||||
|
||||
_, _ = blockchain.writeBlockAndSetHead(block, []*types.Receipt{}, []*types.Log{}, statedb, false)
|
||||
|
||||
_ = blockchain.reorg(block.Header(), block2)
|
||||
|
||||
if *injectionCalled != true {
|
||||
t.Fatalf("pluginReorg injection in blockChain.Reorg() not called")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run(fmt.Sprintf("test NewSideBlock"), func(t *testing.T) {
|
||||
called := false
|
||||
injectionCalled = &called
|
||||
|
||||
TestReorgToShorterRemovesCanonMapping(t)
|
||||
|
||||
if *injectionCalled != true {
|
||||
t.Fatalf("pluginNewSideBlock injection in blockChain.writeBlockAndSetHead() not called")
|
||||
}
|
||||
})
|
||||
|
||||
}
|
348
core/plugin_hooks.go
Normal file
348
core/plugin_hooks.go
Normal file
@ -0,0 +1,348 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"time"
|
||||
"sync"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
"github.com/ethereum/go-ethereum/plugins/wrappers"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/openrelayxyz/plugeth-utils/core"
|
||||
)
|
||||
|
||||
var injectionCalled *bool
|
||||
var metaInjectionCalled *bool
|
||||
|
||||
func PluginPreProcessBlock(pl *plugins.PluginLoader, block *types.Block) {
|
||||
fnList := pl.Lookup("PreProcessBlock", func(item interface{}) bool {
|
||||
_, ok := item.(func(core.Hash, uint64, []byte))
|
||||
return ok
|
||||
})
|
||||
encoded, _ := rlp.EncodeToBytes(block)
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func(core.Hash, uint64, []byte)); ok {
|
||||
fn(core.Hash(block.Hash()), block.NumberU64(), encoded)
|
||||
}
|
||||
}
|
||||
}
|
||||
func pluginPreProcessBlock(block *types.Block) {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting PreProcessBlock, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
PluginPreProcessBlock(plugins.DefaultPluginLoader, block) // TODO
|
||||
}
|
||||
func PluginPreProcessTransaction(pl *plugins.PluginLoader, tx *types.Transaction, block *types.Block, i int) {
|
||||
fnList := pl.Lookup("PreProcessTransaction", func(item interface{}) bool {
|
||||
_, ok := item.(func([]byte, core.Hash, core.Hash, int))
|
||||
return ok
|
||||
})
|
||||
txBytes, _ := tx.MarshalBinary()
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func([]byte, core.Hash, core.Hash, int)); ok {
|
||||
fn(txBytes, core.Hash(tx.Hash()), core.Hash(block.Hash()), i)
|
||||
}
|
||||
}
|
||||
}
|
||||
func pluginPreProcessTransaction(tx *types.Transaction, block *types.Block, i int) {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting PreProcessTransaction, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
PluginPreProcessTransaction(plugins.DefaultPluginLoader, tx, block, i)
|
||||
}
|
||||
func PluginBlockProcessingError(pl *plugins.PluginLoader, tx *types.Transaction, block *types.Block, err error) {
|
||||
fnList := pl.Lookup("BlockProcessingError", func(item interface{}) bool {
|
||||
_, ok := item.(func(core.Hash, core.Hash, error))
|
||||
return ok
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func(core.Hash, core.Hash, error)); ok {
|
||||
fn(core.Hash(tx.Hash()), core.Hash(block.Hash()), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
func pluginBlockProcessingError(tx *types.Transaction, block *types.Block, err error) {
|
||||
|
||||
if injectionCalled != nil {
|
||||
called := true
|
||||
injectionCalled = &called
|
||||
}
|
||||
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting BlockProcessingError, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
PluginBlockProcessingError(plugins.DefaultPluginLoader, tx, block, err)
|
||||
}
|
||||
func PluginPostProcessTransaction(pl *plugins.PluginLoader, tx *types.Transaction, block *types.Block, i int, receipt *types.Receipt) {
|
||||
fnList := pl.Lookup("PostProcessTransaction", func(item interface{}) bool {
|
||||
_, ok := item.(func(core.Hash, core.Hash, int, []byte))
|
||||
return ok
|
||||
})
|
||||
receiptBytes, _ := json.Marshal(receipt)
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func(core.Hash, core.Hash, int, []byte)); ok {
|
||||
fn(core.Hash(tx.Hash()), core.Hash(block.Hash()), i, receiptBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
func pluginPostProcessTransaction(tx *types.Transaction, block *types.Block, i int, receipt *types.Receipt) {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting PostProcessTransaction, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
PluginPostProcessTransaction(plugins.DefaultPluginLoader, tx, block, i, receipt)
|
||||
}
|
||||
func PluginPostProcessBlock(pl *plugins.PluginLoader, block *types.Block) {
|
||||
fnList := pl.Lookup("PostProcessBlock", func(item interface{}) bool {
|
||||
_, ok := item.(func(core.Hash))
|
||||
return ok
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func(core.Hash)); ok {
|
||||
fn(core.Hash(block.Hash()))
|
||||
}
|
||||
}
|
||||
}
|
||||
func pluginPostProcessBlock(block *types.Block) {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting PostProcessBlock, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
PluginPostProcessBlock(plugins.DefaultPluginLoader, block)
|
||||
}
|
||||
func PluginNewHead(pl *plugins.PluginLoader, block *types.Block, hash common.Hash, logs []*types.Log, td *big.Int) {
|
||||
fnList := pl.Lookup("NewHead", func(item interface{}) bool {
|
||||
_, ok := item.(func([]byte, core.Hash, [][]byte, *big.Int))
|
||||
return ok
|
||||
})
|
||||
blockBytes, _ := rlp.EncodeToBytes(block)
|
||||
logBytes := make([][]byte, len(logs))
|
||||
for i, l := range logs {
|
||||
logBytes[i], _ = rlp.EncodeToBytes(l)
|
||||
}
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func([]byte, core.Hash, [][]byte, *big.Int)); ok {
|
||||
fn(blockBytes, core.Hash(hash), logBytes, td)
|
||||
}
|
||||
}
|
||||
}
|
||||
func pluginNewHead(block *types.Block, hash common.Hash, logs []*types.Log, td *big.Int) {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting NewHead, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
PluginNewHead(plugins.DefaultPluginLoader, block, hash, logs, td)
|
||||
}
|
||||
|
||||
func PluginNewSideBlock(pl *plugins.PluginLoader, block *types.Block, hash common.Hash, logs []*types.Log) {
|
||||
fnList := pl.Lookup("NewSideBlock", func(item interface{}) bool {
|
||||
_, ok := item.(func([]byte, core.Hash, [][]byte))
|
||||
return ok
|
||||
})
|
||||
blockBytes, _ := rlp.EncodeToBytes(block)
|
||||
logBytes := make([][]byte, len(logs))
|
||||
for i, l := range logs {
|
||||
logBytes[i], _ = rlp.EncodeToBytes(l)
|
||||
}
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func([]byte, core.Hash, [][]byte)); ok {
|
||||
fn(blockBytes, core.Hash(hash), logBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
func pluginNewSideBlock(block *types.Block, hash common.Hash, logs []*types.Log) {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting NewSideBlock, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
PluginNewSideBlock(plugins.DefaultPluginLoader, block, hash, logs)
|
||||
}
|
||||
|
||||
func PluginReorg(pl *plugins.PluginLoader, commonBlock *types.Block, oldChain, newChain types.Blocks) {
|
||||
|
||||
fnList := pl.Lookup("Reorg", func(item interface{}) bool {
|
||||
_, ok := item.(func(core.Hash, []core.Hash, []core.Hash))
|
||||
return ok
|
||||
})
|
||||
oldChainHashes := make([]core.Hash, len(oldChain))
|
||||
for i, block := range oldChain {
|
||||
oldChainHashes[i] = core.Hash(block.Hash())
|
||||
}
|
||||
newChainHashes := make([]core.Hash, len(newChain))
|
||||
for i, block := range newChain {
|
||||
newChainHashes[i] = core.Hash(block.Hash())
|
||||
}
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func(core.Hash, []core.Hash, []core.Hash)); ok {
|
||||
fn(core.Hash(commonBlock.Hash()), oldChainHashes, newChainHashes)
|
||||
}
|
||||
}
|
||||
}
|
||||
func pluginReorg(commonBlock *types.Block, oldChain, newChain types.Blocks) {
|
||||
|
||||
if injectionCalled != nil {
|
||||
called := true
|
||||
injectionCalled = &called
|
||||
}
|
||||
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting Reorg, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
PluginReorg(plugins.DefaultPluginLoader, commonBlock, oldChain, newChain)
|
||||
}
|
||||
|
||||
type PreTracer interface {
|
||||
CapturePreStart(from common.Address, to *common.Address, input []byte, gas uint64, value *big.Int)
|
||||
|
||||
}
|
||||
|
||||
type metaTracer struct {
|
||||
tracers []core.BlockTracer
|
||||
}
|
||||
|
||||
func (mt *metaTracer) PreProcessBlock(block *types.Block) {
|
||||
if len(mt.tracers) == 0 { return }
|
||||
blockHash := core.Hash(block.Hash())
|
||||
blockNumber := block.NumberU64()
|
||||
encoded, _ := rlp.EncodeToBytes(block)
|
||||
for _, tracer := range mt.tracers {
|
||||
tracer.PreProcessBlock(blockHash, blockNumber, encoded)
|
||||
}
|
||||
}
|
||||
func (mt *metaTracer) PreProcessTransaction(tx *types.Transaction, block *types.Block, i int) {
|
||||
if len(mt.tracers) == 0 { return }
|
||||
blockHash := core.Hash(block.Hash())
|
||||
transactionHash := core.Hash(tx.Hash())
|
||||
for _, tracer := range mt.tracers {
|
||||
tracer.PreProcessTransaction(transactionHash, blockHash, i)
|
||||
}
|
||||
}
|
||||
func (mt *metaTracer) BlockProcessingError(tx *types.Transaction, block *types.Block, err error) {
|
||||
|
||||
if metaInjectionCalled != nil {
|
||||
called := true
|
||||
metaInjectionCalled = &called
|
||||
}
|
||||
|
||||
if len(mt.tracers) == 0 { return }
|
||||
blockHash := core.Hash(block.Hash())
|
||||
transactionHash := core.Hash(tx.Hash())
|
||||
for _, tracer := range mt.tracers {
|
||||
tracer.BlockProcessingError(transactionHash, blockHash, err)
|
||||
}
|
||||
}
|
||||
func (mt *metaTracer) PostProcessTransaction(tx *types.Transaction, block *types.Block, i int, receipt *types.Receipt) {
|
||||
if len(mt.tracers) == 0 { return }
|
||||
blockHash := core.Hash(block.Hash())
|
||||
transactionHash := core.Hash(tx.Hash())
|
||||
receiptBytes, _ := json.Marshal(receipt)
|
||||
for _, tracer := range mt.tracers {
|
||||
tracer.PostProcessTransaction(transactionHash, blockHash, i, receiptBytes)
|
||||
}
|
||||
}
|
||||
func (mt *metaTracer) PostProcessBlock(block *types.Block) {
|
||||
if len(mt.tracers) == 0 { return }
|
||||
blockHash := core.Hash(block.Hash())
|
||||
for _, tracer := range mt.tracers {
|
||||
tracer.PostProcessBlock(blockHash)
|
||||
}
|
||||
}
|
||||
func (mt *metaTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||
for _, tracer := range mt.tracers {
|
||||
tracer.CaptureStart(core.Address(from), core.Address(to), create, input, gas, value)
|
||||
}
|
||||
}
|
||||
func (mt *metaTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
|
||||
for _, tracer := range mt.tracers {
|
||||
tracer.CaptureState(pc, core.OpCode(op), gas, cost, wrappers.NewWrappedScopeContext(scope), rData, depth, err)
|
||||
}
|
||||
}
|
||||
func (mt *metaTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
|
||||
for _, tracer := range mt.tracers {
|
||||
tracer.CaptureFault(pc, core.OpCode(op), gas, cost, wrappers.NewWrappedScopeContext(scope), depth, err)
|
||||
}
|
||||
}
|
||||
// passing zero as a dummy value is foundation PluGeth only, it is being done to preserve compatability with other networks
|
||||
func (mt *metaTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
|
||||
for _, tracer := range mt.tracers {
|
||||
tracer.CaptureEnd(output, gasUsed, 0, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (mt *metaTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
||||
for _, tracer := range mt.tracers {
|
||||
tracer.CaptureEnter(core.OpCode(typ), core.Address(from), core.Address(to), input, gas, value)
|
||||
}
|
||||
}
|
||||
|
||||
func (mt *metaTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
|
||||
for _, tracer := range mt.tracers {
|
||||
tracer.CaptureExit(output, gasUsed, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (mt metaTracer) CaptureTxStart (gasLimit uint64) {}
|
||||
|
||||
func (mt metaTracer) CaptureTxEnd (restGas uint64) {}
|
||||
|
||||
func PluginGetBlockTracer(pl *plugins.PluginLoader, hash common.Hash, statedb *state.StateDB) (*metaTracer, bool) {
|
||||
//look for a function that takes whatever the ctx provides and statedb and returns a core.blocktracer append into meta tracer
|
||||
tracerList := plugins.Lookup("GetLiveTracer", func(item interface{}) bool {
|
||||
_, ok := item.(func(core.Hash, core.StateDB) core.BlockTracer)
|
||||
log.Info("Item is LiveTracer", "ok", ok, "type", reflect.TypeOf(item))
|
||||
return ok
|
||||
})
|
||||
mt := &metaTracer{tracers: []core.BlockTracer{}}
|
||||
for _, tracer := range tracerList {
|
||||
if v, ok := tracer.(func(core.Hash, core.StateDB) core.BlockTracer); ok {
|
||||
bt := v(core.Hash(hash), wrappers.NewWrappedStateDB(statedb))
|
||||
if bt != nil {
|
||||
mt.tracers = append(mt.tracers, bt)
|
||||
}
|
||||
}
|
||||
}
|
||||
return mt, (len(mt.tracers) > 0)
|
||||
}
|
||||
func pluginGetBlockTracer(hash common.Hash, statedb *state.StateDB) (*metaTracer, bool) {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting GetBlockTracer, but default PluginLoader has not been initialized")
|
||||
return &metaTracer{}, false
|
||||
}
|
||||
return PluginGetBlockTracer(plugins.DefaultPluginLoader, hash, statedb)
|
||||
}
|
||||
|
||||
func PluginSetTrieFlushIntervalClone(pl *plugins.PluginLoader, flushInterval time.Duration) time.Duration {
|
||||
fnList := pl.Lookup("SetTrieFlushIntervalClone", func(item interface{}) bool{
|
||||
_, ok := item.(func(time.Duration) time.Duration)
|
||||
return ok
|
||||
})
|
||||
var snc sync.Once
|
||||
if len(fnList) > 1 {
|
||||
snc.Do(func() {log.Warn("The blockChain flushInterval value is being accessed by multiple plugins")})
|
||||
}
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func(time.Duration) time.Duration); ok {
|
||||
flushInterval = fn(flushInterval)
|
||||
}
|
||||
}
|
||||
return flushInterval
|
||||
}
|
||||
|
||||
func pluginSetTrieFlushIntervalClone(flushInterval time.Duration) time.Duration {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting setTreiFlushIntervalClone, but default PluginLoader has not been initialized")
|
||||
return flushInterval
|
||||
}
|
||||
return PluginSetTrieFlushIntervalClone(plugins.DefaultPluginLoader, flushInterval)
|
||||
}
|
@ -274,6 +274,10 @@ func (f *Freezer) ModifyAncients(fn func(ethdb.AncientWriteOp) error) (writeSize
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
//begin PluGeth code injection
|
||||
pluginCommitUpdate(item)
|
||||
//end PluGeth code injection
|
||||
// atomic.StoreUint64(*f.frozen, item)
|
||||
f.frozen.Store(item)
|
||||
return writeSize, nil
|
||||
}
|
||||
|
@ -43,11 +43,17 @@ func newFreezerBatch(f *Freezer) *freezerBatch {
|
||||
|
||||
// Append adds an RLP-encoded item of the given kind.
|
||||
func (batch *freezerBatch) Append(kind string, num uint64, item interface{}) error {
|
||||
// begin PluGeth injection
|
||||
PluginTrackUpdate(num, kind, item)
|
||||
// end PluGeth injection
|
||||
return batch.tables[kind].Append(num, item)
|
||||
}
|
||||
|
||||
// AppendRaw adds an item of the given kind.
|
||||
func (batch *freezerBatch) AppendRaw(kind string, num uint64, item []byte) error {
|
||||
// being PluGeth injection
|
||||
PluginTrackUpdate(num, kind, item)
|
||||
// end PluGeth injection
|
||||
return batch.tables[kind].AppendRaw(num, item)
|
||||
}
|
||||
|
||||
|
@ -26,12 +26,18 @@ import (
|
||||
"path"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// seeding random below, as well as the time import are PluGeth injections to enable this test to pass as it fails in geth v1.11.1
|
||||
func init() {
|
||||
rand.Seed(time.Now().Unix())
|
||||
}
|
||||
|
||||
var freezerTestTableDef = map[string]bool{"test": true}
|
||||
|
||||
func TestFreezerModify(t *testing.T) {
|
||||
|
50
core/rawdb/plugeth_injection_test.go
Normal file
50
core/rawdb/plugeth_injection_test.go
Normal file
@ -0,0 +1,50 @@
|
||||
package rawdb
|
||||
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
)
|
||||
|
||||
|
||||
func TestPlugethInjections(t *testing.T) {
|
||||
var valuesRaw [][]byte
|
||||
var valuesRLP []*big.Int
|
||||
for x := 0; x < 100; x++ {
|
||||
v := getChunk(256, x)
|
||||
valuesRaw = append(valuesRaw, v)
|
||||
iv := big.NewInt(int64(x))
|
||||
iv = iv.Exp(iv, iv, nil)
|
||||
valuesRLP = append(valuesRLP, iv)
|
||||
}
|
||||
tables := map[string]bool{"raw": true, "rlp": false}
|
||||
f, _ := newFreezerForTesting(t, tables)
|
||||
|
||||
t.Run(fmt.Sprintf("test plugeth injections"), func(t *testing.T) {
|
||||
called := false
|
||||
modifyAncientsInjection = &called
|
||||
|
||||
_, _ = f.ModifyAncients(func(op ethdb.AncientWriteOp) error {
|
||||
|
||||
appendRawInjection = &called
|
||||
_ = op.AppendRaw("raw", uint64(0), valuesRaw[0])
|
||||
if *appendRawInjection != true {
|
||||
t.Fatalf("pluginTrackUpdate injection in AppendRaw not called")
|
||||
}
|
||||
|
||||
appendInjection = &called
|
||||
_ = op.Append("rlp", uint64(0), valuesRaw[0])
|
||||
if *appendInjection != true {
|
||||
t.Fatalf("pluginTrackUpdate injection in Append not called")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if *modifyAncientsInjection != true {
|
||||
t.Fatalf("pluginCommitUpdate injection in ModifyAncients not called")
|
||||
}
|
||||
})
|
||||
}
|
142
core/rawdb/plugin_hooks.go
Normal file
142
core/rawdb/plugin_hooks.go
Normal file
@ -0,0 +1,142 @@
|
||||
package rawdb
|
||||
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
var (
|
||||
freezerUpdates map[uint64]map[string]interface{}
|
||||
lock sync.Mutex
|
||||
modifyAncientsInjection *bool
|
||||
appendRawInjection *bool
|
||||
appendInjection *bool
|
||||
)
|
||||
|
||||
func PluginTrackUpdate(num uint64, kind string, value interface{}) {
|
||||
|
||||
if appendRawInjection != nil {
|
||||
called := true
|
||||
appendRawInjection = &called
|
||||
}
|
||||
|
||||
if appendInjection != nil {
|
||||
called := true
|
||||
appendInjection = &called
|
||||
}
|
||||
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
if freezerUpdates == nil { freezerUpdates = make(map[uint64]map[string]interface{}) }
|
||||
update, ok := freezerUpdates[num]
|
||||
if !ok {
|
||||
update = make(map[string]interface{})
|
||||
freezerUpdates[num] = update
|
||||
}
|
||||
update[kind] = value
|
||||
}
|
||||
|
||||
func pluginCommitUpdate(num uint64) {
|
||||
|
||||
if modifyAncientsInjection != nil {
|
||||
called := true
|
||||
modifyAncientsInjection = &called
|
||||
}
|
||||
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting CommitUpdate, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
PluginCommitUpdate(plugins.DefaultPluginLoader, num)
|
||||
}
|
||||
|
||||
func PluginCommitUpdate(pl *plugins.PluginLoader, num uint64) {
|
||||
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
if freezerUpdates == nil { freezerUpdates = make(map[uint64]map[string]interface{}) }
|
||||
min := ^uint64(0)
|
||||
for i := range freezerUpdates{
|
||||
if min > i { min = i }
|
||||
}
|
||||
for i := min ; i < num; i++ {
|
||||
update, ok := freezerUpdates[i]
|
||||
defer func(i uint64) { delete(freezerUpdates, i) }(i)
|
||||
if !ok {
|
||||
log.Warn("Attempting to commit untracked block", "num", i)
|
||||
continue
|
||||
}
|
||||
fnList := pl.Lookup("ModifyAncients", func(item interface{}) bool {
|
||||
_, ok := item.(func(uint64, map[string]interface{}))
|
||||
return ok
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func(uint64, map[string]interface{})); ok {
|
||||
fn(i, update)
|
||||
}
|
||||
}
|
||||
appendAncientFnList := pl.Lookup("AppendAncient", func(item interface{}) bool {
|
||||
_, ok := item.(func(number uint64, hash, header, body, receipts, td []byte))
|
||||
if ok { log.Warn("PluGeth's AppendAncient is deprecated. Please update to ModifyAncients.") }
|
||||
return ok
|
||||
})
|
||||
if len(appendAncientFnList) > 0 {
|
||||
var (
|
||||
hash []byte
|
||||
header []byte
|
||||
body []byte
|
||||
receipts []byte
|
||||
td []byte
|
||||
)
|
||||
if hashi, ok := update[ChainFreezerHashTable]; ok {
|
||||
switch v := hashi.(type) {
|
||||
case []byte:
|
||||
hash = v
|
||||
default:
|
||||
hash, _ = rlp.EncodeToBytes(v)
|
||||
}
|
||||
}
|
||||
if headeri, ok := update[ChainFreezerHeaderTable]; ok {
|
||||
switch v := headeri.(type) {
|
||||
case []byte:
|
||||
header = v
|
||||
default:
|
||||
header, _ = rlp.EncodeToBytes(v)
|
||||
}
|
||||
}
|
||||
if bodyi, ok := update[ChainFreezerBodiesTable]; ok {
|
||||
switch v := bodyi.(type) {
|
||||
case []byte:
|
||||
body = v
|
||||
default:
|
||||
body, _ = rlp.EncodeToBytes(v)
|
||||
}
|
||||
}
|
||||
if receiptsi, ok := update[ChainFreezerReceiptTable]; ok {
|
||||
switch v := receiptsi.(type) {
|
||||
case []byte:
|
||||
receipts = v
|
||||
default:
|
||||
receipts, _ = rlp.EncodeToBytes(v)
|
||||
}
|
||||
}
|
||||
if tdi, ok := update[ChainFreezerDifficultyTable]; ok {
|
||||
switch v := tdi.(type) {
|
||||
case []byte:
|
||||
td = v
|
||||
default:
|
||||
td, _ = rlp.EncodeToBytes(v)
|
||||
}
|
||||
}
|
||||
for _, fni := range appendAncientFnList {
|
||||
if fn, ok := fni.(func(number uint64, hash, header, body, receipts, td []byte)); ok {
|
||||
fn(i, hash, header, body, receipts, td)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
70
core/state/plugin_hooks.go
Normal file
70
core/state/plugin_hooks.go
Normal file
@ -0,0 +1,70 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/openrelayxyz/plugeth-utils/core"
|
||||
)
|
||||
|
||||
type pluginSnapshot struct {
|
||||
root common.Hash
|
||||
}
|
||||
|
||||
func (s *pluginSnapshot) Root() common.Hash {
|
||||
return s.root
|
||||
}
|
||||
|
||||
func (s *pluginSnapshot) Account(hash common.Hash) (*types.SlimAccount, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (s *pluginSnapshot) AccountRLP(hash common.Hash) ([]byte, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (s *pluginSnapshot) Storage(accountHash, storageHash common.Hash) ([]byte, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func PluginStateUpdate(pl *plugins.PluginLoader, blockRoot, parentRoot common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte, codeUpdates map[common.Hash][]byte) {
|
||||
fnList := pl.Lookup("StateUpdate", func(item interface{}) bool {
|
||||
_, ok := item.(func(core.Hash, core.Hash, map[core.Hash]struct{}, map[core.Hash][]byte, map[core.Hash]map[core.Hash][]byte, map[core.Hash][]byte))
|
||||
return ok
|
||||
})
|
||||
coreDestructs := make(map[core.Hash]struct{})
|
||||
for k, v := range destructs {
|
||||
coreDestructs[core.Hash(k)] = v
|
||||
}
|
||||
coreAccounts := make(map[core.Hash][]byte)
|
||||
for k, v := range accounts {
|
||||
coreAccounts[core.Hash(k)] = v
|
||||
}
|
||||
coreStorage := make(map[core.Hash]map[core.Hash][]byte)
|
||||
for k, v := range storage {
|
||||
coreStorage[core.Hash(k)] = make(map[core.Hash][]byte)
|
||||
for h, d := range v {
|
||||
coreStorage[core.Hash(k)][core.Hash(h)] = d
|
||||
}
|
||||
}
|
||||
coreCode := make(map[core.Hash][]byte)
|
||||
for k, v := range codeUpdates {
|
||||
coreCode[core.Hash(k)] = v
|
||||
}
|
||||
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func(core.Hash, core.Hash, map[core.Hash]struct{}, map[core.Hash][]byte, map[core.Hash]map[core.Hash][]byte, map[core.Hash][]byte)); ok {
|
||||
fn(core.Hash(blockRoot), core.Hash(parentRoot), coreDestructs, coreAccounts, coreStorage, coreCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func pluginStateUpdate(blockRoot, parentRoot common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte, codeUpdates map[common.Hash][]byte) {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting StateUpdate, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
PluginStateUpdate(plugins.DefaultPluginLoader, blockRoot, parentRoot, destructs, accounts, storage, codeUpdates)
|
||||
}
|
@ -169,6 +169,15 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error)
|
||||
if sdb.snaps != nil {
|
||||
sdb.snap = sdb.snaps.Snapshot(root)
|
||||
}
|
||||
// Start PluGeth section
|
||||
if sdb.snap == nil {
|
||||
log.Debug("Snapshots not availble. Using plugin snapshot.")
|
||||
sdb.snap = &pluginSnapshot{root}
|
||||
sdb.stateObjectsDestruct = make(map[common.Address]*types.StateAccount)
|
||||
sdb.accounts = make(map[common.Hash][]byte)
|
||||
sdb.storages = make(map[common.Hash]map[common.Hash][]byte)
|
||||
}
|
||||
// End PluGeth section
|
||||
return sdb, nil
|
||||
}
|
||||
|
||||
@ -950,6 +959,11 @@ func (s *StateDB) clearJournalAndRefund() {
|
||||
// storage iteration and constructs trie node deletion markers by creating
|
||||
// stack trie with iterated slots.
|
||||
func (s *StateDB) fastDeleteStorage(addrHash common.Hash, root common.Hash) (bool, common.StorageSize, map[common.Hash][]byte, *trienode.NodeSet, error) {
|
||||
// begin PluGeth Injection // this injection is neccessary to enable the native geth tests in core/state to pass
|
||||
if _, err := s.snap.Account(addrHash); err != nil {
|
||||
return false, 0, nil, nil, err
|
||||
}
|
||||
// end PluGeth Injection
|
||||
iter, err := s.snaps.StorageIterator(s.originalRoot, addrHash, common.Hash{})
|
||||
if err != nil {
|
||||
return false, 0, nil, nil, err
|
||||
@ -1184,6 +1198,10 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
|
||||
return common.Hash{}, err
|
||||
}
|
||||
// Handle all state updates afterwards
|
||||
|
||||
// begin PluGeth injection
|
||||
codeUpdates := make(map[common.Hash][]byte)
|
||||
// end PluGeth injection
|
||||
for addr := range s.stateObjectsDirty {
|
||||
obj := s.stateObjects[addr]
|
||||
if obj.deleted {
|
||||
@ -1192,6 +1210,9 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
|
||||
// Write any contract code associated with the state object
|
||||
if obj.code != nil && obj.dirtyCode {
|
||||
rawdb.WriteCode(codeWriter, common.BytesToHash(obj.CodeHash()), obj.code)
|
||||
// begin PluGeth injection
|
||||
codeUpdates[common.BytesToHash(obj.CodeHash())] = obj.code
|
||||
// end PluGeth injection
|
||||
obj.dirtyCode = false
|
||||
}
|
||||
// Write any storage changes in the state object to its storage trie
|
||||
@ -1251,15 +1272,20 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
|
||||
start := time.Now()
|
||||
// Only update if there's a state transition (skip empty Clique blocks)
|
||||
if parent := s.snap.Root(); parent != root {
|
||||
if err := s.snaps.Update(root, parent, s.convertAccountSet(s.stateObjectsDestruct), s.accounts, s.storages); err != nil {
|
||||
log.Warn("Failed to update snapshot tree", "from", parent, "to", root, "err", err)
|
||||
}
|
||||
// Keep 128 diff layers in the memory, persistent layer is 129th.
|
||||
// - head layer is paired with HEAD state
|
||||
// - head-1 layer is paired with HEAD-1 state
|
||||
// - head-127 layer(bottom-most diff layer) is paired with HEAD-127 state
|
||||
if err := s.snaps.Cap(root, 128); err != nil {
|
||||
log.Warn("Failed to cap snapshot tree", "root", root, "layers", 128, "err", err)
|
||||
//begin PluGeth code injection
|
||||
pluginStateUpdate(root, parent, s.convertAccountSet(s.stateObjectsDestruct), s.accounts, s.storages, codeUpdates)
|
||||
if _, ok := s.snap.(*pluginSnapshot); !ok && s.snaps != nil { // This if statement (but not its content) was added by PluGeth
|
||||
//end PluGeth injection
|
||||
if err := s.snaps.Update(root, parent, s.convertAccountSet(s.stateObjectsDestruct), s.accounts, s.storages); err != nil {
|
||||
log.Warn("Failed to update snapshot tree", "from", parent, "to", root, "err", err)
|
||||
}
|
||||
// Keep 128 diff layers in the memory, persistent layer is 129th.
|
||||
// - head layer is paired with HEAD state
|
||||
// - head-1 layer is paired with HEAD-1 state
|
||||
// - head-127 layer(bottom-most diff layer) is paired with HEAD-127 state
|
||||
if err := s.snaps.Cap(root, 128); err != nil {
|
||||
log.Warn("Failed to cap snapshot tree", "root", root, "layers", 128, "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
if metrics.EnabledExpensive {
|
||||
|
@ -71,6 +71,13 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
|
||||
misc.ApplyDAOHardFork(statedb)
|
||||
}
|
||||
//begin PluGeth code injection
|
||||
blockTracer, ok := pluginGetBlockTracer(header.Hash(), statedb)
|
||||
if ok {
|
||||
cfg.Tracer = blockTracer
|
||||
// cfg.Debug = true
|
||||
}
|
||||
// end pluGeth code injection
|
||||
var (
|
||||
context = NewEVMBlockContext(header, p.bc, nil)
|
||||
vmenv = vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg)
|
||||
@ -79,17 +86,37 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
||||
ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
|
||||
}
|
||||
// begin PluGeth code injection
|
||||
pluginPreProcessBlock(block)
|
||||
blockTracer.PreProcessBlock(block)
|
||||
// end PluGeth code injection
|
||||
// Iterate over and process the individual transactions
|
||||
for i, tx := range block.Transactions() {
|
||||
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
|
||||
if err != nil {
|
||||
// begin PluGeth injection
|
||||
pluginBlockProcessingError(tx, block, err)
|
||||
blockTracer.BlockProcessingError(tx, block, err)
|
||||
// end PluGeth injection
|
||||
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
||||
}
|
||||
statedb.SetTxContext(tx.Hash(), i)
|
||||
// begin PluGeth injection
|
||||
pluginPreProcessTransaction(tx, block, i)
|
||||
blockTracer.PreProcessTransaction(tx, block, i)
|
||||
// end pluGeth injection
|
||||
receipt, err := applyTransaction(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv)
|
||||
if err != nil {
|
||||
// begin PluGeth code injection
|
||||
pluginBlockProcessingError(tx, block, err)
|
||||
blockTracer.BlockProcessingError(tx, block, err)
|
||||
// end PluGeth code injection
|
||||
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
||||
}
|
||||
// begin PluGeth code injection
|
||||
pluginPostProcessTransaction(tx, block, i, receipt)
|
||||
blockTracer.PostProcessTransaction(tx, block, i, receipt)
|
||||
// end PluGeth code injection
|
||||
receipts = append(receipts, receipt)
|
||||
allLogs = append(allLogs, receipt.Logs...)
|
||||
}
|
||||
@ -100,6 +127,10 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||
}
|
||||
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
||||
p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), withdrawals)
|
||||
//begin PluGeth code injection
|
||||
pluginPostProcessBlock(block)
|
||||
blockTracer.PostProcessBlock(block)
|
||||
// end PluGeth code injection
|
||||
|
||||
return receipts, allLogs, *usedGas, nil
|
||||
}
|
||||
|
@ -295,7 +295,9 @@ func (st *StateTransition) preCheck() error {
|
||||
}
|
||||
}
|
||||
// Make sure that transaction gasFeeCap is greater than the baseFee (post london)
|
||||
if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
|
||||
// begin PluGeth injection
|
||||
if st.evm.ChainConfig().Is1559(st.evm.Context.BlockNumber) {
|
||||
// end PluGeth injection
|
||||
// Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call)
|
||||
skipCheck := st.evm.Config.NoBaseFee && msg.GasFeeCap.BitLen() == 0 && msg.GasTipCap.BitLen() == 0
|
||||
if !skipCheck {
|
||||
@ -376,6 +378,14 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
||||
// 6. caller has enough balance to cover asset transfer for **topmost** call
|
||||
|
||||
// Check clauses 1-3, buy gas if everything is correct
|
||||
|
||||
// begin PluGeth injection
|
||||
if v, ok := st.evm.Config.Tracer.(PreTracer); ok {
|
||||
v.CapturePreStart(st.msg.From, st.msg.To, st.msg.Data, st.msg.GasLimit, st.msg.Value)
|
||||
}
|
||||
// end PluGeth injection
|
||||
|
||||
|
||||
if err := st.preCheck(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -445,7 +455,11 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
||||
}
|
||||
effectiveTip := msg.GasPrice
|
||||
if rules.IsLondon {
|
||||
effectiveTip = cmath.BigMin(msg.GasTipCap, new(big.Int).Sub(msg.GasFeeCap, st.evm.Context.BaseFee))
|
||||
// begin PluGeth injection
|
||||
if st.evm.ChainConfig().Is1559(st.evm.Context.BlockNumber) {
|
||||
// end PluGeth injection
|
||||
effectiveTip = cmath.BigMin(msg.GasTipCap, new(big.Int).Sub(msg.GasFeeCap, st.evm.Context.BaseFee))
|
||||
}
|
||||
}
|
||||
effectiveTipU256, _ := uint256.FromBig(effectiveTip)
|
||||
|
||||
|
@ -54,4 +54,10 @@ var (
|
||||
// ErrFutureReplacePending is returned if a future transaction replaces a pending
|
||||
// one. Future transactions should only be able to replace other future transactions.
|
||||
ErrFutureReplacePending = errors.New("future transaction tries to replace pending")
|
||||
|
||||
// ErrAlreadyReserved is returned if the sender address has a pending transaction
|
||||
// in a different subpool. For example, this error is returned in response to any
|
||||
// input transaction of non-blob type when a blob transaction from this sender
|
||||
// remains pending (and vice-versa).
|
||||
ErrAlreadyReserved = errors.New("address already reserved")
|
||||
)
|
||||
|
@ -122,7 +122,7 @@ func (p *TxPool) reserver(id int, subpool SubPool) AddressReserver {
|
||||
log.Error("pool attempted to reserve already-owned address", "address", addr)
|
||||
return nil // Ignore fault to give the pool a chance to recover while the bug gets fixed
|
||||
}
|
||||
return errors.New("address already reserved")
|
||||
return ErrAlreadyReserved
|
||||
}
|
||||
p.reservations[addr] = subpool
|
||||
if metrics.Enabled {
|
||||
|
@ -72,7 +72,9 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter {
|
||||
table = &constantinopleInstructionSet
|
||||
case evm.chainRules.IsByzantium:
|
||||
table = &byzantiumInstructionSet
|
||||
case evm.chainRules.IsEIP158:
|
||||
// begin PluGeth injection
|
||||
case evm.chainRules.IsEIP160:
|
||||
// end PluGeth injection
|
||||
table = &spuriousDragonInstructionSet
|
||||
case evm.chainRules.IsEIP150:
|
||||
table = &tangerineWhistleInstructionSet
|
||||
@ -95,6 +97,11 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter {
|
||||
}
|
||||
}
|
||||
evm.Config.ExtraEips = extraEips
|
||||
// begin PluGeth injection
|
||||
if pluginTable := pluginOpCodeSelect(table); pluginTable != nil {
|
||||
table = pluginTable
|
||||
}
|
||||
// end PluGeth injection
|
||||
return &EVMInterpreter{evm: evm, table: table}
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,9 @@ func LookupInstructionSet(rules params.Rules) (JumpTable, error) {
|
||||
return newConstantinopleInstructionSet(), nil
|
||||
case rules.IsByzantium:
|
||||
return newByzantiumInstructionSet(), nil
|
||||
case rules.IsEIP158:
|
||||
// Begin plugeth injection
|
||||
case rules.IsEIP160:
|
||||
// End plugeth injection
|
||||
return newSpuriousDragonInstructionSet(), nil
|
||||
case rules.IsEIP150:
|
||||
return newTangerineWhistleInstructionSet(), nil
|
||||
|
39
core/vm/plugin_hooks.go
Normal file
39
core/vm/plugin_hooks.go
Normal file
@ -0,0 +1,39 @@
|
||||
package vm
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
)
|
||||
|
||||
func (st *Stack) Len() int {
|
||||
return len(st.data)
|
||||
}
|
||||
|
||||
func PluginOpCodeSelect(pl *plugins.PluginLoader, jt *JumpTable) *JumpTable {
|
||||
var opCodes []int
|
||||
fnList := pl.Lookup("OpCodeSelect", func(item interface{}) bool {
|
||||
_, ok := item.(func() []int)
|
||||
return ok
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func() []int); ok {
|
||||
opCodes = append(opCodes, fn()...)
|
||||
}
|
||||
}
|
||||
if len(opCodes) > 0 {
|
||||
jt = copyJumpTable(jt)
|
||||
}
|
||||
for _, idx := range opCodes {
|
||||
(*jt)[idx] = &operation{execute: opUndefined, maxStack: maxStack(0, 0)}
|
||||
}
|
||||
return jt
|
||||
}
|
||||
|
||||
func pluginOpCodeSelect(jt *JumpTable) *JumpTable {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting PluginOpCodeSelect, but default PluginLoader has not been initialized")
|
||||
return nil
|
||||
}
|
||||
return PluginOpCodeSelect(plugins.DefaultPluginLoader, jt)
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/miner"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
)
|
||||
|
||||
// FullNodeGPO contains default gasprice oracle settings for full node.
|
||||
@ -166,6 +167,12 @@ type Config struct {
|
||||
// only exist on already merged networks.
|
||||
func CreateConsensusEngine(config *params.ChainConfig, db ethdb.Database) (consensus.Engine, error) {
|
||||
// If proof-of-authority is requested, set it up
|
||||
//begin PluGeth code injection
|
||||
if engine := pluginGetEngine(config, db); engine != nil {
|
||||
log.Info("returning plugin consensus engine")
|
||||
return engine, nil
|
||||
}
|
||||
//end PluGeth code injection
|
||||
if config.Clique != nil {
|
||||
return beacon.New(clique.New(config.Clique, db)), nil
|
||||
}
|
||||
|
45
eth/ethconfig/plugin_hooks.go
Normal file
45
eth/ethconfig/plugin_hooks.go
Normal file
@ -0,0 +1,45 @@
|
||||
package ethconfig
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/consensus"
|
||||
|
||||
"github.com/ethereum/go-ethereum/plugins/wrappers/backendwrapper"
|
||||
wengine "github.com/ethereum/go-ethereum/plugins/wrappers/engine"
|
||||
|
||||
"github.com/openrelayxyz/plugeth-utils/restricted"
|
||||
pparams "github.com/openrelayxyz/plugeth-utils/restricted/params"
|
||||
pconsensus "github.com/openrelayxyz/plugeth-utils/restricted/consensus"
|
||||
)
|
||||
|
||||
|
||||
|
||||
func PluginGetEngine(pl *plugins.PluginLoader, chainConfig *params.ChainConfig, db ethdb.Database) consensus.Engine {
|
||||
fnList := pl.Lookup("CreateEngine", func(item interface{}) bool {
|
||||
_, ok := item.(func(*pparams.ChainConfig, restricted.Database) pconsensus.Engine)
|
||||
return ok
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func(*pparams.ChainConfig, restricted.Database) pconsensus.Engine); ok {
|
||||
clonedConfig := backendwrapper.CloneChainConfig(chainConfig)
|
||||
wrappedDb := backendwrapper.NewDb(db)
|
||||
if engine := fn(clonedConfig, wrappedDb); engine != nil {
|
||||
wrappedEngine := wengine.NewWrappedEngine(engine)
|
||||
return wrappedEngine
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func pluginGetEngine(chainConfig *params.ChainConfig, db ethdb.Database) consensus.Engine {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting GetEngine, but default PluginLoader has not been initialized")
|
||||
return nil
|
||||
}
|
||||
return PluginGetEngine(plugins.DefaultPluginLoader, chainConfig, db)
|
||||
}
|
@ -947,10 +947,17 @@ func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Conte
|
||||
// Default tracer is the struct logger
|
||||
tracer = logger.NewStructLogger(config.Config)
|
||||
if config.Tracer != nil {
|
||||
tracer, err = DefaultDirectory.New(*config.Tracer, txctx, config.TracerConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// Get the tracer from the plugin loader
|
||||
//begin PluGeth code injection
|
||||
if tr, ok := getPluginTracer(*config.Tracer); ok {
|
||||
tracer = tr(statedb, vmctx)
|
||||
} else {
|
||||
tracer, err = DefaultDirectory.New(*config.Tracer, txctx, config.TracerConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// end PluGeth injection
|
||||
}
|
||||
vmenv := vm.NewEVM(vmctx, txContext, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer, NoBaseFee: true})
|
||||
|
||||
|
@ -161,7 +161,7 @@ func (t *callTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, sco
|
||||
return
|
||||
}
|
||||
// Avoid processing nested calls when only caring about top call
|
||||
if t.config.OnlyTopCall && depth > 0 {
|
||||
if t.config.OnlyTopCall && depth > 1 {
|
||||
return
|
||||
}
|
||||
// Skip if tracing was interrupted
|
||||
|
60
eth/tracers/plugin_hooks.go
Normal file
60
eth/tracers/plugin_hooks.go
Normal file
@ -0,0 +1,60 @@
|
||||
package tracers
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
"github.com/ethereum/go-ethereum/plugins/interfaces"
|
||||
"github.com/ethereum/go-ethereum/plugins/wrappers"
|
||||
"github.com/openrelayxyz/plugeth-utils/core"
|
||||
)
|
||||
|
||||
func GetPluginTracer(pl *plugins.PluginLoader, name string) (func(*state.StateDB, vm.BlockContext) interfaces.TracerResult, bool) {
|
||||
tracers := pl.Lookup("Tracers", func(item interface{}) bool {
|
||||
_, ok := item.(*map[string]func(core.StateDB) core.TracerResult)
|
||||
_, ok2 := item.(*map[string]func(core.StateDB, core.BlockContext) core.TracerResult)
|
||||
if !(ok || ok2) {
|
||||
log.Warn("Found tracer that did not match type", "tracer", reflect.TypeOf(item))
|
||||
}
|
||||
return ok || ok2
|
||||
})
|
||||
|
||||
for _, tmap := range tracers {
|
||||
if tracerMap, ok := tmap.(*map[string]func(core.StateDB) core.TracerResult); ok {
|
||||
if tracer, ok := (*tracerMap)[name]; ok {
|
||||
return func(sdb *state.StateDB, vmctx vm.BlockContext) interfaces.TracerResult {
|
||||
return wrappers.NewWrappedTracer(tracer(wrappers.NewWrappedStateDB(sdb)))
|
||||
}, true
|
||||
}
|
||||
}
|
||||
if tracerMap, ok := tmap.(*map[string]func(core.StateDB, core.BlockContext) core.TracerResult); ok {
|
||||
if tracer, ok := (*tracerMap)[name]; ok {
|
||||
return func(sdb *state.StateDB, vmctx vm.BlockContext) interfaces.TracerResult {
|
||||
return wrappers.NewWrappedTracer(tracer(wrappers.NewWrappedStateDB(sdb), core.BlockContext{
|
||||
Coinbase: core.Address(vmctx.Coinbase),
|
||||
GasLimit: vmctx.GasLimit,
|
||||
BlockNumber: vmctx.BlockNumber,
|
||||
// casting int64 zero as bigInt is foundation PluGeth only, it is being done to preserve compatability with other networks
|
||||
Time: new(big.Int).SetInt64(int64(vmctx.Time)),
|
||||
Difficulty: vmctx.Difficulty,
|
||||
BaseFee: vmctx.BaseFee,
|
||||
}))
|
||||
}, true
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Info("Tracer not found", "name", name, "tracers", len(tracers))
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func getPluginTracer(name string) (func(*state.StateDB, vm.BlockContext) interfaces.TracerResult, bool) {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting GetPluginTracer, but default PluginLoader has not been initialized")
|
||||
return nil, false
|
||||
}
|
||||
return GetPluginTracer(plugins.DefaultPluginLoader, name)
|
||||
}
|
13
go.mod
13
go.mod
@ -10,7 +10,7 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.45
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.43
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.2
|
||||
github.com/cespare/cp v0.1.0
|
||||
github.com/cloudflare/cloudflare-go v0.79.0
|
||||
github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593
|
||||
@ -34,7 +34,7 @@ require (
|
||||
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb
|
||||
github.com/google/gofuzz v1.2.0
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/graph-gophers/graphql-go v1.3.0
|
||||
github.com/hashicorp/go-bexpr v0.1.10
|
||||
github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4
|
||||
@ -52,9 +52,10 @@ require (
|
||||
github.com/mattn/go-isatty v0.0.17
|
||||
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/openrelayxyz/plugeth-utils v1.5.0
|
||||
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7
|
||||
github.com/protolambda/bls12-381-util v0.0.0-20220416220906-d8552aa452c7
|
||||
github.com/rs/cors v1.7.0
|
||||
github.com/rs/cors v1.8.2
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible
|
||||
github.com/status-im/keycard-go v0.2.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
@ -66,7 +67,7 @@ require (
|
||||
golang.org/x/crypto v0.17.0
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
|
||||
golang.org/x/sync v0.5.0
|
||||
golang.org/x/sys v0.16.0
|
||||
golang.org/x/sys v0.15.0
|
||||
golang.org/x/text v0.14.0
|
||||
golang.org/x/time v0.3.0
|
||||
golang.org/x/tools v0.15.0
|
||||
@ -133,7 +134,7 @@ require (
|
||||
github.com/prometheus/common v0.32.1 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.9.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||
@ -144,3 +145,5 @@ require (
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
rsc.io/tmplfunc v0.0.3 // indirect
|
||||
)
|
||||
|
||||
replace github.com/openrelayxyz/plugeth-utils => git.vdb.to/cerc-io/plugeth-utils v0.0.0-20230706160122-cd41de354c46
|
||||
|
21
go.sum
21
go.sum
@ -31,6 +31,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
git.vdb.to/cerc-io/plugeth-utils v0.0.0-20230706160122-cd41de354c46 h1:KYcbbne/RXd7AuxbUd/3hgk1jPN+33k2CKiNsUsMCC0=
|
||||
git.vdb.to/cerc-io/plugeth-utils v0.0.0-20230706160122-cd41de354c46/go.mod h1:VpDN61dxy64zGff05F0adujR5enD/JEdXBkTQ+PaIsQ=
|
||||
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
|
||||
@ -99,8 +101,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88=
|
||||
github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk=
|
||||
@ -322,8 +324,8 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0=
|
||||
github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
|
||||
github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE=
|
||||
@ -535,10 +537,11 @@ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
|
||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U=
|
||||
github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
@ -784,8 +787,8 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
|
@ -902,6 +902,10 @@ type Rules struct {
|
||||
IsBerlin, IsLondon bool
|
||||
IsMerge, IsShanghai, IsCancun, IsPrague bool
|
||||
IsVerkle bool
|
||||
|
||||
// begin plugeth injection
|
||||
IsEIP160 bool
|
||||
// end plugeth injection
|
||||
}
|
||||
|
||||
// Rules ensures c's ChainID is not nil.
|
||||
@ -929,5 +933,10 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules
|
||||
IsCancun: isMerge && c.IsCancun(num, timestamp),
|
||||
IsPrague: isMerge && c.IsPrague(num, timestamp),
|
||||
IsVerkle: isMerge && c.IsVerkle(num, timestamp),
|
||||
|
||||
// Begin plugeth injection
|
||||
IsEIP160: c.IsEIP160(num),
|
||||
// End plugeth injection
|
||||
|
||||
}
|
||||
}
|
||||
|
41
params/plugin_hooks.go
Normal file
41
params/plugin_hooks.go
Normal file
@ -0,0 +1,41 @@
|
||||
package params
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
)
|
||||
|
||||
// Is1559 returns whether num is either equal to the London fork block or greater, if the chain supports EIP1559
|
||||
func (c *ChainConfig) Is1559(num *big.Int) bool {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting is1559, but default PluginLoader has not been initialized")
|
||||
return c.IsLondon(num)
|
||||
}
|
||||
if active, ok := PluginEIPCheck(plugins.DefaultPluginLoader, "Is1559", num); ok {
|
||||
return active
|
||||
}
|
||||
return c.IsLondon(num)
|
||||
}
|
||||
|
||||
|
||||
func PluginEIPCheck(pl *plugins.PluginLoader, eipHookName string, num *big.Int) (bool, bool) {
|
||||
fn, ok := plugins.LookupOne[func(*big.Int) bool](pl, eipHookName)
|
||||
if !ok {
|
||||
return false, false
|
||||
}
|
||||
return fn(num), ok
|
||||
}
|
||||
// IsEIP160 returns whether num is either equal to the EIP160 block or greater.
|
||||
// This defaults to same as 158, but some chains do it at a different block
|
||||
func (c *ChainConfig) IsEIP160(num *big.Int) bool {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting is160, but default PluginLoader has not been initialized")
|
||||
return c.IsEIP158(num)
|
||||
}
|
||||
if active, ok := PluginEIPCheck(plugins.DefaultPluginLoader, "Is160", num); ok {
|
||||
return active
|
||||
}
|
||||
return c.IsEIP158(num)
|
||||
}
|
@ -21,10 +21,10 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
VersionMajor = 1 // Major version component of the current release
|
||||
VersionMinor = 13 // Minor version component of the current release
|
||||
VersionPatch = 14 // Patch version component of the current release
|
||||
VersionMeta = "unstable" // Version metadata to append to the version string
|
||||
VersionMajor = 1 // Major version component of the current release
|
||||
VersionMinor = 13 // Minor version component of the current release
|
||||
VersionPatch = 14 // Patch version component of the current release
|
||||
VersionMeta = "stable" // Version metadata to append to the version string
|
||||
)
|
||||
|
||||
// Version holds the textual version string.
|
||||
|
19
plugins/hooktester.go
Normal file
19
plugins/hooktester.go
Normal file
@ -0,0 +1,19 @@
|
||||
package plugins
|
||||
|
||||
|
||||
// type PluginLoader struct{
|
||||
// Plugins []*plugin.Plugin
|
||||
// Subcommands map[string]Subcommand
|
||||
// Flags []*flag.FlagSet
|
||||
// LookupCache map[string][]interface{}
|
||||
// }
|
||||
|
||||
func HookTester(name string, fn interface{}) func() {
|
||||
oldDefault := DefaultPluginLoader
|
||||
DefaultPluginLoader = &PluginLoader{
|
||||
LookupCache: map[string][]interface{}{
|
||||
name: []interface{}{fn},
|
||||
},
|
||||
}
|
||||
return func() { DefaultPluginLoader = oldDefault }
|
||||
}
|
81
plugins/interfaces/interface.go
Normal file
81
plugins/interfaces/interface.go
Normal file
@ -0,0 +1,81 @@
|
||||
package interfaces
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/consensus"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/bloombits"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
|
||||
//"github.com/ethereum/go-ethereum/core/vm/logger"
|
||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
// Backend interface provides the common API services (that are provided by
|
||||
// both full and light clients) with access to necessary functions.
|
||||
type Backend interface {
|
||||
// General Ethereum API
|
||||
Downloader() *downloader.Downloader
|
||||
SuggestGasTipCap(ctx context.Context) (*big.Int, error)
|
||||
ChainDb() ethdb.Database
|
||||
ExtRPCEnabled() bool
|
||||
RPCGasCap() uint64 // global gas cap for eth_call over rpc: DoS protection
|
||||
RPCTxFeeCap() float64 // global tx fee cap for all transaction related APIs
|
||||
UnprotectedAllowed() bool // allows only for EIP155 transactions.
|
||||
|
||||
// Blockchain API
|
||||
SetHead(number uint64)
|
||||
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
|
||||
HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error)
|
||||
HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error)
|
||||
CurrentHeader() *types.Header
|
||||
CurrentBlock() *types.Block
|
||||
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
|
||||
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
|
||||
BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error)
|
||||
StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error)
|
||||
StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error)
|
||||
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
|
||||
GetTd(ctx context.Context, hash common.Hash) *big.Int
|
||||
GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, cfg *vm.Config) (*vm.EVM, func() error, error)
|
||||
SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription
|
||||
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
|
||||
SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription
|
||||
|
||||
// Transaction pool API
|
||||
SendTx(ctx context.Context, signedTx *types.Transaction) error
|
||||
GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
|
||||
GetPoolTransactions() (types.Transactions, error)
|
||||
GetPoolTransaction(txHash common.Hash) *types.Transaction
|
||||
GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error)
|
||||
Stats() (pending int, queued int)
|
||||
TxPoolContent() (map[common.Address]types.Transactions, map[common.Address]types.Transactions)
|
||||
SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
|
||||
|
||||
// Filter API
|
||||
BloomStatus() (uint64, uint64)
|
||||
GetLogs(ctx context.Context, blockHash common.Hash) ([][]*types.Log, error)
|
||||
ServiceFilter(ctx context.Context, session *bloombits.MatcherSession)
|
||||
SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription
|
||||
SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription
|
||||
SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription
|
||||
|
||||
ChainConfig() *params.ChainConfig
|
||||
Engine() consensus.Engine
|
||||
}
|
||||
|
||||
type TracerResult interface {
|
||||
vm.EVMLogger
|
||||
GetResult() (json.RawMessage, error)
|
||||
Stop(error)
|
||||
}
|
202
plugins/plugin_loader.go
Normal file
202
plugins/plugin_loader.go
Normal file
@ -0,0 +1,202 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"plugin"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/openrelayxyz/plugeth-utils/core"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type Subcommand func(core.Context, []string) error
|
||||
|
||||
type pluginDetails struct {
|
||||
p *plugin.Plugin
|
||||
name string
|
||||
}
|
||||
|
||||
type PluginLoader struct {
|
||||
Plugins []pluginDetails
|
||||
Subcommands map[string]Subcommand
|
||||
Flags []*flag.FlagSet
|
||||
LookupCache map[string][]interface{}
|
||||
}
|
||||
|
||||
func (pl *PluginLoader) Lookup(name string, validate func(interface{}) bool) []interface{} {
|
||||
if v, ok := pl.LookupCache[name]; ok {
|
||||
return v
|
||||
}
|
||||
results := []interface{}{}
|
||||
for _, plugin := range pl.Plugins {
|
||||
if v, err := plugin.p.Lookup(name); err == nil {
|
||||
if validate(v) {
|
||||
results = append(results, v)
|
||||
} else {
|
||||
log.Warn("Plugin matches hook but not signature", "plugin", plugin.name, "hook", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
pl.LookupCache[name] = results
|
||||
return results
|
||||
}
|
||||
|
||||
func Lookup(name string, validate func(interface{}) bool) []interface{} {
|
||||
if DefaultPluginLoader == nil {
|
||||
log.Warn("Lookup attempted, but PluginLoader is not initialized", "name", name)
|
||||
return []interface{}{}
|
||||
}
|
||||
return DefaultPluginLoader.Lookup(name, validate)
|
||||
}
|
||||
|
||||
var DefaultPluginLoader *PluginLoader
|
||||
|
||||
func NewPluginLoader(target string) (*PluginLoader, error) {
|
||||
log.Info("Loading plugins from directory", "path", target)
|
||||
pl := &PluginLoader{
|
||||
Plugins: []pluginDetails{},
|
||||
Subcommands: make(map[string]Subcommand),
|
||||
Flags: []*flag.FlagSet{},
|
||||
LookupCache: make(map[string][]interface{}),
|
||||
}
|
||||
files, err := ioutil.ReadDir(target)
|
||||
if err != nil {
|
||||
log.Warn("Could not load plugins directory. Skipping.", "path", target)
|
||||
return pl, nil
|
||||
}
|
||||
for _, file := range files {
|
||||
fpath := path.Join(target, file.Name())
|
||||
if !strings.HasSuffix(file.Name(), ".so") {
|
||||
log.Debug("File in plugin directory is not '.so' file. Skipping.", "file", fpath)
|
||||
continue
|
||||
}
|
||||
plug, err := plugin.Open(fpath)
|
||||
if err != nil {
|
||||
log.Warn("File in plugin directory could not be loaded", "file", fpath, "error", err)
|
||||
continue
|
||||
}
|
||||
// Any type of plugin can potentially specify flags
|
||||
f, err := plug.Lookup("Flags")
|
||||
if err == nil {
|
||||
flagset, ok := f.(*flag.FlagSet)
|
||||
if !ok {
|
||||
log.Warn("Found plugin.Flags, but it its not a *FlagSet", "file", fpath)
|
||||
} else {
|
||||
pl.Flags = append(pl.Flags, flagset)
|
||||
}
|
||||
}
|
||||
sb, err := plug.Lookup("Subcommands")
|
||||
if err == nil {
|
||||
subcommands, ok := sb.(*map[string]func(core.Context, []string) error)
|
||||
if !ok {
|
||||
log.Warn("Could not cast plugin.Subcommands to `map[string]func(core.Context, []string) error`", "file", fpath, "type", reflect.TypeOf(sb))
|
||||
} else {
|
||||
for k, v := range *subcommands {
|
||||
if _, ok := pl.Subcommands[k]; ok {
|
||||
log.Warn("Subcommand redeclared", "file", fpath, "subcommand", k)
|
||||
}
|
||||
pl.Subcommands[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
pl.Plugins = append(pl.Plugins, pluginDetails{plug, fpath})
|
||||
}
|
||||
return pl, nil
|
||||
}
|
||||
|
||||
func Initialize(target string, ctx core.Context) (err error) {
|
||||
DefaultPluginLoader, err = NewPluginLoader(target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
DefaultPluginLoader.Initialize(ctx)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pl *PluginLoader) Initialize(ctx core.Context) {
|
||||
fns := pl.Lookup("Initialize", func(i interface{}) bool {
|
||||
_, ok := i.(func(core.Context, core.PluginLoader, core.Logger))
|
||||
return ok
|
||||
})
|
||||
for _, fni := range fns {
|
||||
if fn, ok := fni.(func(core.Context, core.PluginLoader, core.Logger)); ok {
|
||||
fn(ctx, pl, log.Root())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (pl *PluginLoader) RunSubcommand(ctx *cli.Context) (bool, error) {
|
||||
args := ctx.Args().Slice()
|
||||
if len(args) == 0 {
|
||||
return false, fmt.Errorf("no subcommand arguments")
|
||||
}
|
||||
subcommand, ok := pl.Subcommands[args[0]]
|
||||
if !ok {
|
||||
return false, fmt.Errorf("Subcommand %v does not exist", args[0])
|
||||
}
|
||||
return true, subcommand(ctx, args[1:])
|
||||
}
|
||||
|
||||
func RunSubcommand(ctx *cli.Context) (bool, error) {
|
||||
if DefaultPluginLoader == nil {
|
||||
return false, fmt.Errorf("Plugin loader not initialized")
|
||||
}
|
||||
return DefaultPluginLoader.RunSubcommand(ctx)
|
||||
}
|
||||
|
||||
func (pl *PluginLoader) ParseFlags(args []string) bool {
|
||||
for _, flagset := range pl.Flags {
|
||||
flagset.Parse(args)
|
||||
}
|
||||
return len(pl.Flags) > 0
|
||||
}
|
||||
|
||||
func LookupOne[T any](pl *PluginLoader, name string) (T, bool) {
|
||||
var zero T
|
||||
if pl == nil {
|
||||
if DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting to LookupOne, but default PluginLoader has not been initialized")
|
||||
return zero, false
|
||||
}
|
||||
pl = DefaultPluginLoader
|
||||
}
|
||||
items := pl.Lookup(name, func(v interface{}) bool {
|
||||
_, ok := v.(T)
|
||||
return ok
|
||||
})
|
||||
if len(items) == 0 {
|
||||
return zero, false
|
||||
}
|
||||
return items[0].(T), true
|
||||
}
|
||||
|
||||
|
||||
func ParseFlags(args []string) bool {
|
||||
if DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting to parse flags, but default PluginLoader has not been initialized")
|
||||
return false
|
||||
}
|
||||
return DefaultPluginLoader.ParseFlags(args)
|
||||
}
|
||||
|
||||
type feedWrapper struct {
|
||||
feed *event.Feed
|
||||
}
|
||||
|
||||
func (f *feedWrapper) Send(item interface{}) int {
|
||||
return f.feed.Send(item)
|
||||
}
|
||||
|
||||
func (f *feedWrapper) Subscribe(ch interface{}) core.Subscription {
|
||||
return f.feed.Subscribe(ch)
|
||||
}
|
||||
|
||||
func (pl *PluginLoader) GetFeed() core.Feed {
|
||||
return &feedWrapper{&event.Feed{}}
|
||||
}
|
9
plugins/test-plugin/README.md
Normal file
9
plugins/test-plugin/README.md
Normal file
@ -0,0 +1,9 @@
|
||||
## Plugeth Test Plugin
|
||||
|
||||
This plugin works in a very similar fashion as the [Consensus Engine plugin](https://github.com/openrelayxyz/plugeth-plugins/tree/master/packages/consensus-engine#readme). There is a bash script, `./test/run-test.sh` which instantiates three individual nodes which execute a pseudo blockchain. Throughout the execution of the chain many of the PluGeth hooks and injections are engaged which in turn trigger `pluginBlockChain()` to track the invoked methods and complain if any are not called. Thus we can confirm that the PluGeth application is fully implemented on the target client.
|
||||
|
||||
In order to use the plugin navigate to the `/test/` directory. Change the permissions on `run-test.sh` to enable execution. Then point the executable geth file to a Geth binary like so: `$ /path/to/geth/geth ./run-test.sh `. The test takes roughly 4.5 mins to run. If successful it should close with an exit code of `0`.
|
||||
|
||||
There are four methods not covered by testing at this time: `LiveCaptureFault()`, `LiveCaptureEnter()`, `LiveCaptureExit()`, `LiveTracerResult()`. Also, there are several injections which fall outside of the testing parameters of this application: `./core/` `NewSideBlock()`, `Reorg()`, `BlockProcessingError()`, `./core/rawdb/` `ModifyAncients()`, `AppendAncient()`. These are covered by stand alone standard go tests which can all be run by navigating to the respective directories and running: `go test -v -run TestPlugethInjections`.
|
||||
|
||||
Note: depending on where the script is deployed Geth may complain that the path to the `.ipc` file is too long. Renaming of the directories or moving the project may be necessary.
|
115
plugins/test-plugin/engine.go
Normal file
115
plugins/test-plugin/engine.go
Normal file
@ -0,0 +1,115 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/openrelayxyz/plugeth-utils/core"
|
||||
"github.com/openrelayxyz/plugeth-utils/restricted"
|
||||
"github.com/openrelayxyz/plugeth-utils/restricted/consensus"
|
||||
"github.com/openrelayxyz/plugeth-utils/restricted/params"
|
||||
"github.com/openrelayxyz/plugeth-utils/restricted/types"
|
||||
)
|
||||
|
||||
var (
|
||||
pl core.PluginLoader
|
||||
backend restricted.Backend
|
||||
log core.Logger
|
||||
events core.Feed
|
||||
createEngineCalled bool
|
||||
)
|
||||
|
||||
var httpApiFlagName = "http.api"
|
||||
|
||||
func Initialize(ctx core.Context, loader core.PluginLoader, logger core.Logger) {
|
||||
pl = loader
|
||||
events = pl.GetFeed()
|
||||
log = logger
|
||||
v := ctx.String(httpApiFlagName)
|
||||
if v != "" {
|
||||
ctx.Set(httpApiFlagName, v+",plugeth")
|
||||
} else {
|
||||
ctx.Set(httpApiFlagName, "eth,net,web3,plugeth")
|
||||
log.Info("Loaded consensus engine plugin")
|
||||
}
|
||||
}
|
||||
|
||||
type engine struct {
|
||||
}
|
||||
|
||||
func (e *engine) Author(header *types.Header) (core.Address, error) {
|
||||
return header.Coinbase, nil
|
||||
}
|
||||
func (e *engine) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error {
|
||||
return nil
|
||||
}
|
||||
func (e *engine) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
|
||||
quit := make(chan struct{})
|
||||
err := make(chan error)
|
||||
go func () {
|
||||
for i, h := range headers {
|
||||
select {
|
||||
case <-quit:
|
||||
return
|
||||
case err<- e.VerifyHeader(chain, h, seals[i]):
|
||||
}
|
||||
}
|
||||
} ()
|
||||
return quit, err
|
||||
}
|
||||
func (e *engine) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
|
||||
return nil
|
||||
}
|
||||
func (e *engine) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
|
||||
if header.BaseFee == nil {
|
||||
header.BaseFee = new(big.Int)
|
||||
|
||||
}
|
||||
header.Difficulty = new(big.Int).SetUint64(123456789)
|
||||
header.UncleHash = core.HexToHash("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")
|
||||
return nil
|
||||
}
|
||||
func (e *engine) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state core.RWStateDB, txs []*types.Transaction,uncles []*types.Header, withdrawals []*types.Withdrawal) {
|
||||
}
|
||||
func (e *engine) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state core.RWStateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) {
|
||||
if header.BaseFee == nil {
|
||||
header.BaseFee = new(big.Int)
|
||||
|
||||
}
|
||||
header.Root = state.IntermediateRoot(false)
|
||||
|
||||
//hasher := hasher.NewStackTrie(nil)
|
||||
hasher := types.TrieHasher(nil)
|
||||
block := types.NewBlockWithWithdrawals(header, txs, uncles, receipts, withdrawals, hasher)
|
||||
return block, nil
|
||||
|
||||
}
|
||||
func (e *engine) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
|
||||
if len(block.Transactions()) == 0 {
|
||||
return errors.New("sealing paused while waiting for transactions")
|
||||
}
|
||||
go func () {
|
||||
results <- block
|
||||
close(results)
|
||||
} ()
|
||||
// TO DO: the stop channel will need to be addressed in a non test case scenerio
|
||||
return nil
|
||||
}
|
||||
func (e *engine) SealHash(header *types.Header) core.Hash {
|
||||
return header.Hash()
|
||||
}
|
||||
func (e *engine) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int {
|
||||
return new(big.Int).SetUint64(uint64(123456789))
|
||||
}
|
||||
func (e *engine) APIs(chain consensus.ChainHeaderReader) []core.API {
|
||||
return []core.API{}
|
||||
}
|
||||
func (e *engine) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateEngine(chainConfig *params.ChainConfig, db restricted.Database) consensus.Engine {
|
||||
createEngineCalled = true
|
||||
return &engine{}
|
||||
}
|
||||
|
815
plugins/test-plugin/genesis.go
Normal file
815
plugins/test-plugin/genesis.go
Normal file
@ -0,0 +1,815 @@
|
||||
package main
|
||||
|
||||
func GenesisBlock() []byte {
|
||||
return []byte(`{
|
||||
"config": {
|
||||
"chainId": 6448,
|
||||
"homesteadBlock": 0,
|
||||
"eip150Block": 0,
|
||||
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"eip155Block": 0,
|
||||
"eip158Block": 0,
|
||||
"byzantiumBlock": 0,
|
||||
"constantinopleBlock": 0,
|
||||
"petersburgBlock": 0,
|
||||
"istanbulBlock": 0,
|
||||
"berlinBlock" : 0,
|
||||
"londonBlock": 0,
|
||||
"mergeNetsplitBlock": 0,
|
||||
"shanghaiTime": 0,
|
||||
"clique": {
|
||||
"period": 5,
|
||||
"epoch": 30000
|
||||
}
|
||||
},
|
||||
"nonce": "0x0",
|
||||
"timestamp": "0x603e6caa",
|
||||
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000f2c207111cb6ef761e439e56b25c7c99ac026a010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"gasLimit": "0x47b760",
|
||||
"difficulty": "0x1",
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase": "0x0000000000000000000000000000000000000000",
|
||||
"alloc": {
|
||||
"0000000000000000000000000000000000000000": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000001": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000002": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000003": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000004": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000005": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000006": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000007": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000008": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000009": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000010": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000011": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000012": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000013": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000014": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000015": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000016": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000017": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000018": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000019": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000020": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000021": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000022": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000023": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000024": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000025": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000026": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000027": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000028": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000029": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000030": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000031": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000032": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000033": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000034": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000035": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000036": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000037": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000038": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000039": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000040": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000041": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000042": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000043": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000044": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000045": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000046": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000047": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000048": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000049": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000050": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000051": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000052": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000053": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000054": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000055": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000056": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000057": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000058": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000059": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000060": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000061": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000062": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000063": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000064": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000065": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000066": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000067": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000068": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000069": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000070": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000071": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000072": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000073": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000074": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000075": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000076": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000077": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000078": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000079": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000080": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000081": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000082": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000083": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000084": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000085": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000086": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000087": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000088": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000089": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000090": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000091": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000092": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000093": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000094": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000095": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000096": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000097": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000098": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000099": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000aa": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ab": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ac": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ad": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ae": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000af": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ba": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000bb": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000bc": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000bd": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000be": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000bf": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ca": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000cb": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000cc": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000cd": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ce": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000cf": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000da": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000db": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000dc": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000dd": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000de": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000df": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ea": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000eb": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ec": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ed": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ee": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ef": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000fa": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000fb": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000fc": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000fd": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000fe": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ff": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"2cb2e3bdb066a83a7f1191eef1697da51793f631": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"4204477bf7fce868e761caaba991ffc607717dbf": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"f2c207111cb6ef761e439e56b25c7c99ac026a01": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
"number": "0x0",
|
||||
"gasUsed": "0x0",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}`)
|
||||
}
|
305
plugins/test-plugin/hooks.go
Normal file
305
plugins/test-plugin/hooks.go
Normal file
@ -0,0 +1,305 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
"math/big"
|
||||
"sync"
|
||||
|
||||
"github.com/openrelayxyz/plugeth-utils/core"
|
||||
"github.com/openrelayxyz/plugeth-utils/restricted"
|
||||
|
||||
)
|
||||
|
||||
var apis []core.API
|
||||
|
||||
type engineService struct {
|
||||
backend core.Backend
|
||||
stack core.Node
|
||||
}
|
||||
|
||||
// cmd/geth/
|
||||
|
||||
func GetAPIs(stack core.Node, backend core.Backend) []core.API {
|
||||
// GetAPIs is covered by virtue of the plugeth_captureShutdown method functioning.
|
||||
apis = []core.API{
|
||||
{
|
||||
Namespace: "plugeth",
|
||||
Version: "1.0",
|
||||
Service: &engineService{backend, stack},
|
||||
Public: true,
|
||||
},
|
||||
{
|
||||
Namespace: "plugeth",
|
||||
Version: "1.0",
|
||||
Service: &LiveTracerResult{},
|
||||
Public: true,
|
||||
},
|
||||
}
|
||||
return apis
|
||||
}
|
||||
|
||||
func InitializeNode(stack core.Node, b restricted.Backend) {
|
||||
go func() {
|
||||
m := map[string]struct{}{
|
||||
"InitializeNode":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}()
|
||||
}
|
||||
|
||||
// func OnShutdown(){
|
||||
// this injection is covered by another test in this package. See documentation for details.
|
||||
// }
|
||||
|
||||
// cmd/utils/
|
||||
|
||||
func SetDefaultDataDir(arg string) string {
|
||||
m := map[string]struct{}{
|
||||
"SetDefaultDataDir":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
return "test"
|
||||
}
|
||||
|
||||
func SetBootstrapNodes() []string {
|
||||
m := map[string]struct{}{
|
||||
"SetBootstrapNodes":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetNetworkId() *uint64 {
|
||||
m := map[string]struct{}{
|
||||
"SetNetworkId":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetETHDiscoveryURLs(arg bool) []string {
|
||||
m := map[string]struct{}{
|
||||
"SetETHDiscoveryURLs":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetSnapDiscoveryURLs() []string {
|
||||
m := map[string]struct{}{
|
||||
"SetSnapDiscoveryURLs":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
return nil
|
||||
}
|
||||
|
||||
// core/
|
||||
|
||||
|
||||
func PreProcessBlock(hash core.Hash, number uint64, encoded []byte) {
|
||||
m := map[string]struct{}{
|
||||
"PreProcessBlock":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
|
||||
func PreProcessTransaction(txBytes []byte, txHash, blockHash core.Hash, i int) {
|
||||
m := map[string]struct{}{
|
||||
"PreProcessTransaction":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
|
||||
func BlockProcessingError(tx core.Hash, block core.Hash, err error) {
|
||||
// this injection is covered by a stand alone test: plugeth_injection_test.go in the core/ package.
|
||||
}
|
||||
|
||||
func PostProcessTransaction(tx core.Hash, block core.Hash, i int, receipt []byte) {
|
||||
m := map[string]struct{}{
|
||||
"PostProcessTransaction":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
|
||||
func PostProcessBlock(block core.Hash) {
|
||||
m := map[string]struct{}{
|
||||
"PostProcessBlock":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
|
||||
func NewHead(block []byte, hash core.Hash, logs [][]byte, td *big.Int) {
|
||||
m := map[string]struct{}{
|
||||
"NewHead":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
|
||||
func NewSideBlock(block []byte, hash core.Hash, logs [][]byte) { // beyond the scope of the test at this time
|
||||
// this injection is covered by a stand alone test: plugeth_injection_test.go in the core/ package.
|
||||
}
|
||||
|
||||
func Reorg(commonBlock core.Hash, oldChain, newChain []core.Hash) { // beyond the scope of the test at this time
|
||||
// this injection is covered by a stand alone test: plugeth_injection_test.go in the core/ package.
|
||||
}
|
||||
|
||||
func SetTrieFlushIntervalClone(duration time.Duration) time.Duration {
|
||||
m := map[string]struct{}{
|
||||
"SetTrieFlushIntervalClone":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
return duration
|
||||
}
|
||||
|
||||
// core/forkid/
|
||||
|
||||
var onceZero sync.Once
|
||||
|
||||
func ForkIDs(byBlock, byTime []uint64) ([]uint64, []uint64) {
|
||||
go func() {
|
||||
onceZero.Do(func() {
|
||||
m := map[string]struct{}{
|
||||
"ForkIDs":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
})
|
||||
}()
|
||||
|
||||
return byBlock, byTime
|
||||
}
|
||||
|
||||
// core/rawdb/
|
||||
|
||||
func ModifyAncients(index uint64, freezerUpdate map[string]struct{}) {
|
||||
// this injection is covered by a stand alone test: plugeth_injection_test.go in the core/rawdb package.
|
||||
}
|
||||
|
||||
func AppendAncient(number uint64, hash, header, body, receipts, td []byte) {
|
||||
// this injection is covered by a stand alone test: plugeth_injection_test.go in the core/rawdb package.
|
||||
}
|
||||
|
||||
// core/state/
|
||||
|
||||
func StateUpdate(blockRoot core.Hash, parentRoot core.Hash, coreDestructs map[core.Hash]struct{}, coreAccounts map[core.Hash][]byte, coreStorage map[core.Hash]map[core.Hash][]byte, coreCode map[core.Hash][]byte) {
|
||||
m := map[string]struct{}{
|
||||
"StateUpdate":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
|
||||
// core/vm/
|
||||
|
||||
func OpCodeSelect() []int {
|
||||
m := map[string]struct{}{
|
||||
"OpCodeSelect":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
return nil
|
||||
}
|
||||
|
||||
// eth/ethconfig
|
||||
|
||||
func pseudoCreateEngine() {
|
||||
if createEngineCalled {
|
||||
m := map[string]struct{}{
|
||||
"CreateEngine":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
}
|
||||
|
||||
// rpc/
|
||||
|
||||
|
||||
func GetRPCCalls(method string, id string, params string) {
|
||||
m := map[string]struct{}{
|
||||
"GetRPCCalls":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
|
||||
var onceOne sync.Once
|
||||
|
||||
func RPCSubscriptionTest() {
|
||||
go func() {
|
||||
onceOne.Do(func() {
|
||||
m := map[string]struct{}{
|
||||
"RPCSubscriptionTest":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
})
|
||||
}()
|
||||
}
|
||||
|
||||
// trie/
|
||||
|
||||
// func PreTrieCommit(node core.Hash) {
|
||||
// this injection is covered by another test in this package. See documentation for details.
|
||||
// }
|
||||
|
||||
// func PostTrieCommit(node core.Hash) {
|
||||
// this injection is covered by another test in this package. See documentation for details.
|
||||
// }
|
||||
|
||||
// params/
|
||||
|
||||
func Is1559(*big.Int) bool { // while this hook resides in params the injections are in consensus/misc/ (2), and core/ (2)
|
||||
m := map[string]struct{}{
|
||||
"Is1559":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
return true
|
||||
}
|
||||
|
||||
func Is160(num *big.Int) bool {
|
||||
m := map[string]struct{}{
|
||||
"PluginEIPCheck":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
return true
|
||||
}
|
||||
|
||||
var plugins map[string]struct{} = map[string]struct{}{
|
||||
"InitializeNode":struct{}{},
|
||||
"CreateEngine":struct{}{},
|
||||
"OnShutdown": struct{}{},
|
||||
"SetTrieFlushIntervalClone":struct{}{},
|
||||
"StateUpdate": struct{}{},
|
||||
"PreProcessBlock": struct{}{},
|
||||
"PreProcessTransaction": struct{}{},
|
||||
"PostProcessTransaction": struct{}{},
|
||||
"PostProcessBlock": struct{}{},
|
||||
"NewHead": struct{}{},
|
||||
"StandardCaptureStart": struct{}{},
|
||||
"StandardCaptureState": struct{}{},
|
||||
"StandardCaptureFault": struct{}{},
|
||||
"StandardCaptureEnter": struct{}{},
|
||||
"StandardCaptureExit": struct{}{},
|
||||
"StandardCaptureEnd": struct{}{},
|
||||
"StandardTracerResult": struct{}{},
|
||||
"GetRPCCalls": struct{}{},
|
||||
"RPCSubscriptionTest": struct{}{},
|
||||
"LivePreProcessBlock": struct{}{},
|
||||
"LivePreProcessTransaction": struct{}{},
|
||||
"LivePostProcessTransaction": struct{}{},
|
||||
"LivePostProcessBlock": struct{}{},
|
||||
"LiveCaptureStart": struct{}{},
|
||||
"LiveCaptureState": struct{}{},
|
||||
"LiveCaptureEnd": struct{}{},
|
||||
"PreTrieCommit": struct{}{},
|
||||
"PostTrieCommit": struct{}{},
|
||||
// "LiveCaptureFault": struct{}{},
|
||||
// "LiveCaptureEnter": struct{}{},
|
||||
// "LiveCaptureExit": struct{}{},
|
||||
// "LiveTracerResult": struct{}{},
|
||||
"SetDefaultDataDir":struct{}{},
|
||||
"SetBootstrapNodes":struct{}{},
|
||||
"SetNetworkId":struct{}{},
|
||||
"SetETHDiscoveryURLs": struct{}{},
|
||||
"SetSnapDiscoveryURLs": struct{}{},
|
||||
"ForkIDs": struct{}{},
|
||||
"OpCodeSelect":struct{}{},
|
||||
"Is1559":struct{}{},
|
||||
"PluginEIPCheck":struct{}{},
|
||||
}
|
||||
|
157
plugins/test-plugin/live_tracer.go
Normal file
157
plugins/test-plugin/live_tracer.go
Normal file
@ -0,0 +1,157 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/openrelayxyz/plugeth-utils/core"
|
||||
"github.com/openrelayxyz/plugeth-utils/restricted/hexutil"
|
||||
)
|
||||
|
||||
type LiveTracerResult struct {
|
||||
CallStack []CallStack
|
||||
Results []CallStack
|
||||
}
|
||||
|
||||
type CallStack struct {
|
||||
Type string `json:"type"`
|
||||
From core.Address `json:"from"`
|
||||
To core.Address `json:"to"`
|
||||
Value *big.Int `json:"value,omitempty"`
|
||||
Gas hexutil.Uint64 `json:"gas"`
|
||||
GasUsed hexutil.Uint64 `json:"gasUsed"`
|
||||
Input hexutil.Bytes `json:"input"`
|
||||
Output hexutil.Bytes `json:"output"`
|
||||
Time string `json:"time,omitempty"`
|
||||
Calls []CallStack `json:"calls,omitempty"`
|
||||
Results []CallStack `json:"results,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (t *LiveTracerResult) TraceBlock(ctx context.Context) (<-chan []CallStack, error) {
|
||||
subch := make(chan []CallStack, 1000)
|
||||
rtrnch := make(chan []CallStack, 1000)
|
||||
go func() {
|
||||
log.Info("Subscription Block Tracer setup")
|
||||
sub := events.Subscribe(subch)
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
sub.Unsubscribe()
|
||||
close(subch)
|
||||
close(rtrnch)
|
||||
return
|
||||
case t := <-subch:
|
||||
rtrnch <- t
|
||||
case <-sub.Err():
|
||||
sub.Unsubscribe()
|
||||
close(subch)
|
||||
close(rtrnch)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
return rtrnch, nil
|
||||
}
|
||||
|
||||
func GetLiveTracer(core.Hash, core.StateDB) core.BlockTracer {
|
||||
return &LiveTracerResult{}
|
||||
}
|
||||
|
||||
func (r *LiveTracerResult) PreProcessBlock(hash core.Hash, number uint64, encoded []byte) {
|
||||
m := map[string]struct{}{
|
||||
"LivePreProcessBlock":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
r.Results = []CallStack{}
|
||||
}
|
||||
|
||||
func (r *LiveTracerResult) PreProcessTransaction(tx core.Hash, block core.Hash, i int) {
|
||||
m := map[string]struct{}{
|
||||
"LivePreProcessTransaction":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
|
||||
func (r *LiveTracerResult) BlockProcessingError(tx core.Hash, block core.Hash, err error) {
|
||||
m := map[string]struct{}{
|
||||
"LiveBlockProcessingError":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
|
||||
func (r *LiveTracerResult) PostProcessTransaction(tx core.Hash, block core.Hash, i int, receipt []byte) {
|
||||
m := map[string]struct{}{
|
||||
"LivePostProcessTransaction":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
|
||||
func (r *LiveTracerResult) PostProcessBlock(block core.Hash) {
|
||||
m := map[string]struct{}{
|
||||
"LivePostProcessBlock":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
if len(r.Results) > 0 {
|
||||
events.Send(r.Results)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *LiveTracerResult) CaptureStart(from core.Address, to core.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||
r.CallStack = []CallStack{}
|
||||
m := map[string]struct{}{
|
||||
"LiveCaptureStart":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
func (r *LiveTracerResult) CaptureState(pc uint64, op core.OpCode, gas, cost uint64, scope core.ScopeContext, rData []byte, depth int, err error) {
|
||||
m := map[string]struct{}{
|
||||
"LiveCaptureState":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
|
||||
func (r *LiveTracerResult) CaptureFault(pc uint64, op core.OpCode, gas, cost uint64, scope core.ScopeContext, depth int, err error) {
|
||||
// this method is not covered by tests at this time
|
||||
// m := map[string]struct{}{
|
||||
// "LiveCaptureFault":struct{}{},
|
||||
// }
|
||||
// hookChan <- m
|
||||
}
|
||||
|
||||
func (r *LiveTracerResult) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {
|
||||
m := map[string]struct{}{
|
||||
"LiveCaptureEnd":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
if len(r.CallStack) > 0 {
|
||||
r.Results = append(r.CallStack)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *LiveTracerResult) CaptureEnter(typ core.OpCode, from core.Address, to core.Address, input []byte, gas uint64, value *big.Int) {
|
||||
// this method is not covered by tests at this time
|
||||
// m := map[string]struct{}{
|
||||
// "LiveCaptureEnter":struct{}{},
|
||||
// }
|
||||
// hookChan <- m
|
||||
}
|
||||
|
||||
func (r *LiveTracerResult) CaptureExit(output []byte, gasUsed uint64, err error) {
|
||||
// this method is not covered by tests at this time
|
||||
// m := map[string]struct{}{
|
||||
// "LiveCaptureExit":struct{}{},
|
||||
// }
|
||||
// hookChan <- m
|
||||
}
|
||||
|
||||
func (r *LiveTracerResult) Result() (interface{}, error) {
|
||||
// this method is not covered by tests at this time
|
||||
// m := map[string]struct{}{
|
||||
// "LiveTracerResult":struct{}{},
|
||||
// }
|
||||
// hookChan <- m
|
||||
return "", nil
|
||||
}
|
||||
|
320
plugins/test-plugin/main.go
Normal file
320
plugins/test-plugin/main.go
Normal file
@ -0,0 +1,320 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"time"
|
||||
"os"
|
||||
"bytes"
|
||||
|
||||
"github.com/openrelayxyz/plugeth-utils/core"
|
||||
"github.com/openrelayxyz/plugeth-utils/restricted/hexutil"
|
||||
"github.com/openrelayxyz/plugeth-utils/restricted/crypto"
|
||||
)
|
||||
|
||||
var hookChan chan map[string]struct{} = make(chan map[string]struct{}, 10)
|
||||
var quit chan string = make(chan string)
|
||||
|
||||
func (service *engineService) CaptureShutdown(ctx context.Context) {
|
||||
m := map[string]struct{}{
|
||||
"OnShutdown":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
|
||||
func (service *engineService) CapturePreTrieCommit(ctx context.Context) {
|
||||
m := map[string]struct{}{
|
||||
"PreTrieCommit":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
|
||||
func (service *engineService) CapturePostTrieCommit(ctx context.Context) {
|
||||
m := map[string]struct{}{
|
||||
"PostTrieCommit":struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
|
||||
func BlockChain() {
|
||||
|
||||
go func () {
|
||||
for {
|
||||
select {
|
||||
case <- quit:
|
||||
if len(plugins) > 0 {
|
||||
log.Error("Exit with Error, Plugins map not empty", "Plugins not called", plugins)
|
||||
os.Exit(1)
|
||||
} else {
|
||||
log.Info("Exit without error")
|
||||
os.Exit(0)
|
||||
}
|
||||
case m := <- hookChan:
|
||||
var ok bool
|
||||
f := func(key string) bool {_, ok = m[key]; return ok}
|
||||
switch {
|
||||
case f("InitializeNode"):
|
||||
delete(plugins, "InitializeNode")
|
||||
case f("CreateEngine"):
|
||||
delete(plugins, "CreateEngine")
|
||||
case f("OnShutdown"):
|
||||
delete(plugins, "OnShutdown")
|
||||
case f("StateUpdate"):
|
||||
delete(plugins, "StateUpdate")
|
||||
case f("PreProcessBlock"):
|
||||
delete(plugins, "PreProcessBlock")
|
||||
case f("PreProcessTransaction"):
|
||||
delete(plugins, "PreProcessTransaction")
|
||||
case f("PostProcessTransaction"):
|
||||
delete(plugins, "PostProcessTransaction")
|
||||
case f("PostProcessBlock"):
|
||||
delete(plugins, "PostProcessBlock")
|
||||
case f("NewHead"):
|
||||
delete(plugins, "NewHead")
|
||||
case f("LivePreProcessBlock"):
|
||||
delete(plugins, "LivePreProcessBlock")
|
||||
case f("LivePreProcessTransaction"):
|
||||
delete(plugins, "LivePreProcessTransaction")
|
||||
case f("LivePostProcessTransaction"):
|
||||
delete(plugins, "LivePostProcessTransaction")
|
||||
case f("LivePostProcessBlock"):
|
||||
delete(plugins, "LivePostProcessBlock")
|
||||
case f("GetRPCCalls"):
|
||||
delete(plugins, "GetRPCCalls")
|
||||
case f("RPCSubscriptionTest"):
|
||||
delete(plugins, "RPCSubscriptionTest")
|
||||
case f("SetTrieFlushIntervalClone"):
|
||||
delete(plugins, "SetTrieFlushIntervalClone")
|
||||
case f("StandardCaptureStart"):
|
||||
delete(plugins, "StandardCaptureStart")
|
||||
case f("StandardCaptureState"):
|
||||
delete(plugins, "StandardCaptureState")
|
||||
case f("StandardCaptureFault"):
|
||||
delete(plugins, "StandardCaptureFault")
|
||||
case f("StandardCaptureEnter"):
|
||||
delete(plugins, "StandardCaptureEnter")
|
||||
case f("StandardCaptureExit"):
|
||||
delete(plugins, "StandardCaptureExit")
|
||||
case f("StandardCaptureEnd"):
|
||||
delete(plugins, "StandardCaptureEnd")
|
||||
case f("StandardTracerResult"):
|
||||
delete(plugins, "StandardTracerResult")
|
||||
case f("LivePreProcessBlock"):
|
||||
delete(plugins, "LivePreProcessBlock")
|
||||
case f("LiveCaptureStart"):
|
||||
delete(plugins, "LiveCaptureStart")
|
||||
case f("LiveCaptureState"):
|
||||
delete(plugins, "LiveCaptureState")
|
||||
case f("LiveCaptureEnd"):
|
||||
delete(plugins, "LiveCaptureEnd")
|
||||
case f("PreTrieCommit"):
|
||||
delete(plugins, "PreTrieCommit")
|
||||
case f("PostTrieCommit"):
|
||||
delete(plugins, "PostTrieCommit")
|
||||
// These methods are not covered by tests at this time
|
||||
// case f("LiveCaptureFault"):
|
||||
// delete(plugins, "LiveCaptureFault")
|
||||
// case f("LiveCaptureEnter"):
|
||||
// delete(plugins, "LiveCaptureEnter")
|
||||
// case f("LiveCaptureExit"):
|
||||
// delete(plugins, "LiveCaptureExit")
|
||||
// case f("LiveTracerResult"):
|
||||
// delete(plugins, "LiveTracerResult")
|
||||
case f("SetDefaultDataDir"):
|
||||
delete(plugins, "SetDefaultDataDir")
|
||||
case f("SetBootstrapNodes"):
|
||||
delete(plugins, "SetBootstrapNodes")
|
||||
case f("SetNetworkId"):
|
||||
delete(plugins, "SetNetworkId")
|
||||
case f("SetETHDiscoveryURLs"):
|
||||
delete(plugins, "SetETHDiscoveryURLs")
|
||||
case f("SetSnapDiscoveryURLs"):
|
||||
delete(plugins, "SetSnapDiscoveryURLs")
|
||||
case f("ForkIDs"):
|
||||
delete(plugins, "ForkIDs")
|
||||
case f("OpCodeSelect"):
|
||||
delete(plugins, "OpCodeSelect")
|
||||
case f("Is1559"):
|
||||
delete(plugins, "Is1559")
|
||||
case f("PluginEIPCheck"):
|
||||
delete(plugins, "PluginEIPCheck")
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
pseudoCreateEngine()
|
||||
txFactory()
|
||||
txTracer()
|
||||
}
|
||||
|
||||
var t0 core.Hash
|
||||
var t1 core.Hash
|
||||
var t2 core.Hash
|
||||
var t3 core.Hash
|
||||
var coinBase *core.Address
|
||||
|
||||
func txFactory() {
|
||||
|
||||
cl := apis[0].Service.(*engineService).stack
|
||||
client, err := cl.Attach()
|
||||
if err != nil {
|
||||
log.Error("Error connecting with client txFactory", "err", err)
|
||||
}
|
||||
|
||||
err = client.Call(&coinBase, "eth_coinbase")
|
||||
if err != nil {
|
||||
log.Error("failed to call eth_coinbase txFactory", "err", err)
|
||||
}
|
||||
|
||||
var peerCount hexutil.Uint64
|
||||
for peerCount == 0 {
|
||||
err = client.Call(&peerCount, "net_peerCount")
|
||||
if err != nil {
|
||||
log.Error("failed to call net_peerCount", "err", err)
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
tx0_params := map[string]interface{}{
|
||||
"from": coinBase,
|
||||
"to": coinBase,
|
||||
"value": (*hexutil.Big)(big.NewInt(1)),
|
||||
}
|
||||
|
||||
err = client.Call(&t0, "eth_sendTransaction", tx0_params)
|
||||
if err != nil {
|
||||
log.Error("transaction zero failed", "err", err)
|
||||
}
|
||||
|
||||
tx1_params := map[string]interface{}{
|
||||
"input": "0x60018080600053f3",
|
||||
"from": coinBase,
|
||||
}
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
err = client.Call(&t1, "eth_sendTransaction", tx1_params)
|
||||
if err != nil {
|
||||
log.Error("transaction one failed", "err", err)
|
||||
}
|
||||
|
||||
tx2_params := map[string]interface{}{
|
||||
"input": "0x61520873000000000000000000000000000000000000000060006000600060006000f1",
|
||||
"from": coinBase,
|
||||
}
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
err = client.Call(&t2, "eth_sendTransaction", tx2_params)
|
||||
if err != nil {
|
||||
log.Error("transaction two failed", "err", err)
|
||||
}
|
||||
|
||||
genericArg := map[string]interface{}{
|
||||
"input": "0x608060405234801561001057600080fd5b5061011a806100206000396000f3fe608060405234801561001057600080fd5b50600436106100375760003560e01c806360fe47b11461003c5780636d4ce63c1461005d57610037565b600080fd5b61004561007e565b60405161005291906100c5565b60405180910390f35b61007c6004803603602081101561007a57600080fd5b50356100c2565b6040516020018083838082843780820191505050505b565b005b6100946100c4565b60405161005291906100bf565b6100d1565b60405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e11b815260040161010060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146101e557600080fd5b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e7ba30df6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156101ae57600080fd5b505af11580156101c2573d6000803e3d6000fd5b50505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461029157600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fdacd5766040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156102f957600080fd5b505af115801561030d573d6000803e3d6000fd5b50505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168156fea2646970667358221220d4f2763f3a0ae2826cc9ef37a65ff0c14d7a3aafe8d1636ff99f72e2f705413d64736f6c634300060c0033",
|
||||
"from": coinBase,
|
||||
}
|
||||
|
||||
for i := 0; i < 10; i ++ {
|
||||
time.Sleep(2 * time.Second)
|
||||
err = client.Call(&t3, "eth_sendTransaction", genericArg)
|
||||
if err != nil {
|
||||
log.Error("looped transaction failed on index", "i", i, "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type TraceConfig struct {
|
||||
Tracer *string
|
||||
}
|
||||
|
||||
func txTracer() {
|
||||
|
||||
cl := apis[0].Service.(*engineService).stack
|
||||
client, err := cl.Attach()
|
||||
if err != nil {
|
||||
log.Error("Error connecting with client block factory")
|
||||
}
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
tr := "testTracer"
|
||||
t := TraceConfig{
|
||||
Tracer: &tr,
|
||||
}
|
||||
|
||||
var trResult interface{}
|
||||
err = client.Call(&trResult, "debug_traceTransaction", t0, t)
|
||||
if err != nil {
|
||||
log.Error("debug_traceTransaction failed", "err", err)
|
||||
}
|
||||
|
||||
testGetContractCode(t3)
|
||||
|
||||
debugArg0 := map[string]interface{}{
|
||||
"input": "0x60006000fd",
|
||||
"from": coinBase,
|
||||
}
|
||||
|
||||
var trResult0 interface{}
|
||||
err = client.Call(&trResult0, "debug_traceCall", debugArg0, "latest", t)
|
||||
if err != nil {
|
||||
log.Error("debug_traceCall 0 failed", "err", err)
|
||||
}
|
||||
|
||||
debugArg1 := map[string]interface{}{
|
||||
"input": "0x61520873000000000000000000000000000000000000000060006000600060006000f1",
|
||||
"from": coinBase,
|
||||
}
|
||||
|
||||
var trResult1 interface{}
|
||||
err = client.Call(&trResult1, "debug_traceCall", debugArg1, "latest", t)
|
||||
|
||||
final := map[string]interface{}{
|
||||
"input": "0x61520873000000000000000000000000000000000000000060006000600060006000f1",
|
||||
"from": coinBase,
|
||||
}
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
err = client.Call(&t3, "eth_sendTransaction", final)
|
||||
if err != nil {
|
||||
log.Error("contract call failed", "err", err)
|
||||
}
|
||||
|
||||
quit <- "quit"
|
||||
|
||||
}
|
||||
|
||||
func testGetContractCode(hash core.Hash) {
|
||||
|
||||
cl := apis[0].Service.(*engineService).stack
|
||||
client, err := cl.Attach()
|
||||
if err != nil {
|
||||
log.Error("Error connecting with client testGetContractCode")
|
||||
}
|
||||
|
||||
receipt := map[string]interface{}{}
|
||||
err = client.Call(&receipt, "eth_getTransactionReceipt", hash)
|
||||
if err != nil {
|
||||
log.Error("Error calling getTransactionReciepts, testGetContractCode", "err", err)
|
||||
}
|
||||
|
||||
var controlCode hexutil.Bytes
|
||||
err = client.Call(&controlCode, "eth_getCode", receipt["contractAddress"], receipt["blockNumber"])
|
||||
if err != nil {
|
||||
log.Error("Error calling getCode, testGetContractCode", "err", err)
|
||||
}
|
||||
|
||||
codeHash := crypto.Keccak256Hash(controlCode)
|
||||
|
||||
testCode, err := apis[0].Service.(*engineService).backend.GetContractCode(codeHash)
|
||||
if err != nil {
|
||||
log.Error("Error calling GetContractCode", "err", err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(testCode, controlCode) {
|
||||
|
||||
log.Error("Exit with error, return value from GetContractCode is divergent from control value")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
132
plugins/test-plugin/shutdown.go
Normal file
132
plugins/test-plugin/shutdown.go
Normal file
@ -0,0 +1,132 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/openrelayxyz/plugeth-utils/core"
|
||||
)
|
||||
|
||||
var globalId int64
|
||||
|
||||
var client = &http.Client{Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).DialContext,
|
||||
MaxIdleConnsPerHost: 16,
|
||||
MaxIdleConns: 16,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
}}
|
||||
|
||||
type Call struct {
|
||||
Version string `json:"jsonrpc"`
|
||||
ID json.RawMessage `json:"id"`
|
||||
Method string `json:"method"`
|
||||
Params []json.RawMessage `json:"params"`
|
||||
}
|
||||
|
||||
func toRawMessages(items ...interface{}) ([]json.RawMessage, error) {
|
||||
result := make([]json.RawMessage, len(items))
|
||||
for i, item := range items {
|
||||
d, err := json.Marshal(item)
|
||||
if err != nil { return nil, err }
|
||||
result[i] = (json.RawMessage)(d)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func PreTrieCommit(node core.Hash) {
|
||||
|
||||
id, err := toRawMessages(atomic.AddInt64(&globalId, 1))
|
||||
if err != nil {
|
||||
log.Error("json marshalling error, id", "err", err)
|
||||
}
|
||||
|
||||
call := &Call{
|
||||
Version: "2.0",
|
||||
ID : id[0],
|
||||
Method: "plugeth_capturePreTrieCommit",
|
||||
Params: []json.RawMessage{},
|
||||
}
|
||||
|
||||
backendURL := "http://127.0.0.1:9546"
|
||||
|
||||
callBytes, _ := json.Marshal(call)
|
||||
|
||||
request, _ := http.NewRequestWithContext(context.Background(), "POST", backendURL, bytes.NewReader(callBytes))
|
||||
request.Header.Add("Content-Type", "application/json")
|
||||
|
||||
_, err = client.Do(request)
|
||||
|
||||
if err != nil {
|
||||
log.Error("Error calling passive node from PreTrieCommit", "err", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func PostTrieCommit(node core.Hash) {
|
||||
|
||||
id, err := toRawMessages(atomic.AddInt64(&globalId, 1))
|
||||
if err != nil {
|
||||
log.Error("json marshalling error, id", "err", err)
|
||||
}
|
||||
|
||||
call := &Call{
|
||||
Version: "2.0",
|
||||
ID : id[0],
|
||||
Method: "plugeth_capturePostTrieCommit",
|
||||
Params: []json.RawMessage{},
|
||||
}
|
||||
|
||||
backendURL := "http://127.0.0.1:9546"
|
||||
|
||||
callBytes, _ := json.Marshal(call)
|
||||
|
||||
request, _ := http.NewRequestWithContext(context.Background(), "POST", backendURL, bytes.NewReader(callBytes))
|
||||
request.Header.Add("Content-Type", "application/json")
|
||||
|
||||
_, err = client.Do(request)
|
||||
|
||||
if err != nil {
|
||||
log.Error("Error calling passive node from PostTrieCommit", "err", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func OnShutdown() {
|
||||
|
||||
id, err := toRawMessages(atomic.AddInt64(&globalId, 1))
|
||||
if err != nil {
|
||||
log.Error("json marshalling error, id", "err", err)
|
||||
}
|
||||
|
||||
call := &Call{
|
||||
Version: "2.0",
|
||||
ID : id[0],
|
||||
Method: "plugeth_captureShutdown",
|
||||
Params: []json.RawMessage{},
|
||||
}
|
||||
|
||||
backendURL := "http://127.0.0.1:9546"
|
||||
|
||||
callBytes, _ := json.Marshal(call)
|
||||
|
||||
request, _ := http.NewRequestWithContext(context.Background(), "POST", backendURL, bytes.NewReader(callBytes))
|
||||
request.Header.Add("Content-Type", "application/json")
|
||||
|
||||
_, err = client.Do(request)
|
||||
|
||||
if err != nil {
|
||||
log.Error("Error calling passive node from OnShutdown", "err", err)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1 @@
|
||||
{"address":"4204477bf7fce868e761caaba991ffc607717dbf","crypto":{"cipher":"aes-128-ctr","ciphertext":"696c049cb65264a96373f7d9aaed51710fd0ebbc8ac32647d129b76449f75e2b","cipherparams":{"iv":"1ef3f18226b66595ff3c960e97790fa2"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"94a3c3acafb55e9af05585531f0a03ec80a0bc0e9d5898f7ee7441b5d4cb3031"},"mac":"f3df0bb6af2c99da74bf4194e867f49f57b296306e3600a99ec6688a973f06e7"},"id":"c7f4a651-6306-44f2-93f7-ed325e658a62","version":3}
|
@ -0,0 +1 @@
|
||||
{"address":"f2c207111cb6ef761e439e56b25c7c99ac026a01","crypto":{"cipher":"aes-128-ctr","ciphertext":"c0c42fb1896ef33d8502ee89e17dcaea2ac3416ef44ef6670609a3e6cf23d52e","cipherparams":{"iv":"b974baaaab375cb0f01c0aebbd863f64"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"d76ee5cfaf5c399cbdd2647fde4367729cf2b7f4f45191d700b220c8a7472858"},"mac":"fb22367cccb09c87e86e3d4d2e46f3eb3f1abfecbfc8b700a5e4b30b27e8e136"},"id":"71393286-2d91-42ab-83b1-b314aeab344e","version":3}
|
@ -0,0 +1 @@
|
||||
{"address":"2cb2e3bdb066a83a7f1191eef1697da51793f631","crypto":{"cipher":"aes-128-ctr","ciphertext":"9b144d767e7395c0aee0c315037dc7ab20e942ac9e98667e4934ca67210d06ed","cipherparams":{"iv":"fb484a2cab5e9cbaac5a01c4f111c62b"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"d060787b49eaea67d8e9d1c0368965f9d9b5ebc2a0981ca0d126036ceb7b30c9"},"mac":"39c1a4f67ca6855e148e766c79e1fb944433d9fc68c3b0bf64308860cb788563"},"id":"7b7959d7-098a-451d-b178-5cfcdef9e385","version":3}
|
96
plugins/test-plugin/test/config00.toml
Normal file
96
plugins/test-plugin/test/config00.toml
Normal file
@ -0,0 +1,96 @@
|
||||
[Eth]
|
||||
NetworkId = 6448
|
||||
SyncMode = "snap"
|
||||
EthDiscoveryURLs = []
|
||||
SnapDiscoveryURLs = []
|
||||
NoPruning = false
|
||||
NoPrefetch = false
|
||||
TxLookupLimit = 2350000
|
||||
LightPeers = 100
|
||||
DatabaseCache = 512
|
||||
DatabaseFreezer = ""
|
||||
TrieCleanCache = 154
|
||||
TrieCleanCacheJournal = "triecache"
|
||||
TrieCleanCacheRejournal = 3600000000000
|
||||
TrieDirtyCache = 256
|
||||
TrieTimeout = 3600000000000
|
||||
SnapshotCache = 102
|
||||
Preimages = false
|
||||
FilterLogCacheSize = 32
|
||||
EnablePreimageRecording = false
|
||||
RPCGasCap = 50000000
|
||||
RPCEVMTimeout = 5000000000
|
||||
RPCTxFeeCap = 1e+00
|
||||
|
||||
[Eth.Miner]
|
||||
Etherbase = "0xf2c207111cb6ef761e439e56b25c7c99ac026a01"
|
||||
GasFloor = 0
|
||||
GasCeil = 30000000
|
||||
GasPrice = 1000000000
|
||||
Recommit = 2000000000
|
||||
NewPayloadTimeout = 2000000000
|
||||
|
||||
[Eth.TxPool]
|
||||
Locals = []
|
||||
NoLocals = false
|
||||
Journal = "transactions.rlp"
|
||||
Rejournal = 3600000000000
|
||||
PriceLimit = 1
|
||||
PriceBump = 10
|
||||
AccountSlots = 16
|
||||
GlobalSlots = 5120
|
||||
AccountQueue = 64
|
||||
GlobalQueue = 1024
|
||||
Lifetime = 10800000000000
|
||||
|
||||
[Eth.GPO]
|
||||
Blocks = 20
|
||||
Percentile = 60
|
||||
MaxHeaderHistory = 1024
|
||||
MaxBlockHistory = 1024
|
||||
MaxPrice = 500000000000
|
||||
IgnorePrice = 2
|
||||
|
||||
[Node]
|
||||
DataDir = "00"
|
||||
IPCPath = "geth.ipc"
|
||||
HTTPHost = ""
|
||||
HTTPPort = 8545
|
||||
HTTPVirtualHosts = ["localhost"]
|
||||
HTTPModules = ["net", "web3", "eth"]
|
||||
AuthAddr = "localhost"
|
||||
AuthPort = 8552
|
||||
AuthVirtualHosts = ["localhost"]
|
||||
WSHost = ""
|
||||
WSPort = 8546
|
||||
WSModules = ["net", "web3", "eth"]
|
||||
GraphQLVirtualHosts = ["localhost"]
|
||||
|
||||
[Node.P2P]
|
||||
MaxPeers = 50
|
||||
NoDiscovery = true
|
||||
BootstrapNodes = ["enode://d860a01f9722d78051619d1e2351aba3f43f943f6f00718d1b9baa4101932a1f5011f16bb2b1bb35db20d6fe28fa0bf09636d26a87d31de9ec6203eeedb1f666@18.138.108.67:30303", "enode://22a8232c3abc76a16ae9d6c3b164f98775fe226f0917b0ca871128a74a8e9630b458460865bab457221f1d448dd9791d24c4e5d88786180ac185df813a68d4de@3.209.45.79:30303", "enode://8499da03c47d637b20eee24eec3c356c9a2e6148d6fe25ca195c7949ab8ec2c03e3556126b0d7ed644675e78c4318b08691b7b57de10e5f0d40d05b09238fa0a@52.187.207.27:30303", "enode://103858bdb88756c71f15e9b5e09b56dc1be52f0a5021d46301dbbfb7e130029cc9d0d6f73f693bc29b665770fff7da4d34f3c6379fe12721b5d7a0bcb5ca1fc1@191.234.162.198:30303", "enode://715171f50508aba88aecd1250af392a45a330af91d7b90701c436b618c86aaa1589c9184561907bebbb56439b8f8787bc01f49a7c77276c58c1b09822d75e8e8@52.231.165.108:30303", "enode://5d6d7cd20d6da4bb83a1d28cadb5d409b64edf314c0335df658c1a54e32c7c4a7ab7823d57c39b6a757556e68ff1df17c748b698544a55cb488b52479a92b60f@104.42.217.25:30303", "enode://2b252ab6a1d0f971d9722cb839a42cb81db019ba44c08754628ab4a823487071b5695317c8ccd085219c3a03af063495b2f1da8d18218da2d6a82981b45e6ffc@65.108.70.101:30303", "enode://4aeb4ab6c14b23e2c4cfdce879c04b0748a20d8e9b59e25ded2a08143e265c6c25936e74cbc8e641e3312ca288673d91f2f93f8e277de3cfa444ecdaaf982052@157.90.35.166:30303"]
|
||||
BootstrapNodesV5 = ["enr:-KG4QOtcP9X1FbIMOe17QNMKqDxCpm14jcX5tiOE4_TyMrFqbmhPZHK_ZPG2Gxb1GE2xdtodOfx9-cgvNtxnRyHEmC0ghGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQDE8KdiXNlY3AyNTZrMaEDhpehBDbZjM_L9ek699Y7vhUJ-eAdMyQW_Fil522Y0fODdGNwgiMog3VkcIIjKA", "enr:-KG4QDyytgmE4f7AnvW-ZaUOIi9i79qX4JwjRAiXBZCU65wOfBu-3Nb5I7b_Rmg3KCOcZM_C3y5pg7EBU5XGrcLTduQEhGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQ2_DUbiXNlY3AyNTZrMaEDKnz_-ps3UUOfHWVYaskI5kWYO_vtYMGYCQRAR3gHDouDdGNwgiMog3VkcIIjKA", "enr:-Ku4QImhMc1z8yCiNJ1TyUxdcfNucje3BGwEHzodEZUan8PherEo4sF7pPHPSIB1NNuSg5fZy7qFsjmUKs2ea1Whi0EBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQOVphkDqal4QzPMksc5wnpuC3gvSC8AfbFOnZY_On34wIN1ZHCCIyg", "enr:-Ku4QP2xDnEtUXIjzJ_DhlCRN9SN99RYQPJL92TMlSv7U5C1YnYLjwOQHgZIUXw6c-BvRg2Yc2QsZxxoS_pPRVe0yK8Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQMeFF5GrS7UZpAH2Ly84aLK-TyvH-dRo0JM1i8yygH50YN1ZHCCJxA", "enr:-Ku4QPp9z1W4tAO8Ber_NQierYaOStqhDqQdOPY3bB3jDgkjcbk6YrEnVYIiCBbTxuar3CzS528d2iE7TdJsrL-dEKoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQMw5fqqkw2hHC4F5HZZDPsNmPdB1Gi8JPQK7pRc9XHh-oN1ZHCCKvg", "enr:-IS4QLkKqDMy_ExrpOEWa59NiClemOnor-krjp4qoeZwIw2QduPC-q7Kz4u1IOWf3DDbdxqQIgC4fejavBOuUPy-HE4BgmlkgnY0gmlwhCLzAHqJc2VjcDI1NmsxoQLQSJfEAHZApkm5edTCZ_4qps_1k_ub2CxHFxi-gr2JMIN1ZHCCIyg", "enr:-IS4QDAyibHCzYZmIYZCjXwU9BqpotWmv2BsFlIq1V31BwDDMJPFEbox1ijT5c2Ou3kvieOKejxuaCqIcjxBjJ_3j_cBgmlkgnY0gmlwhAMaHiCJc2VjcDI1NmsxoQJIdpj_foZ02MXz4It8xKD7yUHTBx7lVFn3oeRP21KRV4N1ZHCCIyg", "enr:-Ku4QHqVeJ8PPICcWk1vSn_XcSkjOkNiTg6Fmii5j6vUQgvzMc9L1goFnLKgXqBJspJjIsB91LTOleFmyWWrFVATGngBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhAMRHkWJc2VjcDI1NmsxoQKLVXFOhp2uX6jeT0DvvDpPcU8FWMjQdR4wMuORMhpX24N1ZHCCIyg", "enr:-Ku4QG-2_Md3sZIAUebGYT6g0SMskIml77l6yR-M_JXc-UdNHCmHQeOiMLbylPejyJsdAPsTHJyjJB2sYGDLe0dn8uYBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhBLY-NyJc2VjcDI1NmsxoQORcM6e19T1T9gi7jxEZjk_sjVLGFscUNqAY9obgZaxbIN1ZHCCIyg", "enr:-Ku4QPn5eVhcoF1opaFEvg1b6JNFD2rqVkHQ8HApOKK61OIcIXD127bKWgAtbwI7pnxx6cDyk_nI88TrZKQaGMZj0q0Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDayLMaJc2VjcDI1NmsxoQK2sBOLGcUb4AwuYzFuAVCaNHA-dy24UuEKkeFNgCVCsIN1ZHCCIyg", "enr:-Ku4QEWzdnVtXc2Q0ZVigfCGggOVB2Vc1ZCPEc6j21NIFLODSJbvNaef1g4PxhPwl_3kax86YPheFUSLXPRs98vvYsoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDZBrP2Jc2VjcDI1NmsxoQM6jr8Rb1ktLEsVcKAPa08wCsKUmvoQ8khiOl_SLozf9IN1ZHCCIyg"]
|
||||
StaticNodes = ["enode://3a25d05c552af77d4346b82affb6c249c14dc11a9ee08c11b75ca1d05e04b464fa40b1770e3e8dd06b365ff29ba0b24a1f41bef9db4d6004566767b62b19f905@127.0.0.1:64480","enode://56206f2d4d22aacdc89a1d95c0c120437de5ea3bab3ad2bee57a82b3578a0b3af245de80c98e94b8a6c2733e4ae0d5da25fccceb6094132a5c2ab784355f89ef@127.0.0.1:64481","enode://6d5b388dbc3b672606e9731f82bc5ad6443241dd5894e561d272155806d6497770d2e323b011580c661a2e8a40e1f79b017fa5b57ea20a632db95fb90893d04d@127.0.0.1:64482"]
|
||||
TrustedNodes = []
|
||||
ListenAddr = ":64480"
|
||||
DiscAddr = ""
|
||||
EnableMsgEvents = false
|
||||
|
||||
[Node.HTTPTimeouts]
|
||||
ReadTimeout = 30000000000
|
||||
ReadHeaderTimeout = 30000000000
|
||||
WriteTimeout = 30000000000
|
||||
IdleTimeout = 120000000000
|
||||
|
||||
[Metrics]
|
||||
HTTP = "127.0.0.1"
|
||||
Port = 6060
|
||||
InfluxDBEndpoint = "http://localhost:8086"
|
||||
InfluxDBDatabase = "geth"
|
||||
InfluxDBUsername = "test"
|
||||
InfluxDBPassword = "test"
|
||||
InfluxDBTags = "host=localhost"
|
||||
InfluxDBToken = "test"
|
||||
InfluxDBBucket = "geth"
|
||||
InfluxDBOrganization = "geth"
|
94
plugins/test-plugin/test/config01.toml
Normal file
94
plugins/test-plugin/test/config01.toml
Normal file
@ -0,0 +1,94 @@
|
||||
[Eth]
|
||||
NetworkId = 6448
|
||||
SyncMode = "snap"
|
||||
NoPruning = false
|
||||
NoPrefetch = false
|
||||
TxLookupLimit = 2350000
|
||||
LightPeers = 100
|
||||
DatabaseCache = 512
|
||||
DatabaseFreezer = ""
|
||||
TrieCleanCache = 154
|
||||
TrieCleanCacheJournal = "triecache"
|
||||
TrieCleanCacheRejournal = 3600000000000
|
||||
TrieDirtyCache = 256
|
||||
TrieTimeout = 3600000000000
|
||||
SnapshotCache = 102
|
||||
Preimages = false
|
||||
FilterLogCacheSize = 32
|
||||
EnablePreimageRecording = false
|
||||
RPCGasCap = 50000000
|
||||
RPCEVMTimeout = 5000000000
|
||||
RPCTxFeeCap = 1e+00
|
||||
|
||||
[Eth.Miner]
|
||||
GasFloor = 0
|
||||
GasCeil = 30000000
|
||||
GasPrice = 1000000000
|
||||
Recommit = 2000000000
|
||||
NewPayloadTimeout = 2000000000
|
||||
|
||||
[Eth.TxPool]
|
||||
Locals = []
|
||||
NoLocals = false
|
||||
Journal = "transactions.rlp"
|
||||
Rejournal = 3600000000000
|
||||
PriceLimit = 1
|
||||
PriceBump = 10
|
||||
AccountSlots = 16
|
||||
GlobalSlots = 5120
|
||||
AccountQueue = 64
|
||||
GlobalQueue = 1024
|
||||
Lifetime = 10800000000000
|
||||
|
||||
[Eth.GPO]
|
||||
Blocks = 20
|
||||
Percentile = 60
|
||||
MaxHeaderHistory = 1024
|
||||
MaxBlockHistory = 1024
|
||||
MaxPrice = 500000000000
|
||||
IgnorePrice = 2
|
||||
|
||||
[Node]
|
||||
DataDir = "01"
|
||||
InsecureUnlockAllowed = true
|
||||
IPCPath = "geth.ipc"
|
||||
HTTPHost = ""
|
||||
HTTPPort = 8545
|
||||
HTTPVirtualHosts = ["localhost"]
|
||||
HTTPModules = ["net", "web3", "eth"]
|
||||
AuthAddr = "localhost"
|
||||
AuthPort = 8553
|
||||
AuthVirtualHosts = ["localhost"]
|
||||
WSHost = "127.0.0.1"
|
||||
WSPort = 8546
|
||||
WSModules = ["eth", "admin"]
|
||||
GraphQLVirtualHosts = ["localhost"]
|
||||
|
||||
[Node.P2P]
|
||||
MaxPeers = 50
|
||||
NoDiscovery = true
|
||||
BootstrapNodes = ["enode://d860a01f9722d78051619d1e2351aba3f43f943f6f00718d1b9baa4101932a1f5011f16bb2b1bb35db20d6fe28fa0bf09636d26a87d31de9ec6203eeedb1f666@18.138.108.67:30303", "enode://22a8232c3abc76a16ae9d6c3b164f98775fe226f0917b0ca871128a74a8e9630b458460865bab457221f1d448dd9791d24c4e5d88786180ac185df813a68d4de@3.209.45.79:30303", "enode://8499da03c47d637b20eee24eec3c356c9a2e6148d6fe25ca195c7949ab8ec2c03e3556126b0d7ed644675e78c4318b08691b7b57de10e5f0d40d05b09238fa0a@52.187.207.27:30303", "enode://103858bdb88756c71f15e9b5e09b56dc1be52f0a5021d46301dbbfb7e130029cc9d0d6f73f693bc29b665770fff7da4d34f3c6379fe12721b5d7a0bcb5ca1fc1@191.234.162.198:30303", "enode://715171f50508aba88aecd1250af392a45a330af91d7b90701c436b618c86aaa1589c9184561907bebbb56439b8f8787bc01f49a7c77276c58c1b09822d75e8e8@52.231.165.108:30303", "enode://5d6d7cd20d6da4bb83a1d28cadb5d409b64edf314c0335df658c1a54e32c7c4a7ab7823d57c39b6a757556e68ff1df17c748b698544a55cb488b52479a92b60f@104.42.217.25:30303", "enode://2b252ab6a1d0f971d9722cb839a42cb81db019ba44c08754628ab4a823487071b5695317c8ccd085219c3a03af063495b2f1da8d18218da2d6a82981b45e6ffc@65.108.70.101:30303", "enode://4aeb4ab6c14b23e2c4cfdce879c04b0748a20d8e9b59e25ded2a08143e265c6c25936e74cbc8e641e3312ca288673d91f2f93f8e277de3cfa444ecdaaf982052@157.90.35.166:30303"]
|
||||
BootstrapNodesV5 = ["enr:-KG4QOtcP9X1FbIMOe17QNMKqDxCpm14jcX5tiOE4_TyMrFqbmhPZHK_ZPG2Gxb1GE2xdtodOfx9-cgvNtxnRyHEmC0ghGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQDE8KdiXNlY3AyNTZrMaEDhpehBDbZjM_L9ek699Y7vhUJ-eAdMyQW_Fil522Y0fODdGNwgiMog3VkcIIjKA", "enr:-KG4QDyytgmE4f7AnvW-ZaUOIi9i79qX4JwjRAiXBZCU65wOfBu-3Nb5I7b_Rmg3KCOcZM_C3y5pg7EBU5XGrcLTduQEhGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQ2_DUbiXNlY3AyNTZrMaEDKnz_-ps3UUOfHWVYaskI5kWYO_vtYMGYCQRAR3gHDouDdGNwgiMog3VkcIIjKA", "enr:-Ku4QImhMc1z8yCiNJ1TyUxdcfNucje3BGwEHzodEZUan8PherEo4sF7pPHPSIB1NNuSg5fZy7qFsjmUKs2ea1Whi0EBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQOVphkDqal4QzPMksc5wnpuC3gvSC8AfbFOnZY_On34wIN1ZHCCIyg", "enr:-Ku4QP2xDnEtUXIjzJ_DhlCRN9SN99RYQPJL92TMlSv7U5C1YnYLjwOQHgZIUXw6c-BvRg2Yc2QsZxxoS_pPRVe0yK8Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQMeFF5GrS7UZpAH2Ly84aLK-TyvH-dRo0JM1i8yygH50YN1ZHCCJxA", "enr:-Ku4QPp9z1W4tAO8Ber_NQierYaOStqhDqQdOPY3bB3jDgkjcbk6YrEnVYIiCBbTxuar3CzS528d2iE7TdJsrL-dEKoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQMw5fqqkw2hHC4F5HZZDPsNmPdB1Gi8JPQK7pRc9XHh-oN1ZHCCKvg", "enr:-IS4QLkKqDMy_ExrpOEWa59NiClemOnor-krjp4qoeZwIw2QduPC-q7Kz4u1IOWf3DDbdxqQIgC4fejavBOuUPy-HE4BgmlkgnY0gmlwhCLzAHqJc2VjcDI1NmsxoQLQSJfEAHZApkm5edTCZ_4qps_1k_ub2CxHFxi-gr2JMIN1ZHCCIyg", "enr:-IS4QDAyibHCzYZmIYZCjXwU9BqpotWmv2BsFlIq1V31BwDDMJPFEbox1ijT5c2Ou3kvieOKejxuaCqIcjxBjJ_3j_cBgmlkgnY0gmlwhAMaHiCJc2VjcDI1NmsxoQJIdpj_foZ02MXz4It8xKD7yUHTBx7lVFn3oeRP21KRV4N1ZHCCIyg", "enr:-Ku4QHqVeJ8PPICcWk1vSn_XcSkjOkNiTg6Fmii5j6vUQgvzMc9L1goFnLKgXqBJspJjIsB91LTOleFmyWWrFVATGngBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhAMRHkWJc2VjcDI1NmsxoQKLVXFOhp2uX6jeT0DvvDpPcU8FWMjQdR4wMuORMhpX24N1ZHCCIyg", "enr:-Ku4QG-2_Md3sZIAUebGYT6g0SMskIml77l6yR-M_JXc-UdNHCmHQeOiMLbylPejyJsdAPsTHJyjJB2sYGDLe0dn8uYBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhBLY-NyJc2VjcDI1NmsxoQORcM6e19T1T9gi7jxEZjk_sjVLGFscUNqAY9obgZaxbIN1ZHCCIyg", "enr:-Ku4QPn5eVhcoF1opaFEvg1b6JNFD2rqVkHQ8HApOKK61OIcIXD127bKWgAtbwI7pnxx6cDyk_nI88TrZKQaGMZj0q0Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDayLMaJc2VjcDI1NmsxoQK2sBOLGcUb4AwuYzFuAVCaNHA-dy24UuEKkeFNgCVCsIN1ZHCCIyg", "enr:-Ku4QEWzdnVtXc2Q0ZVigfCGggOVB2Vc1ZCPEc6j21NIFLODSJbvNaef1g4PxhPwl_3kax86YPheFUSLXPRs98vvYsoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDZBrP2Jc2VjcDI1NmsxoQM6jr8Rb1ktLEsVcKAPa08wCsKUmvoQ8khiOl_SLozf9IN1ZHCCIyg"]
|
||||
StaticNodes = ["enode://3a25d05c552af77d4346b82affb6c249c14dc11a9ee08c11b75ca1d05e04b464fa40b1770e3e8dd06b365ff29ba0b24a1f41bef9db4d6004566767b62b19f905@127.0.0.1:64480","enode://56206f2d4d22aacdc89a1d95c0c120437de5ea3bab3ad2bee57a82b3578a0b3af245de80c98e94b8a6c2733e4ae0d5da25fccceb6094132a5c2ab784355f89ef@127.0.0.1:64481","enode://6d5b388dbc3b672606e9731f82bc5ad6443241dd5894e561d272155806d6497770d2e323b011580c661a2e8a40e1f79b017fa5b57ea20a632db95fb90893d04d@127.0.0.1:64482"]
|
||||
TrustedNodes = []
|
||||
ListenAddr = ":64481"
|
||||
DiscAddr = ""
|
||||
EnableMsgEvents = false
|
||||
|
||||
[Node.HTTPTimeouts]
|
||||
ReadTimeout = 30000000000
|
||||
ReadHeaderTimeout = 30000000000
|
||||
WriteTimeout = 30000000000
|
||||
IdleTimeout = 120000000000
|
||||
|
||||
[Metrics]
|
||||
HTTP = "127.0.0.1"
|
||||
Port = 6060
|
||||
InfluxDBEndpoint = "http://localhost:8086"
|
||||
InfluxDBDatabase = "geth"
|
||||
InfluxDBUsername = "test"
|
||||
InfluxDBPassword = "test"
|
||||
InfluxDBTags = "host=localhost"
|
||||
InfluxDBToken = "test"
|
||||
InfluxDBBucket = "geth"
|
||||
InfluxDBOrganization = "geth"
|
96
plugins/test-plugin/test/config02.toml
Normal file
96
plugins/test-plugin/test/config02.toml
Normal file
@ -0,0 +1,96 @@
|
||||
[Eth]
|
||||
NetworkId = 6448
|
||||
SyncMode = "snap"
|
||||
EthDiscoveryURLs = []
|
||||
SnapDiscoveryURLs = []
|
||||
NoPruning = false
|
||||
NoPrefetch = false
|
||||
TxLookupLimit = 2350000
|
||||
LightPeers = 100
|
||||
DatabaseCache = 512
|
||||
DatabaseFreezer = ""
|
||||
TrieCleanCache = 154
|
||||
TrieCleanCacheJournal = "triecache"
|
||||
TrieCleanCacheRejournal = 3600000000000
|
||||
TrieDirtyCache = 256
|
||||
TrieTimeout = 3600000000000
|
||||
SnapshotCache = 102
|
||||
Preimages = false
|
||||
FilterLogCacheSize = 32
|
||||
EnablePreimageRecording = false
|
||||
RPCGasCap = 50000000
|
||||
RPCEVMTimeout = 5000000000
|
||||
RPCTxFeeCap = 1e+00
|
||||
|
||||
[Eth.Miner]
|
||||
GasFloor = 0
|
||||
GasCeil = 30000000
|
||||
GasPrice = 1000000000
|
||||
Recommit = 2000000000
|
||||
NewPayloadTimeout = 2000000000
|
||||
|
||||
[Eth.TxPool]
|
||||
Locals = []
|
||||
NoLocals = false
|
||||
Journal = "transactions.rlp"
|
||||
Rejournal = 3600000000000
|
||||
PriceLimit = 1
|
||||
PriceBump = 10
|
||||
AccountSlots = 16
|
||||
GlobalSlots = 5120
|
||||
AccountQueue = 64
|
||||
GlobalQueue = 1024
|
||||
Lifetime = 10800000000000
|
||||
|
||||
[Eth.GPO]
|
||||
Blocks = 20
|
||||
Percentile = 60
|
||||
MaxHeaderHistory = 1024
|
||||
MaxBlockHistory = 1024
|
||||
MaxPrice = 500000000000
|
||||
IgnorePrice = 2
|
||||
|
||||
[Node]
|
||||
DataDir = "02"
|
||||
InsecureUnlockAllowed = true
|
||||
IPCPath = "geth.ipc"
|
||||
HTTPHost = ""
|
||||
HTTPPort = 8545
|
||||
HTTPVirtualHosts = ["localhost"]
|
||||
HTTPModules = ["net", "web3", "eth"]
|
||||
AuthAddr = "localhost"
|
||||
AuthPort = 8554
|
||||
AuthVirtualHosts = ["localhost"]
|
||||
WSHost = "127.0.0.1"
|
||||
WSPort = 8547
|
||||
WSModules = ["eth", "admin"]
|
||||
GraphQLVirtualHosts = ["localhost"]
|
||||
|
||||
[Node.P2P]
|
||||
MaxPeers = 50
|
||||
NoDiscovery = true
|
||||
BootstrapNodes = ["enode://d860a01f9722d78051619d1e2351aba3f43f943f6f00718d1b9baa4101932a1f5011f16bb2b1bb35db20d6fe28fa0bf09636d26a87d31de9ec6203eeedb1f666@18.138.108.67:30303", "enode://22a8232c3abc76a16ae9d6c3b164f98775fe226f0917b0ca871128a74a8e9630b458460865bab457221f1d448dd9791d24c4e5d88786180ac185df813a68d4de@3.209.45.79:30303", "enode://8499da03c47d637b20eee24eec3c356c9a2e6148d6fe25ca195c7949ab8ec2c03e3556126b0d7ed644675e78c4318b08691b7b57de10e5f0d40d05b09238fa0a@52.187.207.27:30303", "enode://103858bdb88756c71f15e9b5e09b56dc1be52f0a5021d46301dbbfb7e130029cc9d0d6f73f693bc29b665770fff7da4d34f3c6379fe12721b5d7a0bcb5ca1fc1@191.234.162.198:30303", "enode://715171f50508aba88aecd1250af392a45a330af91d7b90701c436b618c86aaa1589c9184561907bebbb56439b8f8787bc01f49a7c77276c58c1b09822d75e8e8@52.231.165.108:30303", "enode://5d6d7cd20d6da4bb83a1d28cadb5d409b64edf314c0335df658c1a54e32c7c4a7ab7823d57c39b6a757556e68ff1df17c748b698544a55cb488b52479a92b60f@104.42.217.25:30303", "enode://2b252ab6a1d0f971d9722cb839a42cb81db019ba44c08754628ab4a823487071b5695317c8ccd085219c3a03af063495b2f1da8d18218da2d6a82981b45e6ffc@65.108.70.101:30303", "enode://4aeb4ab6c14b23e2c4cfdce879c04b0748a20d8e9b59e25ded2a08143e265c6c25936e74cbc8e641e3312ca288673d91f2f93f8e277de3cfa444ecdaaf982052@157.90.35.166:30303"]
|
||||
BootstrapNodesV5 = ["enr:-KG4QOtcP9X1FbIMOe17QNMKqDxCpm14jcX5tiOE4_TyMrFqbmhPZHK_ZPG2Gxb1GE2xdtodOfx9-cgvNtxnRyHEmC0ghGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQDE8KdiXNlY3AyNTZrMaEDhpehBDbZjM_L9ek699Y7vhUJ-eAdMyQW_Fil522Y0fODdGNwgiMog3VkcIIjKA", "enr:-KG4QDyytgmE4f7AnvW-ZaUOIi9i79qX4JwjRAiXBZCU65wOfBu-3Nb5I7b_Rmg3KCOcZM_C3y5pg7EBU5XGrcLTduQEhGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQ2_DUbiXNlY3AyNTZrMaEDKnz_-ps3UUOfHWVYaskI5kWYO_vtYMGYCQRAR3gHDouDdGNwgiMog3VkcIIjKA", "enr:-Ku4QImhMc1z8yCiNJ1TyUxdcfNucje3BGwEHzodEZUan8PherEo4sF7pPHPSIB1NNuSg5fZy7qFsjmUKs2ea1Whi0EBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQOVphkDqal4QzPMksc5wnpuC3gvSC8AfbFOnZY_On34wIN1ZHCCIyg", "enr:-Ku4QP2xDnEtUXIjzJ_DhlCRN9SN99RYQPJL92TMlSv7U5C1YnYLjwOQHgZIUXw6c-BvRg2Yc2QsZxxoS_pPRVe0yK8Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQMeFF5GrS7UZpAH2Ly84aLK-TyvH-dRo0JM1i8yygH50YN1ZHCCJxA", "enr:-Ku4QPp9z1W4tAO8Ber_NQierYaOStqhDqQdOPY3bB3jDgkjcbk6YrEnVYIiCBbTxuar3CzS528d2iE7TdJsrL-dEKoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLf22SJc2VjcDI1NmsxoQMw5fqqkw2hHC4F5HZZDPsNmPdB1Gi8JPQK7pRc9XHh-oN1ZHCCKvg", "enr:-IS4QLkKqDMy_ExrpOEWa59NiClemOnor-krjp4qoeZwIw2QduPC-q7Kz4u1IOWf3DDbdxqQIgC4fejavBOuUPy-HE4BgmlkgnY0gmlwhCLzAHqJc2VjcDI1NmsxoQLQSJfEAHZApkm5edTCZ_4qps_1k_ub2CxHFxi-gr2JMIN1ZHCCIyg", "enr:-IS4QDAyibHCzYZmIYZCjXwU9BqpotWmv2BsFlIq1V31BwDDMJPFEbox1ijT5c2Ou3kvieOKejxuaCqIcjxBjJ_3j_cBgmlkgnY0gmlwhAMaHiCJc2VjcDI1NmsxoQJIdpj_foZ02MXz4It8xKD7yUHTBx7lVFn3oeRP21KRV4N1ZHCCIyg", "enr:-Ku4QHqVeJ8PPICcWk1vSn_XcSkjOkNiTg6Fmii5j6vUQgvzMc9L1goFnLKgXqBJspJjIsB91LTOleFmyWWrFVATGngBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhAMRHkWJc2VjcDI1NmsxoQKLVXFOhp2uX6jeT0DvvDpPcU8FWMjQdR4wMuORMhpX24N1ZHCCIyg", "enr:-Ku4QG-2_Md3sZIAUebGYT6g0SMskIml77l6yR-M_JXc-UdNHCmHQeOiMLbylPejyJsdAPsTHJyjJB2sYGDLe0dn8uYBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhBLY-NyJc2VjcDI1NmsxoQORcM6e19T1T9gi7jxEZjk_sjVLGFscUNqAY9obgZaxbIN1ZHCCIyg", "enr:-Ku4QPn5eVhcoF1opaFEvg1b6JNFD2rqVkHQ8HApOKK61OIcIXD127bKWgAtbwI7pnxx6cDyk_nI88TrZKQaGMZj0q0Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDayLMaJc2VjcDI1NmsxoQK2sBOLGcUb4AwuYzFuAVCaNHA-dy24UuEKkeFNgCVCsIN1ZHCCIyg", "enr:-Ku4QEWzdnVtXc2Q0ZVigfCGggOVB2Vc1ZCPEc6j21NIFLODSJbvNaef1g4PxhPwl_3kax86YPheFUSLXPRs98vvYsoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDZBrP2Jc2VjcDI1NmsxoQM6jr8Rb1ktLEsVcKAPa08wCsKUmvoQ8khiOl_SLozf9IN1ZHCCIyg"]
|
||||
StaticNodes = ["enode://3a25d05c552af77d4346b82affb6c249c14dc11a9ee08c11b75ca1d05e04b464fa40b1770e3e8dd06b365ff29ba0b24a1f41bef9db4d6004566767b62b19f905@127.0.0.1:64480","enode://56206f2d4d22aacdc89a1d95c0c120437de5ea3bab3ad2bee57a82b3578a0b3af245de80c98e94b8a6c2733e4ae0d5da25fccceb6094132a5c2ab784355f89ef@127.0.0.1:64481","enode://6d5b388dbc3b672606e9731f82bc5ad6443241dd5894e561d272155806d6497770d2e323b011580c661a2e8a40e1f79b017fa5b57ea20a632db95fb90893d04d@127.0.0.1:64482"]
|
||||
TrustedNodes = []
|
||||
ListenAddr = ":64482"
|
||||
DiscAddr = ""
|
||||
EnableMsgEvents = false
|
||||
|
||||
[Node.HTTPTimeouts]
|
||||
ReadTimeout = 30000000000
|
||||
ReadHeaderTimeout = 30000000000
|
||||
WriteTimeout = 30000000000
|
||||
IdleTimeout = 120000000000
|
||||
|
||||
[Metrics]
|
||||
HTTP = "127.0.0.1"
|
||||
Port = 6060
|
||||
InfluxDBEndpoint = "http://localhost:8086"
|
||||
InfluxDBDatabase = "geth"
|
||||
InfluxDBUsername = "test"
|
||||
InfluxDBPassword = "test"
|
||||
InfluxDBTags = "host=localhost"
|
||||
InfluxDBToken = "test"
|
||||
InfluxDBBucket = "geth"
|
||||
InfluxDBOrganization = "geth"
|
811
plugins/test-plugin/test/genesis.json
Normal file
811
plugins/test-plugin/test/genesis.json
Normal file
@ -0,0 +1,811 @@
|
||||
{
|
||||
"config": {
|
||||
"chainId": 6448,
|
||||
"homesteadBlock": 0,
|
||||
"eip150Block": 0,
|
||||
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"eip155Block": 0,
|
||||
"eip158Block": 0,
|
||||
"byzantiumBlock": 0,
|
||||
"constantinopleBlock": 0,
|
||||
"petersburgBlock": 0,
|
||||
"istanbulBlock": 0,
|
||||
"berlinBlock" : 0,
|
||||
"londonBlock": 0,
|
||||
"mergeNetsplitBlock": 0,
|
||||
"shanghaiTime": 0,
|
||||
"clique": {
|
||||
"period": 5,
|
||||
"epoch": 30000
|
||||
}
|
||||
},
|
||||
"nonce": "0x0",
|
||||
"timestamp": "0x603e6caa",
|
||||
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000f2c207111cb6ef761e439e56b25c7c99ac026a010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"gasLimit": "0x1c9c380",
|
||||
"difficulty": "0x1",
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase": "0x0000000000000000000000000000000000000000",
|
||||
"alloc": {
|
||||
"0000000000000000000000000000000000000000": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000001": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000002": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000003": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000004": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000005": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000006": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000007": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000008": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000009": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000000f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000010": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000011": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000012": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000013": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000014": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000015": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000016": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000017": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000018": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000019": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000001f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000020": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000021": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000022": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000023": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000024": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000025": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000026": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000027": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000028": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000029": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000002f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000030": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000031": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000032": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000033": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000034": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000035": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000036": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000037": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000038": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000039": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000003f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000040": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000041": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000042": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000043": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000044": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000045": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000046": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000047": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000048": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000049": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000004f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000050": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000051": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000052": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000053": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000054": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000055": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000056": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000057": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000058": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000059": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000005f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000060": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000061": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000062": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000063": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000064": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000065": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000066": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000067": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000068": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000069": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000006f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000070": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000071": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000072": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000073": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000074": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000075": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000076": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000077": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000078": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000079": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000007f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000080": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000081": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000082": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000083": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000084": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000085": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000086": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000087": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000088": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000089": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000008f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000090": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000091": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000092": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000093": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000094": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000095": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000096": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000097": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000098": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"0000000000000000000000000000000000000099": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009a": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009b": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009c": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009d": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009e": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"000000000000000000000000000000000000009f": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000a9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000aa": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ab": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ac": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ad": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ae": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000af": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000b9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ba": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000bb": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000bc": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000bd": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000be": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000bf": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000c9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ca": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000cb": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000cc": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000cd": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ce": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000cf": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000d9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000da": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000db": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000dc": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000dd": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000de": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000df": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000e9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ea": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000eb": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ec": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ed": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ee": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ef": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f0": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f1": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f2": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f3": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f4": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f5": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f6": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f7": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f8": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000f9": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000fa": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000fb": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000fc": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000fd": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000fe": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"00000000000000000000000000000000000000ff": {
|
||||
"balance": "0x1"
|
||||
},
|
||||
"2cb2e3bdb066a83a7f1191eef1697da51793f631": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"4204477bf7fce868e761caaba991ffc607717dbf": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"f2c207111cb6ef761e439e56b25c7c99ac026a01": {
|
||||
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
"number": "0x0",
|
||||
"gasUsed": "0x0",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
1
plugins/test-plugin/test/nodekey00
Normal file
1
plugins/test-plugin/test/nodekey00
Normal file
@ -0,0 +1 @@
|
||||
60eab35e8ff2d588e5ebea2e702db274274e03908deb28680c3e962cfbe5863e
|
1
plugins/test-plugin/test/nodekey01
Normal file
1
plugins/test-plugin/test/nodekey01
Normal file
@ -0,0 +1 @@
|
||||
dcb6263019d1cf73f3fca130acbbd93a8e5936e297e7a4de5aedd5cfabda4c5d
|
1
plugins/test-plugin/test/nodekey02
Normal file
1
plugins/test-plugin/test/nodekey02
Normal file
@ -0,0 +1 @@
|
||||
e5b6e5670ac9be865d2eb330649c131ff431456a3d15a4d891efb7b63c8f03f1
|
70
plugins/test-plugin/test/run-test.sh
Executable file
70
plugins/test-plugin/test/run-test.sh
Executable file
@ -0,0 +1,70 @@
|
||||
[ -f "passwordfile" ] && rm -f passwordfile
|
||||
[ -d "00/" ] && rm -rf 00/
|
||||
[ -d "test00/" ] && rm -rf test00/
|
||||
[ -d "01/" ] && rm -rf 01/
|
||||
[ -d "test01/" ] && rm -rf test01/
|
||||
[ -d "02/" ] && rm -rf 02/
|
||||
[ -d "test02/" ] && rm -rf test02/
|
||||
|
||||
mkdir -p test00 test01 test02 00/keystore 01/keystore 02/keystore 00/geth 01/geth 02/geth 00/plugins 01/plugins 02/plugins
|
||||
|
||||
|
||||
cp ../engine.go ../genesis.go test00/
|
||||
cp ../engine.go ../genesis.go ../main.go ../hooks.go ../tracer.go ../live_tracer.go test01/
|
||||
cp ../engine.go ../genesis.go ../shutdown.go test02/
|
||||
cd test00/
|
||||
go build -buildmode=plugin -o ../00/plugins
|
||||
cd ../
|
||||
cd test01/
|
||||
go build -buildmode=plugin -o ../01/plugins
|
||||
cd ../
|
||||
cd test02/
|
||||
go build -buildmode=plugin -o ../02/plugins
|
||||
cd ../
|
||||
|
||||
cp UTC--2021-03-02T16-47-49.510918858Z--f2c207111cb6ef761e439e56b25c7c99ac026a01 00/keystore
|
||||
cp UTC--2021-03-02T16-47-39.492920333Z--4204477bf7fce868e761caaba991ffc607717dbf 01/keystore
|
||||
cp UTC--2021-03-02T16-47-59.816632526Z--2cb2e3bdb066a83a7f1191eef1697da51793f631 02/keystore
|
||||
|
||||
cp nodekey00 00/geth/nodekey
|
||||
cp nodekey01 01/geth/nodekey
|
||||
cp nodekey02 02/geth/nodekey
|
||||
|
||||
echo -n "supersecretpassword" > passwordfile
|
||||
|
||||
# $GETH init --datadir=./00 genesis.json
|
||||
# $GETH init --datadir=./01 genesis.json
|
||||
# $GETH init --datadir=./02 genesis.json
|
||||
|
||||
# miner node
|
||||
$GETH --cache.preimages --config config00.toml --authrpc.port 8552 --pprof --pprof.port=6767 --port 64480 --verbosity=0 --nodiscover --networkid=6448 --datadir=./00/ --mine --miner.etherbase f2c207111cb6ef761e439e56b25c7c99ac026a01 --unlock f2c207111cb6ef761e439e56b25c7c99ac026a01 --http --http.api eth,debug,net --http.port 9545 --password passwordfile --allow-insecure-unlock &
|
||||
pid0=$!
|
||||
|
||||
sleep 1
|
||||
# passive node
|
||||
$GETH --cache.preimages --config config01.toml --authrpc.port 8553 --pprof --pprof.port=6868 --port 64481 --verbosity=3 --syncmode=full --nodiscover --networkid=6448 --datadir=./01/ --unlock 4204477bf7fce868e761caaba991ffc607717dbf --miner.etherbase 4204477bf7fce868e761caaba991ffc607717dbf --password passwordfile --ws --ws.port 8546 --ws.api eth,admin --http --http.api eth,debug,net --http.port 9546 --allow-insecure-unlock &
|
||||
|
||||
sleep 1
|
||||
|
||||
# shutdown node
|
||||
$GETH --config config02.toml --authrpc.port 8556 --pprof --pprof.port=6969 --port 64484 --verbosity=0 --syncmode=full --nodiscover --networkid=6448 --datadir=./02/ --unlock 2cb2e3bdb066a83a7f1191eef1697da51793f631 --miner.etherbase 2cb2e3bdb066a83a7f1191eef1697da51793f631 --password passwordfile --ws --ws.port 8548 --ws.api eth,admin --http --http.api eth,debug,net --http.port 9547 --allow-insecure-unlock &
|
||||
pid1=$!
|
||||
|
||||
sleep 5
|
||||
|
||||
if ps -p $pid1 > /dev/null; then
|
||||
kill $pid1
|
||||
fi
|
||||
|
||||
sleep 25
|
||||
|
||||
if ps -p $pid0 > /dev/null; then
|
||||
kill $pid0
|
||||
fi
|
||||
|
||||
wait
|
||||
|
||||
rm -f passwordfile
|
||||
rm -rf 00/ 01/ 02/ test00/ test01/ test02/
|
||||
|
||||
|
59
plugins/test-plugin/tracer.go
Normal file
59
plugins/test-plugin/tracer.go
Normal file
@ -0,0 +1,59 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/openrelayxyz/plugeth-utils/core"
|
||||
)
|
||||
|
||||
type TracerService struct {}
|
||||
|
||||
var Tracers = map[string]func(core.StateDB) core.TracerResult{
|
||||
"testTracer": func(core.StateDB) core.TracerResult {
|
||||
return &TracerService{}
|
||||
},
|
||||
}
|
||||
|
||||
func (b *TracerService) CaptureStart(from core.Address, to core.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||
m := map[string]struct{}{
|
||||
"StandardCaptureStart": struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
func (b *TracerService) CaptureState(pc uint64, op core.OpCode, gas, cost uint64, scope core.ScopeContext, rData []byte, depth int, err error) {
|
||||
m := map[string]struct{}{
|
||||
"StandardCaptureState": struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
func (b *TracerService) CaptureFault(pc uint64, op core.OpCode, gas, cost uint64, scope core.ScopeContext, depth int, err error) {
|
||||
m := map[string]struct{}{
|
||||
"StandardCaptureFault": struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
func (b *TracerService) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {
|
||||
m := map[string]struct{}{
|
||||
"StandardCaptureEnd": struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
func (b *TracerService) CaptureEnter(typ core.OpCode, from core.Address, to core.Address, input []byte, gas uint64, value *big.Int) {
|
||||
m := map[string]struct{}{
|
||||
"StandardCaptureEnter": struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
func (b *TracerService) CaptureExit(output []byte, gasUsed uint64, err error) {
|
||||
m := map[string]struct{}{
|
||||
"StandardCaptureExit": struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
}
|
||||
func (b *TracerService) Result() (interface{}, error) {
|
||||
m := map[string]struct{}{
|
||||
"StandardTracerResult": struct{}{},
|
||||
}
|
||||
hookChan <- m
|
||||
return "", nil }
|
522
plugins/wrappers/backendwrapper/backendwrapper.go
Normal file
522
plugins/wrappers/backendwrapper/backendwrapper.go
Normal file
@ -0,0 +1,522 @@
|
||||
package backendwrapper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
gcore "github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
gparams "github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
|
||||
"github.com/openrelayxyz/plugeth-utils/core"
|
||||
"github.com/openrelayxyz/plugeth-utils/restricted"
|
||||
"github.com/openrelayxyz/plugeth-utils/restricted/params"
|
||||
)
|
||||
|
||||
type Backend struct {
|
||||
b ethapi.Backend
|
||||
db state.Database
|
||||
newTxsFeed event.Feed
|
||||
newTxsOnce sync.Once
|
||||
chainFeed event.Feed
|
||||
chainOnce sync.Once
|
||||
chainHeadFeed event.Feed
|
||||
chainHeadOnce sync.Once
|
||||
chainSideFeed event.Feed
|
||||
chainSideOnce sync.Once
|
||||
logsFeed event.Feed
|
||||
logsOnce sync.Once
|
||||
pendingLogsFeed event.Feed
|
||||
pendingLogsOnce sync.Once
|
||||
removedLogsFeed event.Feed
|
||||
removedLogsOnce sync.Once
|
||||
chainConfig *params.ChainConfig
|
||||
}
|
||||
|
||||
func NewBackend(b ethapi.Backend) *Backend {
|
||||
state, _, err := b.StateAndHeaderByNumber(context.Background(), 0)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
return &Backend{
|
||||
b: b,
|
||||
db: state.Database(),
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Backend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
|
||||
return b.b.SuggestGasTipCap(ctx)
|
||||
}
|
||||
func (b *Backend) ChainDb() restricted.Database {
|
||||
return &dbWrapper{b.b.ChainDb()}
|
||||
}
|
||||
func (b *Backend) ExtRPCEnabled() bool {
|
||||
return b.b.ExtRPCEnabled()
|
||||
}
|
||||
func (b *Backend) RPCGasCap() uint64 {
|
||||
return b.b.RPCGasCap()
|
||||
}
|
||||
func (b *Backend) RPCTxFeeCap() float64 {
|
||||
return b.b.RPCTxFeeCap()
|
||||
}
|
||||
func (b *Backend) UnprotectedAllowed() bool {
|
||||
return b.b.UnprotectedAllowed()
|
||||
}
|
||||
func (b *Backend) SetHead(number uint64) {
|
||||
b.b.SetHead(number)
|
||||
}
|
||||
func (b *Backend) HeaderByNumber(ctx context.Context, number int64) ([]byte, error) {
|
||||
header, err := b.b.HeaderByNumber(ctx, rpc.BlockNumber(number))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rlp.EncodeToBytes(header)
|
||||
}
|
||||
func (b *Backend) HeaderByHash(ctx context.Context, hash core.Hash) ([]byte, error) {
|
||||
header, err := b.b.HeaderByHash(ctx, common.Hash(hash))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rlp.EncodeToBytes(header)
|
||||
}
|
||||
func (b *Backend) CurrentHeader() []byte {
|
||||
ret, _ := rlp.EncodeToBytes(b.b.CurrentHeader())
|
||||
return ret
|
||||
}
|
||||
func (b *Backend) CurrentBlock() []byte {
|
||||
ret, _ := rlp.EncodeToBytes(b.b.CurrentBlock())
|
||||
return ret
|
||||
}
|
||||
func (b *Backend) BlockByNumber(ctx context.Context, number int64) ([]byte, error) {
|
||||
block, err := b.b.BlockByNumber(ctx, rpc.BlockNumber(number))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rlp.EncodeToBytes(block)
|
||||
}
|
||||
func (b *Backend) BlockByHash(ctx context.Context, hash core.Hash) ([]byte, error) {
|
||||
block, err := b.b.BlockByHash(ctx, common.Hash(hash))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rlp.EncodeToBytes(block)
|
||||
}
|
||||
func (b *Backend) GetReceipts(ctx context.Context, hash core.Hash) ([]byte, error) {
|
||||
receipts, err := b.b.GetReceipts(ctx, common.Hash(hash))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return json.Marshal(receipts)
|
||||
}
|
||||
func (b *Backend) GetTd(ctx context.Context, hash core.Hash) *big.Int {
|
||||
return b.b.GetTd(ctx, common.Hash(hash))
|
||||
}
|
||||
func (b *Backend) SendTx(ctx context.Context, signedTx []byte) error {
|
||||
tx := new(types.Transaction)
|
||||
if err := tx.UnmarshalBinary(signedTx); err != nil {
|
||||
return err
|
||||
}
|
||||
return b.b.SendTx(ctx, tx)
|
||||
}
|
||||
func (b *Backend) GetTransaction(ctx context.Context, txHash core.Hash) ([]byte, core.Hash, uint64, uint64, error) { // RLP Encoded transaction {
|
||||
_, tx, blockHash, blockNumber, index, err := b.b.GetTransaction(ctx, common.Hash(txHash))
|
||||
if err != nil {
|
||||
return nil, core.Hash(blockHash), blockNumber, index, err
|
||||
}
|
||||
enc, err := tx.MarshalBinary()
|
||||
return enc, core.Hash(blockHash), blockNumber, index, err
|
||||
}
|
||||
func (b *Backend) GetPoolTransactions() ([][]byte, error) {
|
||||
txs, err := b.b.GetPoolTransactions()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
results := make([][]byte, len(txs))
|
||||
for i, tx := range txs {
|
||||
results[i], _ = rlp.EncodeToBytes(tx)
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
func (b *Backend) GetPoolTransaction(txHash core.Hash) []byte {
|
||||
tx := b.b.GetPoolTransaction(common.Hash(txHash))
|
||||
if tx == nil {
|
||||
return []byte{}
|
||||
}
|
||||
enc, _ := rlp.EncodeToBytes(tx)
|
||||
return enc
|
||||
}
|
||||
func (b *Backend) GetPoolNonce(ctx context.Context, addr core.Address) (uint64, error) {
|
||||
return b.b.GetPoolNonce(ctx, common.Address(addr))
|
||||
}
|
||||
func (b *Backend) Stats() (pending int, queued int) {
|
||||
return b.b.Stats()
|
||||
}
|
||||
func (b *Backend) TxPoolContent() (map[core.Address][][]byte, map[core.Address][][]byte) {
|
||||
pending, queued := b.b.TxPoolContent()
|
||||
trpending, trqueued := make(map[core.Address][][]byte), make(map[core.Address][][]byte)
|
||||
for k, v := range pending {
|
||||
trpending[core.Address(k)] = make([][]byte, len(v))
|
||||
for i, tx := range v {
|
||||
trpending[core.Address(k)][i], _ = tx.MarshalBinary()
|
||||
}
|
||||
}
|
||||
for k, v := range queued {
|
||||
trqueued[core.Address(k)] = make([][]byte, len(v))
|
||||
for i, tx := range v {
|
||||
trpending[core.Address(k)][i], _ = tx.MarshalBinary()
|
||||
}
|
||||
}
|
||||
return trpending, trqueued
|
||||
} // RLP encoded transactions
|
||||
func (b *Backend) BloomStatus() (uint64, uint64) {
|
||||
return b.b.BloomStatus()
|
||||
}
|
||||
func (b *Backend) GetLogs(ctx context.Context, blockHash core.Hash) ([][]byte, error) {
|
||||
header, _ := b.b.HeaderByHash(ctx, common.Hash(blockHash))
|
||||
logs, err := b.b.GetLogs(ctx, common.Hash(blockHash), uint64(header.Number.Uint64()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
encLogs := make([][]byte, len(logs))
|
||||
for i, log := range logs {
|
||||
encLogs[i], _ = rlp.EncodeToBytes(log)
|
||||
}
|
||||
return encLogs, nil
|
||||
} // []RLP encoded logs
|
||||
|
||||
type dli interface {
|
||||
SyncProgress() ethereum.SyncProgress
|
||||
}
|
||||
|
||||
type dl struct {
|
||||
dl dli
|
||||
}
|
||||
|
||||
type progress struct {
|
||||
p ethereum.SyncProgress
|
||||
}
|
||||
|
||||
func (p *progress) StartingBlock() uint64 {
|
||||
return p.p.StartingBlock
|
||||
}
|
||||
func (p *progress) CurrentBlock() uint64 {
|
||||
return p.p.CurrentBlock
|
||||
}
|
||||
func (p *progress) HighestBlock() uint64 {
|
||||
return p.p.HighestBlock
|
||||
}
|
||||
|
||||
func (p *progress) PulledStates() uint64 {
|
||||
log.Warn("PulledStates is no longer supported by Geth")
|
||||
return 0
|
||||
}
|
||||
func (p *progress) KnownStates() uint64 {
|
||||
log.Warn("KnownStates is no longer supported by Geth")
|
||||
return 0
|
||||
}
|
||||
func (p *progress) SyncedAccounts() uint64 {
|
||||
return p.p.SyncedAccounts
|
||||
}
|
||||
func (p *progress) SyncedAccountBytes() uint64 {
|
||||
return p.p.SyncedAccountBytes
|
||||
}
|
||||
func (p *progress) SyncedBytecodes() uint64 {
|
||||
return p.p.SyncedBytecodes
|
||||
}
|
||||
func (p *progress) SyncedBytecodeBytes() uint64 {
|
||||
return p.p.SyncedBytecodeBytes
|
||||
}
|
||||
func (p *progress) SyncedStorage() uint64 {
|
||||
return p.p.SyncedStorage
|
||||
}
|
||||
func (p *progress) SyncedStorageBytes() uint64 {
|
||||
return p.p.SyncedStorageBytes
|
||||
}
|
||||
func (p *progress) HealedTrienodes() uint64 {
|
||||
return p.p.HealedTrienodes
|
||||
}
|
||||
func (p *progress) HealedTrienodeBytes() uint64 {
|
||||
return p.p.HealedTrienodeBytes
|
||||
}
|
||||
func (p *progress) HealedBytecodes() uint64 {
|
||||
return p.p.HealedBytecodes
|
||||
}
|
||||
func (p *progress) HealedBytecodeBytes() uint64 {
|
||||
return p.p.HealedBytecodeBytes
|
||||
}
|
||||
func (p *progress) HealingTrienodes() uint64 {
|
||||
return p.p.HealingTrienodes
|
||||
}
|
||||
func (p *progress) HealingBytecode() uint64 {
|
||||
return p.p.HealingBytecode
|
||||
}
|
||||
|
||||
func (d *dl) Progress() core.Progress {
|
||||
return &progress{d.dl.SyncProgress()}
|
||||
}
|
||||
|
||||
func (b *Backend) Downloader() core.Downloader {
|
||||
return &dl{b.b}
|
||||
}
|
||||
|
||||
func (b *Backend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) core.Subscription {
|
||||
var sub event.Subscription
|
||||
b.newTxsOnce.Do(func() {
|
||||
bch := make(chan gcore.NewTxsEvent, 100)
|
||||
sub = b.b.SubscribeNewTxsEvent(bch)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case item := <-bch:
|
||||
txe := core.NewTxsEvent{
|
||||
Txs: make([][]byte, len(item.Txs)),
|
||||
}
|
||||
for i, tx := range item.Txs {
|
||||
txe.Txs[i], _ = tx.MarshalBinary()
|
||||
}
|
||||
b.newTxsFeed.Send(txe)
|
||||
case err := <-sub.Err():
|
||||
log.Warn("Subscription error for NewTxs", "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
return b.newTxsFeed.Subscribe(ch)
|
||||
}
|
||||
func (b *Backend) SubscribeChainEvent(ch chan<- core.ChainEvent) core.Subscription {
|
||||
var sub event.Subscription
|
||||
b.chainOnce.Do(func() {
|
||||
bch := make(chan gcore.ChainEvent, 100)
|
||||
sub = b.b.SubscribeChainEvent(bch)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case item := <-bch:
|
||||
ce := core.ChainEvent{
|
||||
Hash: core.Hash(item.Hash),
|
||||
}
|
||||
ce.Block, _ = rlp.EncodeToBytes(item.Block)
|
||||
ce.Logs, _ = rlp.EncodeToBytes(item.Logs)
|
||||
b.chainFeed.Send(ce)
|
||||
case err := <-sub.Err():
|
||||
log.Warn("Subscription error for Chain", "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
return b.chainFeed.Subscribe(ch)
|
||||
}
|
||||
func (b *Backend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) core.Subscription {
|
||||
var sub event.Subscription
|
||||
b.chainHeadOnce.Do(func() {
|
||||
bch := make(chan gcore.ChainHeadEvent, 100)
|
||||
sub = b.b.SubscribeChainHeadEvent(bch)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case item := <-bch:
|
||||
che := core.ChainHeadEvent{}
|
||||
che.Block, _ = rlp.EncodeToBytes(item.Block)
|
||||
b.chainHeadFeed.Send(che)
|
||||
case err := <-sub.Err():
|
||||
log.Warn("Subscription error for ChainHead", "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
return b.chainHeadFeed.Subscribe(ch)
|
||||
}
|
||||
func (b *Backend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) core.Subscription {
|
||||
var sub event.Subscription
|
||||
b.chainSideOnce.Do(func() {
|
||||
bch := make(chan gcore.ChainSideEvent, 100)
|
||||
sub = b.b.SubscribeChainSideEvent(bch)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case item := <-bch:
|
||||
cse := core.ChainSideEvent{}
|
||||
cse.Block, _ = rlp.EncodeToBytes(item.Block)
|
||||
b.chainSideFeed.Send(cse)
|
||||
case err := <-sub.Err():
|
||||
log.Warn("Subscription error for ChainSide", "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
return b.chainSideFeed.Subscribe(ch)
|
||||
}
|
||||
func (b *Backend) SubscribeLogsEvent(ch chan<- [][]byte) core.Subscription {
|
||||
var sub event.Subscription
|
||||
b.logsOnce.Do(func() {
|
||||
bch := make(chan []*types.Log, 100)
|
||||
sub = b.b.SubscribeLogsEvent(bch)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case item := <-bch:
|
||||
logs := make([][]byte, len(item))
|
||||
for i, log := range item {
|
||||
logs[i], _ = rlp.EncodeToBytes(log)
|
||||
}
|
||||
b.logsFeed.Send(logs)
|
||||
case err := <-sub.Err():
|
||||
log.Warn("Subscription error for Logs", "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
return b.logsFeed.Subscribe(ch)
|
||||
} // []RLP encoded logs
|
||||
func (b *Backend) SubscribePendingLogsEvent(ch chan<- [][]byte) core.Subscription {
|
||||
var sub event.Subscription
|
||||
b.pendingLogsOnce.Do(func() {
|
||||
bch := make(chan []*types.Log, 100)
|
||||
sub = b.b.SubscribePendingLogsEvent(bch)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case item := <-bch:
|
||||
logs := make([][]byte, len(item))
|
||||
for i, log := range item {
|
||||
logs[i], _ = rlp.EncodeToBytes(log)
|
||||
}
|
||||
b.pendingLogsFeed.Send(logs)
|
||||
case err := <-sub.Err():
|
||||
log.Warn("Subscription error for PendingLogs", "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
return b.pendingLogsFeed.Subscribe(ch)
|
||||
} // RLP Encoded logs
|
||||
func (b *Backend) SubscribeRemovedLogsEvent(ch chan<- []byte) core.Subscription {
|
||||
var sub event.Subscription
|
||||
b.removedLogsOnce.Do(func() {
|
||||
bch := make(chan gcore.RemovedLogsEvent, 100)
|
||||
sub = b.b.SubscribeRemovedLogsEvent(bch)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case item := <-bch:
|
||||
logs := make([][]byte, len(item.Logs))
|
||||
for i, log := range item.Logs {
|
||||
logs[i], _ = rlp.EncodeToBytes(log)
|
||||
}
|
||||
b.removedLogsFeed.Send(item)
|
||||
case err := <-sub.Err():
|
||||
log.Warn("Subscription error for RemovedLogs", "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
return b.removedLogsFeed.Subscribe(ch)
|
||||
} // RLP encoded logs
|
||||
|
||||
func convertAndSet(a, b reflect.Value) (err error) {
|
||||
defer func() {
|
||||
if recover() != nil {
|
||||
fmt.Errorf("error converting: %v", err.Error())
|
||||
}
|
||||
}()
|
||||
a.Set(b.Convert(a.Type()))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Backend) ChainConfig() *params.ChainConfig {
|
||||
// We're using the reflect library to copy data from params.ChainConfig to
|
||||
// pparams.ChainConfig, so this function shouldn't need to be touched for
|
||||
// simple changes to ChainConfig (though pparams.ChainConfig may need to be
|
||||
// updated). Note that this probably won't carry over consensus engine data.
|
||||
if b.chainConfig != nil {
|
||||
return b.chainConfig
|
||||
}
|
||||
b.chainConfig = ¶ms.ChainConfig{}
|
||||
nval := reflect.ValueOf(b.b.ChainConfig())
|
||||
ntype := nval.Elem().Type()
|
||||
lval := reflect.ValueOf(b.chainConfig)
|
||||
for i := 0; i < nval.Elem().NumField(); i++ {
|
||||
field := ntype.Field(i)
|
||||
v := nval.Elem().FieldByName(field.Name)
|
||||
lv := lval.Elem().FieldByName(field.Name)
|
||||
log.Info("Checking value for", "field", field.Name)
|
||||
if lv.Kind() != reflect.Invalid {
|
||||
// If core.ChainConfig doesn't have this field, skip it.
|
||||
if v.Type() == lv.Type() && lv.CanSet() {
|
||||
lv.Set(v)
|
||||
} else {
|
||||
convertAndSet(lv, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
return b.chainConfig
|
||||
}
|
||||
|
||||
func CloneChainConfig(cf *gparams.ChainConfig) *params.ChainConfig {
|
||||
result := ¶ms.ChainConfig{}
|
||||
nval := reflect.ValueOf(result)
|
||||
ntype := nval.Elem().Type()
|
||||
lval := reflect.ValueOf(cf)
|
||||
for i := 0; i < nval.Elem().NumField(); i++ {
|
||||
field := ntype.Field(i)
|
||||
v := nval.Elem().FieldByName(field.Name)
|
||||
lv := lval.Elem().FieldByName(field.Name)
|
||||
log.Info("Checking value for", "field", field.Name)
|
||||
if lv.Kind() != reflect.Invalid {
|
||||
// If core.ChainConfig doesn't have this field, skip it.
|
||||
if v.Type() == lv.Type() && lv.CanSet() {
|
||||
v.Set(lv)
|
||||
} else {
|
||||
convertAndSet(v, lv)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (b *Backend) GetTrie(h core.Hash) (core.Trie, error) {
|
||||
tr, err := b.db.OpenTrie(common.Hash(h))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewWrappedTrie(tr), nil
|
||||
}
|
||||
|
||||
func (b *Backend) GetAccountTrie(stateRoot core.Hash, account core.Address) (core.Trie, error) {
|
||||
tr, err := b.db.OpenTrie(common.Hash(stateRoot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
act, err := tr.GetAccount(common.Address(account))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
acTr, err := b.db.OpenStorageTrie(common.Hash(stateRoot), common.Address(account), common.Hash(act.Root), tr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewWrappedTrie(acTr), nil
|
||||
}
|
||||
|
||||
func (b *Backend) GetContractCode(h core.Hash) ([]byte, error) {
|
||||
return state.NewDatabase(b.b.ChainDb()).ContractCode(common.Address{}, common.Hash(h))
|
||||
}
|
54
plugins/wrappers/backendwrapper/dbwrapper.go
Normal file
54
plugins/wrappers/backendwrapper/dbwrapper.go
Normal file
@ -0,0 +1,54 @@
|
||||
package backendwrapper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/openrelayxyz/plugeth-utils/restricted"
|
||||
)
|
||||
|
||||
type dbWrapper struct {
|
||||
db ethdb.Database
|
||||
}
|
||||
|
||||
func NewDb(d ethdb.Database) restricted.Database {
|
||||
return &dbWrapper{d}
|
||||
}
|
||||
|
||||
func (d *dbWrapper) Has(key []byte) (bool, error) { return d.db.Has(key) }
|
||||
func (d *dbWrapper) Get(key []byte) ([]byte, error) { return d.db.Get(key) }
|
||||
func (d *dbWrapper) Put(key []byte, value []byte) error { return d.db.Put(key, value) }
|
||||
func (d *dbWrapper) Delete(key []byte) error { return d.db.Delete(key) }
|
||||
func (d *dbWrapper) Stat(property string) (string, error) { return d.db.Stat(property) }
|
||||
func (d *dbWrapper) Compact(start []byte, limit []byte) error { return d.db.Compact(start, limit) }
|
||||
func (d *dbWrapper) HasAncient(kind string, number uint64) (bool, error) {
|
||||
return d.db.HasAncient(kind, number)
|
||||
}
|
||||
func (d *dbWrapper) Ancient(kind string, number uint64) ([]byte, error) {
|
||||
return d.db.Ancient(kind, number)
|
||||
}
|
||||
func (d *dbWrapper) Ancients() (uint64, error) { return d.db.Ancients() }
|
||||
func (d *dbWrapper) AncientSize(kind string) (uint64, error) { return d.db.AncientSize(kind) }
|
||||
func (d *dbWrapper) AppendAncient(number uint64, hash, header, body, receipt, td []byte) error {
|
||||
return fmt.Errorf("AppendAncient is no longer supported in geth 1.10.9 and above. Use ModifyAncients instead.")
|
||||
}
|
||||
func (d *dbWrapper) ModifyAncients(fn func(ethdb.AncientWriteOp) error) (int64, error) {
|
||||
return d.db.ModifyAncients(fn)
|
||||
}
|
||||
func (d *dbWrapper) TruncateAncients(n uint64) error {
|
||||
return fmt.Errorf("TruncateAncients is no longer supported in geth 1.10.17 and above.") }
|
||||
func (d *dbWrapper) Sync() error { return d.db.Sync() }
|
||||
func (d *dbWrapper) Close() error { return d.db.Close() }
|
||||
func (d *dbWrapper) NewIterator(prefix []byte, start []byte) restricted.Iterator {
|
||||
return &iterWrapper{d.db.NewIterator(prefix, start)}
|
||||
}
|
||||
|
||||
type iterWrapper struct {
|
||||
iter ethdb.Iterator
|
||||
}
|
||||
|
||||
func (it *iterWrapper) Next() bool { return it.iter.Next() }
|
||||
func (it *iterWrapper) Error() error { return it.iter.Error() }
|
||||
func (it *iterWrapper) Key() []byte { return it.iter.Key() }
|
||||
func (it *iterWrapper) Value() []byte { return it.iter.Value() }
|
||||
func (it *iterWrapper) Release() { it.iter.Release() }
|
107
plugins/wrappers/backendwrapper/triewrapper.go
Normal file
107
plugins/wrappers/backendwrapper/triewrapper.go
Normal file
@ -0,0 +1,107 @@
|
||||
package backendwrapper
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
|
||||
"github.com/openrelayxyz/plugeth-utils/core"
|
||||
)
|
||||
|
||||
type WrappedTrie struct {
|
||||
t state.Trie
|
||||
}
|
||||
|
||||
func NewWrappedTrie(t state.Trie) core.Trie {
|
||||
return &WrappedTrie{t}
|
||||
}
|
||||
|
||||
func (t *WrappedTrie) GetKey(b []byte) []byte {
|
||||
return t.t.GetKey(b)
|
||||
}
|
||||
|
||||
func (t *WrappedTrie) GetAccount(address core.Address) (*core.StateAccount, error) {
|
||||
act, err := t.t.GetAccount(common.Address(address))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &core.StateAccount{
|
||||
Nonce: act.Nonce,
|
||||
Balance: new(big.Int).SetBytes(act.Balance.Bytes()),
|
||||
Root: core.Hash(act.Root),
|
||||
CodeHash: act.CodeHash,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (t *WrappedTrie) Hash() core.Hash {
|
||||
return core.Hash(t.t.Hash())
|
||||
}
|
||||
|
||||
func (t *WrappedTrie) NodeIterator(startKey []byte) core.NodeIterator {
|
||||
itr, err := t.t.NodeIterator(startKey)
|
||||
if err != nil {
|
||||
log.Error("Error returned from geth side NodeIterator", "err", err)
|
||||
}
|
||||
return &WrappedNodeIterator{itr}
|
||||
}
|
||||
|
||||
func (t *WrappedTrie) Prove(key []byte, fromLevel uint, proofDb core.KeyValueWriter) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type WrappedNodeIterator struct {
|
||||
n trie.NodeIterator
|
||||
}
|
||||
|
||||
func (n WrappedNodeIterator) Next(b bool) bool {
|
||||
return n.n.Next(b)
|
||||
}
|
||||
|
||||
func (n WrappedNodeIterator) Error() error {
|
||||
return n.n.Error()
|
||||
}
|
||||
|
||||
func (n WrappedNodeIterator) Hash() core.Hash {
|
||||
return core.Hash(n.n.Hash())
|
||||
}
|
||||
|
||||
func (n WrappedNodeIterator) Parent() core.Hash {
|
||||
return core.Hash(n.n.Parent())
|
||||
}
|
||||
|
||||
func (n WrappedNodeIterator) Path() []byte {
|
||||
return n.n.Path()
|
||||
}
|
||||
|
||||
func (n WrappedNodeIterator) NodeBlob() []byte {
|
||||
return n.n.NodeBlob()
|
||||
}
|
||||
|
||||
func (n WrappedNodeIterator) Leaf() bool {
|
||||
return n.n.Leaf()
|
||||
}
|
||||
|
||||
func (n WrappedNodeIterator) LeafKey() []byte {
|
||||
return n.n.LeafKey()
|
||||
}
|
||||
|
||||
func (n WrappedNodeIterator) LeafBlob() []byte {
|
||||
return n.n.LeafBlob()
|
||||
}
|
||||
|
||||
func (n WrappedNodeIterator) LeafProof() [][]byte {
|
||||
return n.n.LeafProof()
|
||||
}
|
||||
|
||||
func (n WrappedNodeIterator) AddResolver(c core.NodeResolver) {
|
||||
n.n.AddResolver(WrappedNodeResolver(c))
|
||||
}
|
||||
|
||||
func WrappedNodeResolver(fn core.NodeResolver) trie.NodeResolver {
|
||||
return func(owner common.Hash, path []byte, hash common.Hash) []byte {
|
||||
return fn(core.Hash(owner), path, core.Hash(hash) )
|
||||
}
|
||||
}
|
429
plugins/wrappers/engine/enginewrapper.go
Normal file
429
plugins/wrappers/engine/enginewrapper.go
Normal file
@ -0,0 +1,429 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/consensus"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/plugins/wrappers"
|
||||
"github.com/openrelayxyz/plugeth-utils/core"
|
||||
ptypes "github.com/openrelayxyz/plugeth-utils/restricted/types"
|
||||
pconsensus "github.com/openrelayxyz/plugeth-utils/restricted/consensus"
|
||||
pparams "github.com/openrelayxyz/plugeth-utils/restricted/params"
|
||||
)
|
||||
|
||||
|
||||
func gethToUtilsHeader(header *types.Header) *ptypes.Header {
|
||||
if header == nil { return nil }
|
||||
return &ptypes.Header{
|
||||
ParentHash: core.Hash(header.ParentHash),
|
||||
UncleHash: core.Hash(header.UncleHash),
|
||||
Coinbase: core.Address(header.Coinbase),
|
||||
Root: core.Hash(header.Root),
|
||||
TxHash: core.Hash(header.TxHash),
|
||||
ReceiptHash: core.Hash(header.ReceiptHash),
|
||||
Bloom: ptypes.Bloom(header.Bloom),
|
||||
Difficulty: header.Difficulty,
|
||||
Number: header.Number,
|
||||
GasLimit: header.GasLimit,
|
||||
GasUsed: header.GasUsed,
|
||||
Time: header.Time,
|
||||
Extra: header.Extra,
|
||||
MixDigest: core.Hash(header.MixDigest),
|
||||
Nonce: ptypes.BlockNonce(header.Nonce),
|
||||
BaseFee: header.BaseFee,
|
||||
WithdrawalsHash: (*core.Hash)(header.WithdrawalsHash),
|
||||
}
|
||||
}
|
||||
func utilsToGethHeader(header *ptypes.Header) *types.Header {
|
||||
if header == nil { return nil }
|
||||
return &types.Header{
|
||||
ParentHash: common.Hash(header.ParentHash),
|
||||
UncleHash: common.Hash(header.UncleHash),
|
||||
Coinbase: common.Address(header.Coinbase),
|
||||
Root: common.Hash(header.Root),
|
||||
TxHash: common.Hash(header.TxHash),
|
||||
ReceiptHash: common.Hash(header.ReceiptHash),
|
||||
Bloom: types.Bloom(header.Bloom),
|
||||
Difficulty: header.Difficulty,
|
||||
Number: header.Number,
|
||||
GasLimit: header.GasLimit,
|
||||
GasUsed: header.GasUsed,
|
||||
Time: header.Time,
|
||||
Extra: header.Extra,
|
||||
MixDigest: common.Hash(header.MixDigest),
|
||||
Nonce: types.BlockNonce(header.Nonce),
|
||||
BaseFee: header.BaseFee,
|
||||
WithdrawalsHash: (*common.Hash)(header.WithdrawalsHash),
|
||||
}
|
||||
}
|
||||
|
||||
func gethToUtilsTransactions(transactions []*types.Transaction) []*ptypes.Transaction {
|
||||
if transactions == nil { return nil }
|
||||
txs := make([]*ptypes.Transaction, len(transactions))
|
||||
for i, tx := range transactions {
|
||||
bin, err := tx.MarshalBinary()
|
||||
if err != nil { panic (err) }
|
||||
txs[i] = &ptypes.Transaction{}
|
||||
txs[i].UnmarshalBinary(bin)
|
||||
}
|
||||
return txs
|
||||
}
|
||||
|
||||
func gethToUtilsHeaders(headers []*types.Header) []*ptypes.Header {
|
||||
if headers == nil { return nil }
|
||||
pheaders := make([]*ptypes.Header, len(headers))
|
||||
for i, header := range headers {
|
||||
pheaders[i] = gethToUtilsHeader(header)
|
||||
}
|
||||
return pheaders
|
||||
}
|
||||
|
||||
func gethToUtilsReceipts(receipts []*types.Receipt) []*ptypes.Receipt {
|
||||
if receipts == nil { return nil }
|
||||
preceipts := make([]*ptypes.Receipt, len(receipts))
|
||||
for i, receipt := range receipts {
|
||||
preceipts[i] = &ptypes.Receipt{
|
||||
Type: receipt.Type,
|
||||
PostState: receipt.PostState,
|
||||
Status: receipt.Status,
|
||||
CumulativeGasUsed: receipt.CumulativeGasUsed,
|
||||
Bloom: ptypes.Bloom(receipt.Bloom),
|
||||
Logs: gethToUtilsLogs(receipt.Logs),
|
||||
TxHash: core.Hash(receipt.TxHash),
|
||||
ContractAddress: core.Address(receipt.ContractAddress),
|
||||
GasUsed: receipt.GasUsed,
|
||||
BlockHash: core.Hash(receipt.BlockHash),
|
||||
BlockNumber: receipt.BlockNumber,
|
||||
TransactionIndex: receipt.TransactionIndex,
|
||||
}
|
||||
}
|
||||
return preceipts
|
||||
}
|
||||
|
||||
func gethToUtilsWithdrawals(withdrawals []*types.Withdrawal) []*ptypes.Withdrawal {
|
||||
if withdrawals == nil { return nil }
|
||||
pwithdrawals := make([]*ptypes.Withdrawal, len(withdrawals))
|
||||
for i, withdrawal := range withdrawals {
|
||||
pwithdrawals[i] = &ptypes.Withdrawal{
|
||||
Index: withdrawal.Index,
|
||||
Validator: withdrawal.Validator,
|
||||
Address: core.Address(withdrawal.Address),
|
||||
Amount: withdrawal.Amount,
|
||||
}
|
||||
}
|
||||
return pwithdrawals
|
||||
}
|
||||
|
||||
func gethToUtilsBlock(block *types.Block) *ptypes.Block {
|
||||
if block == nil { return nil }
|
||||
return ptypes.NewBlockWithHeader(gethToUtilsHeader(block.Header())).WithBody(gethToUtilsTransactions(block.Transactions()), gethToUtilsHeaders(block.Uncles())).WithWithdrawals(gethToUtilsWithdrawals(block.Withdrawals()))
|
||||
}
|
||||
|
||||
func utilsToGethBlock(block *ptypes.Block) *types.Block {
|
||||
if block == nil { return nil }
|
||||
return types.NewBlockWithHeader(utilsToGethHeader(block.Header())).WithBody(utilsToGethTransactions(block.Transactions()), utilsToGethHeaders(block.Uncles())).WithWithdrawals(utilsToGethWithdrawals(block.Withdrawals()))
|
||||
}
|
||||
|
||||
func utilsToGethHeaders(headers []*ptypes.Header) []*types.Header {
|
||||
if headers == nil { return nil }
|
||||
pheaders := make([]*types.Header, len(headers))
|
||||
for i, header := range headers {
|
||||
pheaders[i] = utilsToGethHeader(header)
|
||||
}
|
||||
return pheaders
|
||||
}
|
||||
|
||||
func utilsToGethTransactions(transactions []*ptypes.Transaction) []*types.Transaction {
|
||||
if transactions == nil { return nil }
|
||||
txs := make([]*types.Transaction, len(transactions))
|
||||
for i, tx := range transactions {
|
||||
bin, err := tx.MarshalBinary()
|
||||
if err != nil { panic (err) }
|
||||
txs[i] = &types.Transaction{}
|
||||
txs[i].UnmarshalBinary(bin)
|
||||
}
|
||||
return txs
|
||||
}
|
||||
func utilsToGethWithdrawals(withdrawals []*ptypes.Withdrawal) []*types.Withdrawal {
|
||||
if withdrawals == nil { return nil }
|
||||
pwithdrawals := make([]*types.Withdrawal, len(withdrawals))
|
||||
for i, withdrawal := range withdrawals {
|
||||
pwithdrawals[i] = &types.Withdrawal{
|
||||
Index: withdrawal.Index,
|
||||
Validator: withdrawal.Validator,
|
||||
Address: common.Address(withdrawal.Address),
|
||||
Amount: withdrawal.Amount,
|
||||
}
|
||||
}
|
||||
return pwithdrawals
|
||||
}
|
||||
|
||||
func gethToUtilsBlockChan(ch chan<- *types.Block) chan<- *ptypes.Block {
|
||||
pchan := make(chan *ptypes.Block)
|
||||
go func() {
|
||||
for block := range pchan {
|
||||
ch <- utilsToGethBlock(block)
|
||||
}
|
||||
}()
|
||||
return pchan
|
||||
}
|
||||
|
||||
func gethToUtilsLog(logRecord *types.Log) *ptypes.Log {
|
||||
if logRecord == nil { return nil }
|
||||
topics := make([]core.Hash, len(logRecord.Topics))
|
||||
for i, t := range logRecord.Topics {
|
||||
topics[i] = core.Hash(t)
|
||||
}
|
||||
return &ptypes.Log{
|
||||
Address: core.Address(logRecord.Address),
|
||||
Topics: topics,
|
||||
Data: logRecord.Data,
|
||||
BlockNumber: logRecord.BlockNumber,
|
||||
TxHash: core.Hash(logRecord.TxHash),
|
||||
TxIndex: logRecord.TxIndex,
|
||||
BlockHash: core.Hash(logRecord.BlockHash),
|
||||
Index: logRecord.Index,
|
||||
Removed: logRecord.Removed,
|
||||
}
|
||||
}
|
||||
|
||||
func utilsToGethLog(logRecord *ptypes.Log) *types.Log {
|
||||
if logRecord == nil { return nil }
|
||||
topics := make([]common.Hash, len(logRecord.Topics))
|
||||
for i, t := range logRecord.Topics {
|
||||
topics[i] = common.Hash(t)
|
||||
}
|
||||
return &types.Log{
|
||||
Address: common.Address(logRecord.Address),
|
||||
Topics: topics,
|
||||
Data: logRecord.Data,
|
||||
BlockNumber: logRecord.BlockNumber,
|
||||
TxHash: common.Hash(logRecord.TxHash),
|
||||
TxIndex: logRecord.TxIndex,
|
||||
BlockHash: common.Hash(logRecord.BlockHash),
|
||||
Index: logRecord.Index,
|
||||
Removed: logRecord.Removed,
|
||||
}
|
||||
}
|
||||
|
||||
func gethToUtilsLogs(logs []*types.Log) []*ptypes.Log {
|
||||
result := make([]*ptypes.Log, len(logs))
|
||||
for i, logRecord := range logs {
|
||||
result[i] = gethToUtilsLog(logRecord)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func utilsToGethLogs(logs []*ptypes.Log) []*types.Log {
|
||||
result := make([]*types.Log, len(logs))
|
||||
for i, logRecord := range logs {
|
||||
result[i] = utilsToGethLog(logRecord)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
func convertAndSet(a, b reflect.Value) (err error) {
|
||||
defer func() {
|
||||
if recover() != nil {
|
||||
fmt.Errorf("error converting: %v", err.Error())
|
||||
}
|
||||
}()
|
||||
a.Set(b.Convert(a.Type()))
|
||||
return nil
|
||||
}
|
||||
|
||||
func gethToUtilsConfig(gcfg *params.ChainConfig) *pparams.ChainConfig {
|
||||
cfg := &pparams.ChainConfig{}
|
||||
nval := reflect.ValueOf(gcfg)
|
||||
ntype := nval.Elem().Type()
|
||||
lval := reflect.ValueOf(cfg)
|
||||
for i := 0; i < nval.Elem().NumField(); i++ {
|
||||
field := ntype.Field(i)
|
||||
v := nval.Elem().FieldByName(field.Name)
|
||||
lv := lval.Elem().FieldByName(field.Name)
|
||||
log.Info("Checking value for", "field", field.Name)
|
||||
if lv.Kind() != reflect.Invalid {
|
||||
// If core.ChainConfig doesn't have this field, skip it.
|
||||
if v.Type() == lv.Type() && lv.CanSet() {
|
||||
lv.Set(v)
|
||||
} else {
|
||||
convertAndSet(lv, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
type WrappedHeaderReader struct {
|
||||
chr consensus.ChainHeaderReader
|
||||
cfg *pparams.ChainConfig
|
||||
}
|
||||
|
||||
func (whr *WrappedHeaderReader) Config() *pparams.ChainConfig {
|
||||
if whr.cfg == nil {
|
||||
whr.cfg = gethToUtilsConfig(whr.chr.Config())
|
||||
}
|
||||
return whr.cfg
|
||||
}
|
||||
|
||||
// CurrentHeader retrieves the current header from the local chain.
|
||||
func (whr *WrappedHeaderReader) CurrentHeader() *ptypes.Header {
|
||||
return gethToUtilsHeader(whr.chr.CurrentHeader())
|
||||
}
|
||||
|
||||
// GetHeader retrieves a block header from the database by hash and number.
|
||||
func (whr *WrappedHeaderReader) GetHeader(hash core.Hash, number uint64) *ptypes.Header {
|
||||
return gethToUtilsHeader(whr.chr.GetHeader(common.Hash(hash), number))
|
||||
}
|
||||
|
||||
// GetHeaderByNumber retrieves a block header from the database by number.
|
||||
func (whr *WrappedHeaderReader) GetHeaderByNumber(number uint64) *ptypes.Header {
|
||||
return gethToUtilsHeader(whr.chr.GetHeaderByNumber(number))
|
||||
}
|
||||
|
||||
// GetHeaderByHash retrieves a block header from the database by its hash.
|
||||
func (whr *WrappedHeaderReader) GetHeaderByHash(hash core.Hash) *ptypes.Header {
|
||||
return gethToUtilsHeader(whr.chr.GetHeaderByHash(common.Hash(hash)))
|
||||
}
|
||||
|
||||
// GetTd retrieves the total difficulty from the database by hash and number.
|
||||
func (whr *WrappedHeaderReader) GetTd(hash core.Hash, number uint64) *big.Int {
|
||||
return whr.chr.GetTd(common.Hash(hash), number)
|
||||
}
|
||||
|
||||
|
||||
type WrappedChainReader struct {
|
||||
chr consensus.ChainReader
|
||||
cfg *pparams.ChainConfig
|
||||
}
|
||||
|
||||
func (whr *WrappedChainReader) Config() *pparams.ChainConfig {
|
||||
// We're using the reflect library to copy data from params.ChainConfig to
|
||||
// pparams.ChainConfig, so this function shouldn't need to be touched for
|
||||
// simple changes to ChainConfig (though pparams.ChainConfig may need to be
|
||||
// updated). Note that this probably won't carry over consensus engine data.
|
||||
if whr.cfg == nil {
|
||||
whr.cfg = gethToUtilsConfig(whr.chr.Config())
|
||||
}
|
||||
return whr.cfg
|
||||
}
|
||||
|
||||
// CurrentHeader retrieves the current header from the local chain.
|
||||
func (whr *WrappedChainReader) CurrentHeader() *ptypes.Header {
|
||||
return gethToUtilsHeader(whr.chr.CurrentHeader())
|
||||
}
|
||||
|
||||
// GetHeader retrieves a block header from the database by hash and number.
|
||||
func (whr *WrappedChainReader) GetHeader(hash core.Hash, number uint64) *ptypes.Header {
|
||||
return gethToUtilsHeader(whr.chr.GetHeader(common.Hash(hash), number))
|
||||
}
|
||||
|
||||
// GetHeaderByNumber retrieves a block header from the database by number.
|
||||
func (whr *WrappedChainReader) GetHeaderByNumber(number uint64) *ptypes.Header {
|
||||
return gethToUtilsHeader(whr.chr.GetHeaderByNumber(number))
|
||||
}
|
||||
|
||||
// GetHeaderByHash retrieves a block header from the database by its hash.
|
||||
func (whr *WrappedChainReader) GetHeaderByHash(hash core.Hash) *ptypes.Header {
|
||||
return gethToUtilsHeader(whr.chr.GetHeaderByHash(common.Hash(hash)))
|
||||
}
|
||||
|
||||
// GetTd retrieves the total difficulty from the database by hash and number.
|
||||
func (whr *WrappedChainReader) GetTd(hash core.Hash, number uint64) *big.Int {
|
||||
return whr.chr.GetTd(common.Hash(hash), number)
|
||||
}
|
||||
|
||||
func (whr *WrappedChainReader) GetBlock(hash core.Hash, number uint64) *ptypes.Block {
|
||||
return gethToUtilsBlock(whr.chr.GetBlock(common.Hash(hash), number))
|
||||
}
|
||||
|
||||
type hasherWrapper struct {
|
||||
th types.TrieHasher
|
||||
}
|
||||
func (hw *hasherWrapper) Reset() {
|
||||
hw.th.Reset()
|
||||
}
|
||||
func (hw *hasherWrapper) Update(a, b []byte) {
|
||||
hw.th.Update(a, b)
|
||||
}
|
||||
func (hw *hasherWrapper) Hash() core.Hash {
|
||||
return core.Hash(hw.th.Hash())
|
||||
}
|
||||
|
||||
type engineWrapper struct {
|
||||
engine pconsensus.Engine
|
||||
}
|
||||
|
||||
func NewWrappedEngine(e pconsensus.Engine) consensus.Engine {
|
||||
return &engineWrapper {
|
||||
engine: e,
|
||||
}
|
||||
}
|
||||
|
||||
func (ew *engineWrapper) Author(header *types.Header) (common.Address, error) {
|
||||
addr, err := ew.engine.Author(gethToUtilsHeader(header))
|
||||
return common.Address(addr), err
|
||||
}
|
||||
func (ew *engineWrapper) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header) error {
|
||||
var dummySeal bool
|
||||
return ew.engine.VerifyHeader(&WrappedHeaderReader{chain, nil}, gethToUtilsHeader(header), dummySeal)
|
||||
}
|
||||
func (ew *engineWrapper) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) (chan<- struct{}, <-chan error) {
|
||||
pheaders := make([]*ptypes.Header, len(headers))
|
||||
for i, header := range headers {
|
||||
pheaders[i] = gethToUtilsHeader(header)
|
||||
}
|
||||
dummySeals := make([]bool, len(headers))
|
||||
return ew.engine.VerifyHeaders(&WrappedHeaderReader{chain, nil}, pheaders, dummySeals)
|
||||
}
|
||||
func (ew *engineWrapper) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
|
||||
return ew.engine.VerifyUncles(&WrappedChainReader{chain, nil}, gethToUtilsBlock(block))
|
||||
}
|
||||
func (ew *engineWrapper) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
|
||||
uHeader := gethToUtilsHeader(header)
|
||||
if err := ew.engine.Prepare(&WrappedHeaderReader{chain, nil}, uHeader); err != nil {
|
||||
return err
|
||||
}
|
||||
*header = *utilsToGethHeader(uHeader)
|
||||
return nil
|
||||
}
|
||||
func (ew *engineWrapper) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) {
|
||||
ew.engine.Finalize(&WrappedHeaderReader{chain, nil}, gethToUtilsHeader(header), wrappers.NewWrappedStateDB(state), gethToUtilsTransactions(txs), gethToUtilsHeaders(uncles), gethToUtilsWithdrawals(withdrawals))
|
||||
}
|
||||
func (ew *engineWrapper) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) {
|
||||
block, err := ew.engine.FinalizeAndAssemble(&WrappedHeaderReader{chain, nil}, gethToUtilsHeader(header), wrappers.NewWrappedStateDB(state), gethToUtilsTransactions(txs), gethToUtilsHeaders(uncles), gethToUtilsReceipts(receipts), gethToUtilsWithdrawals(withdrawals))
|
||||
return utilsToGethBlock(block), err
|
||||
}
|
||||
func (ew *engineWrapper) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
|
||||
return ew.engine.Seal(&WrappedHeaderReader{chain, nil}, gethToUtilsBlock(block), gethToUtilsBlockChan(results), stop)
|
||||
}
|
||||
func (ew *engineWrapper) SealHash(header *types.Header) common.Hash {
|
||||
return common.Hash(ew.engine.SealHash(gethToUtilsHeader(header)))
|
||||
}
|
||||
func (ew *engineWrapper) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int {
|
||||
return ew.engine.CalcDifficulty(&WrappedHeaderReader{chain, nil}, time, gethToUtilsHeader(parent))
|
||||
}
|
||||
func (ew *engineWrapper) APIs(chain consensus.ChainHeaderReader) []rpc.API {
|
||||
papis := ew.engine.APIs(&WrappedHeaderReader{chain, nil})
|
||||
apis := make([]rpc.API, len(papis))
|
||||
for i, api := range papis {
|
||||
apis[i] = rpc.API{
|
||||
Namespace: api.Namespace,
|
||||
Version: api.Version,
|
||||
Service: api.Service,
|
||||
Public: api.Public,
|
||||
}
|
||||
}
|
||||
return apis
|
||||
}
|
||||
func (ew *engineWrapper) Close() error {
|
||||
return ew.engine.Close()
|
||||
}
|
274
plugins/wrappers/wrappers.go
Normal file
274
plugins/wrappers/wrappers.go
Normal file
@ -0,0 +1,274 @@
|
||||
package wrappers
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/holiman/uint256"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
|
||||
"github.com/openrelayxyz/plugeth-utils/core"
|
||||
)
|
||||
|
||||
type WrappedScopeContext struct {
|
||||
s *vm.ScopeContext
|
||||
}
|
||||
|
||||
func NewWrappedScopeContext(s *vm.ScopeContext) *WrappedScopeContext {
|
||||
return &WrappedScopeContext{s}
|
||||
}
|
||||
|
||||
func (w *WrappedScopeContext) Memory() core.Memory {
|
||||
return w.s.Memory
|
||||
}
|
||||
|
||||
func (w *WrappedScopeContext) Stack() core.Stack {
|
||||
return w.s.Stack
|
||||
}
|
||||
|
||||
func (w *WrappedScopeContext) Contract() core.Contract {
|
||||
return &WrappedContract{w.s.Contract}
|
||||
}
|
||||
|
||||
type WrappedContract struct {
|
||||
c *vm.Contract
|
||||
}
|
||||
|
||||
func (w *WrappedContract) AsDelegate() core.Contract {
|
||||
return &WrappedContract{w.c.AsDelegate()}
|
||||
}
|
||||
|
||||
func (w *WrappedContract) GetOp(n uint64) core.OpCode {
|
||||
return core.OpCode(w.c.GetOp(n))
|
||||
}
|
||||
|
||||
func (w *WrappedContract) GetByte(n uint64) byte {
|
||||
return byte(w.c.GetOp(n))
|
||||
}
|
||||
|
||||
func (w *WrappedContract) Caller() core.Address {
|
||||
return core.Address(w.c.Caller())
|
||||
}
|
||||
|
||||
func (w *WrappedContract) Address() core.Address {
|
||||
return core.Address(w.c.Address())
|
||||
}
|
||||
|
||||
func (w *WrappedContract) Value() *big.Int {
|
||||
return new(big.Int).SetBytes(w.c.Value().Bytes())
|
||||
}
|
||||
|
||||
func (w *WrappedContract) Input() []byte {
|
||||
return w.c.Input
|
||||
}
|
||||
|
||||
func (w *WrappedContract) Code() []byte {
|
||||
return w.c.Code
|
||||
}
|
||||
|
||||
// added UseGas bc compiler compained without it. Should investigate if the false return with effect performance.
|
||||
// take this out of core.interface
|
||||
func (w *WrappedContract) UseGas(gas uint64) (ok bool) {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
type WrappedTracer struct {
|
||||
r core.TracerResult
|
||||
}
|
||||
|
||||
func NewWrappedTracer(r core.TracerResult) *WrappedTracer {
|
||||
return &WrappedTracer{r}
|
||||
}
|
||||
func (w WrappedTracer) CapturePreStart(from common.Address, to *common.Address, input []byte, gas uint64, value *big.Int) {
|
||||
if v, ok := w.r.(core.PreTracer); ok {
|
||||
v.CapturePreStart(core.Address(from), (*core.Address)(to), input, gas, value)}
|
||||
}
|
||||
func (w WrappedTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||
w.r.CaptureStart(core.Address(from), core.Address(to), create, input, gas, value)
|
||||
}
|
||||
func (w WrappedTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
|
||||
w.r.CaptureState(pc, core.OpCode(op), gas, cost, &WrappedScopeContext{scope}, rData, depth, err)
|
||||
}
|
||||
func (w WrappedTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
||||
w.r.CaptureEnter(core.OpCode(typ), core.Address(from), core.Address(to), input, gas, value)
|
||||
}
|
||||
func (w WrappedTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
|
||||
w.r.CaptureExit(output, gasUsed, err)
|
||||
}
|
||||
func (w WrappedTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
|
||||
w.r.CaptureFault(pc, core.OpCode(op), gas, cost, &WrappedScopeContext{scope}, depth, err)
|
||||
}
|
||||
// passing zero as a dummy value is foundation PluGeth only, it is being done to preserve compatability with other networks
|
||||
func (w WrappedTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
|
||||
w.r.CaptureEnd(output, gasUsed, 0, err)
|
||||
}
|
||||
func (w WrappedTracer) GetResult() (json.RawMessage, error) {
|
||||
data, err := w.r.Result()
|
||||
if err != nil { return nil, err}
|
||||
result, err := json.Marshal(data)
|
||||
return json.RawMessage(result), err
|
||||
}
|
||||
func (w WrappedTracer) CaptureTxStart (gasLimit uint64) {}
|
||||
|
||||
func (w WrappedTracer) CaptureTxEnd (restGas uint64) {}
|
||||
|
||||
func (w WrappedTracer) Stop(err error) {}
|
||||
|
||||
|
||||
type WrappedStateDB struct {
|
||||
s *state.StateDB
|
||||
}
|
||||
|
||||
func NewWrappedStateDB(d *state.StateDB) *WrappedStateDB {
|
||||
return &WrappedStateDB{d}
|
||||
}
|
||||
|
||||
// GetBalance(Address) *big.Int
|
||||
func (w *WrappedStateDB) GetBalance(addr core.Address) *big.Int {
|
||||
return new(big.Int).SetBytes(w.s.GetBalance(common.Address(addr)).Bytes())
|
||||
|
||||
}
|
||||
|
||||
// GetNonce(Address) uint64
|
||||
func (w *WrappedStateDB) GetNonce(addr core.Address) uint64 {
|
||||
return w.s.GetNonce(common.Address(addr))
|
||||
}
|
||||
|
||||
// GetCodeHash(Address) Hash
|
||||
func (w *WrappedStateDB) GetCodeHash(addr core.Address) core.Hash {
|
||||
return core.Hash(w.s.GetCodeHash(common.Address(addr)))
|
||||
} // sort this out
|
||||
|
||||
// GetCode(Address) []byte
|
||||
func (w *WrappedStateDB) GetCode(addr core.Address) []byte {
|
||||
return w.s.GetCode(common.Address(addr))
|
||||
}
|
||||
|
||||
// GetCodeSize(Address) int
|
||||
func (w *WrappedStateDB) GetCodeSize(addr core.Address) int {
|
||||
return w.s.GetCodeSize(common.Address(addr))
|
||||
}
|
||||
|
||||
//GetRefund() uint64
|
||||
func (w *WrappedStateDB) GetRefund() uint64 { //are we sure we want to include this? getting a refund seems like changing state
|
||||
return w.s.GetRefund()
|
||||
}
|
||||
|
||||
// GetCommittedState(Address, Hash) Hash
|
||||
func (w *WrappedStateDB) GetCommittedState(addr core.Address, hsh core.Hash) core.Hash {
|
||||
return core.Hash(w.s.GetCommittedState(common.Address(addr), common.Hash(hsh)))
|
||||
}
|
||||
|
||||
// GetState(Address, Hash) Hash
|
||||
func (w *WrappedStateDB) GetState(addr core.Address, hsh core.Hash) core.Hash {
|
||||
return core.Hash(w.s.GetState(common.Address(addr), common.Hash(hsh)))
|
||||
}
|
||||
|
||||
// HasSuicided(Address) bool
|
||||
func (w *WrappedStateDB) HasSuicided(addr core.Address) bool {
|
||||
return w.s.HasSelfDestructed(common.Address(addr))
|
||||
}
|
||||
|
||||
// // Exist reports whether the given account exists in state.
|
||||
// // Notably this should also return true for suicided accounts.
|
||||
// Exist(Address) bool
|
||||
func (w *WrappedStateDB) Exist(addr core.Address) bool {
|
||||
return w.s.Exist(common.Address(addr))
|
||||
}
|
||||
|
||||
// // Empty returns whether the given account is empty. Empty
|
||||
// // is defined according to EIP161 (balance = nonce = code = 0).
|
||||
// Empty(Address) bool
|
||||
func (w *WrappedStateDB) Empty(addr core.Address) bool {
|
||||
return w.s.Empty(common.Address(addr))
|
||||
}
|
||||
|
||||
// AddressInAccessList(addr Address) bool
|
||||
func (w *WrappedStateDB) AddressInAccessList(addr core.Address) bool {
|
||||
return w.s.AddressInAccessList(common.Address(addr))
|
||||
}
|
||||
|
||||
// SlotInAccessList(addr Address, slot Hash) (addressOk bool, slotOk bool)
|
||||
func (w *WrappedStateDB) SlotInAccessList(addr core.Address, slot core.Hash) (addressOK, slotOk bool) {
|
||||
return w.s.SlotInAccessList(common.Address(addr), common.Hash(slot))
|
||||
}
|
||||
|
||||
// IntermediateRoot(deleteEmptyObjects bool) common.Hash
|
||||
func (w *WrappedStateDB) IntermediateRoot(deleteEmptyObjects bool) core.Hash {
|
||||
return core.Hash(w.s.IntermediateRoot(deleteEmptyObjects))
|
||||
}
|
||||
|
||||
func (w *WrappedStateDB) AddBalance(addr core.Address, amount *big.Int) {
|
||||
castAmount := new(uint256.Int)
|
||||
w.s.AddBalance(common.Address(addr), castAmount.SetBytes(amount.Bytes()))
|
||||
}
|
||||
|
||||
type Node struct {
|
||||
n *node.Node
|
||||
}
|
||||
|
||||
func NewNode(n *node.Node) *Node {
|
||||
return &Node{n}
|
||||
}
|
||||
|
||||
func (n *Node) Server() core.Server {
|
||||
return n.n.Server()
|
||||
}
|
||||
|
||||
func (n *Node) DataDir() string {
|
||||
return n.n.DataDir()
|
||||
}
|
||||
func (n *Node) InstanceDir() string {
|
||||
return n.n.InstanceDir()
|
||||
}
|
||||
func (n *Node) IPCEndpoint() string {
|
||||
return n.n.IPCEndpoint()
|
||||
}
|
||||
func (n *Node) HTTPEndpoint() string {
|
||||
return n.n.HTTPEndpoint()
|
||||
}
|
||||
func (n *Node) WSEndpoint() string {
|
||||
return n.n.WSEndpoint()
|
||||
}
|
||||
func (n *Node) ResolvePath(x string) string {
|
||||
return n.n.ResolvePath(x)
|
||||
}
|
||||
func (n *Node) Attach() (core.Client, error) {
|
||||
return n.n.Attach(), nil
|
||||
}
|
||||
func (n *Node) Close() error {
|
||||
return n.n.Close()
|
||||
}
|
||||
|
||||
type WrappedBlockContext struct {
|
||||
b vm.BlockContext
|
||||
}
|
||||
|
||||
// type WrappedBlockContext vm.BlockContext
|
||||
|
||||
func NewWrappedBlockContext(c vm.BlockContext) *WrappedBlockContext {
|
||||
return &WrappedBlockContext{c}
|
||||
}
|
||||
func (w *WrappedBlockContext) Coinbase() core.Address {
|
||||
return core.Address(w.b.Coinbase)
|
||||
}
|
||||
func (w *WrappedBlockContext) GasLimit() uint64 {
|
||||
return w.b.GasLimit
|
||||
}
|
||||
func (w *WrappedBlockContext) BlockNumber() *big.Int {
|
||||
return w.b.BlockNumber
|
||||
}
|
||||
func (w *WrappedBlockContext) Time() *big.Int {
|
||||
return new(big.Int).SetInt64(int64(w.b.Time))
|
||||
}
|
||||
func (w *WrappedBlockContext) Difficulty() *big.Int {
|
||||
return w.b.Difficulty
|
||||
}
|
||||
func (w *WrappedBlockContext) BaseFee() *big.Int {
|
||||
return w.b.BaseFee
|
||||
}
|
28
rpc/getRPCcall_test.go
Normal file
28
rpc/getRPCcall_test.go
Normal file
@ -0,0 +1,28 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
)
|
||||
|
||||
func TestGetRPCCalls(t *testing.T) {
|
||||
invoked := false
|
||||
done := plugins.HookTester("GetRPCCalls", func(id, method, params string) {
|
||||
invoked = true
|
||||
if id == "" {
|
||||
t.Errorf("Expected id to be non-nil")
|
||||
}
|
||||
if method == "" {
|
||||
t.Errorf("Expected method to be non-nil")
|
||||
}
|
||||
if params == "" {
|
||||
t.Errorf("Expected params to be non-nil")
|
||||
}
|
||||
})
|
||||
defer done()
|
||||
TestClientResponseType(t)
|
||||
if !invoked {
|
||||
t.Errorf("Expected plugin invocation")
|
||||
}
|
||||
}
|
@ -508,6 +508,10 @@ func (h *handler) handleCall(cp *callProc, msg *jsonrpcMessage) *jsonrpcMessage
|
||||
if err != nil {
|
||||
return msg.errorResponse(&invalidParamsError{err.Error()})
|
||||
}
|
||||
|
||||
//begin PluGeth code injection
|
||||
pluginGetRPCCalls(string(msg.ID), string(msg.Method), string(msg.Params))
|
||||
//begin PluGeth code injection
|
||||
start := time.Now()
|
||||
answer := h.runMethod(cp.ctx, msg, callb, args)
|
||||
|
||||
|
26
rpc/plugin_hooks.go
Normal file
26
rpc/plugin_hooks.go
Normal file
@ -0,0 +1,26 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
)
|
||||
|
||||
func PluginGetRPCCalls(pl *plugins.PluginLoader, id, method, params string) {
|
||||
fnList := pl.Lookup("GetRPCCalls", func(item interface{}) bool {
|
||||
_, ok := item.(func(string, string, string))
|
||||
return ok
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func(string, string, string)); ok {
|
||||
fn(id, method, params)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func pluginGetRPCCalls(id, method, params string) {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting GerRPCCalls, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
PluginGetRPCCalls(plugins.DefaultPluginLoader, id, method, params)
|
||||
}
|
162
rpc/plugin_subscriptions.go
Normal file
162
rpc/plugin_subscriptions.go
Normal file
@ -0,0 +1,162 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
)
|
||||
|
||||
// Is t context.Context or *context.Context?
|
||||
func isContextType(t reflect.Type) bool {
|
||||
for t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
return t == contextType
|
||||
}
|
||||
|
||||
func isChanType(t reflect.Type) bool {
|
||||
// Pointers to channels are weird, but whatever
|
||||
for t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
// Make sure we have a channel
|
||||
if t.Kind() != reflect.Chan {
|
||||
return false
|
||||
}
|
||||
// Make sure it is a receivable channel
|
||||
return (t.ChanDir() & reflect.RecvDir) == reflect.RecvDir
|
||||
}
|
||||
|
||||
func isChanPubsub(methodType reflect.Type) bool {
|
||||
if methodType.NumIn() < 2 || methodType.NumOut() != 2 {
|
||||
return false
|
||||
}
|
||||
return isContextType(methodType.In(1)) &&
|
||||
isChanType(methodType.Out(0)) &&
|
||||
isErrorType(methodType.Out(1))
|
||||
}
|
||||
|
||||
func callbackifyChanPubSub(receiver, fn reflect.Value) *callback {
|
||||
c := &callback{rcvr: receiver, errPos: 1, isSubscribe: true}
|
||||
fntype := fn.Type()
|
||||
// Skip receiver and context.Context parameter (if present).
|
||||
firstArg := 0
|
||||
if c.rcvr.IsValid() {
|
||||
firstArg++
|
||||
}
|
||||
if fntype.NumIn() > firstArg && fntype.In(firstArg) == contextType {
|
||||
c.hasCtx = true
|
||||
firstArg++
|
||||
}
|
||||
// Add all remaining parameters.
|
||||
c.argTypes = make([]reflect.Type, fntype.NumIn()-firstArg)
|
||||
for i := firstArg; i < fntype.NumIn(); i++ {
|
||||
c.argTypes[i-firstArg] = fntype.In(i)
|
||||
}
|
||||
|
||||
retFnType := reflect.FuncOf(append([]reflect.Type{receiver.Type(), contextType}, c.argTypes...), []reflect.Type{subscriptionType, errorType}, false)
|
||||
|
||||
// // What follows uses reflection to construct a dynamically typed function equivalent to:
|
||||
// func(receiver <T>, cctx context.Context, args ...<T>) (rpc.Subscription, error) {
|
||||
// notifier, supported := NotifierFromContext(cctx)
|
||||
// if !supported { return Subscription{}, ErrNotificationsUnsupported}
|
||||
// ctx, cancel := context.WithCancel(context.Background())
|
||||
// ch, err := fn()
|
||||
// if err != nil { return Subscription{}, err }
|
||||
// rpcSub := notifier.CreateSubscription()
|
||||
// go func() {
|
||||
// select {
|
||||
// case v, ok := <- ch:
|
||||
// if !ok { return }
|
||||
// notifier.Notify(rpcSub.ID, v)
|
||||
// case <-rpcSub.Err():
|
||||
// cancel()
|
||||
// return
|
||||
// case <-notifier.Closed():
|
||||
// cancel()
|
||||
// return
|
||||
// }
|
||||
// }()
|
||||
// return rpcSub, nil
|
||||
// }
|
||||
//
|
||||
|
||||
c.fn = reflect.MakeFunc(retFnType, func(args []reflect.Value) ([]reflect.Value) {
|
||||
notifier, supported := NotifierFromContext(args[1].Interface().(context.Context))
|
||||
if !supported {
|
||||
return []reflect.Value{reflect.Zero(subscriptionType), reflect.ValueOf(ErrNotificationsUnsupported)}
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
args[1] = reflect.ValueOf(ctx)
|
||||
out := fn.Call(args)
|
||||
if !out[1].IsNil() {
|
||||
// This amounts to: if err != nil { return nil, err }
|
||||
return []reflect.Value{reflect.Zero(subscriptionType), out[1]}
|
||||
}
|
||||
// Geth's provided context is done once we've returned the subscription id.
|
||||
// This new context will cancel when the notifier closes.
|
||||
|
||||
rpcSub := notifier.CreateSubscription()
|
||||
go func() {
|
||||
defer log.Info("Plugin subscription goroutine closed")
|
||||
selectCases := []reflect.SelectCase{
|
||||
{Dir: reflect.SelectRecv, Chan: out[0]},
|
||||
{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(rpcSub.Err())},
|
||||
{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(notifier.Closed())},
|
||||
}
|
||||
for {
|
||||
chosen, val, recvOK := reflect.Select(selectCases)
|
||||
switch chosen {
|
||||
case 0: // val, ok := <-ch
|
||||
if !recvOK {
|
||||
return
|
||||
}
|
||||
if err := notifier.Notify(rpcSub.ID, val.Interface()); err != nil {
|
||||
log.Warn("Subscription notification failed", "id", rpcSub.ID, "err", err)
|
||||
}
|
||||
case 1:
|
||||
cancel()
|
||||
return
|
||||
case 2:
|
||||
cancel()
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
return []reflect.Value{reflect.ValueOf(*rpcSub), reflect.Zero(errorType)}
|
||||
})
|
||||
return c
|
||||
}
|
||||
|
||||
func RPCSubscription(pl *plugins.PluginLoader) {
|
||||
fnList := pl.Lookup("RPCSubscriptionTest", func(item interface{}) bool {
|
||||
_, ok := item.(func())
|
||||
return ok
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func()); ok {
|
||||
fn()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func pluginExtendedCallbacks(callbacks map[string]*callback, receiver reflect.Value) {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting RPCSubscriptionTest, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
RPCSubscription(plugins.DefaultPluginLoader)
|
||||
typ := receiver.Type()
|
||||
for m := 0; m < typ.NumMethod(); m++ {
|
||||
method := typ.Method(m)
|
||||
if method.PkgPath != "" {
|
||||
continue // method not exported
|
||||
}
|
||||
if isChanPubsub(method.Type) {
|
||||
cb := callbackifyChanPubSub(receiver, method.Func)
|
||||
name := formatName(method.Name)
|
||||
callbacks[name] = cb
|
||||
}
|
||||
}
|
||||
}
|
@ -63,6 +63,9 @@ func (r *serviceRegistry) registerName(name string, rcvr interface{}) error {
|
||||
return fmt.Errorf("no service name for type %s", rcvrVal.Type().String())
|
||||
}
|
||||
callbacks := suitableCallbacks(rcvrVal)
|
||||
// begin PluGeth code injection
|
||||
pluginExtendedCallbacks(callbacks, rcvrVal)
|
||||
// end PluGeth code injection
|
||||
if len(callbacks) == 0 {
|
||||
return fmt.Errorf("service %T doesn't have any suitable methods/subscriptions to expose", rcvr)
|
||||
}
|
||||
|
87
slack-post.sh
Executable file
87
slack-post.sh
Executable file
@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Usage: slackpost -w <webhook_url> -c <channel> -u <username> -m <message> [-a <alert_type>]
|
||||
# Usage: echo <message> | slackpost -w <webhook_url> -c <channel> -u <username> [-a <alert_type>]
|
||||
|
||||
# exit immediately if a command exits with a non-zero status
|
||||
set -e
|
||||
|
||||
# error if variable referenced before being set
|
||||
set -u
|
||||
|
||||
# produce failure return code if any command fails in pipe
|
||||
set -o pipefail
|
||||
|
||||
# accepted values: good, warning, danger
|
||||
alert_type=""
|
||||
channel=""
|
||||
message=""
|
||||
username=""
|
||||
webhook_url=""
|
||||
|
||||
# colon after var means it has a value rather than it being a bool flag
|
||||
while getopts 'a:c:m:u:w:' OPTION; do
|
||||
case "$OPTION" in
|
||||
a)
|
||||
alert_type="$OPTARG"
|
||||
;;
|
||||
c)
|
||||
channel="$OPTARG"
|
||||
;;
|
||||
m)
|
||||
message="$OPTARG"
|
||||
;;
|
||||
u)
|
||||
username="$OPTARG"
|
||||
;;
|
||||
w)
|
||||
webhook_url="$OPTARG"
|
||||
;;
|
||||
?)
|
||||
echo "script usage: $(basename $0) {-c channel} {-m message} {-u username} {-w webhook} [-a alert_type]" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift "$(($OPTIND -1))"
|
||||
|
||||
# # exit if channel not provided
|
||||
# if [[ -z "$channel" ]]
|
||||
# then
|
||||
# echo "No channel specified"
|
||||
# exit 1
|
||||
# fi
|
||||
|
||||
# read piped data as message if message argument is not provided
|
||||
if [[ -z "$message" ]]
|
||||
then
|
||||
message=$*
|
||||
|
||||
while IFS= read -r line; do
|
||||
message="$message$line\n"
|
||||
done
|
||||
fi
|
||||
|
||||
# # exit if username not provided
|
||||
# if [[ -z "$username" ]]
|
||||
# then
|
||||
# echo "No username specified"
|
||||
# exit 1
|
||||
# fi
|
||||
|
||||
# exit if webhook not provided
|
||||
if [[ -z "$webhook_url" ]]
|
||||
then
|
||||
echo "No webhook_url specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# escape message text
|
||||
escapedText=$(echo $message | sed 's/"/\"/g' | sed "s/'/\'/g")
|
||||
|
||||
# create JSON payload
|
||||
# json="{\"channel\": \"$channel\", \"username\":\"$username\", \"icon_emoji\":\"ghost\", \"attachments\":[{\"color\":\"$alert_type\" , \"text\": \"$escapedText\"}]}"
|
||||
json="{\"attachments\":[{\"color\":\"$alert_type\" , \"text\": \"$escapedText\"}]}"
|
||||
|
||||
# fire off slack message post
|
||||
curl -s -d "payload=$json" "$webhook_url"
|
@ -413,6 +413,11 @@ func (db *Database) Commit(node common.Hash, report bool) error {
|
||||
// outside code doesn't see an inconsistent state (referenced data removed from
|
||||
// memory cache during commit but not yet in persistent storage). This is ensured
|
||||
// by only uncaching existing data when the database write finalizes.
|
||||
|
||||
// begin PluGeth injection
|
||||
pluginPreTrieCommit(node)
|
||||
// end PluGeth injection
|
||||
|
||||
start := time.Now()
|
||||
batch := db.diskdb.NewBatch()
|
||||
|
||||
@ -451,6 +456,10 @@ func (db *Database) Commit(node common.Hash, report bool) error {
|
||||
db.gcnodes, db.gcsize, db.gctime = 0, 0, 0
|
||||
db.flushnodes, db.flushsize, db.flushtime = 0, 0, 0
|
||||
|
||||
// begin PluGeth injection
|
||||
pluginPostTrieCommit(node)
|
||||
// end PluGeth injection
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
48
triedb/hashdb/plugin_hooks.go
Normal file
48
triedb/hashdb/plugin_hooks.go
Normal file
@ -0,0 +1,48 @@
|
||||
package hashdb
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/openrelayxyz/plugeth-utils/core"
|
||||
)
|
||||
|
||||
func PluginPreTrieCommit(pl *plugins.PluginLoader, node common.Hash) {
|
||||
fnList := pl.Lookup("PreTrieCommit", func(item interface{}) bool {
|
||||
_, ok := item.(func(core.Hash))
|
||||
return ok
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func(core.Hash)); ok {
|
||||
fn(core.Hash(node))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func pluginPreTrieCommit(node common.Hash) {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting PreTrieCommit, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
PluginPreTrieCommit(plugins.DefaultPluginLoader, node)
|
||||
}
|
||||
|
||||
func PluginPostTrieCommit(pl *plugins.PluginLoader, node common.Hash) {
|
||||
fnList := pl.Lookup("PostTrieCommit", func(item interface{}) bool {
|
||||
_, ok := item.(func(core.Hash))
|
||||
return ok
|
||||
})
|
||||
for _, fni := range fnList {
|
||||
if fn, ok := fni.(func(core.Hash)); ok {
|
||||
fn(core.Hash(node))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func pluginPostTrieCommit(node common.Hash) {
|
||||
if plugins.DefaultPluginLoader == nil {
|
||||
log.Warn("Attempting PostTrieCommit, but default PluginLoader has not been initialized")
|
||||
return
|
||||
}
|
||||
PluginPostTrieCommit(plugins.DefaultPluginLoader, node)
|
||||
}
|
101
wrapmain/go.mod
Normal file
101
wrapmain/go.mod
Normal file
@ -0,0 +1,101 @@
|
||||
module github.com/cerc-io/plugeth-statediff/wrapmain
|
||||
|
||||
go 1.19
|
||||
|
||||
require github.com/ethereum/go-ethereum v1.11.6
|
||||
|
||||
require (
|
||||
github.com/DataDog/zstd v1.5.2 // indirect
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
|
||||
github.com/VictoriaMetrics/fastcache v1.6.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cockroachdb/errors v1.9.1 // indirect
|
||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
|
||||
github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 // indirect
|
||||
github.com/cockroachdb/redact v1.1.3 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/crate-crypto/go-ipa v0.0.0-20220523130400-f11357ae11c7 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/deckarep/golang-set/v2 v2.1.0 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
|
||||
github.com/deepmap/oapi-codegen v1.8.2 // indirect
|
||||
github.com/dlclark/regexp2 v1.7.0 // indirect
|
||||
github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7 // indirect
|
||||
github.com/edsrzf/mmap-go v1.0.0 // indirect
|
||||
github.com/fatih/color v1.7.0 // indirect
|
||||
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
|
||||
github.com/gballet/go-verkle v0.0.0-20220902153445-097bd83b7732 // indirect
|
||||
github.com/getsentry/sentry-go v0.18.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.1 // indirect
|
||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
||||
github.com/go-stack/stack v1.8.1 // indirect
|
||||
github.com/gofrs/flock v0.8.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.3.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/graph-gophers/graphql-go v1.3.0 // indirect
|
||||
github.com/hashicorp/go-bexpr v0.1.10 // indirect
|
||||
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
|
||||
github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect
|
||||
github.com/huin/goupnp v1.0.3 // indirect
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c // indirect
|
||||
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
|
||||
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
|
||||
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e // indirect
|
||||
github.com/karalabe/usb v0.0.2 // indirect
|
||||
github.com/klauspost/compress v1.15.15 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
||||
github.com/mitchellh/pointerstructure v1.2.0 // indirect
|
||||
github.com/naoina/go-stringutil v0.1.0 // indirect
|
||||
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/openrelayxyz/plugeth-utils v1.2.0 // indirect
|
||||
github.com/opentracing/opentracing-go v1.1.0 // indirect
|
||||
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/prometheus/client_golang v1.14.0 // indirect
|
||||
github.com/prometheus/client_model v0.3.0 // indirect
|
||||
github.com/prometheus/common v0.39.0 // indirect
|
||||
github.com/prometheus/procfs v0.9.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.9.0 // indirect
|
||||
github.com/rs/cors v1.7.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
|
||||
github.com/status-im/keycard-go v0.2.0 // indirect
|
||||
github.com/stretchr/testify v1.8.1 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.5 // indirect
|
||||
github.com/tklauser/numcpus v0.2.2 // indirect
|
||||
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
|
||||
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
golang.org/x/crypto v0.1.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/sync v0.1.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/ethereum/go-ethereum => ../
|
||||
|
||||
replace github.com/openrelayxyz/plugeth-utils => git.vdb.to/cerc-io/plugeth-utils v0.0.0-20230706160122-cd41de354c46
|
575
wrapmain/go.sum
Normal file
575
wrapmain/go.sum
Normal file
@ -0,0 +1,575 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
git.vdb.to/cerc-io/plugeth-utils v0.0.0-20230706160122-cd41de354c46 h1:KYcbbne/RXd7AuxbUd/3hgk1jPN+33k2CKiNsUsMCC0=
|
||||
git.vdb.to/cerc-io/plugeth-utils v0.0.0-20230706160122-cd41de354c46/go.mod h1:VpDN61dxy64zGff05F0adujR5enD/JEdXBkTQ+PaIsQ=
|
||||
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0=
|
||||
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
|
||||
github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo=
|
||||
github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8=
|
||||
github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
||||
github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
|
||||
github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o=
|
||||
github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw=
|
||||
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
||||
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
|
||||
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU=
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA=
|
||||
github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
|
||||
github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8=
|
||||
github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk=
|
||||
github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
|
||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
|
||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
|
||||
github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk=
|
||||
github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM=
|
||||
github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ=
|
||||
github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/crate-crypto/go-ipa v0.0.0-20220523130400-f11357ae11c7 h1:6IrxszG5G+O7zhtkWxq6+unVvnrm1fqV2Pe+T95DUzw=
|
||||
github.com/crate-crypto/go-ipa v0.0.0-20220523130400-f11357ae11c7/go.mod h1:gFnFS95y8HstDP6P9pPwzrxOOC5TRDkwbM+ao15ChAI=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI=
|
||||
github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
|
||||
github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M=
|
||||
github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbzjuhfU=
|
||||
github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw=
|
||||
github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
|
||||
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/docker/docker v1.6.2 h1:HlFGsy+9/xrgMmhmN+NGhCc5SHGJ7I+kHosRR1xc/aI=
|
||||
github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
|
||||
github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7 h1:kgvzE5wLsLa7XKfV85VZl40QXaMCaeFtHpPwJ8fhotY=
|
||||
github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7/go.mod h1:yRkwfj0CBpOGre+TwBsqPV0IH0Pk73e4PXJOeNDboGs=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
|
||||
github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
|
||||
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
|
||||
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
|
||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
|
||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
|
||||
github.com/gballet/go-verkle v0.0.0-20220902153445-097bd83b7732 h1:AB7YjNrzlVHsYz06zCULVV2zYCEft82P86dSmtwxKL0=
|
||||
github.com/gballet/go-verkle v0.0.0-20220902153445-097bd83b7732/go.mod h1:o/XfIXWi4/GqbQirfRm5uTbXMG5NpqxkxblnbZ+QM9I=
|
||||
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
|
||||
github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
|
||||
github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c=
|
||||
github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0=
|
||||
github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
|
||||
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
|
||||
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
|
||||
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
|
||||
github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
|
||||
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU=
|
||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
|
||||
github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
|
||||
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
|
||||
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
||||
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||
github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog=
|
||||
github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk=
|
||||
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
|
||||
github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0=
|
||||
github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
|
||||
github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE=
|
||||
github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao=
|
||||
github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA=
|
||||
github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8=
|
||||
github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ=
|
||||
github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y=
|
||||
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
|
||||
github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE=
|
||||
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k=
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSHzRbhzK8RdXOsAdfDgO49TtqC1oZ+acxPrkfTxcCs=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
|
||||
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 h1:vilfsDSy7TDxedi9gyBkMvAirat/oRcL0lFdJBf6tdM=
|
||||
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
|
||||
github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI=
|
||||
github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0=
|
||||
github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk=
|
||||
github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g=
|
||||
github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e h1:UvSe12bq+Uj2hWd8aOlwPmoZ+CITRFrdit+sDGfAg8U=
|
||||
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
|
||||
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
|
||||
github.com/karalabe/usb v0.0.2 h1:M6QQBNxF+CQ8OFvxrT90BA0qBOXymndZnk5q235mFc4=
|
||||
github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
|
||||
github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8=
|
||||
github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE=
|
||||
github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE=
|
||||
github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro=
|
||||
github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw=
|
||||
github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4=
|
||||
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg=
|
||||
github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y=
|
||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
|
||||
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
|
||||
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A=
|
||||
github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
|
||||
github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks=
|
||||
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
|
||||
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcouEdwIeOtOGA/ELRUw/GwvxwfT+0=
|
||||
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
|
||||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
|
||||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
|
||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM=
|
||||
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
|
||||
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
||||
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
|
||||
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
|
||||
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
|
||||
github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI=
|
||||
github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y=
|
||||
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
|
||||
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
|
||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA=
|
||||
github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
||||
github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4=
|
||||
github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
|
||||
github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
|
||||
github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
|
||||
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
|
||||
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q=
|
||||
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI=
|
||||
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
|
||||
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
|
||||
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
|
||||
github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg=
|
||||
golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y=
|
||||
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
|
||||
google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
|
||||
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
|
||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user