Merge pull request #95 from jdkanani/geth-bor

use go-ethereum for better forked-bor release  and geth v1.9.24 upgrade
This commit is contained in:
Jaynti Kanani 2020-11-23 13:33:15 +05:30 committed by GitHub
commit 3de2110886
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
849 changed files with 35186 additions and 23302 deletions

View file

@ -7,7 +7,7 @@ executors:
golang: golang:
docker: docker:
- image: circleci/golang:1.13 - image: circleci/golang:1.13
working_directory: /go/src/github.com/maticnetwork/bor working_directory: /go/src/github.com/ethereum/go-ethereum
jobs: jobs:
build: build:

11
.github/CODEOWNERS vendored
View file

@ -3,21 +3,20 @@
accounts/usbwallet @karalabe accounts/usbwallet @karalabe
accounts/scwallet @gballet accounts/scwallet @gballet
accounts/abi @gballet accounts/abi @gballet @MariusVanDerWijden
cmd/clef @holiman cmd/clef @holiman
cmd/puppeth @karalabe cmd/puppeth @karalabe
consensus @karalabe consensus @karalabe
core/ @karalabe @holiman @rjl493456442 core/ @karalabe @holiman @rjl493456442
dashboard/ @kurkomisi
eth/ @karalabe @holiman @rjl493456442 eth/ @karalabe @holiman @rjl493456442
graphql/ @gballet graphql/ @gballet
les/ @zsfelfoldi @rjl493456442 les/ @zsfelfoldi @rjl493456442
light/ @zsfelfoldi @rjl493456442 light/ @zsfelfoldi @rjl493456442
mobile/ @karalabe @ligi mobile/ @karalabe @ligi
node/ @fjl @renaynay
p2p/ @fjl @zsfelfoldi p2p/ @fjl @zsfelfoldi
rpc/ @fjl @holiman rpc/ @fjl @holiman
p2p/simulations @zelig @janos @justelad p2p/simulations @fjl
p2p/protocols @zelig @janos @justelad p2p/protocols @fjl
p2p/testing @zelig @janos @justelad p2p/testing @fjl
signer/ @holiman signer/ @holiman
whisper/ @gballet @gluk256

View file

@ -8,7 +8,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v1 uses: actions/setup-go@v1
with: with:
go-version: 1.14.7 go-version: 1.15.5
- name: "Build binaries" - name: "Build binaries"
run: make all run: make all
- name: "Run tests" - name: "Run tests"

View file

@ -13,7 +13,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v1 uses: actions/setup-go@v1
with: with:
go-version: 1.14.7 go-version: 1.15.5
- name: Set up Ruby 2.6 - name: Set up Ruby 2.6
uses: actions/setup-ruby@v1 uses: actions/setup-ruby@v1

View file

@ -1,5 +1,5 @@
language: go language: go
go_import_path: github.com/maticnetwork/bor go_import_path: github.com/ethereum/go-ethereum
sudo: false sudo: false
jobs: jobs:
allow_failures: allow_failures:
@ -16,7 +16,7 @@ jobs:
- stage: lint - stage: lint
os: linux os: linux
dist: xenial dist: xenial
go: 1.14.x go: 1.15.x
env: env:
- lint - lint
git: git:
@ -24,65 +24,12 @@ jobs:
script: script:
- go run build/ci.go lint - go run build/ci.go lint
- stage: build
os: linux
dist: xenial
go: 1.13.x
env:
- GO111MODULE=on
script:
- go run build/ci.go install
- go run build/ci.go test -coverage $TEST_PACKAGES
# These are the latest Go versions.
- stage: build
os: linux
arch: amd64
dist: xenial
go: 1.14.x
env:
- GO111MODULE=on
script:
- go run build/ci.go install
- go run build/ci.go test -coverage $TEST_PACKAGES
- stage: build
if: type = pull_request
os: linux
arch: arm64
dist: xenial
go: 1.14.x
env:
- GO111MODULE=on
script:
- go run build/ci.go install
- go run build/ci.go test -coverage $TEST_PACKAGES
- stage: build
os: osx
osx_image: xcode11.3
go: 1.14.x
env:
- GO111MODULE=on
script:
- echo "Increase the maximum number of open file descriptors on macOS"
- NOFILE=20480
- sudo sysctl -w kern.maxfiles=$NOFILE
- sudo sysctl -w kern.maxfilesperproc=$NOFILE
- sudo launchctl limit maxfiles $NOFILE $NOFILE
- sudo launchctl limit maxfiles
- ulimit -S -n $NOFILE
- ulimit -n
- unset -f cd # workaround for https://github.com/travis-ci/travis-ci/issues/8703
- go run build/ci.go install
- go run build/ci.go test -coverage $TEST_PACKAGES
# This builder does the Ubuntu PPA upload # This builder does the Ubuntu PPA upload
- stage: build - stage: build
if: type = push if: type = push
os: linux os: linux
dist: xenial dist: xenial
go: 1.14.x go: 1.15.x
env: env:
- ubuntu-ppa - ubuntu-ppa
- GO111MODULE=on - GO111MODULE=on
@ -107,7 +54,7 @@ jobs:
os: linux os: linux
dist: xenial dist: xenial
sudo: required sudo: required
go: 1.14.x go: 1.15.x
env: env:
- azure-linux - azure-linux
- GO111MODULE=on - GO111MODULE=on
@ -119,22 +66,22 @@ jobs:
- gcc-multilib - gcc-multilib
script: script:
# Build for the primary platforms that Trusty can manage # Build for the primary platforms that Trusty can manage
- go run build/ci.go install - go run build/ci.go install -dlgo
- go run build/ci.go archive -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds - go run build/ci.go archive -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
- go run build/ci.go install -arch 386 - go run build/ci.go install -dlgo -arch 386
- go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds - go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
# Switch over GCC to cross compilation (breaks 386, hence why do it here only) # Switch over GCC to cross compilation (breaks 386, hence why do it here only)
- sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross - sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross
- sudo ln -s /usr/include/asm-generic /usr/include/asm - sudo ln -s /usr/include/asm-generic /usr/include/asm
- GOARM=5 go run build/ci.go install -arch arm -cc arm-linux-gnueabi-gcc - GOARM=5 go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc
- GOARM=5 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds - GOARM=5 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
- GOARM=6 go run build/ci.go install -arch arm -cc arm-linux-gnueabi-gcc - GOARM=6 go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc
- GOARM=6 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds - GOARM=6 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
- GOARM=7 go run build/ci.go install -arch arm -cc arm-linux-gnueabihf-gcc - GOARM=7 go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabihf-gcc
- GOARM=7 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds - GOARM=7 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
- go run build/ci.go install -arch arm64 -cc aarch64-linux-gnu-gcc - go run build/ci.go install -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc
- go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds - go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
# This builder does the Linux Azure MIPS xgo uploads # This builder does the Linux Azure MIPS xgo uploads
@ -144,7 +91,7 @@ jobs:
dist: xenial dist: xenial
services: services:
- docker - docker
go: 1.14.x go: 1.15.x
env: env:
- azure-linux-mips - azure-linux-mips
- GO111MODULE=on - GO111MODULE=on
@ -192,7 +139,7 @@ jobs:
git: git:
submodules: false # avoid cloning ethereum/tests submodules: false # avoid cloning ethereum/tests
before_install: before_install:
- curl https://dl.google.com/go/go1.14.2.linux-amd64.tar.gz | tar -xz - curl https://dl.google.com/go/go1.15.5.linux-amd64.tar.gz | tar -xz
- export PATH=`pwd`/go/bin:$PATH - export PATH=`pwd`/go/bin:$PATH
- export GOROOT=`pwd`/go - export GOROOT=`pwd`/go
- export GOPATH=$HOME/go - export GOPATH=$HOME/go
@ -203,14 +150,14 @@ jobs:
- mv android-ndk-r19b $ANDROID_HOME/ndk-bundle - mv android-ndk-r19b $ANDROID_HOME/ndk-bundle
- mkdir -p $GOPATH/src/github.com/ethereum - mkdir -p $GOPATH/src/github.com/ethereum
- ln -s `pwd` $GOPATH/src/github.com/maticnetwork/bor - ln -s `pwd` $GOPATH/src/github.com/ethereum/go-ethereum
- go run build/ci.go aar -signer ANDROID_SIGNING_KEY -deploy https://oss.sonatype.org -upload gethstore/builds - go run build/ci.go aar -signer ANDROID_SIGNING_KEY -deploy https://oss.sonatype.org -upload gethstore/builds
# This builder does the OSX Azure, iOS CocoaPods and iOS Azure uploads # This builder does the OSX Azure, iOS CocoaPods and iOS Azure uploads
- stage: build - stage: build
if: type = push if: type = push
os: osx os: osx
go: 1.14.x go: 1.15.x
env: env:
- azure-osx - azure-osx
- azure-ios - azure-ios
@ -219,7 +166,7 @@ jobs:
git: git:
submodules: false # avoid cloning ethereum/tests submodules: false # avoid cloning ethereum/tests
script: script:
- go run build/ci.go install - go run build/ci.go install -dlgo
- go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -upload gethstore/builds - go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -upload gethstore/builds
# Build the iOS framework and upload it to CocoaPods and Azure # Build the iOS framework and upload it to CocoaPods and Azure
@ -237,12 +184,43 @@ jobs:
- export CGO_CFLAGS_ALLOW='-fmodules|-fblocks|-fobjc-arc' - export CGO_CFLAGS_ALLOW='-fmodules|-fblocks|-fobjc-arc'
- go run build/ci.go xcode -signer IOS_SIGNING_KEY -deploy trunk -upload gethstore/builds - go run build/ci.go xcode -signer IOS_SIGNING_KEY -deploy trunk -upload gethstore/builds
# These builders run the tests
- stage: build
os: linux
arch: amd64
dist: xenial
go: 1.15.x
env:
- GO111MODULE=on
script:
- go run build/ci.go test -coverage $TEST_PACKAGES
- stage: build
if: type = pull_request
os: linux
arch: arm64
dist: xenial
go: 1.15.x
env:
- GO111MODULE=on
script:
- go run build/ci.go test -coverage $TEST_PACKAGES
- stage: build
os: linux
dist: xenial
go: 1.14.x
env:
- GO111MODULE=on
script:
- go run build/ci.go test -coverage $TEST_PACKAGES
# This builder does the Azure archive purges to avoid accumulating junk # This builder does the Azure archive purges to avoid accumulating junk
- stage: build - stage: build
if: type = cron if: type = cron
os: linux os: linux
dist: xenial dist: xenial
go: 1.14.x go: 1.15.x
env: env:
- azure-purge - azure-purge
- GO111MODULE=on - GO111MODULE=on

59
COPYING
View file

@ -1,7 +1,7 @@
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007 Version 3, 29 June 2007
Copyright (C) 2014 The go-ethereum Authors. Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
@ -616,4 +616,59 @@ above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee. copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program 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.
This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View file

@ -1,5 +1,5 @@
# Build Geth in a stock Go builder container # Build Geth in a stock Go builder container
FROM golang:1.14-alpine as builder FROM golang:1.15-alpine as builder
RUN apk add --no-cache make gcc musl-dev linux-headers git RUN apk add --no-cache make gcc musl-dev linux-headers git

View file

@ -1,10 +1,10 @@
# Build Geth in a stock Go builder container # Build Geth in a stock Go builder container
FROM golang:1.14-alpine as builder FROM golang:1.15-alpine as builder
RUN apk add --no-cache make gcc musl-dev linux-headers git RUN apk add --no-cache make gcc musl-dev linux-headers git
ADD . /bor ADD . /bor
RUN cd /bor && make all RUN cd /bor && make bor-all
# Pull all binaries into a second stage deploy alpine container # Pull all binaries into a second stage deploy alpine container
FROM alpine:latest FROM alpine:latest
@ -12,4 +12,4 @@ FROM alpine:latest
RUN apk add --no-cache ca-certificates RUN apk add --no-cache ca-certificates
COPY --from=builder /bor/build/bin/* /usr/local/bin/ COPY --from=builder /bor/build/bin/* /usr/local/bin/
EXPOSE 8545 8546 8547 30303 30303/udp EXPOSE 8545 8546 30303 30303/udp

152
Makefile
View file

@ -2,43 +2,53 @@
# with Go source code. If you know what GOPATH is then you probably # with Go source code. If you know what GOPATH is then you probably
# don't need to bother with make. # don't need to bother with make.
.PHONY: bor android ios bor-cross evm all test clean .PHONY: geth android ios geth-cross evm all test clean
.PHONY: bor-linux bor-linux-386 bor-linux-amd64 bor-linux-mips64 bor-linux-mips64le .PHONY: geth-linux geth-linux-386 geth-linux-amd64 geth-linux-mips64 geth-linux-mips64le
.PHONY: bor-linux-arm bor-linux-arm-5 bor-linux-arm-6 bor-linux-arm-7 bor-linux-arm64 .PHONY: geth-linux-arm geth-linux-arm-5 geth-linux-arm-6 geth-linux-arm-7 geth-linux-arm64
.PHONY: bor-darwin bor-darwin-386 bor-darwin-amd64 .PHONY: geth-darwin geth-darwin-386 geth-darwin-amd64
.PHONY: bor-windows bor-windows-386 bor-windows-amd64 .PHONY: geth-windows geth-windows-386 geth-windows-amd64
GOBIN = ./build/bin GOBIN = ./build/bin
GO ?= latest GO ?= latest
GORUN = go run GORUN = env GO111MODULE=on go run
GOPATH = $(shell go env GOPATH) GOPATH = $(shell go env GOPATH)
bor: bor:
$(GORUN) build/ci.go install ./cmd/bor $(GORUN) build/ci.go install ./cmd/geth
mkdir -p $(GOPATH)/bin/ mkdir -p $(GOPATH)/bin/
cp $(GOBIN)/bor $(GOPATH)/bin/ cp $(GOBIN)/geth $(GOBIN)/bor
cp $(GOBIN)/* $(GOPATH)/bin/
bor-all:
$(GORUN) build/ci.go install
mkdir -p $(GOPATH)/bin/
cp $(GOBIN)/geth $(GOBIN)/bor
cp $(GOBIN)/* $(GOPATH)/bin/
geth:
$(GORUN) build/ci.go install ./cmd/geth
@echo "Done building."
@echo "Run \"$(GOBIN)/geth\" to launch geth."
all: all:
$(GORUN) build/ci.go install $(GORUN) build/ci.go install
mkdir -p $(GOPATH)/bin/
cp $(GOBIN)/* $(GOPATH)/bin/
android: android:
$(GORUN) build/ci.go aar --local $(GORUN) build/ci.go aar --local
@echo "Done building." @echo "Done building."
@echo "Import \"$(GOBIN)/bor.aar\" to use the library." @echo "Import \"$(GOBIN)/geth.aar\" to use the library."
@echo "Import \"$(GOBIN)/geth-sources.jar\" to add javadocs"
@echo "For more info see https://stackoverflow.com/questions/20994336/android-studio-how-to-attach-javadoc"
ios: ios:
$(GORUN) build/ci.go xcode --local $(GORUN) build/ci.go xcode --local
@echo "Done building." @echo "Done building."
@echo "Import \"$(GOBIN)/bor.framework\" to use the library." @echo "Import \"$(GOBIN)/Geth.framework\" to use the library."
test: bor test: all
go test github.com/maticnetwork/bor/consensus/bor # $(GORUN) build/ci.go test
go test github.com/maticnetwork/bor/tests/bor go test github.com/ethereum/go-ethereum/consensus/bor
go test github.com/ethereum/go-ethereum/tests/bor
# test: all
# $(GORUN) build/ci.go test
lint: ## Run linters. lint: ## Run linters.
$(GORUN) build/ci.go lint $(GORUN) build/ci.go lint
@ -62,92 +72,92 @@ devtools:
# Cross Compilation Targets (xgo) # Cross Compilation Targets (xgo)
bor-cross: bor-linux bor-darwin bor-windows bor-android bor-ios geth-cross: geth-linux geth-darwin geth-windows geth-android geth-ios
@echo "Full cross compilation done:" @echo "Full cross compilation done:"
@ls -ld $(GOBIN)/bor-* @ls -ld $(GOBIN)/geth-*
bor-linux: bor-linux-386 bor-linux-amd64 bor-linux-arm bor-linux-mips64 bor-linux-mips64le geth-linux: geth-linux-386 geth-linux-amd64 geth-linux-arm geth-linux-mips64 geth-linux-mips64le
@echo "Linux cross compilation done:" @echo "Linux cross compilation done:"
@ls -ld $(GOBIN)/bor-linux-* @ls -ld $(GOBIN)/geth-linux-*
bor-linux-386: geth-linux-386:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/386 -v ./cmd/bor $(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/386 -v ./cmd/geth
@echo "Linux 386 cross compilation done:" @echo "Linux 386 cross compilation done:"
@ls -ld $(GOBIN)/bor-linux-* | grep 386 @ls -ld $(GOBIN)/geth-linux-* | grep 386
bor-linux-amd64: geth-linux-amd64:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/amd64 -v ./cmd/bor $(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/amd64 -v ./cmd/geth
@echo "Linux amd64 cross compilation done:" @echo "Linux amd64 cross compilation done:"
@ls -ld $(GOBIN)/bor-linux-* | grep amd64 @ls -ld $(GOBIN)/geth-linux-* | grep amd64
bor-linux-arm: bor-linux-arm-5 bor-linux-arm-6 bor-linux-arm-7 bor-linux-arm64 geth-linux-arm: geth-linux-arm-5 geth-linux-arm-6 geth-linux-arm-7 geth-linux-arm64
@echo "Linux ARM cross compilation done:" @echo "Linux ARM cross compilation done:"
@ls -ld $(GOBIN)/bor-linux-* | grep arm @ls -ld $(GOBIN)/geth-linux-* | grep arm
bor-linux-arm-5: geth-linux-arm-5:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/arm-5 -v ./cmd/bor $(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/arm-5 -v ./cmd/geth
@echo "Linux ARMv5 cross compilation done:" @echo "Linux ARMv5 cross compilation done:"
@ls -ld $(GOBIN)/bor-linux-* | grep arm-5 @ls -ld $(GOBIN)/geth-linux-* | grep arm-5
bor-linux-arm-6: geth-linux-arm-6:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/arm-6 -v ./cmd/bor $(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/arm-6 -v ./cmd/geth
@echo "Linux ARMv6 cross compilation done:" @echo "Linux ARMv6 cross compilation done:"
@ls -ld $(GOBIN)/bor-linux-* | grep arm-6 @ls -ld $(GOBIN)/geth-linux-* | grep arm-6
bor-linux-arm-7: geth-linux-arm-7:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/arm-7 -v ./cmd/bor $(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/arm-7 -v ./cmd/geth
@echo "Linux ARMv7 cross compilation done:" @echo "Linux ARMv7 cross compilation done:"
@ls -ld $(GOBIN)/bor-linux-* | grep arm-7 @ls -ld $(GOBIN)/geth-linux-* | grep arm-7
bor-linux-arm64: geth-linux-arm64:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/arm64 -v ./cmd/bor $(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/arm64 -v ./cmd/geth
@echo "Linux ARM64 cross compilation done:" @echo "Linux ARM64 cross compilation done:"
@ls -ld $(GOBIN)/bor-linux-* | grep arm64 @ls -ld $(GOBIN)/geth-linux-* | grep arm64
bor-linux-mips: geth-linux-mips:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/mips --ldflags '-extldflags "-static"' -v ./cmd/bor $(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/mips --ldflags '-extldflags "-static"' -v ./cmd/geth
@echo "Linux MIPS cross compilation done:" @echo "Linux MIPS cross compilation done:"
@ls -ld $(GOBIN)/bor-linux-* | grep mips @ls -ld $(GOBIN)/geth-linux-* | grep mips
bor-linux-mipsle: geth-linux-mipsle:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/mipsle --ldflags '-extldflags "-static"' -v ./cmd/bor $(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/mipsle --ldflags '-extldflags "-static"' -v ./cmd/geth
@echo "Linux MIPSle cross compilation done:" @echo "Linux MIPSle cross compilation done:"
@ls -ld $(GOBIN)/bor-linux-* | grep mipsle @ls -ld $(GOBIN)/geth-linux-* | grep mipsle
bor-linux-mips64: geth-linux-mips64:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/mips64 --ldflags '-extldflags "-static"' -v ./cmd/bor $(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/mips64 --ldflags '-extldflags "-static"' -v ./cmd/geth
@echo "Linux MIPS64 cross compilation done:" @echo "Linux MIPS64 cross compilation done:"
@ls -ld $(GOBIN)/bor-linux-* | grep mips64 @ls -ld $(GOBIN)/geth-linux-* | grep mips64
bor-linux-mips64le: geth-linux-mips64le:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/mips64le --ldflags '-extldflags "-static"' -v ./cmd/bor $(GORUN) build/ci.go xgo -- --go=$(GO) --targets=linux/mips64le --ldflags '-extldflags "-static"' -v ./cmd/geth
@echo "Linux MIPS64le cross compilation done:" @echo "Linux MIPS64le cross compilation done:"
@ls -ld $(GOBIN)/bor-linux-* | grep mips64le @ls -ld $(GOBIN)/geth-linux-* | grep mips64le
bor-darwin: bor-darwin-386 bor-darwin-amd64 geth-darwin: geth-darwin-386 geth-darwin-amd64
@echo "Darwin cross compilation done:" @echo "Darwin cross compilation done:"
@ls -ld $(GOBIN)/bor-darwin-* @ls -ld $(GOBIN)/geth-darwin-*
bor-darwin-386: geth-darwin-386:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=darwin/386 -v ./cmd/bor $(GORUN) build/ci.go xgo -- --go=$(GO) --targets=darwin/386 -v ./cmd/geth
@echo "Darwin 386 cross compilation done:" @echo "Darwin 386 cross compilation done:"
@ls -ld $(GOBIN)/bor-darwin-* | grep 386 @ls -ld $(GOBIN)/geth-darwin-* | grep 386
bor-darwin-amd64: geth-darwin-amd64:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=darwin/amd64 -v ./cmd/bor $(GORUN) build/ci.go xgo -- --go=$(GO) --targets=darwin/amd64 -v ./cmd/geth
@echo "Darwin amd64 cross compilation done:" @echo "Darwin amd64 cross compilation done:"
@ls -ld $(GOBIN)/bor-darwin-* | grep amd64 @ls -ld $(GOBIN)/geth-darwin-* | grep amd64
bor-windows: bor-windows-386 bor-windows-amd64 geth-windows: geth-windows-386 geth-windows-amd64
@echo "Windows cross compilation done:" @echo "Windows cross compilation done:"
@ls -ld $(GOBIN)/bor-windows-* @ls -ld $(GOBIN)/geth-windows-*
bor-windows-386: geth-windows-386:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=windows/386 -v ./cmd/bor $(GORUN) build/ci.go xgo -- --go=$(GO) --targets=windows/386 -v ./cmd/geth
@echo "Windows 386 cross compilation done:" @echo "Windows 386 cross compilation done:"
@ls -ld $(GOBIN)/bor-windows-* | grep 386 @ls -ld $(GOBIN)/geth-windows-* | grep 386
bor-windows-amd64: geth-windows-amd64:
$(GORUN) build/ci.go xgo -- --go=$(GO) --targets=windows/amd64 -v ./cmd/bor $(GORUN) build/ci.go xgo -- --go=$(GO) --targets=windows/amd64 -v ./cmd/geth
@echo "Windows amd64 cross compilation done:" @echo "Windows amd64 cross compilation done:"
@ls -ld $(GOBIN)/bor-windows-* | grep amd64 @ls -ld $(GOBIN)/geth-windows-* | grep amd64

View file

@ -14,7 +14,7 @@ make bor
or, to build the full suite of utilities: or, to build the full suite of utilities:
```shell ```shell
make all make bor-all
``` ```
## License ## License

View file

@ -6,13 +6,13 @@ Please see Releases. We recommend to use the most recent released version.
## Audit reports ## Audit reports
Audit reports are published in the `docs` folder: https://github.com/maticnetwork/bor/tree/master/docs/audits Audit reports are published in the `docs` folder: https://github.com/ethereum/go-ethereum/tree/master/docs/audits
| Scope | Date | Report Link | | Scope | Date | Report Link |
| ------- | ------- | ----------- | | ------- | ------- | ----------- |
| `geth` | 20170425 | [pdf](https://github.com/maticnetwork/bor/blob/master/docs/audits/2017-04-25_Geth-audit_Truesec.pdf) | | `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/maticnetwork/bor/blob/master/docs/audits/2018-09-14_Clef-audit_NCC.pdf) | | `clef` | 20180914 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2018-09-14_Clef-audit_NCC.pdf) |

View file

@ -23,8 +23,8 @@ import (
"fmt" "fmt"
"io" "io"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
// The ABI holds information about a contract's context and available // The ABI holds information about a contract's context and available
@ -80,39 +80,59 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) {
return append(method.ID, arguments...), nil return append(method.ID, arguments...), nil
} }
// Unpack output in v according to the abi specification func (abi ABI) getArguments(name string, data []byte) (Arguments, error) {
func (abi ABI) Unpack(v interface{}, name string, data []byte) (err error) {
// since there can't be naming collisions with contracts and events, // since there can't be naming collisions with contracts and events,
// we need to decide whether we're calling a method or an event // we need to decide whether we're calling a method or an event
var args Arguments
if method, ok := abi.Methods[name]; ok { if method, ok := abi.Methods[name]; ok {
if len(data)%32 != 0 { if len(data)%32 != 0 {
return fmt.Errorf("abi: improperly formatted output: %s - Bytes: [%+v]", string(data), data) return nil, fmt.Errorf("abi: improperly formatted output: %s - Bytes: [%+v]", string(data), data)
} }
return method.Outputs.Unpack(v, data) args = method.Outputs
} }
if event, ok := abi.Events[name]; ok { if event, ok := abi.Events[name]; ok {
return event.Inputs.Unpack(v, data) args = event.Inputs
} }
return fmt.Errorf("abi: could not locate named method or event") if args == nil {
return nil, errors.New("abi: could not locate named method or event")
}
return args, nil
} }
// UnpackIntoMap unpacks a log into the provided map[string]interface{} // Unpack unpacks the output according to the abi specification.
func (abi ABI) Unpack(name string, data []byte) ([]interface{}, error) {
args, err := abi.getArguments(name, data)
if err != nil {
return nil, err
}
return args.Unpack(data)
}
// UnpackIntoInterface unpacks the output in v according to the abi specification.
// It performs an additional copy. Please only use, if you want to unpack into a
// structure that does not strictly conform to the abi structure (e.g. has additional arguments)
func (abi ABI) UnpackIntoInterface(v interface{}, name string, data []byte) error {
args, err := abi.getArguments(name, data)
if err != nil {
return err
}
unpacked, err := args.Unpack(data)
if err != nil {
return err
}
return args.Copy(v, unpacked)
}
// UnpackIntoMap unpacks a log into the provided map[string]interface{}.
func (abi ABI) UnpackIntoMap(v map[string]interface{}, name string, data []byte) (err error) { func (abi ABI) UnpackIntoMap(v map[string]interface{}, name string, data []byte) (err error) {
// since there can't be naming collisions with contracts and events, args, err := abi.getArguments(name, data)
// we need to decide whether we're calling a method or an event if err != nil {
if method, ok := abi.Methods[name]; ok { return err
if len(data)%32 != 0 {
return fmt.Errorf("abi: improperly formatted output")
}
return method.Outputs.UnpackIntoMap(v, data)
} }
if event, ok := abi.Events[name]; ok { return args.UnpackIntoMap(v, data)
return event.Inputs.UnpackIntoMap(v, data)
}
return fmt.Errorf("abi: could not locate named method or event")
} }
// UnmarshalJSON implements json.Unmarshaler interface // UnmarshalJSON implements json.Unmarshaler interface.
func (abi *ABI) UnmarshalJSON(data []byte) error { func (abi *ABI) UnmarshalJSON(data []byte) error {
var fields []struct { var fields []struct {
Type string Type string
@ -201,8 +221,8 @@ func (abi *ABI) overloadedEventName(rawName string) string {
return name return name
} }
// MethodById looks up a method by the 4-byte id // MethodById looks up a method by the 4-byte id,
// returns nil if none found // returns nil if none found.
func (abi *ABI) MethodById(sigdata []byte) (*Method, error) { func (abi *ABI) MethodById(sigdata []byte) (*Method, error) {
if len(sigdata) < 4 { if len(sigdata) < 4 {
return nil, fmt.Errorf("data too short (%d bytes) for abi method lookup", len(sigdata)) return nil, fmt.Errorf("data too short (%d bytes) for abi method lookup", len(sigdata))
@ -250,10 +270,10 @@ func UnpackRevert(data []byte) (string, error) {
if !bytes.Equal(data[:4], revertSelector) { if !bytes.Equal(data[:4], revertSelector) {
return "", errors.New("invalid data for unpacking") return "", errors.New("invalid data for unpacking")
} }
var reason string
typ, _ := NewType("string", "", nil) typ, _ := NewType("string", "", nil)
if err := (Arguments{{Type: typ}}).Unpack(&reason, data[4:]); err != nil { unpacked, err := (Arguments{{Type: typ}}).Unpack(data[4:])
if err != nil {
return "", err return "", err
} }
return reason, nil return unpacked[0].(string), nil
} }

View file

@ -26,14 +26,14 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/common/math" "github.com/ethereum/go-ethereum/common/math"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
const jsondata = ` const jsondata = `
[ [
{ "type" : "function", "name" : "", "stateMutability" : "view" }, { "type" : "function", "name" : ""},
{ "type" : "function", "name" : "balance", "stateMutability" : "view" }, { "type" : "function", "name" : "balance", "stateMutability" : "view" },
{ "type" : "function", "name" : "send", "inputs" : [ { "name" : "amount", "type" : "uint256" } ] }, { "type" : "function", "name" : "send", "inputs" : [ { "name" : "amount", "type" : "uint256" } ] },
{ "type" : "function", "name" : "test", "inputs" : [ { "name" : "number", "type" : "uint32" } ] }, { "type" : "function", "name" : "test", "inputs" : [ { "name" : "number", "type" : "uint32" } ] },
@ -88,7 +88,7 @@ var (
) )
var methods = map[string]Method{ var methods = map[string]Method{
"": NewMethod("", "", Function, "view", false, false, nil, nil), "": NewMethod("", "", Function, "", false, false, nil, nil),
"balance": NewMethod("balance", "balance", Function, "view", false, false, nil, nil), "balance": NewMethod("balance", "balance", Function, "view", false, false, nil, nil),
"send": NewMethod("send", "send", Function, "", false, false, []Argument{{"amount", Uint256, false}}, nil), "send": NewMethod("send", "send", Function, "", false, false, []Argument{{"amount", Uint256, false}}, nil),
"test": NewMethod("test", "test", Function, "", false, false, []Argument{{"number", Uint32, false}}, nil), "test": NewMethod("test", "test", Function, "", false, false, []Argument{{"number", Uint32, false}}, nil),
@ -181,18 +181,15 @@ func TestConstructor(t *testing.T) {
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
v := struct { unpacked, err := abi.Constructor.Inputs.Unpack(packed)
A *big.Int if err != nil {
B *big.Int
}{new(big.Int), new(big.Int)}
//abi.Unpack(&v, "", packed)
if err := abi.Constructor.Inputs.Unpack(&v, packed); err != nil {
t.Error(err) t.Error(err)
} }
if !reflect.DeepEqual(v.A, big.NewInt(1)) {
if !reflect.DeepEqual(unpacked[0], big.NewInt(1)) {
t.Error("Unable to pack/unpack from constructor") t.Error("Unable to pack/unpack from constructor")
} }
if !reflect.DeepEqual(v.B, big.NewInt(2)) { if !reflect.DeepEqual(unpacked[1], big.NewInt(2)) {
t.Error("Unable to pack/unpack from constructor") t.Error("Unable to pack/unpack from constructor")
} }
} }
@ -743,7 +740,7 @@ func TestUnpackEvent(t *testing.T) {
} }
var ev ReceivedEvent var ev ReceivedEvent
err = abi.Unpack(&ev, "received", data) err = abi.UnpackIntoInterface(&ev, "received", data)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -752,7 +749,7 @@ func TestUnpackEvent(t *testing.T) {
Sender common.Address Sender common.Address
} }
var receivedAddrEv ReceivedAddrEvent var receivedAddrEv ReceivedAddrEvent
err = abi.Unpack(&receivedAddrEv, "receivedAddr", data) err = abi.UnpackIntoInterface(&receivedAddrEv, "receivedAddr", data)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -1092,7 +1089,7 @@ func TestDoubleDuplicateEventNames(t *testing.T) {
} }
// TestUnnamedEventParam checks that an event with unnamed parameters is // TestUnnamedEventParam checks that an event with unnamed parameters is
// correctly handled // correctly handled.
// The test runs the abi of the following contract. // The test runs the abi of the following contract.
// contract TestEvent { // contract TestEvent {
// event send(uint256, uint256); // event send(uint256, uint256);

View file

@ -41,7 +41,7 @@ type ArgumentMarshaling struct {
Indexed bool Indexed bool
} }
// UnmarshalJSON implements json.Unmarshaler interface // UnmarshalJSON implements json.Unmarshaler interface.
func (argument *Argument) UnmarshalJSON(data []byte) error { func (argument *Argument) UnmarshalJSON(data []byte) error {
var arg ArgumentMarshaling var arg ArgumentMarshaling
err := json.Unmarshal(data, &arg) err := json.Unmarshal(data, &arg)
@ -59,7 +59,7 @@ func (argument *Argument) UnmarshalJSON(data []byte) error {
return nil return nil
} }
// NonIndexed returns the arguments with indexed arguments filtered out // NonIndexed returns the arguments with indexed arguments filtered out.
func (arguments Arguments) NonIndexed() Arguments { func (arguments Arguments) NonIndexed() Arguments {
var ret []Argument var ret []Argument
for _, arg := range arguments { for _, arg := range arguments {
@ -70,37 +70,29 @@ func (arguments Arguments) NonIndexed() Arguments {
return ret return ret
} }
// isTuple returns true for non-atomic constructs, like (uint,uint) or uint[] // isTuple returns true for non-atomic constructs, like (uint,uint) or uint[].
func (arguments Arguments) isTuple() bool { func (arguments Arguments) isTuple() bool {
return len(arguments) > 1 return len(arguments) > 1
} }
// Unpack performs the operation hexdata -> Go format // Unpack performs the operation hexdata -> Go format.
func (arguments Arguments) Unpack(v interface{}, data []byte) error { func (arguments Arguments) Unpack(data []byte) ([]interface{}, error) {
if len(data) == 0 { if len(data) == 0 {
if len(arguments) != 0 { if len(arguments) != 0 {
return fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected") return nil, fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected")
} }
return nil // Nothing to unmarshal, return // Nothing to unmarshal, return default variables
nonIndexedArgs := arguments.NonIndexed()
defaultVars := make([]interface{}, len(nonIndexedArgs))
for index, arg := range nonIndexedArgs {
defaultVars[index] = reflect.New(arg.Type.GetType())
}
return defaultVars, nil
} }
// make sure the passed value is arguments pointer return arguments.UnpackValues(data)
if reflect.Ptr != reflect.ValueOf(v).Kind() {
return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
}
marshalledValues, err := arguments.UnpackValues(data)
if err != nil {
return err
}
if len(marshalledValues) == 0 {
return fmt.Errorf("abi: Unpack(no-values unmarshalled %T)", v)
}
if arguments.isTuple() {
return arguments.unpackTuple(v, marshalledValues)
}
return arguments.unpackAtomic(v, marshalledValues[0])
} }
// UnpackIntoMap performs the operation hexdata -> mapping of argument name to argument value // UnpackIntoMap performs the operation hexdata -> mapping of argument name to argument value.
func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) error { func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) error {
// Make sure map is not nil // Make sure map is not nil
if v == nil { if v == nil {
@ -122,8 +114,26 @@ func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte)
return nil return nil
} }
// Copy performs the operation go format -> provided struct.
func (arguments Arguments) Copy(v interface{}, values []interface{}) error {
// make sure the passed value is arguments pointer
if reflect.Ptr != reflect.ValueOf(v).Kind() {
return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
}
if len(values) == 0 {
if len(arguments) != 0 {
return fmt.Errorf("abi: attempting to copy no values while %d arguments are expected", len(arguments))
}
return nil // Nothing to copy, return
}
if arguments.isTuple() {
return arguments.copyTuple(v, values)
}
return arguments.copyAtomic(v, values[0])
}
// unpackAtomic unpacks ( hexdata -> go ) a single value // unpackAtomic unpacks ( hexdata -> go ) a single value
func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interface{}) error { func (arguments Arguments) copyAtomic(v interface{}, marshalledValues interface{}) error {
dst := reflect.ValueOf(v).Elem() dst := reflect.ValueOf(v).Elem()
src := reflect.ValueOf(marshalledValues) src := reflect.ValueOf(marshalledValues)
@ -133,8 +143,8 @@ func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interfac
return set(dst, src) return set(dst, src)
} }
// unpackTuple unpacks ( hexdata -> go ) a batch of values. // copyTuple copies a batch of values from marshalledValues to v.
func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error { func (arguments Arguments) copyTuple(v interface{}, marshalledValues []interface{}) error {
value := reflect.ValueOf(v).Elem() value := reflect.ValueOf(v).Elem()
nonIndexedArgs := arguments.NonIndexed() nonIndexedArgs := arguments.NonIndexed()
@ -207,13 +217,13 @@ func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) {
return retval, nil return retval, nil
} }
// PackValues performs the operation Go format -> Hexdata // PackValues performs the operation Go format -> Hexdata.
// It is the semantic opposite of UnpackValues // It is the semantic opposite of UnpackValues.
func (arguments Arguments) PackValues(args []interface{}) ([]byte, error) { func (arguments Arguments) PackValues(args []interface{}) ([]byte, error) {
return arguments.Pack(args...) return arguments.Pack(args...)
} }
// Pack performs the operation Go format -> Hexdata // Pack performs the operation Go format -> Hexdata.
func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) { func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
// Make sure arguments match up and pack them // Make sure arguments match up and pack them
abiArgs := arguments abiArgs := arguments

View file

@ -22,12 +22,12 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"github.com/maticnetwork/bor/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/maticnetwork/bor/accounts/external" "github.com/ethereum/go-ethereum/accounts/external"
"github.com/maticnetwork/bor/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
// NewTransactor is a utility method to easily create a transaction signer from // NewTransactor is a utility method to easily create a transaction signer from
@ -45,7 +45,7 @@ func NewTransactor(keyin io.Reader, passphrase string) (*TransactOpts, error) {
} }
// NewKeyStoreTransactor is a utility method to easily create a transaction signer from // NewKeyStoreTransactor is a utility method to easily create a transaction signer from
// an decrypted key from a keystore // a decrypted key from a keystore.
func NewKeyStoreTransactor(keystore *keystore.KeyStore, account accounts.Account) (*TransactOpts, error) { func NewKeyStoreTransactor(keystore *keystore.KeyStore, account accounts.Account) (*TransactOpts, error) {
return &TransactOpts{ return &TransactOpts{
From: account.Address, From: account.Address,

View file

@ -21,9 +21,9 @@ import (
"errors" "errors"
"math/big" "math/big"
ethereum "github.com/maticnetwork/bor" "github.com/ethereum/go-ethereum"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/core/types" "github.com/ethereum/go-ethereum/core/types"
) )
var ( var (
@ -41,7 +41,7 @@ var (
ErrNoCodeAfterDeploy = errors.New("no contract code after deployment") ErrNoCodeAfterDeploy = errors.New("no contract code after deployment")
) )
// ContractCaller defines the methods needed to allow operating with contract on a read // ContractCaller defines the methods needed to allow operating with a contract on a read
// only basis. // only basis.
type ContractCaller interface { type ContractCaller interface {
// CodeAt returns the code of the given account. This is needed to differentiate // CodeAt returns the code of the given account. This is needed to differentiate
@ -62,8 +62,8 @@ type PendingContractCaller interface {
PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error) PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error)
} }
// ContractTransactor defines the methods needed to allow operating with contract // ContractTransactor defines the methods needed to allow operating with a contract
// on a write only basis. Beside the transacting method, the remainder are helpers // on a write only basis. Besides the transacting method, the remainder are helpers
// used when the user does not provide some needed values, but rather leaves it up // used when the user does not provide some needed values, but rather leaves it up
// to the transactor to decide. // to the transactor to decide.
type ContractTransactor interface { type ContractTransactor interface {

View file

@ -0,0 +1,11 @@
package backends
import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/event"
)
// SubscribeStateSyncEvent subscribes to state sync events
func (fb *filterBackend) SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) event.Subscription {
return fb.bc.SubscribeStateSyncEvent(ch)
}

View file

@ -24,28 +24,28 @@ import (
"sync" "sync"
"time" "time"
ethereum "github.com/maticnetwork/bor" "github.com/ethereum/go-ethereum"
"github.com/maticnetwork/bor/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/maticnetwork/bor/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/maticnetwork/bor/common/math" "github.com/ethereum/go-ethereum/common/math"
"github.com/maticnetwork/bor/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/maticnetwork/bor/core" "github.com/ethereum/go-ethereum/core"
"github.com/maticnetwork/bor/core/bloombits" "github.com/ethereum/go-ethereum/core/bloombits"
"github.com/maticnetwork/bor/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/maticnetwork/bor/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/maticnetwork/bor/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/maticnetwork/bor/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/maticnetwork/bor/eth/filters" "github.com/ethereum/go-ethereum/eth/filters"
"github.com/maticnetwork/bor/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/maticnetwork/bor/event" "github.com/ethereum/go-ethereum/event"
"github.com/maticnetwork/bor/log" "github.com/ethereum/go-ethereum/log"
"github.com/maticnetwork/bor/params" "github.com/ethereum/go-ethereum/params"
"github.com/maticnetwork/bor/rpc" "github.com/ethereum/go-ethereum/rpc"
) )
// This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend. // This nil assignment ensures at compile time that SimulatedBackend implements bind.ContractBackend.
var _ bind.ContractBackend = (*SimulatedBackend)(nil) var _ bind.ContractBackend = (*SimulatedBackend)(nil)
var ( var (
@ -55,7 +55,7 @@ var (
) )
// SimulatedBackend implements bind.ContractBackend, simulating a blockchain in // SimulatedBackend implements bind.ContractBackend, simulating a blockchain in
// the background. Its main purpose is to allow easily testing contract bindings. // the background. Its main purpose is to allow for easy testing of contract bindings.
// Simulated backend implements the following interfaces: // Simulated backend implements the following interfaces:
// ChainReader, ChainStateReader, ContractBackend, ContractCaller, ContractFilterer, ContractTransactor, // ChainReader, ChainStateReader, ContractBackend, ContractCaller, ContractFilterer, ContractTransactor,
// DeployBackend, GasEstimator, GasPricer, LogFilterer, PendingContractCaller, TransactionReader, and TransactionSender // DeployBackend, GasEstimator, GasPricer, LogFilterer, PendingContractCaller, TransactionReader, and TransactionSender
@ -123,10 +123,10 @@ func (b *SimulatedBackend) Rollback() {
func (b *SimulatedBackend) rollback() { func (b *SimulatedBackend) rollback() {
blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(int, *core.BlockGen) {}) blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(int, *core.BlockGen) {})
statedb, _ := b.blockchain.State() stateDB, _ := b.blockchain.State()
b.pendingBlock = blocks[0] b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), statedb.Database(), nil) b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
} }
// stateByBlockNumber retrieves a state by a given blocknumber. // stateByBlockNumber retrieves a state by a given blocknumber.
@ -146,12 +146,12 @@ func (b *SimulatedBackend) CodeAt(ctx context.Context, contract common.Address,
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
statedb, err := b.stateByBlockNumber(ctx, blockNumber) stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return statedb.GetCode(contract), nil return stateDB.GetCode(contract), nil
} }
// BalanceAt returns the wei balance of a certain account in the blockchain. // BalanceAt returns the wei balance of a certain account in the blockchain.
@ -159,12 +159,12 @@ func (b *SimulatedBackend) BalanceAt(ctx context.Context, contract common.Addres
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
statedb, err := b.stateByBlockNumber(ctx, blockNumber) stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return statedb.GetBalance(contract), nil return stateDB.GetBalance(contract), nil
} }
// NonceAt returns the nonce of a certain account in the blockchain. // NonceAt returns the nonce of a certain account in the blockchain.
@ -172,12 +172,12 @@ func (b *SimulatedBackend) NonceAt(ctx context.Context, contract common.Address,
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
statedb, err := b.stateByBlockNumber(ctx, blockNumber) stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
if err != nil { if err != nil {
return 0, err return 0, err
} }
return statedb.GetNonce(contract), nil return stateDB.GetNonce(contract), nil
} }
// StorageAt returns the value of key in the storage of an account in the blockchain. // StorageAt returns the value of key in the storage of an account in the blockchain.
@ -185,12 +185,12 @@ func (b *SimulatedBackend) StorageAt(ctx context.Context, contract common.Addres
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
statedb, err := b.stateByBlockNumber(ctx, blockNumber) stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
if err != nil { if err != nil {
return nil, err return nil, err
} }
val := statedb.GetState(contract, key) val := stateDB.GetState(contract, key)
return val[:], nil return val[:], nil
} }
@ -222,7 +222,7 @@ func (b *SimulatedBackend) TransactionByHash(ctx context.Context, txHash common.
return nil, false, ethereum.NotFound return nil, false, ethereum.NotFound
} }
// BlockByHash retrieves a block based on the block hash // BlockByHash retrieves a block based on the block hash.
func (b *SimulatedBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { func (b *SimulatedBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
@ -293,7 +293,7 @@ func (b *SimulatedBackend) HeaderByNumber(ctx context.Context, block *big.Int) (
return b.blockchain.GetHeaderByNumber(uint64(block.Int64())), nil return b.blockchain.GetHeaderByNumber(uint64(block.Int64())), nil
} }
// TransactionCount returns the number of transactions in a given block // TransactionCount returns the number of transactions in a given block.
func (b *SimulatedBackend) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) { func (b *SimulatedBackend) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) {
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
@ -310,7 +310,7 @@ func (b *SimulatedBackend) TransactionCount(ctx context.Context, blockHash commo
return uint(block.Transactions().Len()), nil return uint(block.Transactions().Len()), nil
} }
// TransactionInBlock returns the transaction for a specific block at a specific index // TransactionInBlock returns the transaction for a specific block at a specific index.
func (b *SimulatedBackend) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) { func (b *SimulatedBackend) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) {
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
@ -357,14 +357,14 @@ func newRevertError(result *core.ExecutionResult) *revertError {
} }
} }
// revertError is an API error that encompassas an EVM revertal with JSON error // revertError is an API error that encompasses an EVM revert with JSON error
// code and a binary data blob. // code and a binary data blob.
type revertError struct { type revertError struct {
error error
reason string // revert reason hex encoded reason string // revert reason hex encoded
} }
// ErrorCode returns the JSON error code for a revertal. // ErrorCode returns the JSON error code for a revert.
// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal // See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal
func (e *revertError) ErrorCode() int { func (e *revertError) ErrorCode() int {
return 3 return 3
@ -383,11 +383,11 @@ func (b *SimulatedBackend) CallContract(ctx context.Context, call ethereum.CallM
if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 { if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 {
return nil, errBlockNumberUnsupported return nil, errBlockNumberUnsupported
} }
state, err := b.blockchain.State() stateDB, err := b.blockchain.State()
if err != nil { if err != nil {
return nil, err return nil, err
} }
res, err := b.callContract(ctx, call, b.blockchain.CurrentBlock(), state) res, err := b.callContract(ctx, call, b.blockchain.CurrentBlock(), stateDB)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -448,7 +448,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
hi = b.pendingBlock.GasLimit() hi = b.pendingBlock.GasLimit()
} }
// Recap the highest gas allowance with account's balance. // Recap the highest gas allowance with account's balance.
if call.GasPrice != nil && call.GasPrice.Uint64() != 0 { if call.GasPrice != nil && call.GasPrice.BitLen() != 0 {
balance := b.pendingState.GetBalance(call.From) // from can't be nil balance := b.pendingState.GetBalance(call.From) // from can't be nil
available := new(big.Int).Set(balance) available := new(big.Int).Set(balance)
if call.Value != nil { if call.Value != nil {
@ -458,7 +458,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
available.Sub(available, call.Value) available.Sub(available, call.Value)
} }
allowance := new(big.Int).Div(available, call.GasPrice) allowance := new(big.Int).Div(available, call.GasPrice)
if hi > allowance.Uint64() { if allowance.IsUint64() && hi > allowance.Uint64() {
transfer := call.Value transfer := call.Value
if transfer == nil { if transfer == nil {
transfer = new(big.Int) transfer = new(big.Int)
@ -525,7 +525,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
// callContract implements common code between normal and pending contract calls. // callContract implements common code between normal and pending contract calls.
// state is modified during execution, make sure to copy it if necessary. // state is modified during execution, make sure to copy it if necessary.
func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, statedb *state.StateDB) (*core.ExecutionResult, error) { func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, stateDB *state.StateDB) (*core.ExecutionResult, error) {
// Ensure message is initialized properly. // Ensure message is initialized properly.
if call.GasPrice == nil { if call.GasPrice == nil {
call.GasPrice = big.NewInt(1) call.GasPrice = big.NewInt(1)
@ -537,18 +537,18 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
call.Value = new(big.Int) call.Value = new(big.Int)
} }
// Set infinite balance to the fake caller account. // Set infinite balance to the fake caller account.
from := statedb.GetOrNewStateObject(call.From) from := stateDB.GetOrNewStateObject(call.From)
from.SetBalance(math.MaxBig256) from.SetBalance(math.MaxBig256)
// Execute the call. // Execute the call.
msg := callmsg{call} msg := callMsg{call}
evmContext := core.NewEVMContext(msg, block.Header(), b.blockchain, nil) evmContext := core.NewEVMContext(msg, block.Header(), b.blockchain, nil)
// Create a new environment which holds all relevant information // Create a new environment which holds all relevant information
// about the transaction and calling mechanisms. // about the transaction and calling mechanisms.
vmenv := vm.NewEVM(evmContext, statedb, b.config, vm.Config{}) vmEnv := vm.NewEVM(evmContext, stateDB, b.config, vm.Config{})
gaspool := new(core.GasPool).AddGas(math.MaxUint64) gasPool := new(core.GasPool).AddGas(math.MaxUint64)
return core.NewStateTransition(vmenv, msg, gaspool).TransitionDb() return core.NewStateTransition(vmEnv, msg, gasPool).TransitionDb()
} }
// SendTransaction updates the pending block to include the given transaction. // SendTransaction updates the pending block to include the given transaction.
@ -572,10 +572,10 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
} }
block.AddTxWithChain(b.blockchain, tx) block.AddTxWithChain(b.blockchain, tx)
}) })
statedb, _ := b.blockchain.State() stateDB, _ := b.blockchain.State()
b.pendingBlock = blocks[0] b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), statedb.Database(), nil) b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
return nil return nil
} }
@ -589,7 +589,7 @@ func (b *SimulatedBackend) FilterLogs(ctx context.Context, query ethereum.Filter
// Block filter requested, construct a single-shot filter // Block filter requested, construct a single-shot filter
filter = filters.NewBlockFilter(&filterBackend{b.database, b.blockchain}, *query.BlockHash, query.Addresses, query.Topics) filter = filters.NewBlockFilter(&filterBackend{b.database, b.blockchain}, *query.BlockHash, query.Addresses, query.Topics)
} else { } else {
// Initialize unset filter boundaried to run from genesis to chain head // Initialize unset filter boundaries to run from genesis to chain head
from := int64(0) from := int64(0)
if query.FromBlock != nil { if query.FromBlock != nil {
from = query.FromBlock.Int64() from = query.FromBlock.Int64()
@ -607,8 +607,8 @@ func (b *SimulatedBackend) FilterLogs(ctx context.Context, query ethereum.Filter
return nil, err return nil, err
} }
res := make([]types.Log, len(logs)) res := make([]types.Log, len(logs))
for i, log := range logs { for i, nLog := range logs {
res[i] = *log res[i] = *nLog
} }
return res, nil return res, nil
} }
@ -629,9 +629,9 @@ func (b *SimulatedBackend) SubscribeFilterLogs(ctx context.Context, query ethere
for { for {
select { select {
case logs := <-sink: case logs := <-sink:
for _, log := range logs { for _, nlog := range logs {
select { select {
case ch <- *log: case ch <- *nlog:
case err := <-sub.Err(): case err := <-sub.Err():
return err return err
case <-quit: case <-quit:
@ -647,7 +647,7 @@ func (b *SimulatedBackend) SubscribeFilterLogs(ctx context.Context, query ethere
}), nil }), nil
} }
// SubscribeNewHead returns an event subscription for a new header // SubscribeNewHead returns an event subscription for a new header.
func (b *SimulatedBackend) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { func (b *SimulatedBackend) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) {
// subscribe to a new head // subscribe to a new head
sink := make(chan *types.Header) sink := make(chan *types.Header)
@ -675,20 +675,22 @@ func (b *SimulatedBackend) SubscribeNewHead(ctx context.Context, ch chan<- *type
} }
// AdjustTime adds a time shift to the simulated clock. // AdjustTime adds a time shift to the simulated clock.
// It can only be called on empty blocks.
func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error { func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error {
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
if len(b.pendingBlock.Transactions()) != 0 {
return errors.New("Could not adjust time on non-empty block")
}
blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) { blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
for _, tx := range b.pendingBlock.Transactions() {
block.AddTx(tx)
}
block.OffsetTime(int64(adjustment.Seconds())) block.OffsetTime(int64(adjustment.Seconds()))
}) })
statedb, _ := b.blockchain.State() stateDB, _ := b.blockchain.State()
b.pendingBlock = blocks[0] b.pendingBlock = blocks[0]
b.pendingState, _ = state.New(b.pendingBlock.Root(), statedb.Database(), nil) b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
return nil return nil
} }
@ -698,19 +700,19 @@ func (b *SimulatedBackend) Blockchain() *core.BlockChain {
return b.blockchain return b.blockchain
} }
// callmsg implements core.Message to allow passing it as a transaction simulator. // callMsg implements core.Message to allow passing it as a transaction simulator.
type callmsg struct { type callMsg struct {
ethereum.CallMsg ethereum.CallMsg
} }
func (m callmsg) From() common.Address { return m.CallMsg.From } func (m callMsg) From() common.Address { return m.CallMsg.From }
func (m callmsg) Nonce() uint64 { return 0 } func (m callMsg) Nonce() uint64 { return 0 }
func (m callmsg) CheckNonce() bool { return false } func (m callMsg) CheckNonce() bool { return false }
func (m callmsg) To() *common.Address { return m.CallMsg.To } func (m callMsg) To() *common.Address { return m.CallMsg.To }
func (m callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice } func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
func (m callmsg) Gas() uint64 { return m.CallMsg.Gas } func (m callMsg) Gas() uint64 { return m.CallMsg.Gas }
func (m callmsg) Value() *big.Int { return m.CallMsg.Value } func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
func (m callmsg) Data() []byte { return m.CallMsg.Data } func (m callMsg) Data() []byte { return m.CallMsg.Data }
// filterBackend implements filters.Backend to support filtering for logs without // filterBackend implements filters.Backend to support filtering for logs without
// taking bloom-bits acceleration structures into account. // taking bloom-bits acceleration structures into account.
@ -777,10 +779,6 @@ func (fb *filterBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event
return nullSubscription() return nullSubscription()
} }
func (fb *filterBackend) SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) event.Subscription {
return fb.bc.SubscribeStateSyncEvent(ch)
}
func (fb *filterBackend) BloomStatus() (uint64, uint64) { return 4096, 0 } func (fb *filterBackend) BloomStatus() (uint64, uint64) { return 4096, 0 }
func (fb *filterBackend) ServiceFilter(ctx context.Context, ms *bloombits.MatcherSession) { func (fb *filterBackend) ServiceFilter(ctx context.Context, ms *bloombits.MatcherSession) {

View file

@ -26,14 +26,14 @@ import (
"testing" "testing"
"time" "time"
ethereum "github.com/maticnetwork/bor" "github.com/ethereum/go-ethereum"
"github.com/maticnetwork/bor/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/maticnetwork/bor/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/core" "github.com/ethereum/go-ethereum/core"
"github.com/maticnetwork/bor/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/maticnetwork/bor/params" "github.com/ethereum/go-ethereum/params"
) )
func TestSimulatedBackend(t *testing.T) { func TestSimulatedBackend(t *testing.T) {
@ -129,8 +129,8 @@ func TestNewSimulatedBackend(t *testing.T) {
t.Errorf("expected sim blockchain config to equal params.AllEthashProtocolChanges, got %v", sim.config) t.Errorf("expected sim blockchain config to equal params.AllEthashProtocolChanges, got %v", sim.config)
} }
statedb, _ := sim.blockchain.State() stateDB, _ := sim.blockchain.State()
bal := statedb.GetBalance(testAddr) bal := stateDB.GetBalance(testAddr)
if bal.Cmp(expectedBal) != 0 { if bal.Cmp(expectedBal) != 0 {
t.Errorf("expected balance for test address not received. expected: %v actual: %v", expectedBal, bal) t.Errorf("expected balance for test address not received. expected: %v actual: %v", expectedBal, bal)
} }
@ -143,8 +143,7 @@ func TestSimulatedBackend_AdjustTime(t *testing.T) {
defer sim.Close() defer sim.Close()
prevTime := sim.pendingBlock.Time() prevTime := sim.pendingBlock.Time()
err := sim.AdjustTime(time.Second) if err := sim.AdjustTime(time.Second); err != nil {
if err != nil {
t.Error(err) t.Error(err)
} }
newTime := sim.pendingBlock.Time() newTime := sim.pendingBlock.Time()
@ -154,6 +153,44 @@ func TestSimulatedBackend_AdjustTime(t *testing.T) {
} }
} }
func TestNewSimulatedBackend_AdjustTimeFail(t *testing.T) {
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr)
// Create tx and send
tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
if err != nil {
t.Errorf("could not sign tx: %v", err)
}
sim.SendTransaction(context.Background(), signedTx)
// AdjustTime should fail on non-empty block
if err := sim.AdjustTime(time.Second); err == nil {
t.Error("Expected adjust time to error on non-empty block")
}
sim.Commit()
prevTime := sim.pendingBlock.Time()
if err := sim.AdjustTime(time.Minute); err != nil {
t.Error(err)
}
newTime := sim.pendingBlock.Time()
if newTime-prevTime != uint64(time.Minute.Seconds()) {
t.Errorf("adjusted time not equal to a minute. prev: %v, new: %v", prevTime, newTime)
}
// Put a transaction after adjusting time
tx2 := types.NewTransaction(1, testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
signedTx2, err := types.SignTx(tx2, types.HomesteadSigner{}, testKey)
if err != nil {
t.Errorf("could not sign tx: %v", err)
}
sim.SendTransaction(context.Background(), signedTx2)
sim.Commit()
newTime = sim.pendingBlock.Time()
if newTime-prevTime >= uint64(time.Minute.Seconds()) {
t.Errorf("time adjusted, but shouldn't be: prev: %v, new: %v", prevTime, newTime)
}
}
func TestSimulatedBackend_BalanceAt(t *testing.T) { func TestSimulatedBackend_BalanceAt(t *testing.T) {
testAddr := crypto.PubkeyToAddress(testKey.PublicKey) testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
expectedBal := big.NewInt(10000000000) expectedBal := big.NewInt(10000000000)
@ -484,7 +521,7 @@ func TestSimulatedBackend_EstimateGasWithPrice(t *testing.T) {
sim := NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(params.Ether*2 + 2e17)}}, 10000000) sim := NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(params.Ether*2 + 2e17)}}, 10000000)
defer sim.Close() defer sim.Close()
receipant := common.HexToAddress("deadbeef") recipient := common.HexToAddress("deadbeef")
var cases = []struct { var cases = []struct {
name string name string
message ethereum.CallMsg message ethereum.CallMsg
@ -493,7 +530,7 @@ func TestSimulatedBackend_EstimateGasWithPrice(t *testing.T) {
}{ }{
{"EstimateWithoutPrice", ethereum.CallMsg{ {"EstimateWithoutPrice", ethereum.CallMsg{
From: addr, From: addr,
To: &receipant, To: &recipient,
Gas: 0, Gas: 0,
GasPrice: big.NewInt(0), GasPrice: big.NewInt(0),
Value: big.NewInt(1000), Value: big.NewInt(1000),
@ -502,7 +539,7 @@ func TestSimulatedBackend_EstimateGasWithPrice(t *testing.T) {
{"EstimateWithPrice", ethereum.CallMsg{ {"EstimateWithPrice", ethereum.CallMsg{
From: addr, From: addr,
To: &receipant, To: &recipient,
Gas: 0, Gas: 0,
GasPrice: big.NewInt(1000), GasPrice: big.NewInt(1000),
Value: big.NewInt(1000), Value: big.NewInt(1000),
@ -511,7 +548,7 @@ func TestSimulatedBackend_EstimateGasWithPrice(t *testing.T) {
{"EstimateWithVeryHighPrice", ethereum.CallMsg{ {"EstimateWithVeryHighPrice", ethereum.CallMsg{
From: addr, From: addr,
To: &receipant, To: &recipient,
Gas: 0, Gas: 0,
GasPrice: big.NewInt(1e14), // gascost = 2.1ether GasPrice: big.NewInt(1e14), // gascost = 2.1ether
Value: big.NewInt(1e17), // the remaining balance for fee is 2.1ether Value: big.NewInt(1e17), // the remaining balance for fee is 2.1ether
@ -520,7 +557,7 @@ func TestSimulatedBackend_EstimateGasWithPrice(t *testing.T) {
{"EstimateWithSuperhighPrice", ethereum.CallMsg{ {"EstimateWithSuperhighPrice", ethereum.CallMsg{
From: addr, From: addr,
To: &receipant, To: &recipient,
Gas: 0, Gas: 0,
GasPrice: big.NewInt(2e14), // gascost = 4.2ether GasPrice: big.NewInt(2e14), // gascost = 4.2ether
Value: big.NewInt(1000), Value: big.NewInt(1000),

View file

@ -22,12 +22,12 @@ import (
"fmt" "fmt"
"math/big" "math/big"
ethereum "github.com/maticnetwork/bor" "github.com/ethereum/go-ethereum"
"github.com/maticnetwork/bor/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/maticnetwork/bor/event" "github.com/ethereum/go-ethereum/event"
) )
// SignerFn is a signer function callback when a contract requires a method to // SignerFn is a signer function callback when a contract requires a method to
@ -117,11 +117,14 @@ func DeployContract(opts *TransactOpts, abi abi.ABI, bytecode []byte, backend Co
// sets the output to result. The result type might be a single field for simple // sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named // returns, a slice of interfaces for anonymous returns and a struct for named
// returns. // returns.
func (c *BoundContract) Call(opts *CallOpts, result interface{}, method string, params ...interface{}) error { func (c *BoundContract) Call(opts *CallOpts, results *[]interface{}, method string, params ...interface{}) error {
// Don't crash on a lazy user // Don't crash on a lazy user
if opts == nil { if opts == nil {
opts = new(CallOpts) opts = new(CallOpts)
} }
if results == nil {
results = new([]interface{})
}
// Pack the input, call and unpack the results // Pack the input, call and unpack the results
input, err := c.abi.Pack(method, params...) input, err := c.abi.Pack(method, params...)
if err != nil { if err != nil {
@ -149,7 +152,10 @@ func (c *BoundContract) Call(opts *CallOpts, result interface{}, method string,
} }
} else { } else {
output, err = c.caller.CallContract(ctx, msg, opts.BlockNumber) output, err = c.caller.CallContract(ctx, msg, opts.BlockNumber)
if err == nil && len(output) == 0 { if err != nil {
return err
}
if len(output) == 0 {
// Make sure we have a contract to operate on, and bail out otherwise. // Make sure we have a contract to operate on, and bail out otherwise.
if code, err = c.caller.CodeAt(ctx, c.address, opts.BlockNumber); err != nil { if code, err = c.caller.CodeAt(ctx, c.address, opts.BlockNumber); err != nil {
return err return err
@ -158,10 +164,14 @@ func (c *BoundContract) Call(opts *CallOpts, result interface{}, method string,
} }
} }
} }
if err != nil {
if len(*results) == 0 {
res, err := c.abi.Unpack(method, output)
*results = res
return err return err
} }
return c.abi.Unpack(result, method, output) res := *results
return c.abi.UnpackIntoInterface(res[0], method, output)
} }
// Transact invokes the (paid) contract method with params as input values. // Transact invokes the (paid) contract method with params as input values.
@ -177,7 +187,7 @@ func (c *BoundContract) Transact(opts *TransactOpts, method string, params ...in
} }
// RawTransact initiates a transaction with the given raw calldata as the input. // RawTransact initiates a transaction with the given raw calldata as the input.
// It's usually used to initiates transaction for invoking **Fallback** function. // It's usually used to initiate transactions for invoking **Fallback** function.
func (c *BoundContract) RawTransact(opts *TransactOpts, calldata []byte) (*types.Transaction, error) { func (c *BoundContract) RawTransact(opts *TransactOpts, calldata []byte) (*types.Transaction, error) {
// todo(rjl493456442) check the method is payable or not, // todo(rjl493456442) check the method is payable or not,
// reject invalid transaction at the first place // reject invalid transaction at the first place
@ -339,7 +349,7 @@ func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]inter
// UnpackLog unpacks a retrieved log into the provided output structure. // UnpackLog unpacks a retrieved log into the provided output structure.
func (c *BoundContract) UnpackLog(out interface{}, event string, log types.Log) error { func (c *BoundContract) UnpackLog(out interface{}, event string, log types.Log) error {
if len(log.Data) > 0 { if len(log.Data) > 0 {
if err := c.abi.Unpack(out, event, log.Data); err != nil { if err := c.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
return err return err
} }
} }

View file

@ -23,14 +23,14 @@ import (
"strings" "strings"
"testing" "testing"
ethereum "github.com/maticnetwork/bor" "github.com/ethereum/go-ethereum"
"github.com/maticnetwork/bor/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/maticnetwork/bor/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/maticnetwork/bor/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/maticnetwork/bor/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
type mockCaller struct { type mockCaller struct {
@ -71,11 +71,10 @@ func TestPassingBlockNumber(t *testing.T) {
}, },
}, },
}, mc, nil, nil) }, mc, nil, nil)
var ret string
blockNumber := big.NewInt(42) blockNumber := big.NewInt(42)
bc.Call(&bind.CallOpts{BlockNumber: blockNumber}, &ret, "something") bc.Call(&bind.CallOpts{BlockNumber: blockNumber}, nil, "something")
if mc.callContractBlockNumber != blockNumber { if mc.callContractBlockNumber != blockNumber {
t.Fatalf("CallContract() was not passed the block number") t.Fatalf("CallContract() was not passed the block number")
@ -85,7 +84,7 @@ func TestPassingBlockNumber(t *testing.T) {
t.Fatalf("CodeAt() was not passed the block number") t.Fatalf("CodeAt() was not passed the block number")
} }
bc.Call(&bind.CallOpts{}, &ret, "something") bc.Call(&bind.CallOpts{}, nil, "something")
if mc.callContractBlockNumber != nil { if mc.callContractBlockNumber != nil {
t.Fatalf("CallContract() was passed a block number when it should not have been") t.Fatalf("CallContract() was passed a block number when it should not have been")
@ -95,7 +94,7 @@ func TestPassingBlockNumber(t *testing.T) {
t.Fatalf("CodeAt() was passed a block number when it should not have been") t.Fatalf("CodeAt() was passed a block number when it should not have been")
} }
bc.Call(&bind.CallOpts{BlockNumber: blockNumber, Pending: true}, &ret, "something") bc.Call(&bind.CallOpts{BlockNumber: blockNumber, Pending: true}, nil, "something")
if !mc.pendingCallContractCalled { if !mc.pendingCallContractCalled {
t.Fatalf("CallContract() was not passed the block number") t.Fatalf("CallContract() was not passed the block number")

View file

@ -30,8 +30,8 @@ import (
"text/template" "text/template"
"unicode" "unicode"
"github.com/maticnetwork/bor/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/maticnetwork/bor/log" "github.com/ethereum/go-ethereum/log"
) )
// Lang is a target programming language selector to generate bindings for. // Lang is a target programming language selector to generate bindings for.
@ -52,7 +52,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
// contracts is the map of each individual contract requested binding // contracts is the map of each individual contract requested binding
contracts = make(map[string]*tmplContract) contracts = make(map[string]*tmplContract)
// structs is the map of all reclared structs shared by passed contracts. // structs is the map of all redeclared structs shared by passed contracts.
structs = make(map[string]*tmplStruct) structs = make(map[string]*tmplStruct)
// isLib is the map used to flag each encountered library as such // isLib is the map used to flag each encountered library as such
@ -80,10 +80,10 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
fallback *tmplMethod fallback *tmplMethod
receive *tmplMethod receive *tmplMethod
// identifiers are used to detect duplicated identifier of function // identifiers are used to detect duplicated identifiers of functions
// and event. For all calls, transacts and events, abigen will generate // and events. For all calls, transacts and events, abigen will generate
// corresponding bindings. However we have to ensure there is no // corresponding bindings. However we have to ensure there is no
// identifier coliision in the bindings of these categories. // identifier collisions in the bindings of these categories.
callIdentifiers = make(map[string]bool) callIdentifiers = make(map[string]bool)
transactIdentifiers = make(map[string]bool) transactIdentifiers = make(map[string]bool)
eventIdentifiers = make(map[string]bool) eventIdentifiers = make(map[string]bool)
@ -246,7 +246,7 @@ var bindType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct) stri
LangJava: bindTypeJava, LangJava: bindTypeJava,
} }
// bindBasicTypeGo converts basic solidity types(except array, slice and tuple) to Go one. // bindBasicTypeGo converts basic solidity types(except array, slice and tuple) to Go ones.
func bindBasicTypeGo(kind abi.Type) string { func bindBasicTypeGo(kind abi.Type) string {
switch kind.T { switch kind.T {
case abi.AddressTy: case abi.AddressTy:
@ -286,7 +286,7 @@ func bindTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
} }
} }
// bindBasicTypeJava converts basic solidity types(except array, slice and tuple) to Java one. // bindBasicTypeJava converts basic solidity types(except array, slice and tuple) to Java ones.
func bindBasicTypeJava(kind abi.Type) string { func bindBasicTypeJava(kind abi.Type) string {
switch kind.T { switch kind.T {
case abi.AddressTy: case abi.AddressTy:
@ -330,7 +330,7 @@ func bindBasicTypeJava(kind abi.Type) string {
} }
// pluralizeJavaType explicitly converts multidimensional types to predefined // pluralizeJavaType explicitly converts multidimensional types to predefined
// type in go side. // types in go side.
func pluralizeJavaType(typ string) string { func pluralizeJavaType(typ string) string {
switch typ { switch typ {
case "boolean": case "boolean":
@ -369,7 +369,7 @@ var bindTopicType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct)
} }
// bindTopicTypeGo converts a Solidity topic type to a Go one. It is almost the same // bindTopicTypeGo converts a Solidity topic type to a Go one. It is almost the same
// funcionality as for simple types, but dynamic types get converted to hashes. // functionality as for simple types, but dynamic types get converted to hashes.
func bindTopicTypeGo(kind abi.Type, structs map[string]*tmplStruct) string { func bindTopicTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
bound := bindTypeGo(kind, structs) bound := bindTypeGo(kind, structs)
@ -386,7 +386,7 @@ func bindTopicTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
} }
// bindTopicTypeJava converts a Solidity topic type to a Java one. It is almost the same // bindTopicTypeJava converts a Solidity topic type to a Java one. It is almost the same
// funcionality as for simple types, but dynamic types get converted to hashes. // functionality as for simple types, but dynamic types get converted to hashes.
func bindTopicTypeJava(kind abi.Type, structs map[string]*tmplStruct) string { func bindTopicTypeJava(kind abi.Type, structs map[string]*tmplStruct) string {
bound := bindTypeJava(kind, structs) bound := bindTypeJava(kind, structs)
@ -394,7 +394,7 @@ func bindTopicTypeJava(kind abi.Type, structs map[string]*tmplStruct) string {
// parameters that are not value types i.e. arrays and structs are not // parameters that are not value types i.e. arrays and structs are not
// stored directly but instead a keccak256-hash of an encoding is stored. // stored directly but instead a keccak256-hash of an encoding is stored.
// //
// We only convert stringS and bytes to hash, still need to deal with // We only convert strings and bytes to hash, still need to deal with
// array(both fixed-size and dynamic-size) and struct. // array(both fixed-size and dynamic-size) and struct.
if bound == "String" || bound == "byte[]" { if bound == "String" || bound == "byte[]" {
bound = "Hash" bound = "Hash"
@ -415,7 +415,7 @@ var bindStructType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct
func bindStructTypeGo(kind abi.Type, structs map[string]*tmplStruct) string { func bindStructTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
switch kind.T { switch kind.T {
case abi.TupleTy: case abi.TupleTy:
// We compose raw struct name and canonical parameter expression // We compose a raw struct name and a canonical parameter expression
// together here. The reason is before solidity v0.5.11, kind.TupleRawName // together here. The reason is before solidity v0.5.11, kind.TupleRawName
// is empty, so we use canonical parameter expression to distinguish // is empty, so we use canonical parameter expression to distinguish
// different struct definition. From the consideration of backward // different struct definition. From the consideration of backward
@ -454,7 +454,7 @@ func bindStructTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
func bindStructTypeJava(kind abi.Type, structs map[string]*tmplStruct) string { func bindStructTypeJava(kind abi.Type, structs map[string]*tmplStruct) string {
switch kind.T { switch kind.T {
case abi.TupleTy: case abi.TupleTy:
// We compose raw struct name and canonical parameter expression // We compose a raw struct name and a canonical parameter expression
// together here. The reason is before solidity v0.5.11, kind.TupleRawName // together here. The reason is before solidity v0.5.11, kind.TupleRawName
// is empty, so we use canonical parameter expression to distinguish // is empty, so we use canonical parameter expression to distinguish
// different struct definition. From the consideration of backward // different struct definition. From the consideration of backward
@ -486,7 +486,7 @@ func bindStructTypeJava(kind abi.Type, structs map[string]*tmplStruct) string {
} }
// namedType is a set of functions that transform language specific types to // namedType is a set of functions that transform language specific types to
// named versions that my be used inside method names. // named versions that may be used inside method names.
var namedType = map[Lang]func(string, abi.Type) string{ var namedType = map[Lang]func(string, abi.Type) string{
LangGo: func(string, abi.Type) string { panic("this shouldn't be needed") }, LangGo: func(string, abi.Type) string { panic("this shouldn't be needed") },
LangJava: namedTypeJava, LangJava: namedTypeJava,
@ -528,7 +528,7 @@ func alias(aliases map[string]string, n string) string {
} }
// methodNormalizer is a name transformer that modifies Solidity method names to // methodNormalizer is a name transformer that modifies Solidity method names to
// conform to target language naming concentions. // conform to target language naming conventions.
var methodNormalizer = map[Lang]func(string) string{ var methodNormalizer = map[Lang]func(string) string{
LangGo: abi.ToCamelCase, LangGo: abi.ToCamelCase,
LangJava: decapitalise, LangJava: decapitalise,

File diff suppressed because one or more lines are too long

View file

@ -16,7 +16,7 @@
package bind package bind
import "github.com/maticnetwork/bor/accounts/abi" import "github.com/ethereum/go-ethereum/accounts/abi"
// tmplData is the data structure required to fill the binding template. // tmplData is the data structure required to fill the binding template.
type tmplData struct { type tmplData struct {
@ -30,7 +30,7 @@ type tmplData struct {
type tmplContract struct { type tmplContract struct {
Type string // Type name of the main contract binding Type string // Type name of the main contract binding
InputABI string // JSON ABI used as the input to generate the binding from InputABI string // JSON ABI used as the input to generate the binding from
InputBin string // Optional EVM bytecode used to denetare deploy code from InputBin string // Optional EVM bytecode used to generate deploy code from
FuncSigs map[string]string // Optional map: string signature -> 4-byte signature FuncSigs map[string]string // Optional map: string signature -> 4-byte signature
Constructor abi.Method // Contract constructor for deploy parametrization Constructor abi.Method // Contract constructor for deploy parametrization
Calls map[string]*tmplMethod // Contract calls that only read state data Calls map[string]*tmplMethod // Contract calls that only read state data
@ -50,7 +50,8 @@ type tmplMethod struct {
Structured bool // Whether the returns should be accumulated into a struct Structured bool // Whether the returns should be accumulated into a struct
} }
// tmplEvent is a wrapper around an a // tmplEvent is a wrapper around an abi.Event that contains a few preprocessed
// and cached data fields.
type tmplEvent struct { type tmplEvent struct {
Original abi.Event // Original event as parsed by the abi package Original abi.Event // Original event as parsed by the abi package
Normalized abi.Event // Normalized version of the parsed fields Normalized abi.Event // Normalized version of the parsed fields
@ -64,7 +65,7 @@ type tmplField struct {
SolKind abi.Type // Raw abi type information SolKind abi.Type // Raw abi type information
} }
// tmplStruct is a wrapper around an abi.tuple contains an auto-generated // tmplStruct is a wrapper around an abi.tuple and contains an auto-generated
// struct name. // struct name.
type tmplStruct struct { type tmplStruct struct {
Name string // Auto-generated struct name(before solidity v0.5.11) or raw name. Name string // Auto-generated struct name(before solidity v0.5.11) or raw name.
@ -78,8 +79,8 @@ var tmplSource = map[Lang]string{
LangJava: tmplSourceJava, LangJava: tmplSourceJava,
} }
// tmplSourceGo is the Go source template use to generate the contract binding // tmplSourceGo is the Go source template that the generated Go contract binding
// based on. // is based on.
const tmplSourceGo = ` const tmplSourceGo = `
// Code generated - DO NOT EDIT. // Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost. // This file is a generated binding and any manual changes will be lost.
@ -90,12 +91,12 @@ import (
"math/big" "math/big"
"strings" "strings"
ethereum "github.com/maticnetwork/bor" ethereum "github.com/ethereum/go-ethereum"
"github.com/maticnetwork/bor/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/maticnetwork/bor/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/maticnetwork/bor/event" "github.com/ethereum/go-ethereum/event"
) )
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@ -260,7 +261,7 @@ var (
// sets the output to result. The result type might be a single field for simple // sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named // returns, a slice of interfaces for anonymous returns and a struct for named
// returns. // returns.
func (_{{$contract.Type}} *{{$contract.Type}}Raw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { func (_{{$contract.Type}} *{{$contract.Type}}Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _{{$contract.Type}}.Contract.{{$contract.Type}}Caller.contract.Call(opts, result, method, params...) return _{{$contract.Type}}.Contract.{{$contract.Type}}Caller.contract.Call(opts, result, method, params...)
} }
@ -279,7 +280,7 @@ var (
// sets the output to result. The result type might be a single field for simple // sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named // returns, a slice of interfaces for anonymous returns and a struct for named
// returns. // returns.
func (_{{$contract.Type}} *{{$contract.Type}}CallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error { func (_{{$contract.Type}} *{{$contract.Type}}CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _{{$contract.Type}}.Contract.contract.Call(opts, result, method, params...) return _{{$contract.Type}}.Contract.contract.Call(opts, result, method, params...)
} }
@ -299,19 +300,23 @@ var (
// //
// Solidity: {{.Original.String}} // Solidity: {{.Original.String}}
func (_{{$contract.Type}} *{{$contract.Type}}Caller) {{.Normalized.Name}}(opts *bind.CallOpts {{range .Normalized.Inputs}}, {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} },{{else}}{{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}}{{end}} error) { func (_{{$contract.Type}} *{{$contract.Type}}Caller) {{.Normalized.Name}}(opts *bind.CallOpts {{range .Normalized.Inputs}}, {{.Name}} {{bindtype .Type $structs}} {{end}}) ({{if .Structured}}struct{ {{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}};{{end}} },{{else}}{{range .Normalized.Outputs}}{{bindtype .Type $structs}},{{end}}{{end}} error) {
{{if .Structured}}ret := new(struct{ var out []interface{}
{{range .Normalized.Outputs}}{{.Name}} {{bindtype .Type $structs}} err := _{{$contract.Type}}.contract.Call(opts, &out, "{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}})
{{end}} {{if .Structured}}
}){{else}}var ( outstruct := new(struct{ {{range .Normalized.Outputs}} {{.Name}} {{bindtype .Type $structs}}; {{end}} })
{{range $i, $_ := .Normalized.Outputs}}ret{{$i}} = new({{bindtype .Type $structs}}) {{range $i, $t := .Normalized.Outputs}}
{{end}} outstruct.{{.Name}} = out[{{$i}}].({{bindtype .Type $structs}}){{end}}
){{end}}
out := {{if .Structured}}ret{{else}}{{if eq (len .Normalized.Outputs) 1}}ret0{{else}}&[]interface{}{ return *outstruct, err
{{range $i, $_ := .Normalized.Outputs}}ret{{$i}}, {{else}}
{{end}} if err != nil {
}{{end}}{{end}} return {{range $i, $_ := .Normalized.Outputs}}*new({{bindtype .Type $structs}}), {{end}} err
err := _{{$contract.Type}}.contract.Call(opts, out, "{{.Original.Name}}" {{range .Normalized.Inputs}}, {{.Name}}{{end}}) }
return {{if .Structured}}*ret,{{else}}{{range $i, $_ := .Normalized.Outputs}}*ret{{$i}},{{end}}{{end}} err {{range $i, $t := .Normalized.Outputs}}
out{{$i}} := *abi.ConvertType(out[{{$i}}], new({{bindtype .Type $structs}})).(*{{bindtype .Type $structs}}){{end}}
return {{range $i, $t := .Normalized.Outputs}}out{{$i}}, {{end}} err
{{end}}
} }
// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}. // {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}.
@ -543,8 +548,8 @@ var (
{{end}} {{end}}
` `
// tmplSourceJava is the Java source template use to generate the contract binding // tmplSourceJava is the Java source template that the generated Java contract binding
// based on. // is based on.
const tmplSourceJava = ` const tmplSourceJava = `
// This file is an automatically generated Java binding. Do not modify as any // This file is an automatically generated Java binding. Do not modify as any
// change will likely be lost upon the next re-generation! // change will likely be lost upon the next re-generation!

View file

@ -21,9 +21,9 @@ import (
"errors" "errors"
"time" "time"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/maticnetwork/bor/log" "github.com/ethereum/go-ethereum/log"
) )
// WaitMined waits for tx to be mined on the blockchain. // WaitMined waits for tx to be mined on the blockchain.

View file

@ -23,12 +23,12 @@ import (
"testing" "testing"
"time" "time"
"github.com/maticnetwork/bor/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/maticnetwork/bor/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/core" "github.com/ethereum/go-ethereum/core"
"github.com/maticnetwork/bor/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")

View file

@ -52,7 +52,7 @@ func sliceTypeCheck(t Type, val reflect.Value) error {
} }
} }
if elemKind := val.Type().Elem().Kind(); elemKind != t.Elem.GetType().Kind() { if val.Type().Elem().Kind() != t.Elem.GetType().Kind() {
return typeErr(formatSliceString(t.Elem.GetType().Kind(), t.Size), val.Type()) return typeErr(formatSliceString(t.Elem.GetType().Kind(), t.Size), val.Type())
} }
return nil return nil

View file

@ -20,8 +20,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
// Event is an event potentially triggered by the EVM's LOG mechanism. The Event // Event is an event potentially triggered by the EVM's LOG mechanism. The Event
@ -32,7 +32,7 @@ type Event struct {
// the raw name and a suffix will be added in the case of a event overload. // the raw name and a suffix will be added in the case of a event overload.
// //
// e.g. // e.g.
// There are two events have same name: // These are two events that have the same name:
// * foo(int,int) // * foo(int,int)
// * foo(uint,uint) // * foo(uint,uint)
// The event name of the first one wll be resolved as foo while the second one // The event name of the first one wll be resolved as foo while the second one

View file

@ -25,8 +25,8 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -147,10 +147,6 @@ func TestEventString(t *testing.T) {
// TestEventMultiValueWithArrayUnpack verifies that array fields will be counted after parsing array. // TestEventMultiValueWithArrayUnpack verifies that array fields will be counted after parsing array.
func TestEventMultiValueWithArrayUnpack(t *testing.T) { func TestEventMultiValueWithArrayUnpack(t *testing.T) {
definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": false, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"uint8"}]}]` definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": false, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"uint8"}]}]`
type testStruct struct {
Value1 [2]uint8
Value2 uint8
}
abi, err := JSON(strings.NewReader(definition)) abi, err := JSON(strings.NewReader(definition))
require.NoError(t, err) require.NoError(t, err)
var b bytes.Buffer var b bytes.Buffer
@ -158,10 +154,10 @@ func TestEventMultiValueWithArrayUnpack(t *testing.T) {
for ; i <= 3; i++ { for ; i <= 3; i++ {
b.Write(packNum(reflect.ValueOf(i))) b.Write(packNum(reflect.ValueOf(i)))
} }
var rst testStruct unpacked, err := abi.Unpack("test", b.Bytes())
require.NoError(t, abi.Unpack(&rst, "test", b.Bytes())) require.NoError(t, err)
require.Equal(t, [2]uint8{1, 2}, rst.Value1) require.Equal(t, [2]uint8{1, 2}, unpacked[0])
require.Equal(t, uint8(3), rst.Value2) require.Equal(t, uint8(3), unpacked[1])
} }
func TestEventTupleUnpack(t *testing.T) { func TestEventTupleUnpack(t *testing.T) {
@ -351,14 +347,14 @@ func unpackTestEventData(dest interface{}, hexData string, jsonEvent []byte, ass
var e Event var e Event
assert.NoError(json.Unmarshal(jsonEvent, &e), "Should be able to unmarshal event ABI") assert.NoError(json.Unmarshal(jsonEvent, &e), "Should be able to unmarshal event ABI")
a := ABI{Events: map[string]Event{"e": e}} a := ABI{Events: map[string]Event{"e": e}}
return a.Unpack(dest, "e", data) return a.UnpackIntoInterface(dest, "e", data)
} }
// TestEventUnpackIndexed verifies that indexed field will be skipped by event decoder. // TestEventUnpackIndexed verifies that indexed field will be skipped by event decoder.
func TestEventUnpackIndexed(t *testing.T) { func TestEventUnpackIndexed(t *testing.T) {
definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8"},{"indexed": false, "name":"value2", "type":"uint8"}]}]` definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8"},{"indexed": false, "name":"value2", "type":"uint8"}]}]`
type testStruct struct { type testStruct struct {
Value1 uint8 Value1 uint8 // indexed
Value2 uint8 Value2 uint8
} }
abi, err := JSON(strings.NewReader(definition)) abi, err := JSON(strings.NewReader(definition))
@ -366,16 +362,16 @@ func TestEventUnpackIndexed(t *testing.T) {
var b bytes.Buffer var b bytes.Buffer
b.Write(packNum(reflect.ValueOf(uint8(8)))) b.Write(packNum(reflect.ValueOf(uint8(8))))
var rst testStruct var rst testStruct
require.NoError(t, abi.Unpack(&rst, "test", b.Bytes())) require.NoError(t, abi.UnpackIntoInterface(&rst, "test", b.Bytes()))
require.Equal(t, uint8(0), rst.Value1) require.Equal(t, uint8(0), rst.Value1)
require.Equal(t, uint8(8), rst.Value2) require.Equal(t, uint8(8), rst.Value2)
} }
// TestEventIndexedWithArrayUnpack verifies that decoder will not overlow when static array is indexed input. // TestEventIndexedWithArrayUnpack verifies that decoder will not overflow when static array is indexed input.
func TestEventIndexedWithArrayUnpack(t *testing.T) { func TestEventIndexedWithArrayUnpack(t *testing.T) {
definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"string"}]}]` definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"string"}]}]`
type testStruct struct { type testStruct struct {
Value1 [2]uint8 Value1 [2]uint8 // indexed
Value2 string Value2 string
} }
abi, err := JSON(strings.NewReader(definition)) abi, err := JSON(strings.NewReader(definition))
@ -388,7 +384,7 @@ func TestEventIndexedWithArrayUnpack(t *testing.T) {
b.Write(common.RightPadBytes([]byte(stringOut), 32)) b.Write(common.RightPadBytes([]byte(stringOut), 32))
var rst testStruct var rst testStruct
require.NoError(t, abi.Unpack(&rst, "test", b.Bytes())) require.NoError(t, abi.UnpackIntoInterface(&rst, "test", b.Bytes()))
require.Equal(t, [2]uint8{0, 0}, rst.Value1) require.Equal(t, [2]uint8{0, 0}, rst.Value1)
require.Equal(t, stringOut, rst.Value2) require.Equal(t, stringOut, rst.Value2)
} }

View file

@ -20,7 +20,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
// FunctionType represents different types of functions a contract might have. // FunctionType represents different types of functions a contract might have.
@ -45,7 +45,7 @@ const (
// If the method is `Const` no transaction needs to be created for this // If the method is `Const` no transaction needs to be created for this
// particular Method call. It can easily be simulated using a local VM. // particular Method call. It can easily be simulated using a local VM.
// For example a `Balance()` method only needs to retrieve something // For example a `Balance()` method only needs to retrieve something
// from the storage and therefore requires no Tx to be send to the // from the storage and therefore requires no Tx to be sent to the
// network. A method such as `Transact` does require a Tx and thus will // network. A method such as `Transact` does require a Tx and thus will
// be flagged `false`. // be flagged `false`.
// Input specifies the required input parameters for this gives method. // Input specifies the required input parameters for this gives method.
@ -54,7 +54,7 @@ type Method struct {
// the raw name and a suffix will be added in the case of a function overload. // the raw name and a suffix will be added in the case of a function overload.
// //
// e.g. // e.g.
// There are two functions have same name: // These are two functions that have the same name:
// * foo(int,int) // * foo(int,int)
// * foo(uint,uint) // * foo(uint,uint)
// The method name of the first one will be resolved as foo while the second one // The method name of the first one will be resolved as foo while the second one

View file

@ -17,15 +17,17 @@
package abi package abi
import ( import (
"errors"
"fmt"
"math/big" "math/big"
"reflect" "reflect"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/common/math" "github.com/ethereum/go-ethereum/common/math"
) )
// packBytesSlice packs the given bytes as [L, V] as the canonical representation // packBytesSlice packs the given bytes as [L, V] as the canonical representation
// bytes slice // bytes slice.
func packBytesSlice(bytes []byte, l int) []byte { func packBytesSlice(bytes []byte, l int) []byte {
len := packNum(reflect.ValueOf(l)) len := packNum(reflect.ValueOf(l))
return append(len, common.RightPadBytes(bytes, (l+31)/32*32)...) return append(len, common.RightPadBytes(bytes, (l+31)/32*32)...)
@ -33,39 +35,42 @@ func packBytesSlice(bytes []byte, l int) []byte {
// packElement packs the given reflect value according to the abi specification in // packElement packs the given reflect value according to the abi specification in
// t. // t.
func packElement(t Type, reflectValue reflect.Value) []byte { func packElement(t Type, reflectValue reflect.Value) ([]byte, error) {
switch t.T { switch t.T {
case IntTy, UintTy: case IntTy, UintTy:
return packNum(reflectValue) return packNum(reflectValue), nil
case StringTy: case StringTy:
return packBytesSlice([]byte(reflectValue.String()), reflectValue.Len()) return packBytesSlice([]byte(reflectValue.String()), reflectValue.Len()), nil
case AddressTy: case AddressTy:
if reflectValue.Kind() == reflect.Array { if reflectValue.Kind() == reflect.Array {
reflectValue = mustArrayToByteSlice(reflectValue) reflectValue = mustArrayToByteSlice(reflectValue)
} }
return common.LeftPadBytes(reflectValue.Bytes(), 32) return common.LeftPadBytes(reflectValue.Bytes(), 32), nil
case BoolTy: case BoolTy:
if reflectValue.Bool() { if reflectValue.Bool() {
return math.PaddedBigBytes(common.Big1, 32) return math.PaddedBigBytes(common.Big1, 32), nil
} }
return math.PaddedBigBytes(common.Big0, 32) return math.PaddedBigBytes(common.Big0, 32), nil
case BytesTy: case BytesTy:
if reflectValue.Kind() == reflect.Array { if reflectValue.Kind() == reflect.Array {
reflectValue = mustArrayToByteSlice(reflectValue) reflectValue = mustArrayToByteSlice(reflectValue)
} }
return packBytesSlice(reflectValue.Bytes(), reflectValue.Len()) if reflectValue.Type() != reflect.TypeOf([]byte{}) {
return []byte{}, errors.New("Bytes type is neither slice nor array")
}
return packBytesSlice(reflectValue.Bytes(), reflectValue.Len()), nil
case FixedBytesTy, FunctionTy: case FixedBytesTy, FunctionTy:
if reflectValue.Kind() == reflect.Array { if reflectValue.Kind() == reflect.Array {
reflectValue = mustArrayToByteSlice(reflectValue) reflectValue = mustArrayToByteSlice(reflectValue)
} }
return common.RightPadBytes(reflectValue.Bytes(), 32) return common.RightPadBytes(reflectValue.Bytes(), 32), nil
default: default:
panic("abi: fatal error") return []byte{}, fmt.Errorf("Could not pack element, unknown type: %v", t.T)
} }
} }
// packNum packs the given number (using the reflect value) and will cast it to appropriate number representation // packNum packs the given number (using the reflect value) and will cast it to appropriate number representation.
func packNum(value reflect.Value) []byte { func packNum(value reflect.Value) []byte {
switch kind := value.Kind(); kind { switch kind := value.Kind(); kind {
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
@ -77,5 +82,4 @@ func packNum(value reflect.Value) []byte {
default: default:
panic("abi: fatal error") panic("abi: fatal error")
} }
} }

View file

@ -27,7 +27,7 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
) )
// TestPack tests the general pack/unpack tests in packing_test.go // TestPack tests the general pack/unpack tests in packing_test.go
@ -44,18 +44,7 @@ func TestPack(t *testing.T) {
t.Fatalf("invalid ABI definition %s, %v", inDef, err) t.Fatalf("invalid ABI definition %s, %v", inDef, err)
} }
var packed []byte var packed []byte
if reflect.TypeOf(test.unpacked).Kind() != reflect.Struct { packed, err = inAbi.Pack("method", test.unpacked)
packed, err = inAbi.Pack("method", test.unpacked)
} else {
// if want is a struct we need to use the components.
elem := reflect.ValueOf(test.unpacked)
var values []interface{}
for i := 0; i < elem.NumField(); i++ {
field := elem.Field(i)
values = append(values, field.Interface())
}
packed, err = inAbi.Pack("method", values...)
}
if err != nil { if err != nil {
t.Fatalf("test %d (%v) failed: %v", i, test.def, err) t.Fatalf("test %d (%v) failed: %v", i, test.def, err)

View file

@ -19,7 +19,7 @@ package abi
import ( import (
"math/big" "math/big"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
) )
type packUnpackTest struct { type packUnpackTest struct {
@ -620,7 +620,7 @@ var packUnpackTests = []packUnpackTest{
{ {
def: `[{"type": "bytes32[]"}]`, def: `[{"type": "bytes32[]"}]`,
unpacked: []common.Hash{{1}, {2}}, unpacked: [][32]byte{{1}, {2}},
packed: "0000000000000000000000000000000000000000000000000000000000000020" + packed: "0000000000000000000000000000000000000000000000000000000000000020" +
"0000000000000000000000000000000000000000000000000000000000000002" + "0000000000000000000000000000000000000000000000000000000000000002" +
"0100000000000000000000000000000000000000000000000000000000000000" + "0100000000000000000000000000000000000000000000000000000000000000" +
@ -722,7 +722,7 @@ var packUnpackTests = []packUnpackTest{
}, },
// struct outputs // struct outputs
{ {
def: `[{"name":"int1","type":"int256"},{"name":"int2","type":"int256"}]`, def: `[{"components": [{"name":"int1","type":"int256"},{"name":"int2","type":"int256"}], "type":"tuple"}]`,
packed: "0000000000000000000000000000000000000000000000000000000000000001" + packed: "0000000000000000000000000000000000000000000000000000000000000001" +
"0000000000000000000000000000000000000000000000000000000000000002", "0000000000000000000000000000000000000000000000000000000000000002",
unpacked: struct { unpacked: struct {
@ -731,28 +731,28 @@ var packUnpackTests = []packUnpackTest{
}{big.NewInt(1), big.NewInt(2)}, }{big.NewInt(1), big.NewInt(2)},
}, },
{ {
def: `[{"name":"int_one","type":"int256"}]`, def: `[{"components": [{"name":"int_one","type":"int256"}], "type":"tuple"}]`,
packed: "0000000000000000000000000000000000000000000000000000000000000001", packed: "0000000000000000000000000000000000000000000000000000000000000001",
unpacked: struct { unpacked: struct {
IntOne *big.Int IntOne *big.Int
}{big.NewInt(1)}, }{big.NewInt(1)},
}, },
{ {
def: `[{"name":"int__one","type":"int256"}]`, def: `[{"components": [{"name":"int__one","type":"int256"}], "type":"tuple"}]`,
packed: "0000000000000000000000000000000000000000000000000000000000000001", packed: "0000000000000000000000000000000000000000000000000000000000000001",
unpacked: struct { unpacked: struct {
IntOne *big.Int IntOne *big.Int
}{big.NewInt(1)}, }{big.NewInt(1)},
}, },
{ {
def: `[{"name":"int_one_","type":"int256"}]`, def: `[{"components": [{"name":"int_one_","type":"int256"}], "type":"tuple"}]`,
packed: "0000000000000000000000000000000000000000000000000000000000000001", packed: "0000000000000000000000000000000000000000000000000000000000000001",
unpacked: struct { unpacked: struct {
IntOne *big.Int IntOne *big.Int
}{big.NewInt(1)}, }{big.NewInt(1)},
}, },
{ {
def: `[{"name":"int_one","type":"int256"}, {"name":"intone","type":"int256"}]`, def: `[{"components": [{"name":"int_one","type":"int256"}, {"name":"intone","type":"int256"}], "type":"tuple"}]`,
packed: "0000000000000000000000000000000000000000000000000000000000000001" + packed: "0000000000000000000000000000000000000000000000000000000000000001" +
"0000000000000000000000000000000000000000000000000000000000000002", "0000000000000000000000000000000000000000000000000000000000000002",
unpacked: struct { unpacked: struct {
@ -831,11 +831,11 @@ var packUnpackTests = []packUnpackTest{
}, },
{ {
// static tuple // static tuple
def: `[{"name":"a","type":"int64"}, def: `[{"components": [{"name":"a","type":"int64"},
{"name":"b","type":"int256"}, {"name":"b","type":"int256"},
{"name":"c","type":"int256"}, {"name":"c","type":"int256"},
{"name":"d","type":"bool"}, {"name":"d","type":"bool"},
{"name":"e","type":"bytes32[3][2]"}]`, {"name":"e","type":"bytes32[3][2]"}], "type":"tuple"}]`,
unpacked: struct { unpacked: struct {
A int64 A int64
B *big.Int B *big.Int
@ -855,21 +855,22 @@ var packUnpackTests = []packUnpackTest{
"0500000000000000000000000000000000000000000000000000000000000000", // struct[e] array[1][2] "0500000000000000000000000000000000000000000000000000000000000000", // struct[e] array[1][2]
}, },
{ {
def: `[{"name":"a","type":"string"}, def: `[{"components": [{"name":"a","type":"string"},
{"name":"b","type":"int64"}, {"name":"b","type":"int64"},
{"name":"c","type":"bytes"}, {"name":"c","type":"bytes"},
{"name":"d","type":"string[]"}, {"name":"d","type":"string[]"},
{"name":"e","type":"int256[]"}, {"name":"e","type":"int256[]"},
{"name":"f","type":"address[]"}]`, {"name":"f","type":"address[]"}], "type":"tuple"}]`,
unpacked: struct { unpacked: struct {
FieldA string `abi:"a"` // Test whether abi tag works A string
FieldB int64 `abi:"b"` B int64
C []byte C []byte
D []string D []string
E []*big.Int E []*big.Int
F []common.Address F []common.Address
}{"foobar", 1, []byte{1}, []string{"foo", "bar"}, []*big.Int{big.NewInt(1), big.NewInt(-1)}, []common.Address{{1}, {2}}}, }{"foobar", 1, []byte{1}, []string{"foo", "bar"}, []*big.Int{big.NewInt(1), big.NewInt(-1)}, []common.Address{{1}, {2}}},
packed: "00000000000000000000000000000000000000000000000000000000000000c0" + // struct[a] offset packed: "0000000000000000000000000000000000000000000000000000000000000020" + // struct a
"00000000000000000000000000000000000000000000000000000000000000c0" + // struct[a] offset
"0000000000000000000000000000000000000000000000000000000000000001" + // struct[b] "0000000000000000000000000000000000000000000000000000000000000001" + // struct[b]
"0000000000000000000000000000000000000000000000000000000000000100" + // struct[c] offset "0000000000000000000000000000000000000000000000000000000000000100" + // struct[c] offset
"0000000000000000000000000000000000000000000000000000000000000140" + // struct[d] offset "0000000000000000000000000000000000000000000000000000000000000140" + // struct[d] offset
@ -894,23 +895,24 @@ var packUnpackTests = []packUnpackTest{
"0000000000000000000000000200000000000000000000000000000000000000", // common.Address{2} "0000000000000000000000000200000000000000000000000000000000000000", // common.Address{2}
}, },
{ {
def: `[{"components": [{"name": "a","type": "uint256"}, def: `[{"components": [{ "type": "tuple","components": [{"name": "a","type": "uint256"},
{"name": "b","type": "uint256[]"}], {"name": "b","type": "uint256[]"}],
"name": "a","type": "tuple"}, "name": "a","type": "tuple"},
{"name": "b","type": "uint256[]"}]`, {"name": "b","type": "uint256[]"}], "type": "tuple"}]`,
unpacked: struct { unpacked: struct {
A struct { A struct {
FieldA *big.Int `abi:"a"` A *big.Int
B []*big.Int B []*big.Int
} }
B []*big.Int B []*big.Int
}{ }{
A: struct { A: struct {
FieldA *big.Int `abi:"a"` // Test whether abi tag works for nested tuple A *big.Int
B []*big.Int B []*big.Int
}{big.NewInt(1), []*big.Int{big.NewInt(1), big.NewInt(2)}}, }{big.NewInt(1), []*big.Int{big.NewInt(1), big.NewInt(2)}},
B: []*big.Int{big.NewInt(1), big.NewInt(2)}}, B: []*big.Int{big.NewInt(1), big.NewInt(2)}},
packed: "0000000000000000000000000000000000000000000000000000000000000040" + // a offset packed: "0000000000000000000000000000000000000000000000000000000000000020" + // struct a
"0000000000000000000000000000000000000000000000000000000000000040" + // a offset
"00000000000000000000000000000000000000000000000000000000000000e0" + // b offset "00000000000000000000000000000000000000000000000000000000000000e0" + // b offset
"0000000000000000000000000000000000000000000000000000000000000001" + // a.a value "0000000000000000000000000000000000000000000000000000000000000001" + // a.a value
"0000000000000000000000000000000000000000000000000000000000000040" + // a.b offset "0000000000000000000000000000000000000000000000000000000000000040" + // a.b offset

View file

@ -24,6 +24,29 @@ import (
"strings" "strings"
) )
// ConvertType converts an interface of a runtime type into a interface of the
// given type
// e.g. turn
// var fields []reflect.StructField
// fields = append(fields, reflect.StructField{
// Name: "X",
// Type: reflect.TypeOf(new(big.Int)),
// Tag: reflect.StructTag("json:\"" + "x" + "\""),
// }
// into
// type TupleT struct { X *big.Int }
func ConvertType(in interface{}, proto interface{}) interface{} {
protoType := reflect.TypeOf(proto)
if reflect.TypeOf(in).ConvertibleTo(protoType) {
return reflect.ValueOf(in).Convert(protoType).Interface()
}
// Use set as a last ditch effort
if err := set(reflect.ValueOf(proto), reflect.ValueOf(in)); err != nil {
panic(err)
}
return proto
}
// indirect recursively dereferences the value until it either gets the value // indirect recursively dereferences the value until it either gets the value
// or finds a big.Int // or finds a big.Int
func indirect(v reflect.Value) reflect.Value { func indirect(v reflect.Value) reflect.Value {
@ -61,7 +84,7 @@ func reflectIntType(unsigned bool, size int) reflect.Type {
return reflect.TypeOf(&big.Int{}) return reflect.TypeOf(&big.Int{})
} }
// mustArrayToBytesSlice creates a new byte slice with the exact same size as value // mustArrayToByteSlice creates a new byte slice with the exact same size as value
// and copies the bytes in value to the new slice. // and copies the bytes in value to the new slice.
func mustArrayToByteSlice(value reflect.Value) reflect.Value { func mustArrayToByteSlice(value reflect.Value) reflect.Value {
slice := reflect.MakeSlice(reflect.TypeOf([]byte{}), value.Len(), value.Len()) slice := reflect.MakeSlice(reflect.TypeOf([]byte{}), value.Len(), value.Len())
@ -119,6 +142,9 @@ func setSlice(dst, src reflect.Value) error {
} }
func setArray(dst, src reflect.Value) error { func setArray(dst, src reflect.Value) error {
if src.Kind() == reflect.Ptr {
return set(dst, indirect(src))
}
array := reflect.New(dst.Type()).Elem() array := reflect.New(dst.Type()).Elem()
min := src.Len() min := src.Len()
if src.Len() > dst.Len() { if src.Len() > dst.Len() {

View file

@ -17,6 +17,7 @@
package abi package abi
import ( import (
"math/big"
"reflect" "reflect"
"testing" "testing"
) )
@ -189,3 +190,72 @@ func TestReflectNameToStruct(t *testing.T) {
}) })
} }
} }
func TestConvertType(t *testing.T) {
// Test Basic Struct
type T struct {
X *big.Int
Y *big.Int
}
// Create on-the-fly structure
var fields []reflect.StructField
fields = append(fields, reflect.StructField{
Name: "X",
Type: reflect.TypeOf(new(big.Int)),
Tag: reflect.StructTag("json:\"" + "x" + "\""),
})
fields = append(fields, reflect.StructField{
Name: "Y",
Type: reflect.TypeOf(new(big.Int)),
Tag: reflect.StructTag("json:\"" + "y" + "\""),
})
val := reflect.New(reflect.StructOf(fields))
val.Elem().Field(0).Set(reflect.ValueOf(big.NewInt(1)))
val.Elem().Field(1).Set(reflect.ValueOf(big.NewInt(2)))
// ConvertType
out := *ConvertType(val.Interface(), new(T)).(*T)
if out.X.Cmp(big.NewInt(1)) != 0 {
t.Errorf("ConvertType failed, got %v want %v", out.X, big.NewInt(1))
}
if out.Y.Cmp(big.NewInt(2)) != 0 {
t.Errorf("ConvertType failed, got %v want %v", out.Y, big.NewInt(2))
}
// Slice Type
val2 := reflect.MakeSlice(reflect.SliceOf(reflect.StructOf(fields)), 2, 2)
val2.Index(0).Field(0).Set(reflect.ValueOf(big.NewInt(1)))
val2.Index(0).Field(1).Set(reflect.ValueOf(big.NewInt(2)))
val2.Index(1).Field(0).Set(reflect.ValueOf(big.NewInt(3)))
val2.Index(1).Field(1).Set(reflect.ValueOf(big.NewInt(4)))
out2 := *ConvertType(val2.Interface(), new([]T)).(*[]T)
if out2[0].X.Cmp(big.NewInt(1)) != 0 {
t.Errorf("ConvertType failed, got %v want %v", out2[0].X, big.NewInt(1))
}
if out2[0].Y.Cmp(big.NewInt(2)) != 0 {
t.Errorf("ConvertType failed, got %v want %v", out2[1].Y, big.NewInt(2))
}
if out2[1].X.Cmp(big.NewInt(3)) != 0 {
t.Errorf("ConvertType failed, got %v want %v", out2[0].X, big.NewInt(1))
}
if out2[1].Y.Cmp(big.NewInt(4)) != 0 {
t.Errorf("ConvertType failed, got %v want %v", out2[1].Y, big.NewInt(2))
}
// Array Type
val3 := reflect.New(reflect.ArrayOf(2, reflect.StructOf(fields)))
val3.Elem().Index(0).Field(0).Set(reflect.ValueOf(big.NewInt(1)))
val3.Elem().Index(0).Field(1).Set(reflect.ValueOf(big.NewInt(2)))
val3.Elem().Index(1).Field(0).Set(reflect.ValueOf(big.NewInt(3)))
val3.Elem().Index(1).Field(1).Set(reflect.ValueOf(big.NewInt(4)))
out3 := *ConvertType(val3.Interface(), new([2]T)).(*[2]T)
if out3[0].X.Cmp(big.NewInt(1)) != 0 {
t.Errorf("ConvertType failed, got %v want %v", out3[0].X, big.NewInt(1))
}
if out3[0].Y.Cmp(big.NewInt(2)) != 0 {
t.Errorf("ConvertType failed, got %v want %v", out3[1].Y, big.NewInt(2))
}
if out3[1].X.Cmp(big.NewInt(3)) != 0 {
t.Errorf("ConvertType failed, got %v want %v", out3[0].X, big.NewInt(1))
}
if out3[1].Y.Cmp(big.NewInt(4)) != 0 {
t.Errorf("ConvertType failed, got %v want %v", out3[1].Y, big.NewInt(2))
}
}

View file

@ -23,8 +23,8 @@ import (
"math/big" "math/big"
"reflect" "reflect"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
// MakeTopics converts a filter query argument list into a filter topic set. // MakeTopics converts a filter query argument list into a filter topic set.
@ -102,7 +102,7 @@ func genIntType(rule int64, size uint) []byte {
var topic [common.HashLength]byte var topic [common.HashLength]byte
if rule < 0 { if rule < 0 {
// if a rule is negative, we need to put it into two's complement. // if a rule is negative, we need to put it into two's complement.
// extended to common.Hashlength bytes. // extended to common.HashLength bytes.
topic = [common.HashLength]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255} topic = [common.HashLength]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}
} }
for i := uint(0); i < size; i++ { for i := uint(0); i < size; i++ {
@ -120,7 +120,7 @@ func ParseTopics(out interface{}, fields Arguments, topics []common.Hash) error
}) })
} }
// ParseTopicsIntoMap converts the indexed topic field-value pairs into map key-value pairs // ParseTopicsIntoMap converts the indexed topic field-value pairs into map key-value pairs.
func ParseTopicsIntoMap(out map[string]interface{}, fields Arguments, topics []common.Hash) error { func ParseTopicsIntoMap(out map[string]interface{}, fields Arguments, topics []common.Hash) error {
return parseTopicWithSetter(fields, topics, return parseTopicWithSetter(fields, topics,
func(arg Argument, reconstr interface{}) { func(arg Argument, reconstr interface{}) {

View file

@ -21,8 +21,8 @@ import (
"reflect" "reflect"
"testing" "testing"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
func TestMakeTopics(t *testing.T) { func TestMakeTopics(t *testing.T) {

View file

@ -24,7 +24,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
) )
// Type enumerator // Type enumerator
@ -44,7 +44,7 @@ const (
FunctionTy FunctionTy
) )
// Type is the reflection of the supported argument type // Type is the reflection of the supported argument type.
type Type struct { type Type struct {
Elem *Type Elem *Type
Size int Size int
@ -264,7 +264,7 @@ func overloadedArgName(rawName string, names map[string]string) (string, error)
return fieldName, nil return fieldName, nil
} }
// String implements Stringer // String implements Stringer.
func (t Type) String() (out string) { func (t Type) String() (out string) {
return t.stringKind return t.stringKind
} }
@ -346,7 +346,7 @@ func (t Type) pack(v reflect.Value) ([]byte, error) {
return append(ret, tail...), nil return append(ret, tail...), nil
default: default:
return packElement(t, v), nil return packElement(t, v)
} }
} }
@ -386,7 +386,7 @@ func isDynamicType(t Type) bool {
func getTypeSize(t Type) int { func getTypeSize(t Type) int {
if t.T == ArrayTy && !isDynamicType(*t.Elem) { if t.T == ArrayTy && !isDynamicType(*t.Elem) {
// Recursively calculate type size if it is a nested array // Recursively calculate type size if it is a nested array
if t.Elem.T == ArrayTy { if t.Elem.T == ArrayTy || t.Elem.T == TupleTy {
return t.Size * getTypeSize(*t.Elem) return t.Size * getTypeSize(*t.Elem)
} }
return t.Size * 32 return t.Size * 32

View file

@ -22,7 +22,7 @@ import (
"testing" "testing"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
) )
// typeWithoutStringer is a alias for the Type type which simply doesn't implement // typeWithoutStringer is a alias for the Type type which simply doesn't implement
@ -330,3 +330,39 @@ func TestInternalType(t *testing.T) {
t.Errorf("type %q: parsed type mismatch:\nGOT %s\nWANT %s ", blob, spew.Sdump(typeWithoutStringer(typ)), spew.Sdump(typeWithoutStringer(kind))) t.Errorf("type %q: parsed type mismatch:\nGOT %s\nWANT %s ", blob, spew.Sdump(typeWithoutStringer(typ)), spew.Sdump(typeWithoutStringer(kind)))
} }
} }
func TestGetTypeSize(t *testing.T) {
var testCases = []struct {
typ string
components []ArgumentMarshaling
typSize int
}{
// simple array
{"uint256[2]", nil, 32 * 2},
{"address[3]", nil, 32 * 3},
{"bytes32[4]", nil, 32 * 4},
// array array
{"uint256[2][3][4]", nil, 32 * (2 * 3 * 4)},
// array tuple
{"tuple[2]", []ArgumentMarshaling{{Name: "x", Type: "bytes32"}, {Name: "y", Type: "bytes32"}}, (32 * 2) * 2},
// simple tuple
{"tuple", []ArgumentMarshaling{{Name: "x", Type: "uint256"}, {Name: "y", Type: "uint256"}}, 32 * 2},
// tuple array
{"tuple", []ArgumentMarshaling{{Name: "x", Type: "bytes32[2]"}}, 32 * 2},
// tuple tuple
{"tuple", []ArgumentMarshaling{{Name: "x", Type: "tuple", Components: []ArgumentMarshaling{{Name: "x", Type: "bytes32"}}}}, 32},
{"tuple", []ArgumentMarshaling{{Name: "x", Type: "tuple", Components: []ArgumentMarshaling{{Name: "x", Type: "bytes32[2]"}, {Name: "y", Type: "uint256"}}}}, 32 * (2 + 1)},
}
for i, data := range testCases {
typ, err := NewType(data.typ, "", data.components)
if err != nil {
t.Errorf("type %q: failed to parse type string: %v", data.typ, err)
}
result := getTypeSize(typ)
if result != data.typSize {
t.Errorf("case %d type %q: get type size error: actual: %d expected: %d", i, data.typ, result, data.typSize)
}
}
}

View file

@ -22,17 +22,17 @@ import (
"math/big" "math/big"
"reflect" "reflect"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
) )
var ( var (
// MaxUint256 is the maximum value that can be represented by a uint256 // MaxUint256 is the maximum value that can be represented by a uint256.
MaxUint256 = new(big.Int).Sub(new(big.Int).Lsh(common.Big1, 256), common.Big1) MaxUint256 = new(big.Int).Sub(new(big.Int).Lsh(common.Big1, 256), common.Big1)
// MaxInt256 is the maximum value that can be represented by a int256 // MaxInt256 is the maximum value that can be represented by a int256.
MaxInt256 = new(big.Int).Sub(new(big.Int).Lsh(common.Big1, 255), common.Big1) MaxInt256 = new(big.Int).Sub(new(big.Int).Lsh(common.Big1, 255), common.Big1)
) )
// ReadInteger reads the integer based on its kind and returns the appropriate value // ReadInteger reads the integer based on its kind and returns the appropriate value.
func ReadInteger(typ Type, b []byte) interface{} { func ReadInteger(typ Type, b []byte) interface{} {
if typ.T == UintTy { if typ.T == UintTy {
switch typ.Size { switch typ.Size {
@ -73,7 +73,7 @@ func ReadInteger(typ Type, b []byte) interface{} {
} }
} }
// reads a bool // readBool reads a bool.
func readBool(word []byte) (bool, error) { func readBool(word []byte) (bool, error) {
for _, b := range word[:31] { for _, b := range word[:31] {
if b != 0 { if b != 0 {
@ -91,7 +91,8 @@ func readBool(word []byte) (bool, error) {
} }
// A function type is simply the address with the function selection signature at the end. // A function type is simply the address with the function selection signature at the end.
// This enforces that standard by always presenting it as a 24-array (address + sig = 24 bytes) //
// readFunctionType enforces that standard by always presenting it as a 24-array (address + sig = 24 bytes)
func readFunctionType(t Type, word []byte) (funcTy [24]byte, err error) { func readFunctionType(t Type, word []byte) (funcTy [24]byte, err error) {
if t.T != FunctionTy { if t.T != FunctionTy {
return [24]byte{}, fmt.Errorf("abi: invalid type in call to make function type byte array") return [24]byte{}, fmt.Errorf("abi: invalid type in call to make function type byte array")
@ -104,7 +105,7 @@ func readFunctionType(t Type, word []byte) (funcTy [24]byte, err error) {
return return
} }
// ReadFixedBytes uses reflection to create a fixed array to be read from // ReadFixedBytes uses reflection to create a fixed array to be read from.
func ReadFixedBytes(t Type, word []byte) (interface{}, error) { func ReadFixedBytes(t Type, word []byte) (interface{}, error) {
if t.T != FixedBytesTy { if t.T != FixedBytesTy {
return nil, fmt.Errorf("abi: invalid type in call to make fixed byte array") return nil, fmt.Errorf("abi: invalid type in call to make fixed byte array")
@ -117,7 +118,7 @@ func ReadFixedBytes(t Type, word []byte) (interface{}, error) {
} }
// iteratively unpack elements // forEachUnpack iteratively unpack elements.
func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error) { func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error) {
if size < 0 { if size < 0 {
return nil, fmt.Errorf("cannot marshal input to array, size is negative (%d)", size) return nil, fmt.Errorf("cannot marshal input to array, size is negative (%d)", size)
@ -224,7 +225,10 @@ func toGoType(index int, t Type, output []byte) (interface{}, error) {
return forEachUnpack(t, output[begin:], 0, length) return forEachUnpack(t, output[begin:], 0, length)
case ArrayTy: case ArrayTy:
if isDynamicType(*t.Elem) { if isDynamicType(*t.Elem) {
offset := int64(binary.BigEndian.Uint64(returnOutput[len(returnOutput)-8:])) offset := binary.BigEndian.Uint64(returnOutput[len(returnOutput)-8:])
if offset > uint64(len(output)) {
return nil, fmt.Errorf("abi: toGoType offset greater than output length: offset: %d, len(output): %d", offset, len(output))
}
return forEachUnpack(t, output[offset:], 0, t.Size) return forEachUnpack(t, output[offset:], 0, t.Size)
} }
return forEachUnpack(t, output[index:], 0, t.Size) return forEachUnpack(t, output[index:], 0, t.Size)
@ -249,7 +253,7 @@ func toGoType(index int, t Type, output []byte) (interface{}, error) {
} }
} }
// interprets a 32 byte slice as an offset and then determines which indice to look to decode the type. // lengthPrefixPointsTo interprets a 32 byte slice as an offset and then determines which indices to look to decode the type.
func lengthPrefixPointsTo(index int, output []byte) (start int, length int, err error) { func lengthPrefixPointsTo(index int, output []byte) (start int, length int, err error) {
bigOffsetEnd := big.NewInt(0).SetBytes(output[index : index+32]) bigOffsetEnd := big.NewInt(0).SetBytes(output[index : index+32])
bigOffsetEnd.Add(bigOffsetEnd, common.Big32) bigOffsetEnd.Add(bigOffsetEnd, common.Big32)

View file

@ -26,7 +26,7 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -44,15 +44,13 @@ func TestUnpack(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("invalid hex %s: %v", test.packed, err) t.Fatalf("invalid hex %s: %v", test.packed, err)
} }
outptr := reflect.New(reflect.TypeOf(test.unpacked)) out, err := abi.Unpack("method", encb)
err = abi.Unpack(outptr.Interface(), "method", encb)
if err != nil { if err != nil {
t.Errorf("test %d (%v) failed: %v", i, test.def, err) t.Errorf("test %d (%v) failed: %v", i, test.def, err)
return return
} }
out := outptr.Elem().Interface() if !reflect.DeepEqual(test.unpacked, ConvertType(out[0], test.unpacked)) {
if !reflect.DeepEqual(test.unpacked, out) { t.Errorf("test %d (%v) failed: expected %v, got %v", i, test.def, test.unpacked, out[0])
t.Errorf("test %d (%v) failed: expected %v, got %v", i, test.def, test.unpacked, out)
} }
}) })
} }
@ -221,7 +219,7 @@ func TestLocalUnpackTests(t *testing.T) {
t.Fatalf("invalid hex %s: %v", test.enc, err) t.Fatalf("invalid hex %s: %v", test.enc, err)
} }
outptr := reflect.New(reflect.TypeOf(test.want)) outptr := reflect.New(reflect.TypeOf(test.want))
err = abi.Unpack(outptr.Interface(), "method", encb) err = abi.UnpackIntoInterface(outptr.Interface(), "method", encb)
if err := test.checkError(err); err != nil { if err := test.checkError(err); err != nil {
t.Errorf("test %d (%v) failed: %v", i, test.def, err) t.Errorf("test %d (%v) failed: %v", i, test.def, err)
return return
@ -234,7 +232,7 @@ func TestLocalUnpackTests(t *testing.T) {
} }
} }
func TestUnpackSetDynamicArrayOutput(t *testing.T) { func TestUnpackIntoInterfaceSetDynamicArrayOutput(t *testing.T) {
abi, err := JSON(strings.NewReader(`[{"constant":true,"inputs":[],"name":"testDynamicFixedBytes15","outputs":[{"name":"","type":"bytes15[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"testDynamicFixedBytes32","outputs":[{"name":"","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"}]`)) abi, err := JSON(strings.NewReader(`[{"constant":true,"inputs":[],"name":"testDynamicFixedBytes15","outputs":[{"name":"","type":"bytes15[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"testDynamicFixedBytes32","outputs":[{"name":"","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"}]`))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -249,7 +247,7 @@ func TestUnpackSetDynamicArrayOutput(t *testing.T) {
) )
// test 32 // test 32
err = abi.Unpack(&out32, "testDynamicFixedBytes32", marshalledReturn32) err = abi.UnpackIntoInterface(&out32, "testDynamicFixedBytes32", marshalledReturn32)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -266,7 +264,7 @@ func TestUnpackSetDynamicArrayOutput(t *testing.T) {
} }
// test 15 // test 15
err = abi.Unpack(&out15, "testDynamicFixedBytes32", marshalledReturn15) err = abi.UnpackIntoInterface(&out15, "testDynamicFixedBytes32", marshalledReturn15)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -367,7 +365,7 @@ func TestMethodMultiReturn(t *testing.T) {
tc := tc tc := tc
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
require := require.New(t) require := require.New(t)
err := abi.Unpack(tc.dest, "multi", data) err := abi.UnpackIntoInterface(tc.dest, "multi", data)
if tc.error == "" { if tc.error == "" {
require.Nil(err, "Should be able to unpack method outputs.") require.Nil(err, "Should be able to unpack method outputs.")
require.Equal(tc.expected, tc.dest) require.Equal(tc.expected, tc.dest)
@ -390,7 +388,7 @@ func TestMultiReturnWithArray(t *testing.T) {
ret1, ret1Exp := new([3]uint64), [3]uint64{9, 9, 9} ret1, ret1Exp := new([3]uint64), [3]uint64{9, 9, 9}
ret2, ret2Exp := new(uint64), uint64(8) ret2, ret2Exp := new(uint64), uint64(8)
if err := abi.Unpack(&[]interface{}{ret1, ret2}, "multi", buff.Bytes()); err != nil { if err := abi.UnpackIntoInterface(&[]interface{}{ret1, ret2}, "multi", buff.Bytes()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if !reflect.DeepEqual(*ret1, ret1Exp) { if !reflect.DeepEqual(*ret1, ret1Exp) {
@ -414,7 +412,7 @@ func TestMultiReturnWithStringArray(t *testing.T) {
ret2, ret2Exp := new(common.Address), common.HexToAddress("ab1257528b3782fb40d7ed5f72e624b744dffb2f") ret2, ret2Exp := new(common.Address), common.HexToAddress("ab1257528b3782fb40d7ed5f72e624b744dffb2f")
ret3, ret3Exp := new([2]string), [2]string{"Ethereum", "Hello, Ethereum!"} ret3, ret3Exp := new([2]string), [2]string{"Ethereum", "Hello, Ethereum!"}
ret4, ret4Exp := new(bool), false ret4, ret4Exp := new(bool), false
if err := abi.Unpack(&[]interface{}{ret1, ret2, ret3, ret4}, "multi", buff.Bytes()); err != nil { if err := abi.UnpackIntoInterface(&[]interface{}{ret1, ret2, ret3, ret4}, "multi", buff.Bytes()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if !reflect.DeepEqual(*ret1, ret1Exp) { if !reflect.DeepEqual(*ret1, ret1Exp) {
@ -452,7 +450,7 @@ func TestMultiReturnWithStringSlice(t *testing.T) {
buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000065")) // output[1][1] value buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000065")) // output[1][1] value
ret1, ret1Exp := new([]string), []string{"ethereum", "go-ethereum"} ret1, ret1Exp := new([]string), []string{"ethereum", "go-ethereum"}
ret2, ret2Exp := new([]*big.Int), []*big.Int{big.NewInt(100), big.NewInt(101)} ret2, ret2Exp := new([]*big.Int), []*big.Int{big.NewInt(100), big.NewInt(101)}
if err := abi.Unpack(&[]interface{}{ret1, ret2}, "multi", buff.Bytes()); err != nil { if err := abi.UnpackIntoInterface(&[]interface{}{ret1, ret2}, "multi", buff.Bytes()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if !reflect.DeepEqual(*ret1, ret1Exp) { if !reflect.DeepEqual(*ret1, ret1Exp) {
@ -492,7 +490,7 @@ func TestMultiReturnWithDeeplyNestedArray(t *testing.T) {
{{0x411, 0x412, 0x413}, {0x421, 0x422, 0x423}}, {{0x411, 0x412, 0x413}, {0x421, 0x422, 0x423}},
} }
ret2, ret2Exp := new(uint64), uint64(0x9876) ret2, ret2Exp := new(uint64), uint64(0x9876)
if err := abi.Unpack(&[]interface{}{ret1, ret2}, "multi", buff.Bytes()); err != nil { if err := abi.UnpackIntoInterface(&[]interface{}{ret1, ret2}, "multi", buff.Bytes()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if !reflect.DeepEqual(*ret1, ret1Exp) { if !reflect.DeepEqual(*ret1, ret1Exp) {
@ -531,7 +529,7 @@ func TestUnmarshal(t *testing.T) {
buff.Write(common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000a")) buff.Write(common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000a"))
buff.Write(common.Hex2Bytes("0102000000000000000000000000000000000000000000000000000000000000")) buff.Write(common.Hex2Bytes("0102000000000000000000000000000000000000000000000000000000000000"))
err = abi.Unpack(&mixedBytes, "mixedBytes", buff.Bytes()) err = abi.UnpackIntoInterface(&mixedBytes, "mixedBytes", buff.Bytes())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} else { } else {
@ -546,7 +544,7 @@ func TestUnmarshal(t *testing.T) {
// marshal int // marshal int
var Int *big.Int var Int *big.Int
err = abi.Unpack(&Int, "int", common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")) err = abi.UnpackIntoInterface(&Int, "int", common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001"))
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -557,7 +555,7 @@ func TestUnmarshal(t *testing.T) {
// marshal bool // marshal bool
var Bool bool var Bool bool
err = abi.Unpack(&Bool, "bool", common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001")) err = abi.UnpackIntoInterface(&Bool, "bool", common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001"))
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -574,7 +572,7 @@ func TestUnmarshal(t *testing.T) {
buff.Write(bytesOut) buff.Write(bytesOut)
var Bytes []byte var Bytes []byte
err = abi.Unpack(&Bytes, "bytes", buff.Bytes()) err = abi.UnpackIntoInterface(&Bytes, "bytes", buff.Bytes())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -590,7 +588,7 @@ func TestUnmarshal(t *testing.T) {
bytesOut = common.RightPadBytes([]byte("hello"), 64) bytesOut = common.RightPadBytes([]byte("hello"), 64)
buff.Write(bytesOut) buff.Write(bytesOut)
err = abi.Unpack(&Bytes, "bytes", buff.Bytes()) err = abi.UnpackIntoInterface(&Bytes, "bytes", buff.Bytes())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -606,7 +604,7 @@ func TestUnmarshal(t *testing.T) {
bytesOut = common.RightPadBytes([]byte("hello"), 64) bytesOut = common.RightPadBytes([]byte("hello"), 64)
buff.Write(bytesOut) buff.Write(bytesOut)
err = abi.Unpack(&Bytes, "bytes", buff.Bytes()) err = abi.UnpackIntoInterface(&Bytes, "bytes", buff.Bytes())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -616,7 +614,7 @@ func TestUnmarshal(t *testing.T) {
} }
// marshal dynamic bytes output empty // marshal dynamic bytes output empty
err = abi.Unpack(&Bytes, "bytes", nil) err = abi.UnpackIntoInterface(&Bytes, "bytes", nil)
if err == nil { if err == nil {
t.Error("expected error") t.Error("expected error")
} }
@ -627,7 +625,7 @@ func TestUnmarshal(t *testing.T) {
buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000005")) buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000005"))
buff.Write(common.RightPadBytes([]byte("hello"), 32)) buff.Write(common.RightPadBytes([]byte("hello"), 32))
err = abi.Unpack(&Bytes, "bytes", buff.Bytes()) err = abi.UnpackIntoInterface(&Bytes, "bytes", buff.Bytes())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -641,7 +639,7 @@ func TestUnmarshal(t *testing.T) {
buff.Write(common.RightPadBytes([]byte("hello"), 32)) buff.Write(common.RightPadBytes([]byte("hello"), 32))
var hash common.Hash var hash common.Hash
err = abi.Unpack(&hash, "fixed", buff.Bytes()) err = abi.UnpackIntoInterface(&hash, "fixed", buff.Bytes())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -654,12 +652,12 @@ func TestUnmarshal(t *testing.T) {
// marshal error // marshal error
buff.Reset() buff.Reset()
buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")) buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020"))
err = abi.Unpack(&Bytes, "bytes", buff.Bytes()) err = abi.UnpackIntoInterface(&Bytes, "bytes", buff.Bytes())
if err == nil { if err == nil {
t.Error("expected error") t.Error("expected error")
} }
err = abi.Unpack(&Bytes, "multi", make([]byte, 64)) err = abi.UnpackIntoInterface(&Bytes, "multi", make([]byte, 64))
if err == nil { if err == nil {
t.Error("expected error") t.Error("expected error")
} }
@ -670,7 +668,7 @@ func TestUnmarshal(t *testing.T) {
buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000003")) buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000003"))
// marshal int array // marshal int array
var intArray [3]*big.Int var intArray [3]*big.Int
err = abi.Unpack(&intArray, "intArraySingle", buff.Bytes()) err = abi.UnpackIntoInterface(&intArray, "intArraySingle", buff.Bytes())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -691,7 +689,7 @@ func TestUnmarshal(t *testing.T) {
buff.Write(common.Hex2Bytes("0000000000000000000000000100000000000000000000000000000000000000")) buff.Write(common.Hex2Bytes("0000000000000000000000000100000000000000000000000000000000000000"))
var outAddr []common.Address var outAddr []common.Address
err = abi.Unpack(&outAddr, "addressSliceSingle", buff.Bytes()) err = abi.UnpackIntoInterface(&outAddr, "addressSliceSingle", buff.Bytes())
if err != nil { if err != nil {
t.Fatal("didn't expect error:", err) t.Fatal("didn't expect error:", err)
} }
@ -718,7 +716,7 @@ func TestUnmarshal(t *testing.T) {
A []common.Address A []common.Address
B []common.Address B []common.Address
} }
err = abi.Unpack(&outAddrStruct, "addressSliceDouble", buff.Bytes()) err = abi.UnpackIntoInterface(&outAddrStruct, "addressSliceDouble", buff.Bytes())
if err != nil { if err != nil {
t.Fatal("didn't expect error:", err) t.Fatal("didn't expect error:", err)
} }
@ -746,7 +744,7 @@ func TestUnmarshal(t *testing.T) {
buff.Reset() buff.Reset()
buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000100")) buff.Write(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000100"))
err = abi.Unpack(&outAddr, "addressSliceSingle", buff.Bytes()) err = abi.UnpackIntoInterface(&outAddr, "addressSliceSingle", buff.Bytes())
if err == nil { if err == nil {
t.Fatal("expected error:", err) t.Fatal("expected error:", err)
} }
@ -769,7 +767,7 @@ func TestUnpackTuple(t *testing.T) {
B *big.Int B *big.Int
}{new(big.Int), new(big.Int)} }{new(big.Int), new(big.Int)}
err = abi.Unpack(&v, "tuple", buff.Bytes()) err = abi.UnpackIntoInterface(&v, "tuple", buff.Bytes())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} else { } else {
@ -841,7 +839,7 @@ func TestUnpackTuple(t *testing.T) {
A: big.NewInt(1), A: big.NewInt(1),
} }
err = abi.Unpack(&ret, "tuple", buff.Bytes()) err = abi.UnpackIntoInterface(&ret, "tuple", buff.Bytes())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View file

@ -21,10 +21,10 @@ import (
"fmt" "fmt"
"math/big" "math/big"
ethereum "github.com/maticnetwork/bor" ethereum "github.com/ethereum/go-ethereum"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/maticnetwork/bor/event" "github.com/ethereum/go-ethereum/event"
"golang.org/x/crypto/sha3" "golang.org/x/crypto/sha3"
) )
@ -89,7 +89,7 @@ type Wallet interface {
// to discover non zero accounts and automatically add them to list of tracked // to discover non zero accounts and automatically add them to list of tracked
// accounts. // accounts.
// //
// Note, self derivaton will increment the last component of the specified path // Note, self derivation will increment the last component of the specified path
// opposed to decending into a child path to allow discovering accounts starting // opposed to decending into a child path to allow discovering accounts starting
// from non zero components. // from non zero components.
// //

View file

@ -20,7 +20,7 @@ import (
"bytes" "bytes"
"testing" "testing"
"github.com/maticnetwork/bor/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
) )
func TestTextHash(t *testing.T) { func TestTextHash(t *testing.T) {

View file

@ -21,15 +21,15 @@ import (
"math/big" "math/big"
"sync" "sync"
ethereum "github.com/maticnetwork/bor" "github.com/ethereum/go-ethereum"
"github.com/maticnetwork/bor/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/maticnetwork/bor/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/maticnetwork/bor/event" "github.com/ethereum/go-ethereum/event"
"github.com/maticnetwork/bor/log" "github.com/ethereum/go-ethereum/log"
"github.com/maticnetwork/bor/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/maticnetwork/bor/signer/core" "github.com/ethereum/go-ethereum/signer/core"
) )
type ExternalBackend struct { type ExternalBackend struct {

View file

@ -28,9 +28,9 @@ import (
"time" "time"
mapset "github.com/deckarep/golang-set" mapset "github.com/deckarep/golang-set"
"github.com/maticnetwork/bor/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/log" "github.com/ethereum/go-ethereum/log"
) )
// Minimum amount of time between cache reloads. This limit applies if the platform does // Minimum amount of time between cache reloads. This limit applies if the platform does

View file

@ -29,8 +29,8 @@ import (
"github.com/cespare/cp" "github.com/cespare/cp"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/maticnetwork/bor/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
) )
var ( var (

View file

@ -25,14 +25,14 @@ import (
"time" "time"
mapset "github.com/deckarep/golang-set" mapset "github.com/deckarep/golang-set"
"github.com/maticnetwork/bor/log" "github.com/ethereum/go-ethereum/log"
) )
// fileCache is a cache of files seen during scan of keystore. // fileCache is a cache of files seen during scan of keystore.
type fileCache struct { type fileCache struct {
all mapset.Set // Set of all files from the keystore folder all mapset.Set // Set of all files from the keystore folder
lastMod time.Time // Last time instance when a file was modified lastMod time.Time // Last time instance when a file was modified
mu sync.RWMutex mu sync.Mutex
} }
// scan performs a new scan on the given directory, compares against the already // scan performs a new scan on the given directory, compares against the already

View file

@ -29,9 +29,9 @@ import (
"strings" "strings"
"time" "time"
"github.com/maticnetwork/bor/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/pborman/uuid" "github.com/pborman/uuid"
) )

View file

@ -32,11 +32,11 @@ import (
"sync" "sync"
"time" "time"
"github.com/maticnetwork/bor/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/maticnetwork/bor/event" "github.com/ethereum/go-ethereum/event"
) )
var ( var (

View file

@ -28,10 +28,10 @@ import (
"testing" "testing"
"time" "time"
"github.com/maticnetwork/bor/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/maticnetwork/bor/event" "github.com/ethereum/go-ethereum/event"
) )
var testSigData = make([]byte, 32) var testSigData = make([]byte, 32)
@ -336,7 +336,9 @@ func TestWalletNotifications(t *testing.T) {
// Shut down the event collector and check events. // Shut down the event collector and check events.
sub.Unsubscribe() sub.Unsubscribe()
<-updates for ev := range updates {
events = append(events, walletEvent{ev, ev.Wallet.Accounts()[0]})
}
checkAccounts(t, live, ks.Wallets()) checkAccounts(t, live, ks.Wallets())
checkEvents(t, wantEvents, events) checkEvents(t, wantEvents, events)
} }

View file

@ -38,10 +38,10 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/maticnetwork/bor/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/common/math" "github.com/ethereum/go-ethereum/common/math"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/pborman/uuid" "github.com/pborman/uuid"
"golang.org/x/crypto/pbkdf2" "golang.org/x/crypto/pbkdf2"
"golang.org/x/crypto/scrypt" "golang.org/x/crypto/scrypt"

View file

@ -20,7 +20,7 @@ import (
"io/ioutil" "io/ioutil"
"testing" "testing"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
) )
const ( const (

View file

@ -22,7 +22,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
) )
type keyStorePlain struct { type keyStorePlain struct {

View file

@ -27,8 +27,8 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
func tmpKeyStoreIface(t *testing.T, encrypted bool) (dir string, ks keyStore) { func tmpKeyStoreIface(t *testing.T, encrypted bool) (dir string, ks keyStore) {

View file

@ -25,8 +25,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/maticnetwork/bor/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/pborman/uuid" "github.com/pborman/uuid"
"golang.org/x/crypto/pbkdf2" "golang.org/x/crypto/pbkdf2"
) )

View file

@ -19,10 +19,10 @@ package keystore
import ( import (
"math/big" "math/big"
ethereum "github.com/maticnetwork/bor" ethereum "github.com/ethereum/go-ethereum"
"github.com/maticnetwork/bor/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/maticnetwork/bor/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
// keystoreWallet implements the accounts.Wallet interface for the original // keystoreWallet implements the accounts.Wallet interface for the original

View file

@ -21,7 +21,7 @@ package keystore
import ( import (
"time" "time"
"github.com/maticnetwork/bor/log" "github.com/ethereum/go-ethereum/log"
"github.com/rjeczalik/notify" "github.com/rjeczalik/notify"
) )

View file

@ -21,8 +21,8 @@ import (
"sort" "sort"
"sync" "sync"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/event" "github.com/ethereum/go-ethereum/event"
) )
// Config contains the settings of the global account manager. // Config contains the settings of the global account manager.

View file

@ -41,11 +41,11 @@ import (
"sync" "sync"
"time" "time"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
pcsc "github.com/gballet/go-libpcsclite" pcsc "github.com/gballet/go-libpcsclite"
"github.com/maticnetwork/bor/accounts"
"github.com/maticnetwork/bor/common"
"github.com/maticnetwork/bor/event"
"github.com/maticnetwork/bor/log"
) )
// Scheme is the URI prefix for smartcard wallets. // Scheme is the URI prefix for smartcard wallets.

View file

@ -25,8 +25,8 @@ import (
"crypto/sha512" "crypto/sha512"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/crypto"
pcsc "github.com/gballet/go-libpcsclite" pcsc "github.com/gballet/go-libpcsclite"
"github.com/maticnetwork/bor/crypto"
"github.com/wsddn/go-ecdh" "github.com/wsddn/go-ecdh"
"golang.org/x/crypto/pbkdf2" "golang.org/x/crypto/pbkdf2"
"golang.org/x/text/unicode/norm" "golang.org/x/text/unicode/norm"

View file

@ -33,13 +33,13 @@ import (
"sync" "sync"
"time" "time"
ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
pcsc "github.com/gballet/go-libpcsclite" pcsc "github.com/gballet/go-libpcsclite"
ethereum "github.com/maticnetwork/bor"
"github.com/maticnetwork/bor/accounts"
"github.com/maticnetwork/bor/common"
"github.com/maticnetwork/bor/core/types"
"github.com/maticnetwork/bor/crypto"
"github.com/maticnetwork/bor/log"
"github.com/status-im/keycard-go/derivationpath" "github.com/status-im/keycard-go/derivationpath"
) )
@ -637,7 +637,7 @@ func (w *Wallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Accoun
// to discover non zero accounts and automatically add them to list of tracked // to discover non zero accounts and automatically add them to list of tracked
// accounts. // accounts.
// //
// Note, self derivaton will increment the last component of the specified path // Note, self derivation will increment the last component of the specified path
// opposed to decending into a child path to allow discovering accounts starting // opposed to decending into a child path to allow discovering accounts starting
// from non zero components. // from non zero components.
// //

View file

@ -23,10 +23,10 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/karalabe/usb" "github.com/karalabe/usb"
"github.com/maticnetwork/bor/accounts"
"github.com/maticnetwork/bor/event"
"github.com/maticnetwork/bor/log"
) )
// LedgerScheme is the protocol scheme prefixing account and wallet URLs. // LedgerScheme is the protocol scheme prefixing account and wallet URLs.

View file

@ -28,13 +28,13 @@ import (
"io" "io"
"math/big" "math/big"
"github.com/maticnetwork/bor/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/maticnetwork/bor/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/maticnetwork/bor/log" "github.com/ethereum/go-ethereum/log"
"github.com/maticnetwork/bor/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
// ledgerOpcode is an enumeration encoding the supported Ledger opcodes. // ledgerOpcode is an enumeration encoding the supported Ledger opcodes.
@ -162,7 +162,7 @@ func (w *ledgerDriver) SignTx(path accounts.DerivationPath, tx *types.Transactio
return common.Address{}, nil, accounts.ErrWalletClosed return common.Address{}, nil, accounts.ErrWalletClosed
} }
// Ensure the wallet is capable of signing the given transaction // Ensure the wallet is capable of signing the given transaction
if chainID != nil && w.version[0] <= 1 && w.version[2] <= 2 { if chainID != nil && w.version[0] <= 1 && w.version[1] <= 0 && w.version[2] <= 2 {
//lint:ignore ST1005 brand name displayed on the console //lint:ignore ST1005 brand name displayed on the console
return common.Address{}, nil, fmt.Errorf("Ledger v%d.%d.%d doesn't support signing this transaction, please update to v1.0.3 at least", w.version[0], w.version[1], w.version[2]) return common.Address{}, nil, fmt.Errorf("Ledger v%d.%d.%d doesn't support signing this transaction, please update to v1.0.3 at least", w.version[0], w.version[1], w.version[2])
} }

View file

@ -27,13 +27,13 @@ import (
"io" "io"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/usbwallet/trezor"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/maticnetwork/bor/accounts"
"github.com/maticnetwork/bor/accounts/usbwallet/trezor"
"github.com/maticnetwork/bor/common"
"github.com/maticnetwork/bor/common/hexutil"
"github.com/maticnetwork/bor/core/types"
"github.com/maticnetwork/bor/log"
) )
// ErrTrezorPINNeeded is returned if opening the trezor requires a PIN code. In // ErrTrezorPINNeeded is returned if opening the trezor requires a PIN code. In

View file

@ -25,13 +25,13 @@ import (
"sync" "sync"
"time" "time"
ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/karalabe/usb" "github.com/karalabe/usb"
ethereum "github.com/maticnetwork/bor"
"github.com/maticnetwork/bor/accounts"
"github.com/maticnetwork/bor/common"
"github.com/maticnetwork/bor/core/types"
"github.com/maticnetwork/bor/crypto"
"github.com/maticnetwork/bor/log"
) )
// Maximum time between wallet health checks to detect USB unplugs. // Maximum time between wallet health checks to detect USB unplugs.
@ -368,18 +368,22 @@ func (w *wallet) selfDerive() {
w.log.Warn("USB wallet nonce retrieval failed", "err", err) w.log.Warn("USB wallet nonce retrieval failed", "err", err)
break break
} }
// If the next account is empty, stop self-derivation, but add for the last base path // We've just self-derived a new account, start tracking it locally
// unless the account was empty.
path := make(accounts.DerivationPath, len(nextPaths[i]))
copy(path[:], nextPaths[i][:])
if balance.Sign() == 0 && nonce == 0 { if balance.Sign() == 0 && nonce == 0 {
empty = true empty = true
// If it indeed was empty, make a log output for it anyway. In the case
// of legacy-ledger, the first account on the legacy-path will
// be shown to the user, even if we don't actively track it
if i < len(nextAddrs)-1 { if i < len(nextAddrs)-1 {
w.log.Info("Skipping trakcking first account on legacy path, use personal.deriveAccount(<url>,<path>, false) to track",
"path", path, "address", nextAddrs[i])
break break
} }
} }
// We've just self-derived a new account, start tracking it locally
path := make(accounts.DerivationPath, len(nextPaths[i]))
copy(path[:], nextPaths[i][:])
paths = append(paths, path) paths = append(paths, path)
account := accounts.Account{ account := accounts.Account{
Address: nextAddrs[i], Address: nextAddrs[i],
URL: accounts.URL{Scheme: w.url.Scheme, Path: fmt.Sprintf("%s/%s", w.url.Path, path)}, URL: accounts.URL{Scheme: w.url.Scheme, Path: fmt.Sprintf("%s/%s", w.url.Path, path)},
@ -489,7 +493,7 @@ func (w *wallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Accoun
// to discover non zero accounts and automatically add them to list of tracked // to discover non zero accounts and automatically add them to list of tracked
// accounts. // accounts.
// //
// Note, self derivaton will increment the last component of the specified path // Note, self derivation will increment the last component of the specified path
// opposed to decending into a child path to allow discovering accounts starting // opposed to decending into a child path to allow discovering accounts starting
// from non zero components. // from non zero components.
// //

View file

@ -24,13 +24,13 @@ environment:
install: install:
- git submodule update --init - git submodule update --init
- rmdir C:\go /s /q - rmdir C:\go /s /q
- appveyor DownloadFile https://dl.google.com/go/go1.14.2.windows-%GETH_ARCH%.zip - appveyor DownloadFile https://dl.google.com/go/go1.15.5.windows-%GETH_ARCH%.zip
- 7z x go1.14.2.windows-%GETH_ARCH%.zip -y -oC:\ > NUL - 7z x go1.15.5.windows-%GETH_ARCH%.zip -y -oC:\ > NUL
- go version - go version
- gcc --version - gcc --version
build_script: build_script:
- go run build\ci.go install - go run build\ci.go install -dlgo
after_build: after_build:
- go run build\ci.go archive -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds - go run build\ci.go archive -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds

View file

@ -1,6 +1,13 @@
# This file contains sha256 checksums of optional build dependencies. # This file contains sha256 checksums of optional build dependencies.
98de84e69726a66da7b4e58eac41b99cbe274d7e8906eeb8a5b7eb0aadee7f7c go1.14.2.src.tar.gz c1076b90cf94b73ebed62a81d802cd84d43d02dea8c07abdc922c57a071c84f1 go1.15.5.src.tar.gz
359a4334b8c8f5e3067e5a76f16419791ac3fef4613d8e8e1eac0b9719915f6d go1.15.5.darwin-amd64.tar.gz
4c8179d406136979724c71732009c7e2e7c794dbeaaa2a043c00da34d4be0559 go1.15.5.linux-386.tar.gz
9a58494e8da722c3aef248c9227b0e9c528c7318309827780f16220998180a0d go1.15.5.linux-amd64.tar.gz
a72a0b036beb4193a0214bca3fca4c5d68a38a4ccf098c909f7ce8bf08567c48 go1.15.5.linux-arm64.tar.gz
5ea6456620d3efed5dda99238c7f23866eafdd915e5348736e631bc283c0238a go1.15.5.linux-armv6l.tar.gz
d812436c7e3482ba3c97172edf26afaf35aca60a5621ff4a5f6a08386505ab9c go1.15.5.windows-386.zip
1d24be3a200201a74be25e4134fbec467750e834e84e9c7789a9fc13248c5507 go1.15.5.windows-amd64.zip
d998a84eea42f2271aca792a7b027ca5c1edfcba229e8e5a844c9ac3f336df35 golangci-lint-1.27.0-linux-armv7.tar.gz d998a84eea42f2271aca792a7b027ca5c1edfcba229e8e5a844c9ac3f336df35 golangci-lint-1.27.0-linux-armv7.tar.gz
bf781f05b0d393b4bf0a327d9e62926949a4f14d7774d950c4e009fc766ed1d4 golangci-lint.exe-1.27.0-windows-amd64.zip bf781f05b0d393b4bf0a327d9e62926949a4f14d7774d950c4e009fc766ed1d4 golangci-lint.exe-1.27.0-windows-amd64.zip

View file

@ -46,12 +46,11 @@ import (
"encoding/base64" "encoding/base64"
"flag" "flag"
"fmt" "fmt"
"go/parser"
"go/token"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
"os/exec" "os/exec"
"path"
"path/filepath" "path/filepath"
"regexp" "regexp"
"runtime" "runtime"
@ -59,8 +58,8 @@ import (
"time" "time"
"github.com/cespare/cp" "github.com/cespare/cp"
"github.com/maticnetwork/bor/internal/build" "github.com/ethereum/go-ethereum/internal/build"
"github.com/maticnetwork/bor/params" "github.com/ethereum/go-ethereum/params"
) )
var ( var (
@ -79,7 +78,6 @@ var (
executablePath("geth"), executablePath("geth"),
executablePath("puppeth"), executablePath("puppeth"),
executablePath("rlpdump"), executablePath("rlpdump"),
executablePath("wnode"),
executablePath("clef"), executablePath("clef"),
} }
@ -109,10 +107,6 @@ var (
BinaryName: "rlpdump", BinaryName: "rlpdump",
Description: "Developer utility tool that prints RLP structures.", Description: "Developer utility tool that prints RLP structures.",
}, },
{
BinaryName: "wnode",
Description: "Ethereum Whisper diagnostic tool",
},
{ {
BinaryName: "clef", BinaryName: "clef",
Description: "Ethereum account management tool.", Description: "Ethereum account management tool.",
@ -139,19 +133,25 @@ var (
// Note: zesty is unsupported because it was officially deprecated on Launchpad. // Note: zesty is unsupported because it was officially deprecated on Launchpad.
// Note: artful is unsupported because it was officially deprecated on Launchpad. // Note: artful is unsupported because it was officially deprecated on Launchpad.
// Note: cosmic is unsupported because it was officially deprecated on Launchpad. // Note: cosmic is unsupported because it was officially deprecated on Launchpad.
// Note: disco is unsupported because it was officially deprecated on Launchpad.
// Note: eoan is unsupported because it was officially deprecated on Launchpad.
debDistroGoBoots = map[string]string{ debDistroGoBoots = map[string]string{
"trusty": "golang-1.11", "trusty": "golang-1.11",
"xenial": "golang-go", "xenial": "golang-go",
"bionic": "golang-go", "bionic": "golang-go",
"disco": "golang-go",
"eoan": "golang-go",
"focal": "golang-go", "focal": "golang-go",
"groovy": "golang-go",
} }
debGoBootPaths = map[string]string{ debGoBootPaths = map[string]string{
"golang-1.11": "/usr/lib/go-1.11", "golang-1.11": "/usr/lib/go-1.11",
"golang-go": "/usr/lib/go", "golang-go": "/usr/lib/go",
} }
// This is the version of go that will be downloaded by
//
// go run ci.go install -dlgo
dlgoVersion = "1.15.5"
) )
var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin")) var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin"))
@ -202,108 +202,130 @@ func main() {
func doInstall(cmdline []string) { func doInstall(cmdline []string) {
var ( var (
dlgo = flag.Bool("dlgo", false, "Download Go and build with it")
arch = flag.String("arch", "", "Architecture to cross build for") arch = flag.String("arch", "", "Architecture to cross build for")
cc = flag.String("cc", "", "C compiler to cross build with") cc = flag.String("cc", "", "C compiler to cross build with")
) )
flag.CommandLine.Parse(cmdline) flag.CommandLine.Parse(cmdline)
env := build.Env() env := build.Env()
// Check Go version. People regularly open issues about compilation // Check local Go version. People regularly open issues about compilation
// failure with outdated Go. This should save them the trouble. // failure with outdated Go. This should save them the trouble.
if !strings.Contains(runtime.Version(), "devel") { if !strings.Contains(runtime.Version(), "devel") {
// Figure out the minor version number since we can't textually compare (1.10 < 1.9) // Figure out the minor version number since we can't textually compare (1.10 < 1.9)
var minor int var minor int
fmt.Sscanf(strings.TrimPrefix(runtime.Version(), "go1."), "%d", &minor) fmt.Sscanf(strings.TrimPrefix(runtime.Version(), "go1."), "%d", &minor)
if minor < 13 {
if minor < 11 {
log.Println("You have Go version", runtime.Version()) log.Println("You have Go version", runtime.Version())
log.Println("go-ethereum requires at least Go version 1.11 and cannot") log.Println("go-ethereum requires at least Go version 1.13 and cannot")
log.Println("be compiled with an earlier version. Please upgrade your Go installation.") log.Println("be compiled with an earlier version. Please upgrade your Go installation.")
os.Exit(1) os.Exit(1)
} }
} }
// Compile packages given as arguments, or everything if there are no arguments.
packages := []string{"./..."} // Choose which go command we're going to use.
if flag.NArg() > 0 { var gobuild *exec.Cmd
packages = flag.Args() if !*dlgo {
// Default behavior: use the go version which runs ci.go right now.
gobuild = goTool("build")
} else {
// Download of Go requested. This is for build environments where the
// installed version is too old and cannot be upgraded easily.
cachedir := filepath.Join("build", "cache")
goroot := downloadGo(runtime.GOARCH, runtime.GOOS, cachedir)
gobuild = localGoTool(goroot, "build")
} }
if *arch == "" || *arch == runtime.GOARCH { // Configure environment for cross build.
goinstall := goTool("install", buildFlags(env)...) if *arch != "" || *arch != runtime.GOARCH {
if runtime.GOARCH == "arm64" { gobuild.Env = append(gobuild.Env, "CGO_ENABLED=1")
goinstall.Args = append(goinstall.Args, "-p", "1") gobuild.Env = append(gobuild.Env, "GOARCH="+*arch)
}
goinstall.Args = append(goinstall.Args, "-v")
goinstall.Args = append(goinstall.Args, packages...)
build.MustRun(goinstall)
return
} }
// Seems we are cross compiling, work around forbidden GOBIN // Configure C compiler.
goinstall := goToolArch(*arch, *cc, "install", buildFlags(env)...) if *cc != "" {
goinstall.Args = append(goinstall.Args, "-v") gobuild.Env = append(gobuild.Env, "CC="+*cc)
goinstall.Args = append(goinstall.Args, []string{"-buildmode", "archive"}...) } else if os.Getenv("CC") != "" {
goinstall.Args = append(goinstall.Args, packages...) gobuild.Env = append(gobuild.Env, "CC="+os.Getenv("CC"))
build.MustRun(goinstall) }
if cmds, err := ioutil.ReadDir("cmd"); err == nil { // arm64 CI builders are memory-constrained and can't handle concurrent builds,
for _, cmd := range cmds { // better disable it. This check isn't the best, it should probably
pkgs, err := parser.ParseDir(token.NewFileSet(), filepath.Join(".", "cmd", cmd.Name()), nil, parser.PackageClauseOnly) // check for something in env instead.
if err != nil { if runtime.GOARCH == "arm64" {
log.Fatal(err) gobuild.Args = append(gobuild.Args, "-p", "1")
} }
for name := range pkgs {
if name == "main" { // Put the default settings in.
gobuild := goToolArch(*arch, *cc, "build", buildFlags(env)...) gobuild.Args = append(gobuild.Args, buildFlags(env)...)
gobuild.Args = append(gobuild.Args, "-v")
gobuild.Args = append(gobuild.Args, []string{"-o", executablePath(cmd.Name())}...) // We use -trimpath to avoid leaking local paths into the built executables.
gobuild.Args = append(gobuild.Args, "."+string(filepath.Separator)+filepath.Join("cmd", cmd.Name())) gobuild.Args = append(gobuild.Args, "-trimpath")
build.MustRun(gobuild)
break // Show packages during build.
} gobuild.Args = append(gobuild.Args, "-v")
}
} // Now we choose what we're even building.
// Default: collect all 'main' packages in cmd/ and build those.
packages := flag.Args()
if len(packages) == 0 {
packages = build.FindMainPackages("./cmd")
}
// Do the build!
for _, pkg := range packages {
args := make([]string, len(gobuild.Args))
copy(args, gobuild.Args)
args = append(args, "-o", executablePath(path.Base(pkg)))
args = append(args, pkg)
build.MustRun(&exec.Cmd{Path: gobuild.Path, Args: args, Env: gobuild.Env})
} }
} }
// buildFlags returns the go tool flags for building.
func buildFlags(env build.Environment) (flags []string) { func buildFlags(env build.Environment) (flags []string) {
var ld []string var ld []string
if env.Commit != "" { if env.Commit != "" {
ld = append(ld, "-X", "main.gitCommit="+env.Commit) ld = append(ld, "-X", "main.gitCommit="+env.Commit)
ld = append(ld, "-X", "main.gitDate="+env.Date) ld = append(ld, "-X", "main.gitDate="+env.Date)
} }
// Strip DWARF on darwin. This used to be required for certain things,
// and there is no downside to this, so we just keep doing it.
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
ld = append(ld, "-s") ld = append(ld, "-s")
} }
if len(ld) > 0 { if len(ld) > 0 {
flags = append(flags, "-ldflags", strings.Join(ld, " ")) flags = append(flags, "-ldflags", strings.Join(ld, " "))
} }
return flags return flags
} }
// goTool returns the go tool. This uses the Go version which runs ci.go.
func goTool(subcmd string, args ...string) *exec.Cmd { func goTool(subcmd string, args ...string) *exec.Cmd {
return goToolArch(runtime.GOARCH, os.Getenv("CC"), subcmd, args...) cmd := build.GoTool(subcmd, args...)
goToolSetEnv(cmd)
return cmd
} }
func goToolArch(arch string, cc string, subcmd string, args ...string) *exec.Cmd { // localGoTool returns the go tool from the given GOROOT.
cmd := build.GoTool(subcmd, args...) func localGoTool(goroot string, subcmd string, args ...string) *exec.Cmd {
if arch == "" || arch == runtime.GOARCH { gotool := filepath.Join(goroot, "bin", "go")
cmd.Env = append(cmd.Env, "GOBIN="+GOBIN) cmd := exec.Command(gotool, subcmd)
} else { goToolSetEnv(cmd)
cmd.Env = append(cmd.Env, "CGO_ENABLED=1") cmd.Env = append(cmd.Env, "GOROOT="+goroot)
cmd.Env = append(cmd.Env, "GOARCH="+arch) cmd.Args = append(cmd.Args, args...)
} return cmd
if cc != "" { }
cmd.Env = append(cmd.Env, "CC="+cc)
} // goToolSetEnv forwards the build environment to the go tool.
func goToolSetEnv(cmd *exec.Cmd) {
cmd.Env = append(cmd.Env, "GOBIN="+GOBIN)
for _, e := range os.Environ() { for _, e := range os.Environ() {
if strings.HasPrefix(e, "GOBIN=") { if strings.HasPrefix(e, "GOBIN=") || strings.HasPrefix(e, "CC=") {
continue continue
} }
cmd.Env = append(cmd.Env, e) cmd.Env = append(cmd.Env, e)
} }
return cmd
} }
// Running The Tests // Running The Tests
@ -365,7 +387,7 @@ func downloadLinter(cachedir string) string {
if err := csdb.DownloadFile(url, archivePath); err != nil { if err := csdb.DownloadFile(url, archivePath); err != nil {
log.Fatal(err) log.Fatal(err)
} }
if err := build.ExtractTarballArchive(archivePath, cachedir); err != nil { if err := build.ExtractArchive(archivePath, cachedir); err != nil {
log.Fatal(err) log.Fatal(err)
} }
return filepath.Join(cachedir, base, "golangci-lint") return filepath.Join(cachedir, base, "golangci-lint")
@ -471,13 +493,12 @@ func maybeSkipArchive(env build.Environment) {
// Debian Packaging // Debian Packaging
func doDebianSource(cmdline []string) { func doDebianSource(cmdline []string) {
var ( var (
goversion = flag.String("goversion", "", `Go version to build with (will be included in the source package)`) cachedir = flag.String("cachedir", "./build/cache", `Filesystem path to cache the downloaded Go bundles at`)
cachedir = flag.String("cachedir", "./build/cache", `Filesystem path to cache the downloaded Go bundles at`) signer = flag.String("signer", "", `Signing key name, also used as package author`)
signer = flag.String("signer", "", `Signing key name, also used as package author`) upload = flag.String("upload", "", `Where to upload the source package (usually "ethereum/ethereum")`)
upload = flag.String("upload", "", `Where to upload the source package (usually "ethereum/ethereum")`) sshUser = flag.String("sftp-user", "", `Username for SFTP upload (usually "geth-ci")`)
sshUser = flag.String("sftp-user", "", `Username for SFTP upload (usually "geth-ci")`) workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`)
workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`) now = time.Now()
now = time.Now()
) )
flag.CommandLine.Parse(cmdline) flag.CommandLine.Parse(cmdline)
*workdir = makeWorkdir(*workdir) *workdir = makeWorkdir(*workdir)
@ -492,10 +513,10 @@ func doDebianSource(cmdline []string) {
} }
// Download and verify the Go source package. // Download and verify the Go source package.
gobundle := downloadGoSources(*goversion, *cachedir) gobundle := downloadGoSources(*cachedir)
// Download all the dependencies needed to build the sources and run the ci script // Download all the dependencies needed to build the sources and run the ci script
srcdepfetch := goTool("install", "-n", "./...") srcdepfetch := goTool("mod", "download")
srcdepfetch.Env = append(os.Environ(), "GOPATH="+filepath.Join(*workdir, "modgopath")) srcdepfetch.Env = append(os.Environ(), "GOPATH="+filepath.Join(*workdir, "modgopath"))
build.MustRun(srcdepfetch) build.MustRun(srcdepfetch)
@ -511,7 +532,7 @@ func doDebianSource(cmdline []string) {
pkgdir := stageDebianSource(*workdir, meta) pkgdir := stageDebianSource(*workdir, meta)
// Add Go source code // Add Go source code
if err := build.ExtractTarballArchive(gobundle, pkgdir); err != nil { if err := build.ExtractArchive(gobundle, pkgdir); err != nil {
log.Fatalf("Failed to extract Go sources: %v", err) log.Fatalf("Failed to extract Go sources: %v", err)
} }
if err := os.Rename(filepath.Join(pkgdir, "go"), filepath.Join(pkgdir, ".go")); err != nil { if err := os.Rename(filepath.Join(pkgdir, "go"), filepath.Join(pkgdir, ".go")); err != nil {
@ -543,9 +564,10 @@ func doDebianSource(cmdline []string) {
} }
} }
func downloadGoSources(version string, cachedir string) string { // downloadGoSources downloads the Go source tarball.
func downloadGoSources(cachedir string) string {
csdb := build.MustLoadChecksums("build/checksums.txt") csdb := build.MustLoadChecksums("build/checksums.txt")
file := fmt.Sprintf("go%s.src.tar.gz", version) file := fmt.Sprintf("go%s.src.tar.gz", dlgoVersion)
url := "https://dl.google.com/go/" + file url := "https://dl.google.com/go/" + file
dst := filepath.Join(cachedir, file) dst := filepath.Join(cachedir, file)
if err := csdb.DownloadFile(url, dst); err != nil { if err := csdb.DownloadFile(url, dst); err != nil {
@ -554,6 +576,41 @@ func downloadGoSources(version string, cachedir string) string {
return dst return dst
} }
// downloadGo downloads the Go binary distribution and unpacks it into a temporary
// directory. It returns the GOROOT of the unpacked toolchain.
func downloadGo(goarch, goos, cachedir string) string {
if goarch == "arm" {
goarch = "armv6l"
}
csdb := build.MustLoadChecksums("build/checksums.txt")
file := fmt.Sprintf("go%s.%s-%s", dlgoVersion, goos, goarch)
if goos == "windows" {
file += ".zip"
} else {
file += ".tar.gz"
}
url := "https://golang.org/dl/" + file
dst := filepath.Join(cachedir, file)
if err := csdb.DownloadFile(url, dst); err != nil {
log.Fatal(err)
}
ucache, err := os.UserCacheDir()
if err != nil {
log.Fatal(err)
}
godir := filepath.Join(ucache, fmt.Sprintf("geth-go-%s-%s-%s", dlgoVersion, goos, goarch))
if err := build.ExtractArchive(dst, godir); err != nil {
log.Fatal(err)
}
goroot, err := filepath.Abs(filepath.Join(godir, "go"))
if err != nil {
log.Fatal(err)
}
return goroot
}
func ppaUpload(workdir, ppa, sshUser string, files []string) { func ppaUpload(workdir, ppa, sshUser string, files []string) {
p := strings.Split(ppa, "/") p := strings.Split(ppa, "/")
if len(p) != 2 { if len(p) != 2 {
@ -833,11 +890,12 @@ func doAndroidArchive(cmdline []string) {
} }
// Build the Android archive and Maven resources // Build the Android archive and Maven resources
build.MustRun(goTool("get", "golang.org/x/mobile/cmd/gomobile", "golang.org/x/mobile/cmd/gobind")) build.MustRun(goTool("get", "golang.org/x/mobile/cmd/gomobile", "golang.org/x/mobile/cmd/gobind"))
build.MustRun(gomobileTool("bind", "-ldflags", "-s -w", "--target", "android", "--javapkg", "org.ethereum", "-v", "github.com/maticnetwork/bor/mobile")) build.MustRun(gomobileTool("bind", "-ldflags", "-s -w", "--target", "android", "--javapkg", "org.ethereum", "-v", "github.com/ethereum/go-ethereum/mobile"))
if *local { if *local {
// If we're building locally, copy bundle to build dir and skip Maven // If we're building locally, copy bundle to build dir and skip Maven
os.Rename("geth.aar", filepath.Join(GOBIN, "geth.aar")) os.Rename("geth.aar", filepath.Join(GOBIN, "geth.aar"))
os.Rename("geth-sources.jar", filepath.Join(GOBIN, "geth-sources.jar"))
return return
} }
meta := newMavenMetadata(env) meta := newMavenMetadata(env)
@ -884,11 +942,12 @@ func gomobileTool(subcmd string, args ...string) *exec.Cmd {
"PATH=" + GOBIN + string(os.PathListSeparator) + os.Getenv("PATH"), "PATH=" + GOBIN + string(os.PathListSeparator) + os.Getenv("PATH"),
} }
for _, e := range os.Environ() { for _, e := range os.Environ() {
if strings.HasPrefix(e, "GOPATH=") || strings.HasPrefix(e, "PATH=") { if strings.HasPrefix(e, "GOPATH=") || strings.HasPrefix(e, "PATH=") || strings.HasPrefix(e, "GOBIN=") {
continue continue
} }
cmd.Env = append(cmd.Env, e) cmd.Env = append(cmd.Env, e)
} }
cmd.Env = append(cmd.Env, "GOBIN="+GOBIN)
return cmd return cmd
} }
@ -953,11 +1012,11 @@ func doXCodeFramework(cmdline []string) {
// Build the iOS XCode framework // Build the iOS XCode framework
build.MustRun(goTool("get", "golang.org/x/mobile/cmd/gomobile", "golang.org/x/mobile/cmd/gobind")) build.MustRun(goTool("get", "golang.org/x/mobile/cmd/gomobile", "golang.org/x/mobile/cmd/gobind"))
build.MustRun(gomobileTool("init")) build.MustRun(gomobileTool("init"))
bind := gomobileTool("bind", "-ldflags", "-s -w", "--target", "ios", "-v", "github.com/maticnetwork/bor/mobile") bind := gomobileTool("bind", "-ldflags", "-s -w", "--target", "ios", "-v", "github.com/ethereum/go-ethereum/mobile")
if *local { if *local {
// If we're building locally, use the build folder and stop afterwards // If we're building locally, use the build folder and stop afterwards
bind.Dir, _ = filepath.Abs(GOBIN) bind.Dir = GOBIN
build.MustRun(bind) build.MustRun(bind)
return return
} }
@ -980,7 +1039,7 @@ func doXCodeFramework(cmdline []string) {
if *deploy != "" { if *deploy != "" {
meta := newPodMetadata(env, archive) meta := newPodMetadata(env, archive)
build.Render("build/pod.podspec", "Geth.podspec", 0755, meta) build.Render("build/pod.podspec", "Geth.podspec", 0755, meta)
build.MustRunCommand("pod", *deploy, "push", "Geth.podspec", "--allow-warnings", "--verbose") build.MustRunCommand("pod", *deploy, "push", "Geth.podspec", "--allow-warnings")
} }
} }

View file

@ -5,8 +5,8 @@ Maintainer: {{.Author}}
Build-Depends: debhelper (>= 8.0.0), {{.GoBootPackage}} Build-Depends: debhelper (>= 8.0.0), {{.GoBootPackage}}
Standards-Version: 3.9.5 Standards-Version: 3.9.5
Homepage: https://ethereum.org Homepage: https://ethereum.org
Vcs-Git: git://github.com/maticnetwork/bor.git Vcs-Git: git://github.com/ethereum/go-ethereum.git
Vcs-Browser: https://github.com/maticnetwork/bor Vcs-Browser: https://github.com/ethereum/go-ethereum
Package: {{.Name}} Package: {{.Name}}
Architecture: any Architecture: any

View file

@ -11,7 +11,7 @@
<name>Android Ethereum Client</name> <name>Android Ethereum Client</name>
<description>Android port of the go-ethereum libraries and node</description> <description>Android port of the go-ethereum libraries and node</description>
<url>https://github.com/maticnetwork/bor</url> <url>https://github.com/ethereum/go-ethereum</url>
<inceptionYear>2015</inceptionYear> <inceptionYear>2015</inceptionYear>
<licenses> <licenses>
@ -48,10 +48,10 @@
<issueManagement> <issueManagement>
<system>GitHub Issues</system> <system>GitHub Issues</system>
<url>https://github.com/maticnetwork/bor/issues/</url> <url>https://github.com/ethereum/go-ethereum/issues/</url>
</issueManagement> </issueManagement>
<scm> <scm>
<url>https://github.com/maticnetwork/bor</url> <url>https://github.com/ethereum/go-ethereum</url>
</scm> </scm>
</project> </project>

View file

@ -3,9 +3,9 @@ InstallDir "$InstDir"
OutFile "${OUTPUTFILE}" # set through command line arguments OutFile "${OUTPUTFILE}" # set through command line arguments
# Links for "Add/Remove Programs" # Links for "Add/Remove Programs"
!define HELPURL "https://github.com/maticnetwork/bor/issues" !define HELPURL "https://github.com/ethereum/go-ethereum/issues"
!define UPDATEURL "https://github.com/maticnetwork/bor/releases" !define UPDATEURL "https://github.com/ethereum/go-ethereum/releases"
!define ABOUTURL "https://github.com/maticnetwork/bor#ethereum-go" !define ABOUTURL "https://github.com/ethereum/go-ethereum#ethereum-go"
!define /date NOW "%Y%m%d" !define /date NOW "%Y%m%d"
PageEx license PageEx license
@ -34,8 +34,8 @@ Section "Geth" GETH_IDX
SimpleFC::AdvAddRule "Geth UDP discovery (UDP:30303)" "" 17 2 1 2147483647 1 "$INSTDIR\geth.exe" "" "" "Ethereum" "" 30303 "" "" SimpleFC::AdvAddRule "Geth UDP discovery (UDP:30303)" "" 17 2 1 2147483647 1 "$INSTDIR\geth.exe" "" "" "Ethereum" "" 30303 "" ""
# Set default IPC endpoint (https://github.com/ethereum/EIPs/issues/147) # Set default IPC endpoint (https://github.com/ethereum/EIPs/issues/147)
${EnvVarUpdate} $0 "ETHEREUM_SOCKET" "R" "HKLM" "\\.\pipe\bor.ipc" ${EnvVarUpdate} $0 "ETHEREUM_SOCKET" "R" "HKLM" "\\.\pipe\geth.ipc"
${EnvVarUpdate} $0 "ETHEREUM_SOCKET" "A" "HKLM" "\\.\pipe\bor.ipc" ${EnvVarUpdate} $0 "ETHEREUM_SOCKET" "A" "HKLM" "\\.\pipe\geth.ipc"
# Add instdir to PATH # Add instdir to PATH
Push "$INSTDIR" Push "$INSTDIR"

View file

@ -22,7 +22,7 @@ Section "Uninstall"
SimpleFC::AdvRemoveRule "Geth UDP discovery (UDP:30303)" SimpleFC::AdvRemoveRule "Geth UDP discovery (UDP:30303)"
# Remove IPC endpoint (https://github.com/ethereum/EIPs/issues/147) # Remove IPC endpoint (https://github.com/ethereum/EIPs/issues/147)
${un.EnvVarUpdate} $0 "ETHEREUM_SOCKET" "R" "HKLM" "\\.\pipe\bor.ipc" ${un.EnvVarUpdate} $0 "ETHEREUM_SOCKET" "R" "HKLM" "\\.\pipe\geth.ipc"
# Remove install directory from PATH # Remove install directory from PATH
Push "$INSTDIR" Push "$INSTDIR"

View file

@ -2,12 +2,12 @@ Pod::Spec.new do |spec|
spec.name = 'Geth' spec.name = 'Geth'
spec.version = '{{.Version}}' spec.version = '{{.Version}}'
spec.license = { :type => 'GNU Lesser General Public License, Version 3.0' } spec.license = { :type => 'GNU Lesser General Public License, Version 3.0' }
spec.homepage = 'https://github.com/maticnetwork/bor' spec.homepage = 'https://github.com/ethereum/go-ethereum'
spec.authors = { {{range .Contributors}} spec.authors = { {{range .Contributors}}
'{{.Name}}' => '{{.Email}}',{{end}} '{{.Name}}' => '{{.Email}}',{{end}}
} }
spec.summary = 'iOS Ethereum Client' spec.summary = 'iOS Ethereum Client'
spec.source = { :git => 'https://github.com/maticnetwork/bor.git', :commit => '{{.Commit}}' } spec.source = { :git => 'https://github.com/ethereum/go-ethereum.git', :commit => '{{.Commit}}' }
spec.platform = :ios spec.platform = :ios
spec.ios.deployment_target = '9.0' spec.ios.deployment_target = '9.0'

32
circle.yml Normal file
View file

@ -0,0 +1,32 @@
machine:
services:
- docker
dependencies:
cache_directories:
- "~/.ethash" # Cache the ethash DAG generated by hive for consecutive builds
- "~/.docker" # Cache all docker images manually to avoid lengthy rebuilds
override:
# Restore all previously cached docker images
- mkdir -p ~/.docker
- for img in `ls ~/.docker`; do docker load -i ~/.docker/$img; done
# Pull in and hive, restore cached ethash DAGs and do a dry run
- go get -u github.com/karalabe/hive
- (cd ~/.go_workspace/src/github.com/karalabe/hive && mkdir -p workspace/ethash/ ~/.ethash)
- (cd ~/.go_workspace/src/github.com/karalabe/hive && cp -r ~/.ethash/. workspace/ethash/)
- (cd ~/.go_workspace/src/github.com/karalabe/hive && hive --docker-noshell --client=NONE --test=. --sim=. --loglevel=6)
# Cache all the docker images and the ethash DAGs
- for img in `docker images | grep -v "^<none>" | tail -n +2 | awk '{print $1}'`; do docker save $img > ~/.docker/`echo $img | tr '/' ':'`.tar; done
- cp -r ~/.go_workspace/src/github.com/karalabe/hive/workspace/ethash/. ~/.ethash
test:
override:
# Build Geth and move into a known folder
- make geth
- cp ./build/bin/geth $HOME/geth
# Run hive and move all generated logs into the public artifacts folder
- (cd ~/.go_workspace/src/github.com/karalabe/hive && hive --docker-noshell --client=go-ethereum:local --override=$HOME/geth --test=. --sim=.)
- cp -r ~/.go_workspace/src/github.com/karalabe/hive/workspace/logs/* $CIRCLE_ARTIFACTS

View file

@ -23,8 +23,8 @@ import (
"os" "os"
"strings" "strings"
"github.com/maticnetwork/bor/signer/core" "github.com/ethereum/go-ethereum/signer/core"
"github.com/maticnetwork/bor/signer/fourbyte" "github.com/ethereum/go-ethereum/signer/fourbyte"
) )
func init() { func init() {

View file

@ -25,12 +25,13 @@ import (
"regexp" "regexp"
"strings" "strings"
"github.com/maticnetwork/bor/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/maticnetwork/bor/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/maticnetwork/bor/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/maticnetwork/bor/common/compiler" "github.com/ethereum/go-ethereum/common/compiler"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/maticnetwork/bor/log" "github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/log"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
) )
@ -100,7 +101,7 @@ var (
) )
func init() { func init() {
app = utils.NewApp(gitCommit, gitDate, "ethereum checkpoint helper tool") app = flags.NewApp(gitCommit, gitDate, "ethereum checkpoint helper tool")
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
abiFlag, abiFlag,
binFlag, binFlag,
@ -117,7 +118,7 @@ func init() {
aliasFlag, aliasFlag,
} }
app.Action = utils.MigrateFlags(abigen) app.Action = utils.MigrateFlags(abigen)
cli.CommandHelpTemplate = utils.OriginCommandHelpTemplate cli.CommandHelpTemplate = flags.OriginCommandHelpTemplate
} }
func abigen(c *cli.Context) error { func abigen(c *cli.Context) error {

View file

@ -24,14 +24,14 @@ import (
"net" "net"
"os" "os"
"github.com/maticnetwork/bor/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/maticnetwork/bor/log" "github.com/ethereum/go-ethereum/log"
"github.com/maticnetwork/bor/p2p/discover" "github.com/ethereum/go-ethereum/p2p/discover"
"github.com/maticnetwork/bor/p2p/discv5" "github.com/ethereum/go-ethereum/p2p/discv5"
"github.com/maticnetwork/bor/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/maticnetwork/bor/p2p/nat" "github.com/ethereum/go-ethereum/p2p/nat"
"github.com/maticnetwork/bor/p2p/netutil" "github.com/ethereum/go-ethereum/p2p/netutil"
) )
func main() { func main() {
@ -44,7 +44,7 @@ func main() {
natdesc = flag.String("nat", "none", "port mapping mechanism (any|none|upnp|pmp|extip:<IP>)") natdesc = flag.String("nat", "none", "port mapping mechanism (any|none|upnp|pmp|extip:<IP>)")
netrestrict = flag.String("netrestrict", "", "restrict network communication to the given IP networks (CIDR masks)") netrestrict = flag.String("netrestrict", "", "restrict network communication to the given IP networks (CIDR masks)")
runv5 = flag.Bool("v5", false, "run a v5 topic discovery bootnode") runv5 = flag.Bool("v5", false, "run a v5 topic discovery bootnode")
verbosity = flag.Int("verbosity", int(log.LvlInfo), "log verbosity (0-9)") verbosity = flag.Int("verbosity", int(log.LvlInfo), "log verbosity (0-5)")
vmodule = flag.String("vmodule", "", "log verbosity pattern") vmodule = flag.String("vmodule", "", "log verbosity pattern")
nodeKey *ecdsa.PrivateKey nodeKey *ecdsa.PrivateKey

View file

@ -19,15 +19,15 @@ package main
import ( import (
"strconv" "strconv"
"github.com/maticnetwork/bor/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/maticnetwork/bor/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/maticnetwork/bor/accounts/external" "github.com/ethereum/go-ethereum/accounts/external"
"github.com/maticnetwork/bor/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/contracts/checkpointoracle" "github.com/ethereum/go-ethereum/contracts/checkpointoracle"
"github.com/maticnetwork/bor/ethclient" "github.com/ethereum/go-ethereum/ethclient"
"github.com/maticnetwork/bor/params" "github.com/ethereum/go-ethereum/params"
"github.com/maticnetwork/bor/rpc" "github.com/ethereum/go-ethereum/rpc"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
) )

View file

@ -25,17 +25,17 @@ import (
"strings" "strings"
"time" "time"
"github.com/maticnetwork/bor/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/maticnetwork/bor/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/maticnetwork/bor/contracts/checkpointoracle" "github.com/ethereum/go-ethereum/contracts/checkpointoracle"
"github.com/maticnetwork/bor/contracts/checkpointoracle/contract" "github.com/ethereum/go-ethereum/contracts/checkpointoracle/contract"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/maticnetwork/bor/ethclient" "github.com/ethereum/go-ethereum/ethclient"
"github.com/maticnetwork/bor/log" "github.com/ethereum/go-ethereum/log"
"github.com/maticnetwork/bor/params" "github.com/ethereum/go-ethereum/params"
"github.com/maticnetwork/bor/rpc" "github.com/ethereum/go-ethereum/rpc"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
) )

View file

@ -22,9 +22,9 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/maticnetwork/bor/cmd/utils" "github.com/ethereum/go-ethereum/common/fdlimit"
"github.com/maticnetwork/bor/common/fdlimit" "github.com/ethereum/go-ethereum/internal/flags"
"github.com/maticnetwork/bor/log" "github.com/ethereum/go-ethereum/log"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
) )
@ -37,7 +37,7 @@ var (
var app *cli.App var app *cli.App
func init() { func init() {
app = utils.NewApp(gitCommit, gitDate, "ethereum checkpoint helper tool") app = flags.NewApp(gitCommit, gitDate, "ethereum checkpoint helper tool")
app.Commands = []cli.Command{ app.Commands = []cli.Command{
commandStatus, commandStatus,
commandDeploy, commandDeploy,
@ -48,7 +48,7 @@ func init() {
oracleFlag, oracleFlag,
nodeURLFlag, nodeURLFlag,
} }
cli.CommandHelpTemplate = utils.OriginCommandHelpTemplate cli.CommandHelpTemplate = flags.OriginCommandHelpTemplate
} }
// Commonly used command line flags. // Commonly used command line flags.

View file

@ -19,8 +19,8 @@ package main
import ( import (
"fmt" "fmt"
"github.com/maticnetwork/bor/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
) )

View file

@ -33,12 +33,12 @@ GLOBAL OPTIONS:
--lightkdf Reduce key-derivation RAM & CPU usage at some expense of KDF strength --lightkdf Reduce key-derivation RAM & CPU usage at some expense of KDF strength
--nousb Disables monitoring for and managing USB hardware wallets --nousb Disables monitoring for and managing USB hardware wallets
--pcscdpath value Path to the smartcard daemon (pcscd) socket file (default: "/run/pcscd/pcscd.comm") --pcscdpath value Path to the smartcard daemon (pcscd) socket file (default: "/run/pcscd/pcscd.comm")
--rpcaddr value HTTP-RPC server listening interface (default: "localhost") --http.addr value HTTP-RPC server listening interface (default: "localhost")
--rpcvhosts value Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard. (default: "localhost") --http.vhosts value Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard. (default: "localhost")
--ipcdisable Disable the IPC-RPC server --ipcdisable Disable the IPC-RPC server
--ipcpath Filename for IPC socket/pipe within the datadir (explicit paths escape it) --ipcpath Filename for IPC socket/pipe within the datadir (explicit paths escape it)
--rpc Enable the HTTP-RPC server --http Enable the HTTP-RPC server
--rpcport value HTTP-RPC server listening port (default: 8550) --http.port value HTTP-RPC server listening port (default: 8550)
--signersecret value A file containing the (encrypted) master seed to encrypt Clef data, e.g. keystore credentials and ruleset hash --signersecret value A file containing the (encrypted) master seed to encrypt Clef data, e.g. keystore credentials and ruleset hash
--4bytedb-custom value File used for writing new 4byte-identifiers submitted via API (default: "./4byte-custom.json") --4bytedb-custom value File used for writing new 4byte-identifiers submitted via API (default: "./4byte-custom.json")
--auditlog value File used to emit audit logs. Set to "" to disable (default: "audit.log") --auditlog value File used to emit audit logs. Set to "" to disable (default: "audit.log")
@ -113,7 +113,7 @@ Some snags and todos
### External API ### External API
Clef listens to HTTP requests on `rpcaddr`:`rpcport` (or to IPC on `ipcpath`), with the same JSON-RPC standard as Geth. The messages are expected to be [JSON-RPC 2.0 standard](https://www.jsonrpc.org/specification). Clef listens to HTTP requests on `http.addr`:`http.port` (or to IPC on `ipcpath`), with the same JSON-RPC standard as Geth. The messages are expected to be [JSON-RPC 2.0 standard](https://www.jsonrpc.org/specification).
Some of these calls can require user interaction. Clients must be aware that responses may be delayed significantly or may never be received if a user decides to ignore the confirmation request. Some of these calls can require user interaction. Clients must be aware that responses may be delayed significantly or may never be received if a user decides to ignore the confirmation request.

View file

@ -94,7 +94,7 @@ with minimal requirements.
On the `client` qube, we need to create a listener which will receive the request from the Dapp, and proxy it. On the `client` qube, we need to create a listener which will receive the request from the Dapp, and proxy it.
[qubes-client.py](qubes/client/qubes-client.py): [qubes-client.py](qubes/qubes-client.py):
```python ```python

View file

@ -10,6 +10,64 @@ TL;DR: Given a version number MAJOR.MINOR.PATCH, increment the:
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format. Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
### 6.1.0
The API-method `account_signGnosisSafeTx` was added. This method takes two parameters,
`[address, safeTx]`. The latter, `safeTx`, can be copy-pasted from the gnosis relay. For example:
```
{
"jsonrpc": "2.0",
"method": "account_signGnosisSafeTx",
"params": ["0xfd1c4226bfD1c436672092F4eCbfC270145b7256",
{
"safe": "0x25a6c4BBd32B2424A9c99aEB0584Ad12045382B3",
"to": "0xB372a646f7F05Cc1785018dBDA7EBc734a2A20E2",
"value": "20000000000000000",
"data": null,
"operation": 0,
"gasToken": "0x0000000000000000000000000000000000000000",
"safeTxGas": 27845,
"baseGas": 0,
"gasPrice": "0",
"refundReceiver": "0x0000000000000000000000000000000000000000",
"nonce": 2,
"executionDate": null,
"submissionDate": "2020-09-15T21:54:49.617634Z",
"modified": "2020-09-15T21:54:49.617634Z",
"blockNumber": null,
"transactionHash": null,
"safeTxHash": "0x2edfbd5bc113ff18c0631595db32eb17182872d88d9bf8ee4d8c2dd5db6d95e2",
"executor": null,
"isExecuted": false,
"isSuccessful": null,
"ethGasPrice": null,
"gasUsed": null,
"fee": null,
"origin": null,
"dataDecoded": null,
"confirmationsRequired": null,
"confirmations": [
{
"owner": "0xAd2e180019FCa9e55CADe76E4487F126Fd08DA34",
"submissionDate": "2020-09-15T21:54:49.663299Z",
"transactionHash": null,
"confirmationType": "CONFIRMATION",
"signature": "0x95a7250bb645f831c86defc847350e7faff815b2fb586282568e96cc859e39315876db20a2eed5f7a0412906ec5ab57652a6f645ad4833f345bda059b9da2b821c",
"signatureType": "EOA"
}
],
"signatures": null
}
],
"id": 67
}
```
Not all fields are required, though. This method is really just a UX helper, which massages the
input to conform to the `EIP-712` [specification](https://docs.gnosis.io/safe/docs/contracts_tx_execution/#transaction-hash)
for the Gnosis Safe, and making the output be directly importable to by a relay service.
### 6.0.0 ### 6.0.0

View file

@ -29,29 +29,31 @@ import (
"math/big" "math/big"
"os" "os"
"os/signal" "os/signal"
"os/user"
"path/filepath" "path/filepath"
"runtime" "runtime"
"sort"
"strings" "strings"
"time" "time"
"github.com/maticnetwork/bor/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/maticnetwork/bor/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/maticnetwork/bor/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/maticnetwork/bor/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/maticnetwork/bor/internal/ethapi" "github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/maticnetwork/bor/log" "github.com/ethereum/go-ethereum/internal/flags"
"github.com/maticnetwork/bor/node" "github.com/ethereum/go-ethereum/log"
"github.com/maticnetwork/bor/params" "github.com/ethereum/go-ethereum/node"
"github.com/maticnetwork/bor/rlp" "github.com/ethereum/go-ethereum/params"
"github.com/maticnetwork/bor/rpc" "github.com/ethereum/go-ethereum/rlp"
"github.com/maticnetwork/bor/signer/core" "github.com/ethereum/go-ethereum/rpc"
"github.com/maticnetwork/bor/signer/fourbyte" "github.com/ethereum/go-ethereum/signer/core"
"github.com/maticnetwork/bor/signer/rules" "github.com/ethereum/go-ethereum/signer/fourbyte"
"github.com/maticnetwork/bor/signer/storage" "github.com/ethereum/go-ethereum/signer/rules"
"github.com/ethereum/go-ethereum/signer/storage"
colorable "github.com/mattn/go-colorable" colorable "github.com/mattn/go-colorable"
"github.com/mattn/go-isatty" "github.com/mattn/go-isatty"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
@ -101,10 +103,15 @@ var (
Usage: "Chain id to use for signing (1=mainnet, 3=Ropsten, 4=Rinkeby, 5=Goerli)", Usage: "Chain id to use for signing (1=mainnet, 3=Ropsten, 4=Rinkeby, 5=Goerli)",
} }
rpcPortFlag = cli.IntFlag{ rpcPortFlag = cli.IntFlag{
Name: "rpcport", Name: "http.port",
Usage: "HTTP-RPC server listening port", Usage: "HTTP-RPC server listening port",
Value: node.DefaultHTTPPort + 5, Value: node.DefaultHTTPPort + 5,
} }
legacyRPCPortFlag = cli.IntFlag{
Name: "rpcport",
Usage: "HTTP-RPC server listening port (Deprecated, please use --http.port).",
Value: node.DefaultHTTPPort + 5,
}
signerSecretFlag = cli.StringFlag{ signerSecretFlag = cli.StringFlag{
Name: "signersecret", Name: "signersecret",
Usage: "A file containing the (encrypted) master seed to encrypt Clef data, e.g. keystore credentials and ruleset hash", Usage: "A file containing the (encrypted) master seed to encrypt Clef data, e.g. keystore credentials and ruleset hash",
@ -215,6 +222,42 @@ The gendoc generates example structures of the json-rpc communication types.
`} `}
) )
// AppHelpFlagGroups is the application flags, grouped by functionality.
var AppHelpFlagGroups = []flags.FlagGroup{
{
Name: "FLAGS",
Flags: []cli.Flag{
logLevelFlag,
keystoreFlag,
configdirFlag,
chainIdFlag,
utils.LightKDFFlag,
utils.NoUSBFlag,
utils.SmartCardDaemonPathFlag,
utils.HTTPListenAddrFlag,
utils.HTTPVirtualHostsFlag,
utils.IPCDisabledFlag,
utils.IPCPathFlag,
utils.HTTPEnabledFlag,
rpcPortFlag,
signerSecretFlag,
customDBFlag,
auditLogFlag,
ruleFlag,
stdiouiFlag,
testFlag,
advancedMode,
acceptFlag,
},
},
{
Name: "ALIASED (deprecated)",
Flags: []cli.Flag{
legacyRPCPortFlag,
},
},
}
func init() { func init() {
app.Name = "Clef" app.Name = "Clef"
app.Usage = "Manage Ethereum account operations" app.Usage = "Manage Ethereum account operations"
@ -240,6 +283,7 @@ func init() {
testFlag, testFlag,
advancedMode, advancedMode,
acceptFlag, acceptFlag,
legacyRPCPortFlag,
} }
app.Action = signer app.Action = signer
app.Commands = []cli.Command{initCommand, app.Commands = []cli.Command{initCommand,
@ -248,7 +292,41 @@ func init() {
delCredentialCommand, delCredentialCommand,
newAccountCommand, newAccountCommand,
gendocCommand} gendocCommand}
cli.CommandHelpTemplate = utils.OriginCommandHelpTemplate cli.CommandHelpTemplate = flags.CommandHelpTemplate
// Override the default app help template
cli.AppHelpTemplate = flags.ClefAppHelpTemplate
// Override the default app help printer, but only for the global app help
originalHelpPrinter := cli.HelpPrinter
cli.HelpPrinter = func(w io.Writer, tmpl string, data interface{}) {
if tmpl == flags.ClefAppHelpTemplate {
// Render out custom usage screen
originalHelpPrinter(w, tmpl, flags.HelpData{App: data, FlagGroups: AppHelpFlagGroups})
} else if tmpl == flags.CommandHelpTemplate {
// Iterate over all command specific flags and categorize them
categorized := make(map[string][]cli.Flag)
for _, flag := range data.(cli.Command).Flags {
if _, ok := categorized[flag.String()]; !ok {
categorized[flags.FlagCategory(flag, AppHelpFlagGroups)] = append(categorized[flags.FlagCategory(flag, AppHelpFlagGroups)], flag)
}
}
// sort to get a stable ordering
sorted := make([]flags.FlagGroup, 0, len(categorized))
for cat, flgs := range categorized {
sorted = append(sorted, flags.FlagGroup{Name: cat, Flags: flgs})
}
sort.Sort(flags.ByCategory(sorted))
// add sorted array to data and render with default printer
originalHelpPrinter(w, tmpl, map[string]interface{}{
"cmd": data,
"categorizedFlags": sorted,
})
} else {
originalHelpPrinter(w, tmpl, data)
}
}
} }
func main() { func main() {
@ -587,8 +665,8 @@ func signer(c *cli.Context) error {
Version: "1.0"}, Version: "1.0"},
} }
if c.GlobalBool(utils.HTTPEnabledFlag.Name) { if c.GlobalBool(utils.HTTPEnabledFlag.Name) {
vhosts := splitAndTrim(c.GlobalString(utils.HTTPVirtualHostsFlag.Name)) vhosts := utils.SplitAndTrim(c.GlobalString(utils.HTTPVirtualHostsFlag.Name))
cors := splitAndTrim(c.GlobalString(utils.HTTPCORSDomainFlag.Name)) cors := utils.SplitAndTrim(c.GlobalString(utils.HTTPCORSDomainFlag.Name))
srv := rpc.NewServer() srv := rpc.NewServer()
err := node.RegisterApisFromWhitelist(rpcAPI, []string{"account"}, srv, false) err := node.RegisterApisFromWhitelist(rpcAPI, []string{"account"}, srv, false)
@ -597,8 +675,17 @@ func signer(c *cli.Context) error {
} }
handler := node.NewHTTPHandlerStack(srv, cors, vhosts) handler := node.NewHTTPHandlerStack(srv, cors, vhosts)
// set port
port := c.Int(rpcPortFlag.Name)
if c.GlobalIsSet(legacyRPCPortFlag.Name) {
if !c.GlobalIsSet(rpcPortFlag.Name) {
port = c.Int(legacyRPCPortFlag.Name)
}
log.Warn("The flag --rpcport is deprecated and will be removed in the future, please use --http.port")
}
// start http server // start http server
httpEndpoint := fmt.Sprintf("%s:%d", c.GlobalString(utils.HTTPListenAddrFlag.Name), c.Int(rpcPortFlag.Name)) httpEndpoint := fmt.Sprintf("%s:%d", c.GlobalString(utils.HTTPListenAddrFlag.Name), port)
httpServer, addr, err := node.StartHTTPEndpoint(httpEndpoint, rpc.DefaultHTTPTimeouts, handler) httpServer, addr, err := node.StartHTTPEndpoint(httpEndpoint, rpc.DefaultHTTPTimeouts, handler)
if err != nil { if err != nil {
utils.Fatalf("Could not start RPC api: %v", err) utils.Fatalf("Could not start RPC api: %v", err)
@ -648,21 +735,11 @@ func signer(c *cli.Context) error {
return nil return nil
} }
// splitAndTrim splits input separated by a comma
// and trims excessive white space from the substrings.
func splitAndTrim(input string) []string {
result := strings.Split(input, ",")
for i, r := range result {
result[i] = strings.TrimSpace(r)
}
return result
}
// DefaultConfigDir is the default config directory to use for the vaults and other // DefaultConfigDir is the default config directory to use for the vaults and other
// persistence requirements. // persistence requirements.
func DefaultConfigDir() string { func DefaultConfigDir() string {
// Try to place the data folder in the user's home dir // Try to place the data folder in the user's home dir
home := homeDir() home := utils.HomeDir()
if home != "" { if home != "" {
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
return filepath.Join(home, "Library", "Signer") return filepath.Join(home, "Library", "Signer")
@ -681,15 +758,6 @@ func DefaultConfigDir() string {
return "" return ""
} }
func homeDir() string {
if home := os.Getenv("HOME"); home != "" {
return home
}
if usr, err := user.Current(); err == nil {
return usr.HomeDir
}
return ""
}
func readMasterKey(ctx *cli.Context, ui core.UIClientAPI) ([]byte, error) { func readMasterKey(ctx *cli.Context, ui core.UIClientAPI) ([]byte, error) {
var ( var (
file string file string

105
cmd/devp2p/README.md Normal file
View file

@ -0,0 +1,105 @@
# The devp2p command
The devp2p command line tool is a utility for low-level peer-to-peer debugging and
protocol development purposes. It can do many things.
### ENR Decoding
Use `devp2p enrdump <base64>` to verify and display an Ethereum Node Record.
### Node Key Management
The `devp2p key ...` command family deals with node key files.
Run `devp2p key generate mynode.key` to create a new node key in the `mynode.key` file.
Run `devp2p key to-enode mynode.key -ip 127.0.0.1 -tcp 30303` to create an enode:// URL
corresponding to the given node key and address information.
### Maintaining DNS Discovery Node Lists
The devp2p command can create and publish DNS discovery node lists.
Run `devp2p dns sign <directory>` to update the signature of a DNS discovery tree.
Run `devp2p dns sync <enrtree-URL>` to download a complete DNS discovery tree.
Run `devp2p dns to-cloudflare <directory>` to publish a tree to CloudFlare DNS.
Run `devp2p dns to-route53 <directory>` to publish a tree to Amazon Route53.
You can find more information about these commands in the [DNS Discovery Setup Guide][dns-tutorial].
### Discovery v4 Utilities
The `devp2p discv4 ...` command family deals with the [Node Discovery v4][discv4]
protocol.
Run `devp2p discv4 ping <enode/ENR>` to ping a node.
Run `devp2p discv4 resolve <enode/ENR>` to find the most recent node record of a node in
the DHT.
Run `devp2p discv4 crawl <nodes.json path>` to create or update a JSON node set.
### Discovery v5 Utilities
The `devp2p discv5 ...` command family deals with the [Node Discovery v5][discv5]
protocol. This protocol is currently under active development.
Run `devp2p discv5 ping <ENR>` to ping a node.
Run `devp2p discv5 resolve <ENR>` to find the most recent node record of a node in
the discv5 DHT.
Run `devp2p discv5 listen` to run a Discovery v5 node.
Run `devp2p discv5 crawl <nodes.json path>` to create or update a JSON node set containing
discv5 nodes.
### Discovery Test Suites
The devp2p command also contains interactive test suites for Discovery v4 and Discovery
v5.
To run these tests against your implementation, you need to set up a networking
environment where two separate UDP listening addresses are available on the same machine.
The two listening addresses must also be routed such that they are able to reach the node
you want to test.
For example, if you want to run the test on your local host, and the node under test is
also on the local host, you need to assign two IP addresses (or a larger range) to your
loopback interface. On macOS, this can be done by executing the following command:
sudo ifconfig lo0 add 127.0.0.2
You can now run either test suite as follows: Start the node under test first, ensuring
that it won't talk to the Internet (i.e. disable bootstrapping). An easy way to prevent
unintended connections to the global DHT is listening on `127.0.0.1`.
Now get the ENR of your node and store it in the `NODE` environment variable.
Start the test by running `devp2p discv5 test -listen1 127.0.0.1 -listen2 127.0.0.2 $NODE`.
### Eth Protocol Test Suite
The Eth Protocol test suite is a conformance test suite for the [eth protocol][eth].
To run the eth protocol test suite against your implementation, the node needs to be initialized as such:
1. initialize the geth node with the `genesis.json` file contained in the `testdata` directory
2. import the `halfchain.rlp` file in the `testdata` directory
3. run geth with the following flags:
```
geth --datadir <datadir> --nodiscover --nat=none --networkid 19763 --verbosity 5
```
Then, run the following command, replacing `<enode ID>` with the enode of the geth node:
```
devp2p rlpx eth-test <enode ID> cmd/devp2p/internal/ethtest/testdata/fullchain.rlp cmd/devp2p/internal/ethtest/testdata/genesis.json
```
[eth]: https://github.com/ethereum/devp2p/blob/master/caps/eth.md
[dns-tutorial]: https://geth.ethereum.org/docs/developers/dns-discovery-setup
[discv4]: https://github.com/ethereum/devp2p/tree/master/discv4.md
[discv5]: https://github.com/ethereum/devp2p/tree/master/discv5/discv5.md

View file

@ -19,8 +19,8 @@ package main
import ( import (
"time" "time"
"github.com/maticnetwork/bor/log" "github.com/ethereum/go-ethereum/log"
"github.com/maticnetwork/bor/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
) )
type crawler struct { type crawler struct {

View file

@ -19,17 +19,15 @@ package main
import ( import (
"fmt" "fmt"
"net" "net"
"os"
"strings" "strings"
"time" "time"
"github.com/maticnetwork/bor/cmd/devp2p/internal/v4test" "github.com/ethereum/go-ethereum/cmd/devp2p/internal/v4test"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/maticnetwork/bor/internal/utesting" "github.com/ethereum/go-ethereum/p2p/discover"
"github.com/maticnetwork/bor/p2p/discover" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/maticnetwork/bor/p2p/enode" "github.com/ethereum/go-ethereum/params"
"github.com/maticnetwork/bor/params"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
) )
@ -82,7 +80,13 @@ var (
Name: "test", Name: "test",
Usage: "Runs tests against a node", Usage: "Runs tests against a node",
Action: discv4Test, Action: discv4Test,
Flags: []cli.Flag{remoteEnodeFlag, testPatternFlag, testListen1Flag, testListen2Flag}, Flags: []cli.Flag{
remoteEnodeFlag,
testPatternFlag,
testTAPFlag,
testListen1Flag,
testListen2Flag,
},
} }
) )
@ -113,20 +117,6 @@ var (
Usage: "Enode of the remote node under test", Usage: "Enode of the remote node under test",
EnvVar: "REMOTE_ENODE", EnvVar: "REMOTE_ENODE",
} }
testPatternFlag = cli.StringFlag{
Name: "run",
Usage: "Pattern of test suite(s) to run",
}
testListen1Flag = cli.StringFlag{
Name: "listen1",
Usage: "IP address of the first tester",
Value: v4test.Listen1,
}
testListen2Flag = cli.StringFlag{
Name: "listen2",
Usage: "IP address of the second tester",
Value: v4test.Listen2,
}
) )
func discv4Ping(ctx *cli.Context) error { func discv4Ping(ctx *cli.Context) error {
@ -213,6 +203,7 @@ func discv4Crawl(ctx *cli.Context) error {
return nil return nil
} }
// discv4Test runs the protocol test suite.
func discv4Test(ctx *cli.Context) error { func discv4Test(ctx *cli.Context) error {
// Configure test package globals. // Configure test package globals.
if !ctx.IsSet(remoteEnodeFlag.Name) { if !ctx.IsSet(remoteEnodeFlag.Name) {
@ -221,18 +212,7 @@ func discv4Test(ctx *cli.Context) error {
v4test.Remote = ctx.String(remoteEnodeFlag.Name) v4test.Remote = ctx.String(remoteEnodeFlag.Name)
v4test.Listen1 = ctx.String(testListen1Flag.Name) v4test.Listen1 = ctx.String(testListen1Flag.Name)
v4test.Listen2 = ctx.String(testListen2Flag.Name) v4test.Listen2 = ctx.String(testListen2Flag.Name)
return runTests(ctx, v4test.AllTests)
// Filter and run test cases.
tests := v4test.AllTests
if ctx.IsSet(testPatternFlag.Name) {
tests = utesting.MatchTests(tests, ctx.String(testPatternFlag.Name))
}
results := utesting.RunTests(tests, os.Stdout)
if fails := utesting.CountFailures(results); fails > 0 {
return fmt.Errorf("%v/%v tests passed.", len(tests)-fails, len(tests))
}
fmt.Printf("%v/%v passed\n", len(tests), len(tests))
return nil
} }
// startV4 starts an ephemeral discovery V4 node. // startV4 starts an ephemeral discovery V4 node.
@ -286,7 +266,11 @@ func listen(ln *enode.LocalNode, addr string) *net.UDPConn {
} }
usocket := socket.(*net.UDPConn) usocket := socket.(*net.UDPConn)
uaddr := socket.LocalAddr().(*net.UDPAddr) uaddr := socket.LocalAddr().(*net.UDPAddr)
ln.SetFallbackIP(net.IP{127, 0, 0, 1}) if uaddr.IP.IsUnspecified() {
ln.SetFallbackIP(net.IP{127, 0, 0, 1})
} else {
ln.SetFallbackIP(uaddr.IP)
}
ln.SetFallbackUDP(uaddr.Port) ln.SetFallbackUDP(uaddr.Port)
return usocket return usocket
} }
@ -294,7 +278,11 @@ func listen(ln *enode.LocalNode, addr string) *net.UDPConn {
func parseBootnodes(ctx *cli.Context) ([]*enode.Node, error) { func parseBootnodes(ctx *cli.Context) ([]*enode.Node, error) {
s := params.RinkebyBootnodes s := params.RinkebyBootnodes
if ctx.IsSet(bootnodesFlag.Name) { if ctx.IsSet(bootnodesFlag.Name) {
s = strings.Split(ctx.String(bootnodesFlag.Name), ",") input := ctx.String(bootnodesFlag.Name)
if input == "" {
return nil, nil
}
s = strings.Split(input, ",")
} }
nodes := make([]*enode.Node, len(s)) nodes := make([]*enode.Node, len(s))
var err error var err error

View file

@ -20,8 +20,9 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/cmd/devp2p/internal/v5test"
"github.com/maticnetwork/bor/p2p/discover" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/p2p/discover"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
) )
@ -33,6 +34,7 @@ var (
discv5PingCommand, discv5PingCommand,
discv5ResolveCommand, discv5ResolveCommand,
discv5CrawlCommand, discv5CrawlCommand,
discv5TestCommand,
discv5ListenCommand, discv5ListenCommand,
}, },
} }
@ -53,6 +55,17 @@ var (
Action: discv5Crawl, Action: discv5Crawl,
Flags: []cli.Flag{bootnodesFlag, crawlTimeoutFlag}, Flags: []cli.Flag{bootnodesFlag, crawlTimeoutFlag},
} }
discv5TestCommand = cli.Command{
Name: "test",
Usage: "Runs protocol tests against a node",
Action: discv5Test,
Flags: []cli.Flag{
testPatternFlag,
testTAPFlag,
testListen1Flag,
testListen2Flag,
},
}
discv5ListenCommand = cli.Command{ discv5ListenCommand = cli.Command{
Name: "listen", Name: "listen",
Usage: "Runs a node", Usage: "Runs a node",
@ -103,6 +116,16 @@ func discv5Crawl(ctx *cli.Context) error {
return nil return nil
} }
// discv5Test runs the protocol test suite.
func discv5Test(ctx *cli.Context) error {
suite := &v5test.Suite{
Dest: getNodeArg(ctx),
Listen1: ctx.String(testListen1Flag.Name),
Listen2: ctx.String(testListen2Flag.Name),
}
return runTests(ctx, suite.AllTests())
}
func discv5Listen(ctx *cli.Context) error { func discv5Listen(ctx *cli.Context) error {
disc := startV5(ctx) disc := startV5(ctx)
defer disc.Close() defer disc.Close()

View file

@ -21,8 +21,8 @@ import (
"strings" "strings"
"github.com/cloudflare/cloudflare-go" "github.com/cloudflare/cloudflare-go"
"github.com/maticnetwork/bor/log" "github.com/ethereum/go-ethereum/log"
"github.com/maticnetwork/bor/p2p/dnsdisc" "github.com/ethereum/go-ethereum/p2p/dnsdisc"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
) )

View file

@ -27,8 +27,8 @@ import (
"github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/route53" "github.com/aws/aws-sdk-go/service/route53"
"github.com/maticnetwork/bor/log" "github.com/ethereum/go-ethereum/log"
"github.com/maticnetwork/bor/p2p/dnsdisc" "github.com/ethereum/go-ethereum/p2p/dnsdisc"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
) )

View file

@ -25,11 +25,11 @@ import (
"path/filepath" "path/filepath"
"time" "time"
"github.com/maticnetwork/bor/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/maticnetwork/bor/common" "github.com/ethereum/go-ethereum/common"
"github.com/maticnetwork/bor/console/prompt" "github.com/ethereum/go-ethereum/console/prompt"
"github.com/maticnetwork/bor/p2p/dnsdisc" "github.com/ethereum/go-ethereum/p2p/dnsdisc"
"github.com/maticnetwork/bor/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
cli "gopkg.in/urfave/cli.v1" cli "gopkg.in/urfave/cli.v1"
) )

View file

@ -21,15 +21,16 @@ import (
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
"net" "net"
"os" "os"
"strconv" "strconv"
"strings" "strings"
"github.com/maticnetwork/bor/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/maticnetwork/bor/p2p/enr" "github.com/ethereum/go-ethereum/p2p/enr"
"github.com/maticnetwork/bor/rlp" "github.com/ethereum/go-ethereum/rlp"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
) )
@ -69,22 +70,30 @@ func enrdump(ctx *cli.Context) error {
if err != nil { if err != nil {
return fmt.Errorf("INVALID: %v", err) return fmt.Errorf("INVALID: %v", err)
} }
fmt.Print(dumpRecord(r)) dumpRecord(os.Stdout, r)
return nil return nil
} }
// dumpRecord creates a human-readable description of the given node record. // dumpRecord creates a human-readable description of the given node record.
func dumpRecord(r *enr.Record) string { func dumpRecord(out io.Writer, r *enr.Record) {
out := new(bytes.Buffer) n, err := enode.New(enode.ValidSchemes, r)
if n, err := enode.New(enode.ValidSchemes, r); err != nil { if err != nil {
fmt.Fprintf(out, "INVALID: %v\n", err) fmt.Fprintf(out, "INVALID: %v\n", err)
} else { } else {
fmt.Fprintf(out, "Node ID: %v\n", n.ID()) fmt.Fprintf(out, "Node ID: %v\n", n.ID())
dumpNodeURL(out, n)
} }
kv := r.AppendElements(nil)[1:] kv := r.AppendElements(nil)[1:]
fmt.Fprintf(out, "Record has sequence number %d and %d key/value pairs.\n", r.Seq(), len(kv)/2) fmt.Fprintf(out, "Record has sequence number %d and %d key/value pairs.\n", r.Seq(), len(kv)/2)
fmt.Fprint(out, dumpRecordKV(kv, 2)) fmt.Fprint(out, dumpRecordKV(kv, 2))
return out.String() }
func dumpNodeURL(out io.Writer, n *enode.Node) {
var key enode.Secp256k1
if n.Load(&key) != nil {
return // no secp256k1 public key
}
fmt.Fprintf(out, "URLv4: %s\n", n.URLv4())
} }
func dumpRecordKV(kv []interface{}, indent int) string { func dumpRecordKV(kv []interface{}, indent int) string {

View file

@ -0,0 +1,167 @@
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// 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 ethtest
import (
"compress/gzip"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"math/big"
"os"
"strings"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)
type Chain struct {
blocks []*types.Block
chainConfig *params.ChainConfig
}
func (c *Chain) WriteTo(writer io.Writer) error {
for _, block := range c.blocks {
if err := rlp.Encode(writer, block); err != nil {
return err
}
}
return nil
}
// Len returns the length of the chain.
func (c *Chain) Len() int {
return len(c.blocks)
}
// TD calculates the total difficulty of the chain.
func (c *Chain) TD(height int) *big.Int { // TODO later on channge scheme so that the height is included in range
sum := big.NewInt(0)
for _, block := range c.blocks[:height] {
sum.Add(sum, block.Difficulty())
}
return sum
}
// ForkID gets the fork id of the chain.
func (c *Chain) ForkID() forkid.ID {
return forkid.NewID(c.chainConfig, c.blocks[0].Hash(), uint64(c.Len()))
}
// Shorten returns a copy chain of a desired height from the imported
func (c *Chain) Shorten(height int) *Chain {
blocks := make([]*types.Block, height)
copy(blocks, c.blocks[:height])
config := *c.chainConfig
return &Chain{
blocks: blocks,
chainConfig: &config,
}
}
// Head returns the chain head.
func (c *Chain) Head() *types.Block {
return c.blocks[c.Len()-1]
}
func (c *Chain) GetHeaders(req GetBlockHeaders) (BlockHeaders, error) {
if req.Amount < 1 {
return nil, fmt.Errorf("no block headers requested")
}
headers := make(BlockHeaders, req.Amount)
var blockNumber uint64
// range over blocks to check if our chain has the requested header
for _, block := range c.blocks {
if block.Hash() == req.Origin.Hash || block.Number().Uint64() == req.Origin.Number {
headers[0] = block.Header()
blockNumber = block.Number().Uint64()
}
}
if headers[0] == nil {
return nil, fmt.Errorf("no headers found for given origin number %v, hash %v", req.Origin.Number, req.Origin.Hash)
}
if req.Reverse {
for i := 1; i < int(req.Amount); i++ {
blockNumber -= (1 - req.Skip)
headers[i] = c.blocks[blockNumber].Header()
}
return headers, nil
}
for i := 1; i < int(req.Amount); i++ {
blockNumber += (1 + req.Skip)
headers[i] = c.blocks[blockNumber].Header()
}
return headers, nil
}
// loadChain takes the given chain.rlp file, and decodes and returns
// the blocks from the file.
func loadChain(chainfile string, genesis string) (*Chain, error) {
chainConfig, err := ioutil.ReadFile(genesis)
if err != nil {
return nil, err
}
var gen core.Genesis
if err := json.Unmarshal(chainConfig, &gen); err != nil {
return nil, err
}
gblock := gen.ToBlock(nil)
// Load chain.rlp.
fh, err := os.Open(chainfile)
if err != nil {
return nil, err
}
defer fh.Close()
var reader io.Reader = fh
if strings.HasSuffix(chainfile, ".gz") {
if reader, err = gzip.NewReader(reader); err != nil {
return nil, err
}
}
stream := rlp.NewStream(reader, 0)
var blocks = make([]*types.Block, 1)
blocks[0] = gblock
for i := 0; ; i++ {
var b types.Block
if err := stream.Decode(&b); err == io.EOF {
break
} else if err != nil {
return nil, fmt.Errorf("at block index %d: %v", i, err)
}
if b.NumberU64() != uint64(i+1) {
return nil, fmt.Errorf("block at index %d has wrong number %d", i, b.NumberU64())
}
blocks = append(blocks, &b)
}
c := &Chain{blocks: blocks, chainConfig: gen.Config}
return c, nil
}

View file

@ -0,0 +1,150 @@
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// 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 ethtest
import (
"path/filepath"
"strconv"
"testing"
"github.com/ethereum/go-ethereum/p2p"
"github.com/stretchr/testify/assert"
)
// TestEthProtocolNegotiation tests whether the test suite
// can negotiate the highest eth protocol in a status message exchange
func TestEthProtocolNegotiation(t *testing.T) {
var tests = []struct {
conn *Conn
caps []p2p.Cap
expected uint32
}{
{
conn: &Conn{},
caps: []p2p.Cap{
{Name: "eth", Version: 63},
{Name: "eth", Version: 64},
{Name: "eth", Version: 65},
},
expected: uint32(65),
},
{
conn: &Conn{},
caps: []p2p.Cap{
{Name: "eth", Version: 0},
{Name: "eth", Version: 89},
{Name: "eth", Version: 65},
},
expected: uint32(65),
},
{
conn: &Conn{},
caps: []p2p.Cap{
{Name: "eth", Version: 63},
{Name: "eth", Version: 64},
{Name: "wrongProto", Version: 65},
},
expected: uint32(64),
},
}
for i, tt := range tests {
t.Run(strconv.Itoa(i), func(t *testing.T) {
tt.conn.negotiateEthProtocol(tt.caps)
assert.Equal(t, tt.expected, uint32(tt.conn.ethProtocolVersion))
})
}
}
// TestChain_GetHeaders tests whether the test suite can correctly
// respond to a GetBlockHeaders request from a node.
func TestChain_GetHeaders(t *testing.T) {
chainFile, err := filepath.Abs("./testdata/fullchain.rlp.gz")
if err != nil {
t.Fatal(err)
}
genesisFile, err := filepath.Abs("./testdata/genesis.json")
if err != nil {
t.Fatal(err)
}
chain, err := loadChain(chainFile, genesisFile)
if err != nil {
t.Fatal(err)
}
var tests = []struct {
req GetBlockHeaders
expected BlockHeaders
}{
{
req: GetBlockHeaders{
Origin: hashOrNumber{
Number: uint64(2),
},
Amount: uint64(5),
Skip: 1,
Reverse: false,
},
expected: BlockHeaders{
chain.blocks[2].Header(),
chain.blocks[4].Header(),
chain.blocks[6].Header(),
chain.blocks[8].Header(),
chain.blocks[10].Header(),
},
},
{
req: GetBlockHeaders{
Origin: hashOrNumber{
Number: uint64(chain.Len() - 1),
},
Amount: uint64(3),
Skip: 0,
Reverse: true,
},
expected: BlockHeaders{
chain.blocks[chain.Len()-1].Header(),
chain.blocks[chain.Len()-2].Header(),
chain.blocks[chain.Len()-3].Header(),
},
},
{
req: GetBlockHeaders{
Origin: hashOrNumber{
Hash: chain.Head().Hash(),
},
Amount: uint64(1),
Skip: 0,
Reverse: false,
},
expected: BlockHeaders{
chain.Head().Header(),
},
},
}
for i, tt := range tests {
t.Run(strconv.Itoa(i), func(t *testing.T) {
headers, err := chain.GetHeaders(tt.req)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, headers, tt.expected)
})
}
}

View file

@ -0,0 +1,233 @@
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library 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 Lesser General Public License for more details.
//
// 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 ethtest
import (
"fmt"
"net"
"time"
"github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/internal/utesting"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/rlpx"
"github.com/stretchr/testify/assert"
)
var pretty = spew.ConfigState{
Indent: " ",
DisableCapacities: true,
DisablePointerAddresses: true,
SortKeys: true,
}
// Suite represents a structure used to test the eth
// protocol of a node(s).
type Suite struct {
Dest *enode.Node
chain *Chain
fullChain *Chain
}
// NewSuite creates and returns a new eth-test suite that can
// be used to test the given node against the given blockchain
// data.
func NewSuite(dest *enode.Node, chainfile string, genesisfile string) *Suite {
chain, err := loadChain(chainfile, genesisfile)
if err != nil {
panic(err)
}
return &Suite{
Dest: dest,
chain: chain.Shorten(1000),
fullChain: chain,
}
}
func (s *Suite) AllTests() []utesting.Test {
return []utesting.Test{
{Name: "Status", Fn: s.TestStatus},
{Name: "GetBlockHeaders", Fn: s.TestGetBlockHeaders},
{Name: "Broadcast", Fn: s.TestBroadcast},
{Name: "GetBlockBodies", Fn: s.TestGetBlockBodies},
}
}
// TestStatus attempts to connect to the given node and exchange
// a status message with it, and then check to make sure
// the chain head is correct.
func (s *Suite) TestStatus(t *utesting.T) {
conn, err := s.dial()
if err != nil {
t.Fatalf("could not dial: %v", err)
}
// get protoHandshake
conn.handshake(t)
// get status
switch msg := conn.statusExchange(t, s.chain).(type) {
case *Status:
t.Logf("got status message: %s", pretty.Sdump(msg))
default:
t.Fatalf("unexpected: %s", pretty.Sdump(msg))
}
}
// TestGetBlockHeaders tests whether the given node can respond to
// a `GetBlockHeaders` request and that the response is accurate.
func (s *Suite) TestGetBlockHeaders(t *utesting.T) {
conn, err := s.dial()
if err != nil {
t.Fatalf("could not dial: %v", err)
}
conn.handshake(t)
conn.statusExchange(t, s.chain)
// get block headers
req := &GetBlockHeaders{
Origin: hashOrNumber{
Hash: s.chain.blocks[1].Hash(),
},
Amount: 2,
Skip: 1,
Reverse: false,
}
if err := conn.Write(req); err != nil {
t.Fatalf("could not write to connection: %v", err)
}
timeout := 20 * time.Second
switch msg := conn.ReadAndServe(s.chain, timeout).(type) {
case *BlockHeaders:
headers := msg
for _, header := range *headers {
num := header.Number.Uint64()
t.Logf("received header (%d): %s", num, pretty.Sdump(header))
assert.Equal(t, s.chain.blocks[int(num)].Header(), header)
}
default:
t.Fatalf("unexpected: %s", pretty.Sdump(msg))
}
}
// TestGetBlockBodies tests whether the given node can respond to
// a `GetBlockBodies` request and that the response is accurate.
func (s *Suite) TestGetBlockBodies(t *utesting.T) {
conn, err := s.dial()
if err != nil {
t.Fatalf("could not dial: %v", err)
}
conn.handshake(t)
conn.statusExchange(t, s.chain)
// create block bodies request
req := &GetBlockBodies{s.chain.blocks[54].Hash(), s.chain.blocks[75].Hash()}
if err := conn.Write(req); err != nil {
t.Fatalf("could not write to connection: %v", err)
}
timeout := 20 * time.Second
switch msg := conn.ReadAndServe(s.chain, timeout).(type) {
case *BlockBodies:
t.Logf("received %d block bodies", len(*msg))
default:
t.Fatalf("unexpected: %s", pretty.Sdump(msg))
}
}
// TestBroadcast tests whether a block announcement is correctly
// propagated to the given node's peer(s).
func (s *Suite) TestBroadcast(t *utesting.T) {
// create conn to send block announcement
sendConn, err := s.dial()
if err != nil {
t.Fatalf("could not dial: %v", err)
}
// create conn to receive block announcement
receiveConn, err := s.dial()
if err != nil {
t.Fatalf("could not dial: %v", err)
}
sendConn.handshake(t)
receiveConn.handshake(t)
sendConn.statusExchange(t, s.chain)
receiveConn.statusExchange(t, s.chain)
// sendConn sends the block announcement
blockAnnouncement := &NewBlock{
Block: s.fullChain.blocks[1000],
TD: s.fullChain.TD(1001),
}
if err := sendConn.Write(blockAnnouncement); err != nil {
t.Fatalf("could not write to connection: %v", err)
}
timeout := 20 * time.Second
switch msg := receiveConn.ReadAndServe(s.chain, timeout).(type) {
case *NewBlock:
t.Logf("received NewBlock message: %s", pretty.Sdump(msg.Block))
assert.Equal(t,
blockAnnouncement.Block.Header(), msg.Block.Header(),
"wrong block header in announcement",
)
assert.Equal(t,
blockAnnouncement.TD, msg.TD,
"wrong TD in announcement",
)
case *NewBlockHashes:
hashes := *msg
t.Logf("received NewBlockHashes message: %s", pretty.Sdump(hashes))
assert.Equal(t,
blockAnnouncement.Block.Hash(), hashes[0].Hash,
"wrong block hash in announcement",
)
default:
t.Fatalf("unexpected: %s", pretty.Sdump(msg))
}
// update test suite chain
s.chain.blocks = append(s.chain.blocks, s.fullChain.blocks[1000])
// wait for client to update its chain
if err := receiveConn.waitForBlock(s.chain.Head()); err != nil {
t.Fatal(err)
}
}
// dial attempts to dial the given node and perform a handshake,
// returning the created Conn if successful.
func (s *Suite) dial() (*Conn, error) {
var conn Conn
fd, err := net.Dial("tcp", fmt.Sprintf("%v:%d", s.Dest.IP(), s.Dest.TCP()))
if err != nil {
return nil, err
}
conn.Conn = rlpx.NewConn(fd, s.Dest.Pubkey())
// do encHandshake
conn.ourKey, _ = crypto.GenerateKey()
_, err = conn.Handshake(conn.ourKey)
if err != nil {
return nil, err
}
return &conn, nil
}

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,26 @@
{
"config": {
"chainId": 19763,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"ethash": {}
},
"nonce": "0xdeadbeefdeadbeef",
"timestamp": "0x0",
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x80000000",
"difficulty": "0x20000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"71562b71999873db5b286df957af199ec94617f7": {
"balance": "0xffffffff"
}
},
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more