diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml deleted file mode 100644 index a25bc11f3d..0000000000 --- a/.github/workflows/golangci-lint.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: golangci-lint -on: - pull_request: - branches: '*' -jobs: - golangci: - name: lint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - - name: make - run: bash ./build/build_deps.sh - - - name: golangci-lint - uses: golangci/golangci-lint-action@v2 - with: - version: v1.29 - args: --no-config --issues-exit-code=0 --timeout=30m --tests=false --skip-dirs="tests" --skip-dirs-use-default=true --disable-all --enable=govet --enable=misspell --enable=goconst --enable=gofmt --enable=goimports --enable=gosec --enable=unconvert --enable=unparam --enable=funlen \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000000..343b398b64 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,32 @@ +name: golangci-lint +on: + pull_request: + branches: '**' +jobs: + golangci: + name: lint + runs-on: ubuntu-latest + steps: + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: ^1.16 + id: go + + - uses: actions/checkout@v2 + + - name: make + run: bash ./build/build_deps.sh + + - name: Get dependencies + run : | + go mod download + + - name: golangci-lint + uses: golangci/golangci-lint-action@v2 + with: + version: 'latest' + args: --no-config --issues-exit-code=0 --timeout=30m --tests=false --skip-dirs="tests" --skip-dirs-use-default=true --disable-all --enable=misspell --enable=goconst --enable=gofmt --enable=goimports --enable=gosec --enable=unconvert --enable=unparam --enable=funlen + skip-go-installation: true + skip-pkg-cache: true diff --git a/.github/workflows/test.yml b/.github/workflows/unit_test.yml similarity index 65% rename from .github/workflows/test.yml rename to .github/workflows/unit_test.yml index 07216f1ffe..c3cef9b092 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/unit_test.yml @@ -1,8 +1,8 @@ -name: Go +name: unittest on: pull_request: - branches: '*' + branches: '**' env: GO111MODULE: on jobs: @@ -14,13 +14,13 @@ jobs: - name: Set up Go 1.x uses: actions/setup-go@v2 with: - go-version: ^1.13 + go-version: ^1.15 id: go - name: Check out code into the Go module directory uses: actions/checkout@v2 - - uses: actions/cache@v1 + - uses: actions/cache@v2 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} @@ -28,11 +28,17 @@ jobs: ${{ runner.os }}-go- - name: Get dependencies run: | - go get -v -t -d ./... - + go mod download - name: Build run: make alaya - name: Test - run: go test -tags=test -covermode=count -coverprofile=coverage.out `go list ./...|grep -v life|grep -v swarm|grep -v tests|grep -v bn256|grep -v mobile` \ No newline at end of file + run: go test -tags=test -covermode=count -coverprofile=coverage.txt `go list ./...` + + - name: Upload coverage report + uses: codecov/codecov-action@v1 + with: + file: ./coverage.txt + flags: unittests + name: codecov-umbrella diff --git a/AUTHORS b/AUTHORS index 486c71095d..7ea12c02ef 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,6 +1,7 @@ -# This is the official list of PlatON-Go authors for copyright purposes. +# This is the official list of Alaya-Go authors for copyright purposes. Gavin +GavinXu GavinXu520 James QU Joey @@ -15,6 +16,7 @@ alliswell awake benbaley <45843736+benbaley@users.noreply.github.com> bglmmz +bglmmz caiguopei chenfeixiang chenfeixiang @@ -22,23 +24,30 @@ chinese-wu <1102252651@qq.com> chinese-wu <41734952+chinese-wu@users.noreply.github.com> clearly <910372762@qq.com> gavin +guodeng <905825932@qq.com> jianghaitao@192.168.10.68 joey +kongwei <55940531+kw805@users.noreply.github.com> liuzhiqiang luo-dahui <934803813@qq.com> +luodahui <934803813@qq.com> luodahui luowei +luowei lvxiaoyi lvxiaoyi mowind niuxiaojie81 <30611384+niuxiaojie81@users.noreply.github.com> +niuxiaojie81 <85773309@qq.com> simonhsj simonhsj simonhsj@gmail.com wutao <1102252651@qq.com> wuwei +xujiacan yangzhou zhuying520 zjsunzone 姜海涛 +张军 程林 diff --git a/Dockerfile b/Dockerfile index 078b6487c6..fcbb59f875 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,8 +36,8 @@ ENV P2PPORT=16789 ENV WSPORT=6080 ENV RPCPORT=6789 ENV PPROFPORT=6060 -ENV MAXPEERS=43 -ENV MAXCONSENSUSPEERS=100 +ENV MAXPEERS=80 +ENV MAXCONSENSUSPEERS=75 ENV ENABLE_LIGHT_SRV=false ENV SYNCMODE=full diff --git a/Dockerfile.alltools b/Dockerfile.alltools index e984a1b092..39bb144c98 100644 --- a/Dockerfile.alltools +++ b/Dockerfile.alltools @@ -1,15 +1,46 @@ -# Build Geth in a stock Go builder container -FROM golang:1.11-alpine as builder +# Build Alaya in a stock Go builder container +FROM golang:1.15-alpine as builder -RUN apk add --no-cache make gcc musl-dev linux-headers +RUN apk add --no-cache make gcc musl-dev linux-headers g++ llvm bash cmake git gmp-dev openssl-dev -ADD . /go-ethereum -RUN cd /go-ethereum && make all +RUN git clone https://github.com/dfinity/bn.git +RUN cd bn && make && make install -# Pull all binaries into a second stage deploy alpine container +ADD . /Alaya-Go +RUN cd /Alaya-Go && make clean && make alaya + +# Pull Alaya into a second stage deploy alpine container FROM alpine:latest -RUN apk add --no-cache ca-certificates -COPY --from=builder /go-ethereum/build/bin/* /usr/local/bin/ +RUN apk add --no-cache ca-certificates libstdc++ bash tzdata gmp-dev +COPY --from=builder /Alaya-Go/build/bin/* /usr/local/bin/ +COPY --from=builder /Alaya-Go/entrypoint.sh /usr/local/bin/ +COPY --from=builder /usr/local/lib/libbls384.so /usr/local/lib/ +COPY --from=builder /usr/local/lib/libmcl.so /usr/local/lib/ +RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime + +ENV ENABLE_DEBUG=false +ENV ENABLE_PPROF=false +ENV ENABLE_WS=false +ENV WSAPI= +ENV ENABLE_RPC=false +ENV RPCAPI= +ENV BOOTNODES= +ENV NEW_ACCOUNT=false +ENV INIT=false +ENV VERBOSITY=3 +ENV ENBALE_DISCOVER=false +ENV ENABLE_V5DISC=false +ENV ENABLE_CBFT_TRACING=false +ENV P2PPORT=16789 +ENV WSPORT=6080 +ENV RPCPORT=6789 +ENV PPROFPORT=6060 +ENV MAXPEERS=80 +ENV MAXCONSENSUSPEERS=75 +ENV ENABLE_LIGHT_SRV=false +ENV SYNCMODE=full -EXPOSE 8545 8546 30303 30303/udp +VOLUME /data/alaya +EXPOSE 6060 6080 6789 16789 16789/udp +ENTRYPOINT ["alaya"] \ No newline at end of file diff --git a/Makefile b/Makefile index 1b6aa61636..6cda9745cc 100644 --- a/Makefile +++ b/Makefile @@ -19,10 +19,6 @@ alaya: @echo "Done building." @echo "Run \"$(GOBIN)/alaya\" to launch alaya." -fix-cbft-test: - build/cbft_test.sh - @echo "Done fix." - alaya-with-mpc: build/build_deps.sh $(GORUN) build/ci.go install -mpc on ./cmd/alaya diff --git a/README.md b/README.md index 0d5ce08ad1..f114115aff 100644 --- a/README.md +++ b/README.md @@ -18,20 +18,20 @@ The requirements to build Alaya-Go are: - [Golang](https://golang.org/doc/install) :version 1.14+ - [cmake](https://cmake.org/) :version 3.0+ - [g++&gcc](http://gcc.gnu.org/) :version 7.4.0+ -> The 'cmake' and 'gcc&g++' are usually included in Ubuntu18.04 +> The 'cmake' and 'gcc&g++' are usually built-in with Ubuntu In addition, the following libraries needs to be installed manually ``` sudo apt install libgmp-dev libssl-dev ``` -Then, clone the repository +Then, clone the repository and download dependency ``` git clone https://github.com/AlayaNetwork/Alaya-Go.git --recursive -``` -Switch to the Alaya-Go repository root directory. +cd Alaya-Go && go mod download +``` Ubuntu: @@ -45,7 +45,7 @@ Windows: go run build\ci.go install ``` -The resulting binary will be placed in '$Alaya-Go/build/bin'(Ubuntu) or in '%GOPATH%\bin'(Windows) . +The resulting binary will be placed in '$Alaya-Go/build/bin' . ## Getting Started @@ -117,7 +117,7 @@ Address: {apt1anp4tzmdggdrcf39qvshfq3glacjxcd5mayaa8} Run the following command to launch a Alaya node connecting to the Alaya's mainnet: ``` -$ ./alaya --identity "alaya" --datadir ./data --port {your-p2p-port} --rpcaddr 127.0.0.1 --rpcport {your-rpc-port} --rpcapi "db,platon,net,web3,admin,personal" --rpc --nodiscover --nodekey ./data/nodekey --cbft.blskey ./data/blskey +alaya --identity "alaya" --datadir ./data --port {your-p2p-port} --rpcaddr 127.0.0.1 --rpcport {your-rpc-port} --rpcapi "db,platon,net,web3,admin,personal" --rpc --nodiscover --nodekey ./data/nodekey --cbft.blskey ./data/blskey ``` OK, it seems that the chain is running correctly, we can check it as follow: diff --git a/accounts/abi/bind/backend.go b/accounts/abi/bind/backend.go index 46a9b84620..e2dbc22c4f 100644 --- a/accounts/abi/bind/backend.go +++ b/accounts/abi/bind/backend.go @@ -21,7 +21,7 @@ import ( "errors" "math/big" - platon "github.com/AlayaNetwork/Alaya-Go" + alaya "github.com/AlayaNetwork/Alaya-Go" "github.com/AlayaNetwork/Alaya-Go/common" "github.com/AlayaNetwork/Alaya-Go/core/types" ) @@ -49,7 +49,7 @@ type ContractCaller interface { CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) // ContractCall executes an Ethereum contract call with the specified data as the // input. - CallContract(ctx context.Context, call platon.CallMsg, blockNumber *big.Int) ([]byte, error) + CallContract(ctx context.Context, call alaya.CallMsg, blockNumber *big.Int) ([]byte, error) } // PendingContractCaller defines methods to perform contract calls on the pending state. @@ -59,7 +59,7 @@ type PendingContractCaller interface { // PendingCodeAt returns the code of the given account in the pending state. PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) // PendingCallContract executes an Ethereum contract call against the pending state. - PendingCallContract(ctx context.Context, call platon.CallMsg) ([]byte, error) + PendingCallContract(ctx context.Context, call alaya.CallMsg) ([]byte, error) } // ContractTransactor defines the methods needed to allow operating with contract @@ -79,7 +79,7 @@ type ContractTransactor interface { // There is no guarantee that this is the true gas limit requirement as other // transactions may be added or removed by miners, but it should provide a basis // for setting a reasonable default. - EstimateGas(ctx context.Context, call platon.CallMsg) (gas uint64, err error) + EstimateGas(ctx context.Context, call alaya.CallMsg) (gas uint64, err error) // SendTransaction injects the transaction into the pending pool for execution. SendTransaction(ctx context.Context, tx *types.Transaction) error } @@ -91,11 +91,11 @@ type ContractFilterer interface { // returning all the results in one batch. // // TODO(karalabe): Deprecate when the subscription one can return past data too. - FilterLogs(ctx context.Context, query platon.FilterQuery) ([]types.Log, error) + FilterLogs(ctx context.Context, query alaya.FilterQuery) ([]types.Log, error) // SubscribeFilterLogs creates a background log filtering operation, returning // a subscription immediately, which can be used to stream the found events. - SubscribeFilterLogs(ctx context.Context, query platon.FilterQuery, ch chan<- types.Log) (platon.Subscription, error) + SubscribeFilterLogs(ctx context.Context, query alaya.FilterQuery, ch chan<- types.Log) (alaya.Subscription, error) } // DeployBackend wraps the operations needed by WaitMined and WaitDeployed. diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index bb12805774..0000000000 --- a/appveyor.yml +++ /dev/null @@ -1,40 +0,0 @@ -os: Visual Studio 2015 - -# Clone directly into GOPATH. -clone_folder: C:\gopath\src\github.com\PlatONnetwork\PlatON-Go -clone_depth: 5 -version: "{branch}.{build}" -environment: - global: - GOPATH: C:\gopath - CC: gcc.exe - matrix: - - GETH_ARCH: amd64 - MSYS2_ARCH: x86_64 - MSYS2_BITS: 64 - MSYSTEM: MINGW64 - PATH: C:\msys64\mingw64\bin\;C:\Program Files (x86)\NSIS\;%PATH% - - GETH_ARCH: 386 - MSYS2_ARCH: i686 - MSYS2_BITS: 32 - MSYSTEM: MINGW32 - PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% - -install: - - git submodule update --init - - rmdir C:\go /s /q - - appveyor DownloadFile https://storage.googleapis.com/golang/go1.11.windows-%GETH_ARCH%.zip - - 7z x go1.11.windows-%GETH_ARCH%.zip -y -oC:\ > NUL - - go version - - gcc --version - -build_script: - - go run build\ci.go install - -after_build: - - go run build\ci.go archive -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds - - go run build\ci.go nsis -signer WINDOWS_SIGNING_KEY -upload gethstore/builds - -test_script: - - set CGO_ENABLED=1 - - go run build\ci.go test -coverage diff --git a/build/cbft_test.sh b/build/cbft_test.sh index cdb0adc491..0d56a0ec52 100755 --- a/build/cbft_test.sh +++ b/build/cbft_test.sh @@ -8,7 +8,7 @@ if [ ! -f "build/cbft_test.sh" ]; then fi root=`pwd` -hash=$(go test -v -tags=test github.com/PlatONnetwork/PlatON-Go/consensus/cbft -run TestCbft_CreateGenesis | sed -n '2p') +hash=$(go test -v -tags=test github.com/AlayaNetwork/Alaya-Go/consensus/cbft -run TestCbft_CreateGenesis | sed -n '2p') echo "replace root $hash" tmp='Root: common.BytesToHash(hexutil.MustDecode("HASH")),' diff --git a/build/ci.go b/build/ci.go index 491897eaab..eb347bfd06 100644 --- a/build/ci.go +++ b/build/ci.go @@ -92,11 +92,11 @@ var ( }, { BinaryName: "bootnode", - Description: "Ethereum bootnode.", + Description: "Alaya bootnode.", }, { BinaryName: "alaya", - Description: "PlatON CLI client.", + Description: "Alaya CLI client.", }, { BinaryName: "rlpdump", @@ -104,7 +104,7 @@ var ( }, { BinaryName: "wnode", - Description: "Ethereum Whisper diagnostic tool", + Description: "Alaya Whisper diagnostic tool", }, } diff --git a/circle.yml b/circle.yml deleted file mode 100644 index 371b09e965..0000000000 --- a/circle.yml +++ /dev/null @@ -1,28 +0,0 @@ -machine: - services: - - docker - -dependencies: - cache_directories: - - "~/.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 && hive --docker-noshell --client=NONE --test=. --sim=. --loglevel=6) - - # Cache all the docker images - - for img in `docker images | grep -v "^" | tail -n +2 | awk '{print $1}'`; do docker save $img > ~/.docker/`echo $img | tr '/' ':'`.tar; done - -test: - override: - # Build Geth and move into a known folder - - make alaya - - cp ./build/bin/alaya $HOME/alaya - - # 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/alaya --test=. --sim=.) - - cp -r ~/.go_workspace/src/github.com/karalabe/hive/workspace/logs/* $CIRCLE_ARTIFACTS diff --git a/cmd/alaya/accountcmd_test.go b/cmd/alaya/accountcmd_test.go index dde9672d91..5ba02d90a2 100644 --- a/cmd/alaya/accountcmd_test.go +++ b/cmd/alaya/accountcmd_test.go @@ -109,7 +109,7 @@ Repeat passphrase: {{.InputLine "foobar2"}} func TestUnlockFlag(t *testing.T) { datadir := tmpDatadirWithKeystore(t) platon := runPlatON(t, - "--datadir", datadir, "--ipcdisable", "--alaya", "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0", + "--datadir", datadir, "--ipcdisable", "--alaya", "--nat", "none", "--nodiscover", "--maxpeers", "60", "--port", "0", "--unlock", "atp10m66vy6lrlt2qfvnamwgd8rdg8vnfthc5grew9", "js", "testdata/empty.js") platon.Expect(` @@ -133,7 +133,7 @@ Passphrase: {{.InputLine "foobar"}} func TestUnlockFlagWrongPassword(t *testing.T) { datadir := tmpDatadirWithKeystore(t) platon := runPlatON(t, - "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0", "--ipcdisable", "--alaya", + "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "60", "--port", "0", "--ipcdisable", "--alaya", "--unlock", "atp173ngt84dryedws7kyt9hflq93zpwsey2zecc74") defer platon.ExpectExit() platon.Expect(` @@ -152,7 +152,7 @@ Fatal: Failed to unlock account atp173ngt84dryedws7kyt9hflq93zpwsey2zecc74 (coul func TestUnlockFlagMultiIndex(t *testing.T) { datadir := tmpDatadirWithKeystore(t) platon := runPlatON(t, - "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0", "--ipcdisable", "--alaya", + "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "60", "--port", "0", "--ipcdisable", "--alaya", "--unlock", "0,2", "js", "testdata/empty.js") platon.Expect(` @@ -179,7 +179,7 @@ Passphrase: {{.InputLine "foobar"}} func TestUnlockFlagPasswordFile(t *testing.T) { datadir := tmpDatadirWithKeystore(t) platon := runPlatON(t, - "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0", + "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "60", "--port", "0", "--password", "testdata/passwords.txt", "--unlock", "0,2", "--ipcdisable", "--alaya", "js", "testdata/empty.js") platon.ExpectExit() @@ -199,7 +199,7 @@ func TestUnlockFlagPasswordFile(t *testing.T) { func TestUnlockFlagPasswordFileWrongPassword(t *testing.T) { datadir := tmpDatadirWithKeystore(t) platon := runPlatON(t, - "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0", "--ipcdisable", "--alaya", + "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "60", "--port", "0", "--ipcdisable", "--alaya", "--password", "testdata/wrong-passwords.txt", "--unlock", "0,2") defer platon.ExpectExit() platon.Expect(` @@ -210,7 +210,7 @@ Fatal: Failed to unlock account 0 (could not decrypt key with given passphrase) func TestUnlockFlagAmbiguous(t *testing.T) { store := filepath.Join("..", "..", "accounts", "keystore", "testdata", "dupes") platon := runPlatON(t, - "--keystore", store, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0", "--ipcdisable", "--alaya", + "--keystore", store, "--nat", "none", "--nodiscover", "--maxpeers", "60", "--port", "0", "--ipcdisable", "--alaya", "--unlock", "atp173ngt84dryedws7kyt9hflq93zpwsey2zecc74", "js", "testdata/empty.js") defer platon.ExpectExit() @@ -248,7 +248,7 @@ In order to avoid this warning, you need to remove the following duplicate key f func TestUnlockFlagAmbiguousWrongPassword(t *testing.T) { store := filepath.Join("..", "..", "accounts", "keystore", "testdata", "dupes") platon := runPlatON(t, - "--keystore", store, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0", "--ipcdisable", "--alaya", + "--keystore", store, "--nat", "none", "--nodiscover", "--maxpeers", "60", "--port", "0", "--ipcdisable", "--alaya", "--unlock", "atp173ngt84dryedws7kyt9hflq93zpwsey2zecc74") defer platon.ExpectExit() diff --git a/cmd/alaya/chaincmd.go b/cmd/alaya/chaincmd.go index 713a5c0637..3c73949a1d 100644 --- a/cmd/alaya/chaincmd.go +++ b/cmd/alaya/chaincmd.go @@ -22,8 +22,6 @@ import ( "github.com/AlayaNetwork/Alaya-Go/core/rawdb" - "github.com/AlayaNetwork/Alaya-Go/core/vm" - "os" "runtime" "strconv" @@ -140,7 +138,7 @@ The export-preimages command export hash preimages to an RLP encoded stream`, utils.DataDirFlag, utils.CacheFlag, // utils.SyncModeFlag, - utils.TestnetFlag, + utils.AlayaNetFlag, }, Category: "BLOCKCHAIN COMMANDS", Description: ` @@ -273,7 +271,7 @@ func importChain(ctx *cli.Context) error { StaleThreshold: config.StaleThreshold, DefaultCommitRatio: config.DefaultCommitRatio, } - miner := miner.New(bc, chain.Config(), minningConfig, &vm.Config{}, stack.EventMux(), c, platonConfig.Eth.MinerRecommit, platonConfig.Eth.MinerGasFloor, nil, blockChainCache, platonConfig.Eth.VmTimeoutDuration) + miner := miner.New(bc, chain.Config(), minningConfig, stack.EventMux(), c, platonConfig.Eth.MinerRecommit, platonConfig.Eth.MinerGasFloor, nil, blockChainCache, platonConfig.Eth.VmTimeoutDuration) c.Start(chain, nil, nil, agency) defer c.Close() defer miner.Stop() diff --git a/cmd/alaya/consolecmd.go b/cmd/alaya/consolecmd.go index 483549589c..f2da2206d3 100644 --- a/cmd/alaya/consolecmd.go +++ b/cmd/alaya/consolecmd.go @@ -124,13 +124,7 @@ func remoteConsole(ctx *cli.Context) error { path = ctx.GlobalString(utils.DataDirFlag.Name) } if path != "" { - if ctx.GlobalBool(utils.TestnetFlag.Name) { - path = filepath.Join(path, "testnet") - } else if ctx.GlobalBool(utils.AlayaNetFlag.Name) { - path = filepath.Join(path, "alayanet") - } else if ctx.GlobalBool(utils.AlayaTestNetFlag.Name) { - path = filepath.Join(path, "alayatestnet") - } + path = filepath.Join(path, "alayanet") } endpoint = fmt.Sprintf("%s/alaya.ipc", path) } diff --git a/cmd/alaya/consolecmd_test.go b/cmd/alaya/consolecmd_test.go index d037674483..16d5d18ce0 100644 --- a/cmd/alaya/consolecmd_test.go +++ b/cmd/alaya/consolecmd_test.go @@ -41,7 +41,7 @@ func TestConsoleWelcome(t *testing.T) { datadir := tmpdir(t) defer os.RemoveAll(datadir) platon := runPlatON(t, - "--datadir", datadir, "--port", "0", "--ipcdisable", "--alaya", "--maxpeers", "0", "--nodiscover", "--nat", "none", "console") + "--datadir", datadir, "--port", "0", "--ipcdisable", "--alaya", "--maxpeers", "60", "--nodiscover", "--nat", "none", "console") // Gather all the infos the welcome message needs to contain platon.SetTemplateFunc("goos", func() string { return runtime.GOOS }) @@ -78,7 +78,7 @@ func TestIPCAttachWelcome(t *testing.T) { ipc = filepath.Join(ws, "platon.ipc") } platon := runPlatON(t, - "--port", "0", "--alaya", "--maxpeers", "0", "--nodiscover", "--nat", "none", "--ipcpath", ipc) + "--port", "0", "--alaya", "--maxpeers", "60", "--nodiscover", "--nat", "none", "--ipcpath", ipc) time.Sleep(2 * time.Second) // Simple way to wait for the RPC endpoint to open testAttachWelcome(t, platon, "ipc:"+ipc, ipcAPIs) @@ -90,7 +90,7 @@ func TestIPCAttachWelcome(t *testing.T) { func TestHTTPAttachWelcome(t *testing.T) { port := strconv.Itoa(trulyRandInt(1024, 65536)) // Yeah, sometimes this will fail, sorry :P platon := runPlatON(t, - "--port", "0", "--ipcdisable", "--alaya", "--maxpeers", "0", "--nodiscover", "--nat", "none", + "--port", "0", "--ipcdisable", "--alaya", "--maxpeers", "60", "--nodiscover", "--nat", "none", "--rpc", "--rpcport", port) time.Sleep(2 * time.Second) // Simple way to wait for the RPC endpoint to open @@ -104,7 +104,7 @@ func TestWSAttachWelcome(t *testing.T) { port := strconv.Itoa(trulyRandInt(1024, 65536)) // Yeah, sometimes this will fail, sorry :P platon := runPlatON(t, - "--port", "0", "--ipcdisable", "--alaya", "--maxpeers", "0", "--nodiscover", "--nat", "none", + "--port", "0", "--ipcdisable", "--alaya", "--maxpeers", "60", "--nodiscover", "--nat", "none", "--ws", "--wsport", port /*, "--testnet"*/) time.Sleep(2 * time.Second) // Simple way to wait for the RPC endpoint to open diff --git a/cmd/alaya/genesis_test.go b/cmd/alaya/genesis_test.go index 169be0f0a6..8f3da9298c 100644 --- a/cmd/alaya/genesis_test.go +++ b/cmd/alaya/genesis_test.go @@ -266,7 +266,7 @@ func TestCustomGenesis(t *testing.T) { // Query the custom genesis block platon := runPlatON(t, - "--datadir", datadir, "--maxpeers", "0", "--port", "0", + "--datadir", datadir, "--maxpeers", "60", "--port", "0", "--nodiscover", "--nat", "none", "--ipcdisable", "--alaya", "--exec", tt.query, "console") t.Log("testi", i) diff --git a/cmd/alaya/main.go b/cmd/alaya/main.go index 42e8728d4a..3a80722a00 100644 --- a/cmd/alaya/main.go +++ b/cmd/alaya/main.go @@ -47,7 +47,7 @@ import ( ) const ( - clientIdentifier = "alaya" // Client identifier to advertise over the network + clientIdentifier = "platon" // Client identifier to advertise over the network ) var ( @@ -102,10 +102,7 @@ var ( utils.NodeKeyFileFlag, utils.NodeKeyHexFlag, utils.DeveloperPeriodFlag, - utils.MainFlag, - utils.TestnetFlag, utils.AlayaNetFlag, - utils.AlayaTestNetFlag, utils.NetworkIdFlag, utils.RPCCORSDomainFlag, utils.RPCVirtualHostsFlag, diff --git a/cmd/alaya/misccmd.go b/cmd/alaya/misccmd.go index 28a063554e..b3147f982a 100644 --- a/cmd/alaya/misccmd.go +++ b/cmd/alaya/misccmd.go @@ -47,7 +47,7 @@ The output of this command is supposed to be machine-readable. ) func version(ctx *cli.Context) error { - fmt.Println("PlatON") + fmt.Println("Alaya") fmt.Println("Version:", params.VersionWithMeta) if gitCommit != "" { fmt.Println("Git Commit:", gitCommit) diff --git a/cmd/alaya/run_test.go b/cmd/alaya/run_test.go index cde4409767..be863be885 100644 --- a/cmd/alaya/run_test.go +++ b/cmd/alaya/run_test.go @@ -76,7 +76,7 @@ func runPlatON(t *testing.T, args ...string) *testplaton { if tt.Datadir == "" { tt.Datadir = tmpdir(t) tt.Cleanup = func() { os.RemoveAll(tt.Datadir) } - args = append([]string{"-datadir", tt.Datadir}, args...) + args = append([]string{"--datadir", tt.Datadir}, args...) // Remove the temporary datadir if something fails below. defer func() { if t.Failed() { diff --git a/cmd/alaya/usage.go b/cmd/alaya/usage.go index 32209b3843..9418ea17e9 100644 --- a/cmd/alaya/usage.go +++ b/cmd/alaya/usage.go @@ -64,17 +64,14 @@ type flagGroup struct { // AppHelpFlagGroups is the application flags, grouped by functionality. var AppHelpFlagGroups = []flagGroup{ { - Name: "PLATON", + Name: "ALAYA", Flags: []cli.Flag{ configFileFlag, utils.DataDirFlag, utils.KeyStoreDirFlag, utils.NoUSBFlag, utils.NetworkIdFlag, - utils.MainFlag, - utils.TestnetFlag, utils.AlayaNetFlag, - utils.AlayaTestNetFlag, utils.SyncModeFlag, // utils.EthStatsURLFlag, utils.IdentityFlag, diff --git a/cmd/alayakey/genblskeypair.go b/cmd/alayakey/genblskeypair.go index b634cd33d3..a9675ca634 100644 --- a/cmd/alayakey/genblskeypair.go +++ b/cmd/alayakey/genblskeypair.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/cmd/alayakey/genkeypair.go b/cmd/alayakey/genkeypair.go index bfe5bbc1d2..7179df2dc1 100644 --- a/cmd/alayakey/genkeypair.go +++ b/cmd/alayakey/genkeypair.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/cmd/ctool/core/bytes_util.go b/cmd/ctool/core/bytes_util.go index 62c2dc4663..833fedbf97 100644 --- a/cmd/ctool/core/bytes_util.go +++ b/cmd/ctool/core/bytes_util.go @@ -1,18 +1,19 @@ -// Copyright 2018-2020 The PlatON Network Authors -// This file is part of the Alaya-Go library. +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. // -// The Alaya-Go 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 +// Alaya-Go 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. // -// The Alaya-Go library is distributed in the hope that it will be useful, +// Alaya-Go 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. +// GNU General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public License -// along with the Alaya-Go library. If not, see . +// You should have received a copy of the GNU General Public License +// along with Alaya-Go. If not, see . + package core diff --git a/cmd/ctool/core/bytes_utils_test.go b/cmd/ctool/core/bytes_utils_test.go index 2c4ca13fa3..8d871767bf 100644 --- a/cmd/ctool/core/bytes_utils_test.go +++ b/cmd/ctool/core/bytes_utils_test.go @@ -1,18 +1,19 @@ -// Copyright 2018-2020 The PlatON Network Authors -// This file is part of the Alaya-Go library. +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. // -// The Alaya-Go 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 +// Alaya-Go 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. // -// The Alaya-Go library is distributed in the hope that it will be useful, +// Alaya-Go 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. +// GNU General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public License -// along with the Alaya-Go library. If not, see . +// You should have received a copy of the GNU General Public License +// along with Alaya-Go. If not, see . + package core diff --git a/cmd/ctool/core/contractcmd.go b/cmd/ctool/core/contractcmd.go index 793e5b3335..a097d33b20 100644 --- a/cmd/ctool/core/contractcmd.go +++ b/cmd/ctool/core/contractcmd.go @@ -1,18 +1,19 @@ -// Copyright 2018-2020 The PlatON Network Authors -// This file is part of the Alaya-Go library. +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. // -// The Alaya-Go 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 +// Alaya-Go 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. // -// The Alaya-Go library is distributed in the hope that it will be useful, +// Alaya-Go 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. +// GNU General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public License -// along with the Alaya-Go library. If not, see . +// You should have received a copy of the GNU General Public License +// along with Alaya-Go. If not, see . + package core diff --git a/cmd/ctool/core/flags.go b/cmd/ctool/core/flags.go index b5a630fc7b..69ce079eee 100644 --- a/cmd/ctool/core/flags.go +++ b/cmd/ctool/core/flags.go @@ -1,18 +1,19 @@ -// Copyright 2018-2020 The PlatON Network Authors -// This file is part of the Alaya-Go library. +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. // -// The Alaya-Go 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 +// Alaya-Go 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. // -// The Alaya-Go library is distributed in the hope that it will be useful, +// Alaya-Go 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. +// GNU General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public License -// along with the Alaya-Go library. If not, see . +// You should have received a copy of the GNU General Public License +// along with Alaya-Go. If not, see . + package core @@ -87,6 +88,21 @@ var ( Usage: "transfer value", } + TxStressSourceFilesPathFlag = cli.StringSliceFlag{ + Name: "sourceFile", + Usage: "the tps source file path", + } + + TxStressStatisticTimeFlag = cli.IntFlag{ + Name: "statisticTime", + Usage: "Statistics every few seconds", + } + + TxStressOutPutFileFlag = cli.StringFlag{ + Name: "output", + Usage: "the output file path", + } + deployCmdFlags = []cli.Flag{ ContractWasmFilePathFlag, ContractAbiFilePathFlag, @@ -130,4 +146,9 @@ var ( TransferValueFlag, ConfigPathFlag, } + txStressFlags = []cli.Flag{ + TxStressSourceFilesPathFlag, + TxStressStatisticTimeFlag, + TxStressOutPutFileFlag, + } ) diff --git a/cmd/ctool/core/http_util.go b/cmd/ctool/core/http_util.go index 8a78f6191e..60e47a4d5b 100644 --- a/cmd/ctool/core/http_util.go +++ b/cmd/ctool/core/http_util.go @@ -1,18 +1,19 @@ -// Copyright 2018-2020 The PlatON Network Authors -// This file is part of the Alaya-Go library. +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. // -// The Alaya-Go 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 +// Alaya-Go 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. // -// The Alaya-Go library is distributed in the hope that it will be useful, +// Alaya-Go 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. +// GNU General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public License -// along with the Alaya-Go library. If not, see . +// You should have received a copy of the GNU General Public License +// along with Alaya-Go. If not, see . + package core diff --git a/cmd/ctool/core/http_util_test.go b/cmd/ctool/core/http_util_test.go index 9b1690b130..a9c30f8283 100644 --- a/cmd/ctool/core/http_util_test.go +++ b/cmd/ctool/core/http_util_test.go @@ -1,18 +1,19 @@ -// Copyright 2018-2020 The PlatON Network Authors -// This file is part of the Alaya-Go library. +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. // -// The Alaya-Go 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 +// Alaya-Go 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. // -// The Alaya-Go library is distributed in the hope that it will be useful, +// Alaya-Go 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. +// GNU General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public License -// along with the Alaya-Go library. If not, see . +// You should have received a copy of the GNU General Public License +// along with Alaya-Go. If not, see . + package core diff --git a/cmd/ctool/core/nodeUtil.go b/cmd/ctool/core/nodeUtil.go index ee556f435f..4f4e9a8ca1 100644 --- a/cmd/ctool/core/nodeUtil.go +++ b/cmd/ctool/core/nodeUtil.go @@ -1,18 +1,19 @@ -// Copyright 2018-2020 The PlatON Network Authors -// This file is part of the Alaya-Go library. +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. // -// The Alaya-Go 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 +// Alaya-Go 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. // -// The Alaya-Go library is distributed in the hope that it will be useful, +// Alaya-Go 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. +// GNU General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public License -// along with the Alaya-Go library. If not, see . +// You should have received a copy of the GNU General Public License +// along with Alaya-Go. If not, see . + package core diff --git a/cmd/ctool/core/transactioncmd.go b/cmd/ctool/core/transactioncmd.go index 4449eb5360..e5ff35b3b5 100644 --- a/cmd/ctool/core/transactioncmd.go +++ b/cmd/ctool/core/transactioncmd.go @@ -1,18 +1,19 @@ -// Copyright 2018-2020 The PlatON Network Authors -// This file is part of the Alaya-Go library. +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. // -// The Alaya-Go 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 +// Alaya-Go 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. // -// The Alaya-Go library is distributed in the hope that it will be useful, +// Alaya-Go 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. +// GNU General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public License -// along with the Alaya-Go library. If not, see . +// You should have received a copy of the GNU General Public License +// along with Alaya-Go. If not, see . + package core diff --git a/cmd/ctool/core/transactioncmd_test.go b/cmd/ctool/core/transactioncmd_test.go index 199144a2fe..42f9cf3910 100644 --- a/cmd/ctool/core/transactioncmd_test.go +++ b/cmd/ctool/core/transactioncmd_test.go @@ -1,18 +1,19 @@ -// Copyright 2018-2020 The PlatON Network Authors -// This file is part of the Alaya-Go library. +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. // -// The Alaya-Go 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 +// Alaya-Go 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. // -// The Alaya-Go library is distributed in the hope that it will be useful, +// Alaya-Go 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. +// GNU General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public License -// along with the Alaya-Go library. If not, see . +// You should have received a copy of the GNU General Public License +// along with Alaya-Go. If not, see . + package core diff --git a/cmd/ctool/core/tx_stability.go b/cmd/ctool/core/tx_stability.go index fe4b77ce55..847106d6aa 100644 --- a/cmd/ctool/core/tx_stability.go +++ b/cmd/ctool/core/tx_stability.go @@ -1,18 +1,19 @@ -// Copyright 2018-2020 The PlatON Network Authors -// This file is part of the Alaya-Go library. +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. // -// The Alaya-Go 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 +// Alaya-Go 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. // -// The Alaya-Go library is distributed in the hope that it will be useful, +// Alaya-Go 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. +// GNU General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public License -// along with the Alaya-Go library. If not, see . +// You should have received a copy of the GNU General Public License +// along with Alaya-Go. If not, see . + package core diff --git a/cmd/ctool/core/tx_stability_test.go b/cmd/ctool/core/tx_stability_test.go index 801443c782..d2ec6248a2 100644 --- a/cmd/ctool/core/tx_stability_test.go +++ b/cmd/ctool/core/tx_stability_test.go @@ -1,18 +1,19 @@ -// Copyright 2018-2020 The PlatON Network Authors -// This file is part of the Alaya-Go library. +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. // -// The Alaya-Go 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 +// Alaya-Go 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. // -// The Alaya-Go library is distributed in the hope that it will be useful, +// Alaya-Go 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. +// GNU General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public License -// along with the Alaya-Go library. If not, see . +// You should have received a copy of the GNU General Public License +// along with Alaya-Go. If not, see . + package core diff --git a/cmd/ctool/core/tx_stress .go b/cmd/ctool/core/tx_stress .go new file mode 100644 index 0000000000..e12419caa7 --- /dev/null +++ b/cmd/ctool/core/tx_stress .go @@ -0,0 +1,39 @@ +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. +// +// Alaya-Go 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. +// +// Alaya-Go 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 Alaya-Go. If not, see . + +package core + +import ( + "github.com/AlayaNetwork/Alaya-Go/eth" + + "gopkg.in/urfave/cli.v1" +) + +var ( + AnalyzeStressTestCmd = cli.Command{ + Name: "analyzeStressTest", + Usage: "analyze the tx stress test source file to generate result data", + Action: analyzeStressTest, + Flags: txStressFlags, + } +) + +func analyzeStressTest(c *cli.Context) error { + configPaths := c.StringSlice(TxStressSourceFilesPathFlag.Name) + t := c.Int(TxStressStatisticTimeFlag.Name) + output := c.String(TxStressOutPutFileFlag.Name) + return eth.AnalyzeStressTest(configPaths, output, t) +} diff --git a/cmd/ctool/core/utils.go b/cmd/ctool/core/utils.go index 3e319dd498..1cfb229473 100644 --- a/cmd/ctool/core/utils.go +++ b/cmd/ctool/core/utils.go @@ -1,18 +1,19 @@ -// Copyright 2018-2020 The PlatON Network Authors -// This file is part of the Alaya-Go library. +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. // -// The Alaya-Go 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 +// Alaya-Go 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. // -// The Alaya-Go library is distributed in the hope that it will be useful, +// Alaya-Go 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. +// GNU General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public License -// along with the Alaya-Go library. If not, see . +// You should have received a copy of the GNU General Public License +// along with Alaya-Go. If not, see . + package core diff --git a/cmd/ctool/core/utils_test.go b/cmd/ctool/core/utils_test.go index d86ba0aacc..314a2329ec 100644 --- a/cmd/ctool/core/utils_test.go +++ b/cmd/ctool/core/utils_test.go @@ -1,18 +1,19 @@ -// Copyright 2018-2020 The PlatON Network Authors -// This file is part of the Alaya-Go library. +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. // -// The Alaya-Go 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 +// Alaya-Go 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. // -// The Alaya-Go library is distributed in the hope that it will be useful, +// Alaya-Go 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. +// GNU General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public License -// along with the Alaya-Go library. If not, see . +// You should have received a copy of the GNU General Public License +// along with Alaya-Go. If not, see . + package core diff --git a/cmd/ctool/main.go b/cmd/ctool/main.go index 621e2941aa..d083e2eea1 100644 --- a/cmd/ctool/main.go +++ b/cmd/ctool/main.go @@ -1,18 +1,19 @@ -// Copyright 2018-2020 The PlatON Network Authors -// This file is part of the Alaya-Go library. +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. // -// The Alaya-Go 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 +// Alaya-Go 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. // -// The Alaya-Go library is distributed in the hope that it will be useful, +// Alaya-Go 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. +// GNU General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public License -// along with the Alaya-Go library. If not, see . +// You should have received a copy of the GNU General Public License +// along with Alaya-Go. If not, see . + package main @@ -44,6 +45,7 @@ func init() { core.GetTxReceiptCmd, core.StabilityCmd, core.StabPrepareCmd, + core.AnalyzeStressTestCmd, ppos.GovCmd, ppos.SlashingCmd, ppos.StakingCmd, diff --git a/cmd/ctool/ppos/common.go b/cmd/ctool/ppos/common.go index 9574d6badd..419c106c26 100644 --- a/cmd/ctool/ppos/common.go +++ b/cmd/ctool/ppos/common.go @@ -1,3 +1,19 @@ +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. +// +// Alaya-Go 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. +// +// Alaya-Go 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 Alaya-Go. If not, see . + package ppos import ( diff --git a/cmd/ctool/ppos/flag.go b/cmd/ctool/ppos/flag.go index ed04ad58d8..711a427374 100644 --- a/cmd/ctool/ppos/flag.go +++ b/cmd/ctool/ppos/flag.go @@ -1,3 +1,19 @@ +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. +// +// Alaya-Go 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. +// +// Alaya-Go 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 Alaya-Go. If not, see . + package ppos import "gopkg.in/urfave/cli.v1" diff --git a/cmd/ctool/ppos/gov.go b/cmd/ctool/ppos/gov.go index 357ecd09f9..40a1ff989d 100644 --- a/cmd/ctool/ppos/gov.go +++ b/cmd/ctool/ppos/gov.go @@ -1,3 +1,19 @@ +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. +// +// Alaya-Go 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. +// +// Alaya-Go 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 Alaya-Go. If not, see . + package ppos import ( diff --git a/cmd/ctool/ppos/restricting.go b/cmd/ctool/ppos/restricting.go index 4767af7f36..5b242151a0 100644 --- a/cmd/ctool/ppos/restricting.go +++ b/cmd/ctool/ppos/restricting.go @@ -1,3 +1,19 @@ +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. +// +// Alaya-Go 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. +// +// Alaya-Go 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 Alaya-Go. If not, see . + package ppos import ( diff --git a/cmd/ctool/ppos/reward.go b/cmd/ctool/ppos/reward.go index 4756fa85c3..6bba3541fd 100644 --- a/cmd/ctool/ppos/reward.go +++ b/cmd/ctool/ppos/reward.go @@ -1,3 +1,19 @@ +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. +// +// Alaya-Go 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. +// +// Alaya-Go 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 Alaya-Go. If not, see . + package ppos import ( diff --git a/cmd/ctool/ppos/slashing.go b/cmd/ctool/ppos/slashing.go index d9f4b55c53..fe7f2198d9 100644 --- a/cmd/ctool/ppos/slashing.go +++ b/cmd/ctool/ppos/slashing.go @@ -1,3 +1,19 @@ +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. +// +// Alaya-Go 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. +// +// Alaya-Go 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 Alaya-Go. If not, see . + package ppos import ( diff --git a/cmd/ctool/ppos/staking.go b/cmd/ctool/ppos/staking.go index 0d6fb6603f..4bc6d5d681 100644 --- a/cmd/ctool/ppos/staking.go +++ b/cmd/ctool/ppos/staking.go @@ -1,3 +1,19 @@ +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. +// +// Alaya-Go 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. +// +// Alaya-Go 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 Alaya-Go. If not, see . + package ppos import ( @@ -49,7 +65,7 @@ var ( } getRelatedListByDelAddrCmd = cli.Command{ Name: "getRelatedListByDelAddr", - Usage: "1103,Query the NodeID and pledge Id of the node entrusted by the current account address,parameter:add", + Usage: "1103,Query the NodeID and staking Id of the node entrusted by the current account address,parameter:add", Before: netCheck, Action: getRelatedListByDelAddr, Flags: []cli.Flag{rpcUrlFlag, addressHRPFlag, addFlag, jsonFlag}, @@ -63,7 +79,7 @@ var ( } getCandidateInfoCmd = cli.Command{ Name: "getCandidateInfo", - Usage: "1105,Query the pledge information of the current node,parameter:nodeid", + Usage: "1105,Query the staking information of the current node,parameter:nodeid", Before: netCheck, Action: getCandidateInfo, Flags: []cli.Flag{rpcUrlFlag, addressHRPFlag, nodeIdFlag, jsonFlag}, @@ -77,7 +93,7 @@ var ( } getStakingRewardCmd = cli.Command{ Name: "getStakingReward", - Usage: "1201,query the pledge reward of the current settlement epoch", + Usage: "1201,query the staking reward of the current settlement epoch", Before: netCheck, Action: getStakingReward, Flags: []cli.Flag{rpcUrlFlag, addressHRPFlag, jsonFlag}, diff --git a/cmd/ctool/readme.md b/cmd/ctool/readme.md index 4cc6be372c..3eeee6f9b9 100644 --- a/cmd/ctool/readme.md +++ b/cmd/ctool/readme.md @@ -95,11 +95,11 @@ COMMANDS: getVerifierList 1100,query the validator queue of the current settlement epoch getValidatorList 1101,query the list of validators in the current consensus round getCandidateList 1102,Query the list of all real-time candidates - getRelatedListByDelAddr 1103,Query the NodeID and pledge Id of the node entrusted by the current account address,parameter:add + getRelatedListByDelAddr 1103,Query the NodeID and staking Id of the node entrusted by the current account address,parameter:add getDelegateInfo 1104,Query the delegation information of the current single node,parameter:stakingBlock,address,nodeid - getCandidateInfo 1105,Query the pledge information of the current node,parameter:nodeid + getCandidateInfo 1105,Query the staking information of the current node,parameter:nodeid getPackageReward 1200,query the block reward of the current settlement epoch - getStakingReward 1201,query the pledge reward of the current settlement epoch + getStakingReward 1201,query the staking reward of the current settlement epoch getAvgPackTime 1202,average time to query packaged blocks diff --git a/cmd/faucet/faucet.go b/cmd/faucet/faucet.go index 17e22da63e..c0d230be62 100644 --- a/cmd/faucet/faucet.go +++ b/cmd/faucet/faucet.go @@ -215,7 +215,7 @@ type faucet struct { func newFaucet(genesis *core.Genesis, port int, enodes []*discv5.Node, network uint64, stats string, ks *keystore.KeyStore, index []byte) (*faucet, error) { // Assemble the raw devp2p protocol stack stack, err := node.New(&node.Config{ - Name: "alaya", + Name: "platon", Version: params.VersionWithMeta, DataDir: filepath.Join(os.Getenv("HOME"), ".faucet"), P2P: p2p.Config{ diff --git a/cmd/ppos_tool/main.go b/cmd/ppos_tool/main.go index 8cae0ea4b6..111b7a65a1 100644 --- a/cmd/ppos_tool/main.go +++ b/cmd/ppos_tool/main.go @@ -1,18 +1,18 @@ -// Copyright 2018-2020 The PlatON Network Authors -// This file is part of the Alaya-Go library. +// Copyright 2021 The Alaya Network Authors +// This file is part of Alaya-Go. // -// The Alaya-Go 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 +// Alaya-Go 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. // -// The Alaya-Go library is distributed in the hope that it will be useful, +// Alaya-Go 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. +// GNU General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public License -// along with the Alaya-Go library. If not, see . +// You should have received a copy of the GNU General Public License +// along with Alaya-Go. If not, see . package main @@ -89,7 +89,7 @@ type Ppos_1004 struct { Amount *big.Int } -// withdrewDelegate +// withdrewDelegation type Ppos_1005 struct { StakingBlockNum uint64 NodeId discover.NodeID diff --git a/cmd/rlpdump/main.go b/cmd/rlpdump/main.go index 5ee08d1d92..1d8d2fc108 100644 --- a/cmd/rlpdump/main.go +++ b/cmd/rlpdump/main.go @@ -74,39 +74,39 @@ func main() { } stakingErrCode := map[uint32]string{ - staking.ErrWrongBlsPubKey.Code: staking.ErrWrongBlsPubKey.Msg, - staking.ErrWrongBlsPubKeyProof.Code: staking.ErrWrongBlsPubKeyProof.Msg, - staking.ErrDescriptionLen.Code: staking.ErrDescriptionLen.Msg, - staking.ErrWrongProgramVersionSign.Code: staking.ErrWrongProgramVersionSign.Msg, - staking.ErrProgramVersionTooLow.Code: staking.ErrProgramVersionTooLow.Msg, - staking.ErrDeclVsFialedCreateCan.Code: staking.ErrDeclVsFialedCreateCan.Msg, - staking.ErrNoSameStakingAddr.Code: staking.ErrNoSameStakingAddr.Msg, - staking.ErrStakeVonTooLow.Code: staking.ErrStakeVonTooLow.Msg, - staking.ErrCanAlreadyExist.Code: staking.ErrCanAlreadyExist.Msg, - staking.ErrCanNoExist.Code: staking.ErrCanNoExist.Msg, - staking.ErrCanStatusInvalid.Code: staking.ErrCanStatusInvalid.Msg, - staking.ErrIncreaseStakeVonTooLow.Code: staking.ErrIncreaseStakeVonTooLow.Msg, - staking.ErrDelegateVonTooLow.Code: staking.ErrDelegateVonTooLow.Msg, - staking.ErrAccountNoAllowToDelegate.Code: staking.ErrAccountNoAllowToDelegate.Msg, - staking.ErrCanNoAllowDelegate.Code: staking.ErrCanNoAllowDelegate.Msg, - staking.ErrWithdrewDelegateVonTooLow.Code: staking.ErrWithdrewDelegateVonTooLow.Msg, - staking.ErrDelegateNoExist.Code: staking.ErrDelegateNoExist.Msg, - staking.ErrWrongVonOptType.Code: staking.ErrWrongVonOptType.Msg, - staking.ErrAccountVonNoEnough.Code: staking.ErrAccountVonNoEnough.Msg, - staking.ErrBlockNumberDisordered.Code: staking.ErrBlockNumberDisordered.Msg, - staking.ErrDelegateVonNoEnough.Code: staking.ErrDelegateVonNoEnough.Msg, - staking.ErrWrongWithdrewDelVonCalc.Code: staking.ErrWrongWithdrewDelVonCalc.Msg, - staking.ErrValidatorNoExist.Code: staking.ErrValidatorNoExist.Msg, - staking.ErrWrongFuncParams.Code: staking.ErrWrongFuncParams.Msg, - staking.ErrWrongSlashType.Code: staking.ErrWrongSlashType.Msg, - staking.ErrSlashVonOverflow.Code: staking.ErrSlashVonOverflow.Msg, - staking.ErrWrongSlashVonCalc.Code: staking.ErrWrongSlashVonCalc.Msg, - staking.ErrGetVerifierList.Code: staking.ErrGetVerifierList.Msg, - staking.ErrGetValidatorList.Code: staking.ErrGetValidatorList.Msg, - staking.ErrGetCandidateList.Code: staking.ErrGetCandidateList.Msg, - staking.ErrGetDelegateRelated.Code: staking.ErrGetDelegateRelated.Msg, - staking.ErrQueryCandidateInfo.Code: staking.ErrQueryCandidateInfo.Msg, - staking.ErrQueryDelegateInfo.Code: staking.ErrQueryDelegateInfo.Msg, + staking.ErrWrongBlsPubKey.Code: staking.ErrWrongBlsPubKey.Msg, + staking.ErrWrongBlsPubKeyProof.Code: staking.ErrWrongBlsPubKeyProof.Msg, + staking.ErrDescriptionLen.Code: staking.ErrDescriptionLen.Msg, + staking.ErrWrongProgramVersionSign.Code: staking.ErrWrongProgramVersionSign.Msg, + staking.ErrProgramVersionTooLow.Code: staking.ErrProgramVersionTooLow.Msg, + staking.ErrDeclVsFialedCreateCan.Code: staking.ErrDeclVsFialedCreateCan.Msg, + staking.ErrNoSameStakingAddr.Code: staking.ErrNoSameStakingAddr.Msg, + staking.ErrStakeVonTooLow.Code: staking.ErrStakeVonTooLow.Msg, + staking.ErrCanAlreadyExist.Code: staking.ErrCanAlreadyExist.Msg, + staking.ErrCanNoExist.Code: staking.ErrCanNoExist.Msg, + staking.ErrCanStatusInvalid.Code: staking.ErrCanStatusInvalid.Msg, + staking.ErrIncreaseStakeVonTooLow.Code: staking.ErrIncreaseStakeVonTooLow.Msg, + staking.ErrDelegateVonTooLow.Code: staking.ErrDelegateVonTooLow.Msg, + staking.ErrAccountNoAllowToDelegate.Code: staking.ErrAccountNoAllowToDelegate.Msg, + staking.ErrCanNoAllowDelegate.Code: staking.ErrCanNoAllowDelegate.Msg, + staking.ErrWithdrewDelegationVonTooLow.Code: staking.ErrWithdrewDelegationVonTooLow.Msg, + staking.ErrDelegateNoExist.Code: staking.ErrDelegateNoExist.Msg, + staking.ErrWrongVonOptType.Code: staking.ErrWrongVonOptType.Msg, + staking.ErrAccountVonNoEnough.Code: staking.ErrAccountVonNoEnough.Msg, + staking.ErrBlockNumberDisordered.Code: staking.ErrBlockNumberDisordered.Msg, + staking.ErrDelegateVonNoEnough.Code: staking.ErrDelegateVonNoEnough.Msg, + staking.ErrWrongWithdrewDelVonCalc.Code: staking.ErrWrongWithdrewDelVonCalc.Msg, + staking.ErrValidatorNoExist.Code: staking.ErrValidatorNoExist.Msg, + staking.ErrWrongFuncParams.Code: staking.ErrWrongFuncParams.Msg, + staking.ErrWrongSlashType.Code: staking.ErrWrongSlashType.Msg, + staking.ErrSlashVonOverflow.Code: staking.ErrSlashVonOverflow.Msg, + staking.ErrWrongSlashVonCalc.Code: staking.ErrWrongSlashVonCalc.Msg, + staking.ErrGetVerifierList.Code: staking.ErrGetVerifierList.Msg, + staking.ErrGetValidatorList.Code: staking.ErrGetValidatorList.Msg, + staking.ErrGetCandidateList.Code: staking.ErrGetCandidateList.Msg, + staking.ErrGetDelegateRelated.Code: staking.ErrGetDelegateRelated.Msg, + staking.ErrQueryCandidateInfo.Code: staking.ErrQueryCandidateInfo.Msg, + staking.ErrQueryDelegateInfo.Code: staking.ErrQueryDelegateInfo.Msg, } slashingErrCode := map[uint32]string{ @@ -124,19 +124,19 @@ func main() { } restrictingErrCode := map[uint32]string{ - restricting.ErrParamEpochInvalid.Code: restricting.ErrParamEpochInvalid.Msg, - restricting.ErrCountRestrictPlansInvalid.Code: restricting.ErrCountRestrictPlansInvalid.Msg, - restricting.ErrLockedAmountTooLess.Code: restricting.ErrLockedAmountTooLess.Msg, - restricting.ErrBalanceNotEnough.Code: restricting.ErrBalanceNotEnough.Msg, - restricting.ErrAccountNotFound.Code: restricting.ErrAccountNotFound.Msg, - restricting.ErrSlashingTooMuch.Code: restricting.ErrSlashingTooMuch.Msg, - restricting.ErrStakingAmountEmpty.Code: restricting.ErrStakingAmountEmpty.Msg, - restricting.ErrPledgeLockFundsAmountLessThanZero.Code: restricting.ErrPledgeLockFundsAmountLessThanZero.Msg, - restricting.ErrReturnLockFundsAmountLessThanZero.Code: restricting.ErrReturnLockFundsAmountLessThanZero.Msg, - restricting.ErrSlashingAmountLessThanZero.Code: restricting.ErrSlashingAmountLessThanZero.Msg, - restricting.ErrCreatePlanAmountLessThanZero.Code: restricting.ErrCreatePlanAmountLessThanZero.Msg, - restricting.ErrStakingAmountInvalid.Code: restricting.ErrStakingAmountInvalid.Msg, - restricting.ErrRestrictBalanceNotEnough.Code: restricting.ErrRestrictBalanceNotEnough.Msg, + restricting.ErrParamEpochInvalid.Code: restricting.ErrParamEpochInvalid.Msg, + restricting.ErrCountRestrictPlansInvalid.Code: restricting.ErrCountRestrictPlansInvalid.Msg, + restricting.ErrLockedAmountTooLess.Code: restricting.ErrLockedAmountTooLess.Msg, + restricting.ErrBalanceNotEnough.Code: restricting.ErrBalanceNotEnough.Msg, + restricting.ErrAccountNotFound.Code: restricting.ErrAccountNotFound.Msg, + restricting.ErrSlashingTooMuch.Code: restricting.ErrSlashingTooMuch.Msg, + restricting.ErrStakingAmountEmpty.Code: restricting.ErrStakingAmountEmpty.Msg, + restricting.ErrAdvanceLockedFundsAmountLessThanZero.Code: restricting.ErrAdvanceLockedFundsAmountLessThanZero.Msg, + restricting.ErrReturnLockFundsAmountLessThanZero.Code: restricting.ErrReturnLockFundsAmountLessThanZero.Msg, + restricting.ErrSlashingAmountLessThanZero.Code: restricting.ErrSlashingAmountLessThanZero.Msg, + restricting.ErrCreatePlanAmountLessThanZero.Code: restricting.ErrCreatePlanAmountLessThanZero.Msg, + restricting.ErrStakingAmountInvalid.Code: restricting.ErrStakingAmountInvalid.Msg, + restricting.ErrRestrictBalanceNotEnough.Code: restricting.ErrRestrictBalanceNotEnough.Msg, } govErrCode := map[uint32]string{ diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index c82bec6427..a8444e893f 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -132,22 +132,10 @@ var ( Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby)", Value: eth.DefaultConfig.NetworkId, } - MainFlag = cli.BoolFlag{ - Name: "main", - Usage: "Mainnet network: pre-configured main network (default network)", - } - TestnetFlag = cli.BoolFlag{ - Name: "testnet", - Usage: "Testnet network: pre-configured test network", - } AlayaNetFlag = cli.BoolFlag{ Name: "alaya", Usage: "alaya network: pre-configured alaya network", } - AlayaTestNetFlag = cli.BoolFlag{ - Name: "alayatestnet", - Usage: "alaya test network: pre-configured alaya test network", - } AddressHRPFlag = cli.StringFlag{ Name: "addressHRP", Usage: "set the address hrp,if not set,use default address hrp", @@ -385,12 +373,12 @@ var ( MaxPeersFlag = cli.IntFlag{ Name: "maxpeers", Usage: "Maximum number of network peers (network disabled if set to 0)", - Value: 50, + Value: 60, } MaxConsensusPeersFlag = cli.IntFlag{ Name: "maxconsensuspeers", Usage: "Maximum number of network consensus peers (network disabled if set to 0)", - Value: 75, + Value: 40, } MaxPendingPeersFlag = cli.IntFlag{ Name: "maxpendpeers", @@ -619,15 +607,7 @@ var ( // the a subdirectory of the specified datadir will be used. func MakeDataDir(ctx *cli.Context) string { if path := ctx.GlobalString(DataDirFlag.Name); path != "" { - - if ctx.GlobalBool(TestnetFlag.Name) { - return filepath.Join(path, "testnet") - } else if ctx.GlobalBool(AlayaNetFlag.Name) { - return filepath.Join(path, "alayanet") - } else if ctx.GlobalBool(AlayaTestNetFlag.Name) { - return filepath.Join(path, "alayatestnet") - } - return path + return filepath.Join(path, "alayanet") } Fatalf("Cannot determine default data directory, please set manually (--datadir)") return "" @@ -669,7 +649,7 @@ func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) { // setBootstrapNodes creates a list of bootstrap nodes from the command line // flags, reverting to pre-configured ones if none have been specified. func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { - urls := params.MainnetBootnodes + urls := params.AlayanetBootnodes switch { case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name): @@ -680,10 +660,6 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { } case ctx.GlobalBool(AlayaNetFlag.Name): urls = params.AlayanetBootnodes - case ctx.GlobalBool(AlayaTestNetFlag.Name): - urls = params.AlayaTestnetBootnodes - case ctx.GlobalBool(TestnetFlag.Name): - urls = params.TestnetBootnodes case cfg.BootstrapNodes != nil: return // already set, don't apply defaults. } @@ -905,7 +881,11 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { if lightClient { ethPeers = 0 } - log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers) + if cfg.MaxPeers <= cfg.MaxConsensusPeers { + log.Error("MaxPeers is less than MaxConsensusPeers", "MaxPeers", cfg.MaxPeers, "MaxConsensusPeers", cfg.MaxConsensusPeers) + Fatalf("MaxPeers is less than MaxConsensusPeers, MaxPeers: %d, MaxConsensusPeers: %d", cfg.MaxPeers, cfg.MaxConsensusPeers) + } + log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "consensusTotal", cfg.MaxConsensusPeers, "total", cfg.MaxPeers) if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) { cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name) @@ -949,12 +929,8 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { switch { case ctx.GlobalIsSet(DataDirFlag.Name): cfg.DataDir = ctx.GlobalString(DataDirFlag.Name) - case ctx.GlobalBool(TestnetFlag.Name): - cfg.DataDir = filepath.Join(node.DefaultDataDir(), "testnet") case ctx.GlobalBool(AlayaNetFlag.Name): cfg.DataDir = filepath.Join(node.DefaultDataDir(), "alayanet") - case ctx.GlobalBool(AlayaTestNetFlag.Name): - cfg.DataDir = filepath.Join(node.DefaultDataDir(), "alayatestnet") } if ctx.GlobalIsSet(KeyStoreDirFlag.Name) { @@ -1114,7 +1090,7 @@ func checkExclusive(ctx *cli.Context, args ...interface{}) { // SetEthConfig applies eth-related command line flags to the config. func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { // Avoid conflicting network flags - checkExclusive(ctx, TestnetFlag, AlayaNetFlag, AlayaTestNetFlag) + checkExclusive(ctx, AlayaNetFlag) checkExclusive(ctx, LightServFlag, SyncModeFlag, "light") setGPO(ctx, &cfg.GPO) @@ -1175,23 +1151,11 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { // Override any default configs for hard coded networks. switch { - case ctx.GlobalBool(AlayaNetFlag.Name): if !ctx.GlobalIsSet(NetworkIdFlag.Name) { cfg.NetworkId = 1 } cfg.Genesis = core.DefaultAlayaGenesisBlock() - case ctx.GlobalBool(AlayaTestNetFlag.Name): - if !ctx.GlobalIsSet(NetworkIdFlag.Name) { - cfg.NetworkId = 1 - } - cfg.Genesis = core.DefaultAlayaTestGenesisBlock() - // Test NetWork - case ctx.GlobalBool(TestnetFlag.Name): - if !ctx.GlobalIsSet(NetworkIdFlag.Name) { - cfg.NetworkId = 2000 - } - cfg.Genesis = core.DefaultTestnetGenesisBlock() } if ctx.GlobalIsSet(DBNoGCFlag.Name) { cfg.DBDisabledGC = ctx.GlobalBool(DBNoGCFlag.Name) @@ -1353,12 +1317,8 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database { func MakeGenesis(ctx *cli.Context) *core.Genesis { var genesis *core.Genesis switch { - case ctx.GlobalBool(TestnetFlag.Name): - genesis = core.DefaultTestnetGenesisBlock() case ctx.GlobalBool(AlayaNetFlag.Name): genesis = core.DefaultAlayaGenesisBlock() - case ctx.GlobalBool(AlayaTestNetFlag.Name): - genesis = core.DefaultAlayaTestGenesisBlock() } return genesis } diff --git a/common/args_const.go b/common/args_const.go index 2fe8e0748c..a83f1aa77e 100644 --- a/common/args_const.go +++ b/common/args_const.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/common/byteutil/byteutil.go b/common/byteutil/byteutil.go index d066783e07..94fad75e30 100644 --- a/common/byteutil/byteutil.go +++ b/common/byteutil/byteutil.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package byteutil import ( diff --git a/common/byteutil/byteutil_test.go b/common/byteutil/byteutil_test.go index fbf14a6e07..f262284767 100644 --- a/common/byteutil/byteutil_test.go +++ b/common/byteutil/byteutil_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package byteutil import ( diff --git a/common/consensus/evidence.go b/common/consensus/evidence.go index 3fd4115d46..9b8d6b493f 100644 --- a/common/consensus/evidence.go +++ b/common/consensus/evidence.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package consensus import ( diff --git a/common/errors.go b/common/errors.go index bcf22faea7..98a6c0c470 100644 --- a/common/errors.go +++ b/common/errors.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/common/math/binomial_distribution.go b/common/math/binomial_distribution.go index 17ed2a71b1..292e721f5b 100644 --- a/common/math/binomial_distribution.go +++ b/common/math/binomial_distribution.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/common/math/binomial_distribution_test.go b/common/math/binomial_distribution_test.go index 01f6cc5ab2..62e3caf604 100644 --- a/common/math/binomial_distribution_test.go +++ b/common/math/binomial_distribution_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/common/mclock/mclock.go b/common/mclock/mclock.go index dcac59c6ce..a2fab78e56 100644 --- a/common/mclock/mclock.go +++ b/common/mclock/mclock.go @@ -1,18 +1,18 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of the go-ethereum library. +// Copyright 2021 The Alaya Network Authors +// This file is part of the Alaya-Go library. // -// The go-ethereum library is free software: you can redistribute it and/or modify +// The Alaya-Go 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, +// The Alaya-Go 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 . +// along with the Alaya-Go library. If not, see . // Package mclock is a wrapper for a monotonic clock source package mclock @@ -20,44 +20,108 @@ package mclock import ( "time" - "github.com/aristanetworks/goarista/monotime" + _ "unsafe" // for go:linkname ) +//go:noescape +//go:linkname nanotime runtime.nanotime +func nanotime() int64 + // AbsTime represents absolute monotonic time. -type AbsTime time.Duration +type AbsTime int64 // Now returns the current absolute monotonic time. func Now() AbsTime { - return AbsTime(monotime.Now()) + return AbsTime(nanotime()) } -// Add returns t + d. +// Add returns t + d as absolute time. func (t AbsTime) Add(d time.Duration) AbsTime { return t + AbsTime(d) } -// Clock interface makes it possible to replace the monotonic system clock with +// Sub returns t - t2 as a duration. +func (t AbsTime) Sub(t2 AbsTime) time.Duration { + return time.Duration(t - t2) +} + +// The Clock interface makes it possible to replace the monotonic system clock with // a simulated clock. type Clock interface { Now() AbsTime Sleep(time.Duration) - After(time.Duration) <-chan time.Time + NewTimer(time.Duration) ChanTimer + After(time.Duration) <-chan AbsTime + AfterFunc(d time.Duration, f func()) Timer +} + +// Timer is a cancellable event created by AfterFunc. +type Timer interface { + // Stop cancels the timer. It returns false if the timer has already + // expired or been stopped. + Stop() bool +} + +// ChanTimer is a cancellable event created by NewTimer. +type ChanTimer interface { + Timer + + // The channel returned by C receives a value when the timer expires. + C() <-chan AbsTime + // Reset reschedules the timer with a new timeout. + // It should be invoked only on stopped or expired timers with drained channels. + Reset(time.Duration) } // System implements Clock using the system clock. type System struct{} -// Now implements Clock. -func (System) Now() AbsTime { - return AbsTime(monotime.Now()) +// Now returns the current monotonic time. +func (c System) Now() AbsTime { + return Now() } -// Sleep implements Clock. -func (System) Sleep(d time.Duration) { +// Sleep blocks for the given duration. +func (c System) Sleep(d time.Duration) { time.Sleep(d) } -// After implements Clock. -func (System) After(d time.Duration) <-chan time.Time { - return time.After(d) +// NewTimer creates a timer which can be rescheduled. +func (c System) NewTimer(d time.Duration) ChanTimer { + ch := make(chan AbsTime, 1) + t := time.AfterFunc(d, func() { + // This send is non-blocking because that's how time.Timer + // behaves. It doesn't matter in the happy case, but does + // when Reset is misused. + select { + case ch <- c.Now(): + default: + } + }) + return &systemTimer{t, ch} +} + +// After returns a channel which receives the current time after d has elapsed. +func (c System) After(d time.Duration) <-chan AbsTime { + ch := make(chan AbsTime, 1) + time.AfterFunc(d, func() { ch <- c.Now() }) + return ch +} + +// AfterFunc runs f on a new goroutine after the duration has elapsed. +func (c System) AfterFunc(d time.Duration, f func()) Timer { + return time.AfterFunc(d, f) +} + +type systemTimer struct { + *time.Timer + ch <-chan AbsTime +} + +func (st *systemTimer) Reset(d time.Duration) { + st.Timer.Reset(d) +} + +func (st *systemTimer) C() <-chan AbsTime { + return st.ch } diff --git a/common/mclock/mclock.s b/common/mclock/mclock.s new file mode 100644 index 0000000000..99a7a878f0 --- /dev/null +++ b/common/mclock/mclock.s @@ -0,0 +1 @@ +// This file exists in order to be able to use go:linkname. diff --git a/common/mclock/simclock.go b/common/mclock/simclock.go index e014f56150..8f274ef1fd 100644 --- a/common/mclock/simclock.go +++ b/common/mclock/simclock.go @@ -1,22 +1,23 @@ -// Copyright 2018 The go-ethereum Authors -// This file is part of the go-ethereum library. +// Copyright 2021 The Alaya Network Authors +// This file is part of the Alaya-Go library. // -// The go-ethereum library is free software: you can redistribute it and/or modify +// The Alaya-Go 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, +// The Alaya-Go 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 . +// along with the Alaya-Go library. If not, see . package mclock import ( + "container/heap" "sync" "time" ) @@ -32,35 +33,46 @@ import ( // the timeout using a channel or semaphore. type Simulated struct { now AbsTime - scheduled []event + scheduled simTimerHeap mu sync.RWMutex cond *sync.Cond } -type event struct { - do func() - at AbsTime +// simTimer implements ChanTimer on the virtual clock. +type simTimer struct { + at AbsTime + index int // position in s.scheduled + s *Simulated + do func() + ch <-chan AbsTime +} + +func (s *Simulated) init() { + if s.cond == nil { + s.cond = sync.NewCond(&s.mu) + } } // Run moves the clock by the given duration, executing all timers before that duration. func (s *Simulated) Run(d time.Duration) { s.mu.Lock() - defer s.mu.Unlock() s.init() end := s.now + AbsTime(d) - for len(s.scheduled) > 0 { - ev := s.scheduled[0] - if ev.at > end { - break - } - s.now = ev.at - ev.do() - s.scheduled = s.scheduled[1:] + var do []func() + for len(s.scheduled) > 0 && s.scheduled[0].at <= end { + ev := heap.Pop(&s.scheduled).(*simTimer) + do = append(do, ev.do) } s.now = end + s.mu.Unlock() + + for _, fn := range do { + fn() + } } +// ActiveTimers returns the number of timers that haven't fired. func (s *Simulated) ActiveTimers() int { s.mu.RLock() defer s.mu.RUnlock() @@ -68,6 +80,7 @@ func (s *Simulated) ActiveTimers() int { return len(s.scheduled) } +// WaitForTimers waits until the clock has at least n scheduled timers. func (s *Simulated) WaitForTimers(n int) { s.mu.Lock() defer s.mu.Unlock() @@ -78,7 +91,7 @@ func (s *Simulated) WaitForTimers(n int) { } } -// Now implements Clock. +// Now returns the current virtual time. func (s *Simulated) Now() AbsTime { s.mu.RLock() defer s.mu.RUnlock() @@ -86,44 +99,111 @@ func (s *Simulated) Now() AbsTime { return s.now } -// Sleep implements Clock. +// Sleep blocks until the clock has advanced by d. func (s *Simulated) Sleep(d time.Duration) { <-s.After(d) } -// After implements Clock. -func (s *Simulated) After(d time.Duration) <-chan time.Time { - after := make(chan time.Time, 1) - s.insert(d, func() { - after <- (time.Time{}).Add(time.Duration(s.now)) - }) - return after +// NewTimer creates a timer which fires when the clock has advanced by d. +func (s *Simulated) NewTimer(d time.Duration) ChanTimer { + s.mu.Lock() + defer s.mu.Unlock() + + ch := make(chan AbsTime, 1) + var timer *simTimer + timer = s.schedule(d, func() { ch <- timer.at }) + timer.ch = ch + return timer +} + +// After returns a channel which receives the current time after the clock +// has advanced by d. +func (s *Simulated) After(d time.Duration) <-chan AbsTime { + return s.NewTimer(d).C() } -func (s *Simulated) insert(d time.Duration, do func()) { +// AfterFunc runs fn after the clock has advanced by d. Unlike with the system +// clock, fn runs on the goroutine that calls Run. +func (s *Simulated) AfterFunc(d time.Duration, fn func()) Timer { s.mu.Lock() defer s.mu.Unlock() + + return s.schedule(d, fn) +} + +func (s *Simulated) schedule(d time.Duration, fn func()) *simTimer { s.init() at := s.now + AbsTime(d) - l, h := 0, len(s.scheduled) - ll := h - for l != h { - m := (l + h) / 2 - if at < s.scheduled[m].at { - h = m - } else { - l = m + 1 - } - } - s.scheduled = append(s.scheduled, event{}) - copy(s.scheduled[l+1:], s.scheduled[l:ll]) - s.scheduled[l] = event{do: do, at: at} + ev := &simTimer{do: fn, at: at, s: s} + heap.Push(&s.scheduled, ev) s.cond.Broadcast() + return ev } -func (s *Simulated) init() { - if s.cond == nil { - s.cond = sync.NewCond(&s.mu) +func (ev *simTimer) Stop() bool { + ev.s.mu.Lock() + defer ev.s.mu.Unlock() + + if ev.index < 0 { + return false + } + heap.Remove(&ev.s.scheduled, ev.index) + ev.s.cond.Broadcast() + ev.index = -1 + return true +} + +func (ev *simTimer) Reset(d time.Duration) { + if ev.ch == nil { + panic("mclock: Reset() on timer created by AfterFunc") + } + + ev.s.mu.Lock() + defer ev.s.mu.Unlock() + ev.at = ev.s.now.Add(d) + if ev.index < 0 { + heap.Push(&ev.s.scheduled, ev) // already expired + } else { + heap.Fix(&ev.s.scheduled, ev.index) // hasn't fired yet, reschedule } + ev.s.cond.Broadcast() +} + +func (ev *simTimer) C() <-chan AbsTime { + if ev.ch == nil { + panic("mclock: C() on timer created by AfterFunc") + } + return ev.ch +} + +type simTimerHeap []*simTimer + +func (h *simTimerHeap) Len() int { + return len(*h) +} + +func (h *simTimerHeap) Less(i, j int) bool { + return (*h)[i].at < (*h)[j].at +} + +func (h *simTimerHeap) Swap(i, j int) { + (*h)[i], (*h)[j] = (*h)[j], (*h)[i] + (*h)[i].index = i + (*h)[j].index = j +} + +func (h *simTimerHeap) Push(x interface{}) { + t := x.(*simTimer) + t.index = len(*h) + *h = append(*h, t) +} + +func (h *simTimerHeap) Pop() interface{} { + end := len(*h) - 1 + t := (*h)[end] + t.index = -1 + (*h)[end] = nil + *h = (*h)[:end] + return t } diff --git a/common/mclock/simclock_test.go b/common/mclock/simclock_test.go new file mode 100644 index 0000000000..641a602b9b --- /dev/null +++ b/common/mclock/simclock_test.go @@ -0,0 +1,162 @@ +// Copyright 2018-2020 The PlatON Network Authors +// This file is part of the Alaya-Go library. +// +// The Alaya-Go 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 Alaya-Go 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 Alaya-Go library. If not, see . + +package mclock + +import ( + "testing" + "time" +) + +var _ Clock = System{} +var _ Clock = new(Simulated) + +func TestSimulatedAfter(t *testing.T) { + var ( + timeout = 30 * time.Minute + offset = 99 * time.Hour + adv = 11 * time.Minute + c Simulated + ) + c.Run(offset) + + end := c.Now().Add(timeout) + ch := c.After(timeout) + for c.Now() < end.Add(-adv) { + c.Run(adv) + select { + case <-ch: + t.Fatal("Timer fired early") + default: + } + } + + c.Run(adv) + select { + case stamp := <-ch: + want := AbsTime(0).Add(offset).Add(timeout) + if stamp != want { + t.Errorf("Wrong time sent on timer channel: got %v, want %v", stamp, want) + } + default: + t.Fatal("Timer didn't fire") + } +} + +func TestSimulatedAfterFunc(t *testing.T) { + var c Simulated + + called1 := false + timer1 := c.AfterFunc(100*time.Millisecond, func() { called1 = true }) + if c.ActiveTimers() != 1 { + t.Fatalf("%d active timers, want one", c.ActiveTimers()) + } + if fired := timer1.Stop(); !fired { + t.Fatal("Stop returned false even though timer didn't fire") + } + if c.ActiveTimers() != 0 { + t.Fatalf("%d active timers, want zero", c.ActiveTimers()) + } + if called1 { + t.Fatal("timer 1 called") + } + if fired := timer1.Stop(); fired { + t.Fatal("Stop returned true after timer was already stopped") + } + + called2 := false + timer2 := c.AfterFunc(100*time.Millisecond, func() { called2 = true }) + c.Run(50 * time.Millisecond) + if called2 { + t.Fatal("timer 2 called") + } + c.Run(51 * time.Millisecond) + if !called2 { + t.Fatal("timer 2 not called") + } + if fired := timer2.Stop(); fired { + t.Fatal("Stop returned true after timer has fired") + } +} + +func TestSimulatedSleep(t *testing.T) { + var ( + c Simulated + timeout = 1 * time.Hour + done = make(chan AbsTime, 1) + ) + go func() { + c.Sleep(timeout) + done <- c.Now() + }() + + c.WaitForTimers(1) + c.Run(2 * timeout) + select { + case stamp := <-done: + want := AbsTime(2 * timeout) + if stamp != want { + t.Errorf("Wrong time after sleep: got %v, want %v", stamp, want) + } + case <-time.After(5 * time.Second): + t.Fatal("Sleep didn't return in time") + } +} + +func TestSimulatedTimerReset(t *testing.T) { + var ( + c Simulated + timeout = 1 * time.Hour + ) + timer := c.NewTimer(timeout) + c.Run(2 * timeout) + select { + case ftime := <-timer.C(): + if ftime != AbsTime(timeout) { + t.Fatalf("wrong time %v sent on timer channel, want %v", ftime, AbsTime(timeout)) + } + default: + t.Fatal("timer didn't fire") + } + + timer.Reset(timeout) + c.Run(2 * timeout) + select { + case ftime := <-timer.C(): + if ftime != AbsTime(3*timeout) { + t.Fatalf("wrong time %v sent on timer channel, want %v", ftime, AbsTime(3*timeout)) + } + default: + t.Fatal("timer didn't fire again") + } +} + +func TestSimulatedTimerStop(t *testing.T) { + var ( + c Simulated + timeout = 1 * time.Hour + ) + timer := c.NewTimer(timeout) + c.Run(2 * timeout) + if timer.Stop() { + t.Errorf("Stop returned true for fired timer") + } + select { + case <-timer.C(): + default: + t.Fatal("timer didn't fire") + } +} diff --git a/common/mock/chain.go b/common/mock/chain.go index a3c4ccaf2c..d0bdb21b39 100644 --- a/common/mock/chain.go +++ b/common/mock/chain.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -17,12 +17,14 @@ package mock import ( + "encoding/json" "fmt" "math/big" "math/rand" "reflect" "time" + "github.com/AlayaNetwork/Alaya-Go/common/vm" "github.com/AlayaNetwork/Alaya-Go/crypto" "github.com/AlayaNetwork/Alaya-Go/crypto/sha3" "github.com/AlayaNetwork/Alaya-Go/rlp" @@ -610,3 +612,23 @@ func (lhs *MockStateDB) DeepCopy(rhs *MockStateDB) { } } } + +type ActiveVersionValue struct { + ActiveVersion uint32 `json:"ActiveVersion"` + ActiveBlock uint64 `json:"ActiveBlock"` +} + +func (state *MockStateDB) GetCurrentActiveVersion() uint32 { + + avListBytes := state.GetState(vm.GovContractAddr, []byte("ActVers")) + if len(avListBytes) == 0 { + panic("Cannot find active version list") + } + var avList []ActiveVersionValue + if err := json.Unmarshal(avListBytes, &avList); err != nil { + panic("invalid active version information") + } + + return avList[0].ActiveVersion + +} diff --git a/common/mock/journal.go b/common/mock/journal.go index bd67c9f398..79b69068f7 100644 --- a/common/mock/journal.go +++ b/common/mock/journal.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/common/prque/prque_test.go b/common/prque/prque_test.go index 62e09151a4..5a305236c8 100644 --- a/common/prque/prque_test.go +++ b/common/prque/prque_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/common/rlp_utils.go b/common/rlp_utils.go index 89ef550163..5ab02b908e 100644 --- a/common/rlp_utils.go +++ b/common/rlp_utils.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/common/timeUtil.go b/common/timeUtil.go index dc835b3d1c..def5848161 100644 --- a/common/timeUtil.go +++ b/common/timeUtil.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/common/vm/inner_contract.go b/common/vm/inner_contract.go index 3f7cfbc0a9..5a62b5385a 100644 --- a/common/vm/inner_contract.go +++ b/common/vm/inner_contract.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package vm import "github.com/AlayaNetwork/Alaya-Go/common" diff --git a/consensus/bft_mock.go b/consensus/bft_mock.go index 7d58de65a6..addb68a01a 100644 --- a/consensus/bft_mock.go +++ b/consensus/bft_mock.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -386,6 +386,10 @@ func (bm *BftMock) Resume() { } +func (bm *BftMock) Syncing() bool { + return false +} + func (bm *BftMock) DecodeExtra(extra []byte) (common.Hash, uint64, error) { return common.Hash{}, 0, nil } diff --git a/consensus/cbft/api.go b/consensus/cbft/api.go index f459635f09..2cf8832ed7 100644 --- a/consensus/cbft/api.go +++ b/consensus/cbft/api.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -37,14 +37,14 @@ type API interface { GetSchnorrNIZKProve() (*bls.SchnorrProof, error) } -// PublicConsensusAPI provides an API to access the PlatON blockchain. +// PublicConsensusAPI provides an API to access the Alaya blockchain. // It offers only methods that operate on public data that // is freely available to anyone. type PublicConsensusAPI struct { engine API } -// NewPublicConsensusAPI creates a new PlatON blockchain API. +// NewPublicConsensusAPI creates a new Alaya blockchain API. func NewPublicConsensusAPI(engine API) *PublicConsensusAPI { return &PublicConsensusAPI{engine: engine} } diff --git a/consensus/cbft/cbft.go b/consensus/cbft/cbft.go index 8ed338624f..a12b53d8b4 100644 --- a/consensus/cbft/cbft.go +++ b/consensus/cbft/cbft.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbft import ( @@ -648,6 +649,11 @@ func (cbft *Cbft) VerifyHeader(chain consensus.ChainReader, header *types.Header return fmt.Errorf("verify header fail, missing signature, number:%d, hash:%s", header.Number.Uint64(), header.Hash().String()) } + if header.IsInvalid() { + cbft.log.Error("Verify header fail, Extra field is too long", "number", header.Number, "hash", header.CacheHash()) + return fmt.Errorf("verify header fail, Extra field is too long, number:%d, hash:%s", header.Number.Uint64(), header.CacheHash().String()) + } + if err := cbft.validatorPool.VerifyHeader(header); err != nil { cbft.log.Error("Verify header fail", "number", header.Number, "hash", header.Hash(), "err", err) return fmt.Errorf("verify header fail, number:%d, hash:%s, err:%s", header.Number.Uint64(), header.Hash().String(), err.Error()) @@ -1584,11 +1590,16 @@ func (cbft *Cbft) Pause() { cbft.log.Info("Pause cbft consensus") utils.SetTrue(&cbft.syncing) } + func (cbft *Cbft) Resume() { cbft.log.Info("Resume cbft consensus") utils.SetFalse(&cbft.syncing) } +func (cbft *Cbft) Syncing() bool { + return utils.True(&cbft.syncing) +} + func (cbft *Cbft) generatePrepareQC(votes map[uint32]*protocols.PrepareVote) *ctypes.QuorumCert { if len(votes) == 0 { return nil diff --git a/consensus/cbft/cbft_byzantine_test.go b/consensus/cbft/cbft_byzantine_test.go index d77473dbc6..6369f64614 100644 --- a/consensus/cbft/cbft_byzantine_test.go +++ b/consensus/cbft/cbft_byzantine_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbft import ( diff --git a/consensus/cbft/cbft_common_util.go b/consensus/cbft/cbft_common_util.go index 68f728a99a..d6fe02b92f 100644 --- a/consensus/cbft/cbft_common_util.go +++ b/consensus/cbft/cbft_common_util.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbft import ( diff --git a/consensus/cbft/cbft_test.go b/consensus/cbft/cbft_test.go index 6b738caa9c..2f11095ac3 100644 --- a/consensus/cbft/cbft_test.go +++ b/consensus/cbft/cbft_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbft import ( diff --git a/consensus/cbft/cbft_test_util.go b/consensus/cbft/cbft_test_util.go index fdad0f3cba..74c145d460 100644 --- a/consensus/cbft/cbft_test_util.go +++ b/consensus/cbft/cbft_test_util.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbft import ( diff --git a/consensus/cbft/consensus_process.go b/consensus/cbft/consensus_process.go index af26ab1cfb..f7c215e33c 100644 --- a/consensus/cbft/consensus_process.go +++ b/consensus/cbft/consensus_process.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -85,7 +85,7 @@ func (cbft *Cbft) OnPrepareBlock(id string, msg *protocols.PrepareBlock) error { } else { block, qc = cbft.blockTree.FindBlockAndQC(msg.Block.ParentHash(), msg.Block.NumberU64()-1) } - cbft.log.Info("Receive new view's block, change view", "newEpoch", msg.Epoch, "newView", msg.ViewNumber) + cbft.log.Debug("Receive new view's block, change view", "newEpoch", msg.Epoch, "newView", msg.ViewNumber) cbft.changeView(msg.Epoch, msg.ViewNumber, block, qc, msg.ViewChangeQC) } } @@ -97,7 +97,7 @@ func (cbft *Cbft) OnPrepareBlock(id string, msg *protocols.PrepareBlock) error { } // The new block is notified by the PrepareBlockHash to the nodes in the network. cbft.state.AddPrepareBlock(msg) - cbft.log.Info("Receive new prepareBlock", "msgHash", msg.MsgHash(), "prepare", msg.String()) + cbft.log.Debug("Receive new prepareBlock", "msgHash", msg.MsgHash(), "prepare", msg.String()) cbft.findExecutableBlock() return nil } @@ -137,7 +137,7 @@ func (cbft *Cbft) OnPrepareVote(id string, msg *protocols.PrepareVote) error { } cbft.state.AddPrepareVote(uint32(node.Index), msg) - cbft.log.Info("Receive new prepareVote", "msgHash", msg.MsgHash(), "vote", msg.String(), "votes", cbft.state.PrepareVoteLenByIndex(msg.BlockIndex)) + cbft.log.Debug("Receive new prepareVote", "msgHash", msg.MsgHash(), "vote", msg.String(), "votes", cbft.state.PrepareVoteLenByIndex(msg.BlockIndex)) cbft.insertPrepareQC(msg.ParentQC) cbft.findQCBlock() @@ -166,7 +166,7 @@ func (cbft *Cbft) OnViewChange(id string, msg *protocols.ViewChange) error { } cbft.state.AddViewChange(uint32(node.Index), msg) - cbft.log.Info("Receive new viewChange", "msgHash", msg.MsgHash(), "viewChange", msg.String(), "total", cbft.state.ViewChangeLen()) + cbft.log.Debug("Receive new viewChange", "msgHash", msg.MsgHash(), "viewChange", msg.String(), "total", cbft.state.ViewChangeLen()) // It is possible to achieve viewchangeQC every time you add viewchange cbft.tryChangeView() return nil diff --git a/consensus/cbft/consensus_process_test.go b/consensus/cbft/consensus_process_test.go index 8af2b5d4a3..37b924445d 100644 --- a/consensus/cbft/consensus_process_test.go +++ b/consensus/cbft/consensus_process_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbft import ( diff --git a/consensus/cbft/evidence/duplicateEvidence.go b/consensus/cbft/evidence/duplicateEvidence.go index 99e3ee1c04..c5efa21afd 100644 --- a/consensus/cbft/evidence/duplicateEvidence.go +++ b/consensus/cbft/evidence/duplicateEvidence.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package evidence import ( diff --git a/consensus/cbft/evidence/evidence.go b/consensus/cbft/evidence/evidence.go index 2c066652c5..acc12f37a9 100644 --- a/consensus/cbft/evidence/evidence.go +++ b/consensus/cbft/evidence/evidence.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package evidence import ( diff --git a/consensus/cbft/evidence/evidencePool.go b/consensus/cbft/evidence/evidencePool.go index f75388e47a..79ac58a54e 100644 --- a/consensus/cbft/evidence/evidencePool.go +++ b/consensus/cbft/evidence/evidencePool.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + // Package evidence implements recording duplicate blocks and votes for cbft consensus. package evidence diff --git a/consensus/cbft/evidence/evidence_common_test.go b/consensus/cbft/evidence/evidence_common_test.go index 070e5e7ee6..449252dde5 100644 --- a/consensus/cbft/evidence/evidence_common_test.go +++ b/consensus/cbft/evidence/evidence_common_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package evidence import ( diff --git a/consensus/cbft/evidence/evidence_test.go b/consensus/cbft/evidence/evidence_test.go index fb14966f46..7df49baad2 100644 --- a/consensus/cbft/evidence/evidence_test.go +++ b/consensus/cbft/evidence/evidence_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package evidence import ( diff --git a/consensus/cbft/evidence/message.go b/consensus/cbft/evidence/message.go index b123c4faf1..0acd48be42 100644 --- a/consensus/cbft/evidence/message.go +++ b/consensus/cbft/evidence/message.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package evidence import ( diff --git a/consensus/cbft/evidence_test.go b/consensus/cbft/evidence_test.go index 3086f18694..b12bc52a2f 100644 --- a/consensus/cbft/evidence_test.go +++ b/consensus/cbft/evidence_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbft import ( diff --git a/consensus/cbft/executor/executor.go b/consensus/cbft/executor/executor.go index ca4fa93f22..4ff48079b9 100644 --- a/consensus/cbft/executor/executor.go +++ b/consensus/cbft/executor/executor.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package executor import ( diff --git a/consensus/cbft/executor/executor_test.go b/consensus/cbft/executor/executor_test.go index a14e8fdbf8..f7998916aa 100644 --- a/consensus/cbft/executor/executor_test.go +++ b/consensus/cbft/executor/executor_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package executor import ( diff --git a/consensus/cbft/fetcher/fetcher.go b/consensus/cbft/fetcher/fetcher.go index e9611f1b11..381885d62c 100644 --- a/consensus/cbft/fetcher/fetcher.go +++ b/consensus/cbft/fetcher/fetcher.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package fetcher import ( diff --git a/consensus/cbft/fetcher/fetcher_test.go b/consensus/cbft/fetcher/fetcher_test.go index 56b350420c..d2976a26f3 100644 --- a/consensus/cbft/fetcher/fetcher_test.go +++ b/consensus/cbft/fetcher/fetcher_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package fetcher import ( diff --git a/consensus/cbft/fetcher/limit_fetcher.go b/consensus/cbft/fetcher/limit_fetcher.go index 653702a99c..59e9211c5d 100644 --- a/consensus/cbft/fetcher/limit_fetcher.go +++ b/consensus/cbft/fetcher/limit_fetcher.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package fetcher import ( diff --git a/consensus/cbft/fetcher/limit_fetcher_test.go b/consensus/cbft/fetcher/limit_fetcher_test.go index 57669a503f..a053dc8b7c 100644 --- a/consensus/cbft/fetcher/limit_fetcher_test.go +++ b/consensus/cbft/fetcher/limit_fetcher_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package fetcher import ( diff --git a/consensus/cbft/metrics.go b/consensus/cbft/metrics.go index 1a6da1683f..8ebb0ddbb8 100644 --- a/consensus/cbft/metrics.go +++ b/consensus/cbft/metrics.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbft import ( diff --git a/consensus/cbft/network/handler.go b/consensus/cbft/network/handler.go index 585b052809..b5bdaae1b9 100644 --- a/consensus/cbft/network/handler.go +++ b/consensus/cbft/network/handler.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package network import ( diff --git a/consensus/cbft/network/handler_test.go b/consensus/cbft/network/handler_test.go index e70605ab73..18ea80d183 100644 --- a/consensus/cbft/network/handler_test.go +++ b/consensus/cbft/network/handler_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package network import ( diff --git a/consensus/cbft/network/helper.go b/consensus/cbft/network/helper.go index 0bdceddd6e..483068241d 100644 --- a/consensus/cbft/network/helper.go +++ b/consensus/cbft/network/helper.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package network import ( diff --git a/consensus/cbft/network/helper_test.go b/consensus/cbft/network/helper_test.go index d8d0b9e8f9..fd86a03619 100644 --- a/consensus/cbft/network/helper_test.go +++ b/consensus/cbft/network/helper_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package network import ( diff --git a/consensus/cbft/network/interface.go b/consensus/cbft/network/interface.go index ece7a1beee..0ab3c3d777 100644 --- a/consensus/cbft/network/interface.go +++ b/consensus/cbft/network/interface.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package network import ( diff --git a/consensus/cbft/network/metrics.go b/consensus/cbft/network/metrics.go index 9435bca483..6950f34ebd 100644 --- a/consensus/cbft/network/metrics.go +++ b/consensus/cbft/network/metrics.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package network import ( diff --git a/consensus/cbft/network/metrics_test.go b/consensus/cbft/network/metrics_test.go index 3b5618ee5a..e818fc5eb5 100644 --- a/consensus/cbft/network/metrics_test.go +++ b/consensus/cbft/network/metrics_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package network import ( diff --git a/consensus/cbft/network/peer.go b/consensus/cbft/network/peer.go index ba5b1d3506..89c79f5b8d 100644 --- a/consensus/cbft/network/peer.go +++ b/consensus/cbft/network/peer.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package network import ( diff --git a/consensus/cbft/network/peer_test.go b/consensus/cbft/network/peer_test.go index 8b33421ca1..517ab02dfa 100644 --- a/consensus/cbft/network/peer_test.go +++ b/consensus/cbft/network/peer_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package network import ( diff --git a/consensus/cbft/network/router.go b/consensus/cbft/network/router.go index 790a5da02a..edf511562f 100644 --- a/consensus/cbft/network/router.go +++ b/consensus/cbft/network/router.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + // Package network implements a concrete consensus engines. package network diff --git a/consensus/cbft/network/router_test.go b/consensus/cbft/network/router_test.go index 32f854b73d..33f35b0c24 100644 --- a/consensus/cbft/network/router_test.go +++ b/consensus/cbft/network/router_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package network import ( diff --git a/consensus/cbft/network/test_func.go b/consensus/cbft/network/test_func.go index c58355599e..7fcd909bac 100644 --- a/consensus/cbft/network/test_func.go +++ b/consensus/cbft/network/test_func.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package network import ( diff --git a/consensus/cbft/prepare_block_test.go b/consensus/cbft/prepare_block_test.go index 7f33ec2d2f..d8d0f784b3 100644 --- a/consensus/cbft/prepare_block_test.go +++ b/consensus/cbft/prepare_block_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbft import ( diff --git a/consensus/cbft/prepare_vote_test.go b/consensus/cbft/prepare_vote_test.go index a687f17e7f..484b84aef2 100644 --- a/consensus/cbft/prepare_vote_test.go +++ b/consensus/cbft/prepare_vote_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbft import ( diff --git a/consensus/cbft/protocols/protocol.go b/consensus/cbft/protocols/protocol.go index 1b37f3d376..08ba968d31 100644 --- a/consensus/cbft/protocols/protocol.go +++ b/consensus/cbft/protocols/protocol.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package protocols import ( diff --git a/consensus/cbft/protocols/wal_protocol.go b/consensus/cbft/protocols/wal_protocol.go index e7f915665c..c069932a7d 100644 --- a/consensus/cbft/protocols/wal_protocol.go +++ b/consensus/cbft/protocols/wal_protocol.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -88,7 +88,7 @@ type ConfirmedViewChange struct { Epoch uint64 ViewNumber uint64 Block *types.Block - QC *ctypes.QuorumCert + QC *ctypes.QuorumCert `rlp:"nil"` ViewChangeQC *ctypes.ViewChangeQC `rlp:"nil"` } diff --git a/consensus/cbft/rules/safety_rules.go b/consensus/cbft/rules/safety_rules.go index f656785e6d..0ee2a54282 100644 --- a/consensus/cbft/rules/safety_rules.go +++ b/consensus/cbft/rules/safety_rules.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package rules import ( diff --git a/consensus/cbft/rules/safety_rules_test.go b/consensus/cbft/rules/safety_rules_test.go index e437e2caef..461644780c 100644 --- a/consensus/cbft/rules/safety_rules_test.go +++ b/consensus/cbft/rules/safety_rules_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package rules import ( diff --git a/consensus/cbft/rules/vote_rules.go b/consensus/cbft/rules/vote_rules.go index 68b09afce6..56c3601719 100644 --- a/consensus/cbft/rules/vote_rules.go +++ b/consensus/cbft/rules/vote_rules.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package rules import ( diff --git a/consensus/cbft/rules/vote_rules_test.go b/consensus/cbft/rules/vote_rules_test.go index 9bf39daabf..791365227e 100644 --- a/consensus/cbft/rules/vote_rules_test.go +++ b/consensus/cbft/rules/vote_rules_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package rules import ( diff --git a/consensus/cbft/state/state.go b/consensus/cbft/state/state.go index 7b131cfbb3..ef22415fc5 100644 --- a/consensus/cbft/state/state.go +++ b/consensus/cbft/state/state.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package state import ( diff --git a/consensus/cbft/state/state_test.go b/consensus/cbft/state/state_test.go index 1f0dbdf623..025e07f780 100644 --- a/consensus/cbft/state/state_test.go +++ b/consensus/cbft/state/state_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package state import ( diff --git a/consensus/cbft/state/timer.go b/consensus/cbft/state/timer.go index 5e750ba670..f5ac4a3e09 100644 --- a/consensus/cbft/state/timer.go +++ b/consensus/cbft/state/timer.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package state import ( diff --git a/consensus/cbft/state/timer_test.go b/consensus/cbft/state/timer_test.go index f5bb76e368..3cb7d16220 100644 --- a/consensus/cbft/state/timer_test.go +++ b/consensus/cbft/state/timer_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package state import ( diff --git a/consensus/cbft/sync_msg_test.go b/consensus/cbft/sync_msg_test.go index bf55750712..7554713b50 100644 --- a/consensus/cbft/sync_msg_test.go +++ b/consensus/cbft/sync_msg_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbft import ( diff --git a/consensus/cbft/sync_process.go b/consensus/cbft/sync_process.go index d5996a9650..8c42b2692d 100644 --- a/consensus/cbft/sync_process.go +++ b/consensus/cbft/sync_process.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbft import ( diff --git a/consensus/cbft/sync_process_test.go b/consensus/cbft/sync_process_test.go index 4eca0f015a..4943fb223d 100644 --- a/consensus/cbft/sync_process_test.go +++ b/consensus/cbft/sync_process_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbft import ( diff --git a/consensus/cbft/types/block_tree.go b/consensus/cbft/types/block_tree.go index 23adf92766..fa55f8f0c2 100644 --- a/consensus/cbft/types/block_tree.go +++ b/consensus/cbft/types/block_tree.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package types import ( diff --git a/consensus/cbft/types/block_tree_test.go b/consensus/cbft/types/block_tree_test.go index e408ec6f96..4fe82dc197 100644 --- a/consensus/cbft/types/block_tree_test.go +++ b/consensus/cbft/types/block_tree_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package types import ( diff --git a/consensus/cbft/types/cache.go b/consensus/cbft/types/cache.go index a93bf7b30f..b5952fc402 100644 --- a/consensus/cbft/types/cache.go +++ b/consensus/cbft/types/cache.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package types import ( diff --git a/consensus/cbft/types/cache_test.go b/consensus/cbft/types/cache_test.go index 03d2deaf63..e1cbae0a9b 100644 --- a/consensus/cbft/types/cache_test.go +++ b/consensus/cbft/types/cache_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package types import ( diff --git a/consensus/cbft/types/codec.go b/consensus/cbft/types/codec.go index 1d0a35ce42..d21bec4187 100644 --- a/consensus/cbft/types/codec.go +++ b/consensus/cbft/types/codec.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package types import ( diff --git a/consensus/cbft/types/codec_test.go b/consensus/cbft/types/codec_test.go index ddb082e762..9cea133ec9 100644 --- a/consensus/cbft/types/codec_test.go +++ b/consensus/cbft/types/codec_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package types import ( diff --git a/consensus/cbft/types/config.go b/consensus/cbft/types/config.go index b8eb8fbafc..2e2737c62d 100644 --- a/consensus/cbft/types/config.go +++ b/consensus/cbft/types/config.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package types import ( diff --git a/consensus/cbft/types/crypto.go b/consensus/cbft/types/crypto.go index e466ae1f82..e5c47d56a5 100644 --- a/consensus/cbft/types/crypto.go +++ b/consensus/cbft/types/crypto.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package types import ( diff --git a/consensus/cbft/types/crypto_test.go b/consensus/cbft/types/crypto_test.go index a6cab9d953..8532273218 100644 --- a/consensus/cbft/types/crypto_test.go +++ b/consensus/cbft/types/crypto_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package types import ( diff --git a/consensus/cbft/types/message.go b/consensus/cbft/types/message.go index 3db311a223..db427afaf3 100644 --- a/consensus/cbft/types/message.go +++ b/consensus/cbft/types/message.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package types import ( diff --git a/consensus/cbft/types/message_test.go b/consensus/cbft/types/message_test.go index 4139f25fec..fc1294989d 100644 --- a/consensus/cbft/types/message_test.go +++ b/consensus/cbft/types/message_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package types import ( diff --git a/consensus/cbft/utils/bit_array.go b/consensus/cbft/utils/bit_array.go index 31664190eb..82dc83c706 100644 --- a/consensus/cbft/utils/bit_array.go +++ b/consensus/cbft/utils/bit_array.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package utils import ( diff --git a/consensus/cbft/utils/bit_array_test.go b/consensus/cbft/utils/bit_array_test.go index 89cb74db66..06afe60173 100644 --- a/consensus/cbft/utils/bit_array_test.go +++ b/consensus/cbft/utils/bit_array_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package utils import ( diff --git a/consensus/cbft/utils/util.go b/consensus/cbft/utils/util.go index dd16b29e3d..ff2df72d53 100644 --- a/consensus/cbft/utils/util.go +++ b/consensus/cbft/utils/util.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package utils import ( diff --git a/consensus/cbft/utils/util_test.go b/consensus/cbft/utils/util_test.go index e91080baf6..153bed04d5 100644 --- a/consensus/cbft/utils/util_test.go +++ b/consensus/cbft/utils/util_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package utils import ( diff --git a/consensus/cbft/validator/validator.go b/consensus/cbft/validator/validator.go index 67619a0c20..e306b16df3 100644 --- a/consensus/cbft/validator/validator.go +++ b/consensus/cbft/validator/validator.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package validator import ( @@ -648,7 +649,8 @@ func (vp *ValidatorPool) VerifyAggSigByBA(epoch uint64, vSet *utils.BitArray, ms vp.lock.RUnlock() var pub bls.PublicKey - pub.Deserialize(nodeList[0].BlsPubKey.Serialize()) + pub = *nodeList[0].BlsPubKey + //pub.Deserialize(nodeList[0].BlsPubKey.Serialize()) for i := 1; i < len(nodeList); i++ { pub.Add(nodeList[i].BlsPubKey) } diff --git a/consensus/cbft/validator/validator_test.go b/consensus/cbft/validator/validator_test.go index 5d40907eb4..25dfd77298 100644 --- a/consensus/cbft/validator/validator_test.go +++ b/consensus/cbft/validator/validator_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package validator import ( diff --git a/consensus/cbft/verify_qc_test.go b/consensus/cbft/verify_qc_test.go index 4bd9c29972..4426f90b65 100644 --- a/consensus/cbft/verify_qc_test.go +++ b/consensus/cbft/verify_qc_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbft import ( diff --git a/consensus/cbft/view_change_test.go b/consensus/cbft/view_change_test.go index e0602152aa..d27e18445d 100644 --- a/consensus/cbft/view_change_test.go +++ b/consensus/cbft/view_change_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbft import ( diff --git a/consensus/cbft/wal/wal.go b/consensus/cbft/wal/wal.go index 4a50efdb90..7c28143ad1 100644 --- a/consensus/cbft/wal/wal.go +++ b/consensus/cbft/wal/wal.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + // Package wal implements the similar write-ahead logging for cbft consensus. package wal diff --git a/consensus/cbft/wal/wal_common_test.go b/consensus/cbft/wal/wal_common_test.go index de69ed8f18..ec7085178d 100644 --- a/consensus/cbft/wal/wal_common_test.go +++ b/consensus/cbft/wal/wal_common_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package wal import ( diff --git a/consensus/cbft/wal/wal_database.go b/consensus/cbft/wal/wal_database.go index aa694f565e..3e31ffec32 100644 --- a/consensus/cbft/wal/wal_database.go +++ b/consensus/cbft/wal/wal_database.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package wal import ( diff --git a/consensus/cbft/wal/wal_database_test.go b/consensus/cbft/wal/wal_database_test.go index 8840a3e98a..f8841b7331 100644 --- a/consensus/cbft/wal/wal_database_test.go +++ b/consensus/cbft/wal/wal_database_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package wal import ( diff --git a/consensus/cbft/wal/wal_decoder.go b/consensus/cbft/wal/wal_decoder.go index bbf5cc5143..51d1d9d810 100644 --- a/consensus/cbft/wal/wal_decoder.go +++ b/consensus/cbft/wal/wal_decoder.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package wal import ( diff --git a/consensus/cbft/wal/wal_journal.go b/consensus/cbft/wal/wal_journal.go index 63e450e6bc..574433ba9a 100644 --- a/consensus/cbft/wal/wal_journal.go +++ b/consensus/cbft/wal/wal_journal.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package wal import ( diff --git a/consensus/cbft/wal/wal_test.go b/consensus/cbft/wal/wal_test.go index bac8739330..f0eecaca0c 100644 --- a/consensus/cbft/wal/wal_test.go +++ b/consensus/cbft/wal/wal_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -269,3 +269,22 @@ func TestWalDecoder(t *testing.T) { _, err = WALDecode(data, protocols.SendPrepareBlockMsg) assert.NotNil(t, err) } + +func TestWalProtocalMsg(t *testing.T) { + vc := &protocols.ConfirmedViewChange{ + Epoch: epoch, + ViewNumber: viewNumber, + Block: newBlock(), + QC: nil, + ViewChangeQC: buildViewChangeQC(), + } + m := &Message{ + Timestamp: uint64(time.Now().UnixNano()), + Data: vc, + } + b, err := encodeJournal(m) + assert.Nil(t, err) + msgInfo, err := WALDecode(b[10:], protocols.ConfirmedViewChangeMsg) + assert.Nil(t, err) + assert.Nil(t, msgInfo.(*protocols.ConfirmedViewChange).QC) +} diff --git a/consensus/cbft/wal/wal_writer.go b/consensus/cbft/wal/wal_writer.go index 5d6ec98636..0ea2948f23 100644 --- a/consensus/cbft/wal/wal_writer.go +++ b/consensus/cbft/wal/wal_writer.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package wal import ( diff --git a/consensus/cbft/wal_bridge.go b/consensus/cbft/wal_bridge.go index a0a8fe8574..7d1c7187c5 100644 --- a/consensus/cbft/wal_bridge.go +++ b/consensus/cbft/wal_bridge.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbft import ( diff --git a/consensus/cbft/wal_bridge_test.go b/consensus/cbft/wal_bridge_test.go index bca77b75b5..9dcd5525b3 100644 --- a/consensus/cbft/wal_bridge_test.go +++ b/consensus/cbft/wal_bridge_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbft import ( diff --git a/consensus/consensus.go b/consensus/consensus.go index 22120039c1..e2c85821bb 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -140,6 +140,8 @@ type Engine interface { Resume() DecodeExtra(extra []byte) (common.Hash, uint64, error) + + Syncing() bool } // PoW is a consensus engine based on proof-of-work. diff --git a/consensus/sign.go b/consensus/sign.go index a3589d77a8..750b2ccecd 100644 --- a/consensus/sign.go +++ b/consensus/sign.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -56,7 +56,7 @@ func SigHash(header *types.Header) (hash common.Hash) { header.GasLimit, header.GasUsed, header.Time, - header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short + header.ExtraData(), header.Nonce, }) hasher.Sum(hash[:0]) @@ -74,7 +74,7 @@ func Ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, er if len(header.Extra) < ExtraSeal { return common.Address{}, ErrMissingSignature } - signature := header.Extra[len(header.Extra)-ExtraSeal:] + signature := header.Signature() // Recover the public key and the Ethereum address pubkey, err := crypto.Ecrecover(SigHash(header).Bytes(), signature) diff --git a/core/block_validator.go b/core/block_validator.go index 71fbda9e92..d6b6092029 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -120,10 +120,8 @@ func CalcGasLimit(parent *types.Block, gasFloor /*, gasCeil*/ uint64) uint64 { gasFloor = gasCeil } - // contrib = (parentGasUsed * 3 / 2) / 256 contrib := (parent.GasUsed() + parent.GasUsed()/2) / params.GasLimitBoundDivisor - // decay = parentGasLimit / 256 -1 decay := parent.GasLimit()/params.GasLimitBoundDivisor - 1 /* @@ -134,9 +132,7 @@ func CalcGasLimit(parent *types.Block, gasFloor /*, gasCeil*/ uint64) uint64 { from parentGasLimit * (2/3) parentGasUsed is. */ limit := parent.GasLimit() - decay + contrib - /*if limit < params.MinGasLimit { - limit = params.MinGasLimit - }*/ + // If we're outside our allowed gas range, we try to hone towards them if limit < gasFloor { limit = parent.GasLimit() + decay diff --git a/core/blockchain.go b/core/blockchain.go index 95039d5659..2986eadc5a 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -623,7 +623,6 @@ func (bc *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { return bc.getBlock(hash, number) } -// modified by PlatON func (bc *BlockChain) getBlock(hash common.Hash, number uint64) *types.Block { // Short circuit if the block's already in the cache, retrieve otherwise if block, ok := bc.blockCache.Get(hash); ok { diff --git a/core/blockchain_cache.go b/core/blockchain_cache.go index 9c83c0922c..47fd297f4b 100644 --- a/core/blockchain_cache.go +++ b/core/blockchain_cache.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/blockchain_clean.go b/core/blockchain_clean.go index cc53aa274b..05dc3ceda3 100644 --- a/core/blockchain_clean.go +++ b/core/blockchain_clean.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/blockchain_clean_test.go b/core/blockchain_clean_test.go index 09ae1b32e1..b08ecdb68c 100644 --- a/core/blockchain_clean_test.go +++ b/core/blockchain_clean_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/blockchain_reactor.go b/core/blockchain_reactor.go index 3e2a4a74cd..bf5e3c5d50 100644 --- a/core/blockchain_reactor.go +++ b/core/blockchain_reactor.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -20,6 +20,7 @@ import ( "bytes" "crypto/ecdsa" "encoding/hex" + "errors" "fmt" "math/big" "sync" @@ -30,7 +31,6 @@ import ( "github.com/AlayaNetwork/Alaya-Go/core/snapshotdb" "github.com/AlayaNetwork/Alaya-Go/core/state" "github.com/AlayaNetwork/Alaya-Go/core/vm" - "github.com/AlayaNetwork/Alaya-Go/crypto" "github.com/AlayaNetwork/Alaya-Go/p2p/discover" "github.com/AlayaNetwork/Alaya-Go/x/handler" "github.com/AlayaNetwork/Alaya-Go/x/staking" @@ -248,11 +248,9 @@ func (bcr *BlockChainReactor) BeginBlocker(header *types.Header, state xcom.Stat } else { blockHash = header.CacheHash() // Verify vrf proof - sign := header.Extra[32:97] - sealHash := header.SealHash().Bytes() - pk, err := crypto.SigToPub(sealHash, sign) - if nil != err { - return err + pk := header.CachePublicKey() + if pk == nil { + return errors.New("failed to get the public key of the block producer") } if err := bcr.vh.VerifyVrf(pk, header.Number, header.ParentHash, blockHash, header.Nonce.Bytes()); nil != err { return err diff --git a/core/blockchain_reactor_test.go b/core/blockchain_reactor_test.go index e738b63666..42895f3476 100644 --- a/core/blockchain_reactor_test.go +++ b/core/blockchain_reactor_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 9e02df17b4..019c13fc6d 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -17,7 +17,6 @@ package core import ( - "encoding/json" "fmt" "math/big" "testing" @@ -268,9 +267,6 @@ func testReorg(t *testing.T, first, second []int64, td int64, full bool) { if full { prev := blockchain.engine.CurrentBlock() - b, _ := json.Marshal(prev) - fmt.Println("current block", string(b)) - for block := blockchain.engine.GetBlockByHash(prev.ParentHash()); block != nil; prev, block = block, blockchain.engine.GetBlockByHash(block.ParentHash()) { //for block := blockchain.GetBlockByNumber(blockchain.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, blockchain.GetBlockByNumber(block.NumberU64()-1) { diff --git a/core/cbfttypes/type.go b/core/cbfttypes/type.go index 5aed95247c..433d5bedc5 100644 --- a/core/cbfttypes/type.go +++ b/core/cbfttypes/type.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package cbfttypes import ( diff --git a/core/genesis.go b/core/genesis.go index 1bed775d0f..b39b63ffa7 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -155,7 +155,8 @@ func SetupGenesisBlock(db ethdb.Database, snapshotBaseDB snapshotdb.BaseDB, gene if (stored == common.Hash{}) { if genesis == nil { - panic("Please specify network") + log.Info("Writing default alaya network genesis block") + genesis = DefaultAlayaGenesisBlock() } else { log.Info("Writing custom genesis block", "chainID", genesis.Config.ChainID, "addressHRP", genesis.Config.AddressHRP) } @@ -228,7 +229,7 @@ func SetupGenesisBlock(db ethdb.Database, snapshotBaseDB snapshotdb.BaseDB, gene // Special case: don't change the existing config of a non-mainnet chain if no new // config is supplied. These chains would get AllProtocolChanges (and a compat error) // if we just continued here. - if genesis == nil && stored != params.MainnetGenesisHash { + if genesis == nil && stored != params.AlayanetGenesisHash { return storedcfg, stored, nil } @@ -335,14 +336,10 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig { switch { case g != nil: return g.Config - case ghash == params.MainnetGenesisHash: - return params.MainnetChainConfig case ghash == params.TestnetGenesisHash: return params.TestnetChainConfig case ghash == params.AlayanetGenesisHash: return params.AlayaChainConfig - case ghash == params.AlayaTestnetGenesisHash: - return params.AlayaTestChainConfig default: return params.AllEthashProtocolChanges } @@ -553,31 +550,6 @@ func DefaultAlayaGenesisBlock() *Genesis { return &genesis } -// DefaultGenesisBlock returns the PlatON main net genesis block. -func DefaultAlayaTestGenesisBlock() *Genesis { - - generalAddr := common.MustBech32ToAddress("atx1dl93r6fr022ca5yjqe6cgkg06er9pyqfaxyupd") - generalBalance, _ := new(big.Int).SetString("100000000000000000000000000", 10) - - rewardMgrPoolIssue, _ := new(big.Int).SetString("2000000000000000000000000", 10) - - genesis := Genesis{ - Config: params.AlayaTestChainConfig, - Nonce: hexutil.MustDecode("0x024c6378c176ef6c717cd37a74c612c9abd615d13873ff6651e3d352b31cb0b2e1"), - Timestamp: 1602973620000, - ExtraData: hexutil.MustDecode("0xd782070186706c61746f6e86676f312e3131856c696e757800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), - GasLimit: params.GenesisGasLimit, - Alloc: map[common.Address]GenesisAccount{ - vm.RewardManagerPoolAddr: {Balance: rewardMgrPoolIssue}, - generalAddr: {Balance: generalBalance}, - }, - EconomicModel: xcom.GetEc(xcom.DefaultAlayaTestNet), - } - xcom.SetNodeBlockTimeWindow(genesis.Config.Cbft.Period / 1000) - xcom.SetPerRoundBlocks(uint64(genesis.Config.Cbft.Amount)) - return &genesis -} - // DefaultTestnetGenesisBlock returns the PlatON test net genesis block. func DefaultTestnetGenesisBlock() *Genesis { diff --git a/core/parallel_state_processor.go b/core/parallel_state_processor.go index 558dae5768..20a35e452e 100644 --- a/core/parallel_state_processor.go +++ b/core/parallel_state_processor.go @@ -36,7 +36,7 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat if bcr != nil { // BeginBlocker() - if err := bcr.BeginBlocker(block.Header(), statedb); nil != err { + if err := bcr.BeginBlocker(header, statedb); nil != err { log.Error("Failed to call BeginBlocker on StateProcessor", "blockNumber", block.Number(), "blockHash", block.Hash(), "err", err) return nil, nil, 0, err @@ -78,7 +78,7 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat if bcr != nil { // EndBlocker() - if err := bcr.EndBlocker(block.Header(), statedb); nil != err { + if err := bcr.EndBlocker(header, statedb); nil != err { log.Error("Failed to call EndBlocker on StateProcessor", "blockNumber", block.Number(), "blockHash", block.Hash(), "err", err) return nil, nil, 0, err diff --git a/core/rawdb/accessors_metadata_test.go b/core/rawdb/accessors_metadata_test.go index bdaa2df6e3..594576e496 100644 --- a/core/rawdb/accessors_metadata_test.go +++ b/core/rawdb/accessors_metadata_test.go @@ -43,7 +43,7 @@ func TestReadWriteChainConfig(t *testing.T) { config := ReadChainConfig(chainDb, common.ZeroHash) assert.Nil(t, config, "the chainConfig is not nil") - WriteChainConfig(chainDb, common.ZeroHash, params.MainnetChainConfig) + WriteChainConfig(chainDb, common.ZeroHash, params.AlayaChainConfig) config = ReadChainConfig(chainDb, common.ZeroHash) assert.NotNil(t, config, "the chainConfig is nil") diff --git a/core/snapshotdb/bench_test.go b/core/snapshotdb/bench_test.go index 004df63ca5..ddc2f35d16 100644 --- a/core/snapshotdb/bench_test.go +++ b/core/snapshotdb/bench_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package snapshotdb import ( diff --git a/core/snapshotdb/blockdata.go b/core/snapshotdb/blockdata.go index d128a6d62d..bde7950626 100644 --- a/core/snapshotdb/blockdata.go +++ b/core/snapshotdb/blockdata.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package snapshotdb import ( diff --git a/core/snapshotdb/blockdata_test.go b/core/snapshotdb/blockdata_test.go index 1975cf24b3..3791db4984 100644 --- a/core/snapshotdb/blockdata_test.go +++ b/core/snapshotdb/blockdata_test.go @@ -1,3 +1,19 @@ +// Copyright 2021 The Alaya Network Authors +// This file is part of the Alaya-Go library. +// +// The Alaya-Go 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 Alaya-Go 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 Alaya-Go library. If not, see . + package snapshotdb import ( diff --git a/core/snapshotdb/chain_mock.go b/core/snapshotdb/chain_mock.go index c5344b73dc..d5f0cfacd8 100644 --- a/core/snapshotdb/chain_mock.go +++ b/core/snapshotdb/chain_mock.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package snapshotdb import ( diff --git a/core/snapshotdb/comparer.go b/core/snapshotdb/comparer.go index e03db4883e..862301aec5 100644 --- a/core/snapshotdb/comparer.go +++ b/core/snapshotdb/comparer.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package snapshotdb import "bytes" diff --git a/core/snapshotdb/current.go b/core/snapshotdb/current.go index f932d18e90..9326ffc3e0 100644 --- a/core/snapshotdb/current.go +++ b/core/snapshotdb/current.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package snapshotdb import ( diff --git a/core/snapshotdb/db.go b/core/snapshotdb/db.go index 1af3222872..efd7d2573e 100644 --- a/core/snapshotdb/db.go +++ b/core/snapshotdb/db.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package snapshotdb import ( @@ -84,7 +85,7 @@ func (s *snapshotDB) recover() error { sort.Sort(sortBlockWals) if len(sortBlockWals) > 0 { if sortBlockWals[0].Number > baseNum.Uint64()+1 { - return fmt.Errorf("wal is not enough,want recover from %v,have %v", baseNum.Uint64()+1, s.committed[0].Number.Uint64()) + return fmt.Errorf("wal is not enough,want recover from %v,have %v", baseNum.Uint64()+1, sortBlockWals[0].Number) } var journalBrokenNum uint64 diff --git a/core/snapshotdb/db_cron_job.go b/core/snapshotdb/db_cron_job.go index 5f8f14198e..70fc6328c5 100644 --- a/core/snapshotdb/db_cron_job.go +++ b/core/snapshotdb/db_cron_job.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package snapshotdb import ( diff --git a/core/snapshotdb/db_test.go b/core/snapshotdb/db_test.go index 9bddccb80e..5caae051e2 100644 --- a/core/snapshotdb/db_test.go +++ b/core/snapshotdb/db_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package snapshotdb import ( diff --git a/core/snapshotdb/heap.go b/core/snapshotdb/heap.go index 5828156064..84c1adebeb 100644 --- a/core/snapshotdb/heap.go +++ b/core/snapshotdb/heap.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package snapshotdb import ( diff --git a/core/snapshotdb/init_dev.go b/core/snapshotdb/init_dev.go index e55b7d7b98..64977eaba1 100644 --- a/core/snapshotdb/init_dev.go +++ b/core/snapshotdb/init_dev.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + // +build test package snapshotdb diff --git a/core/snapshotdb/init_prod.go b/core/snapshotdb/init_prod.go index cc2fea2fb3..bad9482a16 100644 --- a/core/snapshotdb/init_prod.go +++ b/core/snapshotdb/init_prod.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + // +build !test package snapshotdb diff --git a/core/snapshotdb/interface.go b/core/snapshotdb/interface.go index 762ac0030f..64ed293ef4 100644 --- a/core/snapshotdb/interface.go +++ b/core/snapshotdb/interface.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package snapshotdb import "github.com/AlayaNetwork/Alaya-Go/common" diff --git a/core/snapshotdb/journal.go b/core/snapshotdb/journal.go index 2509ffc40b..2edce8ce69 100644 --- a/core/snapshotdb/journal.go +++ b/core/snapshotdb/journal.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package snapshotdb import ( diff --git a/core/snapshotdb/journal_test.go b/core/snapshotdb/journal_test.go index d805e636ab..a8c208456c 100644 --- a/core/snapshotdb/journal_test.go +++ b/core/snapshotdb/journal_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package snapshotdb import ( diff --git a/core/snapshotdb/mem_db.go b/core/snapshotdb/mem_db.go index a69b5f6f3e..c5a56cbd00 100644 --- a/core/snapshotdb/mem_db.go +++ b/core/snapshotdb/mem_db.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package snapshotdb import ( diff --git a/core/snapshotdb/metrics.go b/core/snapshotdb/metrics.go index fc0a701800..45391c7b41 100644 --- a/core/snapshotdb/metrics.go +++ b/core/snapshotdb/metrics.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package snapshotdb import ( diff --git a/core/snapshotdb/snapshotdb.go b/core/snapshotdb/snapshotdb.go index e4eabe9307..96b7f7ffd7 100644 --- a/core/snapshotdb/snapshotdb.go +++ b/core/snapshotdb/snapshotdb.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package snapshotdb import ( @@ -47,7 +48,7 @@ const ( JournalRemain = 200 UnBlockNeedClean = 200 MaxBlockCompaction = 10 - MaxBlockCompactionSync = 100 + MaxBlockNotCompactionSync = 10 MaxBlockTriggerCompaction = 200 ) @@ -465,7 +466,8 @@ func (s *snapshotDB) findToWrite() int { commitNum int ) if len(s.committed) > MaxBlockTriggerCompaction { - commitNum = MaxBlockCompactionSync + // So that the number of remaining committed blocks is less than MaxBlockNotCompactionSync + commitNum = len(s.committed) - MaxBlockNotCompactionSync return commitNum } else { for i := 0; i < len(s.committed); i++ { diff --git a/core/snapshotdb/snapshotdb_test.go b/core/snapshotdb/snapshotdb_test.go index 779d609b09..54d4615dfe 100644 --- a/core/snapshotdb/snapshotdb_test.go +++ b/core/snapshotdb/snapshotdb_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package snapshotdb import ( diff --git a/core/snapshotdb/util.go b/core/snapshotdb/util.go index fa78c92a40..bc7ab1de16 100644 --- a/core/snapshotdb/util.go +++ b/core/snapshotdb/util.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package snapshotdb import ( diff --git a/core/state_processor.go b/core/state_processor.go index 6b28385125..1b3064fc3d 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -71,7 +71,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg if bcr != nil { // BeginBlocker() - if err := bcr.BeginBlocker(block.Header(), statedb); nil != err { + if err := bcr.BeginBlocker(header, statedb); nil != err { log.Error("Failed to call BeginBlocker on StateProcessor", "blockNumber", block.Number(), "blockHash", block.Hash(), "err", err) return nil, nil, 0, err @@ -96,7 +96,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg if bcr != nil { // EndBlocker() - if err := bcr.EndBlocker(block.Header(), statedb); nil != err { + if err := bcr.EndBlocker(header, statedb); nil != err { log.Error("Failed to call EndBlocker on StateProcessor", "blockNumber", block.Number(), "blockHash", block.Hash().TerminalString(), "err", err) return nil, nil, 0, err diff --git a/core/tx_cacher.go b/core/tx_cacher.go index c3d5ec8954..2b0821a747 100644 --- a/core/tx_cacher.go +++ b/core/tx_cacher.go @@ -105,58 +105,6 @@ func (cacher *txSenderCacher) recover(signer types.Signer, txs []*types.Transact } } -// recoverFromBlocks recovers the senders from a batch of blocks and caches them -// back into the same data structures. There is no validation being done, nor -// any reaction to invalid signatures. That is up to calling code later. -/*func (cacher *txSenderCacher) recoverFromBlocks(signer types.Signer, blocks []*types.Block) { - count := 0 - for _, block := range blocks { - count += len(block.Transactions()) - } - txs := make([]*types.Transaction, 0, count) - if cacher.txPool != nil { - for _, block := range blocks { - for _, tx := range block.Transactions() { - if txInPool := cacher.txPool.Get(tx.Hash()); txInPool != nil { - tx = txInPool - } else { - txs = append(txs, tx) - } - } - } - } else { - for _, block := range blocks { - for _, tx := range block.Transactions() { - txs = append(txs, tx) - } - } - } - - if len(txs) > 0 { - cacher.recover(signer, txs) - } -}*/ - -/*func (cacher *txSenderCacher) RecoverTxsFromPool(signer types.Signer, txs []*types.Transaction) chan struct{} { - // Ensure we have meaningful task sizes and schedule the recoveries - tasks := cacher.threads - if len(txs) < tasks*4 { - tasks = (len(txs) + 3) / 4 - } - - CalTx := make(chan struct{}, tasks) - for i := 0; i < tasks; i++ { - cacher.tasks <- &txSenderCacherRequest{ - signer: signer, - txs: txs, - inc: tasks, - done: CalTx, - starts: i, - } - } - return CalTx -}*/ - // recoverFromBlock recovers the senders from block and caches them // back into the same data structures. There is no validation being done, nor // any reaction to invalid signatures. That is up to calling code later. diff --git a/core/tx_pool.go b/core/tx_pool.go index fcb97e3eba..814191074d 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -272,7 +272,6 @@ type TxPool struct { gasPrice *big.Int txFeed event.Feed scope event.SubscriptionScope - // modified by PlatON signer types.Signer mu sync.RWMutex @@ -452,7 +451,6 @@ func (pool *TxPool) loop() { } } -// added by PlatON func (pool *TxPool) Reset(newBlock *types.Block) { startTime := time.Now() if pool == nil { @@ -464,7 +462,7 @@ func (pool *TxPool) Reset(newBlock *types.Block) { if newBlock != nil { // pool.mu.Lock() - pool.requestReset(pool.resetHead.Header(), newBlock.Header()) + <-pool.requestReset(pool.resetHead.Header(), newBlock.Header()) pool.resetHead = newBlock // pool.mu.Unlock() @@ -927,6 +925,17 @@ func (pool *TxPool) AddLocal(tx *types.Transaction) error { return errs[0] } +// Get returns a transaction if it is contained in the pool and nil otherwise. +func (pool *TxPool) Get(hash common.Hash) *types.Transaction { + return pool.all.Get(hash) +} + +// Has returns an indicator whether txpool has a transaction cached with the +// given hash. +func (pool *TxPool) Has(hash common.Hash) bool { + return pool.all.Get(hash) != nil +} + // AddRemotes enqueues a batch of transactions into the pool if they are valid. If the // senders are not among the locally tracked ones, full pricing constraints will apply. // @@ -1021,6 +1030,7 @@ func (pool *TxPool) addTxs(txs []*types.Transaction, local, sync bool) []error { nilSlot++ } errs[nilSlot] = err + nilSlot++ } if request { @@ -1073,11 +1083,6 @@ func (pool *TxPool) Status(hashes []common.Hash) []TxStatus { return status } -// Get returns a transaction if it is contained in the pool and nil otherwise. -func (pool *TxPool) Get(hash common.Hash) *types.Transaction { - return pool.all.Get(hash) -} - // removeTx removes a single transaction from the queue, moving all subsequent // transactions back to the future queue. func (pool *TxPool) removeTx(hash common.Hash, outofbound bool) { diff --git a/core/tx_pool_test.go b/core/tx_pool_test.go index 396907115d..2ebad1dbf2 100644 --- a/core/tx_pool_test.go +++ b/core/tx_pool_test.go @@ -113,7 +113,6 @@ func newTestTxPool(config TxPoolConfig, chainconfig *params.ChainConfig) *TxPool queue: make(map[common.Address]*txList), beats: make(map[common.Address]time.Time), all: newTxLookup(), - // modified by PlatON // chainHeadCh: make(chan ChainHeadEvent, chainHeadChanSize), exitCh: make(chan struct{}), gasPrice: new(big.Int).SetUint64(config.PriceLimit), @@ -142,7 +141,6 @@ func newTestTxPool(config TxPoolConfig, chainconfig *params.ChainConfig) *TxPool } } // Subscribe events from blockchain - // modified by PlatON //pool.chainHeadSub = pool.chain.SubscribeChainHeadEvent(pool.chainHeadCh) // Start the event loop and return @@ -924,7 +922,7 @@ func TestTransactionQueueTimeLimitingNoLocals(t *testing.T) { func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) { // Reduce the eviction interval to a testable amount defer func(old time.Duration) { evictionInterval = old }(evictionInterval) - evictionInterval = time.Second + evictionInterval = time.Millisecond * 100 // Create the pool to test the non-expiration enforcement config := testTxPoolConfig diff --git a/core/types/block.go b/core/types/block.go index 561f91e47a..a2cfbdb754 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -18,6 +18,7 @@ package types import ( + "crypto/ecdsa" "fmt" "io" "math/big" @@ -27,16 +28,18 @@ import ( "time" "unsafe" - "github.com/AlayaNetwork/Alaya-Go/crypto" - "github.com/AlayaNetwork/Alaya-Go/common" "github.com/AlayaNetwork/Alaya-Go/common/hexutil" + "github.com/AlayaNetwork/Alaya-Go/crypto" "github.com/AlayaNetwork/Alaya-Go/crypto/sha3" + "github.com/AlayaNetwork/Alaya-Go/log" "github.com/AlayaNetwork/Alaya-Go/rlp" ) var ( EmptyRootHash = DeriveSha(Transactions{}) + // Extra field in the block header, maximum length + ExtraMaxSize = 97 ) // BlockNonce is an 81-byte vrf proof containing random numbers @@ -82,8 +85,9 @@ type Header struct { Nonce BlockNonce `json:"nonce" gencodec:"required"` // caches - sealHash atomic.Value `json:"-" rlp:"-"` - hash atomic.Value `json:"-" rlp:"-"` + sealHash atomic.Value `json:"-" rlp:"-"` + hash atomic.Value `json:"-" rlp:"-"` + publicKey atomic.Value `json:"-" rlp:"-"` } // field type overrides for gencodec @@ -111,37 +115,54 @@ func (h *Header) CacheHash() common.Hash { return v } +func (h *Header) CachePublicKey() *ecdsa.PublicKey { + if pk := h.publicKey.Load(); pk != nil { + return pk.(*ecdsa.PublicKey) + } + + sign := h.Extra[32:97] + sealhash := h.SealHash().Bytes() + + pk, err := crypto.SigToPub(sealhash, sign) + if err != nil { + log.Error("cache publicKey fail,sigToPub fail", "err", err) + return nil + } + h.publicKey.Store(pk) + return pk +} + // SealHash returns the keccak256 seal hash of b's header. // The seal hash is computed on the first call and cached thereafter. -func (header *Header) SealHash() (hash common.Hash) { - if sealHash := header.sealHash.Load(); sealHash != nil { +func (h *Header) SealHash() (hash common.Hash) { + if sealHash := h.sealHash.Load(); sealHash != nil { return sealHash.(common.Hash) } - v := header._sealHash() - header.sealHash.Store(v) + v := h._sealHash() + h.sealHash.Store(v) return v } -func (header *Header) _sealHash() (hash common.Hash) { - extra := header.Extra +func (h *Header) _sealHash() (hash common.Hash) { + extra := h.Extra hasher := sha3.NewKeccak256() - if len(header.Extra) > 32 { - extra = header.Extra[0:32] + if len(h.Extra) > 32 { + extra = h.Extra[0:32] } rlp.Encode(hasher, []interface{}{ - header.ParentHash, - header.Coinbase, - header.Root, - header.TxHash, - header.ReceiptHash, - header.Bloom, - header.Number, - header.GasLimit, - header.GasUsed, - header.Time, + h.ParentHash, + h.Coinbase, + h.Root, + h.TxHash, + h.ReceiptHash, + h.Bloom, + h.Number, + h.GasLimit, + h.GasUsed, + h.Time, extra, - header.Nonce, + h.Nonce, }) hasher.Sum(hash[:0]) @@ -162,6 +183,18 @@ func (h *Header) Signature() []byte { return h.Extra[32:] } +func (h *Header) ExtraData() []byte { + if len(h.Extra) < 32 { + return []byte{} + } + return h.Extra[:32] +} + +// Check whether the Extra field exceeds the limit size +func (h *Header) IsInvalid() bool { + return len(h.Extra) > ExtraMaxSize +} + // hasherPool holds Keccak hashers. var hasherPool = sync.Pool{ New: func() interface{} { diff --git a/core/types/receipt.go b/core/types/receipt.go index 99cd779f75..e6f2b5f9a1 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -92,16 +92,6 @@ type storedReceiptRLP struct { Logs []*LogForStorage } -type v3StoredReceiptRLP struct { - PostStateOrStatus []byte - CumulativeGasUsed uint64 - Bloom Bloom - TxHash common.Hash - ContractAddress common.Address - Logs []*LogForStorage - GasUsed uint64 -} - // NewReceipt creates a barebone transaction receipt, copying the init fields. func NewReceipt(root []byte, failed bool, cumulativeGasUsed uint64) *Receipt { r := &Receipt{PostState: common.CopyBytes(root), CumulativeGasUsed: cumulativeGasUsed} @@ -199,9 +189,6 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { // for old nodes that just upgraded. if err := decodeStoredReceiptRLP(r, blob); err == nil { return nil - } - if err := decodeV3StoredReceiptRLP(r, blob); err == nil { - return nil } else { return err } @@ -225,26 +212,6 @@ func decodeStoredReceiptRLP(r *ReceiptForStorage, blob []byte) error { return nil } -func decodeV3StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error { - var stored v3StoredReceiptRLP - if err := rlp.DecodeBytes(blob, &stored); err != nil { - return err - } - if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil { - return err - } - r.CumulativeGasUsed = stored.CumulativeGasUsed - r.Bloom = stored.Bloom - r.TxHash = stored.TxHash - r.ContractAddress = stored.ContractAddress - r.GasUsed = stored.GasUsed - r.Logs = make([]*Log, len(stored.Logs)) - for i, log := range stored.Logs { - r.Logs[i] = (*Log)(log) - } - return nil -} - // Receipts is a wrapper around a Receipt array to implement DerivableList. type Receipts []*Receipt diff --git a/core/vm/common_test.go b/core/vm/common_test.go index 691eb03ffc..521e771782 100644 --- a/core/vm/common_test.go +++ b/core/vm/common_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/vm/contract_test.go b/core/vm/contract_test.go index 4adad09e0b..1b5700e879 100644 --- a/core/vm/contract_test.go +++ b/core/vm/contract_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/vm/delegate_reward_contract.go b/core/vm/delegate_reward_contract.go index 977bf4c338..ea8bed0acf 100644 --- a/core/vm/delegate_reward_contract.go +++ b/core/vm/delegate_reward_contract.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/vm/delegate_reward_contract_test.go b/core/vm/delegate_reward_contract_test.go index 635979c1b4..67d363b819 100644 --- a/core/vm/delegate_reward_contract_test.go +++ b/core/vm/delegate_reward_contract_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/vm/gas_test.go b/core/vm/gas_test.go index e4b04f7670..919f7bb142 100644 --- a/core/vm/gas_test.go +++ b/core/vm/gas_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/vm/gov_contract.go b/core/vm/gov_contract.go index 934e704c75..3e329ee38a 100644 --- a/core/vm/gov_contract.go +++ b/core/vm/gov_contract.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -131,13 +131,12 @@ func (gc *GovContract) submitText(verifier discover.NodeID, pipID string) ([]byt return nil, ErrOutOfGas } - if gc.Evm.GasPrice.Cmp(params.SubmitTextProposalGasPrice) < 0 { - return nil, ErrUnderPrice - } - if txHash == common.ZeroHash { return nil, nil } + if gc.Evm.GasPrice.Cmp(params.SubmitTextProposalGasPrice) < 0 { + return nil, ErrUnderPrice + } p := &gov.TextProposal{ PIPID: pipID, @@ -171,14 +170,14 @@ func (gc *GovContract) submitVersion(verifier discover.NodeID, pipID string, new return nil, ErrOutOfGas } - if gc.Evm.GasPrice.Cmp(params.SubmitVersionProposalGasPrice) < 0 { - return nil, ErrUnderPrice - } - if txHash == common.ZeroHash { return nil, nil } + if gc.Evm.GasPrice.Cmp(params.SubmitVersionProposalGasPrice) < 0 { + return nil, ErrUnderPrice + } + p := &gov.VersionProposal{ PIPID: pipID, ProposalType: gov.Version, @@ -212,12 +211,14 @@ func (gc *GovContract) submitCancel(verifier discover.NodeID, pipID string, endV return nil, ErrOutOfGas } - if gc.Evm.GasPrice.Cmp(params.SubmitCancelProposalGasPrice) < 0 { - return nil, ErrUnderPrice - } if txHash == common.ZeroHash { return nil, nil } + + if gc.Evm.GasPrice.Cmp(params.SubmitCancelProposalGasPrice) < 0 { + return nil, ErrUnderPrice + } + p := &gov.CancelProposal{ PIPID: pipID, EndVotingRounds: endVotingRounds, @@ -251,13 +252,14 @@ func (gc *GovContract) submitParam(verifier discover.NodeID, pipID string, modul return nil, ErrOutOfGas } + if txHash == common.ZeroHash { + return nil, nil + } + if gc.Evm.GasPrice.Cmp(params.SubmitParamProposalGasPrice) < 0 { return nil, ErrUnderPrice } - if txHash == common.ZeroHash { - return nil, nil - } p := &gov.ParamProposal{ PIPID: pipID, ProposalType: gov.Param, diff --git a/core/vm/gov_contract_test.go b/core/vm/gov_contract_test.go index 1a0c19e7d8..edcb6b1b82 100644 --- a/core/vm/gov_contract_test.go +++ b/core/vm/gov_contract_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/vm/interface.go b/core/vm/interface.go index 400a4e461f..7e500cf9c1 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -74,6 +74,8 @@ type StateDB interface { TxIdx() uint32 IntermediateRoot(deleteEmptyObjects bool) common.Hash + + GetCurrentActiveVersion() uint32 } // MerkleProof diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 182f66c625..ca86b520d2 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -139,8 +139,10 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( go func(ctx context.Context) { <-ctx.Done() - // shutdown vm, change th vm.abort mark - in.evm.Cancel() + if err := ctx.Err(); err != nil && context.DeadlineExceeded == err { + // shutdown vm, change th vm.abort mark + in.evm.Cancel() + } }(in.evm.Ctx) // Increment the call depth which is restricted to 1024 diff --git a/core/vm/memory_table_test.go b/core/vm/memory_table_test.go index 417bc1400c..a3755cb282 100644 --- a/core/vm/memory_table_test.go +++ b/core/vm/memory_table_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/vm/memory_test.go b/core/vm/memory_test.go index 36a8f8c297..c598b47512 100644 --- a/core/vm/memory_test.go +++ b/core/vm/memory_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/vm/opcodes_test.go b/core/vm/opcodes_test.go index e1093d0849..eefad11cdc 100644 --- a/core/vm/opcodes_test.go +++ b/core/vm/opcodes_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/vm/platon_contract_test.go b/core/vm/platon_contract_test.go index ef8f518571..6e86fd2973 100644 --- a/core/vm/platon_contract_test.go +++ b/core/vm/platon_contract_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -926,7 +926,7 @@ func buildDbRestrictingPlan(t *testing.T, account common.Address, balance *big.I var user restricting.RestrictingInfo user.ReleaseList = list user.CachePlanAmount = lockAmount - user.StakingAmount = big.NewInt(0) + user.AdvanceAmount = big.NewInt(0) user.NeedRelease = big.NewInt(0) bUser, err := rlp.EncodeToBytes(user) diff --git a/core/vm/platon_contract_tool.go b/core/vm/platon_contract_tool.go index 2c3a0477ff..37aa36436a 100644 --- a/core/vm/platon_contract_tool.go +++ b/core/vm/platon_contract_tool.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/vm/restricting_contract.go b/core/vm/restricting_contract.go index b92595534e..ae20dfa3c1 100644 --- a/core/vm/restricting_contract.go +++ b/core/vm/restricting_contract.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -67,7 +67,7 @@ func (rc *RestrictingContract) CheckGasPrice(gasPrice *big.Int, fcode uint16) er return nil } -// createRestrictingPlan is a PlatON precompiled contract function, used for create a restricting plan +// createRestrictingPlan is a Alaya precompiled contract function, used for create a restricting plan func (rc *RestrictingContract) createRestrictingPlan(account common.Address, plans []restricting.RestrictingPlan) ([]byte, error) { //sender := rc.Contract.Caller() @@ -103,7 +103,7 @@ func (rc *RestrictingContract) createRestrictingPlan(account common.Address, pla } } -// createRestrictingPlan is a PlatON precompiled contract function, used for getting restricting info. +// createRestrictingPlan is a Alaya precompiled contract function, used for getting restricting info. // first output param is a slice of byte of restricting info; // the secend output param is the result what plugin executed GetRestrictingInfo returns. func (rc *RestrictingContract) getRestrictingInfo(account common.Address) ([]byte, error) { diff --git a/core/vm/restricting_contract_test.go b/core/vm/restricting_contract_test.go index 366723f6aa..d8082fd493 100644 --- a/core/vm/restricting_contract_test.go +++ b/core/vm/restricting_contract_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -38,7 +38,7 @@ func buildRestrictingPlanData() ([]byte, error) { for index := 0; index < len(plans); index++ { epoch = uint64(index + 1) plan.Epoch = uint64(epoch) - plan.Amount = big.NewInt(1E18) + plan.Amount = big.NewInt(1e18) plans[index] = plan } @@ -60,7 +60,7 @@ func buildErrorRestrictingPlanData() ([]byte, error) { var plans = make([]restricting.RestrictingPlan, 1) plan.Epoch = uint64(0) - plan.Amount = big.NewInt(1E18) + plan.Amount = big.NewInt(1e18) plans[0] = plan var params [][]byte diff --git a/core/vm/slashing_contract.go b/core/vm/slashing_contract.go index 5745fb7f34..de6d9f3b34 100644 --- a/core/vm/slashing_contract.go +++ b/core/vm/slashing_contract.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/vm/slashing_contract_test.go b/core/vm/slashing_contract_test.go index 15cbc2c7ad..aac8534a85 100644 --- a/core/vm/slashing_contract_test.go +++ b/core/vm/slashing_contract_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/vm/staking_contract.go b/core/vm/staking_contract.go index 06a83affdc..8c484a902f 100644 --- a/core/vm/staking_contract.go +++ b/core/vm/staking_contract.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -47,21 +47,21 @@ import ( ) const ( - TxCreateStaking = 1000 - TxEditorCandidate = 1001 - TxIncreaseStaking = 1002 - TxWithdrewCandidate = 1003 - TxDelegate = 1004 - TxWithdrewDelegate = 1005 - QueryVerifierList = 1100 - QueryValidatorList = 1101 - QueryCandidateList = 1102 - QueryRelateList = 1103 - QueryDelegateInfo = 1104 - QueryCandidateInfo = 1105 - GetPackageReward = 1200 - GetStakingReward = 1201 - GetAvgPackTime = 1202 + TxCreateStaking = 1000 + TxEditorCandidate = 1001 + TxIncreaseStaking = 1002 + TxWithdrewCandidate = 1003 + TxDelegate = 1004 + TxWithdrewDelegation = 1005 + QueryVerifierList = 1100 + QueryValidatorList = 1101 + QueryCandidateList = 1102 + QueryRelateList = 1103 + QueryDelegateInfo = 1104 + QueryCandidateInfo = 1105 + GetPackageReward = 1200 + GetStakingReward = 1201 + GetAvgPackTime = 1202 ) const ( @@ -96,12 +96,12 @@ func (stkc *StakingContract) CheckGasPrice(gasPrice *big.Int, fcode uint16) erro func (stkc *StakingContract) FnSigns() map[uint16]interface{} { return map[uint16]interface{}{ // Set - TxCreateStaking: stkc.createStaking, - TxEditorCandidate: stkc.editCandidate, - TxIncreaseStaking: stkc.increaseStaking, - TxWithdrewCandidate: stkc.withdrewStaking, - TxDelegate: stkc.delegate, - TxWithdrewDelegate: stkc.withdrewDelegate, + TxCreateStaking: stkc.createStaking, + TxEditorCandidate: stkc.editCandidate, + TxIncreaseStaking: stkc.increaseStaking, + TxWithdrewCandidate: stkc.withdrewStaking, + TxDelegate: stkc.delegate, + TxWithdrewDelegation: stkc.withdrewDelegation, // Get QueryVerifierList: stkc.getVerifierList, @@ -767,7 +767,7 @@ func (stkc *StakingContract) delegate(typ uint16, nodeId discover.NodeID, amount "", TxDelegate, common.NoErr) } -func (stkc *StakingContract) withdrewDelegate(stakingBlockNum uint64, nodeId discover.NodeID, amount *big.Int) ([]byte, error) { +func (stkc *StakingContract) withdrewDelegation(stakingBlockNum uint64, nodeId discover.NodeID, amount *big.Int) ([]byte, error) { txHash := stkc.Evm.StateDB.TxHash() blockNumber := stkc.Evm.BlockNumber @@ -775,17 +775,17 @@ func (stkc *StakingContract) withdrewDelegate(stakingBlockNum uint64, nodeId dis from := stkc.Contract.CallerAddress state := stkc.Evm.StateDB - log.Debug("Call withdrewDelegate of stakingContract", "txHash", txHash.Hex(), + log.Debug("Call withdrewDelegation of stakingContract", "txHash", txHash.Hex(), "blockNumber", blockNumber.Uint64(), "delAddr", from, "nodeId", nodeId.String(), "stakingNum", stakingBlockNum, "amount", amount) - if !stkc.Contract.UseGas(params.WithdrewDelegateGas) { + if !stkc.Contract.UseGas(params.WithdrewDelegationGas) { return nil, ErrOutOfGas } del, err := stkc.Plugin.GetDelegateInfo(blockHash, from, nodeId, stakingBlockNum) if snapshotdb.NonDbNotFoundErr(err) { - log.Error("Failed to withdrewDelegate by GetDelegateInfo", + log.Error("Failed to withdrewDelegation by GetDelegateInfo", "txHash", txHash.Hex(), "blockNumber", blockNumber, "err", err) return nil, err } @@ -794,8 +794,8 @@ func (stkc *StakingContract) withdrewDelegate(stakingBlockNum uint64, nodeId dis if txHash == common.ZeroHash { return nil, nil } else { - return txResultHandler(vm.StakingContractAddr, stkc.Evm, "withdrewDelegate", - "del is nil", TxWithdrewDelegate, staking.ErrDelegateNoExist) + return txResultHandler(vm.StakingContractAddr, stkc.Evm, "withdrewDelegation", + "del is nil", TxWithdrewDelegation, staking.ErrDelegateNoExist) } } @@ -812,30 +812,30 @@ func (stkc *StakingContract) withdrewDelegate(stakingBlockNum uint64, nodeId dis if ok, threshold := plugin.CheckOperatingThreshold(blockNumber.Uint64(), blockHash, amount); !ok { - return txResultHandler(vm.StakingContractAddr, stkc.Evm, "withdrewDelegate", - fmt.Sprintf("withdrewDelegate threshold: %d, deposit: %d", threshold, amount), - TxWithdrewDelegate, staking.ErrWithdrewDelegateVonTooLow) + return txResultHandler(vm.StakingContractAddr, stkc.Evm, "withdrewDelegation", + fmt.Sprintf("withdrewDelegation threshold: %d, deposit: %d", threshold, amount), + TxWithdrewDelegation, staking.ErrWithdrewDelegationVonTooLow) } if txHash == common.ZeroHash { return nil, nil } - issueIncome, err := stkc.Plugin.WithdrewDelegate(state, blockHash, blockNumber, amount, from, nodeId, stakingBlockNum, del, delegateRewardPerList) + issueIncome, err := stkc.Plugin.WithdrewDelegation(state, blockHash, blockNumber, amount, from, nodeId, stakingBlockNum, del, delegateRewardPerList) if nil != err { if bizErr, ok := err.(*common.BizError); ok { - return txResultHandler(vm.StakingContractAddr, stkc.Evm, "withdrewDelegate", - bizErr.Error(), TxWithdrewDelegate, bizErr) + return txResultHandler(vm.StakingContractAddr, stkc.Evm, "withdrewDelegation", + bizErr.Error(), TxWithdrewDelegation, bizErr) } else { - log.Error("Failed to withdrewDelegate by WithdrewDelegate", "txHash", txHash, "blockNumber", blockNumber, "err", err) + log.Error("Failed to withdrewDelegation by WithdrewDelegation", "txHash", txHash, "blockNumber", blockNumber, "err", err) return nil, err } } return txResultHandlerWithRes(vm.StakingContractAddr, stkc.Evm, "", - "", TxWithdrewDelegate, int(common.NoErr.Code), issueIncome), nil + "", TxWithdrewDelegation, int(common.NoErr.Code), issueIncome), nil } func (stkc *StakingContract) calcRewardPerUseGas(delegateRewardPerList []*reward.DelegateRewardPer, del *staking.Delegation) ([]byte, error) { diff --git a/core/vm/staking_contract_test.go b/core/vm/staking_contract_test.go index f5522c57b8..639b570a8c 100644 --- a/core/vm/staking_contract_test.go +++ b/core/vm/staking_contract_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -1181,7 +1181,7 @@ func TestStakingContract_delegate(t *testing.T) { } -func TestStakingContract_withdrewDelegate(t *testing.T) { +func TestStakingContract_withdrewDelegation(t *testing.T) { state, genesis, _ := newChainState() newPlugins() @@ -1240,7 +1240,7 @@ func TestStakingContract_withdrewDelegate(t *testing.T) { state.Prepare(txHashArr[2], blockHash2, 0) - // withdrewDelegate + // withdrewDelegation var params [][]byte params = make([][]byte, 0) @@ -1255,7 +1255,7 @@ func TestStakingContract_withdrewDelegate(t *testing.T) { params = append(params, nodeId) params = append(params, amount) - runContractSendTransaction(contract2, params, "withdrewDelegate", t) + runContractSendTransaction(contract2, params, "withdrewDelegation", t) if err := sndb.Commit(blockHash2); nil != err { t.Errorf("Failed to commit snapshotdb, blockNumber: %d, blockHash: %s, err: %v", blockNumber2, blockHash2.Hex(), err) diff --git a/core/vm/staking_contract_whitebox_test.go b/core/vm/staking_contract_whitebox_test.go index e22ab9b60d..572626b882 100644 --- a/core/vm/staking_contract_whitebox_test.go +++ b/core/vm/staking_contract_whitebox_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/vm/validator_inner_contract.go b/core/vm/validator_inner_contract.go index 8bb6e4d630..858831949f 100644 --- a/core/vm/validator_inner_contract.go +++ b/core/vm/validator_inner_contract.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/core/vm/wagon_runtime.go b/core/vm/wagon_runtime.go index cedad6d6e9..609a3ff734 100644 --- a/core/vm/wagon_runtime.go +++ b/core/vm/wagon_runtime.go @@ -828,16 +828,24 @@ func BlockHash(proc *exec.Process, num uint64, dst uint32) { ctx := proc.HostCtx().(*VMContext) checkGas(ctx, GasExtStep) - // Add get block height limit, same as evm opBlockhash - var upper, lower uint64 - upper = ctx.evm.BlockNumber.Uint64() - if upper < 257 { - lower = 0 - } else { - lower = upper - 256 - } + // get current version + currentValue := ctx.evm.StateDB.GetCurrentActiveVersion() + + // get block hash var blockHash common.Hash - if num >= lower && num < upper { + if currentValue >= params.FORKVERSION_0_16_0 { + // Add get block height limit, same as evm opBlockhash + var upper, lower uint64 + upper = ctx.evm.BlockNumber.Uint64() + if upper < 257 { + lower = 0 + } else { + lower = upper - 256 + } + if num >= lower && num < upper { + blockHash = ctx.evm.GetHash(num) + } + } else { blockHash = ctx.evm.GetHash(num) } @@ -909,7 +917,17 @@ func Origin(proc *exec.Process, dst uint32) { func Caller(proc *exec.Process, dst uint32) { ctx := proc.HostCtx().(*VMContext) checkGas(ctx, GasQuickStep) - _, err := proc.WriteAt(ctx.contract.caller.Address().Bytes(), int64(dst)) + + // get current version + currentValue := ctx.evm.StateDB.GetCurrentActiveVersion() + + // get caller address + callerAddress := ctx.contract.caller.Address().Bytes() + if currentValue >= params.FORKVERSION_0_16_0 { + callerAddress = ctx.contract.Caller().Bytes() + } + + _, err := proc.WriteAt(callerAddress, int64(dst)) if nil != err { panic(err) } diff --git a/core/vm/wagon_runtime_test.go b/core/vm/wagon_runtime_test.go index 15eb8d0f54..cd3a5c55cc 100644 --- a/core/vm/wagon_runtime_test.go +++ b/core/vm/wagon_runtime_test.go @@ -5,13 +5,17 @@ import ( "context" "crypto/sha256" "encoding/binary" - "github.com/PlatONnetwork/PlatON-Go/common/hexutil" + "encoding/json" "hash/fnv" "io/ioutil" "math/big" "strings" "testing" + "github.com/AlayaNetwork/Alaya-Go/common/hexutil" + "github.com/AlayaNetwork/Alaya-Go/common/vm" + "github.com/AlayaNetwork/Alaya-Go/x/gov" + "github.com/AlayaNetwork/Alaya-Go/params" "golang.org/x/crypto/ripemd160" @@ -55,9 +59,20 @@ var testCase = []*Case{ GetHash: func(u uint64) common.Hash { return common.Hash{1, 2, 3} }}, + StateDB: &mock.MockStateDB{ + Balance: make(map[common.Address]*big.Int), + State: make(map[common.Address]map[string][]byte), + Journal: mock.NewJournal(), + }, }, }, funcName: "platon_block_hash_test", + init: func(self *Case, t *testing.T) { + curAv := gov.ActiveVersionValue{ActiveVersion: params.FORKVERSION_0_16_0, ActiveBlock: 1} + avList := []gov.ActiveVersionValue{curAv} + avListBytes, _ := json.Marshal(avList) + self.ctx.evm.StateDB.SetState(vm.GovContractAddr, gov.KeyActiveVersions(), avListBytes) + }, check: func(self *Case, err error) bool { hash := common.Hash{1, 2, 3} return bytes.Equal(hash[:], self.ctx.Output) @@ -167,8 +182,26 @@ var testCase = []*Case{ }, { ctx: &VMContext{ - contract: &Contract{caller: AccountRef{1, 2, 3}}}, + contract: &Contract{caller: &AccountRef{1, 2, 3}}, + evm: &EVM{Context: Context{ + BlockNumber: big.NewInt(99), + GetHash: func(u uint64) common.Hash { + return common.Hash{1, 2, 3} + }}, + StateDB: &mock.MockStateDB{ + Balance: make(map[common.Address]*big.Int), + State: make(map[common.Address]map[string][]byte), + Journal: mock.NewJournal(), + }, + }, + }, funcName: "platon_caller_test", + init: func(self *Case, t *testing.T) { + curAv := gov.ActiveVersionValue{ActiveVersion: params.FORKVERSION_0_15_0, ActiveBlock: 1} + avList := []gov.ActiveVersionValue{curAv} + avListBytes, _ := json.Marshal(avList) + self.ctx.evm.StateDB.SetState(vm.GovContractAddr, gov.KeyActiveVersions(), avListBytes) + }, check: func(self *Case, err error) bool { addr := addr1 return bytes.Equal(addr[:], self.ctx.Output) @@ -1588,6 +1621,11 @@ func TestGetBlockHash(t *testing.T) { }, BlockNumber: big.NewInt(blockNumber), }, + StateDB: &mock.MockStateDB{ + Balance: make(map[common.Address]*big.Int), + State: make(map[common.Address]map[string][]byte), + Journal: mock.NewJournal(), + }, })) } @@ -1596,15 +1634,44 @@ func TestGetBlockHash(t *testing.T) { getNumber uint64 expect common.Hash } - cases := []TestCase{ + + // Before upgrading + casesBeforUpgrade := []TestCase{ + {1, 123, testBlockHash}, + {123, 123, testBlockHash}, + {123, 122, testBlockHash}, + {1024, 122, testBlockHash}, + {1024, 1024 - 256, testBlockHash}, + } + for _, c := range casesBeforUpgrade { + proc := newProc(c.blockNumber) + ctx := proc.HostCtx().(*VMContext) + curAv := gov.ActiveVersionValue{ActiveVersion: params.FORKVERSION_0_15_0, ActiveBlock: 1} + avList := []gov.ActiveVersionValue{curAv} + avListBytes, _ := json.Marshal(avList) + ctx.evm.StateDB.SetState(vm.GovContractAddr, gov.KeyActiveVersions(), avListBytes) + BlockHash(proc, c.getNumber, 1024) + res := common.Hash{} + proc.ReadAt(res[:], 1024) + assert.Equal(t, c.expect, res) + assert.Equal(t, initExternalGas-GasExtStep, proc.HostCtx().(*VMContext).contract.Gas) + } + + // After the upgrade + casesAfterUpgrade := []TestCase{ {1, 123, common.Hash{}}, {123, 123, common.Hash{}}, {123, 122, testBlockHash}, {1024, 122, common.Hash{}}, {1024, 1024 - 256, testBlockHash}, } - for _, c := range cases { + for _, c := range casesAfterUpgrade { proc := newProc(c.blockNumber) + ctx := proc.HostCtx().(*VMContext) + curAv := gov.ActiveVersionValue{ActiveVersion: params.FORKVERSION_0_16_0, ActiveBlock: 1} + avList := []gov.ActiveVersionValue{curAv} + avListBytes, _ := json.Marshal(avList) + ctx.evm.StateDB.SetState(vm.GovContractAddr, gov.KeyActiveVersions(), avListBytes) BlockHash(proc, c.getNumber, 1024) res := common.Hash{} proc.ReadAt(res[:], 1024) diff --git a/crypto/rfc6979/rfc6979_test.go b/crypto/rfc6979/rfc6979_test.go index b9a6a937c3..03a76f88b5 100644 --- a/crypto/rfc6979/rfc6979_test.go +++ b/crypto/rfc6979/rfc6979_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/crypto/secp256k1/secp256.go b/crypto/secp256k1/secp256.go index cfcff989f5..765ff3dae2 100644 --- a/crypto/secp256k1/secp256.go +++ b/crypto/secp256k1/secp256.go @@ -8,10 +8,19 @@ package secp256k1 /* #cgo CFLAGS: -I./libsecp256k1 #cgo CFLAGS: -I./libsecp256k1/src/ + +#ifdef __SIZEOF_INT128__ +# define HAVE___INT128 +# define USE_FIELD_5X52 +# define USE_SCALAR_4X64 +#else +# define USE_FIELD_10X26 +# define USE_SCALAR_8X32 +#endif + +#define USE_ENDOMORPHISM #define USE_NUM_NONE -#define USE_FIELD_10X26 #define USE_FIELD_INV_BUILTIN -#define USE_SCALAR_8X32 #define USE_SCALAR_INV_BUILTIN #define NDEBUG #include "./libsecp256k1/src/secp256k1.c" @@ -26,9 +35,9 @@ import "C" import ( "errors" + "github.com/AlayaNetwork/Alaya-Go/common/math" "math/big" "unsafe" - "github.com/AlayaNetwork/Alaya-Go/common/math" ) var context *C.secp256k1_context @@ -173,6 +182,5 @@ func PubkeyNotInfinity(x, y *big.Int) bool { math.ReadBits(y, point[32:]) pointPtr := (*C.uchar)(unsafe.Pointer(&point[0])) res := C.secp256k1_pubkey_is_infinity(context, pointPtr) - return res ==0 + return res == 0 } - diff --git a/crypto/vrf/vrf.go b/crypto/vrf/vrf.go index 026d7418d0..3606c05006 100644 --- a/crypto/vrf/vrf.go +++ b/crypto/vrf/vrf.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/crypto/vrf/vrf_secp256k1.go b/crypto/vrf/vrf_secp256k1.go index d6b84badf7..33bfcc4f66 100644 --- a/crypto/vrf/vrf_secp256k1.go +++ b/crypto/vrf/vrf_secp256k1.go @@ -1,18 +1,18 @@ -// Copyright 2017 The PlatON Authors -// This file is part of the PlatON library. +// Copyright 2021 The Alaya Network Authors +// This file is part of the Alaya-Go library. // -// The PlatON library is free software: you can redistribute it and/or modify +// The Alaya-Go 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 PlatON library is distributed in the hope that it will be useful, +// The Alaya-Go 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 PlatON library. If not, see . +// along with the Alaya-Go library. If not, see . // +build !nacl,!js,!nocgo diff --git a/crypto/vrf/vrf_test.go b/crypto/vrf/vrf_test.go index 3177b7256c..9dcaa4728b 100644 --- a/crypto/vrf/vrf_test.go +++ b/crypto/vrf/vrf_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/eth/api_tps_cal.go b/eth/api_tps_cal.go index 6a48acb49c..3797b26e9c 100644 --- a/eth/api_tps_cal.go +++ b/eth/api_tps_cal.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "log" + "math" "os" "sort" "strconv" @@ -41,6 +42,10 @@ type AnalystEntity struct { // output,Calculated pressure test result,file type:xlsx // t,Average statistical time func (txg *TxGenAPI) CalRes(configPaths []string, output string, t int) error { + return AnalyzeStressTest(configPaths, output, t) +} + +func AnalyzeStressTest(configPaths []string, output string, t int) error { x := make(BlockInfos, 0) sendTotal := uint64(0) for _, path := range configPaths { @@ -61,17 +66,14 @@ func (txg *TxGenAPI) CalRes(configPaths []string, output string, t int) error { } sort.Sort(x) endTime := common.MillisToTime(x[0].ProduceTime).Add(time.Second * time.Duration(t)) - txConut := 0 + txConut, total := 0, 0 latency, ttf := int64(0), int64(0) analysts := make([][4]int64, 0) - total := 0 for _, info := range x { total += info.TxLength - for common.MillisToTime(info.ProduceTime).After(endTime) { - latRes := time.Duration(0).Milliseconds() - tpsRes := int64(0) - ttfRes := time.Duration(0).Milliseconds() + if common.MillisToTime(info.ProduceTime).After(endTime) { + latRes, ttfRes, tpsRes := time.Duration(0).Milliseconds(), time.Duration(0).Milliseconds(), int64(0) if txConut > 0 { latRes = time.Duration(int64(float64(latency) / float64(txConut))).Milliseconds() tpsRes = int64(txConut) / int64(t) @@ -98,6 +100,18 @@ func (txg *TxGenAPI) CalRes(configPaths []string, output string, t int) error { return err } + sumTx := int64(0) + for _, analyst := range analysts { + sumTx += analyst[2] + } + + avg := sumTx / int64(len(analysts)) + powTx := float64(0) + for _, analyst := range analysts { + powTx += math.Pow(float64(analyst[2]-avg), 2) + } + std := math.Sqrt(powTx / float64(len(analysts))) + // add title row := sheet.AddRow() cell_1 := row.AddCell() @@ -112,6 +126,8 @@ func (txg *TxGenAPI) CalRes(configPaths []string, output string, t int) error { cell_6.Value = "totalReceive" cell_7 := row.AddCell() cell_7.Value = "totalSend" + cell_8 := row.AddCell() + cell_8.Value = "standardDeviation" //add data for i, d := range analysts { @@ -121,14 +137,16 @@ func (txg *TxGenAPI) CalRes(configPaths []string, output string, t int) error { latencyCell := row.AddCell() latencyCell.Value = strconv.FormatInt(d[1], 10) tpsCell := row.AddCell() - tpsCell.Value = strconv.FormatInt(d[2], 10) + tpsCell.SetInt64(d[2]) ttfCell := row.AddCell() - ttfCell.Value = strconv.FormatInt(d[3], 10) + ttfCell.SetInt64(d[3]) if i == 0 { totalReceive := row.AddCell() totalReceive.Value = strconv.FormatInt(int64(total), 10) totalSend := row.AddCell() totalSend.Value = strconv.FormatInt(int64(sendTotal), 10) + stdTps := row.AddCell() + stdTps.Value = strconv.FormatFloat(std, 'f', 2, 64) } } err = xlsxFile.Save(output) diff --git a/eth/backend.go b/eth/backend.go index d64fe835c5..c057c43e26 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -158,7 +158,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { // Just commit the new block if there is no stored genesis block. stored := rawdb.ReadCanonicalHash(chainDb, 0) - log.Info("last fast sync is fail,init db", "status", status, "prichain", config.Genesis == nil) + log.Info("last fast sync is fail,init db", "status", common.BytesToUint32(status) , "prichain", config.Genesis == nil) chainDb.Close() if err := snapshotBaseDB.Close(); err != nil { return nil, err @@ -185,8 +185,8 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { return nil, err } - //only private net need InitGenesisAndSetEconomicConfig - if stored != params.MainnetGenesisHash && config.Genesis == nil { + // only private net need InitGenesisAndSetEconomicConfig + if stored != params.AlayanetGenesisHash && config.Genesis == nil { // private net config.Genesis = new(core.Genesis) if err := config.Genesis.InitGenesisAndSetEconomicConfig(ctx.GenesisPath()); err != nil { @@ -281,7 +281,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { config.TxPool.Journal = ctx.ResolvePath(config.TxPool.Journal) } //eth.txPool = core.NewTxPool(config.TxPool, eth.chainConfig, eth.blockchain) - eth.txPool = core.NewTxPool(config.TxPool, eth.chainConfig, blockChainCache) + eth.txPool = core.NewTxPool(config.TxPool, eth.chainConfig, core.NewTxPoolBlockChain(blockChainCache)) core.SenderCacher.SetTxPool(eth.txPool) @@ -317,7 +317,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { return nil, fmt.Errorf("The gasFloor must be less than gasCeil, got: %d, expect range (0, %d]", config.MinerGasFloor, gasCeil) } - eth.miner = miner.New(eth, eth.chainConfig, minningConfig, &vmConfig, eth.EventMux(), eth.engine, config.MinerRecommit, + eth.miner = miner.New(eth, eth.chainConfig, minningConfig, eth.EventMux(), eth.engine, config.MinerRecommit, config.MinerGasFloor, eth.isLocalBlock, blockChainCache, config.VmTimeoutDuration) //extra data for each block will be set by worker.go diff --git a/eth/broadcast.go b/eth/broadcast.go new file mode 100644 index 0000000000..61c65d6168 --- /dev/null +++ b/eth/broadcast.go @@ -0,0 +1,159 @@ +// Copyright 2018-2020 The PlatON Network Authors +// This file is part of the Alaya-Go library. +// +// The Alaya-Go 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 Alaya-Go 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 Alaya-Go library. If not, see . + +package eth + +import ( + "github.com/AlayaNetwork/Alaya-Go/common" + "github.com/AlayaNetwork/Alaya-Go/core/types" +) + +const ( + // This is the target size for the packs of transactions or announcements. A + // pack can get larger than this if a single transactions exceeds this size. + maxTxPacketSize = 100 * 1024 +) + +// broadcastTransactions is a write loop that schedules transaction broadcasts +// to the remote peer. The goal is to have an async writer that does not lock up +// node internals and at the same time rate limits queued data. +func (p *peer) broadcastTransactions() { + var ( + queue []*types.Transaction // Queue of hashes to broadcast as full transactions + done chan struct{} // Non-nil if background broadcaster is running + fail = make(chan error, 1) // Channel used to receive network error + failed bool // Flag whether a send failed, discard everything onward + ) + for { + // If there's no in-flight broadcast running, check if a new one is needed + if done == nil && len(queue) > 0 { + // Pile transaction until we reach our allowed network limit + var ( + count int + txs []*types.Transaction + size common.StorageSize + ) + + for count = 0; count < len(queue) && size < maxTxPacketSize; count++ { + txs = append(txs, queue[count]) + size += queue[count].Size() + } + // Shift and trim queue + queue = queue[:copy(queue, queue[count:])] + + // If there's anything available to transfer, fire up an async writer + if len(txs) > 0 { + done = make(chan struct{}) + go func() { + if err := p.SendTransactions(txs); err != nil { + fail <- err + return + } + close(done) + p.Log().Trace("Sent transactions", "count", len(txs)) + }() + } + } + // Transfer goroutine may or may not have been started, listen for events + select { + case txs := <-p.txBroadcast: + // If the connection failed, discard all transaction events + if failed { + continue + } + // New batch of transactions to be broadcast, queue them (with cap) + queue = append(queue, txs...) + if len(queue) > maxQueuedTxs { + // Fancy copy and resize to ensure buffer doesn't grow indefinitely + queue = queue[:copy(queue, queue[len(queue)-maxQueuedTxs:])] + } + + case <-done: + done = nil + + case <-fail: + failed = true + + case <-p.term: + return + } + } +} + +// announceTransactions is a write loop that schedules transaction broadcasts +// to the remote peer. The goal is to have an async writer that does not lock up +// node internals and at the same time rate limits queued data. +func (p *peer) announceTransactions() { + var ( + queue []common.Hash // Queue of hashes to announce as transaction stubs + done chan struct{} // Non-nil if background announcer is running + fail = make(chan error, 1) // Channel used to receive network error + failed bool // Flag whether a send failed, discard everything onward + ) + for { + // If there's no in-flight announce running, check if a new one is needed + if done == nil && len(queue) > 0 { + // Pile transaction hashes until we reach our allowed network limit + var ( + count int + pending []common.Hash + size common.StorageSize + ) + for count = 0; count < len(queue) && size < maxTxPacketSize; count++ { + pending = append(pending, queue[count]) + size += common.HashLength + } + // Shift and trim queue + queue = queue[:copy(queue, queue[count:])] + + // If there's anything available to transfer, fire up an async writer + if len(pending) > 0 { + done = make(chan struct{}) + go func() { + if err := p.sendPooledTransactionHashes(pending); err != nil { + fail <- err + return + } + close(done) + p.Log().Trace("Sent transaction announcements", "count", len(pending)) + }() + } + } + // Transfer goroutine may or may not have been started, listen for events + select { + case hashes := <-p.txAnnounce: + // If the connection failed, discard all transaction events + if failed { + continue + } + // New batch of transactions to be broadcast, queue them (with cap) + queue = append(queue, hashes...) + if len(queue) > maxQueuedTxAnns { + // Fancy copy and resize to ensure buffer doesn't grow indefinitely + queue = queue[:copy(queue, queue[len(queue)-maxQueuedTxAnns:])] + } + + case <-done: + done = nil + + case <-fail: + failed = true + + case <-p.term: + return + } + } +} diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index fc31d3e192..832bd4270b 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -438,9 +438,6 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, bn *big.I log.Debug("Synchronising with the network", "peer", p.id, "eth", p.version, "head", hash, "bn", bn, "mode", d.mode) defer func(start time.Time) { - if d.mode == FastSync { - d.setFastSyncStatus(FastSyncDel) - } log.Debug("Synchronisation terminated", "elapsed", time.Since(start)) }(time.Now()) @@ -521,7 +518,15 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, bn *big.I } else if d.mode == FullSync { fetchers = append(fetchers, d.processFullSyncContent) } - return d.spawnSync(fetchers) + if err:= d.spawnSync(fetchers);err!=nil{ + return err + } + if d.mode == FastSync{ + if err:= d.setFastSyncStatus(FastSyncDel);err!=nil{ + return err + } + } + return nil } // origin is the this chain current block header ,compare remote the same num of header in remote, diff --git a/eth/downloader/peer.go b/eth/downloader/peer.go index 9a02a99b9b..db0b787350 100644 --- a/eth/downloader/peer.go +++ b/eth/downloader/peer.go @@ -492,7 +492,7 @@ func (ps *peerSet) HeaderIdlePeers() ([]*peerConnection, int) { defer p.lock.RUnlock() return p.headerThroughput } - return ps.idlePeers(62, 64, idle, throughput) + return ps.idlePeers(62, 65, idle, throughput) } // BodyIdlePeers retrieves a flat list of all the currently body-idle peers within @@ -506,7 +506,7 @@ func (ps *peerSet) BodyIdlePeers() ([]*peerConnection, int) { defer p.lock.RUnlock() return p.blockThroughput } - return ps.idlePeers(62, 64, idle, throughput) + return ps.idlePeers(62, 65, idle, throughput) } // ReceiptIdlePeers retrieves a flat list of all the currently receipt-idle peers @@ -520,7 +520,7 @@ func (ps *peerSet) ReceiptIdlePeers() ([]*peerConnection, int) { defer p.lock.RUnlock() return p.receiptThroughput } - return ps.idlePeers(63, 64, idle, throughput) + return ps.idlePeers(63, 65, idle, throughput) } // NodeDataIdlePeers retrieves a flat list of all the currently node-data-idle @@ -534,7 +534,7 @@ func (ps *peerSet) NodeDataIdlePeers() ([]*peerConnection, int) { defer p.lock.RUnlock() return p.stateThroughput } - return ps.idlePeers(63, 64, idle, throughput) + return ps.idlePeers(63, 65, idle, throughput) } // idlePeers retrieves a flat list of all currently idle peers satisfying the diff --git a/eth/fetcher/tx_fetcher.go b/eth/fetcher/tx_fetcher.go new file mode 100644 index 0000000000..178e46b203 --- /dev/null +++ b/eth/fetcher/tx_fetcher.go @@ -0,0 +1,896 @@ +// Copyright 2018-2020 The PlatON Network Authors +// This file is part of the Alaya-Go library. +// +// The Alaya-Go 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 Alaya-Go 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 Alaya-Go library. If not, see . + +package fetcher + +import ( + "bytes" + "fmt" + mrand "math/rand" + "sort" + "time" + + "github.com/AlayaNetwork/Alaya-Go/common" + "github.com/AlayaNetwork/Alaya-Go/common/mclock" + "github.com/AlayaNetwork/Alaya-Go/core" + "github.com/AlayaNetwork/Alaya-Go/core/types" + "github.com/AlayaNetwork/Alaya-Go/log" + "github.com/AlayaNetwork/Alaya-Go/metrics" + mapset "github.com/deckarep/golang-set" +) + +const ( + // maxTxAnnounces is the maximum number of unique transaction a peer + // can announce in a short time. + maxTxAnnounces = 4096 + + // maxTxRetrievals is the maximum transaction number can be fetched in one + // request. The rationale to pick 256 is: + // - In eth protocol, the softResponseLimit is 2MB. Nowadays according to + // Etherscan the average transaction size is around 200B, so in theory + // we can include lots of transaction in a single protocol packet. + // - However the maximum size of a single transaction is raised to 128KB, + // so pick a middle value here to ensure we can maximize the efficiency + // of the retrieval and response size overflow won't happen in most cases. + maxTxRetrievals = 256 + + // maxTxUnderpricedSetSize is the size of the underpriced transaction set that + // is used to track recent transactions that have been dropped so we don't + // re-request them. + maxTxUnderpricedSetSize = 32768 + + // txArriveTimeout is the time allowance before an announced transaction is + // explicitly requested. + txArriveTimeout = 500 * time.Millisecond + + // txGatherSlack is the interval used to collate almost-expired announces + // with network fetches. + txGatherSlack = 100 * time.Millisecond +) + +var ( + // txFetchTimeout is the maximum allotted time to return an explicitly + // requested transaction. + txFetchTimeout = 5 * time.Second +) + +var ( + txAnnounceInMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/announces/in", nil) + txAnnounceKnownMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/announces/known", nil) + txAnnounceUnderpricedMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/announces/underpriced", nil) + txAnnounceDOSMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/announces/dos", nil) + + txBroadcastInMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/broadcasts/in", nil) + txBroadcastKnownMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/broadcasts/known", nil) + txBroadcastUnderpricedMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/broadcasts/underpriced", nil) + txBroadcastOtherRejectMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/broadcasts/otherreject", nil) + + txRequestOutMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/request/out", nil) + txRequestFailMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/request/fail", nil) + txRequestDoneMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/request/done", nil) + txRequestTimeoutMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/request/timeout", nil) + + txReplyInMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/replies/in", nil) + txReplyKnownMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/replies/known", nil) + txReplyUnderpricedMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/replies/underpriced", nil) + txReplyOtherRejectMeter = metrics.NewRegisteredMeter("eth/fetcher/transaction/replies/otherreject", nil) + + txFetcherWaitingPeers = metrics.NewRegisteredGauge("eth/fetcher/transaction/waiting/peers", nil) + txFetcherWaitingHashes = metrics.NewRegisteredGauge("eth/fetcher/transaction/waiting/hashes", nil) + txFetcherQueueingPeers = metrics.NewRegisteredGauge("eth/fetcher/transaction/queueing/peers", nil) + txFetcherQueueingHashes = metrics.NewRegisteredGauge("eth/fetcher/transaction/queueing/hashes", nil) + txFetcherFetchingPeers = metrics.NewRegisteredGauge("eth/fetcher/transaction/fetching/peers", nil) + txFetcherFetchingHashes = metrics.NewRegisteredGauge("eth/fetcher/transaction/fetching/hashes", nil) +) + +// txAnnounce is the notification of the availability of a batch +// of new transactions in the network. +type txAnnounce struct { + origin string // Identifier of the peer originating the notification + hashes []common.Hash // Batch of transaction hashes being announced +} + +// txRequest represents an in-flight transaction retrieval request destined to +// a specific peers. +type txRequest struct { + hashes []common.Hash // Transactions having been requested + stolen map[common.Hash]struct{} // Deliveries by someone else (don't re-request) + time mclock.AbsTime // Timestamp of the request +} + +// txDelivery is the notification that a batch of transactions have been added +// to the pool and should be untracked. +type txDelivery struct { + origin string // Identifier of the peer originating the notification + hashes []common.Hash // Batch of transaction hashes having been delivered + direct bool // Whether this is a direct reply or a broadcast +} + +// txDrop is the notiication that a peer has disconnected. +type txDrop struct { + peer string +} + +// TxFetcher is responsible for retrieving new transaction based on announcements. +// +// The fetcher operates in 3 stages: +// - Transactions that are newly discovered are moved into a wait list. +// - After ~500ms passes, transactions from the wait list that have not been +// broadcast to us in whole are moved into a queueing area. +// - When a connected peer doesn't have in-flight retrieval requests, any +// transaction queued up (and announced by the peer) are allocated to the +// peer and moved into a fetching status until it's fulfilled or fails. +// +// The invariants of the fetcher are: +// - Each tracked transaction (hash) must only be present in one of the +// three stages. This ensures that the fetcher operates akin to a finite +// state automata and there's do data leak. +// - Each peer that announced transactions may be scheduled retrievals, but +// only ever one concurrently. This ensures we can immediately know what is +// missing from a reply and reschedule it. +type TxFetcher struct { + notify chan *txAnnounce + cleanup chan *txDelivery + drop chan *txDrop + quit chan struct{} + + underpriced mapset.Set // Transactions discarded as too cheap (don't re-fetch) + + // Stage 1: Waiting lists for newly discovered transactions that might be + // broadcast without needing explicit request/reply round trips. + waitlist map[common.Hash]map[string]struct{} // Transactions waiting for an potential broadcast + waittime map[common.Hash]mclock.AbsTime // Timestamps when transactions were added to the waitlist + waitslots map[string]map[common.Hash]struct{} // Waiting announcement sgroupped by peer (DoS protection) + + // Stage 2: Queue of transactions that waiting to be allocated to some peer + // to be retrieved directly. + announces map[string]map[common.Hash]struct{} // Set of announced transactions, grouped by origin peer + announced map[common.Hash]map[string]struct{} // Set of download locations, grouped by transaction hash + + // Stage 3: Set of transactions currently being retrieved, some which may be + // fulfilled and some rescheduled. Note, this step shares 'announces' from the + // previous stage to avoid having to duplicate (need it for DoS checks). + fetching map[common.Hash]string // Transaction set currently being retrieved + requests map[string]*txRequest // In-flight transaction retrievals + alternates map[common.Hash]map[string]struct{} // In-flight transaction alternate origins if retrieval fails + + // Callbacks + hasTx func(common.Hash) bool // Retrieves a tx from the local txpool + addTxs func([]*types.Transaction) []error // Insert a batch of transactions into local txpool + fetchTxs func(string, []common.Hash) error // Retrieves a set of txs from a remote peer + + step chan struct{} // Notification channel when the fetcher loop iterates + clock mclock.Clock // Time wrapper to simulate in tests + rand *mrand.Rand // Randomizer to use in tests instead of map range loops (soft-random) +} + +// NewTxFetcher creates a transaction fetcher to retrieve transaction +// based on hash announcements. +func NewTxFetcher(hasTx func(common.Hash) bool, addTxs func([]*types.Transaction) []error, fetchTxs func(string, []common.Hash) error) *TxFetcher { + return NewTxFetcherForTests(hasTx, addTxs, fetchTxs, mclock.System{}, nil) +} + +// NewTxFetcherForTests is a testing method to mock out the realtime clock with +// a simulated version and the internal randomness with a deterministic one. +func NewTxFetcherForTests( + hasTx func(common.Hash) bool, addTxs func([]*types.Transaction) []error, fetchTxs func(string, []common.Hash) error, + clock mclock.Clock, rand *mrand.Rand) *TxFetcher { + return &TxFetcher{ + notify: make(chan *txAnnounce), + cleanup: make(chan *txDelivery), + drop: make(chan *txDrop), + quit: make(chan struct{}), + waitlist: make(map[common.Hash]map[string]struct{}), + waittime: make(map[common.Hash]mclock.AbsTime), + waitslots: make(map[string]map[common.Hash]struct{}), + announces: make(map[string]map[common.Hash]struct{}), + announced: make(map[common.Hash]map[string]struct{}), + fetching: make(map[common.Hash]string), + requests: make(map[string]*txRequest), + alternates: make(map[common.Hash]map[string]struct{}), + underpriced: mapset.NewSet(), + hasTx: hasTx, + addTxs: addTxs, + fetchTxs: fetchTxs, + clock: clock, + rand: rand, + } +} + +// Notify announces the fetcher of the potential availability of a new batch of +// transactions in the network. +func (f *TxFetcher) Notify(peer string, hashes []common.Hash) error { + // Keep track of all the announced transactions + txAnnounceInMeter.Mark(int64(len(hashes))) + log.Trace("TxFetcher Notify", "peer", peer, "hashes", len(hashes)) + + // Skip any transaction announcements that we already know of, or that we've + // previously marked as cheap and discarded. This check is of course racey, + // because multiple concurrent notifies will still manage to pass it, but it's + // still valuable to check here because it runs concurrent to the internal + // loop, so anything caught here is time saved internally. + var ( + unknowns = make([]common.Hash, 0, len(hashes)) + duplicate, underpriced int64 + ) + for _, hash := range hashes { + switch { + case f.hasTx(hash): + duplicate++ + + case f.underpriced.Contains(hash): + underpriced++ + + default: + unknowns = append(unknowns, hash) + } + } + txAnnounceKnownMeter.Mark(duplicate) + txAnnounceUnderpricedMeter.Mark(underpriced) + + // If anything's left to announce, push it into the internal loop + if len(unknowns) == 0 { + return nil + } + announce := &txAnnounce{ + origin: peer, + hashes: unknowns, + } + select { + case f.notify <- announce: + return nil + case <-f.quit: + return errTerminated + } +} + +// Enqueue imports a batch of received transaction into the transaction pool +// and the fetcher. This method may be called by both transaction broadcasts and +// direct request replies. The differentiation is important so the fetcher can +// re-shedule missing transactions as soon as possible. +func (f *TxFetcher) Enqueue(peer string, txs []*types.Transaction, direct bool) error { + // Keep track of all the propagated transactions + if direct { + txReplyInMeter.Mark(int64(len(txs))) + } else { + txBroadcastInMeter.Mark(int64(len(txs))) + } + // Push all the transactions into the pool, tracking underpriced ones to avoid + // re-requesting them and dropping the peer in case of malicious transfers. + var ( + added = make([]common.Hash, 0, len(txs)) + duplicate int64 + underpriced int64 + otherreject int64 + ) + errs := f.addTxs(txs) + log.Trace("TxFetcher Enqueue", "peer", peer, "txs", len(txs)) + for i, err := range errs { + if err != nil { + // Track the transaction hash if the price is too low for us. + // Avoid re-request this transaction when we receive another + // announcement. + if err == core.ErrUnderpriced || err == core.ErrReplaceUnderpriced { + for f.underpriced.Cardinality() >= maxTxUnderpricedSetSize { + f.underpriced.Pop() + } + f.underpriced.Add(txs[i].Hash()) + } + // Track a few interesting failure types + switch err { + case nil: // Noop, but need to handle to not count these + + case core.ErrAlreadyKnown: + duplicate++ + + case core.ErrUnderpriced, core.ErrReplaceUnderpriced: + underpriced++ + + default: + otherreject++ + } + } + added = append(added, txs[i].Hash()) + } + if direct { + txReplyKnownMeter.Mark(duplicate) + txReplyUnderpricedMeter.Mark(underpriced) + txReplyOtherRejectMeter.Mark(otherreject) + } else { + txBroadcastKnownMeter.Mark(duplicate) + txBroadcastUnderpricedMeter.Mark(underpriced) + txBroadcastOtherRejectMeter.Mark(otherreject) + } + select { + case f.cleanup <- &txDelivery{origin: peer, hashes: added, direct: direct}: + return nil + case <-f.quit: + return errTerminated + } +} + +// Drop should be called when a peer disconnects. It cleans up all the internal +// data structures of the given node. +func (f *TxFetcher) Drop(peer string) error { + select { + case f.drop <- &txDrop{peer: peer}: + return nil + case <-f.quit: + return errTerminated + } +} + +// Start boots up the announcement based synchroniser, accepting and processing +// hash notifications and block fetches until termination requested. +func (f *TxFetcher) Start() { + go f.loop() +} + +// Stop terminates the announcement based synchroniser, canceling all pending +// operations. +func (f *TxFetcher) Stop() { + close(f.quit) +} + +func (f *TxFetcher) loop() { + var ( + waitTimer = new(mclock.Timer) + timeoutTimer = new(mclock.Timer) + + waitTrigger = make(chan struct{}, 1) + timeoutTrigger = make(chan struct{}, 1) + ) + for { + select { + case ann := <-f.notify: + // Drop part of the new announcements if there are too many accumulated. + // Note, we could but do not filter already known transactions here as + // the probability of something arriving between this call and the pre- + // filter outside is essentially zero. + used := len(f.waitslots[ann.origin]) + len(f.announces[ann.origin]) + if used >= maxTxAnnounces { + // This can happen if a set of transactions are requested but not + // all fulfilled, so the remainder are rescheduled without the cap + // check. Should be fine as the limit is in the thousands and the + // request size in the hundreds. + txAnnounceDOSMeter.Mark(int64(len(ann.hashes))) + break + } + want := used + len(ann.hashes) + if want > maxTxAnnounces { + txAnnounceDOSMeter.Mark(int64(want - maxTxAnnounces)) + ann.hashes = ann.hashes[:want-maxTxAnnounces] + } + // All is well, schedule the remainder of the transactions + idleWait := len(f.waittime) == 0 + _, oldPeer := f.announces[ann.origin] + + for _, hash := range ann.hashes { + // If the transaction is already downloading, add it to the list + // of possible alternates (in case the current retrieval fails) and + // also account it for the peer. + if f.alternates[hash] != nil { + f.alternates[hash][ann.origin] = struct{}{} + + // Stage 2 and 3 share the set of origins per tx + if announces := f.announces[ann.origin]; announces != nil { + announces[hash] = struct{}{} + } else { + f.announces[ann.origin] = map[common.Hash]struct{}{hash: {}} + } + continue + } + // If the transaction is not downloading, but is already queued + // from a different peer, track it for the new peer too. + if f.announced[hash] != nil { + f.announced[hash][ann.origin] = struct{}{} + + // Stage 2 and 3 share the set of origins per tx + if announces := f.announces[ann.origin]; announces != nil { + announces[hash] = struct{}{} + } else { + f.announces[ann.origin] = map[common.Hash]struct{}{hash: {}} + } + continue + } + // If the transaction is already known to the fetcher, but not + // yet downloading, add the peer as an alternate origin in the + // waiting list. + if f.waitlist[hash] != nil { + f.waitlist[hash][ann.origin] = struct{}{} + + if waitslots := f.waitslots[ann.origin]; waitslots != nil { + waitslots[hash] = struct{}{} + } else { + f.waitslots[ann.origin] = map[common.Hash]struct{}{hash: {}} + } + continue + } + // Transaction unknown to the fetcher, insert it into the waiting list + f.waitlist[hash] = map[string]struct{}{ann.origin: {}} + f.waittime[hash] = f.clock.Now() + + if waitslots := f.waitslots[ann.origin]; waitslots != nil { + waitslots[hash] = struct{}{} + } else { + f.waitslots[ann.origin] = map[common.Hash]struct{}{hash: {}} + } + } + // If a new item was added to the waitlist, schedule it into the fetcher + if idleWait && len(f.waittime) > 0 { + f.rescheduleWait(waitTimer, waitTrigger) + } + // If this peer is new and announced something already queued, maybe + // request transactions from them + if !oldPeer && len(f.announces[ann.origin]) > 0 { + f.scheduleFetches(timeoutTimer, timeoutTrigger, map[string]struct{}{ann.origin: {}}) + } + + case <-waitTrigger: + // At least one transaction's waiting time ran out, push all expired + // ones into the retrieval queues + actives := make(map[string]struct{}) + for hash, instance := range f.waittime { + if time.Duration(f.clock.Now()-instance)+txGatherSlack > txArriveTimeout { + // Transaction expired without propagation, schedule for retrieval + if f.announced[hash] != nil { + panic("announce tracker already contains waitlist item") + } + f.announced[hash] = f.waitlist[hash] + for peer := range f.waitlist[hash] { + if announces := f.announces[peer]; announces != nil { + announces[hash] = struct{}{} + } else { + f.announces[peer] = map[common.Hash]struct{}{hash: {}} + } + delete(f.waitslots[peer], hash) + if len(f.waitslots[peer]) == 0 { + delete(f.waitslots, peer) + } + actives[peer] = struct{}{} + } + delete(f.waittime, hash) + delete(f.waitlist, hash) + } + } + // If transactions are still waiting for propagation, reschedule the wait timer + if len(f.waittime) > 0 { + f.rescheduleWait(waitTimer, waitTrigger) + } + // If any peers became active and are idle, request transactions from them + if len(actives) > 0 { + f.scheduleFetches(timeoutTimer, timeoutTrigger, actives) + } + + case <-timeoutTrigger: + // Clean up any expired retrievals and avoid re-requesting them from the + // same peer (either overloaded or malicious, useless in both cases). We + // could also penalize (Drop), but there's nothing to gain, and if could + // possibly further increase the load on it. + for peer, req := range f.requests { + if time.Duration(f.clock.Now()-req.time)+txGatherSlack > txFetchTimeout { + txRequestTimeoutMeter.Mark(int64(len(req.hashes))) + + // Reschedule all the not-yet-delivered fetches to alternate peers + for _, hash := range req.hashes { + // Skip rescheduling hashes already delivered by someone else + if req.stolen != nil { + if _, ok := req.stolen[hash]; ok { + continue + } + } + // Move the delivery back from fetching to queued + if _, ok := f.announced[hash]; ok { + panic("announced tracker already contains alternate item") + } + if f.alternates[hash] != nil { // nil if tx was broadcast during fetch + f.announced[hash] = f.alternates[hash] + } + delete(f.announced[hash], peer) + if len(f.announced[hash]) == 0 { + delete(f.announced, hash) + } + delete(f.announces[peer], hash) + delete(f.alternates, hash) + delete(f.fetching, hash) + } + if len(f.announces[peer]) == 0 { + delete(f.announces, peer) + } + // Keep track of the request as dangling, but never expire + f.requests[peer].hashes = nil + } + } + // Schedule a new transaction retrieval + f.scheduleFetches(timeoutTimer, timeoutTrigger, nil) + + // No idea if we scheduled something or not, trigger the timer if needed + // TODO(karalabe): this is kind of lame, can't we dump it into scheduleFetches somehow? + f.rescheduleTimeout(timeoutTimer, timeoutTrigger) + + case delivery := <-f.cleanup: + // Independent if the delivery was direct or broadcast, remove all + // traces of the hash from internal trackers + for _, hash := range delivery.hashes { + if _, ok := f.waitlist[hash]; ok { + for peer, txset := range f.waitslots { + delete(txset, hash) + if len(txset) == 0 { + delete(f.waitslots, peer) + } + } + delete(f.waitlist, hash) + delete(f.waittime, hash) + } else { + for peer, txset := range f.announces { + delete(txset, hash) + if len(txset) == 0 { + delete(f.announces, peer) + } + } + delete(f.announced, hash) + delete(f.alternates, hash) + + // If a transaction currently being fetched from a different + // origin was delivered (delivery stolen), mark it so the + // actual delivery won't double schedule it. + if origin, ok := f.fetching[hash]; ok && (origin != delivery.origin || !delivery.direct) { + stolen := f.requests[origin].stolen + if stolen == nil { + f.requests[origin].stolen = make(map[common.Hash]struct{}) + stolen = f.requests[origin].stolen + } + stolen[hash] = struct{}{} + } + delete(f.fetching, hash) + } + } + // In case of a direct delivery, also reschedule anything missing + // from the original query + if delivery.direct { + // Mark the reqesting successful (independent of individual status) + txRequestDoneMeter.Mark(int64(len(delivery.hashes))) + + // Make sure something was pending, nuke it + req := f.requests[delivery.origin] + if req == nil { + log.Warn("Unexpected transaction delivery", "peer", delivery.origin) + break + } + delete(f.requests, delivery.origin) + + // Anything not delivered should be re-scheduled (with or without + // this peer, depending on the response cutoff) + delivered := make(map[common.Hash]struct{}) + for _, hash := range delivery.hashes { + delivered[hash] = struct{}{} + } + cutoff := len(req.hashes) // If nothing is delivered, assume everything is missing, don't retry!!! + for i, hash := range req.hashes { + if _, ok := delivered[hash]; ok { + cutoff = i + } + } + // Reschedule missing hashes from alternates, not-fulfilled from alt+self + for i, hash := range req.hashes { + // Skip rescheduling hashes already delivered by someone else + if req.stolen != nil { + if _, ok := req.stolen[hash]; ok { + continue + } + } + if _, ok := delivered[hash]; !ok { + if i < cutoff { + delete(f.alternates[hash], delivery.origin) + delete(f.announces[delivery.origin], hash) + if len(f.announces[delivery.origin]) == 0 { + delete(f.announces, delivery.origin) + } + } + if len(f.alternates[hash]) > 0 { + if _, ok := f.announced[hash]; ok { + panic(fmt.Sprintf("announced tracker already contains alternate item: %v", f.announced[hash])) + } + f.announced[hash] = f.alternates[hash] + } + } + delete(f.alternates, hash) + delete(f.fetching, hash) + } + // Something was delivered, try to rechedule requests + f.scheduleFetches(timeoutTimer, timeoutTrigger, nil) // Partial delivery may enable others to deliver too + } + + case drop := <-f.drop: + // A peer was dropped, remove all traces of it + if _, ok := f.waitslots[drop.peer]; ok { + for hash := range f.waitslots[drop.peer] { + delete(f.waitlist[hash], drop.peer) + if len(f.waitlist[hash]) == 0 { + delete(f.waitlist, hash) + delete(f.waittime, hash) + } + } + delete(f.waitslots, drop.peer) + if len(f.waitlist) > 0 { + f.rescheduleWait(waitTimer, waitTrigger) + } + } + // Clean up any active requests + var request *txRequest + if request = f.requests[drop.peer]; request != nil { + for _, hash := range request.hashes { + // Skip rescheduling hashes already delivered by someone else + if request.stolen != nil { + if _, ok := request.stolen[hash]; ok { + continue + } + } + // Undelivered hash, reschedule if there's an alternative origin available + delete(f.alternates[hash], drop.peer) + if len(f.alternates[hash]) == 0 { + delete(f.alternates, hash) + } else { + f.announced[hash] = f.alternates[hash] + delete(f.alternates, hash) + } + delete(f.fetching, hash) + } + delete(f.requests, drop.peer) + } + // Clean up general announcement tracking + if _, ok := f.announces[drop.peer]; ok { + for hash := range f.announces[drop.peer] { + delete(f.announced[hash], drop.peer) + if len(f.announced[hash]) == 0 { + delete(f.announced, hash) + } + } + delete(f.announces, drop.peer) + } + // If a request was cancelled, check if anything needs to be rescheduled + if request != nil { + f.scheduleFetches(timeoutTimer, timeoutTrigger, nil) + f.rescheduleTimeout(timeoutTimer, timeoutTrigger) + } + + case <-f.quit: + return + } + // No idea what happened, but bump some sanity metrics + txFetcherWaitingPeers.Update(int64(len(f.waitslots))) + txFetcherWaitingHashes.Update(int64(len(f.waitlist))) + txFetcherQueueingPeers.Update(int64(len(f.announces) - len(f.requests))) + txFetcherQueueingHashes.Update(int64(len(f.announced))) + txFetcherFetchingPeers.Update(int64(len(f.requests))) + txFetcherFetchingHashes.Update(int64(len(f.fetching))) + + // Loop did something, ping the step notifier if needed (tests) + if f.step != nil { + f.step <- struct{}{} + } + } +} + +// rescheduleWait iterates over all the transactions currently in the waitlist +// and schedules the movement into the fetcher for the earliest. +// +// The method has a granularity of 'gatherSlack', since there's not much point in +// spinning over all the transactions just to maybe find one that should trigger +// a few ms earlier. +func (f *TxFetcher) rescheduleWait(timer *mclock.Timer, trigger chan struct{}) { + if *timer != nil { + (*timer).Stop() + } + now := f.clock.Now() + + earliest := now + for _, instance := range f.waittime { + if earliest > instance { + earliest = instance + if txArriveTimeout-time.Duration(now-earliest) < gatherSlack { + break + } + } + } + *timer = f.clock.AfterFunc(txArriveTimeout-time.Duration(now-earliest), func() { + trigger <- struct{}{} + }) +} + +// rescheduleTimeout iterates over all the transactions currently in flight and +// schedules a cleanup run when the first would trigger. +// +// The method has a granularity of 'gatherSlack', since there's not much point in +// spinning over all the transactions just to maybe find one that should trigger +// a few ms earlier. +// +// This method is a bit "flaky" "by design". In theory the timeout timer only ever +// should be rescheduled if some request is pending. In practice, a timeout will +// cause the timer to be rescheduled every 5 secs (until the peer comes through or +// disconnects). This is a limitation of the fetcher code because we don't trac +// pending requests and timed out requests separatey. Without double tracking, if +// we simply didn't reschedule the timer on all-timeout then the timer would never +// be set again since len(request) > 0 => something's running. +func (f *TxFetcher) rescheduleTimeout(timer *mclock.Timer, trigger chan struct{}) { + if *timer != nil { + (*timer).Stop() + } + now := f.clock.Now() + + earliest := now + for _, req := range f.requests { + // If this request already timed out, skip it altogether + if req.hashes == nil { + continue + } + if earliest > req.time { + earliest = req.time + if txFetchTimeout-time.Duration(now-earliest) < gatherSlack { + break + } + } + } + *timer = f.clock.AfterFunc(txFetchTimeout-time.Duration(now-earliest), func() { + trigger <- struct{}{} + }) +} + +// scheduleFetches starts a batch of retrievals for all available idle peers. +func (f *TxFetcher) scheduleFetches(timer *mclock.Timer, timeout chan struct{}, whitelist map[string]struct{}) { + // Gather the set of peers we want to retrieve from (default to all) + actives := whitelist + if actives == nil { + actives = make(map[string]struct{}) + for peer := range f.announces { + actives[peer] = struct{}{} + } + } + if len(actives) == 0 { + return + } + // For each active peer, try to schedule some transaction fetches + idle := len(f.requests) == 0 + + f.forEachPeer(actives, func(peer string) { + if f.requests[peer] != nil { + return // continue in the for-each + } + if len(f.announces[peer]) == 0 { + return // continue in the for-each + } + hashes := make([]common.Hash, 0, maxTxRetrievals) + f.forEachHash(f.announces[peer], func(hash common.Hash) bool { + if _, ok := f.fetching[hash]; !ok { + // Mark the hash as fetching and stash away possible alternates + f.fetching[hash] = peer + + if _, ok := f.alternates[hash]; ok { + panic(fmt.Sprintf("alternate tracker already contains fetching item: %v", f.alternates[hash])) + } + f.alternates[hash] = f.announced[hash] + delete(f.announced, hash) + + // Accumulate the hash and stop if the limit was reached + hashes = append(hashes, hash) + if len(hashes) >= maxTxRetrievals { + return false // break in the for-each + } + } + return true // continue in the for-each + }) + // If any hashes were allocated, request them from the peer + if len(hashes) > 0 { + f.requests[peer] = &txRequest{hashes: hashes, time: f.clock.Now()} + txRequestOutMeter.Mark(int64(len(hashes))) + + go func(peer string, hashes []common.Hash) { + // Try to fetch the transactions, but in case of a request + // failure (e.g. peer disconnected), reschedule the hashes. + if err := f.fetchTxs(peer, hashes); err != nil { + txRequestFailMeter.Mark(int64(len(hashes))) + f.Drop(peer) + } + }(peer, hashes) + } + }) + // If a new request was fired, schedule a timeout timer + if idle && len(f.requests) > 0 { + f.rescheduleTimeout(timer, timeout) + } +} + +// forEachPeer does a range loop over a map of peers in production, but during +// testing it does a deterministic sorted random to allow reproducing issues. +func (f *TxFetcher) forEachPeer(peers map[string]struct{}, do func(peer string)) { + // If we're running production, use whatever Go's map gives us + if f.rand == nil { + for peer := range peers { + do(peer) + } + return + } + // We're running the test suite, make iteration deterministic + list := make([]string, 0, len(peers)) + for peer := range peers { + list = append(list, peer) + } + sort.Strings(list) + rotateStrings(list, f.rand.Intn(len(list))) + for _, peer := range list { + do(peer) + } +} + +// forEachHash does a range loop over a map of hashes in production, but during +// testing it does a deterministic sorted random to allow reproducing issues. +func (f *TxFetcher) forEachHash(hashes map[common.Hash]struct{}, do func(hash common.Hash) bool) { + // If we're running production, use whatever Go's map gives us + if f.rand == nil { + for hash := range hashes { + if !do(hash) { + return + } + } + return + } + // We're running the test suite, make iteration deterministic + list := make([]common.Hash, 0, len(hashes)) + for hash := range hashes { + list = append(list, hash) + } + sortHashes(list) + rotateHashes(list, f.rand.Intn(len(list))) + for _, hash := range list { + if !do(hash) { + return + } + } +} + +// rotateStrings rotates the contents of a slice by n steps. This method is only +// used in tests to simulate random map iteration but keep it deterministic. +func rotateStrings(slice []string, n int) { + orig := make([]string, len(slice)) + copy(orig, slice) + + for i := 0; i < len(orig); i++ { + slice[i] = orig[(i+n)%len(orig)] + } +} + +// sortHashes sorts a slice of hashes. This method is only used in tests in order +// to simulate random map iteration but keep it deterministic. +func sortHashes(slice []common.Hash) { + for i := 0; i < len(slice); i++ { + for j := i + 1; j < len(slice); j++ { + if bytes.Compare(slice[i][:], slice[j][:]) > 0 { + slice[i], slice[j] = slice[j], slice[i] + } + } + } +} + +// rotateHashes rotates the contents of a slice by n steps. This method is only +// used in tests to simulate random map iteration but keep it deterministic. +func rotateHashes(slice []common.Hash, n int) { + orig := make([]common.Hash, len(slice)) + copy(orig, slice) + + for i := 0; i < len(orig); i++ { + slice[i] = orig[(i+n)%len(orig)] + } +} diff --git a/eth/fetcher/tx_fetcher_test.go b/eth/fetcher/tx_fetcher_test.go new file mode 100644 index 0000000000..78f726dfdb --- /dev/null +++ b/eth/fetcher/tx_fetcher_test.go @@ -0,0 +1,1528 @@ +// Copyright 2018-2020 The PlatON Network Authors +// This file is part of the Alaya-Go library. +// +// The Alaya-Go 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 Alaya-Go 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 Alaya-Go library. If not, see . + +package fetcher + +import ( + "errors" + "math/big" + "math/rand" + "testing" + "time" + + "github.com/AlayaNetwork/Alaya-Go/common" + "github.com/AlayaNetwork/Alaya-Go/common/mclock" + "github.com/AlayaNetwork/Alaya-Go/core" + "github.com/AlayaNetwork/Alaya-Go/core/types" +) + +var ( + // testTxs is a set of transactions to use during testing that have meaningful hashes. + testTxs = []*types.Transaction{ + types.NewTransaction(5577006791947779410, common.Address{0x0f}, new(big.Int), 0, new(big.Int), nil), + types.NewTransaction(15352856648520921629, common.Address{0xbb}, new(big.Int), 0, new(big.Int), nil), + types.NewTransaction(3916589616287113937, common.Address{0x86}, new(big.Int), 0, new(big.Int), nil), + types.NewTransaction(9828766684487745566, common.Address{0xac}, new(big.Int), 0, new(big.Int), nil), + } + // testTxsHashes is the hashes of the test transactions above + testTxsHashes = []common.Hash{testTxs[0].Hash(), testTxs[1].Hash(), testTxs[2].Hash(), testTxs[3].Hash()} +) + +type doTxNotify struct { + peer string + hashes []common.Hash +} +type doTxEnqueue struct { + peer string + txs []*types.Transaction + direct bool +} +type doWait struct { + time time.Duration + step bool +} +type doDrop string +type doFunc func() + +type isWaiting map[string][]common.Hash +type isScheduled struct { + tracking map[string][]common.Hash + fetching map[string][]common.Hash + dangling map[string][]common.Hash +} +type isUnderpriced int + +// txFetcherTest represents a test scenario that can be executed by the test +// runner. +type txFetcherTest struct { + init func() *TxFetcher + steps []interface{} +} + +// Tests that transaction announcements are added to a waitlist, and none +// of them are scheduled for retrieval until the wait expires. +func TestTransactionFetcherWaiting(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + nil, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Initial announcement to get something into the waitlist + doTxNotify{peer: "A", hashes: []common.Hash{{0x01}, {0x02}}}, + isWaiting(map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }), + // Announce from a new peer to check that no overwrite happens + doTxNotify{peer: "B", hashes: []common.Hash{{0x03}, {0x04}}}, + isWaiting(map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + "B": {{0x03}, {0x04}}, + }), + // Announce clashing hashes but unique new peer + doTxNotify{peer: "C", hashes: []common.Hash{{0x01}, {0x04}}}, + isWaiting(map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + "B": {{0x03}, {0x04}}, + "C": {{0x01}, {0x04}}, + }), + // Announce existing and clashing hashes from existing peer + doTxNotify{peer: "A", hashes: []common.Hash{{0x01}, {0x03}, {0x05}}}, + isWaiting(map[string][]common.Hash{ + "A": {{0x01}, {0x02}, {0x03}, {0x05}}, + "B": {{0x03}, {0x04}}, + "C": {{0x01}, {0x04}}, + }), + isScheduled{tracking: nil, fetching: nil}, + + // Wait for the arrival timeout which should move all expired items + // from the wait list to the scheduler + doWait{time: txArriveTimeout, step: true}, + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {{0x01}, {0x02}, {0x03}, {0x05}}, + "B": {{0x03}, {0x04}}, + "C": {{0x01}, {0x04}}, + }, + fetching: map[string][]common.Hash{ // Depends on deterministic test randomizer + "A": {{0x02}, {0x03}, {0x05}}, + "C": {{0x01}, {0x04}}, + }, + }, + // Queue up a non-fetchable transaction and then trigger it with a new + // peer (weird case to test 1 line in the fetcher) + doTxNotify{peer: "C", hashes: []common.Hash{{0x06}, {0x07}}}, + isWaiting(map[string][]common.Hash{ + "C": {{0x06}, {0x07}}, + }), + doWait{time: txArriveTimeout, step: true}, + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {{0x01}, {0x02}, {0x03}, {0x05}}, + "B": {{0x03}, {0x04}}, + "C": {{0x01}, {0x04}, {0x06}, {0x07}}, + }, + fetching: map[string][]common.Hash{ + "A": {{0x02}, {0x03}, {0x05}}, + "C": {{0x01}, {0x04}}, + }, + }, + doTxNotify{peer: "D", hashes: []common.Hash{{0x06}, {0x07}}}, + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {{0x01}, {0x02}, {0x03}, {0x05}}, + "B": {{0x03}, {0x04}}, + "C": {{0x01}, {0x04}, {0x06}, {0x07}}, + "D": {{0x06}, {0x07}}, + }, + fetching: map[string][]common.Hash{ + "A": {{0x02}, {0x03}, {0x05}}, + "C": {{0x01}, {0x04}}, + "D": {{0x06}, {0x07}}, + }, + }, + }, + }) +} + +// Tests that transaction announcements skip the waiting list if they are +// already scheduled. +func TestTransactionFetcherSkipWaiting(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + nil, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Push an initial announcement through to the scheduled stage + doTxNotify{peer: "A", hashes: []common.Hash{{0x01}, {0x02}}}, + isWaiting(map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }), + isScheduled{tracking: nil, fetching: nil}, + + doWait{time: txArriveTimeout, step: true}, + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }, + fetching: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }, + }, + // Announce overlaps from the same peer, ensure the new ones end up + // in stage one, and clashing ones don't get double tracked + doTxNotify{peer: "A", hashes: []common.Hash{{0x02}, {0x03}}}, + isWaiting(map[string][]common.Hash{ + "A": {{0x03}}, + }), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }, + fetching: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }, + }, + // Announce overlaps from a new peer, ensure new transactions end up + // in stage one and clashing ones get tracked for the new peer + doTxNotify{peer: "B", hashes: []common.Hash{{0x02}, {0x03}, {0x04}}}, + isWaiting(map[string][]common.Hash{ + "A": {{0x03}}, + "B": {{0x03}, {0x04}}, + }), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + "B": {{0x02}}, + }, + fetching: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }, + }, + }, + }) +} + +// Tests that only a single transaction request gets scheduled to a peer +// and subsequent announces block or get allotted to someone else. +func TestTransactionFetcherSingletonRequesting(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + nil, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Push an initial announcement through to the scheduled stage + doTxNotify{peer: "A", hashes: []common.Hash{{0x01}, {0x02}}}, + isWaiting(map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }), + isScheduled{tracking: nil, fetching: nil}, + + doWait{time: txArriveTimeout, step: true}, + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }, + fetching: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }, + }, + // Announce a new set of transactions from the same peer and ensure + // they do not start fetching since the peer is already busy + doTxNotify{peer: "A", hashes: []common.Hash{{0x03}, {0x04}}}, + isWaiting(map[string][]common.Hash{ + "A": {{0x03}, {0x04}}, + }), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }, + fetching: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }, + }, + doWait{time: txArriveTimeout, step: true}, + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {{0x01}, {0x02}, {0x03}, {0x04}}, + }, + fetching: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }, + }, + // Announce a duplicate set of transactions from a new peer and ensure + // uniquely new ones start downloading, even if clashing. + doTxNotify{peer: "B", hashes: []common.Hash{{0x02}, {0x03}, {0x05}, {0x06}}}, + isWaiting(map[string][]common.Hash{ + "B": {{0x05}, {0x06}}, + }), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {{0x01}, {0x02}, {0x03}, {0x04}}, + "B": {{0x02}, {0x03}}, + }, + fetching: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + "B": {{0x03}}, + }, + }, + }, + }) +} + +// Tests that if a transaction retrieval fails, all the transactions get +// instantly schedule back to someone else or the announcements dropped +// if no alternate source is available. +func TestTransactionFetcherFailedRescheduling(t *testing.T) { + // Create a channel to control when tx requests can fail + proceed := make(chan struct{}) + + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + nil, + func(origin string, hashes []common.Hash) error { + <-proceed + return errors.New("peer disconnected") + }, + ) + }, + steps: []interface{}{ + // Push an initial announcement through to the scheduled stage + doTxNotify{peer: "A", hashes: []common.Hash{{0x01}, {0x02}}}, + isWaiting(map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }), + isScheduled{tracking: nil, fetching: nil}, + + doWait{time: txArriveTimeout, step: true}, + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }, + fetching: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }, + }, + // While the original peer is stuck in the request, push in an second + // data source. + doTxNotify{peer: "B", hashes: []common.Hash{{0x02}}}, + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + "B": {{0x02}}, + }, + fetching: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }, + }, + // Wait until the original request fails and check that transactions + // are either rescheduled or dropped + doFunc(func() { + proceed <- struct{}{} // Allow peer A to return the failure + }), + doWait{time: 0, step: true}, + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "B": {{0x02}}, + }, + fetching: map[string][]common.Hash{ + "B": {{0x02}}, + }, + }, + doFunc(func() { + proceed <- struct{}{} // Allow peer B to return the failure + }), + doWait{time: 0, step: true}, + isWaiting(nil), + isScheduled{nil, nil, nil}, + }, + }) +} + +// Tests that if a transaction retrieval succeeds, all alternate origins +// are cleaned up. +func TestTransactionFetcherCleanup(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + func(txs []*types.Transaction) []error { + return make([]error, len(txs)) + }, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Push an initial announcement through to the scheduled stage + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, + isWaiting(map[string][]common.Hash{ + "A": {testTxsHashes[0]}, + }), + isScheduled{tracking: nil, fetching: nil}, + + doWait{time: txArriveTimeout, step: true}, + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {testTxsHashes[0]}, + }, + fetching: map[string][]common.Hash{ + "A": {testTxsHashes[0]}, + }, + }, + // Request should be delivered + doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0]}, direct: true}, + isScheduled{nil, nil, nil}, + }, + }) +} + +// Tests that if a transaction retrieval succeeds, but the response is empty (no +// transactions available, then all are nuked instead of being rescheduled (yes, +// this was a bug)). +func TestTransactionFetcherCleanupEmpty(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + func(txs []*types.Transaction) []error { + return make([]error, len(txs)) + }, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Push an initial announcement through to the scheduled stage + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, + isWaiting(map[string][]common.Hash{ + "A": {testTxsHashes[0]}, + }), + isScheduled{tracking: nil, fetching: nil}, + + doWait{time: txArriveTimeout, step: true}, + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {testTxsHashes[0]}, + }, + fetching: map[string][]common.Hash{ + "A": {testTxsHashes[0]}, + }, + }, + // Deliver an empty response and ensure the transaction is cleared, not rescheduled + doTxEnqueue{peer: "A", txs: []*types.Transaction{}, direct: true}, + isScheduled{nil, nil, nil}, + }, + }) +} + +// Tests that non-returned transactions are either re-scheduled from a +// different peer, or self if they are after the cutoff point. +func TestTransactionFetcherMissingRescheduling(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + func(txs []*types.Transaction) []error { + return make([]error, len(txs)) + }, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Push an initial announcement through to the scheduled stage + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0], testTxsHashes[1], testTxsHashes[2]}}, + isWaiting(map[string][]common.Hash{ + "A": {testTxsHashes[0], testTxsHashes[1], testTxsHashes[2]}, + }), + isScheduled{tracking: nil, fetching: nil}, + + doWait{time: txArriveTimeout, step: true}, + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {testTxsHashes[0], testTxsHashes[1], testTxsHashes[2]}, + }, + fetching: map[string][]common.Hash{ + "A": {testTxsHashes[0], testTxsHashes[1], testTxsHashes[2]}, + }, + }, + // Deliver the middle transaction requested, the one before which + // should be dropped and the one after re-requested. + doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0]}, direct: true}, // This depends on the deterministic random + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {testTxsHashes[2]}, + }, + fetching: map[string][]common.Hash{ + "A": {testTxsHashes[2]}, + }, + }, + }, + }) +} + +// Tests that out of two transactions, if one is missing and the last is +// delivered, the peer gets properly cleaned out from the internal state. +func TestTransactionFetcherMissingCleanup(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + func(txs []*types.Transaction) []error { + return make([]error, len(txs)) + }, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Push an initial announcement through to the scheduled stage + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0], testTxsHashes[1]}}, + isWaiting(map[string][]common.Hash{ + "A": {testTxsHashes[0], testTxsHashes[1]}, + }), + isScheduled{tracking: nil, fetching: nil}, + + doWait{time: txArriveTimeout, step: true}, + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {testTxsHashes[0], testTxsHashes[1]}, + }, + fetching: map[string][]common.Hash{ + "A": {testTxsHashes[0], testTxsHashes[1]}, + }, + }, + // Deliver the middle transaction requested, the one before which + // should be dropped and the one after re-requested. + doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[1]}, direct: true}, // This depends on the deterministic random + isScheduled{nil, nil, nil}, + }, + }) +} + +// Tests that transaction broadcasts properly clean up announcements. +func TestTransactionFetcherBroadcasts(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + func(txs []*types.Transaction) []error { + return make([]error, len(txs)) + }, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Set up three transactions to be in different stats, waiting, queued and fetching + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, + doWait{time: txArriveTimeout, step: true}, + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[1]}}, + doWait{time: txArriveTimeout, step: true}, + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[2]}}, + + isWaiting(map[string][]common.Hash{ + "A": {testTxsHashes[2]}, + }), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {testTxsHashes[0], testTxsHashes[1]}, + }, + fetching: map[string][]common.Hash{ + "A": {testTxsHashes[0]}, + }, + }, + // Broadcast all the transactions and ensure everything gets cleaned + // up, but the dangling request is left alone to avoid doing multiple + // concurrent requests. + doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0], testTxs[1], testTxs[2]}, direct: false}, + isWaiting(nil), + isScheduled{ + tracking: nil, + fetching: nil, + dangling: map[string][]common.Hash{ + "A": {testTxsHashes[0]}, + }, + }, + // Deliver the requested hashes + doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0], testTxs[1], testTxs[2]}, direct: true}, + isScheduled{nil, nil, nil}, + }, + }) +} + +// Tests that the waiting list timers properly reset and reschedule. +func TestTransactionFetcherWaitTimerResets(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + nil, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + doTxNotify{peer: "A", hashes: []common.Hash{{0x01}}}, + isWaiting(map[string][]common.Hash{ + "A": {{0x01}}, + }), + isScheduled{nil, nil, nil}, + doWait{time: txArriveTimeout / 2, step: false}, + isWaiting(map[string][]common.Hash{ + "A": {{0x01}}, + }), + isScheduled{nil, nil, nil}, + + doTxNotify{peer: "A", hashes: []common.Hash{{0x02}}}, + isWaiting(map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }), + isScheduled{nil, nil, nil}, + doWait{time: txArriveTimeout / 2, step: true}, + isWaiting(map[string][]common.Hash{ + "A": {{0x02}}, + }), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {{0x01}}, + }, + fetching: map[string][]common.Hash{ + "A": {{0x01}}, + }, + }, + + doWait{time: txArriveTimeout / 2, step: true}, + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }, + fetching: map[string][]common.Hash{ + "A": {{0x01}}, + }, + }, + }, + }) +} + +// Tests that if a transaction request is not replied to, it will time +// out and be re-scheduled for someone else. +func TestTransactionFetcherTimeoutRescheduling(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + func(txs []*types.Transaction) []error { + return make([]error, len(txs)) + }, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Push an initial announcement through to the scheduled stage + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, + isWaiting(map[string][]common.Hash{ + "A": {testTxsHashes[0]}, + }), + isScheduled{tracking: nil, fetching: nil}, + + doWait{time: txArriveTimeout, step: true}, + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {testTxsHashes[0]}, + }, + fetching: map[string][]common.Hash{ + "A": {testTxsHashes[0]}, + }, + }, + // Wait until the delivery times out, everything should be cleaned up + doWait{time: txFetchTimeout, step: true}, + isWaiting(nil), + isScheduled{ + tracking: nil, + fetching: nil, + dangling: map[string][]common.Hash{ + "A": {}, + }, + }, + // Ensure that followup announcements don't get scheduled + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[1]}}, + doWait{time: txArriveTimeout, step: true}, + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {testTxsHashes[1]}, + }, + fetching: nil, + dangling: map[string][]common.Hash{ + "A": {}, + }, + }, + // If the dangling request arrives a bit later, do not choke + doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0]}, direct: true}, + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {testTxsHashes[1]}, + }, + fetching: map[string][]common.Hash{ + "A": {testTxsHashes[1]}, + }, + }, + }, + }) +} + +// Tests that the fetching timeout timers properly reset and reschedule. +func TestTransactionFetcherTimeoutTimerResets(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + nil, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + doTxNotify{peer: "A", hashes: []common.Hash{{0x01}}}, + doWait{time: txArriveTimeout, step: true}, + doTxNotify{peer: "B", hashes: []common.Hash{{0x02}}}, + doWait{time: txArriveTimeout, step: true}, + + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {{0x01}}, + "B": {{0x02}}, + }, + fetching: map[string][]common.Hash{ + "A": {{0x01}}, + "B": {{0x02}}, + }, + }, + doWait{time: txFetchTimeout - txArriveTimeout, step: true}, + isScheduled{ + tracking: map[string][]common.Hash{ + "B": {{0x02}}, + }, + fetching: map[string][]common.Hash{ + "B": {{0x02}}, + }, + dangling: map[string][]common.Hash{ + "A": {}, + }, + }, + doWait{time: txArriveTimeout, step: true}, + isScheduled{ + tracking: nil, + fetching: nil, + dangling: map[string][]common.Hash{ + "A": {}, + "B": {}, + }, + }, + }, + }) +} + +// Tests that if thousands of transactions are announces, only a small +// number of them will be requested at a time. +func TestTransactionFetcherRateLimiting(t *testing.T) { + // Create a slew of transactions and to announce them + var hashes []common.Hash + for i := 0; i < maxTxAnnounces; i++ { + hashes = append(hashes, common.Hash{byte(i / 256), byte(i % 256)}) + } + + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + nil, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Announce all the transactions, wait a bit and ensure only a small + // percentage gets requested + doTxNotify{peer: "A", hashes: hashes}, + doWait{time: txArriveTimeout, step: true}, + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": hashes, + }, + fetching: map[string][]common.Hash{ + "A": hashes[1643 : 1643+maxTxRetrievals], + }, + }, + }, + }) +} + +// Tests that then number of transactions a peer is allowed to announce and/or +// request at the same time is hard capped. +func TestTransactionFetcherDoSProtection(t *testing.T) { + // Create a slew of transactions and to announce them + var hashesA []common.Hash + for i := 0; i < maxTxAnnounces+1; i++ { + hashesA = append(hashesA, common.Hash{0x01, byte(i / 256), byte(i % 256)}) + } + var hashesB []common.Hash + for i := 0; i < maxTxAnnounces+1; i++ { + hashesB = append(hashesB, common.Hash{0x02, byte(i / 256), byte(i % 256)}) + } + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + nil, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Announce half of the transaction and wait for them to be scheduled + doTxNotify{peer: "A", hashes: hashesA[:maxTxAnnounces/2]}, + doTxNotify{peer: "B", hashes: hashesB[:maxTxAnnounces/2-1]}, + doWait{time: txArriveTimeout, step: true}, + + // Announce the second half and keep them in the wait list + doTxNotify{peer: "A", hashes: hashesA[maxTxAnnounces/2 : maxTxAnnounces]}, + doTxNotify{peer: "B", hashes: hashesB[maxTxAnnounces/2-1 : maxTxAnnounces-1]}, + + // Ensure the hashes are split half and half + isWaiting(map[string][]common.Hash{ + "A": hashesA[maxTxAnnounces/2 : maxTxAnnounces], + "B": hashesB[maxTxAnnounces/2-1 : maxTxAnnounces-1], + }), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": hashesA[:maxTxAnnounces/2], + "B": hashesB[:maxTxAnnounces/2-1], + }, + fetching: map[string][]common.Hash{ + "A": hashesA[1643 : 1643+maxTxRetrievals], + "B": append(append([]common.Hash{}, hashesB[maxTxAnnounces/2-3:maxTxAnnounces/2-1]...), hashesB[:maxTxRetrievals-2]...), + }, + }, + // Ensure that adding even one more hash results in dropping the hash + doTxNotify{peer: "A", hashes: []common.Hash{hashesA[maxTxAnnounces]}}, + doTxNotify{peer: "B", hashes: hashesB[maxTxAnnounces-1 : maxTxAnnounces+1]}, + + isWaiting(map[string][]common.Hash{ + "A": hashesA[maxTxAnnounces/2 : maxTxAnnounces], + "B": hashesB[maxTxAnnounces/2-1 : maxTxAnnounces], + }), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": hashesA[:maxTxAnnounces/2], + "B": hashesB[:maxTxAnnounces/2-1], + }, + fetching: map[string][]common.Hash{ + "A": hashesA[1643 : 1643+maxTxRetrievals], + "B": append(append([]common.Hash{}, hashesB[maxTxAnnounces/2-3:maxTxAnnounces/2-1]...), hashesB[:maxTxRetrievals-2]...), + }, + }, + }, + }) +} + +// Tests that underpriced transactions don't get rescheduled after being rejected. +func TestTransactionFetcherUnderpricedDedup(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + func(txs []*types.Transaction) []error { + errs := make([]error, len(txs)) + for i := 0; i < len(errs); i++ { + if i%2 == 0 { + errs[i] = core.ErrUnderpriced + } else { + errs[i] = core.ErrReplaceUnderpriced + } + } + return errs + }, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Deliver a transaction through the fetcher, but reject as underpriced + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0], testTxsHashes[1]}}, + doWait{time: txArriveTimeout, step: true}, + doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0], testTxs[1]}, direct: true}, + isScheduled{nil, nil, nil}, + + // Try to announce the transaction again, ensure it's not scheduled back + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0], testTxsHashes[1], testTxsHashes[2]}}, // [2] is needed to force a step in the fetcher + isWaiting(map[string][]common.Hash{ + "A": {testTxsHashes[2]}, + }), + isScheduled{nil, nil, nil}, + }, + }) +} + +// Tests that underpriced transactions don't get rescheduled after being rejected, +// but at the same time there's a hard cap on the number of transactions that are +// tracked. +func TestTransactionFetcherUnderpricedDoSProtection(t *testing.T) { + // Temporarily disable fetch timeouts as they massively mess up the simulated clock + defer func(timeout time.Duration) { txFetchTimeout = timeout }(txFetchTimeout) + txFetchTimeout = 24 * time.Hour + + // Create a slew of transactions to max out the underpriced set + var txs []*types.Transaction + for i := 0; i < maxTxUnderpricedSetSize+1; i++ { + txs = append(txs, types.NewTransaction(rand.Uint64(), common.Address{byte(rand.Intn(256))}, new(big.Int), 0, new(big.Int), nil)) + } + hashes := make([]common.Hash, len(txs)) + for i, tx := range txs { + hashes[i] = tx.Hash() + } + // Generate a set of steps to announce and deliver the entire set of transactions + var steps []interface{} + for i := 0; i < maxTxUnderpricedSetSize/maxTxRetrievals; i++ { + steps = append(steps, doTxNotify{peer: "A", hashes: hashes[i*maxTxRetrievals : (i+1)*maxTxRetrievals]}) + steps = append(steps, isWaiting(map[string][]common.Hash{ + "A": hashes[i*maxTxRetrievals : (i+1)*maxTxRetrievals], + })) + steps = append(steps, doWait{time: txArriveTimeout, step: true}) + steps = append(steps, isScheduled{ + tracking: map[string][]common.Hash{ + "A": hashes[i*maxTxRetrievals : (i+1)*maxTxRetrievals], + }, + fetching: map[string][]common.Hash{ + "A": hashes[i*maxTxRetrievals : (i+1)*maxTxRetrievals], + }, + }) + steps = append(steps, doTxEnqueue{peer: "A", txs: txs[i*maxTxRetrievals : (i+1)*maxTxRetrievals], direct: true}) + steps = append(steps, isWaiting(nil)) + steps = append(steps, isScheduled{nil, nil, nil}) + steps = append(steps, isUnderpriced((i+1)*maxTxRetrievals)) + } + testTransactionFetcher(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + func(txs []*types.Transaction) []error { + errs := make([]error, len(txs)) + for i := 0; i < len(errs); i++ { + errs[i] = core.ErrUnderpriced + } + return errs + }, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: append(steps, []interface{}{ + // The preparation of the test has already been done in `steps`, add the last check + doTxNotify{peer: "A", hashes: []common.Hash{hashes[maxTxUnderpricedSetSize]}}, + doWait{time: txArriveTimeout, step: true}, + doTxEnqueue{peer: "A", txs: []*types.Transaction{txs[maxTxUnderpricedSetSize]}, direct: true}, + isUnderpriced(maxTxUnderpricedSetSize), + }...), + }) +} + +// Tests that unexpected deliveries don't corrupt the internal state. +func TestTransactionFetcherOutOfBoundDeliveries(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + func(txs []*types.Transaction) []error { + return make([]error, len(txs)) + }, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Deliver something out of the blue + isWaiting(nil), + isScheduled{nil, nil, nil}, + doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0]}, direct: false}, + isWaiting(nil), + isScheduled{nil, nil, nil}, + + // Set up a few hashes into various stages + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, + doWait{time: txArriveTimeout, step: true}, + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[1]}}, + doWait{time: txArriveTimeout, step: true}, + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[2]}}, + + isWaiting(map[string][]common.Hash{ + "A": {testTxsHashes[2]}, + }), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {testTxsHashes[0], testTxsHashes[1]}, + }, + fetching: map[string][]common.Hash{ + "A": {testTxsHashes[0]}, + }, + }, + // Deliver everything and more out of the blue + doTxEnqueue{peer: "B", txs: []*types.Transaction{testTxs[0], testTxs[1], testTxs[2], testTxs[3]}, direct: true}, + isWaiting(nil), + isScheduled{ + tracking: nil, + fetching: nil, + dangling: map[string][]common.Hash{ + "A": {testTxsHashes[0]}, + }, + }, + }, + }) +} + +// Tests that dropping a peer cleans out all internal data structures in all the +// live or danglng stages. +func TestTransactionFetcherDrop(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + func(txs []*types.Transaction) []error { + return make([]error, len(txs)) + }, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Set up a few hashes into various stages + doTxNotify{peer: "A", hashes: []common.Hash{{0x01}}}, + doWait{time: txArriveTimeout, step: true}, + doTxNotify{peer: "A", hashes: []common.Hash{{0x02}}}, + doWait{time: txArriveTimeout, step: true}, + doTxNotify{peer: "A", hashes: []common.Hash{{0x03}}}, + + isWaiting(map[string][]common.Hash{ + "A": {{0x03}}, + }), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {{0x01}, {0x02}}, + }, + fetching: map[string][]common.Hash{ + "A": {{0x01}}, + }, + }, + // Drop the peer and ensure everything's cleaned out + doDrop("A"), + isWaiting(nil), + isScheduled{nil, nil, nil}, + + // Push the node into a dangling (timeout) state + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, + doWait{time: txArriveTimeout, step: true}, + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {testTxsHashes[0]}, + }, + fetching: map[string][]common.Hash{ + "A": {testTxsHashes[0]}, + }, + }, + doWait{time: txFetchTimeout, step: true}, + isWaiting(nil), + isScheduled{ + tracking: nil, + fetching: nil, + dangling: map[string][]common.Hash{ + "A": {}, + }, + }, + // Drop the peer and ensure everything's cleaned out + doDrop("A"), + isWaiting(nil), + isScheduled{nil, nil, nil}, + }, + }) +} + +// Tests that dropping a peer instantly reschedules failed announcements to any +// available peer. +func TestTransactionFetcherDropRescheduling(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + func(txs []*types.Transaction) []error { + return make([]error, len(txs)) + }, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Set up a few hashes into various stages + doTxNotify{peer: "A", hashes: []common.Hash{{0x01}}}, + doWait{time: txArriveTimeout, step: true}, + doTxNotify{peer: "B", hashes: []common.Hash{{0x01}}}, + + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "A": {{0x01}}, + "B": {{0x01}}, + }, + fetching: map[string][]common.Hash{ + "A": {{0x01}}, + }, + }, + // Drop the peer and ensure everything's cleaned out + doDrop("A"), + isWaiting(nil), + isScheduled{ + tracking: map[string][]common.Hash{ + "B": {{0x01}}, + }, + fetching: map[string][]common.Hash{ + "B": {{0x01}}, + }, + }, + }, + }) +} + +// This test reproduces a crash caught by the fuzzer. The root cause was a +// dangling transaction timing out and clashing on readd with a concurrently +// announced one. +func TestTransactionFetcherFuzzCrash01(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + func(txs []*types.Transaction) []error { + return make([]error, len(txs)) + }, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Get a transaction into fetching mode and make it dangling with a broadcast + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, + doWait{time: txArriveTimeout, step: true}, + doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0]}}, + + // Notify the dangling transaction once more and crash via a timeout + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, + doWait{time: txFetchTimeout, step: true}, + }, + }) +} + +// This test reproduces a crash caught by the fuzzer. The root cause was a +// dangling transaction getting peer-dropped and clashing on readd with a +// concurrently announced one. +func TestTransactionFetcherFuzzCrash02(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + func(txs []*types.Transaction) []error { + return make([]error, len(txs)) + }, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Get a transaction into fetching mode and make it dangling with a broadcast + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, + doWait{time: txArriveTimeout, step: true}, + doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0]}}, + + // Notify the dangling transaction once more, re-fetch, and crash via a drop and timeout + doTxNotify{peer: "B", hashes: []common.Hash{testTxsHashes[0]}}, + doWait{time: txArriveTimeout, step: true}, + doDrop("A"), + doWait{time: txFetchTimeout, step: true}, + }, + }) +} + +// This test reproduces a crash caught by the fuzzer. The root cause was a +// dangling transaction getting rescheduled via a partial delivery, clashing +// with a concurrent notify. +func TestTransactionFetcherFuzzCrash03(t *testing.T) { + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + func(txs []*types.Transaction) []error { + return make([]error, len(txs)) + }, + func(string, []common.Hash) error { return nil }, + ) + }, + steps: []interface{}{ + // Get a transaction into fetching mode and make it dangling with a broadcast + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0], testTxsHashes[1]}}, + doWait{time: txFetchTimeout, step: true}, + doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0], testTxs[1]}}, + + // Notify the dangling transaction once more, partially deliver, clash&crash with a timeout + doTxNotify{peer: "B", hashes: []common.Hash{testTxsHashes[0]}}, + doWait{time: txArriveTimeout, step: true}, + + doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[1]}, direct: true}, + doWait{time: txFetchTimeout, step: true}, + }, + }) +} + +// This test reproduces a crash caught by the fuzzer. The root cause was a +// dangling transaction getting rescheduled via a disconnect, clashing with +// a concurrent notify. +func TestTransactionFetcherFuzzCrash04(t *testing.T) { + // Create a channel to control when tx requests can fail + proceed := make(chan struct{}) + + testTransactionFetcherParallel(t, txFetcherTest{ + init: func() *TxFetcher { + return NewTxFetcher( + func(common.Hash) bool { return false }, + func(txs []*types.Transaction) []error { + return make([]error, len(txs)) + }, + func(string, []common.Hash) error { + <-proceed + return errors.New("peer disconnected") + }, + ) + }, + steps: []interface{}{ + // Get a transaction into fetching mode and make it dangling with a broadcast + doTxNotify{peer: "A", hashes: []common.Hash{testTxsHashes[0]}}, + doWait{time: txArriveTimeout, step: true}, + doTxEnqueue{peer: "A", txs: []*types.Transaction{testTxs[0]}}, + + // Notify the dangling transaction once more, re-fetch, and crash via an in-flight disconnect + doTxNotify{peer: "B", hashes: []common.Hash{testTxsHashes[0]}}, + doWait{time: txArriveTimeout, step: true}, + doFunc(func() { + proceed <- struct{}{} // Allow peer A to return the failure + }), + doWait{time: 0, step: true}, + doWait{time: txFetchTimeout, step: true}, + }, + }) +} + +func testTransactionFetcherParallel(t *testing.T, tt txFetcherTest) { + t.Parallel() + testTransactionFetcher(t, tt) +} + +func testTransactionFetcher(t *testing.T, tt txFetcherTest) { + // Create a fetcher and hook into it's simulated fields + clock := new(mclock.Simulated) + wait := make(chan struct{}) + + fetcher := tt.init() + fetcher.clock = clock + fetcher.step = wait + fetcher.rand = rand.New(rand.NewSource(0x3a29)) + + fetcher.Start() + defer fetcher.Stop() + + // Crunch through all the test steps and execute them + for i, step := range tt.steps { + switch step := step.(type) { + case doTxNotify: + if err := fetcher.Notify(step.peer, step.hashes); err != nil { + t.Errorf("step %d: %v", i, err) + } + <-wait // Fetcher needs to process this, wait until it's done + select { + case <-wait: + panic("wtf") + case <-time.After(time.Millisecond): + } + + case doTxEnqueue: + if err := fetcher.Enqueue(step.peer, step.txs, step.direct); err != nil { + t.Errorf("step %d: %v", i, err) + } + <-wait // Fetcher needs to process this, wait until it's done + + case doWait: + clock.Run(step.time) + if step.step { + <-wait // Fetcher supposed to do something, wait until it's done + } + + case doDrop: + if err := fetcher.Drop(string(step)); err != nil { + t.Errorf("step %d: %v", i, err) + } + <-wait // Fetcher needs to process this, wait until it's done + + case doFunc: + step() + + case isWaiting: + // We need to check that the waiting list (stage 1) internals + // match with the expected set. Check the peer->hash mappings + // first. + for peer, hashes := range step { + waiting := fetcher.waitslots[peer] + if waiting == nil { + t.Errorf("step %d: peer %s missing from waitslots", i, peer) + continue + } + for _, hash := range hashes { + if _, ok := waiting[hash]; !ok { + t.Errorf("step %d, peer %s: hash %x missing from waitslots", i, peer, hash) + } + } + for hash := range waiting { + if !containsHash(hashes, hash) { + t.Errorf("step %d, peer %s: hash %x extra in waitslots", i, peer, hash) + } + } + } + for peer := range fetcher.waitslots { + if _, ok := step[peer]; !ok { + t.Errorf("step %d: peer %s extra in waitslots", i, peer) + } + } + // Peer->hash sets correct, check the hash->peer and timeout sets + for peer, hashes := range step { + for _, hash := range hashes { + if _, ok := fetcher.waitlist[hash][peer]; !ok { + t.Errorf("step %d, hash %x: peer %s missing from waitlist", i, hash, peer) + } + if _, ok := fetcher.waittime[hash]; !ok { + t.Errorf("step %d: hash %x missing from waittime", i, hash) + } + } + } + for hash, peers := range fetcher.waitlist { + if len(peers) == 0 { + t.Errorf("step %d, hash %x: empty peerset in waitlist", i, hash) + } + for peer := range peers { + if !containsHash(step[peer], hash) { + t.Errorf("step %d, hash %x: peer %s extra in waitlist", i, hash, peer) + } + } + } + for hash := range fetcher.waittime { + var found bool + for _, hashes := range step { + if containsHash(hashes, hash) { + found = true + break + } + } + if !found { + t.Errorf("step %d,: hash %x extra in waittime", i, hash) + } + } + + case isScheduled: + // Check that all scheduled announces are accounted for and no + // extra ones are present. + for peer, hashes := range step.tracking { + scheduled := fetcher.announces[peer] + if scheduled == nil { + t.Errorf("step %d: peer %s missing from announces", i, peer) + continue + } + for _, hash := range hashes { + if _, ok := scheduled[hash]; !ok { + t.Errorf("step %d, peer %s: hash %x missing from announces", i, peer, hash) + } + } + for hash := range scheduled { + if !containsHash(hashes, hash) { + t.Errorf("step %d, peer %s: hash %x extra in announces", i, peer, hash) + } + } + } + for peer := range fetcher.announces { + if _, ok := step.tracking[peer]; !ok { + t.Errorf("step %d: peer %s extra in announces", i, peer) + } + } + // Check that all announces required to be fetching are in the + // appropriate sets + for peer, hashes := range step.fetching { + request := fetcher.requests[peer] + if request == nil { + t.Errorf("step %d: peer %s missing from requests", i, peer) + continue + } + for _, hash := range hashes { + if !containsHash(request.hashes, hash) { + t.Errorf("step %d, peer %s: hash %x missing from requests", i, peer, hash) + } + } + for _, hash := range request.hashes { + if !containsHash(hashes, hash) { + t.Errorf("step %d, peer %s: hash %x extra in requests", i, peer, hash) + } + } + } + for peer := range fetcher.requests { + if _, ok := step.fetching[peer]; !ok { + if _, ok := step.dangling[peer]; !ok { + t.Errorf("step %d: peer %s extra in requests", i, peer) + } + } + } + for peer, hashes := range step.fetching { + for _, hash := range hashes { + if _, ok := fetcher.fetching[hash]; !ok { + t.Errorf("step %d, peer %s: hash %x missing from fetching", i, peer, hash) + } + } + } + for hash := range fetcher.fetching { + var found bool + for _, req := range fetcher.requests { + if containsHash(req.hashes, hash) { + found = true + break + } + } + if !found { + t.Errorf("step %d: hash %x extra in fetching", i, hash) + } + } + for _, hashes := range step.fetching { + for _, hash := range hashes { + alternates := fetcher.alternates[hash] + if alternates == nil { + t.Errorf("step %d: hash %x missing from alternates", i, hash) + continue + } + for peer := range alternates { + if _, ok := fetcher.announces[peer]; !ok { + t.Errorf("step %d: peer %s extra in alternates", i, peer) + continue + } + if _, ok := fetcher.announces[peer][hash]; !ok { + t.Errorf("step %d, peer %s: hash %x extra in alternates", i, hash, peer) + continue + } + } + for p := range fetcher.announced[hash] { + if _, ok := alternates[p]; !ok { + t.Errorf("step %d, hash %x: peer %s missing from alternates", i, hash, p) + continue + } + } + } + } + for peer, hashes := range step.dangling { + request := fetcher.requests[peer] + if request == nil { + t.Errorf("step %d: peer %s missing from requests", i, peer) + continue + } + for _, hash := range hashes { + if !containsHash(request.hashes, hash) { + t.Errorf("step %d, peer %s: hash %x missing from requests", i, peer, hash) + } + } + for _, hash := range request.hashes { + if !containsHash(hashes, hash) { + t.Errorf("step %d, peer %s: hash %x extra in requests", i, peer, hash) + } + } + } + // Check that all transaction announces that are scheduled for + // retrieval but not actively being downloaded are tracked only + // in the stage 2 `announced` map. + var queued []common.Hash + for _, hashes := range step.tracking { + for _, hash := range hashes { + var found bool + for _, hs := range step.fetching { + if containsHash(hs, hash) { + found = true + break + } + } + if !found { + queued = append(queued, hash) + } + } + } + for _, hash := range queued { + if _, ok := fetcher.announced[hash]; !ok { + t.Errorf("step %d: hash %x missing from announced", i, hash) + } + } + for hash := range fetcher.announced { + if !containsHash(queued, hash) { + t.Errorf("step %d: hash %x extra in announced", i, hash) + } + } + + case isUnderpriced: + if fetcher.underpriced.Cardinality() != int(step) { + t.Errorf("step %d: underpriced set size mismatch: have %d, want %d", i, fetcher.underpriced.Cardinality(), step) + } + + default: + t.Fatalf("step %d: unknown step type %T", i, step) + } + // After every step, cross validate the internal uniqueness invariants + // between stage one and stage two. + for hash := range fetcher.waittime { + if _, ok := fetcher.announced[hash]; ok { + t.Errorf("step %d: hash %s present in both stage 1 and 2", i, hash) + } + } + } +} + +// containsHash returns whether a hash is contained within a hash slice. +func containsHash(slice []common.Hash, hash common.Hash) bool { + for _, have := range slice { + if have == hash { + return true + } + } + return false +} diff --git a/eth/handler.go b/eth/handler.go index 5d8853c389..7c372ac6a2 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -47,14 +47,18 @@ import ( ) const ( - softResponseLimit = 2 * 1024 * 1024 // Target maximum size of returned blocks, headers or node data. - estHeaderRlpSize = 500 // Approximate size of an RLP encoded block header + // softResponseLimit is the target maximum size of replies to data retrievals. + softResponseLimit = 2 * 1024 * 1024 + + estHeaderRlpSize = 500 // Approximate size of an RLP encoded block header // txChanSize is the size of channel listening to NewTxsEvent. // The number is referenced from the size of tx pool. txChanSize = 4096 - numBroadcastTxPeers = 5 // Maximum number of peers for broadcast transactions + numBroadcastTxPeers = 5 // Maximum number of peers for broadcast transactions + numBroadcastTxHashPeers = 5 // Maximum number of peers for broadcast transactions hash + numBroadcastBlockPeers = 5 // Maximum number of peers for broadcast new block defaultTxsCacheSize = 20 defaultBroadcastInterval = 100 * time.Millisecond @@ -82,6 +86,7 @@ type ProtocolManager struct { downloader *downloader.Downloader fetcher *fetcher.Fetcher + txFetcher *fetcher.TxFetcher peers *peerSet SubProtocols []p2p.Protocol @@ -201,6 +206,15 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne //manager.fetcher = fetcher.New(GetBlockByHash, validator, manager.BroadcastBlock, heighter, inserter, manager.removePeer) manager.fetcher = fetcher.New(getBlockByHash, validator, manager.BroadcastBlock, heighter, inserter, manager.removePeer, decodeExtra) + fetchTx := func(peer string, hashes []common.Hash) error { + p := manager.peers.Peer(peer) + if p == nil { + return errors.New("unknown peer") + } + return p.RequestTxs(hashes) + } + manager.txFetcher = fetcher.NewTxFetcher(manager.txpool.Has, manager.txpool.AddRemotes, fetchTx) + return manager, nil } @@ -214,6 +228,7 @@ func (pm *ProtocolManager) removePeer(id string) { // Unregister the peer from the downloader and PlatON peer set pm.downloader.UnregisterPeer(id) + pm.txFetcher.Drop(id) if err := pm.peers.Unregister(id); err != nil { log.Error("Peer removal failed", "peer", id, "err", err) } @@ -278,7 +293,7 @@ func (pm *ProtocolManager) newPeer(pv int, p *p2p.Peer, rw p2p.MsgReadWriter) *p // this function terminates, the peer is disconnected. func (pm *ProtocolManager) handle(p *peer) error { // Ignore maxPeers if this is a trusted peer - if pm.peers.Len() >= pm.maxPeers && !p.Peer.Info().Network.Trusted && !p.Peer.Info().Network.Consensus { + if pm.peers.Len() >= pm.maxPeers && !p.Peer.Info().Network.Trusted && !p.Peer.Info().Network.Static { return p2p.DiscTooManyPeers } p.Log().Debug("PlatON peer connected", "name", p.Name()) @@ -340,7 +355,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { // Status messages should never arrive after the handshake return errResp(ErrExtraStatusMsg, "uncontrolled status message") - // Block header query, collect the requested headers and reply + // Block header query, collect the requested headers and reply case msg.Code == GetBlockHeadersMsg: // Decode the complex header query var query getBlockHeadersData @@ -797,7 +812,57 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { p.MarkTransaction(tx.Hash()) } - go pm.txpool.AddRemotes(txs) + if p.version < eth65 { + go pm.txpool.AddRemotes(txs) + } else { + // PooledTransactions and Transactions are all handled by txFetcher + return pm.txFetcher.Enqueue(p.id, txs, false) + } + + case p.version >= eth65 && msg.Code == NewPooledTransactionHashesMsg: + ann := new(NewPooledTransactionHashesPacket) + if err := msg.Decode(ann); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + // Schedule all the unknown hashes for retrieval + for _, hash := range *ann { + p.MarkTransaction(hash) + } + return pm.txFetcher.Notify(p.id, *ann) + + case p.version >= eth65 && msg.Code == GetPooledTransactionsMsg: + // Decode the pooled transactions retrieval message + var query GetPooledTransactionsPacket + if err := msg.Decode(&query); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + log.Trace("Handler Receive GetPooledTransactions", "peer", p.id, "hashes", len(query)) + hashes, txs := pm.answerGetPooledTransactions(query, p) + if len(txs) > 0 { + log.Trace("Handler Send PooledTransactions", "peer", p.id, "txs", len(txs)) + return p.SendPooledTransactionsRLP(hashes, txs) + } + + case p.version >= eth65 && msg.Code == PooledTransactionsMsg: + // Transactions arrived, make sure we have a valid and fresh chain to handle them + // if txmaker is started,the chain should not accept RemoteTxs,to reduce produce tx cost + if atomic.LoadUint32(&pm.acceptTxs) == 0 || atomic.LoadUint32(&pm.acceptRemoteTxs) == 1 { + break + } + // Transactions can be processed, parse all of them and deliver to the pool + var txs PooledTransactionsPacket + if err := msg.Decode(&txs); err != nil { + return errResp(ErrDecode, "msg %v: %v", msg, err) + } + for i, tx := range txs { + // Validate and mark the remote transaction + if tx == nil { + return errResp(ErrDecode, "transaction %d is nil", i) + } + p.MarkTransaction(tx.Hash()) + } + log.Trace("Handler Receive PooledTransactions", "peer", p.id, "txs", len(txs)) + return pm.txFetcher.Enqueue(p.id, txs, true) default: return errResp(ErrInvalidMsgCode, "%v", msg.Code) @@ -825,8 +890,21 @@ func (pm *ProtocolManager) BroadcastBlock(block *types.Block, propagate bool) { log.Warn("Propagating dangling block", "number", block.Number(), "hash", hash) return } - // Send the block to a subset of our peers - transfer := peers[:int(math.Sqrt(float64(len(peers))))] + + var transfer []*peer + if len(peers) <= numBroadcastBlockPeers { + // Send the block to all peers + transfer = peers + } else { + // Send the block to a subset of our peers + rand.Seed(time.Now().UnixNano()) + indexes := rand.Perm(len(peers)) + maxPeers := int(math.Sqrt(float64(len(peers)))) + transfer = make([]*peer, 0, maxPeers) + for i := 0; i < maxPeers; i++ { + transfer = append(transfer, peers[indexes[i]]) + } + } for _, peer := range transfer { peer.AsyncSendNewBlock(block) } @@ -845,8 +923,16 @@ func (pm *ProtocolManager) BroadcastBlock(block *types.Block, propagate bool) { // BroadcastTxs will propagate a batch of transactions to all peers which are not known to // already have the given transaction. func (pm *ProtocolManager) BroadcastTxs(txs types.Transactions) { - var txset = make(map[*peer]types.Transactions) + var ( + annoCount int // Count of announcements made + annoPeers int + directCount int // Count of the txs sent directly to peers + directPeers int // Count of the peers that were sent transactions directly + txset = make(map[*peer]types.Transactions) // Set peer->transaction to transfer directly + annos = make(map[*peer][]common.Hash) // Set peer->hash to announce + + ) rand.Seed(time.Now().UnixNano()) // Broadcast transactions to a batch of peers not knowing about it @@ -858,18 +944,67 @@ func (pm *ProtocolManager) BroadcastTxs(txs types.Transactions) { } } else { indexes := rand.Perm(len(peers)) - for i := 0; i < numBroadcastTxPeers; i++ { + numAnnos := int(math.Sqrt(float64(len(peers) - numBroadcastTxPeers))) + countAnnos := 0 + if numAnnos > numBroadcastTxHashPeers { + numAnnos = numBroadcastTxHashPeers + } + for i, c := 0, 0; i < len(peers) && countAnnos < numAnnos; i, c = i+1, c+1 { peer := peers[indexes[i]] - txset[peer] = append(txset[peer], tx) + if c < numBroadcastTxPeers { + txset[peer] = append(txset[peer], tx) + } else { + // For the remaining peers, send announcement only + annos[peer] = append(annos[peer], tx.Hash()) + countAnnos++ + } } } - //log.Trace("Broadcast transaction", "hash", tx.Hash(), "recipients", len(peers)) } - // FIXME include this again: peers = peers[:int(math.Sqrt(float64(len(peers))))] for peer, txs := range txset { + directPeers++ + directCount += len(txs) peer.AsyncSendTransactions(txs) } + for peer, hashes := range annos { + annoPeers++ + annoCount += len(hashes) + if peer.version >= eth65 { + peer.AsyncSendPooledTransactionHashes(hashes) + } + } + log.Trace("Transaction broadcast", "txs", len(txs), + "transaction packs", directPeers, "broadcast transaction", directCount, + "announce packs", annoPeers, "announced hashes", annoCount) +} + +func (pm *ProtocolManager) answerGetPooledTransactions(query GetPooledTransactionsPacket, peer *peer) ([]common.Hash, []rlp.RawValue) { + // Gather transactions until the fetch or network limits is reached + var ( + bytes int + hashes []common.Hash + txs []rlp.RawValue + ) + for _, hash := range query { + if bytes >= softResponseLimit { + break + } + // Retrieve the requested transaction, skipping if unknown to us + tx := pm.txpool.Get(hash) + if tx == nil { + continue + } + // If known, encode and queue for response packet + if encoded, err := rlp.EncodeToBytes(tx); err != nil { + log.Error("Failed to encode transaction", "err", err) + } else { + hashes = append(hashes, hash) + txs = append(txs, encoded) + bytes += len(encoded) + } + } + return hashes, txs } // Mined broadcast loop diff --git a/eth/helper_test.go b/eth/helper_test.go index 2d34dd18ec..ddcafea4e0 100644 --- a/eth/helper_test.go +++ b/eth/helper_test.go @@ -110,6 +110,34 @@ type testTxPool struct { lock sync.RWMutex // Protects the transaction pool } +// Has returns an indicator whether txpool has a transaction +// cached with the given hash. +func (p *testTxPool) Has(hash common.Hash) bool { + p.lock.Lock() + defer p.lock.Unlock() + + for _, tx := range p.pool{ + if tx.Hash() == hash{ + return true + } + } + return false +} + +// Get retrieves the transaction from local txpool with given +// tx hash. +func (p *testTxPool) Get(hash common.Hash) *types.Transaction { + p.lock.Lock() + defer p.lock.Unlock() + + for _, tx := range p.pool{ + if tx.Hash() == hash{ + return tx + } + } + return nil +} + // AddRemotes appends a batch of transactions to the pool, and notifies any // listeners if the addition channel is non nil func (p *testTxPool) AddRemotes(txs []*types.Transaction) []error { diff --git a/eth/peer.go b/eth/peer.go index b264a79c96..9078e35ff0 100644 --- a/eth/peer.go +++ b/eth/peer.go @@ -27,7 +27,7 @@ import ( "github.com/AlayaNetwork/Alaya-Go/core/cbfttypes" "github.com/AlayaNetwork/Alaya-Go/eth/downloader" - mapset "github.com/deckarep/golang-set" + "github.com/deckarep/golang-set" "github.com/AlayaNetwork/Alaya-Go/common" "github.com/AlayaNetwork/Alaya-Go/core/types" @@ -45,10 +45,13 @@ const ( maxKnownTxs = 32768 // Maximum transactions hashes to keep in the known list (prevent DOS) maxKnownBlocks = 1024 // Maximum block hashes to keep in the known list (prevent DOS) - // maxQueuedTxs is the maximum number of transaction lists to queue up before - // dropping broadcasts. This is a sensitive number as a transaction list might - // contain a single transaction, or thousands. - maxQueuedTxs = 128 + // maxQueuedTxs is the maximum number of transactions to queue up before dropping + // older broadcasts. + maxQueuedTxs = 4096 + + // maxQueuedTxAnns is the maximum number of transaction announcements to queue up + // before dropping older announcements. + maxQueuedTxAnns = 4096 // maxQueuedProps is the maximum number of block propagations to queue up before // dropping broadcasts. There's not much point in queueing stale blocks, so a few @@ -69,6 +72,14 @@ const ( maxPrioritySigCounts = 10 ) +// max is a helper function which returns the larger of the two given integers. +func max(a, b int) int { + if a > b { + return a + } + return b +} + // PeerInfo represents a short summary of the Ethereum sub-protocol metadata known // about a connected peer. type PeerInfo struct { @@ -98,10 +109,12 @@ type peer struct { knownTxs mapset.Set // Set of transaction hashes known to be known by this peer knownBlocks mapset.Set // Set of block hashes known to be known by this peer knownPrepareBlocks mapset.Set // Set of prepareblock hashes known to be known by this peer - queuedTxs chan []*types.Transaction // Queue of transactions to broadcast to the peer - queuedProps chan *propEvent // Queue of blocks to broadcast to the peer - queuedAnns chan *types.Block // Queue of blocks to announce to the peer - term chan struct{} // Termination channel to stop the broadcaster + txBroadcast chan []*types.Transaction // Channel used to queue transaction propagation requests + txAnnounce chan []common.Hash // Channel used to queue transaction announcement requests + + queuedProps chan *propEvent // Queue of blocks to broadcast to the peer + queuedAnns chan *types.Block // Queue of blocks to announce to the peer + term chan struct{} // Termination channel to stop the broadcaster } func newPeer(version int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { @@ -112,7 +125,8 @@ func newPeer(version int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { id: fmt.Sprintf("%x", p.ID().Bytes()[:8]), knownTxs: mapset.NewSet(), knownBlocks: mapset.NewSet(), - queuedTxs: make(chan []*types.Transaction, maxQueuedTxs), + txBroadcast: make(chan []*types.Transaction), + txAnnounce: make(chan []common.Hash), queuedProps: make(chan *propEvent, maxQueuedProps), queuedAnns: make(chan *types.Block, maxQueuedAnns), term: make(chan struct{}), @@ -145,20 +159,20 @@ func (p *peer) broadcast() { } }() - go func() { - for { - select { - case txs := <-p.queuedTxs: - if err := p.SendTransactions(txs); err != nil { - return - } - p.Log().Trace("Broadcast transactions", "count", len(txs)) - - case <-p.term: - return - } - } - }() + //go func() { + // for { + // select { + // case txs := <-p.txBroadcast: + // if err := p.SendTransactions(txs); err != nil { + // return + // } + // p.Log().Trace("Broadcast transactions", "count", len(txs)) + // + // case <-p.term: + // return + // } + // } + //}() } // close signals the broadcast goroutine to terminate. @@ -218,30 +232,74 @@ func (p *peer) MarkTransaction(hash common.Hash) { // SendTransactions sends transactions to the peer and includes the hashes // in its transaction hash set for future reference. +// +// This method is a helper used by the async transaction sender. Don't call it +// directly as the queueing (memory) and transmission (bandwidth) costs should +// not be managed directly. +// +// The reasons this is public is to allow packages using this protocol to write +// tests that directly send messages without having to do the asyn queueing. func (p *peer) SendTransactions(txs types.Transactions) error { - + // Mark all the transactions as known, but ensure we don't overflow our limits + for p.knownTxs.Cardinality() > max(0, maxKnownTxs-len(txs)) { + p.knownTxs.Pop() + } for _, tx := range txs { p.knownTxs.Add(tx.Hash()) } - for p.knownTxs.Cardinality() >= maxKnownTxs { + return p2p.Send(p.rw, TxMsg, txs) +} + +// sendPooledTransactionHashes sends transaction hashes to the peer and includes +// them in its transaction hash set for future reference. +// +// This method is a helper used by the async transaction announcer. Don't call it +// directly as the queueing (memory) and transmission (bandwidth) costs should +// not be managed directly. +func (p *peer) sendPooledTransactionHashes(hashes []common.Hash) error { + // Mark all the transactions as known, but ensure we don't overflow our limits + for p.knownTxs.Cardinality() > max(0, maxKnownTxs-len(hashes)) { p.knownTxs.Pop() } - return p2p.Send(p.rw, TxMsg, txs) + for _, hash := range hashes { + p.knownTxs.Add(hash) + } + return p2p.Send(p.rw, NewPooledTransactionHashesMsg, NewPooledTransactionHashesPacket(hashes)) } // AsyncSendTransactions queues list of transactions propagation to a remote // peer. If the peer's broadcast queue is full, the event is silently dropped. func (p *peer) AsyncSendTransactions(txs []*types.Transaction) { select { - case p.queuedTxs <- txs: + case p.txBroadcast <- txs: + // Mark all the transactions as known, but ensure we don't overflow our limits + for p.knownTxs.Cardinality() > max(0, maxKnownTxs-len(txs)) { + p.knownTxs.Pop() + } + for _, tx := range txs { p.knownTxs.Add(tx.Hash()) } - for p.knownTxs.Cardinality() >= maxKnownTxs { + case <-p.term: + p.Log().Debug("Dropping transaction propagation", "count", len(txs)) + } +} + +// AsyncSendPooledTransactionHashes queues a list of transactions hashes to eventually +// announce to a remote peer. The number of pending sends are capped (new ones +// will force old sends to be dropped) +func (p *peer) AsyncSendPooledTransactionHashes(hashes []common.Hash) { + select { + case p.txAnnounce <- hashes: + // Mark all the transactions as known, but ensure we don't overflow our limits + for p.knownTxs.Cardinality() > max(0, maxKnownTxs-len(hashes)) { p.knownTxs.Pop() } - default: - //p.Log().Debug("Dropping transaction propagation", "count", len(txs)) + for _, hash := range hashes { + p.knownTxs.Add(hash) + } + case <-p.term: + p.Log().Debug("Dropping transaction announcement", "count", len(hashes)) } } @@ -518,6 +576,10 @@ func (ps *peerSet) Register(p *peer) error { } ps.peers[p.id] = p go p.broadcast() + go p.broadcastTransactions() + if p.version >= eth65 { + go p.announceTransactions() + } return nil } @@ -692,3 +754,25 @@ func (p *peer) SendPrepareBlock(block *types.Block) error { func (p *peer) SendSignature(signature *cbfttypes.BlockSignature) error { return p2p.Send(p.rw, BlockSignatureMsg, []interface{}{signature.SignHash, signature.Hash, signature.Number, signature.Signature}) } + +// RequestTxs fetches a batch of transactions from a remote node. +func (p *peer) RequestTxs(hashes []common.Hash) error { + p.Log().Debug("Fetching batch of transactions", "count", len(hashes)) + return p2p.Send(p.rw, GetPooledTransactionsMsg, GetPooledTransactionsPacket(hashes)) +} + +// SendPooledTransactionsRLP sends requested transactions to the peer and adds the +// hashes in its transaction hash set for future reference. +// +// Note, the method assumes the hashes are correct and correspond to the list of +// transactions being sent. +func (p *peer) SendPooledTransactionsRLP(hashes []common.Hash, txs []rlp.RawValue) error { + // Mark all the transactions as known, but ensure we don't overflow our limits + for p.knownTxs.Cardinality() > max(0, maxKnownTxs-len(hashes)) { + p.knownTxs.Pop() + } + for _, hash := range hashes { + p.knownTxs.Add(hash) + } + return p2p.Send(p.rw, PooledTransactionsMsg, txs) // Not packed into PooledTransactionsPacket to avoid RLP decoding +} diff --git a/eth/protocol.go b/eth/protocol.go index 4e86c14a71..714e18aba4 100644 --- a/eth/protocol.go +++ b/eth/protocol.go @@ -32,16 +32,17 @@ import ( const ( eth62 = 62 eth63 = 63 + eth65 = 65 ) // ProtocolName is the official short name of the protocol used during capability negotiation. var ProtocolName = "platon" // ProtocolVersions are the upported versions of the eth protocol (first is primary). -var ProtocolVersions = []uint{eth63, eth62} +var ProtocolVersions = []uint{eth65, eth63, eth62} // ProtocolLengths are the number of implemented message corresponding to different protocol versions. -var ProtocolLengths = []uint64{23, 8} +var ProtocolLengths = []uint64{40, 23, 8} const ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message @@ -71,6 +72,11 @@ const ( GetOriginAndPivotMsg = 0x13 OriginAndPivotMsg = 0x14 PPOSInfoMsg = 0x15 + + // For transaction fetcher + NewPooledTransactionHashesMsg = 0x16 + GetPooledTransactionsMsg = 0x17 + PooledTransactionsMsg = 0x18 ) type errCode int @@ -105,7 +111,24 @@ var errorToString = map[int]string{ ErrSuspendedPeer: "Suspended peer", } +// NewPooledTransactionHashesPacket represents a transaction announcement packet. +type NewPooledTransactionHashesPacket []common.Hash + +// GetPooledTransactionsPacket represents a transaction query. +type GetPooledTransactionsPacket []common.Hash + +// PooledTransactionsPacket is the network packet for transaction distribution. +type PooledTransactionsPacket []*types.Transaction + type txPool interface { + // Has returns an indicator whether txpool has a transaction + // cached with the given hash. + Has(hash common.Hash) bool + + // Get retrieves the transaction from local txpool with given + // tx hash. + Get(hash common.Hash) *types.Transaction + // AddRemotes should add the given transactions to the pool. AddRemotes([]*types.Transaction) []error diff --git a/eth/sync.go b/eth/sync.go index 1f733714e2..7baee09f70 100644 --- a/eth/sync.go +++ b/eth/sync.go @@ -135,7 +135,9 @@ func (pm *ProtocolManager) txsyncLoop() { func (pm *ProtocolManager) syncer() { // Start and ensure cleanup of sync mechanisms pm.fetcher.Start() + pm.txFetcher.Start() defer pm.fetcher.Stop() + defer pm.txFetcher.Stop() defer pm.downloader.Terminate() // Wait for different events to fire synchronisation operations @@ -179,6 +181,10 @@ func (pm *ProtocolManager) synchronise(peer *peer) { } // Otherwise try to sync with the downloader mode := downloader.FullSync + if currentBlock.NumberU64() > 0 { + log.Info("Blockchain not empty, auto disabling fast sync") + atomic.StoreUint32(&pm.fastSync, 0) + } if atomic.LoadUint32(&pm.fastSync) == 1 { // Fast sync was explicitly requested, and explicitly granted mode = downloader.FastSync diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 07c3d95c29..d1b4c7160a 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -62,6 +62,15 @@ func (ec *Client) Close() { } // Blockchain Access +// ChainId retrieves the current chain ID for transaction replay protection. +func (ec *Client) ChainID(ctx context.Context) (*big.Int, error) { + var result hexutil.Big + err := ec.c.CallContext(ctx, &result, "platon_chainId") + if err != nil { + return nil, err + } + return (*big.Int)(&result), err +} // BlockByHash returns the given full block. // diff --git a/go.mod b/go.mod index 06e3559ce6..30fc035778 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/AlayaNetwork/Alaya-Go -go 1.13 +go 1.14 require ( github.com/Azure/azure-pipeline-go v0.0.0-20180607212504-7571e8eb0876 // indirect @@ -8,7 +8,6 @@ require ( github.com/PlatONnetwork/wagon v0.6.1-0.20201026015350-67507c2a7b96 github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect github.com/VictoriaMetrics/fastcache v1.5.7 - github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 github.com/btcsuite/btcd v0.20.1-beta github.com/btcsuite/btcutil v1.0.2 github.com/cespare/cp v0.1.0 @@ -26,7 +25,6 @@ require ( github.com/golang/snappy v0.0.1 github.com/google/go-cmp v0.4.0 // indirect github.com/hashicorp/golang-lru v0.5.4 - github.com/herumi/bls v0.0.0-20200610053137-1f4204f8b9be github.com/holiman/uint256 v1.1.1 github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3 github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883 @@ -42,7 +40,6 @@ require ( github.com/panjf2000/ants/v2 v2.4.1 github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 github.com/peterh/liner v1.0.1-0.20170902204657-a37ad3984311 - github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 github.com/pkg/errors v0.9.1 github.com/prometheus/prometheus v1.7.2-0.20170814170113-3101606756c5 github.com/rjeczalik/notify v0.9.1 @@ -58,7 +55,6 @@ require ( golang.org/x/net v0.0.0-20200602114024-627f9648deb9 golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 golang.org/x/text v0.3.1-0.20171227012246-e19ae1496984 // indirect - golang.org/x/tools v0.0.0-20170215214335-be0fcc31ae23 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200316214253-d7b0ff38cac9 diff --git a/internal/cmdtest/test_cmd.go b/internal/cmdtest/test_cmd.go index 50e5040c41..03ea1da48b 100644 --- a/internal/cmdtest/test_cmd.go +++ b/internal/cmdtest/test_cmd.go @@ -27,6 +27,8 @@ import ( "regexp" "strings" "sync" + "sync/atomic" + "syscall" "testing" "text/template" "time" @@ -50,12 +52,17 @@ type TestCmd struct { stdout *bufio.Reader stdin io.WriteCloser stderr *testlogger + // Err will contain the process exit error or interrupt signal error + Err error } +var id int32 + // Run exec's the current binary using name as argv[0] which will trigger the // reexec init function for that name (e.g. "alaya-test" in cmd/alaya/run_test.go) func (tt *TestCmd) Run(name string, args ...string) { - tt.stderr = &testlogger{t: tt.T} + id := atomic.AddInt32(&id, 1) + tt.stderr = &testlogger{t: tt.T, name: fmt.Sprintf("%d", id)} tt.cmd = &exec.Cmd{ Path: reexec.Self(), Args: append([]string{name}, args...), @@ -74,7 +81,7 @@ func (tt *TestCmd) Run(name string, args ...string) { } } -// InputLine writes the given text to the childs stdin. +// InputLine writes the given text to the child's stdin. // This method can also be called from an expect template, e.g.: // // alaya.expect(`Passphrase: {{.InputLine "password"}}`) @@ -109,7 +116,6 @@ func (tt *TestCmd) Expect(tplsource string) { want := bytes.TrimPrefix(wantbuf.Bytes(), []byte("\n")) if err := tt.matchExactOutput(want); err != nil { - tt.Log(tt.StderrText()) tt.Fatal(err) } tt.Logf("Matched stdout text:\n%s", want) @@ -121,6 +127,7 @@ func (tt *TestCmd) matchExactOutput(want []byte) error { n := 0 tt.withKillTimeout(func() { n, _ = io.ReadFull(tt.stdout, buf) }) buf = buf[:n] + tt.Log(string(buf)) if n < len(want) || !bytes.Equal(buf, want) { // Grab any additional buffered output in case of mismatch @@ -131,12 +138,12 @@ func (tt *TestCmd) matchExactOutput(want []byte) error { for i := 0; i < n; i++ { if want[i] != buf[i] { - return fmt.Errorf("Output mismatch at ◊:\n---------------- (stdout text)\n%s◊%s\n---------------- (expected text)\n%s", + return fmt.Errorf("output mismatch at ◊:\n---------------- (stdout text)\n%s◊%s\n---------------- (expected text)\n%s", buf[:i], buf[i:n], want) } } if n < len(want) { - return fmt.Errorf("Not enough output, got until ◊:\n---------------- (stdout text)\n%s\n---------------- (expected text)\n%s◊%s", + return fmt.Errorf("not enough output, got until ◊:\n---------------- (stdout text)\n%s\n---------------- (expected text)\n%s◊%s", buf, want[:n], want[n:]) } } @@ -189,11 +196,25 @@ func (tt *TestCmd) ExpectExit() { } func (tt *TestCmd) WaitExit() { - tt.cmd.Wait() + tt.Err = tt.cmd.Wait() } func (tt *TestCmd) Interrupt() { - tt.cmd.Process.Signal(os.Interrupt) + tt.Err = tt.cmd.Process.Signal(os.Interrupt) +} + +// ExitStatus exposes the process' OS exit code +// It will only return a valid value after the process has finished. +func (tt *TestCmd) ExitStatus() int { + if tt.Err != nil { + exitErr := tt.Err.(*exec.ExitError) + if exitErr != nil { + if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { + return status.ExitStatus() + } + } + } + return 0 } // StderrText returns any stderr output written so far. @@ -217,7 +238,7 @@ func (tt *TestCmd) Kill() { } func (tt *TestCmd) withKillTimeout(fn func()) { - timeout := time.AfterFunc(5*time.Second, func() { + timeout := time.AfterFunc(30*time.Second, func() { tt.Log("killing the child process (timeout)") tt.Kill() }) @@ -228,16 +249,17 @@ func (tt *TestCmd) withKillTimeout(fn func()) { // testlogger logs all written lines via t.Log and also // collects them for later inspection. type testlogger struct { - t *testing.T - mu sync.Mutex - buf bytes.Buffer + t *testing.T + mu sync.Mutex + buf bytes.Buffer + name string } func (tl *testlogger) Write(b []byte) (n int, err error) { lines := bytes.Split(b, []byte("\n")) for _, line := range lines { if len(line) > 0 { - tl.t.Logf("(stderr) %s", line) + tl.t.Logf("(stderr:%v) %s", tl.name, line) } } tl.mu.Lock() diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 5668aefa9d..b89b888aa3 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -510,6 +510,15 @@ func NewPublicBlockChainAPI(b Backend) *PublicBlockChainAPI { // return nil //} +// ChainId is the EIP-155 replay-protection chain id for the current ethereum chain config. +func (s *PublicBlockChainAPI) ChainId() (*hexutil.Big, error) { + // if current block is at or past the EIP-155 replay-protection fork block, return chainID from config + if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) { + return (*hexutil.Big)(config.ChainID), nil + } + return nil, fmt.Errorf("chain not synced beyond EIP-155 replay-protection fork block") +} + // BlockNumber returns the block number of the chain head. func (s *PublicBlockChainAPI) BlockNumber() hexutil.Uint64 { header, _ := s.b.HeaderByNumber(context.Background(), rpc.LatestBlockNumber) // latest header should always be available diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index 553d15db9a..7a902cfbc9 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -427,6 +427,11 @@ const Platon_JS = ` web3._extend({ property: 'platon', methods: [ + new web3._extend.Method({ + name: 'chainId', + call: 'platon_chainId', + params: 0 + }), new web3._extend.Method({ name: 'setActor', call: 'platon_setActor', @@ -547,7 +552,7 @@ web3._extend({ params: 2 }), //new web3._extend.Method({ - // name: 'deriveAccount', + // name: 'deriveAccount', // call: 'personal_deriveAccount', // params: 3 //}), diff --git a/miner/miner.go b/miner/miner.go index a3b8989339..b1637ca030 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -21,8 +21,6 @@ import ( "sync/atomic" "time" - "github.com/AlayaNetwork/Alaya-Go/core/vm" - "github.com/AlayaNetwork/Alaya-Go/consensus" "github.com/AlayaNetwork/Alaya-Go/core" "github.com/AlayaNetwork/Alaya-Go/core/state" @@ -51,7 +49,7 @@ type Miner struct { shouldStart int32 // should start indicates whether we should start after sync } -func New(eth Backend, config *params.ChainConfig, miningConfig *core.MiningConfig, vmConfig *vm.Config, mux *event.TypeMux, +func New(eth Backend, config *params.ChainConfig, miningConfig *core.MiningConfig, mux *event.TypeMux, engine consensus.Engine, recommit time.Duration, gasFloor uint64, isLocalBlock func(block *types.Block) bool, blockChainCache *core.BlockChainCache, vmTimeout uint64) *Miner { miner := &Miner{ @@ -59,7 +57,7 @@ func New(eth Backend, config *params.ChainConfig, miningConfig *core.MiningConfi mux: mux, engine: engine, exitCh: make(chan struct{}), - worker: newWorker(config, miningConfig, vmConfig, engine, eth, mux, recommit, gasFloor, isLocalBlock, blockChainCache, vmTimeout), + worker: newWorker(config, miningConfig, engine, eth, mux, recommit, gasFloor, isLocalBlock, blockChainCache, vmTimeout), canStart: 1, } go miner.update() diff --git a/miner/worker.go b/miner/worker.go index 6870051286..2070fae282 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -135,7 +135,6 @@ type worker struct { EmptyBlock string config *params.ChainConfig miningConfig *core.MiningConfig - vmConfig *vm.Config engine consensus.Engine eth Backend chain *core.BlockChain @@ -202,14 +201,13 @@ type worker struct { vmTimeout uint64 } -func newWorker(config *params.ChainConfig, miningConfig *core.MiningConfig, vmConfig *vm.Config, engine consensus.Engine, +func newWorker(config *params.ChainConfig, miningConfig *core.MiningConfig, engine consensus.Engine, eth Backend, mux *event.TypeMux, recommit time.Duration, gasFloor uint64, isLocalBlock func(*types.Block) bool, blockChainCache *core.BlockChainCache, vmTimeout uint64) *worker { worker := &worker{ config: config, miningConfig: miningConfig, - vmConfig: vmConfig, engine: engine, eth: eth, mux: mux, @@ -735,7 +733,10 @@ func (w *worker) resultLoop() { log.Info("Successfully write new block", "hash", block.Hash(), "number", block.NumberU64(), "coinbase", block.Coinbase(), "time", block.Time(), "root", block.Root()) // Broadcast the block and announce chain insertion event - w.mux.Post(core.NewMinedBlockEvent{Block: block}) + if !w.engine.Syncing() { + log.Trace("Broadcast the block and announce chain insertion event", "hash", block.Hash(), "number", block.NumberU64()) + w.mux.Post(core.NewMinedBlockEvent{Block: block}) + } var events []interface{} switch stat { @@ -797,9 +798,10 @@ func (w *worker) updateSnapshot() { func (w *worker) commitTransaction(tx *types.Transaction) ([]*types.Log, error) { snapForSnap, snapForState := w.current.DBSnapshot() - + vmCfg := *w.chain.GetVMConfig() // value copy + vmCfg.VmTimeoutDuration = w.vmTimeout // set vm execution smart contract timeout duration receipt, _, err := core.ApplyTransaction(w.config, w.chain, w.current.gasPool, w.current.state, - w.current.header, tx, &w.current.header.GasUsed, *w.chain.GetVMConfig()) + w.current.header, tx, &w.current.header.GasUsed, vmCfg) if err != nil { log.Error("Failed to commitTransaction on worker", "blockNumer", w.current.header.Number.Uint64(), "txHash", tx.Hash().String(), "err", err) w.current.RevertToDBSnapshot(snapForSnap, snapForState) diff --git a/miner/worker_test.go b/miner/worker_test.go index 5a23917095..85102dc46b 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -153,7 +153,7 @@ func newTestWorker(t *testing.T, chainConfig *params.ChainConfig, miningConfig * bftResultSub := event.Subscribe(cbfttypes.CbftResult{}) core.NewBlockChainReactor(event, chainConfig.ChainID) - w := newWorker(chainConfig, miningConfig, &vm.Config{}, engine, backend, event, time.Second, params.GenesisGasLimit, nil, backend.chainCache, 0) + w := newWorker(chainConfig, miningConfig, engine, backend, event, time.Second, params.GenesisGasLimit, nil, backend.chainCache, 0) go func() { for { diff --git a/mobile/android_test.go b/mobile/android_test.go index 12856cbd87..2628bfa300 100644 --- a/mobile/android_test.go +++ b/mobile/android_test.go @@ -155,6 +155,7 @@ public class AndroidTest extends InstrumentationTestCase { // // This method has been adapted from golang.org/x/mobile/bind/java/seq_test.go/runTest func TestAndroid(t *testing.T) { + t.Skip("not support current") // Skip tests on Windows altogether if runtime.GOOS == "windows" { t.Skip("cannot test Android bindings on Windows, skipping") diff --git a/mobile/params.go b/mobile/params.go index c470fe494d..4ae248c610 100644 --- a/mobile/params.go +++ b/mobile/params.go @@ -26,12 +26,6 @@ import ( "github.com/AlayaNetwork/Alaya-Go/params" ) -// MainnetGenesis returns the JSON spec to use for the main Ethereum network. It -// is actually empty since that defaults to the hard coded binary genesis block. -func MainnetGenesis() string { - return "" -} - // TestnetGenesis returns the JSON spec to use for the Alpha test network. func TestnetGenesis() string { enc, err := json.Marshal(core.DefaultTestnetGenesisBlock()) diff --git a/node/config.go b/node/config.go index 215527b308..dd70f93f1d 100644 --- a/node/config.go +++ b/node/config.go @@ -241,7 +241,7 @@ func DefaultWSEndpoint() string { // NodeName returns the devp2p node identifier. func (c *Config) NodeName() string { name := c.name() - if name == "alaya" || name == "alaya-testnet" || name == "alaya-betanet" || name == "alaya-innertestnet" || name == "alaya-innerdevnet" { + if name == "platon" || name == "alaya" || name == "alaya-testnet" || name == "alaya-betanet" || name == "alaya-innertestnet" || name == "alaya-innerdevnet" { name = "AlayaNetwork" } if c.UserIdent != "" { @@ -291,7 +291,7 @@ func (c *Config) ResolvePath(path string) string { // by alaya 1.4 are used if they exist. if warn, isOld := isOldPlatONResource[path]; isOld { oldpath := "" - if c.name() == "alaya" { + if c.name() == "platon" { oldpath = filepath.Join(c.DataDir, path) } if oldpath != "" && common.FileExist(oldpath) { diff --git a/node/crypto_handler.go b/node/crypto_handler.go index dfbeb98a6c..c530d706c2 100755 --- a/node/crypto_handler.go +++ b/node/crypto_handler.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/node/crypto_handler_test.go b/node/crypto_handler_test.go index ff933d1c6d..d556b0f342 100755 --- a/node/crypto_handler_test.go +++ b/node/crypto_handler_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/node/defaults.go b/node/defaults.go index 9b5c1b7ff7..248e37ebcb 100644 --- a/node/defaults.go +++ b/node/defaults.go @@ -45,9 +45,9 @@ var DefaultConfig = Config{ WSModules: []string{"net", "web3"}, P2P: p2p.Config{ ListenAddr: ":16789", - MaxPeers: 50, + MaxPeers: 60, NAT: nat.Any(), - MaxConsensusPeers: 75, + MaxConsensusPeers: 40, }, } diff --git a/node/fake.go b/node/fake.go index 863c3826de..a563882c30 100644 --- a/node/fake.go +++ b/node/fake.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify diff --git a/p2p/dial.go b/p2p/dial.go index 4f24377175..55d974e227 100644 --- a/p2p/dial.go +++ b/p2p/dial.go @@ -81,8 +81,8 @@ type dialstate struct { randomNodes []*discover.Node // filled from Table static map[discover.NodeID]*dialTask //consensus map[discover.NodeID]*dialTask - consensus *dialedTasks - hist *dialHistory + consensus *dialedTasks + hist *dialHistory start time.Time // time when the dialer was first used bootnodes []*discover.Node // default dials when there are no peers @@ -138,7 +138,7 @@ func newDialState(static []*discover.Node, bootnodes []*discover.Node, ntab disc netrestrict: netrestrict, static: make(map[discover.NodeID]*dialTask), //consensus: make(map[discover.NodeID]*dialTask), - consensus: NewDialedTasks(maxConsensusPeers, nil), + consensus: NewDialedTasks(maxConsensusPeers*2, nil), dialing: make(map[discover.NodeID]connFlag), bootnodes: make([]*discover.Node, len(bootnodes)), randomNodes: make([]*discover.Node, maxdyn/2), diff --git a/p2p/peer_error.go b/p2p/peer_error.go index ab61bfef06..e992026ee4 100644 --- a/p2p/peer_error.go +++ b/p2p/peer_error.go @@ -62,6 +62,7 @@ const ( DiscProtocolError DiscUselessPeer DiscTooManyPeers + DiscTooManyConsensusPeers DiscAlreadyConnected DiscIncompatibleVersion DiscInvalidIdentity @@ -73,19 +74,20 @@ const ( ) var discReasonToString = [...]string{ - DiscRequested: "disconnect requested", - DiscNetworkError: "network error", - DiscProtocolError: "breach of protocol", - DiscUselessPeer: "useless peer", - DiscTooManyPeers: "too many peers", - DiscAlreadyConnected: "already connected", - DiscIncompatibleVersion: "incompatible p2p protocol version", - DiscInvalidIdentity: "invalid node identity", - DiscQuitting: "client quitting", - DiscUnexpectedIdentity: "unexpected identity", - DiscSelf: "connected to self", - DiscReadTimeout: "read timeout", - DiscSubprotocolError: "subprotocol error", + DiscRequested: "disconnect requested", + DiscNetworkError: "network error", + DiscProtocolError: "breach of protocol", + DiscUselessPeer: "useless peer", + DiscTooManyPeers: "too many peers", + DiscTooManyConsensusPeers: "too many consensus peers", + DiscAlreadyConnected: "already connected", + DiscIncompatibleVersion: "incompatible p2p protocol version", + DiscInvalidIdentity: "invalid node identity", + DiscQuitting: "client quitting", + DiscUnexpectedIdentity: "unexpected identity", + DiscSelf: "connected to self", + DiscReadTimeout: "read timeout", + DiscSubprotocolError: "subprotocol error", } func (d DiscReason) String() string { diff --git a/p2p/server.go b/p2p/server.go index dfc092a69a..265633e6a6 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -1028,9 +1028,19 @@ func (srv *Server) protoHandshakeChecks(peers map[discover.NodeID]*Peer, inbound return srv.encHandshakeChecks(peers, inboundCount, c) } +func (srv *Server) numConsensusPeer(peers map[discover.NodeID]*Peer) int { + c := 0 + for _, p := range peers { + if p.rw.is(consensusDialedConn) { + c++ + } + } + return c +} + func (srv *Server) encHandshakeChecks(peers map[discover.NodeID]*Peer, inboundCount int, c *conn) error { // Disconnect over limit non-consensus node. - if srv.consensus && len(peers) >= srv.MaxPeers && c.is(consensusDialedConn) { + if srv.consensus && len(peers) >= srv.MaxPeers && c.is(consensusDialedConn) && srv.numConsensusPeer(peers) < srv.MaxConsensusPeers { for _, p := range peers { if p.rw.is(inboundConn|dynDialedConn) && !p.rw.is(trustedConn|staticDialedConn|consensusDialedConn) { log.Debug("Disconnect over limit connection", "peer", p.ID(), "flags", p.rw.flags, "peers", len(peers)) @@ -1041,6 +1051,10 @@ func (srv *Server) encHandshakeChecks(peers map[discover.NodeID]*Peer, inboundCo } switch { + case c.is(consensusDialedConn) && srv.numConsensusPeer(peers) >= srv.MaxConsensusPeers: + return DiscTooManyConsensusPeers + case !srv.consensus && c.is(consensusDialedConn) && len(peers) >= srv.MaxPeers: + return DiscTooManyPeers case !c.is(trustedConn|staticDialedConn|consensusDialedConn) && len(peers) >= srv.MaxPeers: return DiscTooManyPeers case !c.is(trustedConn|consensusDialedConn) && c.is(inboundConn) && inboundCount >= srv.maxInboundConns(): diff --git a/p2p/server_test.go b/p2p/server_test.go index 7aeed3e3d4..940b508e28 100644 --- a/p2p/server_test.go +++ b/p2p/server_test.go @@ -418,6 +418,7 @@ func TestServerAtCap(t *testing.T) { // Try inserting a consensus connection. consensusID := randomID() + srv.consensus = true srv.AddConsensusPeer(&discover.Node{ID: consensusID}) c = newconn(consensusID) if err := srv.checkpoint(c, srv.posthandshake); err != nil { @@ -427,6 +428,13 @@ func TestServerAtCap(t *testing.T) { t.Error("Server did not set consensus flag") } + // An InboundConn connection was broken in the previous step, and an InboundConn connection is added + time.Sleep(time.Second) // Waiting remove peer + c = newconn(randomID()) + if err := srv.checkpoint(c, srv.addpeer); err != nil { + t.Fatalf("could not add conn: %v", err) + } + // Remove from consensus set and try again srv.RemoveConsensusPeer(&discover.Node{ID: consensusID}) c = newconn(consensusID) @@ -444,6 +452,13 @@ func TestServerAtCap(t *testing.T) { t.Error("Server did not set consensus flag") } + // An InboundConn connection was broken in the previous step, and an InboundConn connection is added + time.Sleep(time.Second) // Waiting remove peer + c = newconn(randomID()) + if err := srv.checkpoint(c, srv.addpeer); err != nil { + t.Fatalf("could not add conn: %v", err) + } + // Removing non-consensus connection srv.consensus = true srv.AddConsensusPeer(&discover.Node{ID: consensusID}) diff --git a/params/bootnodes.go b/params/bootnodes.go index 64491a0b2f..13fa0866e4 100644 --- a/params/bootnodes.go +++ b/params/bootnodes.go @@ -16,17 +16,6 @@ package params -// MainnetBootnodes are the enode URLs of the P2P bootstrap nodes running on -// the main PlatON network. -var MainnetBootnodes = []string{ - "enode://81dd24640878badc06de82a82fdb0fe55f24d27877144261d81b1f39faa6686ac8f5d2489dbf97cd44d583b4b00976a8f92845378084d25c7a8bae671a543983@127.0.0.1:16789", -} - -// TestnetBootnodes are the enode URLs of the P2P bootstrap nodes running on the test network. -var TestnetBootnodes = []string{ - "enode://3fec5e5982a0b32a25168dae575c4705ab8509f266947cb8b16b62ac9eafb78d3e7efce2c31bac447edce3446a12b71383a41dcbdbe80fa856d8739b0214ff35@127.0.0.1:16789", -} - // DiscoveryV5Bootnodes are the enode URLs of the P2P bootstrap nodes for the // experimental RLPx v5 topic-discovery network. var DiscoveryV5Bootnodes = []string{} @@ -41,6 +30,3 @@ var AlayanetBootnodes = []string{ "enode://49648f184dab8acf0927238452e1f7e8f0e86135dcd148baa0a2d22cd931ed9770f726fccf13a3976bbdb738a880a074dc21d811037190267cd9c8c1378a6043@seed6.8d4b.alaya.network:16789", "enode://5670e1b34fe39da46ebdd9c3377053c5214c7b3e6b371d31fcc381f788414a38d44cf844ad71305eb1d0d8afddee8eccafb4d30b33b54ca002db47c4864ba080@seed7.bdac.alaya.network:16789", } - -// AlayaTestnetBootnodes are the enode URLs of the P2P bootstrap nodes running on the test network. -var AlayaTestnetBootnodes = []string{} diff --git a/params/config.go b/params/config.go index 6a3ea05691..c01a89cb01 100644 --- a/params/config.go +++ b/params/config.go @@ -27,77 +27,43 @@ import ( // Genesis hashes to enforce below configs on. var ( - MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3") TestnetGenesisHash = common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d") AlayanetGenesisHash = common.HexToHash("0xfb787fede6752e1a5ad85d2c6fc140454759be5e69d86d2425ceac22c23bd419") - //todo need update - AlayaTestnetGenesisHash = common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d") ) var TrustedCheckpoints = map[common.Hash]*TrustedCheckpoint{ - MainnetGenesisHash: MainnetTrustedCheckpoint, - TestnetGenesisHash: TestnetTrustedCheckpoint, + //MainnetGenesisHash: MainnetTrustedCheckpoint, + //TestnetGenesisHash: TestnetTrustedCheckpoint, } var ( - initialMainNetConsensusNodes = []initNode{ - { - "enode://6de1c55250563c4eb75f7ad3dd54cf5f6b86150bd8613b171ee28e1abc0c4936cf1d0cbc3939734fde31a147af226f98c33bd14d52be23cc2b34b5ba6e0d8765@mf1.a4f9.platon.network:16789", - "555d942d5cc88f3891933986d6dcf9b597f9865c1c8443666ceb0b9097b54a31473a036ceac47e714eaaaeeee2775f15a190449b1fa64cec4072b9407d685b196900ed7a30cd428715ac0f5a4f9c688d66b605daa5efbcab4b188f605a27b502", - }, - { - "enode://3b416a1fb1e66154087e4d98960a24935ab203da330d2fb7be44a1ffce0861cade982a83ff541cd9eef4f0b0b950449be290fd993279973d21a411d3832a52d4@mf2.8cd2.platon.network:16789", - "83268442e50daf719eab1c97d5d9928fcf02bbd6912af904d1d6bedc6c83943f8e9165bf38ffda995f4ff7b89fac5d104141feb5babe40428137701eff3a2289b9aeffbcd2d9160dee560378cd2ee46b90c70a2bdf3d8b62c76bf197f33fe407", - }, - { - "enode://e0d5a4a8732b411040a525db2780cdd8dd45e434f4e8d80400fefbe9b48079e8490ea9e56327c5ae76646107995a7f44d655821818a11bbc0ba6026ce480ccc9@mf3.f9ec.platon.network:16789", - "8d28bef573a9df55a622419e48a6ec2a8a7719c1750ce555e19e5f41927677b5d2885522d9186c538e665a3ada26c50fc52cbe95f4889025c65b8300cd713a2e5afbe7ee4d4953c6dad73adf9ecc5a696cf84a6dd1e1cb3cf7f57b7bb9ade813", - }, - { - "enode://7ebbb666b11d7d63f278308a4750f3721d55bd2fc5115f529fbae12792053672ae7309b1567cd0403b001fe00d678c17ffbc8dfb2a26a8365bd174d37e473d4b@mf4.add3.platon.network:16789", - "99c17a47260722ecdb6074aa1f3d318173702daf930aaaff13b659bbd19f4a98eb10f6edd86ddd1aa588c0989676bf18244ed886a7ff02de930d2a85609710a1e26ae2031a8d88c6d5e2dc1add3462a94a6e2590e16986934c0e2e8d2354680c", - }, - { - "enode://3d5d15388828830ec67711b6d93785868693ddcf27bb8b02217c3dff5ee99b75c6287245a7dfd268f7d340acde44babe3c7ea0c98d0d8f156b985ec81714e293@mf5.0354.platon.network:16789", - "aeb6804f9e1561338b2277b833349aebfbf524e164f96218f2b4c06a9c92ff59d06e0ff5866bbed81c43cfb16075e90911186f37b4678b44a11d7a17ede1d0aab223709d4b80ec4c09843d403544e16c865ce92f20f3455bf2b1502c3933b390", - }, - { - "enode://0f2a38f778e0617ed42b34d21d7b3d28a526a49f142269b0307de505b332c85b7f89f05ae3e39a5896a65928ea3d112e640853b5bbaa77d7c5763bfecb328f7a@mf6.9e2c.platon.network:16789", - "bd8778181425e509f7a37604d2778511f1ede950751d785cbf5a9573623d006c1767e7074c7566088592d6d62106e5001e297a3f352159b5a6e78ed7d55b4691b6f0eade7b25240b2a468099e2c1adb3fbf24bc2e849d476574c7c91e597f684", - }, - { - "enode://f4ff6f37bddb21c02bdaa5a66f0c6572c6aaa0493fdc44cc341d3c2623379c1210862324439a6ea09e11635fafd535d0c3294ba439065b6aa4af50887bece72f@mf7.e1dd.platon.network:16789", - "a298740a0cc11d32d1fe5088db78b9492be0bbefabc85e723f43f715c587eb71d5509122d87c63c61f513bd4f436e607547c249e05211e007d18909e7a275fe973b341099c9d8b540aea15fe1dd04eeb5ebaf2395594626ffe85b419e0410a00", - }, - } - initialTestnetConsensusNodes = []initNode{ { - "enode://b7f1f7757a900cce7ce4caf8663ecf871205763ac201c65f9551d5b841731a9cd9550bc05f3a16fbc2ef589c9faeef74d4500b60d76047939e2ba7fa4a5915aa@tf1.8e1f.platon.network:16789", + "enode://b7f1f7757a900cce7ce4caf8663ecf871205763ac201c65f9551d5b841731a9cd9550bc05f3a16fbc2ef589c9faeef74d4500b60d76047939e2ba7fa4a5915aa@127.0.0.1:16789", "f1735bac863706b49809a4e635fe0c2e224aef5ad549f18ba3f2f6b61c0c9d0005f12d497a301ba26a8aaf009c90e4198301875002984c5cd9bd614cd2fbcb81c57f6355a8400d56c20804e1dfb34782c1f2eadda82c8b226aa4a71bfa60be8c", }, { - "enode://3b2acc72f673173a97295728f6d9f93a8d75d1c615455f3ec3fdc4471e707e54935d89ba4736082db4b618b05de203fe828a8182b0f1ba09d495ad9a8ddb418b@tf2.dd0b.platon.network:16789", + "enode://3b2acc72f673173a97295728f6d9f93a8d75d1c615455f3ec3fdc4471e707e54935d89ba4736082db4b618b05de203fe828a8182b0f1ba09d495ad9a8ddb418b@127.0.0.1:16789", "bd0d378e9d87e552d6f3842b38e30776e45eb14af3462822cbadf5eea492477dd764d10cc73c521e05fa90c6146dd70a6ae1bd25f473147b91ddd65e5077ead12a1010de2714ef7977067df4b519ab2f7d50db7c2e150dc2d5cb2bb6cc30e485", }, { - "enode://184fb0464cd84a28e6c9aec564c058113b6c93ae80eccf1dc50be0481fd27bbfea3dfef492898987aeabba07fd0b5b7048a88163da348b729b0b56b6184f6e6c@tf3.4984.platon.network:16789", + "enode://184fb0464cd84a28e6c9aec564c058113b6c93ae80eccf1dc50be0481fd27bbfea3dfef492898987aeabba07fd0b5b7048a88163da348b729b0b56b6184f6e6c@127.0.0.1:16789", "fd89eb74d9277b8a02eb32f2144bf571d7badbca85ea7ea1158f47f268e36119a8e83608b4b972a5fd332bdc4f0306149390ed0afa4f6bae3e18f80a6062feff0a53cd265c38a3bff43afdf93c06dd8cdd0928a57039aaf59712623cd412a38d", }, { - "enode://31df231e05e089ee517f577a4ded288d210fc9d313c4ed862a7a758e4a74d8ae4b84de69be837371120a521199bce5ecf8665a56cd1efc2c8b665dd563a3f590@tf4.3c1b.platon.network:16789", + "enode://31df231e05e089ee517f577a4ded288d210fc9d313c4ed862a7a758e4a74d8ae4b84de69be837371120a521199bce5ecf8665a56cd1efc2c8b665dd563a3f590@127.0.0.1:16789", "1c6792a7868006106547d48fb77e2941240352fd5def1f447b38c88585655e02bdf91209b48db698866a92b59914d00cacbb4206f99ece4e78fb82a12c732039d5a17e23b9980cd26421f953c3017199dbd41b62f13227d69123f431fdae3506", }, { - "enode://50ed65eb0180f771bbef453f0750bb324b626e6283b10b5203cae28e2e50744ba4bae51242f5d5dd17ce8d5bb71c50599f0432fd64b6a64d8026de181d8c5ae3@tf5.6021.platon.network:16789", + "enode://50ed65eb0180f771bbef453f0750bb324b626e6283b10b5203cae28e2e50744ba4bae51242f5d5dd17ce8d5bb71c50599f0432fd64b6a64d8026de181d8c5ae3@127.0.0.1:16789", "0e82ee8823646e871d319a5e418c5845af4efebbffc873ace0b27ff1391c720fafb98a118447cca88efa2653cb1d8a1443fd38079bd8385e6291a52776158882360657b3c401c1a1dc2fb2cfc083247f454ea160fc6aadecdbc1b44ee7aa6f8c", }, { - "enode://487a68847885a7b198b24920c1a5addc82d7c62fb43a503d7a4701a9fd72deed5e4f53116d8cca139d66731a2dc7537d5234d400188710864b83a7ccd65ab74d@tf6.f6a9.platon.network:16789", + "enode://487a68847885a7b198b24920c1a5addc82d7c62fb43a503d7a4701a9fd72deed5e4f53116d8cca139d66731a2dc7537d5234d400188710864b83a7ccd65ab74d@127.0.0.1:16789", "a41e72db25f7e4d2af738e6170d5d84c72c69a185be75f55a62fb5ad0b931061f8f32c13d851f96d0b819f67d079c205b12d73507fa156967c8e6f385c2ab5b373f6f4a5e3e86bd95fe9857001a1feabcdf9507b45f446a7066213563a8d7a81", }, { - "enode://081da72f53a7cc4eaeace9f8a2960c1c01bf606153fd5acf47f540e0f2a1ebe5aed36fc8bf10263308b18845fe0079e027c85af31e03f995b6834d88f8461a19@tf7.f361.platon.network:16789", + "enode://081da72f53a7cc4eaeace9f8a2960c1c01bf606153fd5acf47f540e0f2a1ebe5aed36fc8bf10263308b18845fe0079e027c85af31e03f995b6834d88f8461a19@127.0.0.1:16789", "77d174270903955fd8b38de00c05c17b078031722e1fc414188251a5da34aa8025dc3cb75bebedf5cd8eb91d25bee213a5fd78f12ed77892bd2f2e4a21595a413280e37d1d1726bf9fa62e042307de89ee6e243304ef768bac3a9d466dc3a406", }, } @@ -133,28 +99,6 @@ var ( }, } - initialAlayaTestNetConsensusNodes = []initNode{ - { - "enode://b7f1f7757a900cce7ce4caf8663ecf871205763ac201c65f9551d5b841731a9cd9550bc05f3a16fbc2ef589c9faeef74d4500b60d76047939e2ba7fa4a5915aa@tf1.8e1f.platon.network:16789", - "f1735bac863706b49809a4e635fe0c2e224aef5ad549f18ba3f2f6b61c0c9d0005f12d497a301ba26a8aaf009c90e4198301875002984c5cd9bd614cd2fbcb81c57f6355a8400d56c20804e1dfb34782c1f2eadda82c8b226aa4a71bfa60be8c", - }, - } - - // MainnetChainConfig is the chain parameters to run a node on the main network. - MainnetChainConfig = &ChainConfig{ - ChainID: big.NewInt(100), - AddressHRP: "atp", - EmptyBlock: "on", - EIP155Block: big.NewInt(1), - Cbft: &CbftConfig{ - InitialNodes: ConvertNodeUrl(initialMainNetConsensusNodes), - Amount: 10, - ValidatorMode: "ppos", - Period: 20000, - }, - GenesisVersion: GenesisVersion, - } - // AlayaChainConfig is the chain parameters to run a node on the main network. AlayaChainConfig = &ChainConfig{ ChainID: big.NewInt(201018), @@ -170,30 +114,6 @@ var ( GenesisVersion: GenesisVersion, } - // AlayaTestChainConfig is the chain parameters to run a node on the main network. - AlayaTestChainConfig = &ChainConfig{ - ChainID: big.NewInt(201030), - AddressHRP: "atp", - EmptyBlock: "on", - EIP155Block: big.NewInt(1), - Cbft: &CbftConfig{ - InitialNodes: ConvertNodeUrl(initialAlayaTestNetConsensusNodes), - Amount: 10, - ValidatorMode: "ppos", - Period: 20000, - }, - GenesisVersion: GenesisVersion, - } - - // MainnetTrustedCheckpoint contains the light client trusted checkpoint for the main network. - MainnetTrustedCheckpoint = &TrustedCheckpoint{ - Name: "mainnet", - SectionIndex: 193, - SectionHead: common.HexToHash("0xc2d574295ecedc4d58530ae24c31a5a98be7d2b3327fba0dd0f4ed3913828a55"), - CHTRoot: common.HexToHash("0x5d1027dfae688c77376e842679ceada87fd94738feb9b32ef165473bfbbb317b"), - BloomRoot: common.HexToHash("0xd38be1a06aabd568e10957fee4fcc523bc64996bcf31bae3f55f86e0a583919f"), - } - // TestnetChainConfig is the chain parameters to run a node on the test network. TestnetChainConfig = &ChainConfig{ ChainID: big.NewInt(104), @@ -209,15 +129,6 @@ var ( GenesisVersion: GenesisVersion, } - // TestnetTrustedCheckpoint contains the light client trusted checkpoint for the test network. - TestnetTrustedCheckpoint = &TrustedCheckpoint{ - Name: "testnet", - SectionIndex: 123, - SectionHead: common.HexToHash("0xa372a53decb68ce453da12bea1c8ee7b568b276aa2aab94d9060aa7c81fc3dee"), - CHTRoot: common.HexToHash("0x6b02e7fada79cd2a80d4b3623df9c44384d6647fc127462e1c188ccd09ece87b"), - BloomRoot: common.HexToHash("0xf2d27490914968279d6377d42868928632573e823b5d1d4a944cba6009e16259"), - } - GrapeChainConfig = &ChainConfig{ AddressHRP: "atp", ChainID: big.NewInt(304), diff --git a/params/protocol_params.go b/params/protocol_params.go index 9c2686c2e8..0e3bed3112 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -133,13 +133,13 @@ const ( // PlatONPrecompiled contract gas - StakingGas uint64 = 6000 // Gas needed for precompiled contract: stakingContract - CreateStakeGas uint64 = 32000 // Gas needed for createStaking - EditCandidatGas uint64 = 12000 // Gas needed for editCandidate - IncStakeGas uint64 = 20000 // Gas needed for increaseStaking - WithdrewStakeGas uint64 = 20000 // Gas needed for withdrewStaking - DelegateGas uint64 = 16000 // Gas needed for delegate - WithdrewDelegateGas uint64 = 8000 // Gas needed for withdrewDelegate + StakingGas uint64 = 6000 // Gas needed for precompiled contract: stakingContract + CreateStakeGas uint64 = 32000 // Gas needed for createStaking + EditCandidatGas uint64 = 12000 // Gas needed for editCandidate + IncStakeGas uint64 = 20000 // Gas needed for increaseStaking + WithdrewStakeGas uint64 = 20000 // Gas needed for withdrewStaking + DelegateGas uint64 = 16000 // Gas needed for delegate + WithdrewDelegationGas uint64 = 8000 // Gas needed for withdrewDelegation GovGas uint64 = 9000 // Gas needed for precompiled contract: govContract SubmitTextProposalGas uint64 = 320000 // Gas needed for submitText diff --git a/params/version.go b/params/version.go index a61e5670fa..fd18ddca80 100644 --- a/params/version.go +++ b/params/version.go @@ -23,8 +23,8 @@ import ( const ( //These versions are meaning the current code version. VersionMajor = 0 // Major version component of the current release - VersionMinor = 15 // Minor version component of the current release - VersionPatch = 1 // Patch version component of the current release + VersionMinor = 16 // Minor version component of the current release + VersionPatch = 0 // Patch version component of the current release VersionMeta = "unstable" // Version metadata to append to the version string //CAUTION: DO NOT MODIFY THIS ONCE THE CHAIN HAS BEEN INITIALIZED!!! diff --git a/params/version_history.go b/params/version_history.go index 28b1ed6f98..66c39ab024 100644 --- a/params/version_history.go +++ b/params/version_history.go @@ -4,4 +4,5 @@ const ( FORKVERSION_0_11_0 = uint32(0<<16 | 11<<8 | 0) FORKVERSION_0_14_0 = uint32(0<<16 | 14<<8 | 0) FORKVERSION_0_15_0 = uint32(0<<16 | 15<<8 | 0) + FORKVERSION_0_16_0 = uint32(0<<16 | 16<<8 | 0) ) diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index febbb187a1..6367baccd0 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -144,7 +144,7 @@ func (t *VMTest) newEVM(statedb *state.StateDB, vmconfig vm.Config) *vm.EVM { GasPrice: t.json.Exec.GasPrice, } vmconfig.NoRecursion = true - return vm.NewEVM(context, nil, statedb, params.MainnetChainConfig, vmconfig) + return vm.NewEVM(context, nil, statedb, params.AlayaChainConfig, vmconfig) } func vmTestBlockHash(n uint64) common.Hash { diff --git a/x/gov/gov.go b/x/gov/gov.go index 8b6c60f5eb..9a2d6ebd01 100644 --- a/x/gov/gov.go +++ b/x/gov/gov.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package gov import ( @@ -91,6 +92,14 @@ func Gte0150Version(version uint32) bool { return version >= params.FORKVERSION_0_15_0 } +func Gte0160VersionState(state xcom.StateDB) bool { + return Gte0160Version(GetCurrentActiveVersion(state)) +} + +func Gte0160Version(version uint32) bool { + return version >= params.FORKVERSION_0_16_0 +} + func WriteEcHash0140(state xcom.StateDB) error { if data, err := xcom.EcParams0140(); nil != err { return err diff --git a/x/gov/gov_db.go b/x/gov/gov_db.go index 7392444644..15a9eb8df3 100644 --- a/x/gov/gov_db.go +++ b/x/gov/gov_db.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package gov import ( diff --git a/x/gov/gov_db_test.go b/x/gov/gov_db_test.go index 93dc6ff225..97a73b3af3 100644 --- a/x/gov/gov_db_test.go +++ b/x/gov/gov_db_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package gov import ( diff --git a/x/gov/gov_err.go b/x/gov/gov_err.go index 7709b33439..0c707f53d8 100644 --- a/x/gov/gov_err.go +++ b/x/gov/gov_err.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package gov import "github.com/AlayaNetwork/Alaya-Go/common" diff --git a/x/gov/gov_keys.go b/x/gov/gov_keys.go index 6d59c2b004..ddd00ed72a 100644 --- a/x/gov/gov_keys.go +++ b/x/gov/gov_keys.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package gov import ( diff --git a/x/gov/gov_params.go b/x/gov/gov_params.go index 4408d473e5..6687e5d645 100644 --- a/x/gov/gov_params.go +++ b/x/gov/gov_params.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package gov import ( diff --git a/x/gov/gov_snapdb.go b/x/gov/gov_snapdb.go index 113d1ff637..dedacba35c 100644 --- a/x/gov/gov_snapdb.go +++ b/x/gov/gov_snapdb.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package gov import ( diff --git a/x/gov/gov_test.go b/x/gov/gov_test.go index cd9beca11f..c491dd9695 100644 --- a/x/gov/gov_test.go +++ b/x/gov/gov_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package gov import ( diff --git a/x/gov/gov_types.go b/x/gov/gov_types.go index 4aac06eee1..c9660f88de 100644 --- a/x/gov/gov_types.go +++ b/x/gov/gov_types.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package gov import ( diff --git a/x/gov/proposals.go b/x/gov/proposals.go index dffc6425db..b65cbf53fb 100644 --- a/x/gov/proposals.go +++ b/x/gov/proposals.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package gov import ( diff --git a/x/handler/vrf_handler.go b/x/handler/vrf_handler.go index f384e50703..95e25dc62e 100644 --- a/x/handler/vrf_handler.go +++ b/x/handler/vrf_handler.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package handler import ( diff --git a/x/handler/vrf_handler_test.go b/x/handler/vrf_handler_test.go index 370e906d7b..7f2503d395 100644 --- a/x/handler/vrf_handler_test.go +++ b/x/handler/vrf_handler_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package handler import ( @@ -118,3 +119,51 @@ func TestVrfHandler_Verify(t *testing.T) { assert.Equal(t, ErrInvalidVrfProve, err) } } + +func TestVrfHandler_Storage_GovMaxValidators(t *testing.T) { + initHandler() + defer func() { + vh.db.Clear() + }() + + gov.InitGenesisGovernParam(common.ZeroHash, vh.db, 2048) + + blockNumber := new(big.Int).SetUint64(1) + phash := common.BytesToHash([]byte("h")) + hash := common.ZeroHash + govPoint := xcom.MaxValidators() + 2 + for i := 0; i < int(xcom.MaxValidators())+10; i++ { + if err := vh.db.NewBlock(blockNumber, phash, common.ZeroHash); nil != err { + t.Fatal(err) + } + if i == int(govPoint) { + if err := gov.SetGovernParam(gov.ModuleStaking, gov.KeyMaxValidators, "", strconv.Itoa(int(govPoint-1)), 1, common.ZeroHash); nil != err { + t.Fatal(err) + } + } + if i == int(govPoint+2) { + if err := gov.SetGovernParam(gov.ModuleStaking, gov.KeyMaxValidators, "", strconv.Itoa(int(govPoint+2)), 1, common.ZeroHash); nil != err { + t.Fatal(err) + } + } + pi, err := vh.GenerateNonce(blockNumber, phash) + if nil != err { + t.Fatal(err) + } + if err := vh.Storage(blockNumber, phash, common.ZeroHash, vrf.ProofToHash(pi)); nil != err { + t.Fatal(err) + } + hash = common.BytesToHash([]byte(strconv.Itoa(i))) + phash = hash + if err := vh.db.Flush(hash, blockNumber); nil != err { + t.Fatal(err) + } + blockNumber.Add(blockNumber, common.Big1) + } + if value, err := vh.Load(hash); nil != err { + t.Fatal(err) + } else { + maxValidatorsNum, _ := gov.GovernMaxValidators(blockNumber.Uint64(), hash) + assert.Equal(t, len(value), int(maxValidatorsNum)) + } +} diff --git a/x/plugin/api.go b/x/plugin/api.go index 8de17a3a1b..b623974361 100644 --- a/x/plugin/api.go +++ b/x/plugin/api.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package plugin import ( diff --git a/x/plugin/base_plugin.go b/x/plugin/base_plugin.go index db2bc5d7d6..86894b9ac0 100644 --- a/x/plugin/base_plugin.go +++ b/x/plugin/base_plugin.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package plugin import ( diff --git a/x/plugin/gov_plugin.go b/x/plugin/gov_plugin.go index 3c52512760..26935e9b90 100644 --- a/x/plugin/gov_plugin.go +++ b/x/plugin/gov_plugin.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package plugin import ( @@ -147,6 +148,18 @@ func (govPlugin *GovPlugin) BeginBlock(blockHash common.Hash, header *types.Head } log.Info("Successfully upgraded the new version 0.15.0", "blockNumber", blockNumber, "blockHash", blockHash, "preActiveProposalID", preActiveVersionProposalID) } + if versionProposal.NewVersion == params.FORKVERSION_0_16_0 { + fixSharesPlugin := NewFixIssue1654Plugin(snapshotdb.Instance()) + if err := fixSharesPlugin.fix(blockHash, govPlugin.chainID, state); err != nil { + return err + } + + fixPlugin := NewFixIssue1583Plugin() + if err := fixPlugin.fix(blockHash, govPlugin.chainID, state); err != nil { + return err + } + log.Info("Successfully upgraded the new version 0.16.0", "blockNumber", blockNumber, "blockHash", blockHash, "preActiveProposalID", preActiveVersionProposalID) + } log.Info("version proposal is active", "blockNumber", blockNumber, "proposalID", versionProposal.ProposalID, "newVersion", versionProposal.NewVersion, "newVersionString", xutil.ProgramVersion2Str(versionProposal.NewVersion)) } diff --git a/x/plugin/gov_plugin_test.go b/x/plugin/gov_plugin_test.go index e4fcaf9234..586955156e 100644 --- a/x/plugin/gov_plugin_test.go +++ b/x/plugin/gov_plugin_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package plugin import ( diff --git a/x/plugin/issue1583_patch.go b/x/plugin/issue1583_patch.go new file mode 100644 index 0000000000..2a3856128c --- /dev/null +++ b/x/plugin/issue1583_patch.go @@ -0,0 +1,129 @@ +// Copyright 2021 The Alaya Network Authors +// This file is part of the Alaya-Go library. +// +// The Alaya-Go 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 Alaya-Go 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 Alaya-Go library. If not, see . + +package plugin + +import ( + "math/big" + + "github.com/AlayaNetwork/Alaya-Go/log" + + "github.com/AlayaNetwork/Alaya-Go/params" + + "github.com/AlayaNetwork/Alaya-Go/x/reward" + + "github.com/AlayaNetwork/Alaya-Go/common" + "github.com/AlayaNetwork/Alaya-Go/x/xcom" +) + +//给没有领取委托奖励的账户平账 , https://github.com/PlatONnetwork/PlatON-Go/issues/1583 +func NewFixIssue1583Plugin() *FixIssue1583Plugin { + fix := new(FixIssue1583Plugin) + return fix +} + +type FixIssue1583Plugin struct{} + +func (a *FixIssue1583Plugin) fix(blockHash common.Hash, chainID *big.Int, state xcom.StateDB) error { + if chainID.Cmp(params.AlayaChainConfig.ChainID) != 0 { + return nil + } + accounts, err := newIssue1583Accounts() + if err != nil { + return err + } + for _, account := range accounts { + receiveReward := account.RewardPer.CalDelegateReward(account.delegationAmount) + if err := rm.ReturnDelegateReward(account.addr, receiveReward, state); err != nil { + log.Error("fix issue 1583,return delegate reward fail", "account", account.addr, "err", err) + return common.InternalError + } + } + return nil +} + +type issue1583Accounts struct { + addr common.Address + delegationAmount *big.Int + RewardPer reward.DelegateRewardPer +} + +func newIssue1583Accounts() ([]issue1583Accounts, error) { + type delegationInfo struct { + account string + delegationAmount string + } + + //node f2ec2830850 in Epoch216 + node1DelegationInfo := []delegationInfo{ + {"atp12trrqnpqkj2kn03cwz5ae4v7lfshvqetqrkeez", "1000000000000000000"}, + {"atp143ml5dd3qz3wykmg4p3vnp9eqlugd9sxmgpsux", "2000000000000000000"}, + {"atp1687slxxcghuhxgv3uy6v2epftn8nhn9jss2sd6", "9361750080000000000"}, + {"atp1dtmhmexryrg7h8tzsufrg4d9y48sne7rr5ezsj", "1150000000000000000"}, + {"atp1y4arxmjpy5grkp9attefax07z56wcuq2n5937u", "2806452320000000000"}, + {"atp1z3w63q0q6rnrqw55s4hhu7ewfep0vcqaxt508d", "1612074080000000000"}, + } + node1DelegationAmount, _ := new(big.Int).SetString("3185100027705555555556", 10) + node1DelegationReward, _ := new(big.Int).SetString("8599922061705855512", 10) + node1RewardPer := reward.DelegateRewardPer{ + Delegate: node1DelegationAmount, + Reward: node1DelegationReward, + } + + accounts := make([]issue1583Accounts, 0) + for _, c := range node1DelegationInfo { + addr, err := common.Bech32ToAddress(c.account) + if err != nil { + return nil, err + } + amount, _ := new(big.Int).SetString(c.delegationAmount, 10) + accounts = append(accounts, issue1583Accounts{ + addr: addr, + delegationAmount: amount, + RewardPer: node1RewardPer, + }) + } + + //fff1010bbf176 in epoch475 + node2DelegationInfos := []delegationInfo{ + {"atp1rek8y8nz07tdp4v469xmuyymar8qe0pnejknyw", "18729736290000000000"}, + {"atp1szy8d7094kl0q82la9l2pfz3hjy99zh730flw4", "89940584120000000000"}, + {"atp15wekgs8q07rs24dmnwmdgd0qhqwvqlus6dh5g5", "62385695880000000000"}, + {"atp1cmfc2nea3am2znutaunaze2q8t6ttyrcu7mjqh", "16252405540000000000"}, + } + + node2DelegationAmount, _ := new(big.Int).SetString("10986475785670000000000", 10) + node2DelegationReward, _ := new(big.Int).SetString("8790854215894931178", 10) + node2RewardPer := reward.DelegateRewardPer{ + Delegate: node2DelegationAmount, + Reward: node2DelegationReward, + } + + for _, c := range node2DelegationInfos { + addr, err := common.Bech32ToAddress(c.account) + if err != nil { + return nil, err + } + amount, _ := new(big.Int).SetString(c.delegationAmount, 10) + accounts = append(accounts, issue1583Accounts{ + addr: addr, + delegationAmount: amount, + RewardPer: node2RewardPer, + }) + } + + return accounts, nil +} diff --git a/x/plugin/issue1625_accounts.go b/x/plugin/issue1625_accounts.go index 4a8025c534..f7d2fadf17 100644 --- a/x/plugin/issue1625_accounts.go +++ b/x/plugin/issue1625_accounts.go @@ -1,3 +1,19 @@ +// Copyright 2021 The Alaya Network Authors +// This file is part of the Alaya-Go library. +// +// The Alaya-Go 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 Alaya-Go 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 Alaya-Go library. If not, see . + package plugin import ( diff --git a/x/plugin/issue1625_patch.go b/x/plugin/issue1625_patch.go index 088fa71bdc..a9c9f3c2d6 100644 --- a/x/plugin/issue1625_patch.go +++ b/x/plugin/issue1625_patch.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package plugin import ( @@ -74,7 +75,7 @@ func (a *FixIssue1625Plugin) fix(blockHash common.Hash, head *types.Header, stat return fmt.Errorf("the account restrictInfo seems not right") } - wrongStakingAmount := new(big.Int).Sub(restrictInfo.StakingAmount, actualRestrictingAmount) + wrongStakingAmount := new(big.Int).Sub(restrictInfo.AdvanceAmount, actualRestrictingAmount) if wrongStakingAmount.Cmp(common.Big0) > 0 { //If the user uses the wrong amount,Roll back the unused part first //优先回滚没有使用的那部分锁仓余额 @@ -98,7 +99,7 @@ func (a *FixIssue1625Plugin) fix(blockHash common.Hash, head *types.Header, stat } else { //当用户没有使用因为漏洞产生的钱,直接减去漏洞的钱就是正确的余额 restrictInfo.CachePlanAmount.Sub(restrictInfo.CachePlanAmount, issue1625Account.amount) - if restrictInfo.StakingAmount.Cmp(common.Big0) == 0 && + if restrictInfo.AdvanceAmount.Cmp(common.Big0) == 0 && len(restrictInfo.ReleaseList) == 0 && restrictInfo.CachePlanAmount.Cmp(common.Big0) == 0 { state.SetState(vm.RestrictingContractAddr, restrictingKey, []byte{}) log.Debug("fix issue 1625 finished,set info empty", "account", issue1625Account.addr, "fix amount", issue1625Account.amount) diff --git a/x/plugin/issue1625_patch_test.go b/x/plugin/issue1625_patch_test.go index 1623035d61..f6cc17dc75 100644 --- a/x/plugin/issue1625_patch_test.go +++ b/x/plugin/issue1625_patch_test.go @@ -1,3 +1,19 @@ +// Copyright 2021 The Alaya Network Authors +// This file is part of the Alaya-Go library. +// +// The Alaya-Go 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 Alaya-Go 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 Alaya-Go library. If not, see . + package plugin import ( diff --git a/x/plugin/issue1654_patch.go b/x/plugin/issue1654_patch.go new file mode 100644 index 0000000000..fdb0f6da87 --- /dev/null +++ b/x/plugin/issue1654_patch.go @@ -0,0 +1,131 @@ +// Copyright 2021 The Alaya Network Authors +// This file is part of the Alaya-Go library. +// +// The Alaya-Go 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 Alaya-Go 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 Alaya-Go library. If not, see . + +package plugin + +import ( + "math/big" + + "github.com/AlayaNetwork/Alaya-Go/x/xcom" + + "github.com/AlayaNetwork/Alaya-Go/log" + + "github.com/AlayaNetwork/Alaya-Go/x/xutil" + + "github.com/AlayaNetwork/Alaya-Go/p2p/discover" + + "github.com/AlayaNetwork/Alaya-Go/params" + + "github.com/AlayaNetwork/Alaya-Go/common" + "github.com/AlayaNetwork/Alaya-Go/core/snapshotdb" +) + +//this is use fix validators staking shares error, https://github.com/PlatONnetwork/PlatON-Go/issues/1654 +func NewFixIssue1654Plugin(sdb snapshotdb.DB) *FixIssue1654Plugin { + fix := new(FixIssue1654Plugin) + fix.sdb = sdb + return fix +} + +type FixIssue1654Plugin struct { + sdb snapshotdb.DB +} + +func (a *FixIssue1654Plugin) fix(blockHash common.Hash, chainID *big.Int, state xcom.StateDB) error { + if chainID.Cmp(params.AlayaChainConfig.ChainID) != 0 { + return nil + } + candidates, err := NewIssue1654Candidates() + if err != nil { + return err + } + for _, candidate := range candidates { + canAddr, err := xutil.NodeId2Addr(candidate.nodeID) + if nil != err { + return err + } + can, err := stk.GetCandidateInfo(blockHash, canAddr) + if snapshotdb.NonDbNotFoundErr(err) { + return err + } + if can.IsNotEmpty() && can.StakingBlockNum == candidate.stakingNum { + if can.Status.IsValid() { + if err := stk.db.DelCanPowerStore(blockHash, can); nil != err { + return err + } + can.SubShares(candidate.shouldSub) + if err := stk.db.SetCanPowerStore(blockHash, canAddr, can); nil != err { + return err + } + if err := stk.db.SetCanMutableStore(blockHash, canAddr, can.CandidateMutable); nil != err { + return err + } + log.Debug("fix issue1654,can is valid,update the can power", "nodeID", candidate.nodeID, "stakingNum", candidate.stakingNum, "sub", candidate.shouldSub, "newShare", can.Shares) + } else { + if can.Shares != nil { + if can.Shares.Cmp(candidate.shouldSub)>=0{ + can.SubShares(candidate.shouldSub) + if err := stk.db.SetCanMutableStore(blockHash, canAddr, can.CandidateMutable); nil != err { + return err + } + log.Debug("fix issue1654,can is invalid", "nodeID", candidate.nodeID, "stakingNum", candidate.stakingNum, "sub", candidate.shouldSub, "newShare", can.Shares) + } + } + } + } + } + return nil +} + +type issue1654Candidate struct { + nodeID discover.NodeID + stakingNum uint64 + shouldSub *big.Int +} + +func NewIssue1654Candidates() ([]issue1654Candidate, error) { + type candidate struct { + Node string + Num int + Amount string + } + + candidates := []candidate{ + {"89ca7ccb7fab8e4c8b1b24c747670757b9ef1b3b7631f64e6ea6b469c5936c501fcdcfa7fef2a77521072162c1fc0f8a1663899d31ebb1bc7d00678634ef746c", 522944, "25839533916550000000000"}, + {"ab74f5500dd35497ce09b2dc92a3da26ea371dd9f6d438559b6e19c8f1622ee630951b510cb370aca8267f9bb9a9108bc532ec48dd077474cb79a48122f2ab03", 507203, "30031800000000000000000"}, + {"a2340b4acd4f7b743d7e8785e8ff297490b0e333f25cfe31d17df006f7e554553c6dc502f7c9f7b8798ab3ccf74624065a6cc20603842b1015793c0b37de9b15", 2944652, "22640000000000000000000"}, + {"fff1010bbf1762d13bf13828142c612a7d287f0f1367f8104a78f001145fd788fb44b87e9eac404bc2e880602450405850ff286658781dce130aee981394551d", 902037, "21794743754935111385799"}, + {"1fd9fd7d9c31dad117384c7cc2f223a9e76f7aa81e30f38f030f24212be3fa20ca1f067d878a8ae97deb89b81efbd0542b3880cbd428b4ffae494fcd2c31834b", 518839, "15890357356590015813760"}, + {"19b8fb478a8502a25e461270122ece3135b15dc0de118264495bae30d39af81fd9134ed95364e6a39c3eebfba57fbffa7961a5158d3dac0f0da0313dac7af024", 514281, "7017624238740000000000"}, + {"8bc8734315acf2af4c92a458f077f1f8c96f0530fb43510c11361f1d6469631423206ef76cd879ade849ee15fbcaeb042e3721168614b4fad4eecd60a6aa3e94", 618133, "11339285782500000000000"}, + {"f1efed4e853d00ff3f1be65fd497bc8f0a3d5f66b285069c9190653567e1838ab635b88940d3ce786747af549a1a5bf9b7173e9dc3a3aea9f10363613581a9e0", 509125, "12734262030390000000000"}, + {"1dbe057f33d9748e1d396d624f4c2554f67742f18247e6be6c615c56c70a6e18a6604dd887fd1e9ffdf9708486fb76b711cb5d8e66ccc69d2cee09428832aa98", 504281, "287542747579596068100"}, + {"e2053e04f95afa5c8378677de62212edb972e21b40421786c53de57141853ce870481a80b68a449903479751da114a30d27a568812e178b919bd1e9b2c82f92e", 508822, "2004160057699128540000"}, + {"94bdbf207f6390354debfc2b3ff30ed101bc52d339e8310b2e2a1dd235cb9d40d27d65013c04030e05bbaceeea635dfdbfbbb47c683d29c6751f2bb3159e6abd", 557309, "900000000000000000000"}, + {"ed552a64f708696ac53962b88e927181688c8bc260787c82e1c9c21a62da4ce59c31fc594e48249e89392ce2e6e2a0320d6688b38ad7884ff6fe664faf4b12d9", 2405590, "5823052137310000000000"}, + } + + nodes := make([]issue1654Candidate, 0) + for _, c := range candidates { + amount, _ := new(big.Int).SetString(c.Amount, 10) + nodes = append(nodes, issue1654Candidate{ + nodeID: discover.MustHexID(c.Node), + stakingNum: uint64(c.Num), + shouldSub: amount, + }) + } + return nodes, nil +} diff --git a/x/plugin/platon_plugin_test.go b/x/plugin/platon_plugin_test.go index ab0f8659f9..b28a8ed11e 100644 --- a/x/plugin/platon_plugin_test.go +++ b/x/plugin/platon_plugin_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package plugin import ( @@ -691,7 +692,7 @@ func buildDbRestrictingPlan(account common.Address, t *testing.T, stateDB xcom.S // build restricting user info var user restricting.RestrictingInfo user.CachePlanAmount = big.NewInt(int64(5e18)) - user.StakingAmount = big.NewInt(0) + user.AdvanceAmount = big.NewInt(0) user.NeedRelease = big.NewInt(0) user.ReleaseList = list diff --git a/x/plugin/restricting_plugin.go b/x/plugin/restricting_plugin.go index 67322ac141..50d7f4a701 100644 --- a/x/plugin/restricting_plugin.go +++ b/x/plugin/restricting_plugin.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package plugin import ( @@ -219,20 +220,21 @@ func (rp *RestrictingPlugin) AddRestrictingRecord(from, account common.Address, return err } // pre-check - { + { + //为了兼容历史数据,所以这里保留 if totalAmount.Cmp(big.NewInt(1e18)) < 0 { rp.log.Error("Failed to AddRestrictingRecord: total restricting amount need more than 1 ATP", "from", from, "amount", totalAmount) return restricting.ErrLockedAmountTooLess } - if state.GetBalance(from).Cmp(totalAmount) < 0 { rp.log.Error("Failed to AddRestrictingRecord: balance of the sender is not enough", "total", totalAmount, "balance", state.GetBalance(from)) return restricting.ErrBalanceNotEnough } } + if txhash == common.ZeroHash { return nil } @@ -252,7 +254,7 @@ func (rp *RestrictingPlugin) AddRestrictingRecord(from, account common.Address, } restrictInfo.CachePlanAmount = totalAmount restrictInfo.NeedRelease = big.NewInt(0) - restrictInfo.StakingAmount = big.NewInt(0) + restrictInfo.AdvanceAmount = big.NewInt(0) restrictInfo.ReleaseList = epochArr } else { rp.log.Trace("restricting record exist", "account", account.String()) @@ -299,26 +301,26 @@ func (rp *RestrictingPlugin) AddRestrictingRecord(from, account common.Address, return nil } -// PledgeLockFunds transfer the money from the restricting contract account to the staking contract account -func (rp *RestrictingPlugin) PledgeLockFunds(account common.Address, amount *big.Int, state xcom.StateDB) error { +// AdvanceLockedFunds transfer the money from the restricting contract account to the staking contract account +func (rp *RestrictingPlugin) AdvanceLockedFunds(account common.Address, amount *big.Int, state xcom.StateDB) error { restrictingKey, restrictInfo, err := rp.mustGetRestrictingInfoByDecode(state, account) if err != nil { return err } - rp.log.Debug("Call PledgeLockFunds begin", "account", account, "amount", amount, "old info", restrictInfo) + rp.log.Debug("Call AdvanceLockedFunds begin", "account", account, "amount", amount, "old info", restrictInfo) if amount.Cmp(common.Big0) < 0 { - return restricting.ErrPledgeLockFundsAmountLessThanZero + return restricting.ErrAdvanceLockedFundsAmountLessThanZero } else if amount.Cmp(common.Big0) == 0 { return nil } if gov.Gte0150VersionState(state) { - canStaking := new(big.Int).Sub(restrictInfo.CachePlanAmount, restrictInfo.StakingAmount) + canStaking := new(big.Int).Sub(restrictInfo.CachePlanAmount, restrictInfo.AdvanceAmount) if canStaking.Cmp(amount) < 0 { rp.log.Warn("Balance of restricting account not enough", "totalAmount", - restrictInfo.CachePlanAmount, "stankingAmount", restrictInfo.StakingAmount, "funds", amount) + restrictInfo.CachePlanAmount, "stakingAmount", restrictInfo.AdvanceAmount, "funds", amount) return restricting.ErrRestrictBalanceNotEnough } @@ -331,46 +333,46 @@ func (rp *RestrictingPlugin) PledgeLockFunds(account common.Address, amount *big // handle the error restricting info, the not release restricting amount should not less than CachePlanAmount if leftAmount.Cmp(restrictInfo.CachePlanAmount) < 0 { // cal the account's amount of can use staking ,use the not release restricting amount instead of the error restricting CachePlanAmount to cal - canStaking := new(big.Int).Sub(leftAmount, restrictInfo.StakingAmount) + canStaking := new(big.Int).Sub(leftAmount, restrictInfo.AdvanceAmount) if canStaking.Cmp(amount) < 0 { rp.log.Warn("Balance of restricting account not enough", "totalAmount", - leftAmount, "stankingAmount", restrictInfo.StakingAmount, "funds", amount) + leftAmount, "stakingAmount", restrictInfo.AdvanceAmount, "funds", amount) return restricting.ErrRestrictBalanceNotEnough } } else { - canStaking := new(big.Int).Sub(restrictInfo.CachePlanAmount, restrictInfo.StakingAmount) + canStaking := new(big.Int).Sub(restrictInfo.CachePlanAmount, restrictInfo.AdvanceAmount) if canStaking.Cmp(amount) < 0 { rp.log.Warn("Balance of restricting account not enough", "totalAmount", - restrictInfo.CachePlanAmount, "stankingAmount", restrictInfo.StakingAmount, "funds", amount) + restrictInfo.CachePlanAmount, "stakingAmount", restrictInfo.AdvanceAmount, "funds", amount) return restricting.ErrRestrictBalanceNotEnough } } } else { - canStaking := new(big.Int).Sub(restrictInfo.CachePlanAmount, restrictInfo.StakingAmount) + canStaking := new(big.Int).Sub(restrictInfo.CachePlanAmount, restrictInfo.AdvanceAmount) if canStaking.Cmp(amount) < 0 { rp.log.Warn("Balance of restricting account not enough", "totalAmount", - restrictInfo.CachePlanAmount, "stankingAmount", restrictInfo.StakingAmount, "funds", amount) + restrictInfo.CachePlanAmount, "stakingAmount", restrictInfo.AdvanceAmount, "funds", amount) return restricting.ErrRestrictBalanceNotEnough } } // sub Balance - restrictInfo.StakingAmount.Add(restrictInfo.StakingAmount, amount) + restrictInfo.AdvanceAmount.Add(restrictInfo.AdvanceAmount, amount) // save restricting account info rp.storeRestrictingInfo(state, restrictingKey, restrictInfo) rp.transferAmount(state, vm.RestrictingContractAddr, vm.StakingContractAddr, amount) - rp.log.Debug("Call PledgeLockFunds finished", "RestrictingContractBalance", state.GetBalance(vm.RestrictingContractAddr), "StakingContractBalance", state.GetBalance(vm.StakingContractAddr), "new info", restrictInfo) + rp.log.Debug("Call AdvanceLockedFunds finished", "RestrictingContractBalance", state.GetBalance(vm.RestrictingContractAddr), "StakingContractBalance", state.GetBalance(vm.StakingContractAddr), "new info", restrictInfo) return nil } -// MixPledgeLockFunds transfer the money from the restricting contract account to the staking contract account,use restricting von first,if restricting not en -func (rp *RestrictingPlugin) MixPledgeLockFunds(account common.Address, amount *big.Int, state xcom.StateDB) (*big.Int, *big.Int, error) { +// MixAdvanceLockedFunds transfer the money from the restricting contract account to the staking contract account,use restricting von first,if restricting not en +func (rp *RestrictingPlugin) MixAdvanceLockedFunds(account common.Address, amount *big.Int, state xcom.StateDB) (*big.Int, *big.Int, error) { restrictingKey, restrictInfo, err := rp.mustGetRestrictingInfoByDecode(state, account) if err != nil { @@ -387,15 +389,15 @@ func (rp *RestrictingPlugin) MixPledgeLockFunds(account common.Address, amount * } } - rp.log.Debug("Call MixPledgeLockFunds begin", "account", account, "amount", amount, "old info", restrictInfo) + rp.log.Debug("Call MixAdvanceLockedFunds begin", "account", account, "amount", amount, "old info", restrictInfo) if amount.Cmp(common.Big0) < 0 { - return nil, nil, restricting.ErrPledgeLockFundsAmountLessThanZero + return nil, nil, restricting.ErrAdvanceLockedFundsAmountLessThanZero } else if amount.Cmp(common.Big0) == 0 { return amount, amount, nil } - canStakingRestricting := new(big.Int).Sub(restrictInfo.CachePlanAmount, restrictInfo.StakingAmount) + canStakingRestricting := new(big.Int).Sub(restrictInfo.CachePlanAmount, restrictInfo.AdvanceAmount) canStakingFree := state.GetBalance(account) @@ -403,7 +405,7 @@ func (rp *RestrictingPlugin) MixPledgeLockFunds(account common.Address, amount * if total.Cmp(amount) < 0 { rp.log.Warn("Balance of restricting and free not enough", "totalAmount", - restrictInfo.CachePlanAmount, "stankingAmount", restrictInfo.StakingAmount, "free", canStakingFree, "funds", amount) + restrictInfo.CachePlanAmount, "stakingAmount", restrictInfo.AdvanceAmount, "free", canStakingFree, "funds", amount) return nil, nil, restricting.ErrRestrictBalanceAndFreeNotEnough } @@ -415,12 +417,12 @@ func (rp *RestrictingPlugin) MixPledgeLockFunds(account common.Address, amount * rp.transferAmount(state, account, vm.StakingContractAddr, forFree) } - restrictInfo.StakingAmount.Add(restrictInfo.StakingAmount, forRestricting) + restrictInfo.AdvanceAmount.Add(restrictInfo.AdvanceAmount, forRestricting) // save restricting account info rp.storeRestrictingInfo(state, restrictingKey, restrictInfo) rp.transferAmount(state, vm.RestrictingContractAddr, vm.StakingContractAddr, forRestricting) - rp.log.Debug("Call mixPledgeLockFunds finished", "RestrictingContractBalance", state.GetBalance(vm.RestrictingContractAddr), "StakingContractBalance", state.GetBalance(vm.StakingContractAddr), "new info", restrictInfo, "for free", forFree, "for restricting", forRestricting) + rp.log.Debug("Call mixAdvanceLockedFunds finished", "RestrictingContractBalance", state.GetBalance(vm.RestrictingContractAddr), "StakingContractBalance", state.GetBalance(vm.StakingContractAddr), "new info", restrictInfo, "for free", forFree, "for restricting", forRestricting) return forRestricting, forFree, nil } @@ -438,7 +440,7 @@ func (rp *RestrictingPlugin) ReturnLockFunds(account common.Address, amount *big } rp.log.Debug("Call ReturnLockFunds begin", "account", account, "amount", amount, "info", restrictInfo) - if restrictInfo.StakingAmount.Cmp(amount) < 0 { + if restrictInfo.AdvanceAmount.Cmp(amount) < 0 { return restricting.ErrStakingAmountInvalid } @@ -462,9 +464,9 @@ func (rp *RestrictingPlugin) ReturnLockFunds(account common.Address, amount *big restrictInfo.NeedRelease = big.NewInt(0) } } - restrictInfo.StakingAmount.Sub(restrictInfo.StakingAmount, amount) + restrictInfo.AdvanceAmount.Sub(restrictInfo.AdvanceAmount, amount) // save restricting account info - if restrictInfo.StakingAmount.Cmp(common.Big0) == 0 && + if restrictInfo.AdvanceAmount.Cmp(common.Big0) == 0 && len(restrictInfo.ReleaseList) == 0 && restrictInfo.CachePlanAmount.Cmp(common.Big0) == 0 { state.SetState(vm.RestrictingContractAddr, restrictingKey, []byte{}) rp.log.Debug("Call ReturnLockFunds finished,set info empty", "RCContractBalance", state.GetBalance(vm.RestrictingContractAddr)) @@ -489,15 +491,15 @@ func (rp *RestrictingPlugin) ReturnWrongLockFunds(account common.Address, amount } rp.log.Debug("Call ReturnWrongLockFunds begin", "account", account, "amount", amount, "info", restrictInfo) - if restrictInfo.StakingAmount.Cmp(amount) < 0 { + if restrictInfo.AdvanceAmount.Cmp(amount) < 0 { return restricting.ErrStakingAmountInvalid } rp.transferAmount(state, vm.StakingContractAddr, vm.RestrictingContractAddr, amount) restrictInfo.CachePlanAmount.Sub(restrictInfo.CachePlanAmount, amount) - restrictInfo.StakingAmount.Sub(restrictInfo.StakingAmount, amount) + restrictInfo.AdvanceAmount.Sub(restrictInfo.AdvanceAmount, amount) // save restricting account info - if restrictInfo.StakingAmount.Cmp(common.Big0) == 0 && + if restrictInfo.AdvanceAmount.Cmp(common.Big0) == 0 && len(restrictInfo.ReleaseList) == 0 && restrictInfo.CachePlanAmount.Cmp(common.Big0) == 0 { state.SetState(vm.RestrictingContractAddr, restrictingKey, []byte{}) rp.log.Debug("Call ReturnWrongLockFunds finished,set info empty", "RCContractBalance", state.GetBalance(vm.RestrictingContractAddr)) @@ -520,19 +522,19 @@ func (rp *RestrictingPlugin) SlashingNotify(account common.Address, amount *big. } else if amount.Cmp(common.Big0) == 0 { return nil } - if restrictInfo.StakingAmount.Cmp(common.Big0) <= 0 { - rp.log.Error("Failed to SlashingNotify", "account", account, "Debt", restrictInfo.StakingAmount, + if restrictInfo.AdvanceAmount.Cmp(common.Big0) <= 0 { + rp.log.Error("Failed to SlashingNotify", "account", account, "Debt", restrictInfo.AdvanceAmount, "slashing", amount, "err", restricting.ErrStakingAmountEmpty.Error()) return restricting.ErrStakingAmountEmpty } - if restrictInfo.StakingAmount.Cmp(amount) < 0 { + if restrictInfo.AdvanceAmount.Cmp(amount) < 0 { return restricting.ErrSlashingTooMuch } - restrictInfo.StakingAmount.Sub(restrictInfo.StakingAmount, amount) + restrictInfo.AdvanceAmount.Sub(restrictInfo.AdvanceAmount, amount) restrictInfo.CachePlanAmount.Sub(restrictInfo.CachePlanAmount, amount) - if restrictInfo.StakingAmount.Cmp(common.Big0) == 0 && + if restrictInfo.AdvanceAmount.Cmp(common.Big0) == 0 && len(restrictInfo.ReleaseList) == 0 && restrictInfo.CachePlanAmount.Cmp(common.Big0) == 0 { state.SetState(vm.RestrictingContractAddr, restrictingKey, []byte{}) // save restricting account info @@ -637,6 +639,7 @@ func (rp *RestrictingPlugin) releaseRestricting(epoch uint64, state xcom.StateDB rp.log.Debug("Call releaseRestricting: begin to release record", "index", index, "account", account, "restrictInfo", restrictInfo, "releaseAmount", releaseAmount) + //if NeedRelease>0,CachePlanAmount = AdvanceAmount if restrictInfo.NeedRelease.Cmp(common.Big0) > 0 { if gov.Gte0140VersionState(state) { restrictInfo.NeedRelease.Add(restrictInfo.NeedRelease, releaseAmount) @@ -649,7 +652,7 @@ func (rp *RestrictingPlugin) releaseRestricting(epoch uint64, state xcom.StateDB } } } else { - canRelease := new(big.Int).Sub(restrictInfo.CachePlanAmount, restrictInfo.StakingAmount) + canRelease := new(big.Int).Sub(restrictInfo.CachePlanAmount, restrictInfo.AdvanceAmount) if canRelease.Cmp(releaseAmount) >= 0 { rp.transferAmount(state, vm.RestrictingContractAddr, account, releaseAmount) restrictInfo.CachePlanAmount.Sub(restrictInfo.CachePlanAmount, releaseAmount) @@ -726,7 +729,7 @@ func (rp *RestrictingPlugin) getRestrictingInfoToReturn(account common.Address, result.Debt = (*hexutil.Big)(info.NeedRelease) result.Entry = plans - result.Pledge = (*hexutil.Big)(info.StakingAmount) + result.Pledge = (*hexutil.Big)(info.AdvanceAmount) rp.log.Debug("Call releaseRestricting: query restricting result", "account", account, "result", result) return &result, nil } diff --git a/x/plugin/restricting_plugin_test.go b/x/plugin/restricting_plugin_test.go index 71af9fed38..aa77c7724d 100644 --- a/x/plugin/restricting_plugin_test.go +++ b/x/plugin/restricting_plugin_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package plugin import ( @@ -153,11 +154,6 @@ func TestRestrictingPlugin_AddRestrictingRecord(t *testing.T) { expect: restricting.ErrBalanceNotEnough, des: "amount not enough", }, - { - input: notEnough, - expect: restricting.ErrLockedAmountTooLess, - des: "amount too small", - }, } for _, value := range x { if err := plugin.AddRestrictingRecord(sender, addrArr[0], 20, common.ZeroHash, value.input, mockDB, RestrictingTxHash); err != value.expect { @@ -211,12 +207,12 @@ func TestRestrictingPlugin_AddRestrictingRecord(t *testing.T) { plugin.storeAccount2ReleaseAccount(mockDB, 2, 2, account2) var info, info2 restricting.RestrictingInfo info.NeedRelease = big.NewInt(0) - info.StakingAmount = big.NewInt(1e18) + info.AdvanceAmount = big.NewInt(1e18) info.CachePlanAmount = big.NewInt(1e18 + 2e18) info.ReleaseList = []uint64{1, 2} plugin.storeRestrictingInfo(mockDB, restricting.GetRestrictingKey(to), info) info2.NeedRelease = big.NewInt(0) - info2.StakingAmount = big.NewInt(1e18) + info2.AdvanceAmount = big.NewInt(1e18) info2.CachePlanAmount = big.NewInt(1e18) plugin.storeRestrictingInfo(mockDB, restricting.GetRestrictingKey(account2), info2) mockDB.AddBalance(vm.RestrictingContractAddr, big.NewInt(2e18)) @@ -246,7 +242,7 @@ func TestRestrictingPlugin_AddRestrictingRecord(t *testing.T) { t.Error() } assert.Equal(t, big.NewInt(3e18+2e17+2e18), info2.CachePlanAmount) - assert.Equal(t, big.NewInt(1e18), info2.StakingAmount) + assert.Equal(t, big.NewInt(1e18), info2.AdvanceAmount) assert.Equal(t, big.NewInt(0), info2.NeedRelease) assert.Equal(t, 3, len(info2.ReleaseList)) @@ -272,7 +268,7 @@ func NewTestRestrictingPlugin() *TestRestrictingPlugin { return tp } -//the plan is PledgeLockFunds,then release, then ReturnLockFunds,the info will delete +//the plan is AdvanceLockedFunds,then release, then ReturnLockFunds,the info will delete func TestRestrictingPlugin_Compose3(t *testing.T) { plugin := NewTestRestrictingPlugin() plans := make([]restricting.RestrictingPlan, 0) @@ -280,7 +276,7 @@ func TestRestrictingPlugin_Compose3(t *testing.T) { if err := plugin.AddRestrictingRecord(plugin.from, plugin.to, xutil.CalcBlocksEachEpoch()-10, common.ZeroHash, plans, plugin.mockDB, RestrictingTxHash); err != nil { t.Error(err) } - if err := plugin.PledgeLockFunds(plugin.to, big.NewInt(1e18), plugin.mockDB); err != nil { + if err := plugin.AdvanceLockedFunds(plugin.to, big.NewInt(1e18), plugin.mockDB); err != nil { t.Error() } if err := plugin.releaseRestricting(1, plugin.mockDB); err != nil { @@ -312,7 +308,7 @@ func TestRestrictingPlugin_Compose2(t *testing.T) { if err := plugin.AddRestrictingRecord(from, to, xutil.CalcBlocksEachEpoch()-10, common.ZeroHash, plans, mockDB, RestrictingTxHash); err != nil { t.Error(err) } - if err := plugin.PledgeLockFunds(to, big.NewInt(2e18), mockDB); err != nil { + if err := plugin.AdvanceLockedFunds(to, big.NewInt(2e18), mockDB); err != nil { t.Error(err) } if err := plugin.releaseRestricting(1, mockDB); err != nil { @@ -330,7 +326,7 @@ func TestRestrictingPlugin_Compose2(t *testing.T) { } assert.Equal(t, info.CachePlanAmount, CachePlanAmount) assert.Equal(t, info.ReleaseList, ReleaseList) - assert.Equal(t, info.StakingAmount, StakingAmount) + assert.Equal(t, info.AdvanceAmount, StakingAmount) assert.Equal(t, info.NeedRelease, NeedRelease) } @@ -355,7 +351,7 @@ func TestRestrictingPlugin_Compose(t *testing.T) { } assert.Equal(t, info.CachePlanAmount, CachePlanAmount) assert.Equal(t, info.ReleaseList, ReleaseList) - assert.Equal(t, info.StakingAmount, StakingAmount) + assert.Equal(t, info.AdvanceAmount, StakingAmount) assert.Equal(t, info.NeedRelease, NeedRelease) } mockDB.AddBalance(from, big.NewInt(9e18)) @@ -371,7 +367,7 @@ func TestRestrictingPlugin_Compose(t *testing.T) { assert.Equal(t, mockDB.GetBalance(vm.RestrictingContractAddr), big.NewInt(2e18)) infoAssertF(big.NewInt(2e18), []uint64{1}, big.NewInt(0), big.NewInt(0)) - if err := plugin.PledgeLockFunds(to, big.NewInt(2e18), mockDB); err != nil { + if err := plugin.AdvanceLockedFunds(to, big.NewInt(2e18), mockDB); err != nil { t.Error(err) } assert.Equal(t, mockDB.GetBalance(to), big.NewInt(0)) @@ -474,7 +470,7 @@ func TestRestrictingInstance(t *testing.T) { t.Error(err) } // SetLatestEpoch(mockDB, 1) - if err := plugin.PledgeLockFunds(to, big.NewInt(5e18), mockDB); err != nil { + if err := plugin.AdvanceLockedFunds(to, big.NewInt(5e18), mockDB); err != nil { t.Error(err) } if err := plugin.releaseRestricting(2, mockDB); err != nil { @@ -506,7 +502,7 @@ func TestRestrictingInstance(t *testing.T) { assert.Equal(t, true, mockDB.GetBalance(vm.StakingContractAddr).Cmp(big.NewInt(0)) == 0) } -func TestNewRestrictingPlugin_MixPledgeLockFunds(t *testing.T) { +func TestNewRestrictingPlugin_MixAdvanceLockedFunds(t *testing.T) { sdb := snapshotdb.Instance() defer sdb.Clear() key := gov.KeyParamValue(gov.ModuleRestricting, gov.KeyRestrictingMinimumAmount) @@ -531,7 +527,7 @@ func TestNewRestrictingPlugin_MixPledgeLockFunds(t *testing.T) { } mockDB.AddBalance(to, big.NewInt(2e18)) - res, free, err := plugin.MixPledgeLockFunds(to, new(big.Int).Mul(big.NewInt(1e18), big.NewInt(10)), mockDB) + res, free, err := plugin.MixAdvanceLockedFunds(to, new(big.Int).Mul(big.NewInt(1e18), big.NewInt(10)), mockDB) if err != nil { t.Error(err) } @@ -547,7 +543,7 @@ func TestNewRestrictingPlugin_MixPledgeLockFunds(t *testing.T) { t.Errorf("to balance von cost wrong") } - if _, _, err := plugin.MixPledgeLockFunds(to, new(big.Int).Mul(big.NewInt(1e18), big.NewInt(10)), mockDB); err == nil { + if _, _, err := plugin.MixAdvanceLockedFunds(to, new(big.Int).Mul(big.NewInt(1e18), big.NewInt(10)), mockDB); err == nil { t.Error("should not success") } @@ -573,7 +569,7 @@ func TestRestrictingInstanceWithSlashing(t *testing.T) { } // SetLatestEpoch(mockDB, 1) - if err := plugin.PledgeLockFunds(to, big.NewInt(5e18), mockDB); err != nil { + if err := plugin.AdvanceLockedFunds(to, big.NewInt(5e18), mockDB); err != nil { t.Error(err) } @@ -682,7 +678,7 @@ func TestRestrictingReturnLockFunds(t *testing.T) { } if err := chain.AddBlockWithSnapDB(true, nil, func(hash common.Hash, header *types.Header, sdb snapshotdb.DB) error { - if err := plugin.PledgeLockFunds(to, big.NewInt(6e18), chain.StateDB); err != nil { + if err := plugin.AdvanceLockedFunds(to, big.NewInt(6e18), chain.StateDB); err != nil { return err } return nil @@ -727,12 +723,12 @@ func TestRestrictingReturnLockFunds(t *testing.T) { if info.CachePlanAmount.Cmp(big.NewInt(3e18)) != 0 { t.Error("CachePlanAmount cal error") } - if info.StakingAmount.Cmp(common.Big0) != 0 { - t.Error("StakingAmount cal error") + if info.AdvanceAmount.Cmp(common.Big0) != 0 { + t.Error("AdvanceAmount cal error") } } -func TestRestrictingForkPledgeLockFunds(t *testing.T) { +func TestRestrictingForkAdvanceLockedFunds(t *testing.T) { chain := mock.NewChain() defer chain.SnapDB.Clear() @@ -771,7 +767,7 @@ func TestRestrictingForkPledgeLockFunds(t *testing.T) { } if err := chain.AddBlockWithSnapDB(true, nil, func(hash common.Hash, header *types.Header, sdb snapshotdb.DB) error { - if err := plugin.PledgeLockFunds(to, big.NewInt(6e18), chain.StateDB); err != nil { + if err := plugin.AdvanceLockedFunds(to, big.NewInt(6e18), chain.StateDB); err != nil { return err } return nil @@ -812,7 +808,7 @@ func TestRestrictingForkPledgeLockFunds(t *testing.T) { if err := gov.AddActiveVersion(uint32(0<<16|14<<8|0), header.Number.Uint64(), chain.StateDB); err != nil { t.Error(err) } - if err := plugin.PledgeLockFunds(to, big.NewInt(9e18), chain.StateDB); err != nil { + if err := plugin.AdvanceLockedFunds(to, big.NewInt(9e18), chain.StateDB); err != nil { return err } return nil @@ -858,7 +854,7 @@ func TestRestrictingSlashingRelease(t *testing.T) { } if err := chain.AddBlockWithSnapDB(true, nil, func(hash common.Hash, header *types.Header, sdb snapshotdb.DB) error { - if err := plugin.PledgeLockFunds(to, big.NewInt(6e18), chain.StateDB); err != nil { + if err := plugin.AdvanceLockedFunds(to, big.NewInt(6e18), chain.StateDB); err != nil { return err } return nil diff --git a/x/plugin/reward_plugin.go b/x/plugin/reward_plugin.go index 9c21c8b5df..271abb2d9f 100644 --- a/x/plugin/reward_plugin.go +++ b/x/plugin/reward_plugin.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,10 +14,12 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package plugin import ( "encoding/json" + "errors" "fmt" "github.com/AlayaNetwork/Alaya-Go/x/gov" "math" @@ -428,11 +430,9 @@ func (rmp *RewardMgrPlugin) getBlockMinderAddress(blockHash common.Hash, head *t if blockHash == common.ZeroHash { return rmp.nodeID, rmp.nodeADD, nil } - sign := head.Extra[32:97] - sealhash := head.SealHash().Bytes() - pk, err := crypto.SigToPub(sealhash, sign) - if err != nil { - return discover.ZeroNodeID, common.ZeroNodeAddr, err + pk := head.CachePublicKey() + if pk == nil { + return discover.ZeroNodeID, common.ZeroNodeAddr, errors.New("failed to get the public key of the block producer") } return discover.PubkeyID(pk), crypto.PubkeyToNodeAddress(*pk), nil } @@ -795,7 +795,7 @@ func (rmp *RewardMgrPlugin) CalcEpochReward(blockHash common.Hash, head *types.H log.Info("Call CalcEpochReward, IncIssuanceNumber stored successfully", "currBlockNumber", head.Number, "currBlockHash", blockHash, "epochBlocks", epochBlocks, "incIssuanceNumber", incIssuanceNumber) } - // Get the total block reward and pledge reward for each settlement cycle + // Get the total block reward and staking reward for each settlement cycle epochTotalNewBlockReward := percentageCalculation(epochTotalReward, xcom.NewBlockRewardRate()) epochTotalStakingReward := new(big.Int).Sub(epochTotalReward, epochTotalNewBlockReward) if err := StorageRemainingReward(blockHash, rmp.db, remainReward); nil != err { diff --git a/x/plugin/reward_plugin_test.go b/x/plugin/reward_plugin_test.go index 85def554c1..f1913eb92a 100644 --- a/x/plugin/reward_plugin_test.go +++ b/x/plugin/reward_plugin_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package plugin import ( diff --git a/x/plugin/slashing_plugin.go b/x/plugin/slashing_plugin.go index 0822d20ec5..5786417d86 100644 --- a/x/plugin/slashing_plugin.go +++ b/x/plugin/slashing_plugin.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package plugin import ( @@ -705,10 +706,9 @@ func parseNodeId(header *types.Header) (discover.NodeID, error) { if xutil.IsWorker(header.Extra) { return discover.PubkeyID(&SlashInstance().privateKey.PublicKey), nil } else { - sign := header.Extra[32:97] - pk, err := crypto.SigToPub(header.SealHash().Bytes(), sign) - if nil != err { - return discover.NodeID{}, err + pk := header.CachePublicKey() + if pk == nil { + return discover.NodeID{}, errors.New("failed to get the public key of the block producer") } return discover.PubkeyID(pk), nil } diff --git a/x/plugin/slashing_plugin_test.go b/x/plugin/slashing_plugin_test.go index 4489f77f26..6506d2d2d3 100644 --- a/x/plugin/slashing_plugin_test.go +++ b/x/plugin/slashing_plugin_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package plugin import ( diff --git a/x/plugin/staking_plugin.go b/x/plugin/staking_plugin.go index 435ab33813..ec9976744c 100644 --- a/x/plugin/staking_plugin.go +++ b/x/plugin/staking_plugin.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -22,6 +22,7 @@ import ( "errors" "fmt" "math/big" + "math/rand" "sort" "strconv" "sync" @@ -298,9 +299,9 @@ func (sk *StakingPlugin) CreateCandidate(state xcom.StateDB, blockHash common.Ha } else if typ == RestrictVon { // from account RestrictingPlan von - err := rt.PledgeLockFunds(can.StakingAddress, amount, state) + err := rt.AdvanceLockedFunds(can.StakingAddress, amount, state) if nil != err { - log.Error("Failed to CreateCandidate on stakingPlugin: call Restricting PledgeLockFunds() is failed", + log.Error("Failed to CreateCandidate on stakingPlugin: call Restricting AdvanceLockedFunds() is failed", "blockNumber", blockNumber.Uint64(), "blockHash", blockHash.Hex(), "nodeId", can.NodeId.String(), "stakeAddr", can.StakingAddress, "stakingVon", amount, "err", err) return err @@ -308,9 +309,9 @@ func (sk *StakingPlugin) CreateCandidate(state xcom.StateDB, blockHash common.Ha can.RestrictingPlanHes = amount } else if typ == RestrictAndFreeVon { // use Restricting and free von if gov.Gte0150VersionState(state) { - restrictingPlanHes, releasedHes, err := rt.MixPledgeLockFunds(can.StakingAddress, amount, state) + restrictingPlanHes, releasedHes, err := rt.MixAdvanceLockedFunds(can.StakingAddress, amount, state) if nil != err { - log.Error("Failed to CreateCandidate on stakingPlugin: call Restricting MixPledgeLockFunds() is failed", + log.Error("Failed to CreateCandidate on stakingPlugin: call Restricting MixAdvanceLockedFunds() is failed", "blockNumber", blockNumber.Uint64(), "blockHash", blockHash.Hex(), "nodeId", can.NodeId.String(), "stakeAddr", can.StakingAddress, "stakingVon", amount, "err", err) return err @@ -454,9 +455,9 @@ func (sk *StakingPlugin) IncreaseStaking(state xcom.StateDB, blockHash common.Ha } else if typ == RestrictVon { - err := rt.PledgeLockFunds(can.StakingAddress, amount, state) + err := rt.AdvanceLockedFunds(can.StakingAddress, amount, state) if nil != err { - log.Error("Failed to IncreaseStaking on stakingPlugin: call Restricting PledgeLockFunds() is failed", + log.Error("Failed to IncreaseStaking on stakingPlugin: call Restricting AdvanceLockedFunds() is failed", "blockNumber", blockNumber.Uint64(), "blockHash", blockHash.Hex(), "nodeId", can.NodeId.String(), "account", can.StakingAddress, "amount", amount, "err", err) return err @@ -656,11 +657,11 @@ func (sk *StakingPlugin) HandleUnCandidateItem(state xcom.StateDB, blockNumber u // The state of the node needs to be restored if stakeItem.Recovery { - // If the pledge has been revoked, there is no need to restore the state + // If the staking has been revoked, there is no need to restore the state if gov.Gte0150VersionState(state) && can.IsWithdrew() { } else { // If the node is reported double-signed during the lock-up period, - // Then you need to enter the double-signed lock-up period after the lock-up period expires and release the pledge after the expiration + // Then you need to enter the double-signed lock-up period after the lock-up period expires and release the staking after the expiration // Otherwise, the state of the node is restored to the normal staking state if can.IsDuplicateSign() { @@ -891,9 +892,9 @@ func (sk *StakingPlugin) Delegate(state xcom.StateDB, blockHash common.Hash, blo del.ReleasedHes = new(big.Int).Add(del.ReleasedHes, amount) } else if typ == RestrictVon { // from account RestrictingPlan von - err := rt.PledgeLockFunds(delAddr, amount, state) + err := rt.AdvanceLockedFunds(delAddr, amount, state) if nil != err { - log.Error("Failed to Delegate on stakingPlugin: call Restricting PledgeLockFunds() is failed", + log.Error("Failed to Delegate on stakingPlugin: call Restricting AdvanceLockedFunds() is failed", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "epoch", epoch, "delAddr", delAddr.String(), "nodeId", can.NodeId.String(), "StakingNum", can.StakingBlockNum, "amount", amount, "err", err) @@ -947,12 +948,12 @@ func (sk *StakingPlugin) Delegate(state xcom.StateDB, blockHash common.Hash, blo return nil } -func (sk *StakingPlugin) WithdrewDelegate(state xcom.StateDB, blockHash common.Hash, blockNumber, amount *big.Int, +func (sk *StakingPlugin) WithdrewDelegation(state xcom.StateDB, blockHash common.Hash, blockNumber, amount *big.Int, delAddr common.Address, nodeId discover.NodeID, stakingBlockNum uint64, del *staking.Delegation, delegateRewardPerList []*reward.DelegateRewardPer) (*big.Int, error) { issueIncome := new(big.Int) canAddr, err := xutil.NodeId2Addr(nodeId) if nil != err { - log.Error("Failed to WithdrewDelegate on stakingPlugin: nodeId parse addr failed", + log.Error("Failed to WithdrewDelegation on stakingPlugin: nodeId parse addr failed", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "delAddr", delAddr, "nodeId", nodeId.String(), "stakingBlockNum", stakingBlockNum, "err", err) return nil, err @@ -960,7 +961,7 @@ func (sk *StakingPlugin) WithdrewDelegate(state xcom.StateDB, blockHash common.H can, err := sk.db.GetCandidateStore(blockHash, canAddr) if snapshotdb.NonDbNotFoundErr(err) { - log.Error("Failed to WithdrewDelegate on stakingPlugin: Query candidate info failed", + log.Error("Failed to WithdrewDelegation on stakingPlugin: Query candidate info failed", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "delAddr", delAddr, "nodeId", nodeId.String(), "stakingBlockNum", stakingBlockNum, "err", err) return nil, err @@ -969,7 +970,7 @@ func (sk *StakingPlugin) WithdrewDelegate(state xcom.StateDB, blockHash common.H total := calcDelegateTotalAmount(del) // First need to deduct the von that is being refunded if total.Cmp(amount) < 0 { - log.Error("Failed to WithdrewDelegate on stakingPlugin: the amount of valid delegate is not enough", + log.Error("Failed to WithdrewDelegation on stakingPlugin: the amount of valid delegate is not enough", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "delAddr", delAddr, "nodeId", nodeId.String(), "stakingBlockNum", stakingBlockNum, "delegate amount", total, "withdrew amount", amount) @@ -996,13 +997,13 @@ func (sk *StakingPlugin) WithdrewDelegate(state xcom.StateDB, blockHash common.H switch { // Illegal parameter case can.IsNotEmpty() && stakingBlockNum > can.StakingBlockNum: - log.Error("Failed to WithdrewDelegate on stakingPlugin: the stakeBlockNum invalid", + log.Error("Failed to WithdrewDelegation on stakingPlugin: the stakeBlockNum invalid", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "delAddr", delAddr, "nodeId", nodeId.String(), "stakingBlockNum", stakingBlockNum, "fn.stakeBlockNum", stakingBlockNum, "can.stakeBlockNum", can.StakingBlockNum) return nil, staking.ErrBlockNumberDisordered default: - log.Debug("Call WithdrewDelegate", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), + log.Debug("Call WithdrewDelegation", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "delAddr", delAddr.String(), "nodeId", nodeId.String(), "StakingNum", stakingBlockNum, "total", total, "amount", amount, "realSub", realSub) @@ -1010,7 +1011,7 @@ func (sk *StakingPlugin) WithdrewDelegate(state xcom.StateDB, blockHash common.H if refundAmount.Cmp(common.Big0) > 0 { rm, rbalance, lbalance, err := rufundDelegateFn(refundAmount, del.ReleasedHes, del.RestrictingPlanHes, delAddr, state) if nil != err { - log.Error("Failed to WithdrewDelegate, refund the hesitate balance is failed", "blockNumber", blockNumber, + log.Error("Failed to WithdrewDelegation, refund the hesitate balance is failed", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "delAddr", delAddr.String(), "nodeId", nodeId.String(), "StakingNum", stakingBlockNum, "refund balance", refundAmount, "releaseHes", del.ReleasedHes, "restrictingPlanHes", del.RestrictingPlanHes, "err", err) return nil, err @@ -1025,7 +1026,7 @@ func (sk *StakingPlugin) WithdrewDelegate(state xcom.StateDB, blockHash common.H if refundAmount.Cmp(common.Big0) > 0 { rm, rbalance, lbalance, err := rufundDelegateFn(refundAmount, del.Released, del.RestrictingPlan, delAddr, state) if nil != err { - log.Error("Failed to WithdrewDelegate, refund the no hesitate balance is failed", "blockNumber", blockNumber, + log.Error("Failed to WithdrewDelegation, refund the no hesitate balance is failed", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "delAddr", delAddr.String(), "nodeId", nodeId.String(), "StakingNum", stakingBlockNum, "refund balance", refundAmount, "release", del.Released, "restrictingPlan", del.RestrictingPlan, "err", err) return nil, err @@ -1037,7 +1038,7 @@ func (sk *StakingPlugin) WithdrewDelegate(state xcom.StateDB, blockHash common.H } if refundAmount.Cmp(common.Big0) != 0 { - log.Error("Failed to WithdrewDelegate on stakingPlugin: the withdrew ramain is not zero", + log.Error("Failed to WithdrewDelegation on stakingPlugin: the withdrew ramain is not zero", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "delAddr", delAddr, "nodeId", nodeId.String(), "stakingBlockNum", stakingBlockNum, "del balance", total, "withdrew balance", amount, "realSub amount", realSub, "withdrew remain", refundAmount) @@ -1050,7 +1051,7 @@ func (sk *StakingPlugin) WithdrewDelegate(state xcom.StateDB, blockHash common.H // When the entrusted information is deleted, the entrusted proceeds need to be issued automatically issueIncome = issueIncome.Add(issueIncome, del.CumulativeIncome) if err := rm.ReturnDelegateReward(delAddr, del.CumulativeIncome, state); err != nil { - log.Error("Failed to WithdrewDelegate on stakingPlugin: return delegate reward is failed", + log.Error("Failed to WithdrewDelegation on stakingPlugin: return delegate reward is failed", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "delAddr", delAddr, "nodeId", nodeId.String(), "stakingBlockNum", stakingBlockNum, "err", err) return nil, common.InternalError @@ -1058,14 +1059,14 @@ func (sk *StakingPlugin) WithdrewDelegate(state xcom.StateDB, blockHash common.H log.Debug("Successful ReturnDelegateReward", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "nodeId", nodeId.TerminalString(), "delAddr", delAddr, "cumulativeIncome", issueIncome) if err := sk.db.DelDelegateStore(blockHash, delAddr, nodeId, stakingBlockNum); nil != err { - log.Error("Failed to WithdrewDelegate on stakingPlugin: Delete detegate is failed", + log.Error("Failed to WithdrewDelegation on stakingPlugin: Delete detegate is failed", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "delAddr", delAddr, "nodeId", nodeId.String(), "stakingBlockNum", stakingBlockNum, "err", err) return nil, err } } else { if err := sk.db.SetDelegateStore(blockHash, delAddr, nodeId, stakingBlockNum, del); nil != err { - log.Error("Failed to WithdrewDelegate on stakingPlugin: Store detegate is failed", + log.Error("Failed to WithdrewDelegation on stakingPlugin: Store detegate is failed", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "delAddr", delAddr, "nodeId", nodeId.String(), "stakingBlockNum", stakingBlockNum, "err", err) return nil, err @@ -1076,7 +1077,7 @@ func (sk *StakingPlugin) WithdrewDelegate(state xcom.StateDB, blockHash common.H if can.IsNotEmpty() && stakingBlockNum == can.StakingBlockNum { if can.IsValid() { if err := sk.db.DelCanPowerStore(blockHash, can); nil != err { - log.Error("Failed to WithdrewDelegate on stakingPlugin: Delete candidate old power is failed", "blockNumber", + log.Error("Failed to WithdrewDelegation on stakingPlugin: Delete candidate old power is failed", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "delAddr", delAddr, "nodeId", nodeId.String(), "stakingBlockNum", stakingBlockNum, "err", err) return nil, err @@ -1086,14 +1087,14 @@ func (sk *StakingPlugin) WithdrewDelegate(state xcom.StateDB, blockHash common.H if can.Shares.Cmp(realSub) > 0 { can.SubShares(realSub) } else { - log.Error("Failed to WithdrewDelegate on stakingPlugin: the candidate shares is no enough", "blockNumber", + log.Error("Failed to WithdrewDelegation on stakingPlugin: the candidate shares is no enough", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "delAddr", delAddr, "nodeId", nodeId.String(), "stakingBlockNum", stakingBlockNum, "can shares", can.Shares, "real withdrew delegate amount", realSub) panic("the candidate shares is no enough") } if err := sk.db.SetCanPowerStore(blockHash, canAddr, can); nil != err { - log.Error("Failed to WithdrewDelegate on stakingPlugin: Store candidate old power is failed", "blockNumber", + log.Error("Failed to WithdrewDelegation on stakingPlugin: Store candidate old power is failed", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "delAddr", delAddr, "nodeId", nodeId.String(), "stakingBlockNum", stakingBlockNum, "err", err) return nil, err @@ -1107,7 +1108,7 @@ func (sk *StakingPlugin) WithdrewDelegate(state xcom.StateDB, blockHash common.H } if err := sk.db.SetCanMutableStore(blockHash, canAddr, can.CandidateMutable); nil != err { - log.Error("Failed to WithdrewDelegate on stakingPlugin: Store CandidateMutable info is failed", "blockNumber", + log.Error("Failed to WithdrewDelegation on stakingPlugin: Store CandidateMutable info is failed", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "delAddr", delAddr, "nodeId", nodeId.String(), "stakingBlockNum", stakingBlockNum, "candidateMutable", can.CandidateMutable, "err", err) return nil, err @@ -2335,9 +2336,9 @@ func (sk *StakingPlugin) toSlash(state xcom.StateDB, blockNumber uint64, blockHa } // Only when the staking is released, the staking-related information needs to be emptied. - // When penalizing the low block rate first, and then report double signing, the pledged deposit in the period of hesitation should be returned + // When penalizing the low block rate first, and then report double signing, the staked deposit in the period of hesitation should be returned if needReturnHes { - // Return the pledged deposit during the hesitation period + // Return the staked deposit during the hesitation period if can.ReleasedHes.Cmp(common.Big0) > 0 { state.AddBalance(can.StakingAddress, can.ReleasedHes) state.SubBalance(vm.StakingContractAddr, can.ReleasedHes) @@ -2363,7 +2364,7 @@ func (sk *StakingPlugin) toSlash(state xcom.StateDB, blockNumber uint64, blockHa // Only when the staking is released, the staking-related information needs to be emptied. if needReturnHes { // need to sub account rc - // Only need to be executed if the pledge is released + // Only need to be executed if the staking is released if err := sk.db.SubAccountStakeRc(blockHash, can.StakingAddress); nil != err { log.Error("Failed to SlashCandidates: Sub Account staking Reference Count is failed", "slashType", slashItem.SlashType, "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "nodeId", slashItem.NodeId.String(), "err", err) @@ -2457,7 +2458,7 @@ func (sk *StakingPlugin) removeFromVerifiers(blockNumber uint64, blockHash commo func handleSlashTypeFn(blockNumber uint64, blockHash common.Hash, slashType staking.CandidateStatus, remain *big.Int) (bool, bool, bool, staking.CandidateStatus) { - var needInvalid, needRemove, needReturnHes bool // need invalid candidate status And need remove from verifierList,Refund of pledged deposits during hesitation period + var needInvalid, needRemove, needReturnHes bool // need invalid candidate status And need remove from verifierList,Refund of staked deposits during hesitation period var changeStatus staking.CandidateStatus // need to add this status switch slashType { @@ -2920,6 +2921,24 @@ func (svs sortValidatorQueue) Swap(i, j int) { svs[i], svs[j] = svs[j], svs[i] } +type newSortValidatorQueue []*sortValidator + +func (svs newSortValidatorQueue) Len() int { + return len(svs) +} + +func (svs newSortValidatorQueue) Less(i, j int) bool { + if xutil.CalcVersion(svs[i].version) == xutil.CalcVersion(svs[j].version) { + return svs[i].x > svs[j].x + } else { + return xutil.CalcVersion(svs[i].version) > xutil.CalcVersion(svs[j].version) + } +} + +func (svs newSortValidatorQueue) Swap(i, j int) { + svs[i], svs[j] = svs[j], svs[i] +} + // Elected verifier by vrf random election // validatorList:Waiting for the elected node // nonce:Vrf proof of the current block @@ -2976,14 +2995,24 @@ func probabilityElection(validatorList staking.ValidatorQueue, shiftLen int, cur } var p float64 - if gov.Gte0150Version(currentVersion) { + if gov.Gte0160Version(currentVersion) { + p = xcom.CalcPNew(totalSqrtWeightsFloat) + } else if gov.Gte0150Version(currentVersion) { p = xcom.CalcP(totalWeightsFloat, totalSqrtWeightsFloat) } else { p = float64(xcom.ShiftValidatorNum()) * float64(xcom.MaxConsensusVals()) / totalSqrtWeightsFloat } + shuffleSeed := new(big.Int).SetBytes(preNonces[0]).Int64() log.Debug("Call probabilityElection Basic parameter on Election", "blockNumber", blockNumber, "currentVersion", currentVersion, "validatorListSize", len(validatorList), - "p", p, "totalWeights", totalWeightsFloat, "totalSqrtWeightsFloat", totalSqrtWeightsFloat, "shiftValidatorNum", shiftLen) + "p", p, "totalWeights", totalWeightsFloat, "totalSqrtWeightsFloat", totalSqrtWeightsFloat, "shiftValidatorNum", shiftLen, "shuffleSeed", shuffleSeed) + + if gov.Gte0160Version(currentVersion) { + rand.Seed(shuffleSeed) + rand.Shuffle(len(svList), func(i, j int) { + svList[i], svList[j] = svList[j], svList[i] + }) + } for index, sv := range svList { resultStr := new(big.Int).Xor(new(big.Int).SetBytes(currentNonce), new(big.Int).SetBytes(preNonces[index])).Text(10) @@ -3010,7 +3039,11 @@ func probabilityElection(validatorList staking.ValidatorQueue, shiftLen int, cur log.Debug("Call probabilityElection, sort probability queue", "blockNumber", blockNumber, "currentVersion", currentVersion, "list", svList) - sort.Sort(svList) + if gov.Gte0160Version(currentVersion) { + sort.Sort(newSortValidatorQueue(svList)) + } else { + sort.Sort(svList) + } for index, sv := range svList { if index == shiftLen { break diff --git a/x/plugin/staking_plugin_test.go b/x/plugin/staking_plugin_test.go index 10a499c341..07ac5699ee 100644 --- a/x/plugin/staking_plugin_test.go +++ b/x/plugin/staking_plugin_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -1544,7 +1544,7 @@ func TestStakingPlugin_HandleUnCandidateItem(t *testing.T) { assert.True(t, recoveryCan.IsValid()) // The simulation first punishes the low block rate, and then the double sign punishment. - // After the lock-up period of the low block rate penalty expires, the double-signing pledge freeze + // After the lock-up period of the low block rate penalty expires, the double-signing staking freeze index++ if err := create_staking(state, blockNumber2, blockHash2, index, 0, t); nil != err { t.Fatal(err) @@ -1575,7 +1575,7 @@ func TestStakingPlugin_HandleUnCandidateItem(t *testing.T) { assert.True(t, recoveryCan2.IsInvalidDuplicateSign()) assert.False(t, recoveryCan2.IsInvalidLowRatio()) - // Handle double-signature freeze and release pledge, delete nodes + // Handle double-signature freeze and release staking, delete nodes newBlockNumber.Add(newBlockNumber, new(big.Int).SetUint64(xutil.CalcBlocksEachEpoch()*xcom.UnStakeFreezeDuration())) err = StakingInstance().HandleUnCandidateItem(state, newBlockNumber.Uint64(), blockHash2, xcom.UnStakeFreezeDuration()+epoch) assert.Nil(t, err) @@ -1690,7 +1690,7 @@ func TestStakingPlugin_Delegate(t *testing.T) { } -func TestStakingPlugin_WithdrewDelegate(t *testing.T) { +func TestStakingPlugin_WithdrewDelegation(t *testing.T) { state, genesis, err := newChainState() if nil != err { @@ -1759,17 +1759,17 @@ func TestStakingPlugin_WithdrewDelegate(t *testing.T) { */ amount := common.Big257 delegateTotalHes := can.DelegateTotalHes - _, err = StakingInstance().WithdrewDelegate(state, blockHash2, blockNumber2, amount, addrArr[index+1], + _, err = StakingInstance().WithdrewDelegation(state, blockHash2, blockNumber2, amount, addrArr[index+1], nodeIdArr[index], blockNumber.Uint64(), del, make([]*reward.DelegateRewardPer, 0)) - if !assert.Nil(t, err, fmt.Sprintf("Failed to WithdrewDelegate: %v", err)) { + if !assert.Nil(t, err, fmt.Sprintf("Failed to WithdrewDelegation: %v", err)) { return } if err := sndb.Commit(blockHash2); nil != err { t.Error("Commit 2 err", err) } - t.Log("Finish WithdrewDelegate ~~", del) + t.Log("Finish WithdrewDelegation ~~", del) can, err = getCandidate(blockHash2, index) assert.Nil(t, err, fmt.Sprintf("Failed to getCandidate: %v", err)) @@ -1804,10 +1804,10 @@ func TestStakingPlugin_WithdrewDelegate(t *testing.T) { expectedIssueIncome := delegateRewardPerList[1].CalDelegateReward(del.ReleasedHes) expectedBalance := new(big.Int).Add(state.GetBalance(addrArr[index+1]), expectedIssueIncome) expectedBalance = new(big.Int).Add(expectedBalance, del.ReleasedHes) - issueIncome, err := StakingInstance().WithdrewDelegate(state, blockHash3, curBlockNumber, del.ReleasedHes, addrArr[index+1], + issueIncome, err := StakingInstance().WithdrewDelegation(state, blockHash3, curBlockNumber, del.ReleasedHes, addrArr[index+1], nodeIdArr[index], blockNumber.Uint64(), del, delegateRewardPerList) - if !assert.Nil(t, err, fmt.Sprintf("Failed to WithdrewDelegate: %v", err)) { + if !assert.Nil(t, err, fmt.Sprintf("Failed to WithdrewDelegation: %v", err)) { return } diff --git a/x/restricting/restricting_db_key.go b/x/restricting/restricting_db_key.go index 8193c2b86a..875686ba84 100644 --- a/x/restricting/restricting_db_key.go +++ b/x/restricting/restricting_db_key.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package restricting import ( diff --git a/x/restricting/restricting_err.go b/x/restricting/restricting_err.go index 408d7f99e0..959728c9c5 100644 --- a/x/restricting/restricting_err.go +++ b/x/restricting/restricting_err.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package restricting import ( @@ -27,19 +28,19 @@ const ( ) var ( - ErrParamEpochInvalid = common.NewBizError(304001, "The initial epoch for staking cannot be zero") - ErrCountRestrictPlansInvalid = common.NewBizError(304002, fmt.Sprintf("The number of the restricting plan cannot be (0, %d]", RestrictTxPlanSize)) - ErrLockedAmountTooLess = common.NewBizError(304003, "Total staking amount shall be more than 1 LAT") - ErrBalanceNotEnough = common.NewBizError(304004, "Create plan,the sender balance is not enough in restrict") - ErrAccountNotFound = common.NewBizError(304005, "Account is not found on restricting contract") - ErrSlashingTooMuch = common.NewBizError(304006, "Slashing amount is larger than staking amount") - ErrStakingAmountEmpty = common.NewBizError(304007, "Staking amount cannot be 0") - ErrPledgeLockFundsAmountLessThanZero = common.NewBizError(304008, "Pledge lock funds amount cannot be less than or equal to 0") - ErrReturnLockFundsAmountLessThanZero = common.NewBizError(304009, "Return lock funds amount cannot be less than or equal to 0") - ErrSlashingAmountLessThanZero = common.NewBizError(304010, "Slashing amount cannot be less than 0") - ErrCreatePlanAmountLessThanZero = common.NewBizError(304011, "Create plan each amount cannot be less than or equal to 0") - ErrStakingAmountInvalid = common.NewBizError(304012, "The staking amount is less than the return amount") - ErrRestrictBalanceNotEnough = common.NewBizError(304013, "The user restricting balance is not enough for pledge lock funds") - ErrCreatePlanAmountLessThanMiniAmount = common.NewBizError(304014, "Create plan each amount should greater than mini amount") - ErrRestrictBalanceAndFreeNotEnough = common.NewBizError(304015, "The user restricting and free balance is not enough for pledge lock funds") + ErrParamEpochInvalid = common.NewBizError(304001, "The initial epoch for staking cannot be zero") + ErrCountRestrictPlansInvalid = common.NewBizError(304002, fmt.Sprintf("The number of the restricting plan cannot be (0, %d]", RestrictTxPlanSize)) + ErrLockedAmountTooLess = common.NewBizError(304003, "Total staking amount shall be more than 1 LAT") + ErrBalanceNotEnough = common.NewBizError(304004, "Create plan,the sender balance is not enough in restrict") + ErrAccountNotFound = common.NewBizError(304005, "Account is not found on restricting contract") + ErrSlashingTooMuch = common.NewBizError(304006, "Slashing amount is larger than staking amount") + ErrStakingAmountEmpty = common.NewBizError(304007, "Staking amount cannot be 0") + ErrAdvanceLockedFundsAmountLessThanZero = common.NewBizError(304008, "Staking lock funds amount cannot be less than or equal to 0") + ErrReturnLockFundsAmountLessThanZero = common.NewBizError(304009, "Return lock funds amount cannot be less than or equal to 0") + ErrSlashingAmountLessThanZero = common.NewBizError(304010, "Slashing amount cannot be less than 0") + ErrCreatePlanAmountLessThanZero = common.NewBizError(304011, "Create plan each amount cannot be less than or equal to 0") + ErrStakingAmountInvalid = common.NewBizError(304012, "The staking amount is less than the return amount") + ErrRestrictBalanceNotEnough = common.NewBizError(304013, "The user restricting balance is not enough for staking lock funds") + ErrCreatePlanAmountLessThanMiniAmount = common.NewBizError(304014, "Create plan each amount should greater than mini amount") + ErrRestrictBalanceAndFreeNotEnough = common.NewBizError(304015, "The user restricting and free balance is not enough for staking lock funds") ) diff --git a/x/restricting/restricting_types.go b/x/restricting/restricting_types.go index 8782fcdb20..3de3b64426 100644 --- a/x/restricting/restricting_types.go +++ b/x/restricting/restricting_types.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package restricting import ( @@ -25,7 +26,7 @@ import ( // for genesis and plugin test type RestrictingInfo struct { NeedRelease *big.Int - StakingAmount *big.Int // including staking and delegation + AdvanceAmount *big.Int // including staking and delegation CachePlanAmount *big.Int ReleaseList []uint64 // ReleaseList representation which epoch will release restricting } diff --git a/x/reward/reward_db_key.go b/x/reward/reward_db_key.go index 34e337c6f4..cad2338806 100644 --- a/x/reward/reward_db_key.go +++ b/x/reward/reward_db_key.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package reward import ( diff --git a/x/reward/reward_error.go b/x/reward/reward_error.go index 2b34eb6b74..98166eb4bf 100644 --- a/x/reward/reward_error.go +++ b/x/reward/reward_error.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package reward import "github.com/AlayaNetwork/Alaya-Go/common" diff --git a/x/reward/reward_type.go b/x/reward/reward_type.go index af69207a40..6130891f02 100644 --- a/x/reward/reward_type.go +++ b/x/reward/reward_type.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package reward import ( diff --git a/x/reward/rward_test.go b/x/reward/rward_test.go index ab92f2e6da..879628740c 100644 --- a/x/reward/rward_test.go +++ b/x/reward/rward_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package reward import ( diff --git a/x/slashing/slashing_err.go b/x/slashing/slashing_err.go index 04bad32fd7..9a506064f7 100644 --- a/x/slashing/slashing_err.go +++ b/x/slashing/slashing_err.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package slashing import "github.com/AlayaNetwork/Alaya-Go/common" diff --git a/x/staking/staking_db.go b/x/staking/staking_db.go index 060f74ea75..60f0bf866b 100644 --- a/x/staking/staking_db.go +++ b/x/staking/staking_db.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package staking import ( diff --git a/x/staking/staking_db_key.go b/x/staking/staking_db_key.go index a2c80e3086..a8c3021e7b 100644 --- a/x/staking/staking_db_key.go +++ b/x/staking/staking_db_key.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package staking import ( diff --git a/x/staking/staking_err.go b/x/staking/staking_err.go index 950681a64b..4457c333b5 100644 --- a/x/staking/staking_err.go +++ b/x/staking/staking_err.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -19,40 +19,40 @@ package staking import "github.com/AlayaNetwork/Alaya-Go/common" var ( - ErrWrongBlsPubKey = common.NewBizError(301000, "Invalid BLS public key length") - ErrWrongBlsPubKeyProof = common.NewBizError(301001, "The BLS proof is incorrect") - ErrDescriptionLen = common.NewBizError(301002, "The Description length is incorrect") - ErrWrongProgramVersionSign = common.NewBizError(301003, "The program version signature is invalid") - ErrProgramVersionTooLow = common.NewBizError(301004, "The program version is too low") - ErrDeclVsFialedCreateCan = common.NewBizError(301005, "The Version Declaration is failed when creating staking") - ErrNoSameStakingAddr = common.NewBizError(301006, "The address must be the same as the one initiated staking") - ErrInvalidRewardPer = common.NewBizError(301007, "Invalid param RewardPer") - ErrRewardPerInterval = common.NewBizError(301008, "Modify the commission reward ratio too frequently") - ErrRewardPerChangeRange = common.NewBizError(301009, "The modification range exceeds the limit") - ErrStakeVonTooLow = common.NewBizError(301100, "Staking deposit is insufficient") - ErrCanAlreadyExist = common.NewBizError(301101, "The candidate already existed") - ErrCanNoExist = common.NewBizError(301102, "The candidate does not exist") - ErrCanStatusInvalid = common.NewBizError(301103, "This candidate status is expired") - ErrIncreaseStakeVonTooLow = common.NewBizError(301104, "Increased stake is insufficient") - ErrDelegateVonTooLow = common.NewBizError(301105, "Delegate deposit is insufficient") - ErrAccountNoAllowToDelegate = common.NewBizError(301106, "The account is not allowed to delegate") - ErrCanNoAllowDelegate = common.NewBizError(301107, "The candidate is not allowed to delegate") - ErrWithdrewDelegateVonTooLow = common.NewBizError(301108, "Withdrawal of delegation is insufficient") - ErrDelegateNoExist = common.NewBizError(301109, "The delegate does not exist") - ErrWrongVonOptType = common.NewBizError(301110, "The von operation type is incorrect") - ErrAccountVonNoEnough = common.NewBizError(301111, "The account balance is insufficient") - ErrBlockNumberDisordered = common.NewBizError(301112, "The blockNumber is inconsistent with the expected number") - ErrDelegateVonNoEnough = common.NewBizError(301113, "The balance of delegate is insufficient") - ErrWrongWithdrewDelVonCalc = common.NewBizError(301114, "The amount of delegate withdrawal is incorrect") - ErrValidatorNoExist = common.NewBizError(301115, "The validator does not exist") - ErrWrongFuncParams = common.NewBizError(301116, "The fn params is invalid") - ErrWrongSlashType = common.NewBizError(301117, "The slash type is illegal") - ErrSlashVonOverflow = common.NewBizError(301118, "The amount of slash is overflowed") - ErrWrongSlashVonCalc = common.NewBizError(301119, "The amount of slash for decreasing staking is incorrect") - ErrGetVerifierList = common.NewBizError(301200, "Retreiving verifier list failed") - ErrGetValidatorList = common.NewBizError(301201, "Retreiving validator list failed") - ErrGetCandidateList = common.NewBizError(301202, "Retreiving candidate list failed") - ErrGetDelegateRelated = common.NewBizError(301203, "Retreiving delegation related mapping failed") - ErrQueryCandidateInfo = common.NewBizError(301204, "Query candidate info failed") - ErrQueryDelegateInfo = common.NewBizError(301205, "Query delegate info failed") + ErrWrongBlsPubKey = common.NewBizError(301000, "Invalid BLS public key length") + ErrWrongBlsPubKeyProof = common.NewBizError(301001, "The BLS proof is incorrect") + ErrDescriptionLen = common.NewBizError(301002, "The Description length is incorrect") + ErrWrongProgramVersionSign = common.NewBizError(301003, "The program version signature is invalid") + ErrProgramVersionTooLow = common.NewBizError(301004, "The program version is too low") + ErrDeclVsFialedCreateCan = common.NewBizError(301005, "The Version Declaration is failed when creating staking") + ErrNoSameStakingAddr = common.NewBizError(301006, "The address must be the same as the one initiated staking") + ErrInvalidRewardPer = common.NewBizError(301007, "Invalid param RewardPer") + ErrRewardPerInterval = common.NewBizError(301008, "Modify the commission reward ratio too frequently") + ErrRewardPerChangeRange = common.NewBizError(301009, "The modification range exceeds the limit") + ErrStakeVonTooLow = common.NewBizError(301100, "Staking deposit is insufficient") + ErrCanAlreadyExist = common.NewBizError(301101, "The candidate already existed") + ErrCanNoExist = common.NewBizError(301102, "The candidate does not exist") + ErrCanStatusInvalid = common.NewBizError(301103, "This candidate status is expired") + ErrIncreaseStakeVonTooLow = common.NewBizError(301104, "Increased stake is insufficient") + ErrDelegateVonTooLow = common.NewBizError(301105, "Delegate deposit is insufficient") + ErrAccountNoAllowToDelegate = common.NewBizError(301106, "The account is not allowed to delegate") + ErrCanNoAllowDelegate = common.NewBizError(301107, "The candidate is not allowed to delegate") + ErrWithdrewDelegationVonTooLow = common.NewBizError(301108, "Withdrawal of delegation is insufficient") + ErrDelegateNoExist = common.NewBizError(301109, "The delegate does not exist") + ErrWrongVonOptType = common.NewBizError(301110, "The von operation type is incorrect") + ErrAccountVonNoEnough = common.NewBizError(301111, "The account balance is insufficient") + ErrBlockNumberDisordered = common.NewBizError(301112, "The blockNumber is inconsistent with the expected number") + ErrDelegateVonNoEnough = common.NewBizError(301113, "The balance of delegate is insufficient") + ErrWrongWithdrewDelVonCalc = common.NewBizError(301114, "The amount of delegate withdrawal is incorrect") + ErrValidatorNoExist = common.NewBizError(301115, "The validator does not exist") + ErrWrongFuncParams = common.NewBizError(301116, "The fn params is invalid") + ErrWrongSlashType = common.NewBizError(301117, "The slash type is illegal") + ErrSlashVonOverflow = common.NewBizError(301118, "The amount of slash is overflowed") + ErrWrongSlashVonCalc = common.NewBizError(301119, "The amount of slash for decreasing staking is incorrect") + ErrGetVerifierList = common.NewBizError(301200, "Retreiving verifier list failed") + ErrGetValidatorList = common.NewBizError(301201, "Retreiving validator list failed") + ErrGetCandidateList = common.NewBizError(301202, "Retreiving candidate list failed") + ErrGetDelegateRelated = common.NewBizError(301203, "Retreiving delegation related mapping failed") + ErrQueryCandidateInfo = common.NewBizError(301204, "Query candidate info failed") + ErrQueryDelegateInfo = common.NewBizError(301205, "Query delegate info failed") ) diff --git a/x/staking/staking_types.go b/x/staking/staking_types.go index 75fb57833d..d2635f26d8 100644 --- a/x/staking/staking_types.go +++ b/x/staking/staking_types.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package staking import ( diff --git a/x/xcom/common.go b/x/xcom/common.go index 47741aa548..e5b58fb16c 100644 --- a/x/xcom/common.go +++ b/x/xcom/common.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package xcom import ( diff --git a/x/xcom/common_config.go b/x/xcom/common_config.go index cce04e0f8c..5ab1e91baf 100644 --- a/x/xcom/common_config.go +++ b/x/xcom/common_config.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package xcom import ( @@ -62,8 +63,12 @@ const ( IncreaseIssuanceRatioLowerLimit = 0 // When electing consensus nodes, it is used to calculate the P value of the binomial distribution + ElectionBase = 25 // New expectations + ElectionBaseL1 = 3000 ElectionBaseL2 = 6000 + + AlayaNetECHash = "0x828aafb72c19203ad930cb21cee8c9887fcd59eaa44f5c4a24f4cab7cfb80ad0" ) var ( @@ -211,11 +216,9 @@ func ResetEconomicExtendConfig(newEc *EconomicModelExtend) { } const ( - DefaultMainNet = iota // PlatON default main net flag - DefaultTestNet // PlatON default test net flag - DefaultUnitTestNet // PlatON default unit test - DefaultAlayaNet // PlatON default Alaya net flag - DefaultAlayaTestNet // PlatON default Alaya test net flag + DefaultAlayaNet = iota // PlatON default Alaya net flag + DefaultTestNet // PlatON default test net flag + DefaultUnitTestNet // PlatON default unit test ) func getDefaultEMConfig(netId int8) *EconomicModel { @@ -294,65 +297,7 @@ func getDefaultEMConfig(netId int8) *EconomicModel { MinimumRelease: new(big.Int).Mul(oneAtp, new(big.Int).SetInt64(80)), }, } - case DefaultAlayaTestNet: - ec = &EconomicModel{ - Common: commonConfig{ - MaxEpochMinutes: uint64(360), // 6 hours - NodeBlockTimeWindow: uint64(20), // 20 seconds - PerRoundBlocks: uint64(10), - MaxConsensusVals: uint64(25), - AdditionalCycleTime: uint64(525960), - }, - Staking: stakingConfig{ - StakeThreshold: new(big.Int).Set(StakeLowerLimit), - OperatingThreshold: new(big.Int).Set(DelegateLowerLimit), - MaxValidators: uint64(101), - UnStakeFreezeDuration: uint64(168), // freezing 28 epoch - RewardPerMaxChangeRange: uint16(500), - RewardPerChangeInterval: uint16(10), - }, - Slashing: slashingConfig{ - SlashFractionDuplicateSign: uint32(10), - DuplicateSignReportReward: uint32(50), - MaxEvidenceAge: uint32(7), - SlashBlocksReward: uint32(250), - ZeroProduceCumulativeTime: uint16(30), - ZeroProduceNumberThreshold: uint16(1), - ZeroProduceFreezeDuration: uint64(56), - }, - Gov: governanceConfig{ - VersionProposalVoteDurationSeconds: uint64(14 * 24 * 3600), - //VersionProposalActive_ConsensusRounds: uint64(5), - VersionProposalSupportRate: 6670, - TextProposalVoteDurationSeconds: uint64(14 * 24 * 3600), - TextProposalVoteRate: 5000, - TextProposalSupportRate: 6670, - CancelProposalVoteRate: 5000, - CancelProposalSupportRate: 6670, - ParamProposalVoteDurationSeconds: uint64(14 * 24 * 3600), - ParamProposalVoteRate: 5000, - ParamProposalSupportRate: 6670, - }, - Reward: rewardConfig{ - NewBlockRate: 50, - PlatONFoundationYear: 2, - IncreaseIssuanceRatio: 500, - }, - InnerAcc: innerAccount{ - PlatONFundAccount: common.HexToAddress("0x7c03dc00f817B4454F4F0FFD04509d14F1b97390"), - PlatONFundBalance: platonFundBalance, - CDFAccount: common.HexToAddress("0xf2D36ea2f0Ab1B96Eb62d5a9131194c3010FeA37"), - CDFBalance: new(big.Int).Set(cdfundBalance), - }, - } - ece = &EconomicModelExtend{ - Reward: rewardConfigExtend{ - TheNumberOfDelegationsReward: 20, - }, - Restricting: restrictingConfigExtend{ - MinimumRelease: new(big.Int).SetInt64(1), - }, - } + case DefaultTestNet: ec = &EconomicModel{ Common: commonConfig{ @@ -927,3 +872,7 @@ func CalcP(totalWeight float64, sqrtWeight float64) float64 { return float64(ElectionBaseL2) / sqrtWeight } } + +func CalcPNew(sqrtWeight float64) float64 { + return float64(ElectionBase) / sqrtWeight +} diff --git a/x/xcom/common_config_dev.go b/x/xcom/common_config_dev.go index c427a90d5b..8510731fdd 100644 --- a/x/xcom/common_config_dev.go +++ b/x/xcom/common_config_dev.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + // +build test package xcom diff --git a/x/xcom/common_config_test.go b/x/xcom/common_config_test.go index 6af87d4f18..6a42c18e02 100644 --- a/x/xcom/common_config_test.go +++ b/x/xcom/common_config_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,17 +14,20 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package xcom import ( + "github.com/AlayaNetwork/Alaya-Go/common" + "github.com/AlayaNetwork/Alaya-Go/rlp" "github.com/stretchr/testify/assert" "testing" ) func TestGetDefaultEMConfig(t *testing.T) { - t.Run("DefaultTestNet", func(t *testing.T) { - if getDefaultEMConfig(DefaultTestNet) == nil { - t.Error("DefaultTestNet can't be nil config") + t.Run("DefaultAlayaNet", func(t *testing.T) { + if getDefaultEMConfig(DefaultAlayaNet) == nil { + t.Error("DefaultAlayaNet can't be nil config") } if err := CheckEconomicModel(); nil != err { t.Error(err) @@ -44,10 +47,21 @@ func TestGetDefaultEMConfig(t *testing.T) { } func TestEcParams0140(t *testing.T) { - GetEc(DefaultAlayaNet) + eceHash := "0xbd45f1783a2344776066ca1a88937e74dfba777c9c3eb2f6819989c66d2c0462" + getDefaultEMConfig(DefaultAlayaNet) if bytes, err := EcParams0140(); nil != err { t.Fatal(err) } else { assert.True(t, bytes != nil) + assert.True(t, common.RlpHash(bytes).Hex() == eceHash) + } +} + +func TestAlayaNetHash(t *testing.T) { + alayaEc := getDefaultEMConfig(DefaultAlayaNet) + bytes, err := rlp.EncodeToBytes(alayaEc) + if err != nil { + t.Error(err) } + assert.True(t, common.RlpHash(bytes).Hex() == AlayaNetECHash) } diff --git a/x/xcom/common_keys.go b/x/xcom/common_keys.go index a1e8bffa42..e012058352 100644 --- a/x/xcom/common_keys.go +++ b/x/xcom/common_keys.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package xcom var ( diff --git a/x/xcom/common_test.go b/x/xcom/common_test.go index 4d81e69211..2467012a10 100644 --- a/x/xcom/common_test.go +++ b/x/xcom/common_test.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package xcom import ( diff --git a/x/xcom/common_types.go b/x/xcom/common_types.go index b18022db03..0b44cf3607 100644 --- a/x/xcom/common_types.go +++ b/x/xcom/common_types.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -14,6 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the Alaya-Go library. If not, see . + package xcom import ( diff --git a/x/xutil/calculate.go b/x/xutil/calculate.go index 0e080dee4e..c6447594dd 100644 --- a/x/xutil/calculate.go +++ b/x/xutil/calculate.go @@ -1,4 +1,4 @@ -// Copyright 2018-2020 The PlatON Network Authors +// Copyright 2021 The Alaya Network Authors // This file is part of the Alaya-Go library. // // The Alaya-Go library is free software: you can redistribute it and/or modify @@ -43,7 +43,7 @@ func CalcVersion(programVersion uint32) uint32 { } func IsWorker(extra []byte) bool { - return len(extra[32:]) >= common.ExtraSeal && bytes.Equal(extra[32:97], make([]byte, common.ExtraSeal)) + return len(extra) > 32 && len(extra[32:]) >= common.ExtraSeal && bytes.Equal(extra[32:97], make([]byte, common.ExtraSeal)) } // eg. 65536 => 1.0.0