mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
merge from dev-upgrade
This commit is contained in:
commit
77f9cc59ec
612 changed files with 26661 additions and 33612 deletions
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
|
|
@ -7,6 +7,4 @@ core/ @karalabe @holiman
|
|||
eth/ @karalabe
|
||||
les/ @zsfelfoldi
|
||||
light/ @zsfelfoldi
|
||||
mobile/ @karalabe
|
||||
p2p/ @fjl @zsfelfoldi
|
||||
whisper/ @gballet @gluk256
|
||||
|
|
|
|||
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
|
@ -55,7 +55,7 @@ jobs:
|
|||
uses: actions/setup-go@v5
|
||||
with:
|
||||
cache: false
|
||||
go-version: '1.21.x'
|
||||
go-version: '1.22.x'
|
||||
- name: Run tests
|
||||
run: ${{ matrix.script }}
|
||||
env:
|
||||
|
|
|
|||
180
.travis.yml.bak
180
.travis.yml.bak
|
|
@ -1,180 +0,0 @@
|
|||
sudo: required
|
||||
language: go
|
||||
go_import_path: github.com/XinFinOrg/XDPoSChain
|
||||
|
||||
on:
|
||||
branches:
|
||||
- master
|
||||
- dev-upgrade
|
||||
tags: true
|
||||
|
||||
env:
|
||||
global:
|
||||
- GOPROXY=https://proxy.golang.org
|
||||
- GO111MODULE=on
|
||||
# Terraform env
|
||||
- tf_version=1.3.0
|
||||
# Setting terraform init CLI options - https://www.terraform.io/docs/commands/init.html
|
||||
- tf_init_cli_options=" -input=false"
|
||||
# Set terraform validation CLI options - https://www.terraform.io/docs/commands/validate.html
|
||||
- tf_validation_cli_options=""
|
||||
# Set terraform plan CLI options - https://www.terraform.io/docs/commands/plan.html
|
||||
- tf_plan_cli_options=" -lock=false -input=false"
|
||||
# Set terraform apply CLI options - https://www.terraform.io/docs/commands/apply.html
|
||||
- tf_apply_cli_options=" -auto-approve -input=false"
|
||||
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: Tests
|
||||
os: linux
|
||||
dist: bionic
|
||||
go: 1.21.x
|
||||
env:
|
||||
- GO111MODULE=auto
|
||||
name: A-B tests
|
||||
script: travis_retry go run build/ci.go test -coverage $(go list ./... | grep "github.com\/XinFinOrg\/XDPoSChain\/[a-b].*")
|
||||
- script: travis_retry go run build/ci.go test -coverage $(go list ./... | grep "github.com\/XinFinOrg\/XDPoSChain\/c[a-m].*")
|
||||
os: linux
|
||||
dist: bionic
|
||||
go: 1.21.x
|
||||
env:
|
||||
- GO111MODULE=auto
|
||||
name: C-[a-m] tests
|
||||
- script: travis_retry go run build/ci.go test -coverage $(go list ./... | grep "github.com\/XinFinOrg\/XDPoSChain\/c[n-o].*")
|
||||
os: linux
|
||||
dist: bionic
|
||||
go: 1.21.x
|
||||
env:
|
||||
- GO111MODULE=auto
|
||||
name: C-[n-o] tests
|
||||
- script: travis_retry go run build/ci.go test -coverage $(go list ./... | grep "github.com\/XinFinOrg\/XDPoSChain\/c[p-z].*")
|
||||
os: linux
|
||||
dist: bionic
|
||||
go: 1.21.x
|
||||
env:
|
||||
- GO111MODULE=auto
|
||||
name: C-[p-z] tests
|
||||
- script: travis_retry go run build/ci.go test -coverage $(go list ./... | grep "github.com\/XinFinOrg\/XDPoSChain\/[d-i].*")
|
||||
os: linux
|
||||
dist: bionic
|
||||
go: 1.21.x
|
||||
env:
|
||||
- GO111MODULE=auto
|
||||
name: D-I tests
|
||||
- script: travis_retry go run build/ci.go test -coverage $(go list ./... | grep "github.com\/XinFinOrg\/XDPoSChain\/[j-n].*")
|
||||
os: linux
|
||||
dist: bionic
|
||||
go: 1.21.x
|
||||
env:
|
||||
- GO111MODULE=auto
|
||||
name: J-N tests
|
||||
- script: travis_retry go run build/ci.go test -coverage $(go list ./... | grep "github.com\/XinFinOrg\/XDPoSChain\/[o-r].*")
|
||||
os: linux
|
||||
dist: bionic
|
||||
go: 1.21.x
|
||||
env:
|
||||
- GO111MODULE=auto
|
||||
name: O-R tests
|
||||
- script: travis_retry go run build/ci.go test -coverage $(go list ./... | grep "github.com\/XinFinOrg\/XDPoSChain\/s.*")
|
||||
os: linux
|
||||
dist: bionic
|
||||
go: 1.21.x
|
||||
env:
|
||||
- GO111MODULE=auto
|
||||
name: S tests
|
||||
- script: travis_retry go run build/ci.go test -coverage $(go list ./... | grep "github.com\/XinFinOrg\/XDPoSChain\/[t-z].*")
|
||||
os: linux
|
||||
dist: bionic
|
||||
go: 1.21.x
|
||||
env:
|
||||
- GO111MODULE=auto
|
||||
name: T-Z tests
|
||||
|
||||
- stage: TAG Build
|
||||
if: tag IS present
|
||||
services:
|
||||
- docker
|
||||
install: skip
|
||||
before_script:
|
||||
- echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
|
||||
- docker --version # document the version travis is using
|
||||
- docker build -t xinfinorg/xdposchain:$TRAVIS_TAG -f cicd/Dockerfile .
|
||||
script:
|
||||
- docker push xinfinorg/xdposchain:$TRAVIS_TAG
|
||||
|
||||
- stage: (Devnet) Build, and push images
|
||||
if: branch = dev-upgrade AND type = push AND tag IS blank
|
||||
services:
|
||||
- docker
|
||||
install: skip
|
||||
before_script:
|
||||
- echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
|
||||
- docker --version # document the version travis is using
|
||||
- docker pull xinfinorg/devnet:latest # build the "previous" tag so that our devnet environment can run with both old and new code at the same time.
|
||||
- docker tag xinfinorg/devnet:latest xinfinorg/devnet:previous
|
||||
- docker rmi xinfinorg/devnet:latest
|
||||
- docker build -t xinfinorg/devnet:latest -f cicd/Dockerfile .
|
||||
script:
|
||||
- docker push xinfinorg/devnet:latest
|
||||
- docker push xinfinorg/devnet:previous
|
||||
|
||||
- stage: (Devnet)Terraform plan
|
||||
if: branch = dev-upgrade AND type = push AND tag IS blank
|
||||
dist: xenial
|
||||
language: bash
|
||||
install:
|
||||
- wget https://releases.hashicorp.com/terraform/"$tf_version"/terraform_"$tf_version"_linux_amd64.zip
|
||||
- unzip terraform_"$tf_version"_linux_amd64.zip
|
||||
- sudo mv terraform /usr/local/bin/
|
||||
- rm terraform_"$tf_version"_linux_amd64.zip
|
||||
script:
|
||||
- echo "Pull request detected, creating change plan(Devnet)"
|
||||
- cd cicd/devnet/terraform
|
||||
# Terraform init, validate, then create change plan. If any fail, fail validation
|
||||
- terraform init $tf_init_cli_options
|
||||
- terraform validate $tf_validation_cli_options
|
||||
- terraform plan $tf_plan_cli_options
|
||||
|
||||
- stage: (Devnet) Terraform apply
|
||||
if: branch = dev-upgrade AND type = push AND tag IS blank
|
||||
dist: xenial
|
||||
language: bash
|
||||
install:
|
||||
# Download and install terraform before each run
|
||||
- wget https://releases.hashicorp.com/terraform/"$tf_version"/terraform_"$tf_version"_linux_amd64.zip
|
||||
- unzip terraform_"$tf_version"_linux_amd64.zip
|
||||
- sudo mv terraform /usr/local/bin/
|
||||
- rm terraform_"$tf_version"_linux_amd64.zip
|
||||
- curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
|
||||
- unzip awscliv2.zip
|
||||
- sudo ./aws/install
|
||||
- export PATH=$PATH:$HOME/.local/bin # put aws in the path
|
||||
script:
|
||||
- echo "Merge detected, executing changes(Devnet)"
|
||||
- cd cicd/devnet/terraform
|
||||
# Terraform init and then apply changes to environment
|
||||
- terraform init $tf_init_cli_options
|
||||
- terraform apply $tf_apply_cli_options
|
||||
- sleep 5
|
||||
- |
|
||||
source .env
|
||||
for ((i=$us_east_2_start;i<$us_east_2_end;i++)); do
|
||||
echo "Force deploy xdc-$i"
|
||||
aws ecs update-service --region us-east-2 --cluster devnet-xdcnode-cluster --service ecs-service-xdc$i --force-new-deployment --no-cli-pager;
|
||||
done
|
||||
for ((i=$eu_west_1_start;i<$eu_west_1_end;i++)); do
|
||||
echo "Force deploy xdc-$i"
|
||||
aws ecs update-service --region eu-west-1 --cluster devnet-xdcnode-cluster --service ecs-service-xdc$i --force-new-deployment --no-cli-pager;
|
||||
done
|
||||
for ((i=$ap_southeast_2_start;i<$ap_southeast_2_end;i++)); do
|
||||
echo "Force deploy xdc-$i"
|
||||
aws ecs update-service --region ap-southeast-2 --cluster devnet-xdcnode-cluster --service ecs-service-xdc$i --force-new-deployment --no-cli-pager;
|
||||
done
|
||||
aws ecs update-service --region ap-southeast-1 --cluster devnet-xdcnode-cluster --service ecs-service-rpc1 --force-new-deployment --no-cli-pager;
|
||||
|
||||
- stage: (Devnet) Send Deployment Notification
|
||||
if: branch = dev-upgrade AND type = push AND tag IS blank
|
||||
language: bash
|
||||
script:
|
||||
- curl --location --request POST "66.94.98.186:8080/deploy?environment=devnet&service=xdc&version=$TRAVIS_COMMIT"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.21-alpine as builder
|
||||
FROM golang:1.22-alpine as builder
|
||||
|
||||
RUN apk add --no-cache make gcc musl-dev linux-headers git
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.21-alpine as builder
|
||||
FROM golang:1.22-alpine as builder
|
||||
|
||||
RUN apk add --no-cache make gcc musl-dev linux-headers
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.21-alpine as builder
|
||||
FROM golang:1.22-alpine as builder
|
||||
|
||||
RUN apk add --no-cache make gcc musl-dev linux-headers git
|
||||
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
GOBIN = $(shell pwd)/build/bin
|
||||
GOFMT = gofmt
|
||||
GO ?= 1.21.3
|
||||
GO ?= 1.22.10
|
||||
GO_PACKAGES = .
|
||||
GO_FILES := $(shell find $(shell go list -f '{{.Dir}}' $(GO_PACKAGES)) -name \*.go)
|
||||
|
||||
|
|
|
|||
40
XDCx/XDCx.go
40
XDCx/XDCx.go
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate"
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCxDAO"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/lru"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/prque"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
|
|
@ -17,7 +18,6 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/XinFinOrg/XDPoSChain/p2p"
|
||||
"github.com/XinFinOrg/XDPoSChain/rpc"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"golang.org/x/sync/syncmap"
|
||||
)
|
||||
|
||||
|
|
@ -59,8 +59,8 @@ type XDCX struct {
|
|||
|
||||
sdkNode bool
|
||||
settings syncmap.Map // holds configuration settings that can be dynamically changed
|
||||
tokenDecimalCache *lru.Cache
|
||||
orderCache *lru.Cache
|
||||
tokenDecimalCache *lru.Cache[common.Address, *big.Int]
|
||||
orderCache *lru.Cache[common.Hash, map[common.Hash]tradingstate.OrderHistoryItem]
|
||||
}
|
||||
|
||||
func (XDCx *XDCX) Protocols() []p2p.Protocol {
|
||||
|
|
@ -94,19 +94,11 @@ func NewMongoDBEngine(cfg *Config) *XDCxDAO.MongoDatabase {
|
|||
}
|
||||
|
||||
func New(cfg *Config) *XDCX {
|
||||
tokenDecimalCache, err := lru.New(defaultCacheLimit)
|
||||
if err != nil {
|
||||
log.Warn("[XDCx-New] fail to create new lru for token decimal", "error", err)
|
||||
}
|
||||
orderCache, err := lru.New(tradingstate.OrderCacheLimit)
|
||||
if err != nil {
|
||||
log.Warn("[XDCx-New] fail to create new lru for order", "error", err)
|
||||
}
|
||||
XDCX := &XDCX{
|
||||
orderNonce: make(map[common.Address]*big.Int),
|
||||
Triegc: prque.New(nil),
|
||||
tokenDecimalCache: tokenDecimalCache,
|
||||
orderCache: orderCache,
|
||||
tokenDecimalCache: lru.NewCache[common.Address, *big.Int](defaultCacheLimit),
|
||||
orderCache: lru.NewCache[common.Hash, map[common.Hash]tradingstate.OrderHistoryItem](tradingstate.OrderCacheLimit),
|
||||
}
|
||||
|
||||
// default DBEngine: levelDB
|
||||
|
|
@ -275,11 +267,11 @@ func (XDCx *XDCX) GetAveragePriceLastEpoch(chain consensus.ChainContext, statedb
|
|||
if inversePrice != nil && inversePrice.Sign() > 0 {
|
||||
quoteTokenDecimal, err := XDCx.GetTokenDecimal(chain, statedb, quoteToken)
|
||||
if err != nil || quoteTokenDecimal.Sign() == 0 {
|
||||
return nil, fmt.Errorf("fail to get tokenDecimal. Token: %v . Err: %v", quoteToken.String(), err)
|
||||
return nil, fmt.Errorf("fail to get tokenDecimal: Token: %v . Err: %v", quoteToken.String(), err)
|
||||
}
|
||||
baseTokenDecimal, err := XDCx.GetTokenDecimal(chain, statedb, baseToken)
|
||||
if err != nil || baseTokenDecimal.Sign() == 0 {
|
||||
return nil, fmt.Errorf("fail to get tokenDecimal. Token: %v . Err: %v", baseToken.String(), err)
|
||||
return nil, fmt.Errorf("fail to get tokenDecimal: Token: %v . Err: %v", baseToken.String(), err)
|
||||
}
|
||||
price = new(big.Int).Mul(baseTokenDecimal, quoteTokenDecimal)
|
||||
price = new(big.Int).Div(price, inversePrice)
|
||||
|
|
@ -302,7 +294,7 @@ func (XDCx *XDCX) ConvertXDCToToken(chain consensus.ChainContext, statedb *state
|
|||
|
||||
tokenDecimal, err := XDCx.GetTokenDecimal(chain, statedb, token)
|
||||
if err != nil || tokenDecimal.Sign() == 0 {
|
||||
return common.Big0, common.Big0, fmt.Errorf("fail to get tokenDecimal. Token: %v . Err: %v", token.String(), err)
|
||||
return common.Big0, common.Big0, fmt.Errorf("fail to get tokenDecimal: Token: %v . Err: %v", token.String(), err)
|
||||
}
|
||||
tokenQuantity := new(big.Int).Mul(quantity, tokenDecimal)
|
||||
tokenQuantity = new(big.Int).Div(tokenQuantity, tokenPriceInXDC)
|
||||
|
|
@ -568,7 +560,7 @@ func (XDCx *XDCX) GetTradingState(block *types.Block, author common.Address) (*t
|
|||
return nil, err
|
||||
}
|
||||
if XDCx.StateCache == nil {
|
||||
return nil, errors.New("Not initialized XDCx")
|
||||
return nil, errors.New("not initialized XDCx")
|
||||
}
|
||||
return tradingstate.New(root, XDCx.StateCache)
|
||||
}
|
||||
|
|
@ -607,12 +599,9 @@ func (XDCx *XDCX) GetTradingStateRoot(block *types.Block, author common.Address)
|
|||
}
|
||||
|
||||
func (XDCx *XDCX) UpdateOrderCache(baseToken, quoteToken common.Address, orderHash common.Hash, txhash common.Hash, lastState tradingstate.OrderHistoryItem) {
|
||||
var orderCacheAtTxHash map[common.Hash]tradingstate.OrderHistoryItem
|
||||
c, ok := XDCx.orderCache.Get(txhash)
|
||||
if !ok || c == nil {
|
||||
orderCacheAtTxHash, ok := XDCx.orderCache.Get(txhash)
|
||||
if !ok || orderCacheAtTxHash == nil {
|
||||
orderCacheAtTxHash = make(map[common.Hash]tradingstate.OrderHistoryItem)
|
||||
} else {
|
||||
orderCacheAtTxHash = c.(map[common.Hash]tradingstate.OrderHistoryItem)
|
||||
}
|
||||
orderKey := tradingstate.GetOrderHistoryKey(baseToken, quoteToken, orderHash)
|
||||
_, ok = orderCacheAtTxHash[orderKey]
|
||||
|
|
@ -629,16 +618,15 @@ func (XDCx *XDCX) RollbackReorgTxMatch(txhash common.Hash) error {
|
|||
items := db.GetListItemByTxHash(txhash, &tradingstate.OrderItem{})
|
||||
if items != nil {
|
||||
for _, order := range items.([]*tradingstate.OrderItem) {
|
||||
c, ok := XDCx.orderCache.Get(txhash)
|
||||
log.Debug("XDCx reorg: rollback order", "txhash", txhash.Hex(), "order", tradingstate.ToJSON(order), "orderHistoryItem", c)
|
||||
if !ok {
|
||||
orderCacheAtTxHash, ok := XDCx.orderCache.Get(txhash)
|
||||
log.Debug("XDCx reorg: rollback order", "txhash", txhash.Hex(), "order", tradingstate.ToJSON(order), "orderHistoryItem", orderCacheAtTxHash)
|
||||
if !ok || orderCacheAtTxHash == nil {
|
||||
log.Debug("XDCx reorg: remove order due to no orderCache", "order", tradingstate.ToJSON(order))
|
||||
if err := db.DeleteObject(order.Hash, &tradingstate.OrderItem{}); err != nil {
|
||||
log.Crit("SDKNode: failed to remove reorg order", "err", err.Error(), "order", tradingstate.ToJSON(order))
|
||||
}
|
||||
continue
|
||||
}
|
||||
orderCacheAtTxHash := c.(map[common.Hash]tradingstate.OrderHistoryItem)
|
||||
orderHistoryItem := orderCacheAtTxHash[tradingstate.GetOrderHistoryKey(order.BaseToken, order.QuoteToken, order.Hash)]
|
||||
if (orderHistoryItem == tradingstate.OrderHistoryItem{}) {
|
||||
log.Debug("XDCx reorg: remove order due to empty orderHistory", "order", tradingstate.ToJSON(order))
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ func (XDCx *XDCX) processOrderList(coinbase common.Address, chain consensus.Chai
|
|||
inversePrice := tradingStateDB.GetLastPrice(tradingstate.GetTradingOrderBookHash(common.XDCNativeAddressBinary, oldestOrder.QuoteToken))
|
||||
quoteTokenDecimal, err := XDCx.GetTokenDecimal(chain, statedb, oldestOrder.QuoteToken)
|
||||
if err != nil || quoteTokenDecimal.Sign() == 0 {
|
||||
return nil, nil, nil, fmt.Errorf("Fail to get tokenDecimal. Token: %v . Err: %v", oldestOrder.QuoteToken.String(), err)
|
||||
return nil, nil, nil, fmt.Errorf("fail to get tokenDecimal: Token: %v . Err: %v", oldestOrder.QuoteToken.String(), err)
|
||||
}
|
||||
log.Debug("TryGet inversePrice XDC/QuoteToken", "inversePrice", inversePrice)
|
||||
if inversePrice != nil && inversePrice.Sign() > 0 {
|
||||
|
|
@ -368,11 +368,11 @@ func (XDCx *XDCX) processOrderList(coinbase common.Address, chain consensus.Chai
|
|||
func (XDCx *XDCX) getTradeQuantity(quotePrice *big.Int, coinbase common.Address, chain consensus.ChainContext, statedb *state.StateDB, takerOrder *tradingstate.OrderItem, makerOrder *tradingstate.OrderItem, quantityToTrade *big.Int) (*big.Int, bool, *tradingstate.SettleBalance, error) {
|
||||
baseTokenDecimal, err := XDCx.GetTokenDecimal(chain, statedb, makerOrder.BaseToken)
|
||||
if err != nil || baseTokenDecimal.Sign() == 0 {
|
||||
return tradingstate.Zero, false, nil, fmt.Errorf("Fail to get tokenDecimal. Token: %v . Err: %v", makerOrder.BaseToken.String(), err)
|
||||
return tradingstate.Zero, false, nil, fmt.Errorf("fail to get tokenDecimal: Token: %v . Err: %v", makerOrder.BaseToken.String(), err)
|
||||
}
|
||||
quoteTokenDecimal, err := XDCx.GetTokenDecimal(chain, statedb, makerOrder.QuoteToken)
|
||||
if err != nil || quoteTokenDecimal.Sign() == 0 {
|
||||
return tradingstate.Zero, false, nil, fmt.Errorf("Fail to get tokenDecimal. Token: %v . Err: %v", makerOrder.QuoteToken.String(), err)
|
||||
return tradingstate.Zero, false, nil, fmt.Errorf("fail to get tokenDecimal: Token: %v . Err: %v", makerOrder.QuoteToken.String(), err)
|
||||
}
|
||||
if makerOrder.QuoteToken == common.XDCNativeAddressBinary {
|
||||
quotePrice = quoteTokenDecimal
|
||||
|
|
@ -526,7 +526,7 @@ func DoSettleBalance(coinbase common.Address, takerOrder, makerOrder *tradingsta
|
|||
matchingFee = new(big.Int).Add(matchingFee, common.RelayerFee)
|
||||
|
||||
if common.EmptyHash(takerExOwner.Hash()) || common.EmptyHash(makerExOwner.Hash()) {
|
||||
return fmt.Errorf("Echange owner empty , Taker: %v , maker : %v ", takerExOwner, makerExOwner)
|
||||
return fmt.Errorf("empty echange owner: taker: %v , maker : %v", takerExOwner, makerExOwner)
|
||||
}
|
||||
mapBalances := map[common.Address]map[common.Address]*big.Int{}
|
||||
//Checking balance
|
||||
|
|
@ -656,9 +656,10 @@ func (XDCx *XDCX) ProcessCancelOrder(header *types.Header, tradingStateDB *tradi
|
|||
}
|
||||
log.Debug("ProcessCancelOrder", "baseToken", originOrder.BaseToken, "quoteToken", originOrder.QuoteToken)
|
||||
feeRate := tradingstate.GetExRelayerFee(originOrder.ExchangeAddress, statedb)
|
||||
tokenCancelFee, tokenPriceInXDC := common.Big0, common.Big0
|
||||
var tokenCancelFee, tokenPriceInXDC *big.Int
|
||||
if !chain.Config().IsTIPXDCXCancellationFee(header.Number) {
|
||||
tokenCancelFee = getCancelFeeV1(baseTokenDecimal, feeRate, &originOrder)
|
||||
tokenPriceInXDC = common.Big0
|
||||
} else {
|
||||
tokenCancelFee, tokenPriceInXDC = XDCx.getCancelFee(chain, statedb, tradingStateDB, &originOrder, feeRate)
|
||||
}
|
||||
|
|
@ -721,7 +722,7 @@ func (XDCx *XDCX) ProcessCancelOrder(header *types.Header, tradingStateDB *tradi
|
|||
// cancellation fee = 1/10 trading fee
|
||||
// deprecated after hardfork at TIPXDCXCancellationFee
|
||||
func getCancelFeeV1(baseTokenDecimal *big.Int, feeRate *big.Int, order *tradingstate.OrderItem) *big.Int {
|
||||
cancelFee := big.NewInt(0)
|
||||
var cancelFee *big.Int
|
||||
if order.Side == tradingstate.Ask {
|
||||
// SELL 1 BTC => XDC ,,
|
||||
// order.Quantity =1 && fee rate =2
|
||||
|
|
@ -748,8 +749,7 @@ func (XDCx *XDCX) getCancelFee(chain consensus.ChainContext, statedb *state.Stat
|
|||
if feeRate == nil || feeRate.Sign() == 0 {
|
||||
return common.Big0, common.Big0
|
||||
}
|
||||
cancelFee := big.NewInt(0)
|
||||
tokenPriceInXDC := big.NewInt(0)
|
||||
var cancelFee, tokenPriceInXDC *big.Int
|
||||
var err error
|
||||
if order.Side == tradingstate.Ask {
|
||||
cancelFee, tokenPriceInXDC, err = XDCx.ConvertXDCToToken(chain, statedb, tradingStateDb, order.BaseToken, common.RelayerCancelFee)
|
||||
|
|
|
|||
|
|
@ -4,15 +4,14 @@ import (
|
|||
"math/big"
|
||||
"strings"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/contracts/XDCx/contract"
|
||||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain"
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts/abi"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||
"github.com/XinFinOrg/XDPoSChain/contracts/XDCx/contract"
|
||||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
)
|
||||
|
||||
// GetTokenAbi return token abi
|
||||
|
|
@ -45,8 +44,8 @@ func RunContract(chain consensus.ChainContext, statedb *state.StateDB, contractA
|
|||
}
|
||||
|
||||
func (XDCx *XDCX) GetTokenDecimal(chain consensus.ChainContext, statedb *state.StateDB, tokenAddr common.Address) (*big.Int, error) {
|
||||
if tokenDecimal, ok := XDCx.tokenDecimalCache.Get(tokenAddr); ok {
|
||||
return tokenDecimal.(*big.Int), nil
|
||||
if tokenDecimal, ok := XDCx.tokenDecimalCache.Get(tokenAddr); ok && tokenDecimal != nil {
|
||||
return tokenDecimal, nil
|
||||
}
|
||||
if tokenAddr == common.XDCNativeAddressBinary {
|
||||
XDCx.tokenDecimalCache.Add(tokenAddr, common.BasePrice)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||
"github.com/XinFinOrg/XDPoSChain/trie"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
)
|
||||
|
||||
// Trie cache generation limit after which to evic trie nodes from memory.
|
||||
|
|
@ -33,9 +32,6 @@ const (
|
|||
// Number of past tries to keep. This value is chosen such that
|
||||
// reasonable chain reorg depths will hit an existing trie.
|
||||
maxPastTries = 12
|
||||
|
||||
// Number of codehash->size associations to keep.
|
||||
codeSizeCacheSize = 100000
|
||||
)
|
||||
|
||||
// Database wraps access to tries and contract code.
|
||||
|
|
@ -79,18 +75,15 @@ type Trie interface {
|
|||
// intermediate trie-node memory pool between the low level storage layer and the
|
||||
// high level trie abstraction.
|
||||
func NewDatabase(db ethdb.Database) Database {
|
||||
csc, _ := lru.New(codeSizeCacheSize)
|
||||
return &cachingDB{
|
||||
db: trie.NewDatabase(db),
|
||||
codeSizeCache: csc,
|
||||
db: trie.NewDatabase(db),
|
||||
}
|
||||
}
|
||||
|
||||
type cachingDB struct {
|
||||
db *trie.Database
|
||||
mu sync.Mutex
|
||||
pastTries []*XDCXTrie
|
||||
codeSizeCache *lru.Cache
|
||||
db *trie.Database
|
||||
mu sync.Mutex
|
||||
pastTries []*XDCXTrie
|
||||
}
|
||||
|
||||
// OpenTrie opens the main account trie.
|
||||
|
|
|
|||
|
|
@ -47,13 +47,13 @@ type DumpOrderBookInfo struct {
|
|||
LowestLiquidationPrice *big.Int
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) DumpAskTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
|
||||
exhangeObject := self.getStateExchangeObject(orderBook)
|
||||
func (t *TradingStateDB) DumpAskTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
|
||||
exhangeObject := t.getStateExchangeObject(orderBook)
|
||||
if exhangeObject == nil {
|
||||
return nil, fmt.Errorf("Order book not found orderBook : %v ", orderBook.Hex())
|
||||
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
|
||||
}
|
||||
mapResult := map[*big.Int]DumpOrderList{}
|
||||
it := trie.NewIterator(exhangeObject.getAsksTrie(self.db).NodeIterator(nil))
|
||||
it := trie.NewIterator(exhangeObject.getAsksTrie(t.db).NodeIterator(nil))
|
||||
for it.Next() {
|
||||
priceHash := common.BytesToHash(it.Key)
|
||||
if common.EmptyHash(priceHash) {
|
||||
|
|
@ -65,15 +65,15 @@ func (self *TradingStateDB) DumpAskTrie(orderBook common.Hash) (map[*big.Int]Dum
|
|||
} else {
|
||||
var data orderList
|
||||
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
|
||||
return nil, fmt.Errorf("Fail when decode order iist orderBook : %v ,price :%v ", orderBook.Hex(), price)
|
||||
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , price :%v", orderBook.Hex(), price)
|
||||
}
|
||||
stateOrderList := newStateOrderList(self, Ask, orderBook, priceHash, data, nil)
|
||||
mapResult[price] = stateOrderList.DumpOrderList(self.db)
|
||||
stateOrderList := newStateOrderList(t, Ask, orderBook, priceHash, data, nil)
|
||||
mapResult[price] = stateOrderList.DumpOrderList(t.db)
|
||||
}
|
||||
}
|
||||
for priceHash, stateOrderList := range exhangeObject.stateAskObjects {
|
||||
if stateOrderList.Volume().Sign() > 0 {
|
||||
mapResult[new(big.Int).SetBytes(priceHash.Bytes())] = stateOrderList.DumpOrderList(self.db)
|
||||
mapResult[new(big.Int).SetBytes(priceHash.Bytes())] = stateOrderList.DumpOrderList(t.db)
|
||||
}
|
||||
}
|
||||
listPrice := []*big.Int{}
|
||||
|
|
@ -90,13 +90,13 @@ func (self *TradingStateDB) DumpAskTrie(orderBook common.Hash) (map[*big.Int]Dum
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) DumpBidTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
|
||||
exhangeObject := self.getStateExchangeObject(orderBook)
|
||||
func (t *TradingStateDB) DumpBidTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
|
||||
exhangeObject := t.getStateExchangeObject(orderBook)
|
||||
if exhangeObject == nil {
|
||||
return nil, fmt.Errorf("Order book not found orderBook : %v ", orderBook.Hex())
|
||||
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
|
||||
}
|
||||
mapResult := map[*big.Int]DumpOrderList{}
|
||||
it := trie.NewIterator(exhangeObject.getBidsTrie(self.db).NodeIterator(nil))
|
||||
it := trie.NewIterator(exhangeObject.getBidsTrie(t.db).NodeIterator(nil))
|
||||
for it.Next() {
|
||||
priceHash := common.BytesToHash(it.Key)
|
||||
if common.EmptyHash(priceHash) {
|
||||
|
|
@ -108,15 +108,15 @@ func (self *TradingStateDB) DumpBidTrie(orderBook common.Hash) (map[*big.Int]Dum
|
|||
} else {
|
||||
var data orderList
|
||||
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
|
||||
return nil, fmt.Errorf("Fail when decode order iist orderBook : %v ,price :%v ", orderBook.Hex(), price)
|
||||
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , price :%v", orderBook.Hex(), price)
|
||||
}
|
||||
stateOrderList := newStateOrderList(self, Bid, orderBook, priceHash, data, nil)
|
||||
mapResult[price] = stateOrderList.DumpOrderList(self.db)
|
||||
stateOrderList := newStateOrderList(t, Bid, orderBook, priceHash, data, nil)
|
||||
mapResult[price] = stateOrderList.DumpOrderList(t.db)
|
||||
}
|
||||
}
|
||||
for priceHash, stateOrderList := range exhangeObject.stateBidObjects {
|
||||
if stateOrderList.Volume().Sign() > 0 {
|
||||
mapResult[new(big.Int).SetBytes(priceHash.Bytes())] = stateOrderList.DumpOrderList(self.db)
|
||||
mapResult[new(big.Int).SetBytes(priceHash.Bytes())] = stateOrderList.DumpOrderList(t.db)
|
||||
}
|
||||
}
|
||||
listPrice := []*big.Int{}
|
||||
|
|
@ -133,13 +133,13 @@ func (self *TradingStateDB) DumpBidTrie(orderBook common.Hash) (map[*big.Int]Dum
|
|||
return mapResult, nil
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) GetBids(orderBook common.Hash) (map[*big.Int]*big.Int, error) {
|
||||
exhangeObject := self.getStateExchangeObject(orderBook)
|
||||
func (t *TradingStateDB) GetBids(orderBook common.Hash) (map[*big.Int]*big.Int, error) {
|
||||
exhangeObject := t.getStateExchangeObject(orderBook)
|
||||
if exhangeObject == nil {
|
||||
return nil, fmt.Errorf("Order book not found orderBook : %v ", orderBook.Hex())
|
||||
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
|
||||
}
|
||||
mapResult := map[*big.Int]*big.Int{}
|
||||
it := trie.NewIterator(exhangeObject.getBidsTrie(self.db).NodeIterator(nil))
|
||||
it := trie.NewIterator(exhangeObject.getBidsTrie(t.db).NodeIterator(nil))
|
||||
for it.Next() {
|
||||
priceHash := common.BytesToHash(it.Key)
|
||||
if common.EmptyHash(priceHash) {
|
||||
|
|
@ -151,9 +151,9 @@ func (self *TradingStateDB) GetBids(orderBook common.Hash) (map[*big.Int]*big.In
|
|||
} else {
|
||||
var data orderList
|
||||
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
|
||||
return nil, fmt.Errorf("Fail when decode order iist orderBook : %v ,price :%v ", orderBook.Hex(), price)
|
||||
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , price :%v", orderBook.Hex(), price)
|
||||
}
|
||||
stateOrderList := newStateOrderList(self, Bid, orderBook, priceHash, data, nil)
|
||||
stateOrderList := newStateOrderList(t, Bid, orderBook, priceHash, data, nil)
|
||||
mapResult[price] = stateOrderList.data.Volume
|
||||
}
|
||||
}
|
||||
|
|
@ -176,13 +176,13 @@ func (self *TradingStateDB) GetBids(orderBook common.Hash) (map[*big.Int]*big.In
|
|||
return mapResult, nil
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) GetAsks(orderBook common.Hash) (map[*big.Int]*big.Int, error) {
|
||||
exhangeObject := self.getStateExchangeObject(orderBook)
|
||||
func (t *TradingStateDB) GetAsks(orderBook common.Hash) (map[*big.Int]*big.Int, error) {
|
||||
exhangeObject := t.getStateExchangeObject(orderBook)
|
||||
if exhangeObject == nil {
|
||||
return nil, fmt.Errorf("Order book not found orderBook : %v ", orderBook.Hex())
|
||||
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
|
||||
}
|
||||
mapResult := map[*big.Int]*big.Int{}
|
||||
it := trie.NewIterator(exhangeObject.getAsksTrie(self.db).NodeIterator(nil))
|
||||
it := trie.NewIterator(exhangeObject.getAsksTrie(t.db).NodeIterator(nil))
|
||||
for it.Next() {
|
||||
priceHash := common.BytesToHash(it.Key)
|
||||
if common.EmptyHash(priceHash) {
|
||||
|
|
@ -194,9 +194,9 @@ func (self *TradingStateDB) GetAsks(orderBook common.Hash) (map[*big.Int]*big.In
|
|||
} else {
|
||||
var data orderList
|
||||
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
|
||||
return nil, fmt.Errorf("Fail when decode order iist orderBook : %v ,price :%v ", orderBook.Hex(), price)
|
||||
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , price : %v", orderBook.Hex(), price)
|
||||
}
|
||||
stateOrderList := newStateOrderList(self, Ask, orderBook, priceHash, data, nil)
|
||||
stateOrderList := newStateOrderList(t, Ask, orderBook, priceHash, data, nil)
|
||||
mapResult[price] = stateOrderList.data.Volume
|
||||
}
|
||||
}
|
||||
|
|
@ -218,22 +218,23 @@ func (self *TradingStateDB) GetAsks(orderBook common.Hash) (map[*big.Int]*big.In
|
|||
}
|
||||
return result, nil
|
||||
}
|
||||
func (self *stateOrderList) DumpOrderList(db Database) DumpOrderList {
|
||||
mapResult := DumpOrderList{Volume: self.Volume(), Orders: map[*big.Int]*big.Int{}}
|
||||
orderListIt := trie.NewIterator(self.getTrie(db).NodeIterator(nil))
|
||||
|
||||
func (s *stateOrderList) DumpOrderList(db Database) DumpOrderList {
|
||||
mapResult := DumpOrderList{Volume: s.Volume(), Orders: map[*big.Int]*big.Int{}}
|
||||
orderListIt := trie.NewIterator(s.getTrie(db).NodeIterator(nil))
|
||||
for orderListIt.Next() {
|
||||
keyHash := common.BytesToHash(orderListIt.Key)
|
||||
if common.EmptyHash(keyHash) {
|
||||
continue
|
||||
}
|
||||
if _, exist := self.cachedStorage[keyHash]; exist {
|
||||
if _, exist := s.cachedStorage[keyHash]; exist {
|
||||
continue
|
||||
} else {
|
||||
_, content, _, _ := rlp.Split(orderListIt.Value)
|
||||
mapResult.Orders[new(big.Int).SetBytes(keyHash.Bytes())] = new(big.Int).SetBytes(content)
|
||||
}
|
||||
}
|
||||
for key, value := range self.cachedStorage {
|
||||
for key, value := range s.cachedStorage {
|
||||
if !common.EmptyHash(value) {
|
||||
mapResult.Orders[new(big.Int).SetBytes(key.Bytes())] = new(big.Int).SetBytes(value.Bytes())
|
||||
}
|
||||
|
|
@ -245,17 +246,17 @@ func (self *stateOrderList) DumpOrderList(db Database) DumpOrderList {
|
|||
sort.Slice(listIds, func(i, j int) bool {
|
||||
return listIds[i].Cmp(listIds[j]) < 0
|
||||
})
|
||||
result := DumpOrderList{Volume: self.Volume(), Orders: map[*big.Int]*big.Int{}}
|
||||
result := DumpOrderList{Volume: s.Volume(), Orders: map[*big.Int]*big.Int{}}
|
||||
for _, id := range listIds {
|
||||
result.Orders[id] = mapResult.Orders[id]
|
||||
}
|
||||
return mapResult
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) DumpOrderBookInfo(orderBook common.Hash) (*DumpOrderBookInfo, error) {
|
||||
exhangeObject := self.getStateExchangeObject(orderBook)
|
||||
func (t *TradingStateDB) DumpOrderBookInfo(orderBook common.Hash) (*DumpOrderBookInfo, error) {
|
||||
exhangeObject := t.getStateExchangeObject(orderBook)
|
||||
if exhangeObject == nil {
|
||||
return nil, fmt.Errorf("Order book not found orderBook : %v ", orderBook.Hex())
|
||||
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
|
||||
}
|
||||
result := &DumpOrderBookInfo{}
|
||||
result.LastPrice = exhangeObject.data.LastPrice
|
||||
|
|
@ -264,29 +265,29 @@ func (self *TradingStateDB) DumpOrderBookInfo(orderBook common.Hash) (*DumpOrder
|
|||
result.MediumPriceBeforeEpoch = exhangeObject.data.MediumPriceBeforeEpoch
|
||||
result.Nonce = exhangeObject.data.Nonce
|
||||
result.TotalQuantity = exhangeObject.data.TotalQuantity
|
||||
result.BestAsk = new(big.Int).SetBytes(exhangeObject.getBestPriceAsksTrie(self.db).Bytes())
|
||||
result.BestBid = new(big.Int).SetBytes(exhangeObject.getBestBidsTrie(self.db).Bytes())
|
||||
lowestPrice, _ := exhangeObject.getLowestLiquidationPrice(self.db)
|
||||
result.BestAsk = new(big.Int).SetBytes(exhangeObject.getBestPriceAsksTrie(t.db).Bytes())
|
||||
result.BestBid = new(big.Int).SetBytes(exhangeObject.getBestBidsTrie(t.db).Bytes())
|
||||
lowestPrice, _ := exhangeObject.getLowestLiquidationPrice(t.db)
|
||||
result.LowestLiquidationPrice = new(big.Int).SetBytes(lowestPrice.Bytes())
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (self *stateLendingBook) DumpOrderList(db Database) DumpOrderList {
|
||||
mapResult := DumpOrderList{Volume: self.Volume(), Orders: map[*big.Int]*big.Int{}}
|
||||
orderListIt := trie.NewIterator(self.getTrie(db).NodeIterator(nil))
|
||||
func (s *stateLendingBook) DumpOrderList(db Database) DumpOrderList {
|
||||
mapResult := DumpOrderList{Volume: s.Volume(), Orders: map[*big.Int]*big.Int{}}
|
||||
orderListIt := trie.NewIterator(s.getTrie(db).NodeIterator(nil))
|
||||
for orderListIt.Next() {
|
||||
keyHash := common.BytesToHash(orderListIt.Key)
|
||||
if common.EmptyHash(keyHash) {
|
||||
continue
|
||||
}
|
||||
if _, exist := self.cachedStorage[keyHash]; exist {
|
||||
if _, exist := s.cachedStorage[keyHash]; exist {
|
||||
continue
|
||||
} else {
|
||||
_, content, _, _ := rlp.Split(orderListIt.Value)
|
||||
mapResult.Orders[new(big.Int).SetBytes(keyHash.Bytes())] = new(big.Int).SetBytes(content)
|
||||
}
|
||||
}
|
||||
for key, value := range self.cachedStorage {
|
||||
for key, value := range s.cachedStorage {
|
||||
if !common.EmptyHash(value) {
|
||||
mapResult.Orders[new(big.Int).SetBytes(key.Bytes())] = new(big.Int).SetBytes(value.Bytes())
|
||||
}
|
||||
|
|
@ -298,33 +299,33 @@ func (self *stateLendingBook) DumpOrderList(db Database) DumpOrderList {
|
|||
sort.Slice(listIds, func(i, j int) bool {
|
||||
return listIds[i].Cmp(listIds[j]) < 0
|
||||
})
|
||||
result := DumpOrderList{Volume: self.Volume(), Orders: map[*big.Int]*big.Int{}}
|
||||
result := DumpOrderList{Volume: s.Volume(), Orders: map[*big.Int]*big.Int{}}
|
||||
for _, id := range listIds {
|
||||
result.Orders[id] = mapResult.Orders[id]
|
||||
}
|
||||
return mapResult
|
||||
}
|
||||
|
||||
func (self *liquidationPriceState) DumpLendingBook(db Database) (DumpLendingBook, error) {
|
||||
result := DumpLendingBook{Volume: self.Volume(), LendingBooks: map[common.Hash]DumpOrderList{}}
|
||||
it := trie.NewIterator(self.getTrie(db).NodeIterator(nil))
|
||||
func (l *liquidationPriceState) DumpLendingBook(db Database) (DumpLendingBook, error) {
|
||||
result := DumpLendingBook{Volume: l.Volume(), LendingBooks: map[common.Hash]DumpOrderList{}}
|
||||
it := trie.NewIterator(l.getTrie(db).NodeIterator(nil))
|
||||
for it.Next() {
|
||||
lendingBook := common.BytesToHash(it.Key)
|
||||
if common.EmptyHash(lendingBook) {
|
||||
continue
|
||||
}
|
||||
if _, exist := self.stateLendingBooks[lendingBook]; exist {
|
||||
if _, exist := l.stateLendingBooks[lendingBook]; exist {
|
||||
continue
|
||||
} else {
|
||||
var data orderList
|
||||
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
|
||||
return result, fmt.Errorf("Failed to decode state lending book orderbook : %s ,liquidation price :%s , lendingBook : %s ,err : %v", self.orderBook, self.liquidationPrice, lendingBook, err)
|
||||
return result, fmt.Errorf("failed to decode state lending book orderbook: %s, liquidation price: %s , lendingBook: %s , err: %v", l.orderBook, l.liquidationPrice, lendingBook, err)
|
||||
}
|
||||
stateLendingBook := newStateLendingBook(self.orderBook, self.liquidationPrice, lendingBook, data, nil)
|
||||
stateLendingBook := newStateLendingBook(l.orderBook, l.liquidationPrice, lendingBook, data, nil)
|
||||
result.LendingBooks[lendingBook] = stateLendingBook.DumpOrderList(db)
|
||||
}
|
||||
}
|
||||
for lendingBook, stateLendingBook := range self.stateLendingBooks {
|
||||
for lendingBook, stateLendingBook := range l.stateLendingBooks {
|
||||
if !common.EmptyHash(lendingBook) {
|
||||
result.LendingBooks[lendingBook] = stateLendingBook.DumpOrderList(db)
|
||||
}
|
||||
|
|
@ -332,13 +333,13 @@ func (self *liquidationPriceState) DumpLendingBook(db Database) (DumpLendingBook
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) DumpLiquidationPriceTrie(orderBook common.Hash) (map[*big.Int]DumpLendingBook, error) {
|
||||
exhangeObject := self.getStateExchangeObject(orderBook)
|
||||
func (t *TradingStateDB) DumpLiquidationPriceTrie(orderBook common.Hash) (map[*big.Int]DumpLendingBook, error) {
|
||||
exhangeObject := t.getStateExchangeObject(orderBook)
|
||||
if exhangeObject == nil {
|
||||
return nil, fmt.Errorf("Order book not found orderBook : %v ", orderBook.Hex())
|
||||
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
|
||||
}
|
||||
mapResult := map[*big.Int]DumpLendingBook{}
|
||||
it := trie.NewIterator(exhangeObject.getLiquidationPriceTrie(self.db).NodeIterator(nil))
|
||||
it := trie.NewIterator(exhangeObject.getLiquidationPriceTrie(t.db).NodeIterator(nil))
|
||||
for it.Next() {
|
||||
priceHash := common.BytesToHash(it.Key)
|
||||
if common.EmptyHash(priceHash) {
|
||||
|
|
@ -350,10 +351,10 @@ func (self *TradingStateDB) DumpLiquidationPriceTrie(orderBook common.Hash) (map
|
|||
} else {
|
||||
var data orderList
|
||||
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
|
||||
return nil, fmt.Errorf("Fail when decode order iist orderBook : %v ,price :%v ", orderBook.Hex(), price)
|
||||
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , price : %v", orderBook.Hex(), price)
|
||||
}
|
||||
liquidationPriceState := newLiquidationPriceState(self, orderBook, priceHash, data, nil)
|
||||
dumpLendingBook, err := liquidationPriceState.DumpLendingBook(self.db)
|
||||
liquidationPriceState := newLiquidationPriceState(t, orderBook, priceHash, data, nil)
|
||||
dumpLendingBook, err := liquidationPriceState.DumpLendingBook(t.db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -362,7 +363,7 @@ func (self *TradingStateDB) DumpLiquidationPriceTrie(orderBook common.Hash) (map
|
|||
}
|
||||
for priceHash, liquidationPriceState := range exhangeObject.liquidationPriceStates {
|
||||
if liquidationPriceState.Volume().Sign() > 0 {
|
||||
dumpLendingBook, err := liquidationPriceState.DumpLendingBook(self.db)
|
||||
dumpLendingBook, err := liquidationPriceState.DumpLendingBook(t.db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ func GetAllTradingPairs(statedb *state.StateDB) (map[common.Hash]bool, error) {
|
|||
toTokenSlot := new(big.Int).Add(locBig, RelayerStructMappingSlot["_toTokens"])
|
||||
toTokenLength := statedb.GetState(common.HexToAddress(common.RelayerRegistrationSMC), common.BigToHash(toTokenSlot)).Big().Uint64()
|
||||
if toTokenLength != fromTokenLength {
|
||||
return map[common.Hash]bool{}, fmt.Errorf("Invalid length from token & to toke : from :%d , to :%d ", fromTokenLength, toTokenLength)
|
||||
return map[common.Hash]bool{}, fmt.Errorf("invalid length from token & to token: from :%d , to :%d ", fromTokenLength, toTokenLength)
|
||||
}
|
||||
fromTokens := []common.Address{}
|
||||
fromTokenSlotHash := common.BytesToHash(fromTokenSlot.Bytes())
|
||||
|
|
@ -279,7 +279,7 @@ func CheckAddTokenBalance(addr common.Address, value *big.Int, token common.Addr
|
|||
newBalance := new(big.Int).Add(balance, value)
|
||||
log.Debug("CheckAddTokenBalance settle balance: ADD TOKEN BALANCE ", "token", token.String(), "address", addr.String(), "balance", balance, "value", value, "newBalance", newBalance)
|
||||
if common.BigToHash(newBalance).Big().Cmp(newBalance) != 0 {
|
||||
return nil, fmt.Errorf("Overflow when try add token balance , max is 2^256 , balance : %v , value:%v ", balance, value)
|
||||
return nil, fmt.Errorf("overflow when try add token balance , max is 2^256 , balance : %v , value : %v", balance, value)
|
||||
} else {
|
||||
return newBalance, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,59 +65,59 @@ func newStateLendingBook(orderBook common.Hash, price common.Hash, lendingBook c
|
|||
}
|
||||
}
|
||||
|
||||
func (self *stateLendingBook) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, self.data)
|
||||
func (s *stateLendingBook) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, s.data)
|
||||
}
|
||||
|
||||
func (self *stateLendingBook) setError(err error) {
|
||||
if self.dbErr == nil {
|
||||
self.dbErr = err
|
||||
func (s *stateLendingBook) setError(err error) {
|
||||
if s.dbErr == nil {
|
||||
s.dbErr = err
|
||||
}
|
||||
}
|
||||
|
||||
func (self *stateLendingBook) getTrie(db Database) Trie {
|
||||
if self.trie == nil {
|
||||
func (s *stateLendingBook) getTrie(db Database) Trie {
|
||||
if s.trie == nil {
|
||||
var err error
|
||||
self.trie, err = db.OpenStorageTrie(self.lendingBook, self.data.Root)
|
||||
s.trie, err = db.OpenStorageTrie(s.lendingBook, s.data.Root)
|
||||
if err != nil {
|
||||
self.trie, _ = db.OpenStorageTrie(self.price, EmptyHash)
|
||||
self.setError(fmt.Errorf("can't create storage trie: %v", err))
|
||||
s.trie, _ = db.OpenStorageTrie(s.price, EmptyHash)
|
||||
s.setError(fmt.Errorf("can't create storage trie: %v", err))
|
||||
}
|
||||
}
|
||||
return self.trie
|
||||
return s.trie
|
||||
}
|
||||
|
||||
func (self *stateLendingBook) Exist(db Database, lendingId common.Hash) bool {
|
||||
amount, exists := self.cachedStorage[lendingId]
|
||||
func (s *stateLendingBook) Exist(db Database, lendingId common.Hash) bool {
|
||||
amount, exists := s.cachedStorage[lendingId]
|
||||
if exists {
|
||||
return true
|
||||
}
|
||||
// Load from DB in case it is missing.
|
||||
enc, err := self.getTrie(db).TryGet(lendingId[:])
|
||||
enc, err := s.getTrie(db).TryGet(lendingId[:])
|
||||
if err != nil {
|
||||
self.setError(err)
|
||||
s.setError(err)
|
||||
return false
|
||||
}
|
||||
if len(enc) > 0 {
|
||||
_, content, _, err := rlp.Split(enc)
|
||||
if err != nil {
|
||||
self.setError(err)
|
||||
s.setError(err)
|
||||
}
|
||||
amount.SetBytes(content)
|
||||
}
|
||||
if (amount != common.Hash{}) {
|
||||
self.cachedStorage[lendingId] = amount
|
||||
s.cachedStorage[lendingId] = amount
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *stateLendingBook) getAllTradeIds(db Database) []common.Hash {
|
||||
func (s *stateLendingBook) getAllTradeIds(db Database) []common.Hash {
|
||||
tradeIds := []common.Hash{}
|
||||
lendingBookTrie := self.getTrie(db)
|
||||
lendingBookTrie := s.getTrie(db)
|
||||
if lendingBookTrie == nil {
|
||||
return tradeIds
|
||||
}
|
||||
for id, value := range self.cachedStorage {
|
||||
for id, value := range s.cachedStorage {
|
||||
if !common.EmptyHash(value) {
|
||||
tradeIds = append(tradeIds, id)
|
||||
}
|
||||
|
|
@ -125,7 +125,7 @@ func (self *stateLendingBook) getAllTradeIds(db Database) []common.Hash {
|
|||
orderListIt := trie.NewIterator(lendingBookTrie.NodeIterator(nil))
|
||||
for orderListIt.Next() {
|
||||
id := common.BytesToHash(orderListIt.Key)
|
||||
if _, exist := self.cachedStorage[id]; exist {
|
||||
if _, exist := s.cachedStorage[id]; exist {
|
||||
continue
|
||||
}
|
||||
tradeIds = append(tradeIds, id)
|
||||
|
|
@ -133,83 +133,83 @@ func (self *stateLendingBook) getAllTradeIds(db Database) []common.Hash {
|
|||
return tradeIds
|
||||
}
|
||||
|
||||
func (self *stateLendingBook) insertTradingId(db Database, tradeId common.Hash) {
|
||||
self.setTradingId(tradeId, tradeId)
|
||||
self.setError(self.getTrie(db).TryUpdate(tradeId[:], tradeId[:]))
|
||||
func (s *stateLendingBook) insertTradingId(db Database, tradeId common.Hash) {
|
||||
s.setTradingId(tradeId, tradeId)
|
||||
s.setError(s.getTrie(db).TryUpdate(tradeId[:], tradeId[:]))
|
||||
}
|
||||
|
||||
func (self *stateLendingBook) removeTradingId(db Database, tradeId common.Hash) {
|
||||
tr := self.getTrie(db)
|
||||
self.setError(tr.TryDelete(tradeId[:]))
|
||||
self.setTradingId(tradeId, EmptyHash)
|
||||
func (s *stateLendingBook) removeTradingId(db Database, tradeId common.Hash) {
|
||||
tr := s.getTrie(db)
|
||||
s.setError(tr.TryDelete(tradeId[:]))
|
||||
s.setTradingId(tradeId, EmptyHash)
|
||||
}
|
||||
|
||||
func (self *stateLendingBook) setTradingId(tradeId common.Hash, value common.Hash) {
|
||||
self.cachedStorage[tradeId] = value
|
||||
self.dirtyStorage[tradeId] = value
|
||||
func (s *stateLendingBook) setTradingId(tradeId common.Hash, value common.Hash) {
|
||||
s.cachedStorage[tradeId] = value
|
||||
s.dirtyStorage[tradeId] = value
|
||||
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.lendingBook)
|
||||
self.onDirty = nil
|
||||
if s.onDirty != nil {
|
||||
s.onDirty(s.lendingBook)
|
||||
s.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *stateLendingBook) updateTrie(db Database) Trie {
|
||||
tr := self.getTrie(db)
|
||||
for key, value := range self.dirtyStorage {
|
||||
delete(self.dirtyStorage, key)
|
||||
func (s *stateLendingBook) updateTrie(db Database) Trie {
|
||||
tr := s.getTrie(db)
|
||||
for key, value := range s.dirtyStorage {
|
||||
delete(s.dirtyStorage, key)
|
||||
if value == EmptyHash {
|
||||
self.setError(tr.TryDelete(key[:]))
|
||||
s.setError(tr.TryDelete(key[:]))
|
||||
continue
|
||||
}
|
||||
v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00"))
|
||||
self.setError(tr.TryUpdate(key[:], v))
|
||||
s.setError(tr.TryUpdate(key[:], v))
|
||||
}
|
||||
return tr
|
||||
}
|
||||
|
||||
func (self *stateLendingBook) updateRoot(db Database) error {
|
||||
self.updateTrie(db)
|
||||
if self.dbErr != nil {
|
||||
return self.dbErr
|
||||
func (s *stateLendingBook) updateRoot(db Database) error {
|
||||
s.updateTrie(db)
|
||||
if s.dbErr != nil {
|
||||
return s.dbErr
|
||||
}
|
||||
root, err := self.trie.Commit(nil)
|
||||
root, err := s.trie.Commit(nil)
|
||||
if err == nil {
|
||||
self.data.Root = root
|
||||
s.data.Root = root
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *stateLendingBook) deepCopy(db *TradingStateDB, onDirty func(price common.Hash)) *stateLendingBook {
|
||||
stateLendingBook := newStateLendingBook(self.lendingBook, self.orderBook, self.price, self.data, onDirty)
|
||||
if self.trie != nil {
|
||||
stateLendingBook.trie = db.db.CopyTrie(self.trie)
|
||||
func (s *stateLendingBook) deepCopy(db *TradingStateDB, onDirty func(price common.Hash)) *stateLendingBook {
|
||||
stateLendingBook := newStateLendingBook(s.lendingBook, s.orderBook, s.price, s.data, onDirty)
|
||||
if s.trie != nil {
|
||||
stateLendingBook.trie = db.db.CopyTrie(s.trie)
|
||||
}
|
||||
for key, value := range self.dirtyStorage {
|
||||
for key, value := range s.dirtyStorage {
|
||||
stateLendingBook.dirtyStorage[key] = value
|
||||
}
|
||||
for key, value := range self.cachedStorage {
|
||||
for key, value := range s.cachedStorage {
|
||||
stateLendingBook.cachedStorage[key] = value
|
||||
}
|
||||
return stateLendingBook
|
||||
}
|
||||
|
||||
func (c *stateLendingBook) AddVolume(amount *big.Int) {
|
||||
c.setVolume(new(big.Int).Add(c.data.Volume, amount))
|
||||
func (s *stateLendingBook) AddVolume(amount *big.Int) {
|
||||
s.setVolume(new(big.Int).Add(s.data.Volume, amount))
|
||||
}
|
||||
|
||||
func (c *stateLendingBook) subVolume(amount *big.Int) {
|
||||
c.setVolume(new(big.Int).Sub(c.data.Volume, amount))
|
||||
func (s *stateLendingBook) subVolume(amount *big.Int) {
|
||||
s.setVolume(new(big.Int).Sub(s.data.Volume, amount))
|
||||
}
|
||||
|
||||
func (self *stateLendingBook) setVolume(volume *big.Int) {
|
||||
self.data.Volume = volume
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.lendingBook)
|
||||
self.onDirty = nil
|
||||
func (s *stateLendingBook) setVolume(volume *big.Int) {
|
||||
s.data.Volume = volume
|
||||
if s.onDirty != nil {
|
||||
s.onDirty(s.lendingBook)
|
||||
s.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *stateLendingBook) Volume() *big.Int {
|
||||
return self.data.Volume
|
||||
func (s *stateLendingBook) Volume() *big.Int {
|
||||
return s.data.Volume
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,54 +68,54 @@ func newLiquidationPriceState(db *TradingStateDB, orderBook common.Hash, price c
|
|||
}
|
||||
|
||||
// EncodeRLP implements rlp.Encoder.
|
||||
func (c *liquidationPriceState) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, c.data)
|
||||
func (l *liquidationPriceState) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, l.data)
|
||||
}
|
||||
|
||||
// setError remembers the first non-nil error it is called with.
|
||||
func (self *liquidationPriceState) setError(err error) {
|
||||
if self.dbErr == nil {
|
||||
self.dbErr = err
|
||||
func (l *liquidationPriceState) setError(err error) {
|
||||
if l.dbErr == nil {
|
||||
l.dbErr = err
|
||||
}
|
||||
}
|
||||
|
||||
func (self *liquidationPriceState) MarkStateLendingBookDirty(price common.Hash) {
|
||||
self.stateLendingBooksDirty[price] = struct{}{}
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.liquidationPrice)
|
||||
self.onDirty = nil
|
||||
func (l *liquidationPriceState) MarkStateLendingBookDirty(price common.Hash) {
|
||||
l.stateLendingBooksDirty[price] = struct{}{}
|
||||
if l.onDirty != nil {
|
||||
l.onDirty(l.liquidationPrice)
|
||||
l.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *liquidationPriceState) createLendingBook(db Database, lendingBook common.Hash) (newobj *stateLendingBook) {
|
||||
newobj = newStateLendingBook(self.orderBook, self.liquidationPrice, lendingBook, orderList{Volume: Zero}, self.MarkStateLendingBookDirty)
|
||||
self.stateLendingBooks[lendingBook] = newobj
|
||||
self.stateLendingBooksDirty[lendingBook] = struct{}{}
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.liquidationPrice)
|
||||
self.onDirty = nil
|
||||
func (l *liquidationPriceState) createLendingBook(db Database, lendingBook common.Hash) (newobj *stateLendingBook) {
|
||||
newobj = newStateLendingBook(l.orderBook, l.liquidationPrice, lendingBook, orderList{Volume: Zero}, l.MarkStateLendingBookDirty)
|
||||
l.stateLendingBooks[lendingBook] = newobj
|
||||
l.stateLendingBooksDirty[lendingBook] = struct{}{}
|
||||
if l.onDirty != nil {
|
||||
l.onDirty(l.liquidationPrice)
|
||||
l.onDirty = nil
|
||||
}
|
||||
return newobj
|
||||
}
|
||||
|
||||
func (self *liquidationPriceState) getTrie(db Database) Trie {
|
||||
if self.trie == nil {
|
||||
func (l *liquidationPriceState) getTrie(db Database) Trie {
|
||||
if l.trie == nil {
|
||||
var err error
|
||||
self.trie, err = db.OpenStorageTrie(self.liquidationPrice, self.data.Root)
|
||||
l.trie, err = db.OpenStorageTrie(l.liquidationPrice, l.data.Root)
|
||||
if err != nil {
|
||||
self.trie, _ = db.OpenStorageTrie(self.liquidationPrice, EmptyHash)
|
||||
self.setError(fmt.Errorf("can't create storage trie: %v", err))
|
||||
l.trie, _ = db.OpenStorageTrie(l.liquidationPrice, EmptyHash)
|
||||
l.setError(fmt.Errorf("can't create storage trie: %v", err))
|
||||
}
|
||||
}
|
||||
return self.trie
|
||||
return l.trie
|
||||
}
|
||||
|
||||
func (self *liquidationPriceState) updateTrie(db Database) Trie {
|
||||
tr := self.getTrie(db)
|
||||
for lendingId, stateObject := range self.stateLendingBooks {
|
||||
delete(self.stateLendingBooksDirty, lendingId)
|
||||
func (l *liquidationPriceState) updateTrie(db Database) Trie {
|
||||
tr := l.getTrie(db)
|
||||
for lendingId, stateObject := range l.stateLendingBooks {
|
||||
delete(l.stateLendingBooksDirty, lendingId)
|
||||
if stateObject.empty() {
|
||||
self.setError(tr.TryDelete(lendingId[:]))
|
||||
l.setError(tr.TryDelete(lendingId[:]))
|
||||
continue
|
||||
}
|
||||
err := stateObject.updateRoot(db)
|
||||
|
|
@ -125,17 +125,17 @@ func (self *liquidationPriceState) updateTrie(db Database) Trie {
|
|||
|
||||
// Encoding []byte cannot fail, ok to ignore the error.
|
||||
v, _ := rlp.EncodeToBytes(stateObject)
|
||||
self.setError(tr.TryUpdate(lendingId[:], v))
|
||||
l.setError(tr.TryUpdate(lendingId[:], v))
|
||||
}
|
||||
return tr
|
||||
}
|
||||
|
||||
func (self *liquidationPriceState) updateRoot(db Database) error {
|
||||
self.updateTrie(db)
|
||||
if self.dbErr != nil {
|
||||
return self.dbErr
|
||||
func (l *liquidationPriceState) updateRoot(db Database) error {
|
||||
l.updateTrie(db)
|
||||
if l.dbErr != nil {
|
||||
return l.dbErr
|
||||
}
|
||||
root, err := self.trie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
root, err := l.trie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
var orderList orderList
|
||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||
return nil
|
||||
|
|
@ -146,57 +146,57 @@ func (self *liquidationPriceState) updateRoot(db Database) error {
|
|||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
self.data.Root = root
|
||||
l.data.Root = root
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *liquidationPriceState) deepCopy(db *TradingStateDB, onDirty func(liquidationPrice common.Hash)) *liquidationPriceState {
|
||||
stateOrderList := newLiquidationPriceState(db, self.orderBook, self.liquidationPrice, self.data, onDirty)
|
||||
if self.trie != nil {
|
||||
stateOrderList.trie = db.db.CopyTrie(self.trie)
|
||||
func (l *liquidationPriceState) deepCopy(db *TradingStateDB, onDirty func(liquidationPrice common.Hash)) *liquidationPriceState {
|
||||
stateOrderList := newLiquidationPriceState(db, l.orderBook, l.liquidationPrice, l.data, onDirty)
|
||||
if l.trie != nil {
|
||||
stateOrderList.trie = db.db.CopyTrie(l.trie)
|
||||
}
|
||||
for key, value := range self.stateLendingBooks {
|
||||
stateOrderList.stateLendingBooks[key] = value.deepCopy(db, self.MarkStateLendingBookDirty)
|
||||
for key, value := range l.stateLendingBooks {
|
||||
stateOrderList.stateLendingBooks[key] = value.deepCopy(db, l.MarkStateLendingBookDirty)
|
||||
}
|
||||
for key, value := range self.stateLendingBooksDirty {
|
||||
for key, value := range l.stateLendingBooksDirty {
|
||||
stateOrderList.stateLendingBooksDirty[key] = value
|
||||
}
|
||||
return stateOrderList
|
||||
}
|
||||
|
||||
// Retrieve a state object given my the address. Returns nil if not found.
|
||||
func (self *liquidationPriceState) getStateLendingBook(db Database, lendingBook common.Hash) (stateObject *stateLendingBook) {
|
||||
func (l *liquidationPriceState) getStateLendingBook(db Database, lendingBook common.Hash) (stateObject *stateLendingBook) {
|
||||
// Prefer 'live' objects.
|
||||
if obj := self.stateLendingBooks[lendingBook]; obj != nil {
|
||||
if obj := l.stateLendingBooks[lendingBook]; obj != nil {
|
||||
return obj
|
||||
}
|
||||
|
||||
// Load the object from the database.
|
||||
enc, err := self.getTrie(db).TryGet(lendingBook[:])
|
||||
enc, err := l.getTrie(db).TryGet(lendingBook[:])
|
||||
if len(enc) == 0 {
|
||||
self.setError(err)
|
||||
l.setError(err)
|
||||
return nil
|
||||
}
|
||||
var data orderList
|
||||
if err := rlp.DecodeBytes(enc, &data); err != nil {
|
||||
log.Error("Failed to decode state lending book ", "orderbook", self.orderBook, "liquidation price", self.liquidationPrice, "lendingBook", lendingBook, "err", err)
|
||||
log.Error("Failed to decode state lending book ", "orderbook", l.orderBook, "liquidation price", l.liquidationPrice, "lendingBook", lendingBook, "err", err)
|
||||
return nil
|
||||
}
|
||||
// Insert into the live set.
|
||||
obj := newStateLendingBook(self.orderBook, self.liquidationPrice, lendingBook, data, self.MarkStateLendingBookDirty)
|
||||
self.stateLendingBooks[lendingBook] = obj
|
||||
obj := newStateLendingBook(l.orderBook, l.liquidationPrice, lendingBook, data, l.MarkStateLendingBookDirty)
|
||||
l.stateLendingBooks[lendingBook] = obj
|
||||
return obj
|
||||
}
|
||||
|
||||
func (self *liquidationPriceState) getAllLiquidationData(db Database) map[common.Hash][]common.Hash {
|
||||
func (l *liquidationPriceState) getAllLiquidationData(db Database) map[common.Hash][]common.Hash {
|
||||
liquidationData := map[common.Hash][]common.Hash{}
|
||||
lendingBookTrie := self.getTrie(db)
|
||||
lendingBookTrie := l.getTrie(db)
|
||||
if lendingBookTrie == nil {
|
||||
return liquidationData
|
||||
}
|
||||
lendingBooks := []common.Hash{}
|
||||
for id, stateLendingBook := range self.stateLendingBooks {
|
||||
for id, stateLendingBook := range l.stateLendingBooks {
|
||||
if !stateLendingBook.empty() {
|
||||
lendingBooks = append(lendingBooks, id)
|
||||
}
|
||||
|
|
@ -204,13 +204,13 @@ func (self *liquidationPriceState) getAllLiquidationData(db Database) map[common
|
|||
lendingBookListIt := trie.NewIterator(lendingBookTrie.NodeIterator(nil))
|
||||
for lendingBookListIt.Next() {
|
||||
id := common.BytesToHash(lendingBookListIt.Key)
|
||||
if _, exist := self.stateLendingBooks[id]; exist {
|
||||
if _, exist := l.stateLendingBooks[id]; exist {
|
||||
continue
|
||||
}
|
||||
lendingBooks = append(lendingBooks, id)
|
||||
}
|
||||
for _, lendingBook := range lendingBooks {
|
||||
stateLendingBook := self.getStateLendingBook(db, lendingBook)
|
||||
stateLendingBook := l.getStateLendingBook(db, lendingBook)
|
||||
if stateLendingBook != nil {
|
||||
liquidationData[lendingBook] = stateLendingBook.getAllTradeIds(db)
|
||||
}
|
||||
|
|
@ -218,22 +218,22 @@ func (self *liquidationPriceState) getAllLiquidationData(db Database) map[common
|
|||
return liquidationData
|
||||
}
|
||||
|
||||
func (c *liquidationPriceState) AddVolume(amount *big.Int) {
|
||||
c.setVolume(new(big.Int).Add(c.data.Volume, amount))
|
||||
func (l *liquidationPriceState) AddVolume(amount *big.Int) {
|
||||
l.setVolume(new(big.Int).Add(l.data.Volume, amount))
|
||||
}
|
||||
|
||||
func (c *liquidationPriceState) subVolume(amount *big.Int) {
|
||||
c.setVolume(new(big.Int).Sub(c.data.Volume, amount))
|
||||
}
|
||||
|
||||
func (self *liquidationPriceState) setVolume(volume *big.Int) {
|
||||
self.data.Volume = volume
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.liquidationPrice)
|
||||
self.onDirty = nil
|
||||
func (l *liquidationPriceState) setVolume(volume *big.Int) {
|
||||
l.data.Volume = volume
|
||||
if l.onDirty != nil {
|
||||
l.onDirty(l.liquidationPrice)
|
||||
l.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *liquidationPriceState) Volume() *big.Int {
|
||||
return self.data.Volume
|
||||
func (l *liquidationPriceState) Volume() *big.Int {
|
||||
return l.data.Volume
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,23 +53,23 @@ func newStateOrderItem(orderBook common.Hash, orderId common.Hash, data OrderIte
|
|||
}
|
||||
|
||||
// EncodeRLP implements rlp.Encoder.
|
||||
func (c *stateOrderItem) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, c.data)
|
||||
func (s *stateOrderItem) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, s.data)
|
||||
}
|
||||
|
||||
func (self *stateOrderItem) deepCopy(onDirty func(orderId common.Hash)) *stateOrderItem {
|
||||
stateOrderList := newStateOrderItem(self.orderBook, self.orderId, self.data, onDirty)
|
||||
func (s *stateOrderItem) deepCopy(onDirty func(orderId common.Hash)) *stateOrderItem {
|
||||
stateOrderList := newStateOrderItem(s.orderBook, s.orderId, s.data, onDirty)
|
||||
return stateOrderList
|
||||
}
|
||||
|
||||
func (self *stateOrderItem) setVolume(volume *big.Int) {
|
||||
self.data.Quantity = volume
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.orderId)
|
||||
self.onDirty = nil
|
||||
func (s *stateOrderItem) setVolume(volume *big.Int) {
|
||||
s.data.Quantity = volume
|
||||
if s.onDirty != nil {
|
||||
s.onDirty(s.orderId)
|
||||
s.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *stateOrderItem) Quantity() *big.Int {
|
||||
return self.data.Quantity
|
||||
func (s *stateOrderItem) Quantity() *big.Int {
|
||||
return s.data.Quantity
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,14 +75,14 @@ func newStateOrderList(db *TradingStateDB, orderType string, orderBook common.Ha
|
|||
}
|
||||
|
||||
// EncodeRLP implements rlp.Encoder.
|
||||
func (c *stateOrderList) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, c.data)
|
||||
func (s *stateOrderList) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, s.data)
|
||||
}
|
||||
|
||||
// setError remembers the first non-nil error it is called with.
|
||||
func (self *stateOrderList) setError(err error) {
|
||||
if self.dbErr == nil {
|
||||
self.dbErr = err
|
||||
func (s *stateOrderList) setError(err error) {
|
||||
if s.dbErr == nil {
|
||||
s.dbErr = err
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -99,90 +99,90 @@ func (c *stateOrderList) getTrie(db Database) Trie {
|
|||
}
|
||||
|
||||
// GetState returns a value in orderId storage.
|
||||
func (self *stateOrderList) GetOrderAmount(db Database, orderId common.Hash) common.Hash {
|
||||
amount, exists := self.cachedStorage[orderId]
|
||||
func (s *stateOrderList) GetOrderAmount(db Database, orderId common.Hash) common.Hash {
|
||||
amount, exists := s.cachedStorage[orderId]
|
||||
if exists {
|
||||
return amount
|
||||
}
|
||||
// Load from DB in case it is missing.
|
||||
enc, err := self.getTrie(db).TryGet(orderId[:])
|
||||
enc, err := s.getTrie(db).TryGet(orderId[:])
|
||||
if err != nil {
|
||||
self.setError(err)
|
||||
s.setError(err)
|
||||
return EmptyHash
|
||||
}
|
||||
if len(enc) > 0 {
|
||||
_, content, _, err := rlp.Split(enc)
|
||||
if err != nil {
|
||||
self.setError(err)
|
||||
s.setError(err)
|
||||
}
|
||||
amount.SetBytes(content)
|
||||
}
|
||||
if (amount != common.Hash{}) {
|
||||
self.cachedStorage[orderId] = amount
|
||||
s.cachedStorage[orderId] = amount
|
||||
}
|
||||
return amount
|
||||
}
|
||||
|
||||
// SetState updates a value in orderId storage.
|
||||
func (self *stateOrderList) insertOrderItem(db Database, orderId common.Hash, amount common.Hash) {
|
||||
self.setOrderItem(orderId, amount)
|
||||
self.setError(self.getTrie(db).TryUpdate(orderId[:], amount[:]))
|
||||
func (s *stateOrderList) insertOrderItem(db Database, orderId common.Hash, amount common.Hash) {
|
||||
s.setOrderItem(orderId, amount)
|
||||
s.setError(s.getTrie(db).TryUpdate(orderId[:], amount[:]))
|
||||
}
|
||||
|
||||
// SetState updates a value in orderId storage.
|
||||
func (self *stateOrderList) removeOrderItem(db Database, orderId common.Hash) {
|
||||
tr := self.getTrie(db)
|
||||
self.setError(tr.TryDelete(orderId[:]))
|
||||
self.setOrderItem(orderId, EmptyHash)
|
||||
func (s *stateOrderList) removeOrderItem(db Database, orderId common.Hash) {
|
||||
tr := s.getTrie(db)
|
||||
s.setError(tr.TryDelete(orderId[:]))
|
||||
s.setOrderItem(orderId, EmptyHash)
|
||||
}
|
||||
|
||||
func (self *stateOrderList) setOrderItem(orderId common.Hash, amount common.Hash) {
|
||||
self.cachedStorage[orderId] = amount
|
||||
self.dirtyStorage[orderId] = amount
|
||||
func (s *stateOrderList) setOrderItem(orderId common.Hash, amount common.Hash) {
|
||||
s.cachedStorage[orderId] = amount
|
||||
s.dirtyStorage[orderId] = amount
|
||||
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Price())
|
||||
self.onDirty = nil
|
||||
if s.onDirty != nil {
|
||||
s.onDirty(s.Price())
|
||||
s.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
// updateAskTrie writes cached storage modifications into the object's storage trie.
|
||||
func (self *stateOrderList) updateTrie(db Database) Trie {
|
||||
tr := self.getTrie(db)
|
||||
for orderId, amount := range self.dirtyStorage {
|
||||
delete(self.dirtyStorage, orderId)
|
||||
func (s *stateOrderList) updateTrie(db Database) Trie {
|
||||
tr := s.getTrie(db)
|
||||
for orderId, amount := range s.dirtyStorage {
|
||||
delete(s.dirtyStorage, orderId)
|
||||
if amount == EmptyHash {
|
||||
self.setError(tr.TryDelete(orderId[:]))
|
||||
s.setError(tr.TryDelete(orderId[:]))
|
||||
continue
|
||||
}
|
||||
v, _ := rlp.EncodeToBytes(bytes.TrimLeft(amount[:], "\x00"))
|
||||
self.setError(tr.TryUpdate(orderId[:], v))
|
||||
s.setError(tr.TryUpdate(orderId[:], v))
|
||||
}
|
||||
return tr
|
||||
}
|
||||
|
||||
// UpdateRoot sets the trie root to the current root orderId of
|
||||
func (self *stateOrderList) updateRoot(db Database) error {
|
||||
self.updateTrie(db)
|
||||
if self.dbErr != nil {
|
||||
return self.dbErr
|
||||
func (s *stateOrderList) updateRoot(db Database) error {
|
||||
s.updateTrie(db)
|
||||
if s.dbErr != nil {
|
||||
return s.dbErr
|
||||
}
|
||||
root, err := self.trie.Commit(nil)
|
||||
root, err := s.trie.Commit(nil)
|
||||
if err == nil {
|
||||
self.data.Root = root
|
||||
s.data.Root = root
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *stateOrderList) deepCopy(db *TradingStateDB, onDirty func(price common.Hash)) *stateOrderList {
|
||||
stateOrderList := newStateOrderList(db, self.orderType, self.orderBook, self.price, self.data, onDirty)
|
||||
if self.trie != nil {
|
||||
stateOrderList.trie = db.db.CopyTrie(self.trie)
|
||||
func (s *stateOrderList) deepCopy(db *TradingStateDB, onDirty func(price common.Hash)) *stateOrderList {
|
||||
stateOrderList := newStateOrderList(db, s.orderType, s.orderBook, s.price, s.data, onDirty)
|
||||
if s.trie != nil {
|
||||
stateOrderList.trie = db.db.CopyTrie(s.trie)
|
||||
}
|
||||
for orderId, amount := range self.dirtyStorage {
|
||||
for orderId, amount := range s.dirtyStorage {
|
||||
stateOrderList.dirtyStorage[orderId] = amount
|
||||
}
|
||||
for orderId, amount := range self.cachedStorage {
|
||||
for orderId, amount := range s.cachedStorage {
|
||||
stateOrderList.cachedStorage[orderId] = amount
|
||||
}
|
||||
return stateOrderList
|
||||
|
|
@ -190,29 +190,29 @@ func (self *stateOrderList) deepCopy(db *TradingStateDB, onDirty func(price comm
|
|||
|
||||
// AddVolume removes amount from c's balance.
|
||||
// It is used to add funds to the destination exchanges of a transfer.
|
||||
func (c *stateOrderList) AddVolume(amount *big.Int) {
|
||||
c.setVolume(new(big.Int).Add(c.data.Volume, amount))
|
||||
func (s *stateOrderList) AddVolume(amount *big.Int) {
|
||||
s.setVolume(new(big.Int).Add(s.data.Volume, amount))
|
||||
}
|
||||
|
||||
// AddVolume removes amount from c's balance.
|
||||
// It is used to add funds to the destination exchanges of a transfer.
|
||||
func (c *stateOrderList) subVolume(amount *big.Int) {
|
||||
c.setVolume(new(big.Int).Sub(c.data.Volume, amount))
|
||||
func (s *stateOrderList) subVolume(amount *big.Int) {
|
||||
s.setVolume(new(big.Int).Sub(s.data.Volume, amount))
|
||||
}
|
||||
|
||||
func (self *stateOrderList) setVolume(volume *big.Int) {
|
||||
self.data.Volume = volume
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.price)
|
||||
self.onDirty = nil
|
||||
func (s *stateOrderList) setVolume(volume *big.Int) {
|
||||
s.data.Volume = volume
|
||||
if s.onDirty != nil {
|
||||
s.onDirty(s.price)
|
||||
s.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the address of the contract/orderId
|
||||
func (c *stateOrderList) Price() common.Hash {
|
||||
return c.price
|
||||
func (s *stateOrderList) Price() common.Hash {
|
||||
return s.price
|
||||
}
|
||||
|
||||
func (self *stateOrderList) Volume() *big.Int {
|
||||
return self.data.Volume
|
||||
func (s *stateOrderList) Volume() *big.Int {
|
||||
return s.data.Volume
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,35 +66,35 @@ type tradingExchanges struct {
|
|||
}
|
||||
|
||||
// empty returns whether the orderId is considered empty.
|
||||
func (s *tradingExchanges) empty() bool {
|
||||
if s.data.Nonce != 0 {
|
||||
func (te *tradingExchanges) empty() bool {
|
||||
if te.data.Nonce != 0 {
|
||||
return false
|
||||
}
|
||||
if s.data.LendingCount != nil && s.data.LendingCount.Sign() > 0 {
|
||||
if te.data.LendingCount != nil && te.data.LendingCount.Sign() > 0 {
|
||||
return false
|
||||
}
|
||||
if s.data.LastPrice != nil && s.data.LastPrice.Sign() > 0 {
|
||||
if te.data.LastPrice != nil && te.data.LastPrice.Sign() > 0 {
|
||||
return false
|
||||
}
|
||||
if s.data.MediumPrice != nil && s.data.MediumPrice.Sign() > 0 {
|
||||
if te.data.MediumPrice != nil && te.data.MediumPrice.Sign() > 0 {
|
||||
return false
|
||||
}
|
||||
if s.data.MediumPriceBeforeEpoch != nil && s.data.MediumPriceBeforeEpoch.Sign() > 0 {
|
||||
if te.data.MediumPriceBeforeEpoch != nil && te.data.MediumPriceBeforeEpoch.Sign() > 0 {
|
||||
return false
|
||||
}
|
||||
if s.data.TotalQuantity != nil && s.data.TotalQuantity.Sign() > 0 {
|
||||
if te.data.TotalQuantity != nil && te.data.TotalQuantity.Sign() > 0 {
|
||||
return false
|
||||
}
|
||||
if !common.EmptyHash(s.data.AskRoot) {
|
||||
if !common.EmptyHash(te.data.AskRoot) {
|
||||
return false
|
||||
}
|
||||
if !common.EmptyHash(s.data.BidRoot) {
|
||||
if !common.EmptyHash(te.data.BidRoot) {
|
||||
return false
|
||||
}
|
||||
if !common.EmptyHash(s.data.OrderRoot) {
|
||||
if !common.EmptyHash(te.data.OrderRoot) {
|
||||
return false
|
||||
}
|
||||
if !common.EmptyHash(s.data.LiquidationPriceRoot) {
|
||||
if !common.EmptyHash(te.data.LiquidationPriceRoot) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
|
@ -119,46 +119,46 @@ func newStateExchanges(db *TradingStateDB, hash common.Hash, data tradingExchang
|
|||
}
|
||||
|
||||
// EncodeRLP implements rlp.Encoder.
|
||||
func (c *tradingExchanges) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, c.data)
|
||||
func (te *tradingExchanges) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, te.data)
|
||||
}
|
||||
|
||||
// setError remembers the first non-nil error it is called with.
|
||||
func (self *tradingExchanges) setError(err error) {
|
||||
if self.dbErr == nil {
|
||||
self.dbErr = err
|
||||
func (te *tradingExchanges) setError(err error) {
|
||||
if te.dbErr == nil {
|
||||
te.dbErr = err
|
||||
}
|
||||
}
|
||||
|
||||
func (c *tradingExchanges) getAsksTrie(db Database) Trie {
|
||||
if c.asksTrie == nil {
|
||||
func (te *tradingExchanges) getAsksTrie(db Database) Trie {
|
||||
if te.asksTrie == nil {
|
||||
var err error
|
||||
c.asksTrie, err = db.OpenStorageTrie(c.orderBookHash, c.data.AskRoot)
|
||||
te.asksTrie, err = db.OpenStorageTrie(te.orderBookHash, te.data.AskRoot)
|
||||
if err != nil {
|
||||
c.asksTrie, _ = db.OpenStorageTrie(c.orderBookHash, EmptyHash)
|
||||
c.setError(fmt.Errorf("can't create asks trie: %v", err))
|
||||
te.asksTrie, _ = db.OpenStorageTrie(te.orderBookHash, EmptyHash)
|
||||
te.setError(fmt.Errorf("can't create asks trie: %v", err))
|
||||
}
|
||||
}
|
||||
return c.asksTrie
|
||||
return te.asksTrie
|
||||
}
|
||||
|
||||
func (c *tradingExchanges) getOrdersTrie(db Database) Trie {
|
||||
if c.ordersTrie == nil {
|
||||
func (te *tradingExchanges) getOrdersTrie(db Database) Trie {
|
||||
if te.ordersTrie == nil {
|
||||
var err error
|
||||
c.ordersTrie, err = db.OpenStorageTrie(c.orderBookHash, c.data.OrderRoot)
|
||||
te.ordersTrie, err = db.OpenStorageTrie(te.orderBookHash, te.data.OrderRoot)
|
||||
if err != nil {
|
||||
c.ordersTrie, _ = db.OpenStorageTrie(c.orderBookHash, EmptyHash)
|
||||
c.setError(fmt.Errorf("can't create asks trie: %v", err))
|
||||
te.ordersTrie, _ = db.OpenStorageTrie(te.orderBookHash, EmptyHash)
|
||||
te.setError(fmt.Errorf("can't create asks trie: %v", err))
|
||||
}
|
||||
}
|
||||
return c.ordersTrie
|
||||
return te.ordersTrie
|
||||
}
|
||||
|
||||
func (c *tradingExchanges) getBestPriceAsksTrie(db Database) common.Hash {
|
||||
trie := c.getAsksTrie(db)
|
||||
func (te *tradingExchanges) getBestPriceAsksTrie(db Database) common.Hash {
|
||||
trie := te.getAsksTrie(db)
|
||||
encKey, encValue, err := trie.TryGetBestLeftKeyAndValue()
|
||||
if err != nil {
|
||||
log.Error("Failed find best price ask trie ", "orderbook", c.orderBookHash.Hex())
|
||||
log.Error("Failed find best price ask trie ", "orderbook", te.orderBookHash.Hex())
|
||||
return EmptyHash
|
||||
}
|
||||
if len(encKey) == 0 || len(encValue) == 0 {
|
||||
|
|
@ -166,23 +166,23 @@ func (c *tradingExchanges) getBestPriceAsksTrie(db Database) common.Hash {
|
|||
return EmptyHash
|
||||
}
|
||||
price := common.BytesToHash(encKey)
|
||||
if _, exit := c.stateAskObjects[price]; !exit {
|
||||
if _, exit := te.stateAskObjects[price]; !exit {
|
||||
var data orderList
|
||||
if err := rlp.DecodeBytes(encValue, &data); err != nil {
|
||||
log.Error("Failed to decode state get best ask trie", "err", err)
|
||||
return EmptyHash
|
||||
}
|
||||
obj := newStateOrderList(c.db, Bid, c.orderBookHash, price, data, c.MarkStateAskObjectDirty)
|
||||
c.stateAskObjects[price] = obj
|
||||
obj := newStateOrderList(te.db, Bid, te.orderBookHash, price, data, te.MarkStateAskObjectDirty)
|
||||
te.stateAskObjects[price] = obj
|
||||
}
|
||||
return common.BytesToHash(encKey)
|
||||
}
|
||||
|
||||
func (c *tradingExchanges) getBestBidsTrie(db Database) common.Hash {
|
||||
trie := c.getBidsTrie(db)
|
||||
func (te *tradingExchanges) getBestBidsTrie(db Database) common.Hash {
|
||||
trie := te.getBidsTrie(db)
|
||||
encKey, encValue, err := trie.TryGetBestRightKeyAndValue()
|
||||
if err != nil {
|
||||
log.Error("Failed find best price bid trie ", "orderbook", c.orderBookHash.Hex())
|
||||
log.Error("Failed find best price bid trie ", "orderbook", te.orderBookHash.Hex())
|
||||
return EmptyHash
|
||||
}
|
||||
if len(encKey) == 0 || len(encValue) == 0 {
|
||||
|
|
@ -190,27 +190,27 @@ func (c *tradingExchanges) getBestBidsTrie(db Database) common.Hash {
|
|||
return EmptyHash
|
||||
}
|
||||
price := common.BytesToHash(encKey)
|
||||
if _, exit := c.stateBidObjects[price]; !exit {
|
||||
if _, exit := te.stateBidObjects[price]; !exit {
|
||||
var data orderList
|
||||
if err := rlp.DecodeBytes(encValue, &data); err != nil {
|
||||
log.Error("Failed to decode state get best bid trie", "err", err)
|
||||
return EmptyHash
|
||||
}
|
||||
// Insert into the live set.
|
||||
obj := newStateOrderList(c.db, Bid, c.orderBookHash, price, data, c.MarkStateBidObjectDirty)
|
||||
c.stateBidObjects[price] = obj
|
||||
obj := newStateOrderList(te.db, Bid, te.orderBookHash, price, data, te.MarkStateBidObjectDirty)
|
||||
te.stateBidObjects[price] = obj
|
||||
}
|
||||
return common.BytesToHash(encKey)
|
||||
}
|
||||
|
||||
// updateAskTrie writes cached storage modifications into the object's storage trie.
|
||||
func (self *tradingExchanges) updateAsksTrie(db Database) Trie {
|
||||
tr := self.getAsksTrie(db)
|
||||
for price, orderList := range self.stateAskObjects {
|
||||
if _, isDirty := self.stateAskObjectsDirty[price]; isDirty {
|
||||
delete(self.stateAskObjectsDirty, price)
|
||||
func (te *tradingExchanges) updateAsksTrie(db Database) Trie {
|
||||
tr := te.getAsksTrie(db)
|
||||
for price, orderList := range te.stateAskObjects {
|
||||
if _, isDirty := te.stateAskObjectsDirty[price]; isDirty {
|
||||
delete(te.stateAskObjectsDirty, price)
|
||||
if orderList.empty() {
|
||||
self.setError(tr.TryDelete(price[:]))
|
||||
te.setError(tr.TryDelete(price[:]))
|
||||
continue
|
||||
}
|
||||
err := orderList.updateRoot(db)
|
||||
|
|
@ -219,7 +219,7 @@ func (self *tradingExchanges) updateAsksTrie(db Database) Trie {
|
|||
}
|
||||
// Encoding []byte cannot fail, ok to ignore the error.
|
||||
v, _ := rlp.EncodeToBytes(orderList)
|
||||
self.setError(tr.TryUpdate(price[:], v))
|
||||
te.setError(tr.TryUpdate(price[:], v))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -228,23 +228,23 @@ func (self *tradingExchanges) updateAsksTrie(db Database) Trie {
|
|||
|
||||
// CommitAskTrie the storage trie of the object to dwb.
|
||||
// This updates the trie root.
|
||||
func (self *tradingExchanges) updateAsksRoot(db Database) error {
|
||||
self.updateAsksTrie(db)
|
||||
if self.dbErr != nil {
|
||||
return self.dbErr
|
||||
func (te *tradingExchanges) updateAsksRoot(db Database) error {
|
||||
te.updateAsksTrie(db)
|
||||
if te.dbErr != nil {
|
||||
return te.dbErr
|
||||
}
|
||||
self.data.AskRoot = self.asksTrie.Hash()
|
||||
te.data.AskRoot = te.asksTrie.Hash()
|
||||
return nil
|
||||
}
|
||||
|
||||
// CommitAskTrie the storage trie of the object to dwb.
|
||||
// This updates the trie root.
|
||||
func (self *tradingExchanges) CommitAsksTrie(db Database) error {
|
||||
self.updateAsksTrie(db)
|
||||
if self.dbErr != nil {
|
||||
return self.dbErr
|
||||
func (te *tradingExchanges) CommitAsksTrie(db Database) error {
|
||||
te.updateAsksTrie(db)
|
||||
if te.dbErr != nil {
|
||||
return te.dbErr
|
||||
}
|
||||
root, err := self.asksTrie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
root, err := te.asksTrie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
var orderList orderList
|
||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||
return nil
|
||||
|
|
@ -255,31 +255,31 @@ func (self *tradingExchanges) CommitAsksTrie(db Database) error {
|
|||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
self.data.AskRoot = root
|
||||
te.data.AskRoot = root
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *tradingExchanges) getBidsTrie(db Database) Trie {
|
||||
if c.bidsTrie == nil {
|
||||
func (te *tradingExchanges) getBidsTrie(db Database) Trie {
|
||||
if te.bidsTrie == nil {
|
||||
var err error
|
||||
c.bidsTrie, err = db.OpenStorageTrie(c.orderBookHash, c.data.BidRoot)
|
||||
te.bidsTrie, err = db.OpenStorageTrie(te.orderBookHash, te.data.BidRoot)
|
||||
if err != nil {
|
||||
c.bidsTrie, _ = db.OpenStorageTrie(c.orderBookHash, EmptyHash)
|
||||
c.setError(fmt.Errorf("can't create bids trie: %v", err))
|
||||
te.bidsTrie, _ = db.OpenStorageTrie(te.orderBookHash, EmptyHash)
|
||||
te.setError(fmt.Errorf("can't create bids trie: %v", err))
|
||||
}
|
||||
}
|
||||
return c.bidsTrie
|
||||
return te.bidsTrie
|
||||
}
|
||||
|
||||
// updateAskTrie writes cached storage modifications into the object's storage trie.
|
||||
func (self *tradingExchanges) updateBidsTrie(db Database) Trie {
|
||||
tr := self.getBidsTrie(db)
|
||||
for price, orderList := range self.stateBidObjects {
|
||||
if _, isDirty := self.stateBidObjectsDirty[price]; isDirty {
|
||||
delete(self.stateBidObjectsDirty, price)
|
||||
func (te *tradingExchanges) updateBidsTrie(db Database) Trie {
|
||||
tr := te.getBidsTrie(db)
|
||||
for price, orderList := range te.stateBidObjects {
|
||||
if _, isDirty := te.stateBidObjectsDirty[price]; isDirty {
|
||||
delete(te.stateBidObjectsDirty, price)
|
||||
if orderList.empty() {
|
||||
self.setError(tr.TryDelete(price[:]))
|
||||
te.setError(tr.TryDelete(price[:]))
|
||||
continue
|
||||
}
|
||||
err := orderList.updateRoot(db)
|
||||
|
|
@ -288,25 +288,25 @@ func (self *tradingExchanges) updateBidsTrie(db Database) Trie {
|
|||
}
|
||||
// Encoding []byte cannot fail, ok to ignore the error.
|
||||
v, _ := rlp.EncodeToBytes(orderList)
|
||||
self.setError(tr.TryUpdate(price[:], v))
|
||||
te.setError(tr.TryUpdate(price[:], v))
|
||||
}
|
||||
}
|
||||
return tr
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) updateBidsRoot(db Database) {
|
||||
self.updateBidsTrie(db)
|
||||
self.data.BidRoot = self.bidsTrie.Hash()
|
||||
func (te *tradingExchanges) updateBidsRoot(db Database) {
|
||||
te.updateBidsTrie(db)
|
||||
te.data.BidRoot = te.bidsTrie.Hash()
|
||||
}
|
||||
|
||||
// CommitAskTrie the storage trie of the object to dwb.
|
||||
// This updates the trie root.
|
||||
func (self *tradingExchanges) CommitBidsTrie(db Database) error {
|
||||
self.updateBidsTrie(db)
|
||||
if self.dbErr != nil {
|
||||
return self.dbErr
|
||||
func (te *tradingExchanges) CommitBidsTrie(db Database) error {
|
||||
te.updateBidsTrie(db)
|
||||
if te.dbErr != nil {
|
||||
return te.dbErr
|
||||
}
|
||||
root, err := self.bidsTrie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
root, err := te.bidsTrie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
var orderList orderList
|
||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||
return nil
|
||||
|
|
@ -317,116 +317,116 @@ func (self *tradingExchanges) CommitBidsTrie(db Database) error {
|
|||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
self.data.BidRoot = root
|
||||
te.data.BidRoot = root
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) deepCopy(db *TradingStateDB, onDirty func(hash common.Hash)) *tradingExchanges {
|
||||
stateExchanges := newStateExchanges(db, self.orderBookHash, self.data, onDirty)
|
||||
if self.asksTrie != nil {
|
||||
stateExchanges.asksTrie = db.db.CopyTrie(self.asksTrie)
|
||||
func (te *tradingExchanges) deepCopy(db *TradingStateDB, onDirty func(hash common.Hash)) *tradingExchanges {
|
||||
stateExchanges := newStateExchanges(db, te.orderBookHash, te.data, onDirty)
|
||||
if te.asksTrie != nil {
|
||||
stateExchanges.asksTrie = db.db.CopyTrie(te.asksTrie)
|
||||
}
|
||||
if self.bidsTrie != nil {
|
||||
stateExchanges.bidsTrie = db.db.CopyTrie(self.bidsTrie)
|
||||
if te.bidsTrie != nil {
|
||||
stateExchanges.bidsTrie = db.db.CopyTrie(te.bidsTrie)
|
||||
}
|
||||
if self.ordersTrie != nil {
|
||||
stateExchanges.ordersTrie = db.db.CopyTrie(self.ordersTrie)
|
||||
if te.ordersTrie != nil {
|
||||
stateExchanges.ordersTrie = db.db.CopyTrie(te.ordersTrie)
|
||||
}
|
||||
for price, bidObject := range self.stateBidObjects {
|
||||
stateExchanges.stateBidObjects[price] = bidObject.deepCopy(db, self.MarkStateBidObjectDirty)
|
||||
for price, bidObject := range te.stateBidObjects {
|
||||
stateExchanges.stateBidObjects[price] = bidObject.deepCopy(db, te.MarkStateBidObjectDirty)
|
||||
}
|
||||
for price := range self.stateBidObjectsDirty {
|
||||
for price := range te.stateBidObjectsDirty {
|
||||
stateExchanges.stateBidObjectsDirty[price] = struct{}{}
|
||||
}
|
||||
for price, askObject := range self.stateAskObjects {
|
||||
stateExchanges.stateAskObjects[price] = askObject.deepCopy(db, self.MarkStateAskObjectDirty)
|
||||
for price, askObject := range te.stateAskObjects {
|
||||
stateExchanges.stateAskObjects[price] = askObject.deepCopy(db, te.MarkStateAskObjectDirty)
|
||||
}
|
||||
for price := range self.stateAskObjectsDirty {
|
||||
for price := range te.stateAskObjectsDirty {
|
||||
stateExchanges.stateAskObjectsDirty[price] = struct{}{}
|
||||
}
|
||||
for orderId, orderItem := range self.stateOrderObjects {
|
||||
stateExchanges.stateOrderObjects[orderId] = orderItem.deepCopy(self.MarkStateOrderObjectDirty)
|
||||
for orderId, orderItem := range te.stateOrderObjects {
|
||||
stateExchanges.stateOrderObjects[orderId] = orderItem.deepCopy(te.MarkStateOrderObjectDirty)
|
||||
}
|
||||
for orderId := range self.stateOrderObjectsDirty {
|
||||
for orderId := range te.stateOrderObjectsDirty {
|
||||
stateExchanges.stateOrderObjectsDirty[orderId] = struct{}{}
|
||||
}
|
||||
for price, liquidationPrice := range self.liquidationPriceStates {
|
||||
stateExchanges.liquidationPriceStates[price] = liquidationPrice.deepCopy(db, self.MarkStateLiquidationPriceDirty)
|
||||
for price, liquidationPrice := range te.liquidationPriceStates {
|
||||
stateExchanges.liquidationPriceStates[price] = liquidationPrice.deepCopy(db, te.MarkStateLiquidationPriceDirty)
|
||||
}
|
||||
for price := range self.liquidationPriceStatesDirty {
|
||||
for price := range te.liquidationPriceStatesDirty {
|
||||
stateExchanges.liquidationPriceStatesDirty[price] = struct{}{}
|
||||
}
|
||||
return stateExchanges
|
||||
}
|
||||
|
||||
// Returns the address of the contract/orderId
|
||||
func (c *tradingExchanges) Hash() common.Hash {
|
||||
return c.orderBookHash
|
||||
func (te *tradingExchanges) Hash() common.Hash {
|
||||
return te.orderBookHash
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) SetNonce(nonce uint64) {
|
||||
self.setNonce(nonce)
|
||||
func (te *tradingExchanges) SetNonce(nonce uint64) {
|
||||
te.setNonce(nonce)
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) setNonce(nonce uint64) {
|
||||
self.data.Nonce = nonce
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
func (te *tradingExchanges) setNonce(nonce uint64) {
|
||||
te.data.Nonce = nonce
|
||||
if te.onDirty != nil {
|
||||
te.onDirty(te.Hash())
|
||||
te.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) Nonce() uint64 {
|
||||
return self.data.Nonce
|
||||
func (te *tradingExchanges) Nonce() uint64 {
|
||||
return te.data.Nonce
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) setLastPrice(price *big.Int) {
|
||||
self.data.LastPrice = price
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
func (te *tradingExchanges) setLastPrice(price *big.Int) {
|
||||
te.data.LastPrice = price
|
||||
if te.onDirty != nil {
|
||||
te.onDirty(te.Hash())
|
||||
te.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) setMediumPriceBeforeEpoch(price *big.Int) {
|
||||
self.data.MediumPriceBeforeEpoch = price
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
func (te *tradingExchanges) setMediumPriceBeforeEpoch(price *big.Int) {
|
||||
te.data.MediumPriceBeforeEpoch = price
|
||||
if te.onDirty != nil {
|
||||
te.onDirty(te.Hash())
|
||||
te.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) setMediumPrice(price *big.Int, quantity *big.Int) {
|
||||
self.data.MediumPrice = price
|
||||
self.data.TotalQuantity = quantity
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
func (te *tradingExchanges) setMediumPrice(price *big.Int, quantity *big.Int) {
|
||||
te.data.MediumPrice = price
|
||||
te.data.TotalQuantity = quantity
|
||||
if te.onDirty != nil {
|
||||
te.onDirty(te.Hash())
|
||||
te.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
// updateStateExchangeObject writes the given object to the trie.
|
||||
func (self *tradingExchanges) removeStateOrderListAskObject(db Database, stateOrderList *stateOrderList) {
|
||||
self.setError(self.asksTrie.TryDelete(stateOrderList.price[:]))
|
||||
func (te *tradingExchanges) removeStateOrderListAskObject(db Database, stateOrderList *stateOrderList) {
|
||||
te.setError(te.asksTrie.TryDelete(stateOrderList.price[:]))
|
||||
}
|
||||
|
||||
// updateStateExchangeObject writes the given object to the trie.
|
||||
func (self *tradingExchanges) removeStateOrderListBidObject(db Database, stateOrderList *stateOrderList) {
|
||||
self.setError(self.bidsTrie.TryDelete(stateOrderList.price[:]))
|
||||
func (te *tradingExchanges) removeStateOrderListBidObject(db Database, stateOrderList *stateOrderList) {
|
||||
te.setError(te.bidsTrie.TryDelete(stateOrderList.price[:]))
|
||||
}
|
||||
|
||||
// Retrieve a state object given my the address. Returns nil if not found.
|
||||
func (self *tradingExchanges) getStateOrderListAskObject(db Database, price common.Hash) (stateOrderList *stateOrderList) {
|
||||
func (te *tradingExchanges) getStateOrderListAskObject(db Database, price common.Hash) (stateOrderList *stateOrderList) {
|
||||
// Prefer 'live' objects.
|
||||
if obj := self.stateAskObjects[price]; obj != nil {
|
||||
if obj := te.stateAskObjects[price]; obj != nil {
|
||||
return obj
|
||||
}
|
||||
|
||||
// Load the object from the database.
|
||||
enc, err := self.getAsksTrie(db).TryGet(price[:])
|
||||
enc, err := te.getAsksTrie(db).TryGet(price[:])
|
||||
if len(enc) == 0 {
|
||||
self.setError(err)
|
||||
te.setError(err)
|
||||
return nil
|
||||
}
|
||||
var data orderList
|
||||
|
|
@ -435,50 +435,50 @@ func (self *tradingExchanges) getStateOrderListAskObject(db Database, price comm
|
|||
return nil
|
||||
}
|
||||
// Insert into the live set.
|
||||
obj := newStateOrderList(self.db, Bid, self.orderBookHash, price, data, self.MarkStateAskObjectDirty)
|
||||
self.stateAskObjects[price] = obj
|
||||
obj := newStateOrderList(te.db, Bid, te.orderBookHash, price, data, te.MarkStateAskObjectDirty)
|
||||
te.stateAskObjects[price] = obj
|
||||
return obj
|
||||
}
|
||||
|
||||
// MarkStateAskObjectDirty adds the specified object to the dirty map to avoid costly
|
||||
// state object cache iteration to find a handful of modified ones.
|
||||
func (self *tradingExchanges) MarkStateAskObjectDirty(price common.Hash) {
|
||||
self.stateAskObjectsDirty[price] = struct{}{}
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
func (te *tradingExchanges) MarkStateAskObjectDirty(price common.Hash) {
|
||||
te.stateAskObjectsDirty[price] = struct{}{}
|
||||
if te.onDirty != nil {
|
||||
te.onDirty(te.Hash())
|
||||
te.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
// createStateOrderListObject creates a new state object. If there is an existing orderId with
|
||||
// the given address, it is overwritten and returned as the second return value.
|
||||
func (self *tradingExchanges) createStateOrderListAskObject(db Database, price common.Hash) (newobj *stateOrderList) {
|
||||
newobj = newStateOrderList(self.db, Ask, self.orderBookHash, price, orderList{Volume: Zero}, self.MarkStateAskObjectDirty)
|
||||
self.stateAskObjects[price] = newobj
|
||||
self.stateAskObjectsDirty[price] = struct{}{}
|
||||
func (te *tradingExchanges) createStateOrderListAskObject(db Database, price common.Hash) (newobj *stateOrderList) {
|
||||
newobj = newStateOrderList(te.db, Ask, te.orderBookHash, price, orderList{Volume: Zero}, te.MarkStateAskObjectDirty)
|
||||
te.stateAskObjects[price] = newobj
|
||||
te.stateAskObjectsDirty[price] = struct{}{}
|
||||
data, err := rlp.EncodeToBytes(newobj)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("can't encode order list object at %x: %v", price[:], err))
|
||||
}
|
||||
self.setError(self.asksTrie.TryUpdate(price[:], data))
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
te.setError(te.asksTrie.TryUpdate(price[:], data))
|
||||
if te.onDirty != nil {
|
||||
te.onDirty(te.Hash())
|
||||
te.onDirty = nil
|
||||
}
|
||||
return newobj
|
||||
}
|
||||
|
||||
// Retrieve a state object given my the address. Returns nil if not found.
|
||||
func (self *tradingExchanges) getStateBidOrderListObject(db Database, price common.Hash) (stateOrderList *stateOrderList) {
|
||||
func (te *tradingExchanges) getStateBidOrderListObject(db Database, price common.Hash) (stateOrderList *stateOrderList) {
|
||||
// Prefer 'live' objects.
|
||||
if obj := self.stateBidObjects[price]; obj != nil {
|
||||
if obj := te.stateBidObjects[price]; obj != nil {
|
||||
return obj
|
||||
}
|
||||
|
||||
// Load the object from the database.
|
||||
enc, err := self.getBidsTrie(db).TryGet(price[:])
|
||||
enc, err := te.getBidsTrie(db).TryGet(price[:])
|
||||
if len(enc) == 0 {
|
||||
self.setError(err)
|
||||
te.setError(err)
|
||||
return nil
|
||||
}
|
||||
var data orderList
|
||||
|
|
@ -487,50 +487,50 @@ func (self *tradingExchanges) getStateBidOrderListObject(db Database, price comm
|
|||
return nil
|
||||
}
|
||||
// Insert into the live set.
|
||||
obj := newStateOrderList(self.db, Bid, self.orderBookHash, price, data, self.MarkStateBidObjectDirty)
|
||||
self.stateBidObjects[price] = obj
|
||||
obj := newStateOrderList(te.db, Bid, te.orderBookHash, price, data, te.MarkStateBidObjectDirty)
|
||||
te.stateBidObjects[price] = obj
|
||||
return obj
|
||||
}
|
||||
|
||||
// MarkStateAskObjectDirty adds the specified object to the dirty map to avoid costly
|
||||
// state object cache iteration to find a handful of modified ones.
|
||||
func (self *tradingExchanges) MarkStateBidObjectDirty(price common.Hash) {
|
||||
self.stateBidObjectsDirty[price] = struct{}{}
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
func (te *tradingExchanges) MarkStateBidObjectDirty(price common.Hash) {
|
||||
te.stateBidObjectsDirty[price] = struct{}{}
|
||||
if te.onDirty != nil {
|
||||
te.onDirty(te.Hash())
|
||||
te.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
// createStateOrderListObject creates a new state object. If there is an existing orderId with
|
||||
// the given address, it is overwritten and returned as the second return value.
|
||||
func (self *tradingExchanges) createStateBidOrderListObject(db Database, price common.Hash) (newobj *stateOrderList) {
|
||||
newobj = newStateOrderList(self.db, Bid, self.orderBookHash, price, orderList{Volume: Zero}, self.MarkStateBidObjectDirty)
|
||||
self.stateBidObjects[price] = newobj
|
||||
self.stateBidObjectsDirty[price] = struct{}{}
|
||||
func (te *tradingExchanges) createStateBidOrderListObject(db Database, price common.Hash) (newobj *stateOrderList) {
|
||||
newobj = newStateOrderList(te.db, Bid, te.orderBookHash, price, orderList{Volume: Zero}, te.MarkStateBidObjectDirty)
|
||||
te.stateBidObjects[price] = newobj
|
||||
te.stateBidObjectsDirty[price] = struct{}{}
|
||||
data, err := rlp.EncodeToBytes(newobj)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("can't encode order list object at %x: %v", price[:], err))
|
||||
}
|
||||
self.setError(self.bidsTrie.TryUpdate(price[:], data))
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
te.setError(te.bidsTrie.TryUpdate(price[:], data))
|
||||
if te.onDirty != nil {
|
||||
te.onDirty(te.Hash())
|
||||
te.onDirty = nil
|
||||
}
|
||||
return newobj
|
||||
}
|
||||
|
||||
// Retrieve a state object given my the address. Returns nil if not found.
|
||||
func (self *tradingExchanges) getStateOrderObject(db Database, orderId common.Hash) (stateOrderItem *stateOrderItem) {
|
||||
func (te *tradingExchanges) getStateOrderObject(db Database, orderId common.Hash) (stateOrderItem *stateOrderItem) {
|
||||
// Prefer 'live' objects.
|
||||
if obj := self.stateOrderObjects[orderId]; obj != nil {
|
||||
if obj := te.stateOrderObjects[orderId]; obj != nil {
|
||||
return obj
|
||||
}
|
||||
|
||||
// Load the object from the database.
|
||||
enc, err := self.getOrdersTrie(db).TryGet(orderId[:])
|
||||
enc, err := te.getOrdersTrie(db).TryGet(orderId[:])
|
||||
if len(enc) == 0 {
|
||||
self.setError(err)
|
||||
te.setError(err)
|
||||
return nil
|
||||
}
|
||||
var data OrderItem
|
||||
|
|
@ -539,48 +539,48 @@ func (self *tradingExchanges) getStateOrderObject(db Database, orderId common.Ha
|
|||
return nil
|
||||
}
|
||||
// Insert into the live set.
|
||||
obj := newStateOrderItem(self.orderBookHash, orderId, data, self.MarkStateOrderObjectDirty)
|
||||
self.stateOrderObjects[orderId] = obj
|
||||
obj := newStateOrderItem(te.orderBookHash, orderId, data, te.MarkStateOrderObjectDirty)
|
||||
te.stateOrderObjects[orderId] = obj
|
||||
return obj
|
||||
}
|
||||
|
||||
// MarkStateAskObjectDirty adds the specified object to the dirty map to avoid costly
|
||||
// state object cache iteration to find a handful of modified ones.
|
||||
func (self *tradingExchanges) MarkStateOrderObjectDirty(orderId common.Hash) {
|
||||
self.stateOrderObjectsDirty[orderId] = struct{}{}
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
func (te *tradingExchanges) MarkStateOrderObjectDirty(orderId common.Hash) {
|
||||
te.stateOrderObjectsDirty[orderId] = struct{}{}
|
||||
if te.onDirty != nil {
|
||||
te.onDirty(te.Hash())
|
||||
te.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
// createStateOrderListObject creates a new state object. If there is an existing orderId with
|
||||
// the given address, it is overwritten and returned as the second return value.
|
||||
func (self *tradingExchanges) createStateOrderObject(db Database, orderId common.Hash, order OrderItem) (newobj *stateOrderItem) {
|
||||
newobj = newStateOrderItem(self.orderBookHash, orderId, order, self.MarkStateOrderObjectDirty)
|
||||
func (t *tradingExchanges) createStateOrderObject(db Database, orderId common.Hash, order OrderItem) (newobj *stateOrderItem) {
|
||||
newobj = newStateOrderItem(t.orderBookHash, orderId, order, t.MarkStateOrderObjectDirty)
|
||||
orderIdHash := common.BigToHash(new(big.Int).SetUint64(order.OrderID))
|
||||
self.stateOrderObjects[orderIdHash] = newobj
|
||||
self.stateOrderObjectsDirty[orderIdHash] = struct{}{}
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.orderBookHash)
|
||||
self.onDirty = nil
|
||||
t.stateOrderObjects[orderIdHash] = newobj
|
||||
t.stateOrderObjectsDirty[orderIdHash] = struct{}{}
|
||||
if t.onDirty != nil {
|
||||
t.onDirty(t.orderBookHash)
|
||||
t.onDirty = nil
|
||||
}
|
||||
return newobj
|
||||
}
|
||||
|
||||
// updateAskTrie writes cached storage modifications into the object's storage trie.
|
||||
func (self *tradingExchanges) updateOrdersTrie(db Database) Trie {
|
||||
tr := self.getOrdersTrie(db)
|
||||
for orderId, orderItem := range self.stateOrderObjects {
|
||||
if _, isDirty := self.stateOrderObjectsDirty[orderId]; isDirty {
|
||||
delete(self.stateOrderObjectsDirty, orderId)
|
||||
func (t *tradingExchanges) updateOrdersTrie(db Database) Trie {
|
||||
tr := t.getOrdersTrie(db)
|
||||
for orderId, orderItem := range t.stateOrderObjects {
|
||||
if _, isDirty := t.stateOrderObjectsDirty[orderId]; isDirty {
|
||||
delete(t.stateOrderObjectsDirty, orderId)
|
||||
if orderItem.empty() {
|
||||
self.setError(tr.TryDelete(orderId[:]))
|
||||
t.setError(tr.TryDelete(orderId[:]))
|
||||
continue
|
||||
}
|
||||
// Encoding []byte cannot fail, ok to ignore the error.
|
||||
v, _ := rlp.EncodeToBytes(orderItem)
|
||||
self.setError(tr.TryUpdate(orderId[:], v))
|
||||
t.setError(tr.TryUpdate(orderId[:], v))
|
||||
}
|
||||
}
|
||||
return tr
|
||||
|
|
@ -588,71 +588,71 @@ func (self *tradingExchanges) updateOrdersTrie(db Database) Trie {
|
|||
|
||||
// CommitAskTrie the storage trie of the object to dwb.
|
||||
// This updates the trie root.
|
||||
func (self *tradingExchanges) updateOrdersRoot(db Database) {
|
||||
self.updateOrdersTrie(db)
|
||||
self.data.OrderRoot = self.ordersTrie.Hash()
|
||||
func (t *tradingExchanges) updateOrdersRoot(db Database) {
|
||||
t.updateOrdersTrie(db)
|
||||
t.data.OrderRoot = t.ordersTrie.Hash()
|
||||
}
|
||||
|
||||
// CommitAskTrie the storage trie of the object to dwb.
|
||||
// This updates the trie root.
|
||||
func (self *tradingExchanges) CommitOrdersTrie(db Database) error {
|
||||
self.updateOrdersTrie(db)
|
||||
if self.dbErr != nil {
|
||||
return self.dbErr
|
||||
func (t *tradingExchanges) CommitOrdersTrie(db Database) error {
|
||||
t.updateOrdersTrie(db)
|
||||
if t.dbErr != nil {
|
||||
return t.dbErr
|
||||
}
|
||||
root, err := self.ordersTrie.Commit(nil)
|
||||
root, err := t.ordersTrie.Commit(nil)
|
||||
if err == nil {
|
||||
self.data.OrderRoot = root
|
||||
t.data.OrderRoot = root
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) MarkStateLiquidationPriceDirty(price common.Hash) {
|
||||
self.liquidationPriceStatesDirty[price] = struct{}{}
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
func (t *tradingExchanges) MarkStateLiquidationPriceDirty(price common.Hash) {
|
||||
t.liquidationPriceStatesDirty[price] = struct{}{}
|
||||
if t.onDirty != nil {
|
||||
t.onDirty(t.Hash())
|
||||
t.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) createStateLiquidationPrice(db Database, liquidationPrice common.Hash) (newobj *liquidationPriceState) {
|
||||
newobj = newLiquidationPriceState(self.db, self.orderBookHash, liquidationPrice, orderList{Volume: Zero}, self.MarkStateLiquidationPriceDirty)
|
||||
self.liquidationPriceStates[liquidationPrice] = newobj
|
||||
self.liquidationPriceStatesDirty[liquidationPrice] = struct{}{}
|
||||
func (t *tradingExchanges) createStateLiquidationPrice(db Database, liquidationPrice common.Hash) (newobj *liquidationPriceState) {
|
||||
newobj = newLiquidationPriceState(t.db, t.orderBookHash, liquidationPrice, orderList{Volume: Zero}, t.MarkStateLiquidationPriceDirty)
|
||||
t.liquidationPriceStates[liquidationPrice] = newobj
|
||||
t.liquidationPriceStatesDirty[liquidationPrice] = struct{}{}
|
||||
data, err := rlp.EncodeToBytes(newobj)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("can't encode liquidation price object at %x: %v", liquidationPrice[:], err))
|
||||
}
|
||||
self.setError(self.getLiquidationPriceTrie(db).TryUpdate(liquidationPrice[:], data))
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
t.setError(t.getLiquidationPriceTrie(db).TryUpdate(liquidationPrice[:], data))
|
||||
if t.onDirty != nil {
|
||||
t.onDirty(t.Hash())
|
||||
t.onDirty = nil
|
||||
}
|
||||
return newobj
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) getLiquidationPriceTrie(db Database) Trie {
|
||||
if self.liquidationPriceTrie == nil {
|
||||
func (t *tradingExchanges) getLiquidationPriceTrie(db Database) Trie {
|
||||
if t.liquidationPriceTrie == nil {
|
||||
var err error
|
||||
self.liquidationPriceTrie, err = db.OpenStorageTrie(self.orderBookHash, self.data.LiquidationPriceRoot)
|
||||
t.liquidationPriceTrie, err = db.OpenStorageTrie(t.orderBookHash, t.data.LiquidationPriceRoot)
|
||||
if err != nil {
|
||||
self.liquidationPriceTrie, _ = db.OpenStorageTrie(self.orderBookHash, EmptyHash)
|
||||
self.setError(fmt.Errorf("can't create liquidation liquidationPrice trie: %v", err))
|
||||
t.liquidationPriceTrie, _ = db.OpenStorageTrie(t.orderBookHash, EmptyHash)
|
||||
t.setError(fmt.Errorf("can't create liquidation liquidationPrice trie: %v", err))
|
||||
}
|
||||
}
|
||||
return self.liquidationPriceTrie
|
||||
return t.liquidationPriceTrie
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) getStateLiquidationPrice(db Database, price common.Hash) (stateObject *liquidationPriceState) {
|
||||
func (t *tradingExchanges) getStateLiquidationPrice(db Database, price common.Hash) (stateObject *liquidationPriceState) {
|
||||
// Prefer 'live' objects.
|
||||
if obj := self.liquidationPriceStates[price]; obj != nil {
|
||||
if obj := t.liquidationPriceStates[price]; obj != nil {
|
||||
return obj
|
||||
}
|
||||
|
||||
// Load the object from the database.
|
||||
enc, err := self.getLiquidationPriceTrie(db).TryGet(price[:])
|
||||
enc, err := t.getLiquidationPriceTrie(db).TryGet(price[:])
|
||||
if len(enc) == 0 {
|
||||
self.setError(err)
|
||||
t.setError(err)
|
||||
return nil
|
||||
}
|
||||
var data orderList
|
||||
|
|
@ -661,16 +661,16 @@ func (self *tradingExchanges) getStateLiquidationPrice(db Database, price common
|
|||
return nil
|
||||
}
|
||||
// Insert into the live set.
|
||||
obj := newLiquidationPriceState(self.db, self.orderBookHash, price, data, self.MarkStateLiquidationPriceDirty)
|
||||
self.liquidationPriceStates[price] = obj
|
||||
obj := newLiquidationPriceState(t.db, t.orderBookHash, price, data, t.MarkStateLiquidationPriceDirty)
|
||||
t.liquidationPriceStates[price] = obj
|
||||
return obj
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) getLowestLiquidationPrice(db Database) (common.Hash, *liquidationPriceState) {
|
||||
trie := self.getLiquidationPriceTrie(db)
|
||||
func (t *tradingExchanges) getLowestLiquidationPrice(db Database) (common.Hash, *liquidationPriceState) {
|
||||
trie := t.getLiquidationPriceTrie(db)
|
||||
encKey, encValue, err := trie.TryGetBestLeftKeyAndValue()
|
||||
if err != nil {
|
||||
log.Error("Failed find best liquidationPrice ask trie ", "orderbook", self.orderBookHash.Hex())
|
||||
log.Error("Failed find best liquidationPrice ask trie ", "orderbook", t.orderBookHash.Hex())
|
||||
return EmptyHash, nil
|
||||
}
|
||||
if len(encKey) == 0 || len(encValue) == 0 {
|
||||
|
|
@ -678,25 +678,25 @@ func (self *tradingExchanges) getLowestLiquidationPrice(db Database) (common.Has
|
|||
return EmptyHash, nil
|
||||
}
|
||||
price := common.BytesToHash(encKey)
|
||||
obj := self.liquidationPriceStates[price]
|
||||
obj := t.liquidationPriceStates[price]
|
||||
if obj == nil {
|
||||
var data orderList
|
||||
if err := rlp.DecodeBytes(encValue, &data); err != nil {
|
||||
log.Error("Failed to decode state get best ask trie", "err", err)
|
||||
return EmptyHash, nil
|
||||
}
|
||||
obj = newLiquidationPriceState(self.db, self.orderBookHash, price, data, self.MarkStateLiquidationPriceDirty)
|
||||
self.liquidationPriceStates[price] = obj
|
||||
obj = newLiquidationPriceState(t.db, t.orderBookHash, price, data, t.MarkStateLiquidationPriceDirty)
|
||||
t.liquidationPriceStates[price] = obj
|
||||
}
|
||||
return price, obj
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) getAllLowerLiquidationPrice(db Database, limit common.Hash) map[common.Hash]*liquidationPriceState {
|
||||
trie := self.getLiquidationPriceTrie(db)
|
||||
func (t *tradingExchanges) getAllLowerLiquidationPrice(db Database, limit common.Hash) map[common.Hash]*liquidationPriceState {
|
||||
trie := t.getLiquidationPriceTrie(db)
|
||||
encKeys, encValues, err := trie.TryGetAllLeftKeyAndValue(limit.Bytes())
|
||||
result := map[common.Hash]*liquidationPriceState{}
|
||||
if err != nil || len(encKeys) != len(encValues) {
|
||||
log.Error("Failed get lower liquidation price trie ", "orderbook", self.orderBookHash.Hex(), "encKeys", len(encKeys), "encValues", len(encValues))
|
||||
log.Error("Failed get lower liquidation price trie ", "orderbook", t.orderBookHash.Hex(), "encKeys", len(encKeys), "encValues", len(encValues))
|
||||
return result
|
||||
}
|
||||
if len(encKeys) == 0 || len(encValues) == 0 {
|
||||
|
|
@ -705,15 +705,15 @@ func (self *tradingExchanges) getAllLowerLiquidationPrice(db Database, limit com
|
|||
}
|
||||
for i := range encKeys {
|
||||
price := common.BytesToHash(encKeys[i])
|
||||
obj := self.liquidationPriceStates[price]
|
||||
obj := t.liquidationPriceStates[price]
|
||||
if obj == nil {
|
||||
var data orderList
|
||||
if err := rlp.DecodeBytes(encValues[i], &data); err != nil {
|
||||
log.Error("Failed to decode state get all lower liquidation price trie", "price", price, "encValues", encValues[i], "err", err)
|
||||
return result
|
||||
}
|
||||
obj = newLiquidationPriceState(self.db, self.orderBookHash, price, data, self.MarkStateLiquidationPriceDirty)
|
||||
self.liquidationPriceStates[price] = obj
|
||||
obj = newLiquidationPriceState(t.db, t.orderBookHash, price, data, t.MarkStateLiquidationPriceDirty)
|
||||
t.liquidationPriceStates[price] = obj
|
||||
}
|
||||
if obj.empty() {
|
||||
continue
|
||||
|
|
@ -723,11 +723,11 @@ func (self *tradingExchanges) getAllLowerLiquidationPrice(db Database, limit com
|
|||
return result
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) getHighestLiquidationPrice(db Database) (common.Hash, *liquidationPriceState) {
|
||||
trie := self.getLiquidationPriceTrie(db)
|
||||
func (t *tradingExchanges) getHighestLiquidationPrice(db Database) (common.Hash, *liquidationPriceState) {
|
||||
trie := t.getLiquidationPriceTrie(db)
|
||||
encKey, encValue, err := trie.TryGetBestRightKeyAndValue()
|
||||
if err != nil {
|
||||
log.Error("Failed find best liquidationPrice ask trie ", "orderbook", self.orderBookHash.Hex())
|
||||
log.Error("Failed find best liquidationPrice ask trie ", "orderbook", t.orderBookHash.Hex())
|
||||
return EmptyHash, nil
|
||||
}
|
||||
if len(encKey) == 0 || len(encValue) == 0 {
|
||||
|
|
@ -735,28 +735,29 @@ func (self *tradingExchanges) getHighestLiquidationPrice(db Database) (common.Ha
|
|||
return EmptyHash, nil
|
||||
}
|
||||
price := common.BytesToHash(encKey)
|
||||
obj := self.liquidationPriceStates[price]
|
||||
obj := t.liquidationPriceStates[price]
|
||||
if obj == nil {
|
||||
var data orderList
|
||||
if err := rlp.DecodeBytes(encValue, &data); err != nil {
|
||||
log.Error("Failed to decode state get best ask trie", "err", err)
|
||||
return EmptyHash, nil
|
||||
}
|
||||
obj = newLiquidationPriceState(self.db, self.orderBookHash, price, data, self.MarkStateLiquidationPriceDirty)
|
||||
self.liquidationPriceStates[price] = obj
|
||||
obj = newLiquidationPriceState(t.db, t.orderBookHash, price, data, t.MarkStateLiquidationPriceDirty)
|
||||
t.liquidationPriceStates[price] = obj
|
||||
}
|
||||
if obj.empty() {
|
||||
return EmptyHash, nil
|
||||
}
|
||||
return price, obj
|
||||
}
|
||||
func (self *tradingExchanges) updateLiquidationPriceTrie(db Database) Trie {
|
||||
tr := self.getLiquidationPriceTrie(db)
|
||||
for price, stateObject := range self.liquidationPriceStates {
|
||||
if _, isDirty := self.liquidationPriceStatesDirty[price]; isDirty {
|
||||
delete(self.liquidationPriceStatesDirty, price)
|
||||
|
||||
func (t *tradingExchanges) updateLiquidationPriceTrie(db Database) Trie {
|
||||
tr := t.getLiquidationPriceTrie(db)
|
||||
for price, stateObject := range t.liquidationPriceStates {
|
||||
if _, isDirty := t.liquidationPriceStatesDirty[price]; isDirty {
|
||||
delete(t.liquidationPriceStatesDirty, price)
|
||||
if stateObject.empty() {
|
||||
self.setError(tr.TryDelete(price[:]))
|
||||
t.setError(tr.TryDelete(price[:]))
|
||||
continue
|
||||
}
|
||||
err := stateObject.updateRoot(db)
|
||||
|
|
@ -765,23 +766,23 @@ func (self *tradingExchanges) updateLiquidationPriceTrie(db Database) Trie {
|
|||
}
|
||||
// Encoding []byte cannot fail, ok to ignore the error.
|
||||
v, _ := rlp.EncodeToBytes(stateObject)
|
||||
self.setError(tr.TryUpdate(price[:], v))
|
||||
t.setError(tr.TryUpdate(price[:], v))
|
||||
}
|
||||
}
|
||||
return tr
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) updateLiquidationPriceRoot(db Database) {
|
||||
self.updateLiquidationPriceTrie(db)
|
||||
self.data.LiquidationPriceRoot = self.liquidationPriceTrie.Hash()
|
||||
func (t *tradingExchanges) updateLiquidationPriceRoot(db Database) {
|
||||
t.updateLiquidationPriceTrie(db)
|
||||
t.data.LiquidationPriceRoot = t.liquidationPriceTrie.Hash()
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) CommitLiquidationPriceTrie(db Database) error {
|
||||
self.updateLiquidationPriceTrie(db)
|
||||
if self.dbErr != nil {
|
||||
return self.dbErr
|
||||
func (t *tradingExchanges) CommitLiquidationPriceTrie(db Database) error {
|
||||
t.updateLiquidationPriceTrie(db)
|
||||
if t.dbErr != nil {
|
||||
return t.dbErr
|
||||
}
|
||||
root, err := self.liquidationPriceTrie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
root, err := t.liquidationPriceTrie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
var orderList orderList
|
||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||
return nil
|
||||
|
|
@ -792,23 +793,23 @@ func (self *tradingExchanges) CommitLiquidationPriceTrie(db Database) error {
|
|||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
self.data.LiquidationPriceRoot = root
|
||||
t.data.LiquidationPriceRoot = root
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *tradingExchanges) addLendingCount(amount *big.Int) {
|
||||
c.setLendingCount(new(big.Int).Add(c.data.LendingCount, amount))
|
||||
func (t *tradingExchanges) addLendingCount(amount *big.Int) {
|
||||
t.setLendingCount(new(big.Int).Add(t.data.LendingCount, amount))
|
||||
}
|
||||
|
||||
func (c *tradingExchanges) subLendingCount(amount *big.Int) {
|
||||
c.setLendingCount(new(big.Int).Sub(c.data.LendingCount, amount))
|
||||
func (t *tradingExchanges) subLendingCount(amount *big.Int) {
|
||||
t.setLendingCount(new(big.Int).Sub(t.data.LendingCount, amount))
|
||||
}
|
||||
|
||||
func (self *tradingExchanges) setLendingCount(volume *big.Int) {
|
||||
self.data.LendingCount = volume
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.orderBookHash)
|
||||
self.onDirty = nil
|
||||
func (t *tradingExchanges) setLendingCount(volume *big.Int) {
|
||||
t.data.LendingCount = volume
|
||||
if t.onDirty != nil {
|
||||
t.onDirty(t.orderBookHash)
|
||||
t.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,55 +78,55 @@ func New(root common.Hash, db Database) (*TradingStateDB, error) {
|
|||
}
|
||||
|
||||
// setError remembers the first non-nil error it is called with.
|
||||
func (self *TradingStateDB) setError(err error) {
|
||||
if self.dbErr == nil {
|
||||
self.dbErr = err
|
||||
func (t *TradingStateDB) setError(err error) {
|
||||
if t.dbErr == nil {
|
||||
t.dbErr = err
|
||||
}
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) Error() error {
|
||||
return self.dbErr
|
||||
func (t *TradingStateDB) Error() error {
|
||||
return t.dbErr
|
||||
}
|
||||
|
||||
// Exist reports whether the given orderId address exists in the state.
|
||||
// Notably this also returns true for suicided exchanges.
|
||||
func (self *TradingStateDB) Exist(addr common.Hash) bool {
|
||||
return self.getStateExchangeObject(addr) != nil
|
||||
func (t *TradingStateDB) Exist(addr common.Hash) bool {
|
||||
return t.getStateExchangeObject(addr) != nil
|
||||
}
|
||||
|
||||
// Empty returns whether the state object is either non-existent
|
||||
// or empty according to the EIP161 specification (balance = nonce = code = 0)
|
||||
func (self *TradingStateDB) Empty(addr common.Hash) bool {
|
||||
so := self.getStateExchangeObject(addr)
|
||||
func (t *TradingStateDB) Empty(addr common.Hash) bool {
|
||||
so := t.getStateExchangeObject(addr)
|
||||
return so == nil || so.empty()
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) GetNonce(addr common.Hash) uint64 {
|
||||
stateObject := self.getStateExchangeObject(addr)
|
||||
func (t *TradingStateDB) GetNonce(addr common.Hash) uint64 {
|
||||
stateObject := t.getStateExchangeObject(addr)
|
||||
if stateObject != nil {
|
||||
return stateObject.Nonce()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) GetLastPrice(addr common.Hash) *big.Int {
|
||||
stateObject := self.getStateExchangeObject(addr)
|
||||
func (t *TradingStateDB) GetLastPrice(addr common.Hash) *big.Int {
|
||||
stateObject := t.getStateExchangeObject(addr)
|
||||
if stateObject != nil {
|
||||
return stateObject.data.LastPrice
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) GetMediumPriceBeforeEpoch(addr common.Hash) *big.Int {
|
||||
stateObject := self.getStateExchangeObject(addr)
|
||||
func (t *TradingStateDB) GetMediumPriceBeforeEpoch(addr common.Hash) *big.Int {
|
||||
stateObject := t.getStateExchangeObject(addr)
|
||||
if stateObject != nil {
|
||||
return stateObject.data.MediumPriceBeforeEpoch
|
||||
}
|
||||
return Zero
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) GetMediumPriceAndTotalAmount(addr common.Hash) (*big.Int, *big.Int) {
|
||||
stateObject := self.getStateExchangeObject(addr)
|
||||
func (t *TradingStateDB) GetMediumPriceAndTotalAmount(addr common.Hash) (*big.Int, *big.Int) {
|
||||
stateObject := t.getStateExchangeObject(addr)
|
||||
if stateObject != nil {
|
||||
return stateObject.data.MediumPrice, stateObject.data.TotalQuantity
|
||||
}
|
||||
|
|
@ -134,25 +134,25 @@ func (self *TradingStateDB) GetMediumPriceAndTotalAmount(addr common.Hash) (*big
|
|||
}
|
||||
|
||||
// Database retrieves the low level database supporting the lower level trie ops.
|
||||
func (self *TradingStateDB) Database() Database {
|
||||
return self.db
|
||||
func (t *TradingStateDB) Database() Database {
|
||||
return t.db
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) SetNonce(addr common.Hash, nonce uint64) {
|
||||
stateObject := self.GetOrNewStateExchangeObject(addr)
|
||||
func (t *TradingStateDB) SetNonce(addr common.Hash, nonce uint64) {
|
||||
stateObject := t.GetOrNewStateExchangeObject(addr)
|
||||
if stateObject != nil {
|
||||
self.journal = append(self.journal, nonceChange{
|
||||
t.journal = append(t.journal, nonceChange{
|
||||
hash: addr,
|
||||
prev: self.GetNonce(addr),
|
||||
prev: t.GetNonce(addr),
|
||||
})
|
||||
stateObject.SetNonce(nonce)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) SetLastPrice(addr common.Hash, price *big.Int) {
|
||||
stateObject := self.GetOrNewStateExchangeObject(addr)
|
||||
func (t *TradingStateDB) SetLastPrice(addr common.Hash, price *big.Int) {
|
||||
stateObject := t.GetOrNewStateExchangeObject(addr)
|
||||
if stateObject != nil {
|
||||
self.journal = append(self.journal, lastPriceChange{
|
||||
t.journal = append(t.journal, lastPriceChange{
|
||||
hash: addr,
|
||||
prev: stateObject.data.LastPrice,
|
||||
})
|
||||
|
|
@ -160,10 +160,10 @@ func (self *TradingStateDB) SetLastPrice(addr common.Hash, price *big.Int) {
|
|||
}
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) SetMediumPrice(addr common.Hash, price *big.Int, quantity *big.Int) {
|
||||
stateObject := self.GetOrNewStateExchangeObject(addr)
|
||||
func (t *TradingStateDB) SetMediumPrice(addr common.Hash, price *big.Int, quantity *big.Int) {
|
||||
stateObject := t.GetOrNewStateExchangeObject(addr)
|
||||
if stateObject != nil {
|
||||
self.journal = append(self.journal, mediumPriceChange{
|
||||
t.journal = append(t.journal, mediumPriceChange{
|
||||
hash: addr,
|
||||
prevPrice: stateObject.data.MediumPrice,
|
||||
prevQuantity: stateObject.data.TotalQuantity,
|
||||
|
|
@ -172,10 +172,10 @@ func (self *TradingStateDB) SetMediumPrice(addr common.Hash, price *big.Int, qua
|
|||
}
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) SetMediumPriceBeforeEpoch(addr common.Hash, price *big.Int) {
|
||||
stateObject := self.GetOrNewStateExchangeObject(addr)
|
||||
func (t *TradingStateDB) SetMediumPriceBeforeEpoch(addr common.Hash, price *big.Int) {
|
||||
stateObject := t.GetOrNewStateExchangeObject(addr)
|
||||
if stateObject != nil {
|
||||
self.journal = append(self.journal, mediumPriceBeforeEpochChange{
|
||||
t.journal = append(t.journal, mediumPriceBeforeEpochChange{
|
||||
hash: addr,
|
||||
prevPrice: stateObject.data.MediumPriceBeforeEpoch,
|
||||
})
|
||||
|
|
@ -183,78 +183,79 @@ func (self *TradingStateDB) SetMediumPriceBeforeEpoch(addr common.Hash, price *b
|
|||
}
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) InsertOrderItem(orderBook common.Hash, orderId common.Hash, order OrderItem) {
|
||||
func (t *TradingStateDB) InsertOrderItem(orderBook common.Hash, orderId common.Hash, order OrderItem) {
|
||||
priceHash := common.BigToHash(order.Price)
|
||||
stateExchange := self.getStateExchangeObject(orderBook)
|
||||
stateExchange := t.getStateExchangeObject(orderBook)
|
||||
if stateExchange == nil {
|
||||
stateExchange = self.createExchangeObject(orderBook)
|
||||
stateExchange = t.createExchangeObject(orderBook)
|
||||
}
|
||||
var stateOrderList *stateOrderList
|
||||
switch order.Side {
|
||||
case Ask:
|
||||
stateOrderList = stateExchange.getStateOrderListAskObject(self.db, priceHash)
|
||||
stateOrderList = stateExchange.getStateOrderListAskObject(t.db, priceHash)
|
||||
if stateOrderList == nil {
|
||||
stateOrderList = stateExchange.createStateOrderListAskObject(self.db, priceHash)
|
||||
stateOrderList = stateExchange.createStateOrderListAskObject(t.db, priceHash)
|
||||
}
|
||||
case Bid:
|
||||
stateOrderList = stateExchange.getStateBidOrderListObject(self.db, priceHash)
|
||||
stateOrderList = stateExchange.getStateBidOrderListObject(t.db, priceHash)
|
||||
if stateOrderList == nil {
|
||||
stateOrderList = stateExchange.createStateBidOrderListObject(self.db, priceHash)
|
||||
stateOrderList = stateExchange.createStateBidOrderListObject(t.db, priceHash)
|
||||
}
|
||||
default:
|
||||
return
|
||||
}
|
||||
self.journal = append(self.journal, insertOrder{
|
||||
t.journal = append(t.journal, insertOrder{
|
||||
orderBook: orderBook,
|
||||
orderId: orderId,
|
||||
order: &order,
|
||||
})
|
||||
stateExchange.createStateOrderObject(self.db, orderId, order)
|
||||
stateOrderList.insertOrderItem(self.db, orderId, common.BigToHash(order.Quantity))
|
||||
stateExchange.createStateOrderObject(t.db, orderId, order)
|
||||
stateOrderList.insertOrderItem(t.db, orderId, common.BigToHash(order.Quantity))
|
||||
stateOrderList.AddVolume(order.Quantity)
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) GetOrder(orderBook common.Hash, orderId common.Hash) OrderItem {
|
||||
stateObject := self.GetOrNewStateExchangeObject(orderBook)
|
||||
func (t *TradingStateDB) GetOrder(orderBook common.Hash, orderId common.Hash) OrderItem {
|
||||
stateObject := t.GetOrNewStateExchangeObject(orderBook)
|
||||
if stateObject == nil {
|
||||
return EmptyOrder
|
||||
}
|
||||
stateOrderItem := stateObject.getStateOrderObject(self.db, orderId)
|
||||
stateOrderItem := stateObject.getStateOrderObject(t.db, orderId)
|
||||
if stateOrderItem == nil {
|
||||
return EmptyOrder
|
||||
}
|
||||
return stateOrderItem.data
|
||||
}
|
||||
func (self *TradingStateDB) SubAmountOrderItem(orderBook common.Hash, orderId common.Hash, price *big.Int, amount *big.Int, side string) error {
|
||||
|
||||
func (t *TradingStateDB) SubAmountOrderItem(orderBook common.Hash, orderId common.Hash, price *big.Int, amount *big.Int, side string) error {
|
||||
priceHash := common.BigToHash(price)
|
||||
stateObject := self.GetOrNewStateExchangeObject(orderBook)
|
||||
stateObject := t.GetOrNewStateExchangeObject(orderBook)
|
||||
if stateObject == nil {
|
||||
return fmt.Errorf("Order book not found : %s ", orderBook.Hex())
|
||||
return fmt.Errorf("not found orderBook: %s", orderBook.Hex())
|
||||
}
|
||||
var stateOrderList *stateOrderList
|
||||
switch side {
|
||||
case Ask:
|
||||
stateOrderList = stateObject.getStateOrderListAskObject(self.db, priceHash)
|
||||
stateOrderList = stateObject.getStateOrderListAskObject(t.db, priceHash)
|
||||
case Bid:
|
||||
stateOrderList = stateObject.getStateBidOrderListObject(self.db, priceHash)
|
||||
stateOrderList = stateObject.getStateBidOrderListObject(t.db, priceHash)
|
||||
default:
|
||||
return fmt.Errorf("Order type not found : %s ", side)
|
||||
return fmt.Errorf("not found order type: %s", side)
|
||||
}
|
||||
if stateOrderList == nil || stateOrderList.empty() {
|
||||
return fmt.Errorf("Order list empty order book : %s , order id : %s , price : %s ", orderBook, orderId.Hex(), priceHash.Hex())
|
||||
return fmt.Errorf("empty Orderlist: order book: %s , order id : %s , price : %s", orderBook, orderId.Hex(), priceHash.Hex())
|
||||
}
|
||||
stateOrderItem := stateObject.getStateOrderObject(self.db, orderId)
|
||||
stateOrderItem := stateObject.getStateOrderObject(t.db, orderId)
|
||||
if stateOrderItem == nil || stateOrderItem.empty() {
|
||||
return fmt.Errorf("Order item empty order book : %s , order id : %s , price : %s ", orderBook, orderId.Hex(), priceHash.Hex())
|
||||
return fmt.Errorf("empty OrderItem: order book: %s , order id : %s , price : %s", orderBook, orderId.Hex(), priceHash.Hex())
|
||||
}
|
||||
currentAmount := new(big.Int).SetBytes(stateOrderList.GetOrderAmount(self.db, orderId).Bytes()[:])
|
||||
currentAmount := new(big.Int).SetBytes(stateOrderList.GetOrderAmount(t.db, orderId).Bytes()[:])
|
||||
if currentAmount.Cmp(amount) < 0 {
|
||||
return fmt.Errorf("Order amount not enough : %s , have : %d , want : %d ", orderId.Hex(), currentAmount, amount)
|
||||
return fmt.Errorf("not enough order amount: %s , have : %d , want : %d ", orderId.Hex(), currentAmount, amount)
|
||||
}
|
||||
self.journal = append(self.journal, subAmountOrder{
|
||||
t.journal = append(t.journal, subAmountOrder{
|
||||
orderBook: orderBook,
|
||||
orderId: orderId,
|
||||
order: self.GetOrder(orderBook, orderId),
|
||||
order: t.GetOrder(orderBook, orderId),
|
||||
amount: amount,
|
||||
})
|
||||
newAmount := new(big.Int).Sub(currentAmount, amount)
|
||||
|
|
@ -262,86 +263,86 @@ func (self *TradingStateDB) SubAmountOrderItem(orderBook common.Hash, orderId co
|
|||
stateOrderList.subVolume(amount)
|
||||
stateOrderItem.setVolume(newAmount)
|
||||
if newAmount.Sign() == 0 {
|
||||
stateOrderList.removeOrderItem(self.db, orderId)
|
||||
stateOrderList.removeOrderItem(t.db, orderId)
|
||||
} else {
|
||||
stateOrderList.setOrderItem(orderId, common.BigToHash(newAmount))
|
||||
}
|
||||
if stateOrderList.empty() {
|
||||
switch side {
|
||||
case Ask:
|
||||
stateObject.removeStateOrderListAskObject(self.db, stateOrderList)
|
||||
stateObject.removeStateOrderListAskObject(t.db, stateOrderList)
|
||||
case Bid:
|
||||
stateObject.removeStateOrderListBidObject(self.db, stateOrderList)
|
||||
stateObject.removeStateOrderListBidObject(t.db, stateOrderList)
|
||||
default:
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) CancelOrder(orderBook common.Hash, order *OrderItem) error {
|
||||
func (t *TradingStateDB) CancelOrder(orderBook common.Hash, order *OrderItem) error {
|
||||
orderIdHash := common.BigToHash(new(big.Int).SetUint64(order.OrderID))
|
||||
stateObject := self.GetOrNewStateExchangeObject(orderBook)
|
||||
stateObject := t.GetOrNewStateExchangeObject(orderBook)
|
||||
if stateObject == nil {
|
||||
return fmt.Errorf("Order book not found : %s ", orderBook.Hex())
|
||||
return fmt.Errorf("not found orderBook: %s", orderBook.Hex())
|
||||
}
|
||||
stateOrderItem := stateObject.getStateOrderObject(self.db, orderIdHash)
|
||||
stateOrderItem := stateObject.getStateOrderObject(t.db, orderIdHash)
|
||||
if stateOrderItem == nil || stateOrderItem.empty() {
|
||||
return fmt.Errorf("Order item empty order book : %s , order id : %s ", orderBook, orderIdHash.Hex())
|
||||
return fmt.Errorf("empty OrderItem: order book: %s , order id : %s", orderBook, orderIdHash.Hex())
|
||||
}
|
||||
priceHash := common.BigToHash(stateOrderItem.data.Price)
|
||||
var stateOrderList *stateOrderList
|
||||
switch stateOrderItem.data.Side {
|
||||
case Ask:
|
||||
stateOrderList = stateObject.getStateOrderListAskObject(self.db, priceHash)
|
||||
stateOrderList = stateObject.getStateOrderListAskObject(t.db, priceHash)
|
||||
case Bid:
|
||||
stateOrderList = stateObject.getStateBidOrderListObject(self.db, priceHash)
|
||||
stateOrderList = stateObject.getStateBidOrderListObject(t.db, priceHash)
|
||||
default:
|
||||
return fmt.Errorf("Order side not found : %s ", order.Side)
|
||||
return fmt.Errorf("not found order.Side: %s", order.Side)
|
||||
}
|
||||
if stateOrderList == nil || stateOrderList.empty() {
|
||||
return fmt.Errorf("Order list empty order book : %s , order id : %s , price : %s ", orderBook, orderIdHash.Hex(), priceHash.Hex())
|
||||
return fmt.Errorf("empty OrderList: order book: %s , order id : %s , price : %s", orderBook, orderIdHash.Hex(), priceHash.Hex())
|
||||
}
|
||||
|
||||
if stateOrderItem.data.UserAddress != order.UserAddress {
|
||||
return fmt.Errorf("Error Order User Address mismatch when cancel order book : %s , order id : %s , got : %s , expect : %s ", orderBook, orderIdHash.Hex(), stateOrderItem.data.UserAddress.Hex(), order.UserAddress.Hex())
|
||||
return fmt.Errorf("error Order UserAddress mismatch when cancel: order book: %s , order id : %s , got : %s , expect : %s", orderBook, orderIdHash.Hex(), stateOrderItem.data.UserAddress.Hex(), order.UserAddress.Hex())
|
||||
}
|
||||
if stateOrderItem.data.Hash != order.Hash {
|
||||
return fmt.Errorf("Invalid order hash : got : %s , expect : %s ", order.Hash.Hex(), stateOrderItem.data.Hash.Hex())
|
||||
return fmt.Errorf("invalid order hash: got : %s , expect : %s", order.Hash.Hex(), stateOrderItem.data.Hash.Hex())
|
||||
}
|
||||
if stateOrderItem.data.ExchangeAddress != order.ExchangeAddress {
|
||||
return fmt.Errorf("Exchange Address mismatch when cancel. order book : %s , order id : %s , got : %s , expect : %s ", orderBook, orderIdHash.Hex(), order.ExchangeAddress.Hex(), stateOrderItem.data.ExchangeAddress.Hex())
|
||||
return fmt.Errorf("mismatch ExchangeAddress when cancel: order book : %s , order id : %s , got : %s , expect : %s", orderBook, orderIdHash.Hex(), order.ExchangeAddress.Hex(), stateOrderItem.data.ExchangeAddress.Hex())
|
||||
}
|
||||
self.journal = append(self.journal, cancelOrder{
|
||||
t.journal = append(t.journal, cancelOrder{
|
||||
orderBook: orderBook,
|
||||
orderId: orderIdHash,
|
||||
order: stateOrderItem.data,
|
||||
})
|
||||
currentAmount := new(big.Int).SetBytes(stateOrderList.GetOrderAmount(self.db, orderIdHash).Bytes()[:])
|
||||
currentAmount := new(big.Int).SetBytes(stateOrderList.GetOrderAmount(t.db, orderIdHash).Bytes()[:])
|
||||
stateOrderItem.setVolume(big.NewInt(0))
|
||||
stateOrderList.subVolume(currentAmount)
|
||||
stateOrderList.removeOrderItem(self.db, orderIdHash)
|
||||
stateOrderList.removeOrderItem(t.db, orderIdHash)
|
||||
if stateOrderList.empty() {
|
||||
switch stateOrderItem.data.Side {
|
||||
case Ask:
|
||||
stateObject.removeStateOrderListAskObject(self.db, stateOrderList)
|
||||
stateObject.removeStateOrderListAskObject(t.db, stateOrderList)
|
||||
case Bid:
|
||||
stateObject.removeStateOrderListBidObject(self.db, stateOrderList)
|
||||
stateObject.removeStateOrderListBidObject(t.db, stateOrderList)
|
||||
default:
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) GetVolume(orderBook common.Hash, price *big.Int, orderType string) *big.Int {
|
||||
stateObject := self.GetOrNewStateExchangeObject(orderBook)
|
||||
func (t *TradingStateDB) GetVolume(orderBook common.Hash, price *big.Int, orderType string) *big.Int {
|
||||
stateObject := t.GetOrNewStateExchangeObject(orderBook)
|
||||
var volume *big.Int = nil
|
||||
if stateObject != nil {
|
||||
var stateOrderList *stateOrderList
|
||||
switch orderType {
|
||||
case Ask:
|
||||
stateOrderList = stateObject.getStateOrderListAskObject(self.db, common.BigToHash(price))
|
||||
stateOrderList = stateObject.getStateOrderListAskObject(t.db, common.BigToHash(price))
|
||||
case Bid:
|
||||
stateOrderList = stateObject.getStateBidOrderListObject(self.db, common.BigToHash(price))
|
||||
stateOrderList = stateObject.getStateBidOrderListObject(t.db, common.BigToHash(price))
|
||||
default:
|
||||
return Zero
|
||||
}
|
||||
|
|
@ -352,14 +353,15 @@ func (self *TradingStateDB) GetVolume(orderBook common.Hash, price *big.Int, ord
|
|||
}
|
||||
return volume
|
||||
}
|
||||
func (self *TradingStateDB) GetBestAskPrice(orderBook common.Hash) (*big.Int, *big.Int) {
|
||||
stateObject := self.getStateExchangeObject(orderBook)
|
||||
|
||||
func (t *TradingStateDB) GetBestAskPrice(orderBook common.Hash) (*big.Int, *big.Int) {
|
||||
stateObject := t.getStateExchangeObject(orderBook)
|
||||
if stateObject != nil {
|
||||
priceHash := stateObject.getBestPriceAsksTrie(self.db)
|
||||
priceHash := stateObject.getBestPriceAsksTrie(t.db)
|
||||
if common.EmptyHash(priceHash) {
|
||||
return Zero, Zero
|
||||
}
|
||||
orderList := stateObject.getStateOrderListAskObject(self.db, priceHash)
|
||||
orderList := stateObject.getStateOrderListAskObject(t.db, priceHash)
|
||||
if orderList == nil {
|
||||
log.Error("order list ask not found", "price", priceHash.Hex())
|
||||
return Zero, Zero
|
||||
|
|
@ -369,14 +371,14 @@ func (self *TradingStateDB) GetBestAskPrice(orderBook common.Hash) (*big.Int, *b
|
|||
return Zero, Zero
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) GetBestBidPrice(orderBook common.Hash) (*big.Int, *big.Int) {
|
||||
stateObject := self.getStateExchangeObject(orderBook)
|
||||
func (t *TradingStateDB) GetBestBidPrice(orderBook common.Hash) (*big.Int, *big.Int) {
|
||||
stateObject := t.getStateExchangeObject(orderBook)
|
||||
if stateObject != nil {
|
||||
priceHash := stateObject.getBestBidsTrie(self.db)
|
||||
priceHash := stateObject.getBestBidsTrie(t.db)
|
||||
if common.EmptyHash(priceHash) {
|
||||
return Zero, Zero
|
||||
}
|
||||
orderList := stateObject.getStateBidOrderListObject(self.db, priceHash)
|
||||
orderList := stateObject.getStateBidOrderListObject(t.db, priceHash)
|
||||
if orderList == nil {
|
||||
log.Error("order list bid not found", "price", priceHash.Hex())
|
||||
return Zero, Zero
|
||||
|
|
@ -386,52 +388,52 @@ func (self *TradingStateDB) GetBestBidPrice(orderBook common.Hash) (*big.Int, *b
|
|||
return Zero, Zero
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) GetBestOrderIdAndAmount(orderBook common.Hash, price *big.Int, side string) (common.Hash, *big.Int, error) {
|
||||
stateObject := self.GetOrNewStateExchangeObject(orderBook)
|
||||
func (t *TradingStateDB) GetBestOrderIdAndAmount(orderBook common.Hash, price *big.Int, side string) (common.Hash, *big.Int, error) {
|
||||
stateObject := t.GetOrNewStateExchangeObject(orderBook)
|
||||
if stateObject != nil {
|
||||
var stateOrderList *stateOrderList
|
||||
switch side {
|
||||
case Ask:
|
||||
stateOrderList = stateObject.getStateOrderListAskObject(self.db, common.BigToHash(price))
|
||||
stateOrderList = stateObject.getStateOrderListAskObject(t.db, common.BigToHash(price))
|
||||
case Bid:
|
||||
stateOrderList = stateObject.getStateBidOrderListObject(self.db, common.BigToHash(price))
|
||||
stateOrderList = stateObject.getStateBidOrderListObject(t.db, common.BigToHash(price))
|
||||
default:
|
||||
return EmptyHash, Zero, fmt.Errorf("not found side :%s ", side)
|
||||
return EmptyHash, Zero, fmt.Errorf("not found side: %s", side)
|
||||
}
|
||||
if stateOrderList != nil {
|
||||
key, _, err := stateOrderList.getTrie(self.db).TryGetBestLeftKeyAndValue()
|
||||
key, _, err := stateOrderList.getTrie(t.db).TryGetBestLeftKeyAndValue()
|
||||
if err != nil {
|
||||
return EmptyHash, Zero, err
|
||||
}
|
||||
orderId := common.BytesToHash(key)
|
||||
amount := stateOrderList.GetOrderAmount(self.db, orderId)
|
||||
amount := stateOrderList.GetOrderAmount(t.db, orderId)
|
||||
return orderId, new(big.Int).SetBytes(amount.Bytes()), nil
|
||||
}
|
||||
return EmptyHash, Zero, fmt.Errorf("not found order list with orderBook : %s , price : %d , side :%s ", orderBook.Hex(), price, side)
|
||||
return EmptyHash, Zero, fmt.Errorf("not found order list with orderBook: %s , price : %d , side : %s", orderBook.Hex(), price, side)
|
||||
}
|
||||
return EmptyHash, Zero, fmt.Errorf("not found orderBook : %s ", orderBook.Hex())
|
||||
return EmptyHash, Zero, fmt.Errorf("not found orderBook: %s", orderBook.Hex())
|
||||
}
|
||||
|
||||
// updateStateExchangeObject writes the given object to the trie.
|
||||
func (self *TradingStateDB) updateStateExchangeObject(stateObject *tradingExchanges) {
|
||||
func (t *TradingStateDB) updateStateExchangeObject(stateObject *tradingExchanges) {
|
||||
addr := stateObject.Hash()
|
||||
data, err := rlp.EncodeToBytes(stateObject)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err))
|
||||
}
|
||||
self.setError(self.trie.TryUpdate(addr[:], data))
|
||||
t.setError(t.trie.TryUpdate(addr[:], data))
|
||||
}
|
||||
|
||||
// Retrieve a state object given my the address. Returns nil if not found.
|
||||
func (self *TradingStateDB) getStateExchangeObject(addr common.Hash) (stateObject *tradingExchanges) {
|
||||
func (t *TradingStateDB) getStateExchangeObject(addr common.Hash) (stateObject *tradingExchanges) {
|
||||
// Prefer 'live' objects.
|
||||
if obj := self.stateExhangeObjects[addr]; obj != nil {
|
||||
if obj := t.stateExhangeObjects[addr]; obj != nil {
|
||||
return obj
|
||||
}
|
||||
// Load the object from the database.
|
||||
enc, err := self.trie.TryGet(addr[:])
|
||||
enc, err := t.trie.TryGet(addr[:])
|
||||
if len(enc) == 0 {
|
||||
self.setError(err)
|
||||
t.setError(err)
|
||||
return nil
|
||||
}
|
||||
var data tradingExchangeObject
|
||||
|
|
@ -440,169 +442,169 @@ func (self *TradingStateDB) getStateExchangeObject(addr common.Hash) (stateObjec
|
|||
return nil
|
||||
}
|
||||
// Insert into the live set.
|
||||
obj := newStateExchanges(self, addr, data, self.MarkStateExchangeObjectDirty)
|
||||
self.stateExhangeObjects[addr] = obj
|
||||
obj := newStateExchanges(t, addr, data, t.MarkStateExchangeObjectDirty)
|
||||
t.stateExhangeObjects[addr] = obj
|
||||
return obj
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) setStateExchangeObject(object *tradingExchanges) {
|
||||
self.stateExhangeObjects[object.Hash()] = object
|
||||
self.stateExhangeObjectsDirty[object.Hash()] = struct{}{}
|
||||
func (t *TradingStateDB) setStateExchangeObject(object *tradingExchanges) {
|
||||
t.stateExhangeObjects[object.Hash()] = object
|
||||
t.stateExhangeObjectsDirty[object.Hash()] = struct{}{}
|
||||
}
|
||||
|
||||
// Retrieve a state object or create a new state object if nil.
|
||||
func (self *TradingStateDB) GetOrNewStateExchangeObject(addr common.Hash) *tradingExchanges {
|
||||
stateExchangeObject := self.getStateExchangeObject(addr)
|
||||
func (t *TradingStateDB) GetOrNewStateExchangeObject(addr common.Hash) *tradingExchanges {
|
||||
stateExchangeObject := t.getStateExchangeObject(addr)
|
||||
if stateExchangeObject == nil {
|
||||
stateExchangeObject = self.createExchangeObject(addr)
|
||||
stateExchangeObject = t.createExchangeObject(addr)
|
||||
}
|
||||
return stateExchangeObject
|
||||
}
|
||||
|
||||
// MarkStateAskObjectDirty adds the specified object to the dirty map to avoid costly
|
||||
// state object cache iteration to find a handful of modified ones.
|
||||
func (self *TradingStateDB) MarkStateExchangeObjectDirty(addr common.Hash) {
|
||||
self.stateExhangeObjectsDirty[addr] = struct{}{}
|
||||
func (t *TradingStateDB) MarkStateExchangeObjectDirty(addr common.Hash) {
|
||||
t.stateExhangeObjectsDirty[addr] = struct{}{}
|
||||
}
|
||||
|
||||
// createStateOrderListObject creates a new state object. If there is an existing orderId with
|
||||
// the given address, it is overwritten and returned as the second return value.
|
||||
func (self *TradingStateDB) createExchangeObject(hash common.Hash) (newobj *tradingExchanges) {
|
||||
newobj = newStateExchanges(self, hash, tradingExchangeObject{LendingCount: Zero, MediumPrice: Zero, MediumPriceBeforeEpoch: Zero, TotalQuantity: Zero}, self.MarkStateExchangeObjectDirty)
|
||||
func (t *TradingStateDB) createExchangeObject(hash common.Hash) (newobj *tradingExchanges) {
|
||||
newobj = newStateExchanges(t, hash, tradingExchangeObject{LendingCount: Zero, MediumPrice: Zero, MediumPriceBeforeEpoch: Zero, TotalQuantity: Zero}, t.MarkStateExchangeObjectDirty)
|
||||
newobj.setNonce(0) // sets the object to dirty
|
||||
self.setStateExchangeObject(newobj)
|
||||
t.setStateExchangeObject(newobj)
|
||||
return newobj
|
||||
}
|
||||
|
||||
// Copy creates a deep, independent copy of the state.
|
||||
// Snapshots of the copied state cannot be applied to the copy.
|
||||
func (self *TradingStateDB) Copy() *TradingStateDB {
|
||||
self.lock.Lock()
|
||||
defer self.lock.Unlock()
|
||||
func (t *TradingStateDB) Copy() *TradingStateDB {
|
||||
t.lock.Lock()
|
||||
defer t.lock.Unlock()
|
||||
|
||||
// Copy all the basic fields, initialize the memory ones
|
||||
state := &TradingStateDB{
|
||||
db: self.db,
|
||||
trie: self.db.CopyTrie(self.trie),
|
||||
stateExhangeObjects: make(map[common.Hash]*tradingExchanges, len(self.stateExhangeObjectsDirty)),
|
||||
stateExhangeObjectsDirty: make(map[common.Hash]struct{}, len(self.stateExhangeObjectsDirty)),
|
||||
db: t.db,
|
||||
trie: t.db.CopyTrie(t.trie),
|
||||
stateExhangeObjects: make(map[common.Hash]*tradingExchanges, len(t.stateExhangeObjectsDirty)),
|
||||
stateExhangeObjectsDirty: make(map[common.Hash]struct{}, len(t.stateExhangeObjectsDirty)),
|
||||
}
|
||||
// Copy the dirty states, logs, and preimages
|
||||
for addr := range self.stateExhangeObjectsDirty {
|
||||
for addr := range t.stateExhangeObjectsDirty {
|
||||
state.stateExhangeObjectsDirty[addr] = struct{}{}
|
||||
}
|
||||
for addr, exchangeObject := range self.stateExhangeObjects {
|
||||
for addr, exchangeObject := range t.stateExhangeObjects {
|
||||
state.stateExhangeObjects[addr] = exchangeObject.deepCopy(state, state.MarkStateExchangeObjectDirty)
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
func (s *TradingStateDB) clearJournalAndRefund() {
|
||||
s.journal = nil
|
||||
s.validRevisions = s.validRevisions[:0]
|
||||
func (t *TradingStateDB) clearJournalAndRefund() {
|
||||
t.journal = nil
|
||||
t.validRevisions = t.validRevisions[:0]
|
||||
}
|
||||
|
||||
// Snapshot returns an identifier for the current revision of the state.
|
||||
func (self *TradingStateDB) Snapshot() int {
|
||||
id := self.nextRevisionId
|
||||
self.nextRevisionId++
|
||||
self.validRevisions = append(self.validRevisions, revision{id, len(self.journal)})
|
||||
func (t *TradingStateDB) Snapshot() int {
|
||||
id := t.nextRevisionId
|
||||
t.nextRevisionId++
|
||||
t.validRevisions = append(t.validRevisions, revision{id, len(t.journal)})
|
||||
return id
|
||||
}
|
||||
|
||||
// RevertToSnapshot reverts all state changes made since the given revision.
|
||||
func (self *TradingStateDB) RevertToSnapshot(revid int) {
|
||||
func (t *TradingStateDB) RevertToSnapshot(revid int) {
|
||||
// Find the snapshot in the stack of valid snapshots.
|
||||
idx := sort.Search(len(self.validRevisions), func(i int) bool {
|
||||
return self.validRevisions[i].id >= revid
|
||||
idx := sort.Search(len(t.validRevisions), func(i int) bool {
|
||||
return t.validRevisions[i].id >= revid
|
||||
})
|
||||
if idx == len(self.validRevisions) || self.validRevisions[idx].id != revid {
|
||||
if idx == len(t.validRevisions) || t.validRevisions[idx].id != revid {
|
||||
panic(fmt.Errorf("revision id %v cannot be reverted", revid))
|
||||
}
|
||||
snapshot := self.validRevisions[idx].journalIndex
|
||||
snapshot := t.validRevisions[idx].journalIndex
|
||||
|
||||
// Replay the journal to undo changes.
|
||||
for i := len(self.journal) - 1; i >= snapshot; i-- {
|
||||
self.journal[i].undo(self)
|
||||
for i := len(t.journal) - 1; i >= snapshot; i-- {
|
||||
t.journal[i].undo(t)
|
||||
}
|
||||
self.journal = self.journal[:snapshot]
|
||||
t.journal = t.journal[:snapshot]
|
||||
|
||||
// Remove invalidated snapshots from the stack.
|
||||
self.validRevisions = self.validRevisions[:idx]
|
||||
t.validRevisions = t.validRevisions[:idx]
|
||||
}
|
||||
|
||||
// Finalise finalises the state by removing the self destructed objects
|
||||
// and clears the journal as well as the refunds.
|
||||
func (s *TradingStateDB) Finalise() {
|
||||
func (t *TradingStateDB) Finalise() {
|
||||
// Commit objects to the trie.
|
||||
for addr, stateObject := range s.stateExhangeObjects {
|
||||
if _, isDirty := s.stateExhangeObjectsDirty[addr]; isDirty {
|
||||
for addr, stateObject := range t.stateExhangeObjects {
|
||||
if _, isDirty := t.stateExhangeObjectsDirty[addr]; isDirty {
|
||||
// Write any storage changes in the state object to its storage trie.
|
||||
err := stateObject.updateAsksRoot(s.db)
|
||||
err := stateObject.updateAsksRoot(t.db)
|
||||
if err != nil {
|
||||
log.Warn("Finalise updateAsksRoot", "err", err, "addr", addr, "stateObject", *stateObject)
|
||||
}
|
||||
stateObject.updateBidsRoot(s.db)
|
||||
stateObject.updateOrdersRoot(s.db)
|
||||
stateObject.updateLiquidationPriceRoot(s.db)
|
||||
stateObject.updateBidsRoot(t.db)
|
||||
stateObject.updateOrdersRoot(t.db)
|
||||
stateObject.updateLiquidationPriceRoot(t.db)
|
||||
// Update the object in the main orderId trie.
|
||||
s.updateStateExchangeObject(stateObject)
|
||||
t.updateStateExchangeObject(stateObject)
|
||||
//delete(s.stateExhangeObjectsDirty, addr)
|
||||
}
|
||||
}
|
||||
s.clearJournalAndRefund()
|
||||
t.clearJournalAndRefund()
|
||||
}
|
||||
|
||||
// IntermediateRoot computes the current root orderBookHash of the state trie.
|
||||
// It is called in between transactions to get the root orderBookHash that
|
||||
// goes into transaction receipts.
|
||||
func (s *TradingStateDB) IntermediateRoot() common.Hash {
|
||||
s.Finalise()
|
||||
return s.trie.Hash()
|
||||
func (t *TradingStateDB) IntermediateRoot() common.Hash {
|
||||
t.Finalise()
|
||||
return t.trie.Hash()
|
||||
}
|
||||
|
||||
// Commit writes the state to the underlying in-memory trie database.
|
||||
func (s *TradingStateDB) Commit() (root common.Hash, err error) {
|
||||
defer s.clearJournalAndRefund()
|
||||
func (t *TradingStateDB) Commit() (root common.Hash, err error) {
|
||||
defer t.clearJournalAndRefund()
|
||||
// Commit objects to the trie.
|
||||
for addr, stateObject := range s.stateExhangeObjects {
|
||||
if _, isDirty := s.stateExhangeObjectsDirty[addr]; isDirty {
|
||||
for addr, stateObject := range t.stateExhangeObjects {
|
||||
if _, isDirty := t.stateExhangeObjectsDirty[addr]; isDirty {
|
||||
// Write any storage changes in the state object to its storage trie.
|
||||
if err := stateObject.CommitAsksTrie(s.db); err != nil {
|
||||
if err := stateObject.CommitAsksTrie(t.db); err != nil {
|
||||
return EmptyHash, err
|
||||
}
|
||||
if err := stateObject.CommitBidsTrie(s.db); err != nil {
|
||||
if err := stateObject.CommitBidsTrie(t.db); err != nil {
|
||||
return EmptyHash, err
|
||||
}
|
||||
if err := stateObject.CommitOrdersTrie(s.db); err != nil {
|
||||
if err := stateObject.CommitOrdersTrie(t.db); err != nil {
|
||||
return EmptyHash, err
|
||||
}
|
||||
if err := stateObject.CommitLiquidationPriceTrie(s.db); err != nil {
|
||||
if err := stateObject.CommitLiquidationPriceTrie(t.db); err != nil {
|
||||
return EmptyHash, err
|
||||
}
|
||||
// Update the object in the main orderId trie.
|
||||
s.updateStateExchangeObject(stateObject)
|
||||
delete(s.stateExhangeObjectsDirty, addr)
|
||||
t.updateStateExchangeObject(stateObject)
|
||||
delete(t.stateExhangeObjectsDirty, addr)
|
||||
}
|
||||
}
|
||||
// Write trie changes.
|
||||
root, err = s.trie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
root, err = t.trie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
var exchange tradingExchangeObject
|
||||
if err := rlp.DecodeBytes(leaf, &exchange); err != nil {
|
||||
return nil
|
||||
}
|
||||
if exchange.AskRoot != EmptyRoot {
|
||||
s.db.TrieDB().Reference(exchange.AskRoot, parent)
|
||||
t.db.TrieDB().Reference(exchange.AskRoot, parent)
|
||||
}
|
||||
if exchange.BidRoot != EmptyRoot {
|
||||
s.db.TrieDB().Reference(exchange.BidRoot, parent)
|
||||
t.db.TrieDB().Reference(exchange.BidRoot, parent)
|
||||
}
|
||||
if exchange.OrderRoot != EmptyRoot {
|
||||
s.db.TrieDB().Reference(exchange.OrderRoot, parent)
|
||||
t.db.TrieDB().Reference(exchange.OrderRoot, parent)
|
||||
}
|
||||
if exchange.LiquidationPriceRoot != EmptyRoot {
|
||||
s.db.TrieDB().Reference(exchange.LiquidationPriceRoot, parent)
|
||||
t.db.TrieDB().Reference(exchange.LiquidationPriceRoot, parent)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
|
@ -610,19 +612,19 @@ func (s *TradingStateDB) Commit() (root common.Hash, err error) {
|
|||
return root, err
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) GetAllLowerLiquidationPriceData(orderBook common.Hash, limit *big.Int) map[*big.Int]map[common.Hash][]common.Hash {
|
||||
func (t *TradingStateDB) GetAllLowerLiquidationPriceData(orderBook common.Hash, limit *big.Int) map[*big.Int]map[common.Hash][]common.Hash {
|
||||
result := map[*big.Int]map[common.Hash][]common.Hash{}
|
||||
orderbookState := self.getStateExchangeObject(orderBook)
|
||||
orderbookState := t.getStateExchangeObject(orderBook)
|
||||
if orderbookState == nil {
|
||||
return result
|
||||
}
|
||||
mapPrices := orderbookState.getAllLowerLiquidationPrice(self.db, common.BigToHash(limit))
|
||||
mapPrices := orderbookState.getAllLowerLiquidationPrice(t.db, common.BigToHash(limit))
|
||||
for priceHash, liquidationState := range mapPrices {
|
||||
price := new(big.Int).SetBytes(priceHash[:])
|
||||
log.Debug("GetAllLowerLiquidationPriceData", "price", price, "limit", limit)
|
||||
if liquidationState != nil && price.Sign() > 0 && price.Cmp(limit) < 0 {
|
||||
liquidationData := map[common.Hash][]common.Hash{}
|
||||
priceLiquidationData := liquidationState.getAllLiquidationData(self.db)
|
||||
priceLiquidationData := liquidationState.getAllLiquidationData(t.db)
|
||||
for lendingBook, data := range priceLiquidationData {
|
||||
if len(data) == 0 {
|
||||
continue
|
||||
|
|
@ -641,16 +643,16 @@ func (self *TradingStateDB) GetAllLowerLiquidationPriceData(orderBook common.Has
|
|||
return result
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) GetHighestLiquidationPriceData(orderBook common.Hash, price *big.Int) (*big.Int, map[common.Hash][]common.Hash) {
|
||||
func (t *TradingStateDB) GetHighestLiquidationPriceData(orderBook common.Hash, price *big.Int) (*big.Int, map[common.Hash][]common.Hash) {
|
||||
liquidationData := map[common.Hash][]common.Hash{}
|
||||
orderbookState := self.getStateExchangeObject(orderBook)
|
||||
orderbookState := t.getStateExchangeObject(orderBook)
|
||||
if orderbookState == nil {
|
||||
return common.Big0, liquidationData
|
||||
}
|
||||
highestPriceHash, liquidationState := orderbookState.getHighestLiquidationPrice(self.db)
|
||||
highestPriceHash, liquidationState := orderbookState.getHighestLiquidationPrice(t.db)
|
||||
highestPrice := new(big.Int).SetBytes(highestPriceHash[:])
|
||||
if liquidationState != nil && highestPrice.Sign() > 0 && price.Cmp(highestPrice) < 0 {
|
||||
priceLiquidationData := liquidationState.getAllLiquidationData(self.db)
|
||||
priceLiquidationData := liquidationState.getAllLiquidationData(t.db)
|
||||
for lendingBook, data := range priceLiquidationData {
|
||||
if len(data) == 0 {
|
||||
continue
|
||||
|
|
@ -667,26 +669,26 @@ func (self *TradingStateDB) GetHighestLiquidationPriceData(orderBook common.Hash
|
|||
return highestPrice, liquidationData
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) InsertLiquidationPrice(orderBook common.Hash, price *big.Int, lendingBook common.Hash, tradeId uint64) {
|
||||
func (t *TradingStateDB) InsertLiquidationPrice(orderBook common.Hash, price *big.Int, lendingBook common.Hash, tradeId uint64) {
|
||||
tradIdHash := common.Uint64ToHash(tradeId)
|
||||
priceHash := common.BigToHash(price)
|
||||
orderBookState := self.getStateExchangeObject(orderBook)
|
||||
orderBookState := t.getStateExchangeObject(orderBook)
|
||||
if orderBookState == nil {
|
||||
orderBookState = self.createExchangeObject(orderBook)
|
||||
orderBookState = t.createExchangeObject(orderBook)
|
||||
}
|
||||
liquidationPriceState := orderBookState.getStateLiquidationPrice(self.db, priceHash)
|
||||
liquidationPriceState := orderBookState.getStateLiquidationPrice(t.db, priceHash)
|
||||
if liquidationPriceState == nil {
|
||||
liquidationPriceState = orderBookState.createStateLiquidationPrice(self.db, priceHash)
|
||||
liquidationPriceState = orderBookState.createStateLiquidationPrice(t.db, priceHash)
|
||||
}
|
||||
lendingBookState := liquidationPriceState.getStateLendingBook(self.db, lendingBook)
|
||||
lendingBookState := liquidationPriceState.getStateLendingBook(t.db, lendingBook)
|
||||
if lendingBookState == nil {
|
||||
lendingBookState = liquidationPriceState.createLendingBook(self.db, lendingBook)
|
||||
lendingBookState = liquidationPriceState.createLendingBook(t.db, lendingBook)
|
||||
}
|
||||
lendingBookState.insertTradingId(self.db, tradIdHash)
|
||||
lendingBookState.insertTradingId(t.db, tradIdHash)
|
||||
lendingBookState.AddVolume(One)
|
||||
liquidationPriceState.AddVolume(One)
|
||||
orderBookState.addLendingCount(One)
|
||||
self.journal = append(self.journal, insertLiquidationPrice{
|
||||
t.journal = append(t.journal, insertLiquidationPrice{
|
||||
orderBook: orderBook,
|
||||
price: price,
|
||||
lendingBook: lendingBook,
|
||||
|
|
@ -694,35 +696,35 @@ func (self *TradingStateDB) InsertLiquidationPrice(orderBook common.Hash, price
|
|||
})
|
||||
}
|
||||
|
||||
func (self *TradingStateDB) RemoveLiquidationPrice(orderBook common.Hash, price *big.Int, lendingBook common.Hash, tradeId uint64) error {
|
||||
func (t *TradingStateDB) RemoveLiquidationPrice(orderBook common.Hash, price *big.Int, lendingBook common.Hash, tradeId uint64) error {
|
||||
tradeIdHash := common.Uint64ToHash(tradeId)
|
||||
priceHash := common.BigToHash(price)
|
||||
orderbookState := self.getStateExchangeObject(orderBook)
|
||||
orderbookState := t.getStateExchangeObject(orderBook)
|
||||
if orderbookState == nil {
|
||||
return fmt.Errorf("order book not found : %s ", orderBook.Hex())
|
||||
return fmt.Errorf("not found order book: %s", orderBook.Hex())
|
||||
}
|
||||
liquidationPriceState := orderbookState.getStateLiquidationPrice(self.db, priceHash)
|
||||
liquidationPriceState := orderbookState.getStateLiquidationPrice(t.db, priceHash)
|
||||
if liquidationPriceState == nil {
|
||||
return fmt.Errorf("liquidation price not found : %s , %s ", orderBook.Hex(), priceHash.Hex())
|
||||
return fmt.Errorf("not found liquidation price: %s , %s", orderBook.Hex(), priceHash.Hex())
|
||||
}
|
||||
lendingBookState := liquidationPriceState.getStateLendingBook(self.db, lendingBook)
|
||||
lendingBookState := liquidationPriceState.getStateLendingBook(t.db, lendingBook)
|
||||
if lendingBookState == nil {
|
||||
return fmt.Errorf("lending book not found : %s , %s ,%s ", orderBook.Hex(), priceHash.Hex(), lendingBook.Hex())
|
||||
return fmt.Errorf("not found lending book: %s , %s ,%s", orderBook.Hex(), priceHash.Hex(), lendingBook.Hex())
|
||||
}
|
||||
if !lendingBookState.Exist(self.db, tradeIdHash) {
|
||||
return fmt.Errorf("trade id not found : %s , %s ,%s , %d ", orderBook.Hex(), priceHash.Hex(), lendingBook.Hex(), tradeId)
|
||||
if !lendingBookState.Exist(t.db, tradeIdHash) {
|
||||
return fmt.Errorf("not found trade id: %s, %s ,%s , %d", orderBook.Hex(), priceHash.Hex(), lendingBook.Hex(), tradeId)
|
||||
}
|
||||
lendingBookState.removeTradingId(self.db, tradeIdHash)
|
||||
lendingBookState.removeTradingId(t.db, tradeIdHash)
|
||||
lendingBookState.subVolume(One)
|
||||
liquidationPriceState.subVolume(One)
|
||||
if liquidationPriceState.Volume().Sign() == 0 {
|
||||
err := orderbookState.getLiquidationPriceTrie(self.db).TryDelete(priceHash[:])
|
||||
err := orderbookState.getLiquidationPriceTrie(t.db).TryDelete(priceHash[:])
|
||||
if err != nil {
|
||||
log.Warn("RemoveLiquidationPrice getLiquidationPriceTrie.TryDelete", "err", err, "priceHash", priceHash[:])
|
||||
}
|
||||
}
|
||||
orderbookState.subLendingCount(One)
|
||||
self.journal = append(self.journal, removeLiquidationPrice{
|
||||
t.journal = append(t.journal, removeLiquidationPrice{
|
||||
orderBook: orderBook,
|
||||
price: price,
|
||||
lendingBook: lendingBook,
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto/sha3"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -136,7 +136,7 @@ func (t *Trade) SetBSON(raw bson.Raw) error {
|
|||
// The OrderHash, Amount, Taker and TradeNonce attributes must be
|
||||
// set before attempting to compute the trade orderBookHash
|
||||
func (t *Trade) ComputeHash() common.Hash {
|
||||
sha := sha3.NewKeccak256()
|
||||
sha := sha3.NewLegacyKeccak256()
|
||||
sha.Write(t.MakerOrderHash.Bytes())
|
||||
sha.Write(t.TakerOrderHash.Bytes())
|
||||
return common.BytesToHash(sha.Sum(nil))
|
||||
|
|
|
|||
|
|
@ -8,10 +8,8 @@ import (
|
|||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
)
|
||||
|
||||
type BatchItem struct {
|
||||
|
|
@ -21,7 +19,6 @@ type BatchItem struct {
|
|||
type BatchDatabase struct {
|
||||
db ethdb.Database
|
||||
emptyKey []byte
|
||||
cacheItems *lru.Cache // Cache for reading
|
||||
lock sync.RWMutex
|
||||
cacheLimit int
|
||||
Debug bool
|
||||
|
|
@ -44,11 +41,8 @@ func NewBatchDatabaseWithEncode(datadir string, cacheLimit int) *BatchDatabase {
|
|||
itemCacheLimit = cacheLimit
|
||||
}
|
||||
|
||||
cacheItems, _ := lru.New(itemCacheLimit)
|
||||
|
||||
batchDB := &BatchDatabase{
|
||||
db: db,
|
||||
cacheItems: cacheItems,
|
||||
emptyKey: EmptyKey(), // pre alloc for comparison
|
||||
cacheLimit: itemCacheLimit,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate"
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCxlending/lendingstate"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/lru"
|
||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/globalsign/mgo"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -32,7 +32,7 @@ type MongoDatabase struct {
|
|||
Session *mgo.Session
|
||||
dbName string
|
||||
emptyKey []byte
|
||||
cacheItems *lru.Cache // Cache for reading
|
||||
cacheItems *lru.Cache[string, interface{}] // Cache for reading
|
||||
orderBulk *mgo.Bulk
|
||||
tradeBulk *mgo.Bulk
|
||||
epochPriceBulk *mgo.Bulk
|
||||
|
|
@ -64,12 +64,11 @@ func NewMongoDatabase(session *mgo.Session, dbName string, mongoURL string, repl
|
|||
if cacheLimit > 0 {
|
||||
itemCacheLimit = cacheLimit
|
||||
}
|
||||
cacheItems, _ := lru.New(itemCacheLimit)
|
||||
|
||||
db := &MongoDatabase{
|
||||
Session: session,
|
||||
dbName: dbName,
|
||||
cacheItems: cacheItems,
|
||||
cacheItems: lru.NewCache[string, interface{}](itemCacheLimit),
|
||||
}
|
||||
if err := db.EnsureIndexes(); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -101,7 +100,7 @@ func (db *MongoDatabase) HasObject(hash common.Hash, val interface{}) (bool, err
|
|||
err error
|
||||
)
|
||||
query := bson.M{"hash": hash.Hex()}
|
||||
switch val.(type) {
|
||||
switch item := val.(type) {
|
||||
case *tradingstate.OrderItem:
|
||||
// Find key in ordersCollection collection
|
||||
count, err = sc.DB(db.dbName).C(ordersCollection).Find(query).Limit(1).Count()
|
||||
|
|
@ -126,7 +125,6 @@ func (db *MongoDatabase) HasObject(hash common.Hash, val interface{}) (bool, err
|
|||
}
|
||||
case *lendingstate.LendingItem:
|
||||
// Find key in lendingItemsCollection collection
|
||||
item := val.(*lendingstate.LendingItem)
|
||||
switch item.Type {
|
||||
case lendingstate.Repay:
|
||||
count, err = sc.DB(db.dbName).C(lendingRepayCollection).Find(query).Limit(1).Count()
|
||||
|
|
@ -176,7 +174,7 @@ func (db *MongoDatabase) GetObject(hash common.Hash, val interface{}) (interface
|
|||
|
||||
query := bson.M{"hash": hash.Hex()}
|
||||
|
||||
switch val.(type) {
|
||||
switch item := val.(type) {
|
||||
case *tradingstate.OrderItem:
|
||||
var oi *tradingstate.OrderItem
|
||||
err := sc.DB(db.dbName).C(ordersCollection).Find(query).One(&oi)
|
||||
|
|
@ -196,7 +194,6 @@ func (db *MongoDatabase) GetObject(hash common.Hash, val interface{}) (interface
|
|||
case *lendingstate.LendingItem:
|
||||
var li *lendingstate.LendingItem
|
||||
var err error
|
||||
item := val.(*lendingstate.LendingItem)
|
||||
switch item.Type {
|
||||
case lendingstate.Repay:
|
||||
err = sc.DB(db.dbName).C(lendingRepayCollection).Find(query).One(&li)
|
||||
|
|
@ -230,62 +227,58 @@ func (db *MongoDatabase) PutObject(hash common.Hash, val interface{}) error {
|
|||
cacheKey := db.getCacheKey(hash.Bytes())
|
||||
db.cacheItems.Add(cacheKey, val)
|
||||
|
||||
switch val.(type) {
|
||||
switch item := val.(type) {
|
||||
case *tradingstate.Trade:
|
||||
// PutObject trade into tradesCollection collection
|
||||
db.tradeBulk.Insert(val.(*tradingstate.Trade))
|
||||
db.tradeBulk.Insert(item)
|
||||
case *tradingstate.OrderItem:
|
||||
// PutObject order into ordersCollection collection
|
||||
o := val.(*tradingstate.OrderItem)
|
||||
if o.Status == tradingstate.OrderStatusOpen {
|
||||
db.orderBulk.Insert(o)
|
||||
if item.Status == tradingstate.OrderStatusOpen {
|
||||
db.orderBulk.Insert(item)
|
||||
} else {
|
||||
query := bson.M{"hash": o.Hash.Hex()}
|
||||
db.orderBulk.Upsert(query, o)
|
||||
query := bson.M{"hash": item.Hash.Hex()}
|
||||
db.orderBulk.Upsert(query, item)
|
||||
}
|
||||
return nil
|
||||
case *tradingstate.EpochPriceItem:
|
||||
item := val.(*tradingstate.EpochPriceItem)
|
||||
query := bson.M{"hash": item.Hash.Hex()}
|
||||
db.epochPriceBulk.Upsert(query, item)
|
||||
return nil
|
||||
case *lendingstate.LendingTrade:
|
||||
lt := val.(*lendingstate.LendingTrade)
|
||||
// PutObject LendingTrade into tradesCollection collection
|
||||
if existed, err := db.HasObject(hash, val); err == nil && existed {
|
||||
query := bson.M{"hash": lt.Hash.Hex()}
|
||||
db.lendingTradeBulk.Upsert(query, lt)
|
||||
query := bson.M{"hash": item.Hash.Hex()}
|
||||
db.lendingTradeBulk.Upsert(query, item)
|
||||
} else {
|
||||
db.lendingTradeBulk.Insert(lt)
|
||||
db.lendingTradeBulk.Insert(item)
|
||||
}
|
||||
case *lendingstate.LendingItem:
|
||||
// PutObject order into ordersCollection collection
|
||||
li := val.(*lendingstate.LendingItem)
|
||||
switch li.Type {
|
||||
switch item.Type {
|
||||
case lendingstate.Repay:
|
||||
if li.Status != lendingstate.LendingStatusReject {
|
||||
li.Status = lendingstate.Repay
|
||||
if item.Status != lendingstate.LendingStatusReject {
|
||||
item.Status = lendingstate.Repay
|
||||
}
|
||||
db.repayBulk.Insert(li)
|
||||
db.repayBulk.Insert(item)
|
||||
return nil
|
||||
case lendingstate.TopUp:
|
||||
if li.Status != lendingstate.LendingStatusReject {
|
||||
li.Status = lendingstate.TopUp
|
||||
if item.Status != lendingstate.LendingStatusReject {
|
||||
item.Status = lendingstate.TopUp
|
||||
}
|
||||
db.topUpBulk.Insert(li)
|
||||
db.topUpBulk.Insert(item)
|
||||
return nil
|
||||
case lendingstate.Recall:
|
||||
if li.Status != lendingstate.LendingStatusReject {
|
||||
li.Status = lendingstate.Recall
|
||||
if item.Status != lendingstate.LendingStatusReject {
|
||||
item.Status = lendingstate.Recall
|
||||
}
|
||||
db.recallBulk.Insert(li)
|
||||
db.recallBulk.Insert(item)
|
||||
return nil
|
||||
default:
|
||||
if li.Status == lendingstate.LendingStatusOpen {
|
||||
db.lendingItemBulk.Insert(li)
|
||||
if item.Status == lendingstate.LendingStatusOpen {
|
||||
db.lendingItemBulk.Insert(item)
|
||||
} else {
|
||||
query := bson.M{"hash": li.Hash.Hex()}
|
||||
db.lendingItemBulk.Upsert(query, li)
|
||||
query := bson.M{"hash": item.Hash.Hex()}
|
||||
db.lendingItemBulk.Upsert(query, item)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -313,7 +306,7 @@ func (db *MongoDatabase) DeleteObject(hash common.Hash, val interface{}) error {
|
|||
|
||||
if found {
|
||||
var err error
|
||||
switch val.(type) {
|
||||
switch item := val.(type) {
|
||||
case *tradingstate.OrderItem:
|
||||
err = sc.DB(db.dbName).C(ordersCollection).Remove(query)
|
||||
if err != nil && err != mgo.ErrNotFound {
|
||||
|
|
@ -325,7 +318,6 @@ func (db *MongoDatabase) DeleteObject(hash common.Hash, val interface{}) error {
|
|||
return fmt.Errorf("failed to delete XDCx trade. Err: %v", err)
|
||||
}
|
||||
case *lendingstate.LendingItem:
|
||||
item := val.(*lendingstate.LendingItem)
|
||||
switch item.Type {
|
||||
case lendingstate.Repay:
|
||||
err = sc.DB(db.dbName).C(lendingRepayCollection).Remove(query)
|
||||
|
|
@ -424,7 +416,7 @@ func (db *MongoDatabase) DeleteItemByTxHash(txhash common.Hash, val interface{})
|
|||
defer sc.Close()
|
||||
|
||||
query := bson.M{"txHash": txhash.Hex()}
|
||||
switch val.(type) {
|
||||
switch item := val.(type) {
|
||||
case *tradingstate.OrderItem:
|
||||
if err := sc.DB(db.dbName).C(ordersCollection).Remove(query); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("DeleteItemByTxHash: failed to delete order", "txhash", txhash, "err", err)
|
||||
|
|
@ -434,7 +426,6 @@ func (db *MongoDatabase) DeleteItemByTxHash(txhash common.Hash, val interface{})
|
|||
log.Error("DeleteItemByTxHash: failed to delete trade", "txhash", txhash, "err", err)
|
||||
}
|
||||
case *lendingstate.LendingItem:
|
||||
item := val.(*lendingstate.LendingItem)
|
||||
switch item.Type {
|
||||
case lendingstate.Repay:
|
||||
if err := sc.DB(db.dbName).C(lendingRepayCollection).Remove(query); err != nil && err != mgo.ErrNotFound {
|
||||
|
|
@ -473,7 +464,7 @@ func (db *MongoDatabase) GetListItemByTxHash(txhash common.Hash, val interface{}
|
|||
defer sc.Close()
|
||||
|
||||
query := bson.M{"txHash": txhash.Hex()}
|
||||
switch val.(type) {
|
||||
switch item := val.(type) {
|
||||
case *tradingstate.OrderItem:
|
||||
result := []*tradingstate.OrderItem{}
|
||||
if err := sc.DB(db.dbName).C(ordersCollection).Find(query).All(&result); err != nil && err != mgo.ErrNotFound {
|
||||
|
|
@ -487,7 +478,6 @@ func (db *MongoDatabase) GetListItemByTxHash(txhash common.Hash, val interface{}
|
|||
}
|
||||
return result
|
||||
case *lendingstate.LendingItem:
|
||||
item := val.(*lendingstate.LendingItem)
|
||||
result := []*lendingstate.LendingItem{}
|
||||
switch item.Type {
|
||||
case lendingstate.Repay:
|
||||
|
|
@ -529,7 +519,7 @@ func (db *MongoDatabase) GetListItemByHashes(hashes []string, val interface{}) i
|
|||
|
||||
query := bson.M{"hash": bson.M{"$in": hashes}}
|
||||
|
||||
switch val.(type) {
|
||||
switch item := val.(type) {
|
||||
case *tradingstate.OrderItem:
|
||||
result := []*tradingstate.OrderItem{}
|
||||
if err := sc.DB(db.dbName).C(ordersCollection).Find(query).All(&result); err != nil && err != mgo.ErrNotFound {
|
||||
|
|
@ -543,7 +533,6 @@ func (db *MongoDatabase) GetListItemByHashes(hashes []string, val interface{}) i
|
|||
}
|
||||
return result
|
||||
case *lendingstate.LendingItem:
|
||||
item := val.(*lendingstate.LendingItem)
|
||||
result := []*lendingstate.LendingItem{}
|
||||
switch item.Type {
|
||||
case lendingstate.Repay:
|
||||
|
|
@ -835,7 +824,10 @@ func (db *MongoDatabase) EnsureIndexes() error {
|
|||
}
|
||||
|
||||
func (db *MongoDatabase) Close() error {
|
||||
return db.Close()
|
||||
if db.Session != nil {
|
||||
db.Session.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// HasAncient returns an error as we don't have a backing chain freezer.
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/XDCxDAO"
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCxlending/lendingstate"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/lru"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/prque"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
|
|
@ -20,7 +21,6 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/XinFinOrg/XDPoSChain/p2p"
|
||||
"github.com/XinFinOrg/XDPoSChain/rpc"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -42,8 +42,8 @@ type Lending struct {
|
|||
orderNonce map[common.Address]*big.Int
|
||||
|
||||
XDCx *XDCx.XDCX
|
||||
lendingItemHistory *lru.Cache
|
||||
lendingTradeHistory *lru.Cache
|
||||
lendingItemHistory *lru.Cache[common.Hash, map[common.Hash]lendingstate.LendingItemHistoryItem]
|
||||
lendingTradeHistory *lru.Cache[common.Hash, map[common.Hash]lendingstate.LendingTradeHistoryItem]
|
||||
}
|
||||
|
||||
func (l *Lending) Protocols() []p2p.Protocol {
|
||||
|
|
@ -62,13 +62,11 @@ func (l *Lending) Stop() error {
|
|||
}
|
||||
|
||||
func New(XDCx *XDCx.XDCX) *Lending {
|
||||
itemCache, _ := lru.New(defaultCacheLimit)
|
||||
lendingTradeCache, _ := lru.New(defaultCacheLimit)
|
||||
lending := &Lending{
|
||||
orderNonce: make(map[common.Address]*big.Int),
|
||||
Triegc: prque.New(nil),
|
||||
lendingItemHistory: itemCache,
|
||||
lendingTradeHistory: lendingTradeCache,
|
||||
lendingItemHistory: lru.NewCache[common.Hash, map[common.Hash]lendingstate.LendingItemHistoryItem](defaultCacheLimit),
|
||||
lendingTradeHistory: lru.NewCache[common.Hash, map[common.Hash]lendingstate.LendingTradeHistoryItem](defaultCacheLimit),
|
||||
}
|
||||
lending.StateCache = lendingstate.NewDatabase(XDCx.GetLevelDB())
|
||||
lending.XDCx = XDCx
|
||||
|
|
@ -311,7 +309,7 @@ func (l *Lending) SyncDataToSDKNode(chain consensus.ChainContext, statedb *state
|
|||
}
|
||||
// maker dirty order
|
||||
makerFilledAmount := big.NewInt(0)
|
||||
makerOrderHash := common.Hash{}
|
||||
var makerOrderHash common.Hash
|
||||
if updatedTakerLendingItem.Side == lendingstate.Borrowing {
|
||||
makerOrderHash = tradeRecord.InvestingOrderHash
|
||||
} else {
|
||||
|
|
@ -665,7 +663,7 @@ func (l *Lending) GetLendingState(block *types.Block, author common.Address) (*l
|
|||
return nil, err
|
||||
}
|
||||
if l.StateCache == nil {
|
||||
return nil, errors.New("Not initialized XDCx")
|
||||
return nil, errors.New("not initialized XDCx")
|
||||
}
|
||||
state, err := lendingstate.New(root, l.StateCache)
|
||||
if err != nil {
|
||||
|
|
@ -684,10 +682,7 @@ func (l *Lending) HasLendingState(block *types.Block, author common.Address) boo
|
|||
return false
|
||||
}
|
||||
_, err = l.StateCache.OpenTrie(root)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (l *Lending) GetTriegc() *prque.Prque {
|
||||
|
|
@ -708,12 +703,9 @@ func (l *Lending) GetLendingStateRoot(block *types.Block, author common.Address)
|
|||
}
|
||||
|
||||
func (l *Lending) UpdateLendingItemCache(LendingToken, CollateralToken common.Address, hash common.Hash, txhash common.Hash, lastState lendingstate.LendingItemHistoryItem) {
|
||||
var lendingCacheAtTxHash map[common.Hash]lendingstate.LendingItemHistoryItem
|
||||
c, ok := l.lendingItemHistory.Get(txhash)
|
||||
if !ok || c == nil {
|
||||
lendingCacheAtTxHash, ok := l.lendingItemHistory.Get(txhash)
|
||||
if !ok || lendingCacheAtTxHash == nil {
|
||||
lendingCacheAtTxHash = make(map[common.Hash]lendingstate.LendingItemHistoryItem)
|
||||
} else {
|
||||
lendingCacheAtTxHash = c.(map[common.Hash]lendingstate.LendingItemHistoryItem)
|
||||
}
|
||||
orderKey := lendingstate.GetLendingItemHistoryKey(LendingToken, CollateralToken, hash)
|
||||
_, ok = lendingCacheAtTxHash[orderKey]
|
||||
|
|
@ -725,11 +717,9 @@ func (l *Lending) UpdateLendingItemCache(LendingToken, CollateralToken common.Ad
|
|||
|
||||
func (l *Lending) UpdateLendingTradeCache(hash common.Hash, txhash common.Hash, lastState lendingstate.LendingTradeHistoryItem) {
|
||||
var lendingCacheAtTxHash map[common.Hash]lendingstate.LendingTradeHistoryItem
|
||||
c, ok := l.lendingTradeHistory.Get(txhash)
|
||||
if !ok || c == nil {
|
||||
lendingCacheAtTxHash, ok := l.lendingTradeHistory.Get(txhash)
|
||||
if !ok || lendingCacheAtTxHash == nil {
|
||||
lendingCacheAtTxHash = make(map[common.Hash]lendingstate.LendingTradeHistoryItem)
|
||||
} else {
|
||||
lendingCacheAtTxHash = c.(map[common.Hash]lendingstate.LendingTradeHistoryItem)
|
||||
}
|
||||
_, ok = lendingCacheAtTxHash[hash]
|
||||
if !ok {
|
||||
|
|
@ -746,16 +736,15 @@ func (l *Lending) RollbackLendingData(txhash common.Hash) error {
|
|||
items := db.GetListItemByTxHash(txhash, &lendingstate.LendingItem{})
|
||||
if items != nil {
|
||||
for _, item := range items.([]*lendingstate.LendingItem) {
|
||||
c, ok := l.lendingItemHistory.Get(txhash)
|
||||
log.Debug("XDCxlending reorg: rollback lendingItem", "txhash", txhash.Hex(), "item", lendingstate.ToJSON(item), "lendingItemHistory", c)
|
||||
if !ok {
|
||||
cacheAtTxHash, ok := l.lendingItemHistory.Get(txhash)
|
||||
log.Debug("XDCxlending reorg: rollback lendingItem", "txhash", txhash.Hex(), "item", lendingstate.ToJSON(item), "lendingItemHistory", cacheAtTxHash)
|
||||
if !ok || cacheAtTxHash == nil {
|
||||
log.Debug("XDCxlending reorg: remove item due to no lendingItemHistory", "item", lendingstate.ToJSON(item))
|
||||
if err := db.DeleteObject(item.Hash, &lendingstate.LendingItem{}); err != nil {
|
||||
return fmt.Errorf("failed to remove reorg LendingItem. Err: %v . Item: %s", err.Error(), lendingstate.ToJSON(item))
|
||||
}
|
||||
continue
|
||||
}
|
||||
cacheAtTxHash := c.(map[common.Hash]lendingstate.LendingItemHistoryItem)
|
||||
lendingItemHistory := cacheAtTxHash[lendingstate.GetLendingItemHistoryKey(item.LendingToken, item.CollateralToken, item.Hash)]
|
||||
if (lendingItemHistory == lendingstate.LendingItemHistoryItem{}) {
|
||||
log.Debug("XDCxlending reorg: remove item due to empty lendingItemHistory", "item", lendingstate.ToJSON(item))
|
||||
|
|
@ -779,16 +768,15 @@ func (l *Lending) RollbackLendingData(txhash common.Hash) error {
|
|||
items = db.GetListItemByTxHash(txhash, &lendingstate.LendingTrade{})
|
||||
if items != nil {
|
||||
for _, trade := range items.([]*lendingstate.LendingTrade) {
|
||||
c, ok := l.lendingTradeHistory.Get(txhash)
|
||||
log.Debug("XDCxlending reorg: rollback LendingTrade", "txhash", txhash.Hex(), "trade", lendingstate.ToJSON(trade), "LendingTradeHistory", c)
|
||||
if !ok {
|
||||
cacheAtTxHash, ok := l.lendingTradeHistory.Get(txhash)
|
||||
log.Debug("XDCxlending reorg: rollback LendingTrade", "txhash", txhash.Hex(), "trade", lendingstate.ToJSON(trade), "LendingTradeHistory", cacheAtTxHash)
|
||||
if !ok || cacheAtTxHash == nil {
|
||||
log.Debug("XDCxlending reorg: remove trade due to no LendingTradeHistory", "trade", lendingstate.ToJSON(trade))
|
||||
if err := db.DeleteObject(trade.Hash, &lendingstate.LendingTrade{}); err != nil {
|
||||
return fmt.Errorf("failed to remove reorg LendingTrade. Err: %v . Trade: %s", err.Error(), lendingstate.ToJSON(trade))
|
||||
}
|
||||
continue
|
||||
}
|
||||
cacheAtTxHash := c.(map[common.Hash]lendingstate.LendingTradeHistoryItem)
|
||||
lendingTradeHistoryItem := cacheAtTxHash[trade.Hash]
|
||||
if (lendingTradeHistoryItem == lendingstate.LendingTradeHistoryItem{}) {
|
||||
log.Debug("XDCxlending reorg: remove trade due to empty LendingTradeHistory", "trade", lendingstate.ToJSON(trade))
|
||||
|
|
@ -926,7 +914,7 @@ func (l *Lending) ProcessLiquidationData(header *types.Header, chain consensus.C
|
|||
trade := lendingState.GetLendingTrade(lendingBook, tradingIdHash)
|
||||
log.Debug("TestRecall", "borrower", trade.Borrower.Hex(), "lendingToken", trade.LendingToken.Hex(), "collateral", trade.CollateralToken.Hex(), "price", price, "tradingIdHash", tradingIdHash.Hex())
|
||||
if trade.AutoTopUp {
|
||||
err, _, newTrade := l.ProcessRecallLendingTrade(lendingState, statedb, tradingState, lendingBook, tradingIdHash, newLiquidatePrice)
|
||||
_, newTrade, err := l.ProcessRecallLendingTrade(lendingState, statedb, tradingState, lendingBook, tradingIdHash, newLiquidatePrice)
|
||||
if err != nil {
|
||||
log.Error("ProcessRecallLendingTrade", "lendingBook", lendingBook.Hex(), "tradingIdHash", tradingIdHash.Hex(), "newLiquidatePrice", newLiquidatePrice, "err", err)
|
||||
return updatedTrades, liquidatedTrades, autoRepayTrades, autoTopUpTrades, autoRecallTrades, err
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||
"github.com/XinFinOrg/XDPoSChain/trie"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
)
|
||||
|
||||
// Trie cache generation limit after which to evic trie nodes from memory.
|
||||
|
|
@ -33,9 +32,6 @@ const (
|
|||
// Number of past tries to keep. This value is chosen such that
|
||||
// reasonable chain reorg depths will hit an existing trie.
|
||||
maxPastTries = 12
|
||||
|
||||
// Number of codehash->size associations to keep.
|
||||
codeSizeCacheSize = 100000
|
||||
)
|
||||
|
||||
// Database wraps access to tries and contract code.
|
||||
|
|
@ -78,18 +74,16 @@ type Trie interface {
|
|||
// intermediate trie-node memory pool between the low level storage layer and the
|
||||
// high level trie abstraction.
|
||||
func NewDatabase(db ethdb.Database) Database {
|
||||
csc, _ := lru.New(codeSizeCacheSize)
|
||||
return &cachingDB{
|
||||
db: trie.NewDatabase(db),
|
||||
codeSizeCache: csc,
|
||||
db: trie.NewDatabase(db),
|
||||
// codeSizeCache: csc,
|
||||
}
|
||||
}
|
||||
|
||||
type cachingDB struct {
|
||||
db *trie.Database
|
||||
mu sync.Mutex
|
||||
pastTries []*XDCXTrie
|
||||
codeSizeCache *lru.Cache
|
||||
db *trie.Database
|
||||
mu sync.Mutex
|
||||
pastTries []*XDCXTrie
|
||||
}
|
||||
|
||||
// OpenTrie opens the main account trie.
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@ package lendingstate
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||
"math/big"
|
||||
"sort"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||
"github.com/XinFinOrg/XDPoSChain/trie"
|
||||
)
|
||||
|
||||
|
|
@ -39,13 +39,13 @@ type DumpOrderBookInfo struct {
|
|||
LowestLiquidationTime *big.Int
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) DumpInvestingTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
|
||||
exhangeObject := self.getLendingExchange(orderBook)
|
||||
func (ls *LendingStateDB) DumpInvestingTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
|
||||
exhangeObject := ls.getLendingExchange(orderBook)
|
||||
if exhangeObject == nil {
|
||||
return nil, fmt.Errorf("Order book not found orderBook : %v ", orderBook.Hex())
|
||||
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
|
||||
}
|
||||
mapResult := map[*big.Int]DumpOrderList{}
|
||||
it := trie.NewIterator(exhangeObject.getInvestingTrie(self.db).NodeIterator(nil))
|
||||
it := trie.NewIterator(exhangeObject.getInvestingTrie(ls.db).NodeIterator(nil))
|
||||
for it.Next() {
|
||||
interestHash := common.BytesToHash(it.Key)
|
||||
if common.EmptyHash(interestHash) {
|
||||
|
|
@ -57,15 +57,15 @@ func (self *LendingStateDB) DumpInvestingTrie(orderBook common.Hash) (map[*big.I
|
|||
} else {
|
||||
var data itemList
|
||||
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
|
||||
return nil, fmt.Errorf("Fail when decode order iist orderBook : %v ,interest :%v ", orderBook.Hex(), interest)
|
||||
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , interest : %v", orderBook.Hex(), interest)
|
||||
}
|
||||
stateOrderList := newItemListState(orderBook, interestHash, data, nil)
|
||||
mapResult[interest] = stateOrderList.DumpItemList(self.db)
|
||||
mapResult[interest] = stateOrderList.DumpItemList(ls.db)
|
||||
}
|
||||
}
|
||||
for interestHash, itemList := range exhangeObject.investingStates {
|
||||
if itemList.Volume().Sign() > 0 {
|
||||
mapResult[new(big.Int).SetBytes(interestHash.Bytes())] = itemList.DumpItemList(self.db)
|
||||
mapResult[new(big.Int).SetBytes(interestHash.Bytes())] = itemList.DumpItemList(ls.db)
|
||||
}
|
||||
}
|
||||
listInterest := []*big.Int{}
|
||||
|
|
@ -82,13 +82,13 @@ func (self *LendingStateDB) DumpInvestingTrie(orderBook common.Hash) (map[*big.I
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) DumpBorrowingTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
|
||||
exhangeObject := self.getLendingExchange(orderBook)
|
||||
func (ls *LendingStateDB) DumpBorrowingTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
|
||||
exhangeObject := ls.getLendingExchange(orderBook)
|
||||
if exhangeObject == nil {
|
||||
return nil, fmt.Errorf("Order book not found orderBook : %v ", orderBook.Hex())
|
||||
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
|
||||
}
|
||||
mapResult := map[*big.Int]DumpOrderList{}
|
||||
it := trie.NewIterator(exhangeObject.getBorrowingTrie(self.db).NodeIterator(nil))
|
||||
it := trie.NewIterator(exhangeObject.getBorrowingTrie(ls.db).NodeIterator(nil))
|
||||
for it.Next() {
|
||||
interestHash := common.BytesToHash(it.Key)
|
||||
if common.EmptyHash(interestHash) {
|
||||
|
|
@ -100,15 +100,15 @@ func (self *LendingStateDB) DumpBorrowingTrie(orderBook common.Hash) (map[*big.I
|
|||
} else {
|
||||
var data itemList
|
||||
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
|
||||
return nil, fmt.Errorf("Fail when decode order iist orderBook : %v ,interest :%v ", orderBook.Hex(), interest)
|
||||
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , interest : %v", orderBook.Hex(), interest)
|
||||
}
|
||||
stateOrderList := newItemListState(orderBook, interestHash, data, nil)
|
||||
mapResult[interest] = stateOrderList.DumpItemList(self.db)
|
||||
mapResult[interest] = stateOrderList.DumpItemList(ls.db)
|
||||
}
|
||||
}
|
||||
for interestHash, itemList := range exhangeObject.borrowingStates {
|
||||
if itemList.Volume().Sign() > 0 {
|
||||
mapResult[new(big.Int).SetBytes(interestHash.Bytes())] = itemList.DumpItemList(self.db)
|
||||
mapResult[new(big.Int).SetBytes(interestHash.Bytes())] = itemList.DumpItemList(ls.db)
|
||||
}
|
||||
}
|
||||
listInterest := []*big.Int{}
|
||||
|
|
@ -125,13 +125,13 @@ func (self *LendingStateDB) DumpBorrowingTrie(orderBook common.Hash) (map[*big.I
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) GetInvestings(orderBook common.Hash) (map[*big.Int]*big.Int, error) {
|
||||
exhangeObject := self.getLendingExchange(orderBook)
|
||||
func (ls *LendingStateDB) GetInvestings(orderBook common.Hash) (map[*big.Int]*big.Int, error) {
|
||||
exhangeObject := ls.getLendingExchange(orderBook)
|
||||
if exhangeObject == nil {
|
||||
return nil, fmt.Errorf("Order book not found orderBook : %v ", orderBook.Hex())
|
||||
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
|
||||
}
|
||||
mapResult := map[*big.Int]*big.Int{}
|
||||
it := trie.NewIterator(exhangeObject.getInvestingTrie(self.db).NodeIterator(nil))
|
||||
it := trie.NewIterator(exhangeObject.getInvestingTrie(ls.db).NodeIterator(nil))
|
||||
for it.Next() {
|
||||
interestHash := common.BytesToHash(it.Key)
|
||||
if common.EmptyHash(interestHash) {
|
||||
|
|
@ -143,7 +143,7 @@ func (self *LendingStateDB) GetInvestings(orderBook common.Hash) (map[*big.Int]*
|
|||
} else {
|
||||
var data itemList
|
||||
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
|
||||
return nil, fmt.Errorf("Fail when decode order iist orderBook : %v ,interest :%v ", orderBook.Hex(), interest)
|
||||
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , interest : %v", orderBook.Hex(), interest)
|
||||
}
|
||||
stateOrderList := newItemListState(orderBook, interestHash, data, nil)
|
||||
mapResult[interest] = stateOrderList.data.Volume
|
||||
|
|
@ -168,13 +168,13 @@ func (self *LendingStateDB) GetInvestings(orderBook common.Hash) (map[*big.Int]*
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) GetBorrowings(orderBook common.Hash) (map[*big.Int]*big.Int, error) {
|
||||
exhangeObject := self.getLendingExchange(orderBook)
|
||||
func (ls *LendingStateDB) GetBorrowings(orderBook common.Hash) (map[*big.Int]*big.Int, error) {
|
||||
exhangeObject := ls.getLendingExchange(orderBook)
|
||||
if exhangeObject == nil {
|
||||
return nil, fmt.Errorf("Order book not found orderBook : %v ", orderBook.Hex())
|
||||
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
|
||||
}
|
||||
mapResult := map[*big.Int]*big.Int{}
|
||||
it := trie.NewIterator(exhangeObject.getBorrowingTrie(self.db).NodeIterator(nil))
|
||||
it := trie.NewIterator(exhangeObject.getBorrowingTrie(ls.db).NodeIterator(nil))
|
||||
for it.Next() {
|
||||
interestHash := common.BytesToHash(it.Key)
|
||||
if common.EmptyHash(interestHash) {
|
||||
|
|
@ -186,7 +186,7 @@ func (self *LendingStateDB) GetBorrowings(orderBook common.Hash) (map[*big.Int]*
|
|||
} else {
|
||||
var data itemList
|
||||
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
|
||||
return nil, fmt.Errorf("Fail when decode order iist orderBook : %v ,interest :%v ", orderBook.Hex(), interest)
|
||||
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , interest : %v", orderBook.Hex(), interest)
|
||||
}
|
||||
stateOrderList := newItemListState(orderBook, interestHash, data, nil)
|
||||
mapResult[interest] = stateOrderList.data.Volume
|
||||
|
|
@ -211,22 +211,22 @@ func (self *LendingStateDB) GetBorrowings(orderBook common.Hash) (map[*big.Int]*
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (self *itemListState) DumpItemList(db Database) DumpOrderList {
|
||||
mapResult := DumpOrderList{Volume: self.Volume(), Orders: map[*big.Int]*big.Int{}}
|
||||
orderListIt := trie.NewIterator(self.getTrie(db).NodeIterator(nil))
|
||||
func (il *itemListState) DumpItemList(db Database) DumpOrderList {
|
||||
mapResult := DumpOrderList{Volume: il.Volume(), Orders: map[*big.Int]*big.Int{}}
|
||||
orderListIt := trie.NewIterator(il.getTrie(db).NodeIterator(nil))
|
||||
for orderListIt.Next() {
|
||||
keyHash := common.BytesToHash(orderListIt.Key)
|
||||
if common.EmptyHash(keyHash) {
|
||||
continue
|
||||
}
|
||||
if _, exist := self.cachedStorage[keyHash]; exist {
|
||||
if _, exist := il.cachedStorage[keyHash]; exist {
|
||||
continue
|
||||
} else {
|
||||
_, content, _, _ := rlp.Split(orderListIt.Value)
|
||||
mapResult.Orders[new(big.Int).SetBytes(keyHash.Bytes())] = new(big.Int).SetBytes(content)
|
||||
}
|
||||
}
|
||||
for key, value := range self.cachedStorage {
|
||||
for key, value := range il.cachedStorage {
|
||||
if !common.EmptyHash(value) {
|
||||
mapResult.Orders[new(big.Int).SetBytes(key.Bytes())] = new(big.Int).SetBytes(value.Bytes())
|
||||
}
|
||||
|
|
@ -238,44 +238,44 @@ func (self *itemListState) DumpItemList(db Database) DumpOrderList {
|
|||
sort.Slice(listIds, func(i, j int) bool {
|
||||
return listIds[i].Cmp(listIds[j]) < 0
|
||||
})
|
||||
result := DumpOrderList{Volume: self.Volume(), Orders: map[*big.Int]*big.Int{}}
|
||||
result := DumpOrderList{Volume: il.Volume(), Orders: map[*big.Int]*big.Int{}}
|
||||
for _, id := range listIds {
|
||||
result.Orders[id] = mapResult.Orders[id]
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) DumpOrderBookInfo(orderBook common.Hash) (*DumpOrderBookInfo, error) {
|
||||
exhangeObject := self.getLendingExchange(orderBook)
|
||||
func (ls *LendingStateDB) DumpOrderBookInfo(orderBook common.Hash) (*DumpOrderBookInfo, error) {
|
||||
exhangeObject := ls.getLendingExchange(orderBook)
|
||||
if exhangeObject == nil {
|
||||
return nil, fmt.Errorf("Order book not found orderBook : %v ", orderBook.Hex())
|
||||
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
|
||||
}
|
||||
result := &DumpOrderBookInfo{}
|
||||
result.Nonce = exhangeObject.data.Nonce
|
||||
result.TradeNonce = exhangeObject.data.TradeNonce
|
||||
result.BestInvesting = new(big.Int).SetBytes(exhangeObject.getBestInvestingInterest(self.db).Bytes())
|
||||
result.BestBorrowing = new(big.Int).SetBytes(exhangeObject.getBestBorrowingInterest(self.db).Bytes())
|
||||
lowestLiquidationTime, _ := exhangeObject.getLowestLiquidationTime(self.db)
|
||||
result.BestInvesting = new(big.Int).SetBytes(exhangeObject.getBestInvestingInterest(ls.db).Bytes())
|
||||
result.BestBorrowing = new(big.Int).SetBytes(exhangeObject.getBestBorrowingInterest(ls.db).Bytes())
|
||||
lowestLiquidationTime, _ := exhangeObject.getLowestLiquidationTime(ls.db)
|
||||
result.LowestLiquidationTime = new(big.Int).SetBytes(lowestLiquidationTime.Bytes())
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (self *liquidationTimeState) DumpItemList(db Database) DumpOrderList {
|
||||
mapResult := DumpOrderList{Volume: self.Volume(), Orders: map[*big.Int]*big.Int{}}
|
||||
orderListIt := trie.NewIterator(self.getTrie(db).NodeIterator(nil))
|
||||
func (lts *liquidationTimeState) DumpItemList(db Database) DumpOrderList {
|
||||
mapResult := DumpOrderList{Volume: lts.Volume(), Orders: map[*big.Int]*big.Int{}}
|
||||
orderListIt := trie.NewIterator(lts.getTrie(db).NodeIterator(nil))
|
||||
for orderListIt.Next() {
|
||||
keyHash := common.BytesToHash(orderListIt.Key)
|
||||
if common.EmptyHash(keyHash) {
|
||||
continue
|
||||
}
|
||||
if _, exist := self.cachedStorage[keyHash]; exist {
|
||||
if _, exist := lts.cachedStorage[keyHash]; exist {
|
||||
continue
|
||||
} else {
|
||||
_, content, _, _ := rlp.Split(orderListIt.Value)
|
||||
mapResult.Orders[new(big.Int).SetBytes(keyHash.Bytes())] = new(big.Int).SetBytes(content)
|
||||
}
|
||||
}
|
||||
for key, value := range self.cachedStorage {
|
||||
for key, value := range lts.cachedStorage {
|
||||
if !common.EmptyHash(value) {
|
||||
mapResult.Orders[new(big.Int).SetBytes(key.Bytes())] = new(big.Int).SetBytes(value.Bytes())
|
||||
}
|
||||
|
|
@ -287,19 +287,20 @@ func (self *liquidationTimeState) DumpItemList(db Database) DumpOrderList {
|
|||
sort.Slice(listIds, func(i, j int) bool {
|
||||
return listIds[i].Cmp(listIds[j]) < 0
|
||||
})
|
||||
result := DumpOrderList{Volume: self.Volume(), Orders: map[*big.Int]*big.Int{}}
|
||||
result := DumpOrderList{Volume: lts.Volume(), Orders: map[*big.Int]*big.Int{}}
|
||||
for _, id := range listIds {
|
||||
result.Orders[id] = mapResult.Orders[id]
|
||||
}
|
||||
return mapResult
|
||||
}
|
||||
func (self *LendingStateDB) DumpLiquidationTimeTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
|
||||
exhangeObject := self.getLendingExchange(orderBook)
|
||||
|
||||
func (ls *LendingStateDB) DumpLiquidationTimeTrie(orderBook common.Hash) (map[*big.Int]DumpOrderList, error) {
|
||||
exhangeObject := ls.getLendingExchange(orderBook)
|
||||
if exhangeObject == nil {
|
||||
return nil, fmt.Errorf("Order book not found orderBook : %v ", orderBook.Hex())
|
||||
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
|
||||
}
|
||||
mapResult := map[*big.Int]DumpOrderList{}
|
||||
it := trie.NewIterator(exhangeObject.getLiquidationTimeTrie(self.db).NodeIterator(nil))
|
||||
it := trie.NewIterator(exhangeObject.getLiquidationTimeTrie(ls.db).NodeIterator(nil))
|
||||
for it.Next() {
|
||||
unixTimeHash := common.BytesToHash(it.Key)
|
||||
if common.EmptyHash(unixTimeHash) {
|
||||
|
|
@ -311,15 +312,15 @@ func (self *LendingStateDB) DumpLiquidationTimeTrie(orderBook common.Hash) (map[
|
|||
} else {
|
||||
var data itemList
|
||||
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
|
||||
return nil, fmt.Errorf("Fail when decode order iist orderBook : %v ,unixTime :%v ", orderBook.Hex(), unixTime)
|
||||
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , unixTime : %v", orderBook.Hex(), unixTime)
|
||||
}
|
||||
stateOrderList := newLiquidationTimeState(orderBook, unixTimeHash, data, nil)
|
||||
mapResult[unixTime] = stateOrderList.DumpItemList(self.db)
|
||||
mapResult[unixTime] = stateOrderList.DumpItemList(ls.db)
|
||||
}
|
||||
}
|
||||
for unixTimeHash, itemList := range exhangeObject.liquidationTimeStates {
|
||||
if itemList.Volume().Sign() > 0 {
|
||||
mapResult[new(big.Int).SetBytes(unixTimeHash.Bytes())] = itemList.DumpItemList(self.db)
|
||||
mapResult[new(big.Int).SetBytes(unixTimeHash.Bytes())] = itemList.DumpItemList(ls.db)
|
||||
}
|
||||
}
|
||||
listUnixTime := []*big.Int{}
|
||||
|
|
@ -336,13 +337,13 @@ func (self *LendingStateDB) DumpLiquidationTimeTrie(orderBook common.Hash) (map[
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) DumpLendingOrderTrie(orderBook common.Hash) (map[*big.Int]LendingItem, error) {
|
||||
exhangeObject := self.getLendingExchange(orderBook)
|
||||
func (ls *LendingStateDB) DumpLendingOrderTrie(orderBook common.Hash) (map[*big.Int]LendingItem, error) {
|
||||
exhangeObject := ls.getLendingExchange(orderBook)
|
||||
if exhangeObject == nil {
|
||||
return nil, fmt.Errorf("Order book not found orderBook : %v ", orderBook.Hex())
|
||||
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
|
||||
}
|
||||
mapResult := map[*big.Int]LendingItem{}
|
||||
it := trie.NewIterator(exhangeObject.getLendingItemTrie(self.db).NodeIterator(nil))
|
||||
it := trie.NewIterator(exhangeObject.getLendingItemTrie(ls.db).NodeIterator(nil))
|
||||
for it.Next() {
|
||||
orderIdHash := common.BytesToHash(it.Key)
|
||||
if common.EmptyHash(orderIdHash) {
|
||||
|
|
@ -354,7 +355,7 @@ func (self *LendingStateDB) DumpLendingOrderTrie(orderBook common.Hash) (map[*bi
|
|||
} else {
|
||||
var data LendingItem
|
||||
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
|
||||
return nil, fmt.Errorf("Fail when decode order iist orderBook : %v ,orderId :%v ", orderBook.Hex(), orderId)
|
||||
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , orderId : %v", orderBook.Hex(), orderId)
|
||||
}
|
||||
mapResult[orderId] = data
|
||||
}
|
||||
|
|
@ -376,13 +377,13 @@ func (self *LendingStateDB) DumpLendingOrderTrie(orderBook common.Hash) (map[*bi
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) DumpLendingTradeTrie(orderBook common.Hash) (map[*big.Int]LendingTrade, error) {
|
||||
exhangeObject := self.getLendingExchange(orderBook)
|
||||
func (ls *LendingStateDB) DumpLendingTradeTrie(orderBook common.Hash) (map[*big.Int]LendingTrade, error) {
|
||||
exhangeObject := ls.getLendingExchange(orderBook)
|
||||
if exhangeObject == nil {
|
||||
return nil, fmt.Errorf("Order book not found orderBook : %v ", orderBook.Hex())
|
||||
return nil, fmt.Errorf("not found orderBook: %v", orderBook.Hex())
|
||||
}
|
||||
mapResult := map[*big.Int]LendingTrade{}
|
||||
it := trie.NewIterator(exhangeObject.getLendingTradeTrie(self.db).NodeIterator(nil))
|
||||
it := trie.NewIterator(exhangeObject.getLendingTradeTrie(ls.db).NodeIterator(nil))
|
||||
for it.Next() {
|
||||
tradeIdHash := common.BytesToHash(it.Key)
|
||||
if common.EmptyHash(tradeIdHash) {
|
||||
|
|
@ -394,7 +395,7 @@ func (self *LendingStateDB) DumpLendingTradeTrie(orderBook common.Hash) (map[*bi
|
|||
} else {
|
||||
var data LendingTrade
|
||||
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
|
||||
return nil, fmt.Errorf("Fail when decode order iist orderBook : %v ,tradeId :%v ", orderBook.Hex(), tradeId)
|
||||
return nil, fmt.Errorf("fail when decode order iist orderBook: %v , tradeId : %v", orderBook.Hex(), tradeId)
|
||||
}
|
||||
mapResult[tradeId] = data
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto/sha3"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -207,7 +207,7 @@ func (l *LendingItem) VerifyLendingItem(state *state.StateDB) error {
|
|||
if err := l.VerifyLendingStatus(); err != nil {
|
||||
return err
|
||||
}
|
||||
if valid, _ := IsValidPair(state, l.Relayer, l.LendingToken, l.Term); valid == false {
|
||||
if valid, _ := IsValidPair(state, l.Relayer, l.LendingToken, l.Term); !valid {
|
||||
return fmt.Errorf("invalid pair . LendToken %s . Term: %v", l.LendingToken.Hex(), l.Term)
|
||||
}
|
||||
if l.Status == LendingStatusNew {
|
||||
|
|
@ -308,7 +308,7 @@ func (l *LendingItem) VerifyLendingStatus() error {
|
|||
}
|
||||
|
||||
func (l *LendingItem) ComputeHash() common.Hash {
|
||||
sha := sha3.NewKeccak256()
|
||||
sha := sha3.NewLegacyKeccak256()
|
||||
if l.Status == LendingStatusNew {
|
||||
sha.Write(l.Relayer.Bytes())
|
||||
sha.Write(l.UserAddress.Bytes())
|
||||
|
|
@ -411,7 +411,7 @@ func VerifyBalance(isXDCXLendingFork bool, statedb *state.StateDB, lendingStateD
|
|||
if lendTokenXDCPrice != nil && lendTokenXDCPrice.Sign() > 0 {
|
||||
defaultFee := new(big.Int).Mul(quantity, new(big.Int).SetUint64(DefaultFeeRate))
|
||||
defaultFee = new(big.Int).Div(defaultFee, common.XDCXBaseFee)
|
||||
defaultFeeInXDC := common.Big0
|
||||
var defaultFeeInXDC *big.Int
|
||||
if lendingToken != common.XDCNativeAddressBinary {
|
||||
defaultFeeInXDC = new(big.Int).Mul(defaultFee, lendTokenXDCPrice)
|
||||
defaultFeeInXDC = new(big.Int).Div(defaultFeeInXDC, lendingTokenDecimal)
|
||||
|
|
@ -429,8 +429,7 @@ func VerifyBalance(isXDCXLendingFork bool, statedb *state.StateDB, lendingStateD
|
|||
// make sure actualBalance >= cancel fee
|
||||
lendingBook := GetLendingOrderBookHash(lendingToken, term)
|
||||
item := lendingStateDb.GetLendingOrder(lendingBook, common.BigToHash(new(big.Int).SetUint64(lendingId)))
|
||||
cancelFee := big.NewInt(0)
|
||||
cancelFee = new(big.Int).Mul(item.Quantity, borrowingFeeRate)
|
||||
cancelFee := new(big.Int).Mul(item.Quantity, borrowingFeeRate)
|
||||
cancelFee = new(big.Int).Div(cancelFee, common.XDCXBaseCancelFee)
|
||||
|
||||
actualBalance := GetTokenBalance(userAddress, lendingToken, statedb)
|
||||
|
|
@ -459,9 +458,8 @@ func VerifyBalance(isXDCXLendingFork bool, statedb *state.StateDB, lendingStateD
|
|||
case LendingStatusCancelled:
|
||||
lendingBook := GetLendingOrderBookHash(lendingToken, term)
|
||||
item := lendingStateDb.GetLendingOrder(lendingBook, common.BigToHash(new(big.Int).SetUint64(lendingId)))
|
||||
cancelFee := big.NewInt(0)
|
||||
// Fee == quantityToLend/base lend token decimal *price*borrowFee/LendingCancelFee
|
||||
cancelFee = new(big.Int).Div(item.Quantity, collateralPrice)
|
||||
cancelFee := new(big.Int).Div(item.Quantity, collateralPrice)
|
||||
cancelFee = new(big.Int).Mul(cancelFee, borrowingFeeRate)
|
||||
cancelFee = new(big.Int).Div(cancelFee, common.XDCXBaseCancelFee)
|
||||
actualBalance := GetTokenBalance(userAddress, collateralToken, statedb)
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto/sha3"
|
||||
"github.com/XinFinOrg/XDPoSChain/rpc"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
func TestLendingItem_VerifyLendingSide(t *testing.T) {
|
||||
|
|
@ -515,11 +515,11 @@ func Test_CreateOrder(t *testing.T) {
|
|||
|
||||
func sendOrder(nonce uint64) {
|
||||
rpcClient, err := rpc.DialHTTP("http://localhost:8501")
|
||||
defer rpcClient.Close()
|
||||
if err != nil {
|
||||
fmt.Println("rpc.DialHTTP failed", "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer rpcClient.Close()
|
||||
rand.Seed(time.Now().UTC().UnixNano())
|
||||
item := &LendingOrderMsg{
|
||||
AccountNonce: nonce,
|
||||
|
|
@ -568,9 +568,8 @@ func sendOrder(nonce uint64) {
|
|||
}
|
||||
|
||||
func computeHash(l *LendingOrderMsg) common.Hash {
|
||||
sha := sha3.NewKeccak256()
|
||||
sha := sha3.NewLegacyKeccak256()
|
||||
if l.Status == LendingStatusCancelled {
|
||||
sha := sha3.NewKeccak256()
|
||||
sha.Write(l.Hash.Bytes())
|
||||
sha.Write(common.BigToHash(big.NewInt(int64(l.AccountNonce))).Bytes())
|
||||
sha.Write(l.UserAddress.Bytes())
|
||||
|
|
@ -593,5 +592,4 @@ func computeHash(l *LendingOrderMsg) common.Hash {
|
|||
sha.Write(common.BigToHash(big.NewInt(int64(l.AccountNonce))).Bytes())
|
||||
}
|
||||
return common.BytesToHash(sha.Sum(nil))
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,10 +41,7 @@ func IsResignedRelayer(relayer common.Address, statedb *state.StateDB) bool {
|
|||
slot := RelayerMappingSlot["RESIGN_REQUESTS"]
|
||||
locBig := GetLocMappingAtKey(relayer.Hash(), slot)
|
||||
locHash := common.BigToHash(locBig)
|
||||
if statedb.GetState(common.HexToAddress(common.RelayerRegistrationSMC), locHash) != (common.Hash{}) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return statedb.GetState(common.HexToAddress(common.RelayerRegistrationSMC), locHash) != (common.Hash{})
|
||||
}
|
||||
|
||||
func GetBaseTokenLength(relayer common.Address, statedb *state.StateDB) uint64 {
|
||||
|
|
@ -235,7 +232,7 @@ func CheckAddTokenBalance(addr common.Address, value *big.Int, token common.Addr
|
|||
newBalance := new(big.Int).Add(balance, value)
|
||||
log.Debug("CheckAddTokenBalance settle balance: ADD TOKEN BALANCE ", "token", token.String(), "address", addr.String(), "balance", balance, "value", value, "newBalance", newBalance)
|
||||
if common.BigToHash(newBalance).Big().Cmp(newBalance) != 0 {
|
||||
return nil, fmt.Errorf("Overflow when try add token balance , max is 2^256 , balance : %v , value:%v ", balance, value)
|
||||
return nil, fmt.Errorf("overflow when try add token balance , max is 2^256 , balance : %v , value : %v", balance, value)
|
||||
} else {
|
||||
return newBalance, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,10 +19,11 @@ package lendingstate
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||
)
|
||||
|
||||
type itemListState struct {
|
||||
|
|
@ -46,8 +47,8 @@ type itemListState struct {
|
|||
onDirty func(price common.Hash) // Callback method to mark a state object newly dirty
|
||||
}
|
||||
|
||||
func (s *itemListState) empty() bool {
|
||||
return s.data.Volume == nil || s.data.Volume.Sign() == 0
|
||||
func (il *itemListState) empty() bool {
|
||||
return il.data.Volume == nil || il.data.Volume.Sign() == 0
|
||||
}
|
||||
|
||||
func newItemListState(lendingBook common.Hash, key common.Hash, data itemList, onDirty func(price common.Hash)) *itemListState {
|
||||
|
|
@ -62,132 +63,132 @@ func newItemListState(lendingBook common.Hash, key common.Hash, data itemList, o
|
|||
}
|
||||
|
||||
// EncodeRLP implements rlp.Encoder.
|
||||
func (c *itemListState) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, c.data)
|
||||
func (il *itemListState) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, il.data)
|
||||
}
|
||||
|
||||
// setError remembers the first non-nil error it is called with.
|
||||
func (self *itemListState) setError(err error) {
|
||||
if self.dbErr == nil {
|
||||
self.dbErr = err
|
||||
func (il *itemListState) setError(err error) {
|
||||
if il.dbErr == nil {
|
||||
il.dbErr = err
|
||||
}
|
||||
}
|
||||
|
||||
func (c *itemListState) getTrie(db Database) Trie {
|
||||
if c.trie == nil {
|
||||
func (il *itemListState) getTrie(db Database) Trie {
|
||||
if il.trie == nil {
|
||||
var err error
|
||||
c.trie, err = db.OpenStorageTrie(c.key, c.data.Root)
|
||||
il.trie, err = db.OpenStorageTrie(il.key, il.data.Root)
|
||||
if err != nil {
|
||||
c.trie, _ = db.OpenStorageTrie(c.key, EmptyHash)
|
||||
c.setError(fmt.Errorf("can't create storage trie: %v", err))
|
||||
il.trie, _ = db.OpenStorageTrie(il.key, EmptyHash)
|
||||
il.setError(fmt.Errorf("can't create storage trie: %v", err))
|
||||
}
|
||||
}
|
||||
return c.trie
|
||||
return il.trie
|
||||
}
|
||||
|
||||
func (self *itemListState) GetOrderAmount(db Database, orderId common.Hash) common.Hash {
|
||||
amount, exists := self.cachedStorage[orderId]
|
||||
func (il *itemListState) GetOrderAmount(db Database, orderId common.Hash) common.Hash {
|
||||
amount, exists := il.cachedStorage[orderId]
|
||||
if exists {
|
||||
return amount
|
||||
}
|
||||
// Load from DB in case it is missing.
|
||||
enc, err := self.getTrie(db).TryGet(orderId[:])
|
||||
enc, err := il.getTrie(db).TryGet(orderId[:])
|
||||
if err != nil {
|
||||
self.setError(err)
|
||||
il.setError(err)
|
||||
return EmptyHash
|
||||
}
|
||||
if len(enc) > 0 {
|
||||
_, content, _, err := rlp.Split(enc)
|
||||
if err != nil {
|
||||
self.setError(err)
|
||||
il.setError(err)
|
||||
}
|
||||
amount.SetBytes(content)
|
||||
}
|
||||
if (amount != common.Hash{}) {
|
||||
self.cachedStorage[orderId] = amount
|
||||
il.cachedStorage[orderId] = amount
|
||||
}
|
||||
return amount
|
||||
}
|
||||
|
||||
func (self *itemListState) insertLendingItem(db Database, orderId common.Hash, amount common.Hash) {
|
||||
self.setOrderItem(orderId, amount)
|
||||
self.setError(self.getTrie(db).TryUpdate(orderId[:], amount[:]))
|
||||
func (il *itemListState) insertLendingItem(db Database, orderId common.Hash, amount common.Hash) {
|
||||
il.setOrderItem(orderId, amount)
|
||||
il.setError(il.getTrie(db).TryUpdate(orderId[:], amount[:]))
|
||||
}
|
||||
|
||||
func (self *itemListState) removeOrderItem(db Database, orderId common.Hash) {
|
||||
tr := self.getTrie(db)
|
||||
self.setError(tr.TryDelete(orderId[:]))
|
||||
self.setOrderItem(orderId, EmptyHash)
|
||||
func (il *itemListState) removeOrderItem(db Database, orderId common.Hash) {
|
||||
tr := il.getTrie(db)
|
||||
il.setError(tr.TryDelete(orderId[:]))
|
||||
il.setOrderItem(orderId, EmptyHash)
|
||||
}
|
||||
|
||||
func (self *itemListState) setOrderItem(orderId common.Hash, amount common.Hash) {
|
||||
self.cachedStorage[orderId] = amount
|
||||
self.dirtyStorage[orderId] = amount
|
||||
func (il *itemListState) setOrderItem(orderId common.Hash, amount common.Hash) {
|
||||
il.cachedStorage[orderId] = amount
|
||||
il.dirtyStorage[orderId] = amount
|
||||
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.key)
|
||||
self.onDirty = nil
|
||||
if il.onDirty != nil {
|
||||
il.onDirty(il.key)
|
||||
il.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
// updateAskTrie writes cached storage modifications into the object's storage trie.
|
||||
func (self *itemListState) updateTrie(db Database) Trie {
|
||||
tr := self.getTrie(db)
|
||||
for orderId, amount := range self.dirtyStorage {
|
||||
delete(self.dirtyStorage, orderId)
|
||||
func (il *itemListState) updateTrie(db Database) Trie {
|
||||
tr := il.getTrie(db)
|
||||
for orderId, amount := range il.dirtyStorage {
|
||||
delete(il.dirtyStorage, orderId)
|
||||
if amount == EmptyHash {
|
||||
self.setError(tr.TryDelete(orderId[:]))
|
||||
il.setError(tr.TryDelete(orderId[:]))
|
||||
continue
|
||||
}
|
||||
v, _ := rlp.EncodeToBytes(bytes.TrimLeft(amount[:], "\x00"))
|
||||
self.setError(tr.TryUpdate(orderId[:], v))
|
||||
il.setError(tr.TryUpdate(orderId[:], v))
|
||||
}
|
||||
return tr
|
||||
}
|
||||
|
||||
// UpdateRoot sets the trie root to the current root tradeId of
|
||||
func (self *itemListState) updateRoot(db Database) error {
|
||||
self.updateTrie(db)
|
||||
if self.dbErr != nil {
|
||||
return self.dbErr
|
||||
func (il *itemListState) updateRoot(db Database) error {
|
||||
il.updateTrie(db)
|
||||
if il.dbErr != nil {
|
||||
return il.dbErr
|
||||
}
|
||||
root, err := self.trie.Commit(nil)
|
||||
root, err := il.trie.Commit(nil)
|
||||
if err == nil {
|
||||
self.data.Root = root
|
||||
il.data.Root = root
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *itemListState) deepCopy(db *LendingStateDB, onDirty func(price common.Hash)) *itemListState {
|
||||
stateOrderList := newItemListState(self.lendingBook, self.key, self.data, onDirty)
|
||||
if self.trie != nil {
|
||||
stateOrderList.trie = db.db.CopyTrie(self.trie)
|
||||
func (il *itemListState) deepCopy(db *LendingStateDB, onDirty func(price common.Hash)) *itemListState {
|
||||
stateOrderList := newItemListState(il.lendingBook, il.key, il.data, onDirty)
|
||||
if il.trie != nil {
|
||||
stateOrderList.trie = db.db.CopyTrie(il.trie)
|
||||
}
|
||||
for orderId, amount := range self.dirtyStorage {
|
||||
for orderId, amount := range il.dirtyStorage {
|
||||
stateOrderList.dirtyStorage[orderId] = amount
|
||||
}
|
||||
for orderId, amount := range self.cachedStorage {
|
||||
for orderId, amount := range il.cachedStorage {
|
||||
stateOrderList.cachedStorage[orderId] = amount
|
||||
}
|
||||
return stateOrderList
|
||||
}
|
||||
|
||||
func (c *itemListState) AddVolume(amount *big.Int) {
|
||||
c.setVolume(new(big.Int).Add(c.data.Volume, amount))
|
||||
func (il *itemListState) AddVolume(amount *big.Int) {
|
||||
il.setVolume(new(big.Int).Add(il.data.Volume, amount))
|
||||
}
|
||||
|
||||
func (c *itemListState) subVolume(amount *big.Int) {
|
||||
c.setVolume(new(big.Int).Sub(c.data.Volume, amount))
|
||||
func (il *itemListState) subVolume(amount *big.Int) {
|
||||
il.setVolume(new(big.Int).Sub(il.data.Volume, amount))
|
||||
}
|
||||
|
||||
func (self *itemListState) setVolume(volume *big.Int) {
|
||||
self.data.Volume = volume
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.key)
|
||||
self.onDirty = nil
|
||||
func (il *itemListState) setVolume(volume *big.Int) {
|
||||
il.data.Volume = volume
|
||||
if il.onDirty != nil {
|
||||
il.onDirty(il.key)
|
||||
il.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *itemListState) Volume() *big.Int {
|
||||
return self.data.Volume
|
||||
func (il *itemListState) Volume() *big.Int {
|
||||
return il.data.Volume
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,14 +108,14 @@ func newStateExchanges(db *LendingStateDB, hash common.Hash, data lendingObject,
|
|||
}
|
||||
|
||||
// EncodeRLP implements rlp.Encoder.
|
||||
func (self *lendingExchangeState) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, self.data)
|
||||
func (le *lendingExchangeState) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, le.data)
|
||||
}
|
||||
|
||||
// setError remembers the first non-nil error it is called with.
|
||||
func (self *lendingExchangeState) setError(err error) {
|
||||
if self.dbErr == nil {
|
||||
self.dbErr = err
|
||||
func (le *lendingExchangeState) setError(err error) {
|
||||
if le.dbErr == nil {
|
||||
le.dbErr = err
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -123,63 +123,64 @@ func (self *lendingExchangeState) setError(err error) {
|
|||
Get Trie
|
||||
*/
|
||||
|
||||
func (self *lendingExchangeState) getLendingItemTrie(db Database) Trie {
|
||||
if self.lendingItemTrie == nil {
|
||||
func (le *lendingExchangeState) getLendingItemTrie(db Database) Trie {
|
||||
if le.lendingItemTrie == nil {
|
||||
var err error
|
||||
self.lendingItemTrie, err = db.OpenStorageTrie(self.lendingBook, self.data.LendingItemRoot)
|
||||
le.lendingItemTrie, err = db.OpenStorageTrie(le.lendingBook, le.data.LendingItemRoot)
|
||||
if err != nil {
|
||||
self.lendingItemTrie, _ = db.OpenStorageTrie(self.lendingBook, EmptyHash)
|
||||
self.setError(fmt.Errorf("can't create Lendings trie: %v", err))
|
||||
le.lendingItemTrie, _ = db.OpenStorageTrie(le.lendingBook, EmptyHash)
|
||||
le.setError(fmt.Errorf("can't create Lendings trie: %v", err))
|
||||
}
|
||||
}
|
||||
return self.lendingItemTrie
|
||||
return le.lendingItemTrie
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) getLendingTradeTrie(db Database) Trie {
|
||||
if self.lendingTradeTrie == nil {
|
||||
func (le *lendingExchangeState) getLendingTradeTrie(db Database) Trie {
|
||||
if le.lendingTradeTrie == nil {
|
||||
var err error
|
||||
self.lendingTradeTrie, err = db.OpenStorageTrie(self.lendingBook, self.data.LendingTradeRoot)
|
||||
le.lendingTradeTrie, err = db.OpenStorageTrie(le.lendingBook, le.data.LendingTradeRoot)
|
||||
if err != nil {
|
||||
self.lendingTradeTrie, _ = db.OpenStorageTrie(self.lendingBook, EmptyHash)
|
||||
self.setError(fmt.Errorf("can't create Lendings trie: %v", err))
|
||||
le.lendingTradeTrie, _ = db.OpenStorageTrie(le.lendingBook, EmptyHash)
|
||||
le.setError(fmt.Errorf("can't create Lendings trie: %v", err))
|
||||
}
|
||||
}
|
||||
return self.lendingTradeTrie
|
||||
}
|
||||
func (self *lendingExchangeState) getInvestingTrie(db Database) Trie {
|
||||
if self.investingTrie == nil {
|
||||
var err error
|
||||
self.investingTrie, err = db.OpenStorageTrie(self.lendingBook, self.data.InvestingRoot)
|
||||
if err != nil {
|
||||
self.investingTrie, _ = db.OpenStorageTrie(self.lendingBook, EmptyHash)
|
||||
self.setError(fmt.Errorf("can't create Lendings trie: %v", err))
|
||||
}
|
||||
}
|
||||
return self.investingTrie
|
||||
return le.lendingTradeTrie
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) getBorrowingTrie(db Database) Trie {
|
||||
if self.borrowingTrie == nil {
|
||||
func (le *lendingExchangeState) getInvestingTrie(db Database) Trie {
|
||||
if le.investingTrie == nil {
|
||||
var err error
|
||||
self.borrowingTrie, err = db.OpenStorageTrie(self.lendingBook, self.data.BorrowingRoot)
|
||||
le.investingTrie, err = db.OpenStorageTrie(le.lendingBook, le.data.InvestingRoot)
|
||||
if err != nil {
|
||||
self.borrowingTrie, _ = db.OpenStorageTrie(self.lendingBook, EmptyHash)
|
||||
self.setError(fmt.Errorf("can't create bids trie: %v", err))
|
||||
le.investingTrie, _ = db.OpenStorageTrie(le.lendingBook, EmptyHash)
|
||||
le.setError(fmt.Errorf("can't create Lendings trie: %v", err))
|
||||
}
|
||||
}
|
||||
return self.borrowingTrie
|
||||
return le.investingTrie
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) getLiquidationTimeTrie(db Database) Trie {
|
||||
if self.liquidationTimeTrie == nil {
|
||||
func (le *lendingExchangeState) getBorrowingTrie(db Database) Trie {
|
||||
if le.borrowingTrie == nil {
|
||||
var err error
|
||||
self.liquidationTimeTrie, err = db.OpenStorageTrie(self.lendingBook, self.data.LiquidationTimeRoot)
|
||||
le.borrowingTrie, err = db.OpenStorageTrie(le.lendingBook, le.data.BorrowingRoot)
|
||||
if err != nil {
|
||||
self.liquidationTimeTrie, _ = db.OpenStorageTrie(self.lendingBook, EmptyHash)
|
||||
self.setError(fmt.Errorf("can't create bids trie: %v", err))
|
||||
le.borrowingTrie, _ = db.OpenStorageTrie(le.lendingBook, EmptyHash)
|
||||
le.setError(fmt.Errorf("can't create bids trie: %v", err))
|
||||
}
|
||||
}
|
||||
return self.liquidationTimeTrie
|
||||
return le.borrowingTrie
|
||||
}
|
||||
|
||||
func (le *lendingExchangeState) getLiquidationTimeTrie(db Database) Trie {
|
||||
if le.liquidationTimeTrie == nil {
|
||||
var err error
|
||||
le.liquidationTimeTrie, err = db.OpenStorageTrie(le.lendingBook, le.data.LiquidationTimeRoot)
|
||||
if err != nil {
|
||||
le.liquidationTimeTrie, _ = db.OpenStorageTrie(le.lendingBook, EmptyHash)
|
||||
le.setError(fmt.Errorf("can't create bids trie: %v", err))
|
||||
}
|
||||
}
|
||||
return le.liquidationTimeTrie
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -187,16 +188,16 @@ func (self *lendingExchangeState) getLiquidationTimeTrie(db Database) Trie {
|
|||
|
||||
Get State
|
||||
*/
|
||||
func (self *lendingExchangeState) getBorrowingOrderList(db Database, rate common.Hash) (stateOrderList *itemListState) {
|
||||
func (le *lendingExchangeState) getBorrowingOrderList(db Database, rate common.Hash) (stateOrderList *itemListState) {
|
||||
// Prefer 'live' objects.
|
||||
if obj := self.borrowingStates[rate]; obj != nil {
|
||||
if obj := le.borrowingStates[rate]; obj != nil {
|
||||
return obj
|
||||
}
|
||||
|
||||
// Load the object from the database.
|
||||
enc, err := self.getBorrowingTrie(db).TryGet(rate[:])
|
||||
enc, err := le.getBorrowingTrie(db).TryGet(rate[:])
|
||||
if len(enc) == 0 {
|
||||
self.setError(err)
|
||||
le.setError(err)
|
||||
return nil
|
||||
}
|
||||
var data itemList
|
||||
|
|
@ -205,21 +206,21 @@ func (self *lendingExchangeState) getBorrowingOrderList(db Database, rate common
|
|||
return nil
|
||||
}
|
||||
// Insert into the live set.
|
||||
obj := newItemListState(self.lendingBook, rate, data, self.MarkBorrowingDirty)
|
||||
self.borrowingStates[rate] = obj
|
||||
obj := newItemListState(le.lendingBook, rate, data, le.MarkBorrowingDirty)
|
||||
le.borrowingStates[rate] = obj
|
||||
return obj
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) getInvestingOrderList(db Database, rate common.Hash) (stateOrderList *itemListState) {
|
||||
func (le *lendingExchangeState) getInvestingOrderList(db Database, rate common.Hash) (stateOrderList *itemListState) {
|
||||
// Prefer 'live' objects.
|
||||
if obj := self.investingStates[rate]; obj != nil {
|
||||
if obj := le.investingStates[rate]; obj != nil {
|
||||
return obj
|
||||
}
|
||||
|
||||
// Load the object from the database.
|
||||
enc, err := self.getInvestingTrie(db).TryGet(rate[:])
|
||||
enc, err := le.getInvestingTrie(db).TryGet(rate[:])
|
||||
if len(enc) == 0 {
|
||||
self.setError(err)
|
||||
le.setError(err)
|
||||
return nil
|
||||
}
|
||||
var data itemList
|
||||
|
|
@ -228,21 +229,21 @@ func (self *lendingExchangeState) getInvestingOrderList(db Database, rate common
|
|||
return nil
|
||||
}
|
||||
// Insert into the live set.
|
||||
obj := newItemListState(self.lendingBook, rate, data, self.MarkInvestingDirty)
|
||||
self.investingStates[rate] = obj
|
||||
obj := newItemListState(le.lendingBook, rate, data, le.MarkInvestingDirty)
|
||||
le.investingStates[rate] = obj
|
||||
return obj
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) getLiquidationTimeOrderList(db Database, time common.Hash) (stateObject *liquidationTimeState) {
|
||||
func (le *lendingExchangeState) getLiquidationTimeOrderList(db Database, time common.Hash) (stateObject *liquidationTimeState) {
|
||||
// Prefer 'live' objects.
|
||||
if obj := self.liquidationTimeStates[time]; obj != nil {
|
||||
if obj := le.liquidationTimeStates[time]; obj != nil {
|
||||
return obj
|
||||
}
|
||||
|
||||
// Load the object from the database.
|
||||
enc, err := self.getLiquidationTimeTrie(db).TryGet(time[:])
|
||||
enc, err := le.getLiquidationTimeTrie(db).TryGet(time[:])
|
||||
if len(enc) == 0 {
|
||||
self.setError(err)
|
||||
le.setError(err)
|
||||
return nil
|
||||
}
|
||||
var data itemList
|
||||
|
|
@ -251,21 +252,21 @@ func (self *lendingExchangeState) getLiquidationTimeOrderList(db Database, time
|
|||
return nil
|
||||
}
|
||||
// Insert into the live set.
|
||||
obj := newLiquidationTimeState(self.lendingBook, time, data, self.MarkLiquidationTimeDirty)
|
||||
self.liquidationTimeStates[time] = obj
|
||||
obj := newLiquidationTimeState(le.lendingBook, time, data, le.MarkLiquidationTimeDirty)
|
||||
le.liquidationTimeStates[time] = obj
|
||||
return obj
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) getLendingItem(db Database, lendingId common.Hash) (stateObject *lendingItemState) {
|
||||
func (le *lendingExchangeState) getLendingItem(db Database, lendingId common.Hash) (stateObject *lendingItemState) {
|
||||
// Prefer 'live' objects.
|
||||
if obj := self.lendingItemStates[lendingId]; obj != nil {
|
||||
if obj := le.lendingItemStates[lendingId]; obj != nil {
|
||||
return obj
|
||||
}
|
||||
|
||||
// Load the object from the database.
|
||||
enc, err := self.getLendingItemTrie(db).TryGet(lendingId[:])
|
||||
enc, err := le.getLendingItemTrie(db).TryGet(lendingId[:])
|
||||
if len(enc) == 0 {
|
||||
self.setError(err)
|
||||
le.setError(err)
|
||||
return nil
|
||||
}
|
||||
var data LendingItem
|
||||
|
|
@ -274,21 +275,21 @@ func (self *lendingExchangeState) getLendingItem(db Database, lendingId common.H
|
|||
return nil
|
||||
}
|
||||
// Insert into the live set.
|
||||
obj := newLendinItemState(self.lendingBook, lendingId, data, self.MarkLendingItemDirty)
|
||||
self.lendingItemStates[lendingId] = obj
|
||||
obj := newLendinItemState(le.lendingBook, lendingId, data, le.MarkLendingItemDirty)
|
||||
le.lendingItemStates[lendingId] = obj
|
||||
return obj
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) getLendingTrade(db Database, tradeId common.Hash) (stateObject *lendingTradeState) {
|
||||
func (le *lendingExchangeState) getLendingTrade(db Database, tradeId common.Hash) (stateObject *lendingTradeState) {
|
||||
// Prefer 'live' objects.
|
||||
if obj := self.lendingTradeStates[tradeId]; obj != nil {
|
||||
if obj := le.lendingTradeStates[tradeId]; obj != nil {
|
||||
return obj
|
||||
}
|
||||
|
||||
// Load the object from the database.
|
||||
enc, err := self.getLendingTradeTrie(db).TryGet(tradeId[:])
|
||||
enc, err := le.getLendingTradeTrie(db).TryGet(tradeId[:])
|
||||
if len(enc) == 0 {
|
||||
self.setError(err)
|
||||
le.setError(err)
|
||||
return nil
|
||||
}
|
||||
var data LendingTrade
|
||||
|
|
@ -297,8 +298,8 @@ func (self *lendingExchangeState) getLendingTrade(db Database, tradeId common.Ha
|
|||
return nil
|
||||
}
|
||||
// Insert into the live set.
|
||||
obj := newLendingTradeState(self.lendingBook, tradeId, data, self.MarkLendingTradeDirty)
|
||||
self.lendingTradeStates[tradeId] = obj
|
||||
obj := newLendingTradeState(le.lendingBook, tradeId, data, le.MarkLendingTradeDirty)
|
||||
le.lendingTradeStates[tradeId] = obj
|
||||
return obj
|
||||
}
|
||||
|
||||
|
|
@ -307,46 +308,47 @@ func (self *lendingExchangeState) getLendingTrade(db Database, tradeId common.Ha
|
|||
|
||||
Update Trie
|
||||
*/
|
||||
func (self *lendingExchangeState) updateLendingTimeTrie(db Database) Trie {
|
||||
tr := self.getLendingItemTrie(db)
|
||||
for lendingId, lendingItem := range self.lendingItemStates {
|
||||
if _, isDirty := self.lendingItemStatesDirty[lendingId]; isDirty {
|
||||
delete(self.lendingItemStatesDirty, lendingId)
|
||||
func (le *lendingExchangeState) updateLendingTimeTrie(db Database) Trie {
|
||||
tr := le.getLendingItemTrie(db)
|
||||
for lendingId, lendingItem := range le.lendingItemStates {
|
||||
if _, isDirty := le.lendingItemStatesDirty[lendingId]; isDirty {
|
||||
delete(le.lendingItemStatesDirty, lendingId)
|
||||
if lendingItem.empty() {
|
||||
self.setError(tr.TryDelete(lendingId[:]))
|
||||
le.setError(tr.TryDelete(lendingId[:]))
|
||||
continue
|
||||
}
|
||||
// Encoding []byte cannot fail, ok to ignore the error.
|
||||
v, _ := rlp.EncodeToBytes(lendingItem)
|
||||
self.setError(tr.TryUpdate(lendingId[:], v))
|
||||
le.setError(tr.TryUpdate(lendingId[:], v))
|
||||
}
|
||||
}
|
||||
return tr
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) updateLendingTradeTrie(db Database) Trie {
|
||||
tr := self.getLendingTradeTrie(db)
|
||||
for tradeId, lendingTradeItem := range self.lendingTradeStates {
|
||||
if _, isDirty := self.lendingTradeStatesDirty[tradeId]; isDirty {
|
||||
delete(self.lendingTradeStatesDirty, tradeId)
|
||||
func (le *lendingExchangeState) updateLendingTradeTrie(db Database) Trie {
|
||||
tr := le.getLendingTradeTrie(db)
|
||||
for tradeId, lendingTradeItem := range le.lendingTradeStates {
|
||||
if _, isDirty := le.lendingTradeStatesDirty[tradeId]; isDirty {
|
||||
delete(le.lendingTradeStatesDirty, tradeId)
|
||||
if lendingTradeItem.empty() {
|
||||
self.setError(tr.TryDelete(tradeId[:]))
|
||||
le.setError(tr.TryDelete(tradeId[:]))
|
||||
continue
|
||||
}
|
||||
// Encoding []byte cannot fail, ok to ignore the error.
|
||||
v, _ := rlp.EncodeToBytes(lendingTradeItem)
|
||||
self.setError(tr.TryUpdate(tradeId[:], v))
|
||||
le.setError(tr.TryUpdate(tradeId[:], v))
|
||||
}
|
||||
}
|
||||
return tr
|
||||
}
|
||||
func (self *lendingExchangeState) updateBorrowingTrie(db Database) Trie {
|
||||
tr := self.getBorrowingTrie(db)
|
||||
for rate, orderList := range self.borrowingStates {
|
||||
if _, isDirty := self.borrowingStatesDirty[rate]; isDirty {
|
||||
delete(self.borrowingStatesDirty, rate)
|
||||
|
||||
func (le *lendingExchangeState) updateBorrowingTrie(db Database) Trie {
|
||||
tr := le.getBorrowingTrie(db)
|
||||
for rate, orderList := range le.borrowingStates {
|
||||
if _, isDirty := le.borrowingStatesDirty[rate]; isDirty {
|
||||
delete(le.borrowingStatesDirty, rate)
|
||||
if orderList.empty() {
|
||||
self.setError(tr.TryDelete(rate[:]))
|
||||
le.setError(tr.TryDelete(rate[:]))
|
||||
continue
|
||||
}
|
||||
err := orderList.updateRoot(db)
|
||||
|
|
@ -355,19 +357,19 @@ func (self *lendingExchangeState) updateBorrowingTrie(db Database) Trie {
|
|||
}
|
||||
// Encoding []byte cannot fail, ok to ignore the error.
|
||||
v, _ := rlp.EncodeToBytes(orderList)
|
||||
self.setError(tr.TryUpdate(rate[:], v))
|
||||
le.setError(tr.TryUpdate(rate[:], v))
|
||||
}
|
||||
}
|
||||
return tr
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) updateInvestingTrie(db Database) Trie {
|
||||
tr := self.getInvestingTrie(db)
|
||||
for rate, orderList := range self.investingStates {
|
||||
if _, isDirty := self.investingStatesDirty[rate]; isDirty {
|
||||
delete(self.investingStatesDirty, rate)
|
||||
func (le *lendingExchangeState) updateInvestingTrie(db Database) Trie {
|
||||
tr := le.getInvestingTrie(db)
|
||||
for rate, orderList := range le.investingStates {
|
||||
if _, isDirty := le.investingStatesDirty[rate]; isDirty {
|
||||
delete(le.investingStatesDirty, rate)
|
||||
if orderList.empty() {
|
||||
self.setError(tr.TryDelete(rate[:]))
|
||||
le.setError(tr.TryDelete(rate[:]))
|
||||
continue
|
||||
}
|
||||
err := orderList.updateRoot(db)
|
||||
|
|
@ -376,19 +378,19 @@ func (self *lendingExchangeState) updateInvestingTrie(db Database) Trie {
|
|||
}
|
||||
// Encoding []byte cannot fail, ok to ignore the error.
|
||||
v, _ := rlp.EncodeToBytes(orderList)
|
||||
self.setError(tr.TryUpdate(rate[:], v))
|
||||
le.setError(tr.TryUpdate(rate[:], v))
|
||||
}
|
||||
}
|
||||
return tr
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) updateLiquidationTimeTrie(db Database) Trie {
|
||||
tr := self.getLiquidationTimeTrie(db)
|
||||
for time, itemList := range self.liquidationTimeStates {
|
||||
if _, isDirty := self.liquidationTimestatesDirty[time]; isDirty {
|
||||
delete(self.liquidationTimestatesDirty, time)
|
||||
func (le *lendingExchangeState) updateLiquidationTimeTrie(db Database) Trie {
|
||||
tr := le.getLiquidationTimeTrie(db)
|
||||
for time, itemList := range le.liquidationTimeStates {
|
||||
if _, isDirty := le.liquidationTimestatesDirty[time]; isDirty {
|
||||
delete(le.liquidationTimestatesDirty, time)
|
||||
if itemList.empty() {
|
||||
self.setError(tr.TryDelete(time[:]))
|
||||
le.setError(tr.TryDelete(time[:]))
|
||||
continue
|
||||
}
|
||||
err := itemList.updateRoot(db)
|
||||
|
|
@ -397,7 +399,7 @@ func (self *lendingExchangeState) updateLiquidationTimeTrie(db Database) Trie {
|
|||
}
|
||||
// Encoding []byte cannot fail, ok to ignore the error.
|
||||
v, _ := rlp.EncodeToBytes(itemList)
|
||||
self.setError(tr.TryUpdate(time[:], v))
|
||||
le.setError(tr.TryUpdate(time[:], v))
|
||||
}
|
||||
}
|
||||
return tr
|
||||
|
|
@ -407,69 +409,69 @@ func (self *lendingExchangeState) updateLiquidationTimeTrie(db Database) Trie {
|
|||
Update Root
|
||||
*/
|
||||
|
||||
func (self *lendingExchangeState) updateOrderRoot(db Database) {
|
||||
self.updateLendingTimeTrie(db)
|
||||
self.data.LendingItemRoot = self.lendingItemTrie.Hash()
|
||||
func (le *lendingExchangeState) updateOrderRoot(db Database) {
|
||||
le.updateLendingTimeTrie(db)
|
||||
le.data.LendingItemRoot = le.lendingItemTrie.Hash()
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) updateInvestingRoot(db Database) error {
|
||||
self.updateInvestingTrie(db)
|
||||
if self.dbErr != nil {
|
||||
return self.dbErr
|
||||
func (le *lendingExchangeState) updateInvestingRoot(db Database) error {
|
||||
le.updateInvestingTrie(db)
|
||||
if le.dbErr != nil {
|
||||
return le.dbErr
|
||||
}
|
||||
self.data.InvestingRoot = self.investingTrie.Hash()
|
||||
le.data.InvestingRoot = le.investingTrie.Hash()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) updateBorrowingRoot(db Database) {
|
||||
self.updateBorrowingTrie(db)
|
||||
self.data.BorrowingRoot = self.borrowingTrie.Hash()
|
||||
func (le *lendingExchangeState) updateBorrowingRoot(db Database) {
|
||||
le.updateBorrowingTrie(db)
|
||||
le.data.BorrowingRoot = le.borrowingTrie.Hash()
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) updateLiquidationTimeRoot(db Database) {
|
||||
self.updateLiquidationTimeTrie(db)
|
||||
self.data.LiquidationTimeRoot = self.liquidationTimeTrie.Hash()
|
||||
func (le *lendingExchangeState) updateLiquidationTimeRoot(db Database) {
|
||||
le.updateLiquidationTimeTrie(db)
|
||||
le.data.LiquidationTimeRoot = le.liquidationTimeTrie.Hash()
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) updateLendingTradeRoot(db Database) {
|
||||
self.updateLendingTradeTrie(db)
|
||||
self.data.LendingTradeRoot = self.lendingTradeTrie.Hash()
|
||||
func (le *lendingExchangeState) updateLendingTradeRoot(db Database) {
|
||||
le.updateLendingTradeTrie(db)
|
||||
le.data.LendingTradeRoot = le.lendingTradeTrie.Hash()
|
||||
}
|
||||
|
||||
/**
|
||||
Commit Trie
|
||||
*/
|
||||
|
||||
func (self *lendingExchangeState) CommitLendingItemTrie(db Database) error {
|
||||
self.updateLendingTimeTrie(db)
|
||||
if self.dbErr != nil {
|
||||
return self.dbErr
|
||||
func (le *lendingExchangeState) CommitLendingItemTrie(db Database) error {
|
||||
le.updateLendingTimeTrie(db)
|
||||
if le.dbErr != nil {
|
||||
return le.dbErr
|
||||
}
|
||||
root, err := self.lendingItemTrie.Commit(nil)
|
||||
root, err := le.lendingItemTrie.Commit(nil)
|
||||
if err == nil {
|
||||
self.data.LendingItemRoot = root
|
||||
le.data.LendingItemRoot = root
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) CommitLendingTradeTrie(db Database) error {
|
||||
self.updateLendingTradeTrie(db)
|
||||
if self.dbErr != nil {
|
||||
return self.dbErr
|
||||
func (le *lendingExchangeState) CommitLendingTradeTrie(db Database) error {
|
||||
le.updateLendingTradeTrie(db)
|
||||
if le.dbErr != nil {
|
||||
return le.dbErr
|
||||
}
|
||||
root, err := self.lendingTradeTrie.Commit(nil)
|
||||
root, err := le.lendingTradeTrie.Commit(nil)
|
||||
if err == nil {
|
||||
self.data.LendingTradeRoot = root
|
||||
le.data.LendingTradeRoot = root
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) CommitInvestingTrie(db Database) error {
|
||||
self.updateInvestingTrie(db)
|
||||
if self.dbErr != nil {
|
||||
return self.dbErr
|
||||
func (le *lendingExchangeState) CommitInvestingTrie(db Database) error {
|
||||
le.updateInvestingTrie(db)
|
||||
if le.dbErr != nil {
|
||||
return le.dbErr
|
||||
}
|
||||
root, err := self.investingTrie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
root, err := le.investingTrie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
var orderList itemList
|
||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||
return nil
|
||||
|
|
@ -480,17 +482,17 @@ func (self *lendingExchangeState) CommitInvestingTrie(db Database) error {
|
|||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
self.data.InvestingRoot = root
|
||||
le.data.InvestingRoot = root
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) CommitBorrowingTrie(db Database) error {
|
||||
self.updateBorrowingTrie(db)
|
||||
if self.dbErr != nil {
|
||||
return self.dbErr
|
||||
func (le *lendingExchangeState) CommitBorrowingTrie(db Database) error {
|
||||
le.updateBorrowingTrie(db)
|
||||
if le.dbErr != nil {
|
||||
return le.dbErr
|
||||
}
|
||||
root, err := self.borrowingTrie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
root, err := le.borrowingTrie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
var orderList itemList
|
||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||
return nil
|
||||
|
|
@ -501,17 +503,17 @@ func (self *lendingExchangeState) CommitBorrowingTrie(db Database) error {
|
|||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
self.data.BorrowingRoot = root
|
||||
le.data.BorrowingRoot = root
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) CommitLiquidationTimeTrie(db Database) error {
|
||||
self.updateLiquidationTimeTrie(db)
|
||||
if self.dbErr != nil {
|
||||
return self.dbErr
|
||||
func (le *lendingExchangeState) CommitLiquidationTimeTrie(db Database) error {
|
||||
le.updateLiquidationTimeTrie(db)
|
||||
if le.dbErr != nil {
|
||||
return le.dbErr
|
||||
}
|
||||
root, err := self.liquidationTimeTrie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
root, err := le.liquidationTimeTrie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
var orderList itemList
|
||||
if err := rlp.DecodeBytes(leaf, &orderList); err != nil {
|
||||
return nil
|
||||
|
|
@ -522,7 +524,7 @@ func (self *lendingExchangeState) CommitLiquidationTimeTrie(db Database) error {
|
|||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
self.data.LiquidationTimeRoot = root
|
||||
le.data.LiquidationTimeRoot = root
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
@ -532,11 +534,11 @@ func (self *lendingExchangeState) CommitLiquidationTimeTrie(db Database) error {
|
|||
|
||||
Get Trie Data
|
||||
*/
|
||||
func (self *lendingExchangeState) getBestInvestingInterest(db Database) common.Hash {
|
||||
trie := self.getInvestingTrie(db)
|
||||
func (le *lendingExchangeState) getBestInvestingInterest(db Database) common.Hash {
|
||||
trie := le.getInvestingTrie(db)
|
||||
encKey, encValue, err := trie.TryGetBestLeftKeyAndValue()
|
||||
if err != nil {
|
||||
log.Error("Failed find best investing rate", "orderbook", self.lendingBook.Hex())
|
||||
log.Error("Failed find best investing rate", "orderbook", le.lendingBook.Hex())
|
||||
return EmptyHash
|
||||
}
|
||||
if len(encKey) == 0 || len(encValue) == 0 {
|
||||
|
|
@ -545,23 +547,23 @@ func (self *lendingExchangeState) getBestInvestingInterest(db Database) common.H
|
|||
}
|
||||
// Insert into the live set.
|
||||
interest := common.BytesToHash(encKey)
|
||||
if _, exist := self.investingStates[interest]; !exist {
|
||||
if _, exist := le.investingStates[interest]; !exist {
|
||||
var data itemList
|
||||
if err := rlp.DecodeBytes(encValue, &data); err != nil {
|
||||
log.Error("Failed to decode state get best investing rate", "err", err)
|
||||
return EmptyHash
|
||||
}
|
||||
obj := newItemListState(self.lendingBook, interest, data, self.MarkInvestingDirty)
|
||||
self.investingStates[interest] = obj
|
||||
obj := newItemListState(le.lendingBook, interest, data, le.MarkInvestingDirty)
|
||||
le.investingStates[interest] = obj
|
||||
}
|
||||
return interest
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) getBestBorrowingInterest(db Database) common.Hash {
|
||||
trie := self.getBorrowingTrie(db)
|
||||
func (le *lendingExchangeState) getBestBorrowingInterest(db Database) common.Hash {
|
||||
trie := le.getBorrowingTrie(db)
|
||||
encKey, encValue, err := trie.TryGetBestRightKeyAndValue()
|
||||
if err != nil {
|
||||
log.Error("Failed find best key bid trie ", "orderbook", self.lendingBook.Hex())
|
||||
log.Error("Failed find best key bid trie ", "orderbook", le.lendingBook.Hex())
|
||||
return EmptyHash
|
||||
}
|
||||
if len(encKey) == 0 || len(encValue) == 0 {
|
||||
|
|
@ -570,23 +572,23 @@ func (self *lendingExchangeState) getBestBorrowingInterest(db Database) common.H
|
|||
}
|
||||
// Insert into the live set.
|
||||
interest := common.BytesToHash(encKey)
|
||||
if _, exist := self.borrowingStates[interest]; !exist {
|
||||
if _, exist := le.borrowingStates[interest]; !exist {
|
||||
var data itemList
|
||||
if err := rlp.DecodeBytes(encValue, &data); err != nil {
|
||||
log.Error("Failed to decode state get best bid trie", "err", err)
|
||||
return EmptyHash
|
||||
}
|
||||
obj := newItemListState(self.lendingBook, interest, data, self.MarkBorrowingDirty)
|
||||
self.borrowingStates[interest] = obj
|
||||
obj := newItemListState(le.lendingBook, interest, data, le.MarkBorrowingDirty)
|
||||
le.borrowingStates[interest] = obj
|
||||
}
|
||||
return interest
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) getLowestLiquidationTime(db Database) (common.Hash, *liquidationTimeState) {
|
||||
trie := self.getLiquidationTimeTrie(db)
|
||||
func (le *lendingExchangeState) getLowestLiquidationTime(db Database) (common.Hash, *liquidationTimeState) {
|
||||
trie := le.getLiquidationTimeTrie(db)
|
||||
encKey, encValue, err := trie.TryGetBestLeftKeyAndValue()
|
||||
if err != nil {
|
||||
log.Error("Failed find best liquidation time trie ", "orderBook", self.lendingBook.Hex())
|
||||
log.Error("Failed find best liquidation time trie ", "orderBook", le.lendingBook.Hex())
|
||||
return EmptyHash, nil
|
||||
}
|
||||
if len(encKey) == 0 || len(encValue) == 0 {
|
||||
|
|
@ -594,15 +596,15 @@ func (self *lendingExchangeState) getLowestLiquidationTime(db Database) (common.
|
|||
return EmptyHash, nil
|
||||
}
|
||||
price := common.BytesToHash(encKey)
|
||||
obj, exist := self.liquidationTimeStates[price]
|
||||
obj, exist := le.liquidationTimeStates[price]
|
||||
if !exist {
|
||||
var data itemList
|
||||
if err := rlp.DecodeBytes(encValue, &data); err != nil {
|
||||
log.Error("Failed to decode state get liquidation time trie", "err", err)
|
||||
return EmptyHash, nil
|
||||
}
|
||||
obj = newLiquidationTimeState(self.lendingBook, price, data, self.MarkLiquidationTimeDirty)
|
||||
self.liquidationTimeStates[price] = obj
|
||||
obj = newLiquidationTimeState(le.lendingBook, price, data, le.MarkLiquidationTimeDirty)
|
||||
le.liquidationTimeStates[price] = obj
|
||||
}
|
||||
if obj.empty() {
|
||||
return EmptyHash, nil
|
||||
|
|
@ -610,193 +612,194 @@ func (self *lendingExchangeState) getLowestLiquidationTime(db Database) (common.
|
|||
return price, obj
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) deepCopy(db *LendingStateDB, onDirty func(hash common.Hash)) *lendingExchangeState {
|
||||
stateExchanges := newStateExchanges(db, self.lendingBook, self.data, onDirty)
|
||||
if self.investingTrie != nil {
|
||||
stateExchanges.investingTrie = db.db.CopyTrie(self.investingTrie)
|
||||
func (le *lendingExchangeState) deepCopy(db *LendingStateDB, onDirty func(hash common.Hash)) *lendingExchangeState {
|
||||
stateExchanges := newStateExchanges(db, le.lendingBook, le.data, onDirty)
|
||||
if le.investingTrie != nil {
|
||||
stateExchanges.investingTrie = db.db.CopyTrie(le.investingTrie)
|
||||
}
|
||||
if self.borrowingTrie != nil {
|
||||
stateExchanges.borrowingTrie = db.db.CopyTrie(self.borrowingTrie)
|
||||
if le.borrowingTrie != nil {
|
||||
stateExchanges.borrowingTrie = db.db.CopyTrie(le.borrowingTrie)
|
||||
}
|
||||
if self.lendingItemTrie != nil {
|
||||
stateExchanges.lendingItemTrie = db.db.CopyTrie(self.lendingItemTrie)
|
||||
if le.lendingItemTrie != nil {
|
||||
stateExchanges.lendingItemTrie = db.db.CopyTrie(le.lendingItemTrie)
|
||||
}
|
||||
for key, value := range self.borrowingStates {
|
||||
stateExchanges.borrowingStates[key] = value.deepCopy(db, self.MarkBorrowingDirty)
|
||||
for key, value := range le.borrowingStates {
|
||||
stateExchanges.borrowingStates[key] = value.deepCopy(db, le.MarkBorrowingDirty)
|
||||
}
|
||||
for key := range self.borrowingStatesDirty {
|
||||
for key := range le.borrowingStatesDirty {
|
||||
stateExchanges.borrowingStatesDirty[key] = struct{}{}
|
||||
}
|
||||
for key, value := range self.investingStates {
|
||||
stateExchanges.investingStates[key] = value.deepCopy(db, self.MarkInvestingDirty)
|
||||
for key, value := range le.investingStates {
|
||||
stateExchanges.investingStates[key] = value.deepCopy(db, le.MarkInvestingDirty)
|
||||
}
|
||||
for key := range self.investingStatesDirty {
|
||||
for key := range le.investingStatesDirty {
|
||||
stateExchanges.investingStatesDirty[key] = struct{}{}
|
||||
}
|
||||
for key, value := range self.lendingItemStates {
|
||||
stateExchanges.lendingItemStates[key] = value.deepCopy(self.MarkLendingItemDirty)
|
||||
for key, value := range le.lendingItemStates {
|
||||
stateExchanges.lendingItemStates[key] = value.deepCopy(le.MarkLendingItemDirty)
|
||||
}
|
||||
for orderId := range self.lendingItemStatesDirty {
|
||||
for orderId := range le.lendingItemStatesDirty {
|
||||
stateExchanges.lendingItemStatesDirty[orderId] = struct{}{}
|
||||
}
|
||||
for key, value := range self.lendingTradeStates {
|
||||
stateExchanges.lendingTradeStates[key] = value.deepCopy(self.MarkLendingTradeDirty)
|
||||
for key, value := range le.lendingTradeStates {
|
||||
stateExchanges.lendingTradeStates[key] = value.deepCopy(le.MarkLendingTradeDirty)
|
||||
}
|
||||
for orderId := range self.lendingTradeStatesDirty {
|
||||
for orderId := range le.lendingTradeStatesDirty {
|
||||
stateExchanges.lendingTradeStatesDirty[orderId] = struct{}{}
|
||||
}
|
||||
for time, orderList := range self.liquidationTimeStates {
|
||||
stateExchanges.liquidationTimeStates[time] = orderList.deepCopy(db, self.MarkLiquidationTimeDirty)
|
||||
for time, orderList := range le.liquidationTimeStates {
|
||||
stateExchanges.liquidationTimeStates[time] = orderList.deepCopy(db, le.MarkLiquidationTimeDirty)
|
||||
}
|
||||
for time := range self.liquidationTimestatesDirty {
|
||||
for time := range le.liquidationTimestatesDirty {
|
||||
stateExchanges.liquidationTimestatesDirty[time] = struct{}{}
|
||||
}
|
||||
return stateExchanges
|
||||
}
|
||||
|
||||
// Returns the address of the contract/tradeId
|
||||
func (self *lendingExchangeState) Hash() common.Hash {
|
||||
return self.lendingBook
|
||||
func (le *lendingExchangeState) Hash() common.Hash {
|
||||
return le.lendingBook
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) setNonce(nonce uint64) {
|
||||
self.data.Nonce = nonce
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
func (le *lendingExchangeState) setNonce(nonce uint64) {
|
||||
le.data.Nonce = nonce
|
||||
if le.onDirty != nil {
|
||||
le.onDirty(le.Hash())
|
||||
le.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) Nonce() uint64 {
|
||||
return self.data.Nonce
|
||||
func (le *lendingExchangeState) Nonce() uint64 {
|
||||
return le.data.Nonce
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) setTradeNonce(nonce uint64) {
|
||||
self.data.TradeNonce = nonce
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
func (le *lendingExchangeState) setTradeNonce(nonce uint64) {
|
||||
le.data.TradeNonce = nonce
|
||||
if le.onDirty != nil {
|
||||
le.onDirty(le.Hash())
|
||||
le.onDirty = nil
|
||||
}
|
||||
}
|
||||
func (self *lendingExchangeState) TradeNonce() uint64 {
|
||||
return self.data.TradeNonce
|
||||
|
||||
func (le *lendingExchangeState) TradeNonce() uint64 {
|
||||
return le.data.TradeNonce
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) removeInvestingOrderList(db Database, stateOrderList *itemListState) {
|
||||
self.setError(self.investingTrie.TryDelete(stateOrderList.key[:]))
|
||||
func (le *lendingExchangeState) removeInvestingOrderList(db Database, stateOrderList *itemListState) {
|
||||
le.setError(le.investingTrie.TryDelete(stateOrderList.key[:]))
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) removeBorrowingOrderList(db Database, stateOrderList *itemListState) {
|
||||
self.setError(self.borrowingTrie.TryDelete(stateOrderList.key[:]))
|
||||
func (le *lendingExchangeState) removeBorrowingOrderList(db Database, stateOrderList *itemListState) {
|
||||
le.setError(le.borrowingTrie.TryDelete(stateOrderList.key[:]))
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) createInvestingOrderList(db Database, price common.Hash) (newobj *itemListState) {
|
||||
newobj = newItemListState(self.lendingBook, price, itemList{Volume: Zero}, self.MarkInvestingDirty)
|
||||
self.investingStates[price] = newobj
|
||||
self.investingStatesDirty[price] = struct{}{}
|
||||
func (le *lendingExchangeState) createInvestingOrderList(db Database, price common.Hash) (newobj *itemListState) {
|
||||
newobj = newItemListState(le.lendingBook, price, itemList{Volume: Zero}, le.MarkInvestingDirty)
|
||||
le.investingStates[price] = newobj
|
||||
le.investingStatesDirty[price] = struct{}{}
|
||||
data, err := rlp.EncodeToBytes(newobj)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("can't encode order list object at %x: %v", price[:], err))
|
||||
}
|
||||
self.setError(self.getInvestingTrie(db).TryUpdate(price[:], data))
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
le.setError(le.getInvestingTrie(db).TryUpdate(price[:], data))
|
||||
if le.onDirty != nil {
|
||||
le.onDirty(le.Hash())
|
||||
le.onDirty = nil
|
||||
}
|
||||
return newobj
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) MarkBorrowingDirty(price common.Hash) {
|
||||
self.borrowingStatesDirty[price] = struct{}{}
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
func (le *lendingExchangeState) MarkBorrowingDirty(price common.Hash) {
|
||||
le.borrowingStatesDirty[price] = struct{}{}
|
||||
if le.onDirty != nil {
|
||||
le.onDirty(le.Hash())
|
||||
le.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) MarkInvestingDirty(price common.Hash) {
|
||||
self.investingStatesDirty[price] = struct{}{}
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
func (le *lendingExchangeState) MarkInvestingDirty(price common.Hash) {
|
||||
le.investingStatesDirty[price] = struct{}{}
|
||||
if le.onDirty != nil {
|
||||
le.onDirty(le.Hash())
|
||||
le.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) MarkLendingItemDirty(lending common.Hash) {
|
||||
self.lendingItemStatesDirty[lending] = struct{}{}
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
func (le *lendingExchangeState) MarkLendingItemDirty(lending common.Hash) {
|
||||
le.lendingItemStatesDirty[lending] = struct{}{}
|
||||
if le.onDirty != nil {
|
||||
le.onDirty(le.Hash())
|
||||
le.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) MarkLendingTradeDirty(tradeId common.Hash) {
|
||||
self.lendingTradeStatesDirty[tradeId] = struct{}{}
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
func (le *lendingExchangeState) MarkLendingTradeDirty(tradeId common.Hash) {
|
||||
le.lendingTradeStatesDirty[tradeId] = struct{}{}
|
||||
if le.onDirty != nil {
|
||||
le.onDirty(le.Hash())
|
||||
le.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) MarkLiquidationTimeDirty(orderId common.Hash) {
|
||||
self.liquidationTimestatesDirty[orderId] = struct{}{}
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
func (le *lendingExchangeState) MarkLiquidationTimeDirty(orderId common.Hash) {
|
||||
le.liquidationTimestatesDirty[orderId] = struct{}{}
|
||||
if le.onDirty != nil {
|
||||
le.onDirty(le.Hash())
|
||||
le.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) createBorrowingOrderList(db Database, price common.Hash) (newobj *itemListState) {
|
||||
newobj = newItemListState(self.lendingBook, price, itemList{Volume: Zero}, self.MarkBorrowingDirty)
|
||||
self.borrowingStates[price] = newobj
|
||||
self.borrowingStatesDirty[price] = struct{}{}
|
||||
func (le *lendingExchangeState) createBorrowingOrderList(db Database, price common.Hash) (newobj *itemListState) {
|
||||
newobj = newItemListState(le.lendingBook, price, itemList{Volume: Zero}, le.MarkBorrowingDirty)
|
||||
le.borrowingStates[price] = newobj
|
||||
le.borrowingStatesDirty[price] = struct{}{}
|
||||
data, err := rlp.EncodeToBytes(newobj)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("can't encode order list object at %x: %v", price[:], err))
|
||||
}
|
||||
self.setError(self.getBorrowingTrie(db).TryUpdate(price[:], data))
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.Hash())
|
||||
self.onDirty = nil
|
||||
le.setError(le.getBorrowingTrie(db).TryUpdate(price[:], data))
|
||||
if le.onDirty != nil {
|
||||
le.onDirty(le.Hash())
|
||||
le.onDirty = nil
|
||||
}
|
||||
return newobj
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) createLendingItem(db Database, orderId common.Hash, order LendingItem) (newobj *lendingItemState) {
|
||||
newobj = newLendinItemState(self.lendingBook, orderId, order, self.MarkLendingItemDirty)
|
||||
func (le *lendingExchangeState) createLendingItem(db Database, orderId common.Hash, order LendingItem) (newobj *lendingItemState) {
|
||||
newobj = newLendinItemState(le.lendingBook, orderId, order, le.MarkLendingItemDirty)
|
||||
orderIdHash := common.BigToHash(new(big.Int).SetUint64(order.LendingId))
|
||||
self.lendingItemStates[orderIdHash] = newobj
|
||||
self.lendingItemStatesDirty[orderIdHash] = struct{}{}
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.lendingBook)
|
||||
self.onDirty = nil
|
||||
le.lendingItemStates[orderIdHash] = newobj
|
||||
le.lendingItemStatesDirty[orderIdHash] = struct{}{}
|
||||
if le.onDirty != nil {
|
||||
le.onDirty(le.lendingBook)
|
||||
le.onDirty = nil
|
||||
}
|
||||
return newobj
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) createLiquidationTime(db Database, time common.Hash) (newobj *liquidationTimeState) {
|
||||
newobj = newLiquidationTimeState(time, self.lendingBook, itemList{Volume: Zero}, self.MarkLiquidationTimeDirty)
|
||||
self.liquidationTimeStates[time] = newobj
|
||||
self.liquidationTimestatesDirty[time] = struct{}{}
|
||||
func (le *lendingExchangeState) createLiquidationTime(db Database, time common.Hash) (newobj *liquidationTimeState) {
|
||||
newobj = newLiquidationTimeState(time, le.lendingBook, itemList{Volume: Zero}, le.MarkLiquidationTimeDirty)
|
||||
le.liquidationTimeStates[time] = newobj
|
||||
le.liquidationTimestatesDirty[time] = struct{}{}
|
||||
data, err := rlp.EncodeToBytes(newobj)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("can't encode liquidation time at %x: %v", time[:], err))
|
||||
}
|
||||
self.setError(self.getLiquidationTimeTrie(db).TryUpdate(time[:], data))
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.lendingBook)
|
||||
self.onDirty = nil
|
||||
le.setError(le.getLiquidationTimeTrie(db).TryUpdate(time[:], data))
|
||||
if le.onDirty != nil {
|
||||
le.onDirty(le.lendingBook)
|
||||
le.onDirty = nil
|
||||
}
|
||||
return newobj
|
||||
}
|
||||
|
||||
func (self *lendingExchangeState) insertLendingTrade(tradeId common.Hash, order LendingTrade) (newobj *lendingTradeState) {
|
||||
newobj = newLendingTradeState(self.lendingBook, tradeId, order, self.MarkLendingTradeDirty)
|
||||
self.lendingTradeStates[tradeId] = newobj
|
||||
self.lendingTradeStatesDirty[tradeId] = struct{}{}
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.lendingBook)
|
||||
self.onDirty = nil
|
||||
func (le *lendingExchangeState) insertLendingTrade(tradeId common.Hash, order LendingTrade) (newobj *lendingTradeState) {
|
||||
newobj = newLendingTradeState(le.lendingBook, tradeId, order, le.MarkLendingTradeDirty)
|
||||
le.lendingTradeStates[tradeId] = newobj
|
||||
le.lendingTradeStatesDirty[tradeId] = struct{}{}
|
||||
if le.onDirty != nil {
|
||||
le.onDirty(le.lendingBook)
|
||||
le.onDirty = nil
|
||||
}
|
||||
return newobj
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ type lendingItemState struct {
|
|||
onDirty func(orderId common.Hash) // Callback method to mark a state object newly dirty
|
||||
}
|
||||
|
||||
func (s *lendingItemState) empty() bool {
|
||||
return s.data.Quantity == nil || s.data.Quantity.Cmp(Zero) == 0
|
||||
func (li *lendingItemState) empty() bool {
|
||||
return li.data.Quantity == nil || li.data.Quantity.Cmp(Zero) == 0
|
||||
}
|
||||
|
||||
func newLendinItemState(orderBook common.Hash, orderId common.Hash, data LendingItem, onDirty func(orderId common.Hash)) *lendingItemState {
|
||||
|
|
@ -45,23 +45,23 @@ func newLendinItemState(orderBook common.Hash, orderId common.Hash, data Lending
|
|||
}
|
||||
|
||||
// EncodeRLP implements rlp.Encoder.
|
||||
func (c *lendingItemState) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, c.data)
|
||||
func (li *lendingItemState) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, li.data)
|
||||
}
|
||||
|
||||
func (self *lendingItemState) deepCopy(onDirty func(orderId common.Hash)) *lendingItemState {
|
||||
stateOrderList := newLendinItemState(self.orderBook, self.orderId, self.data, onDirty)
|
||||
func (li *lendingItemState) deepCopy(onDirty func(orderId common.Hash)) *lendingItemState {
|
||||
stateOrderList := newLendinItemState(li.orderBook, li.orderId, li.data, onDirty)
|
||||
return stateOrderList
|
||||
}
|
||||
|
||||
func (self *lendingItemState) setVolume(volume *big.Int) {
|
||||
self.data.Quantity = volume
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.orderId)
|
||||
self.onDirty = nil
|
||||
func (li *lendingItemState) setVolume(volume *big.Int) {
|
||||
li.data.Quantity = volume
|
||||
if li.onDirty != nil {
|
||||
li.onDirty(li.orderId)
|
||||
li.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *lendingItemState) Quantity() *big.Int {
|
||||
return self.data.Quantity
|
||||
func (li *lendingItemState) Quantity() *big.Int {
|
||||
return li.data.Quantity
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,10 +17,11 @@
|
|||
package lendingstate
|
||||
|
||||
import (
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||
)
|
||||
|
||||
type lendingTradeState struct {
|
||||
|
|
@ -30,8 +31,8 @@ type lendingTradeState struct {
|
|||
onDirty func(orderId common.Hash) // Callback method to mark a state object newly dirty
|
||||
}
|
||||
|
||||
func (s *lendingTradeState) empty() bool {
|
||||
return s.data.Amount.Sign() == 0
|
||||
func (lt *lendingTradeState) empty() bool {
|
||||
return lt.data.Amount.Sign() == 0
|
||||
}
|
||||
|
||||
func newLendingTradeState(orderBook common.Hash, tradeId common.Hash, data LendingTrade, onDirty func(orderId common.Hash)) *lendingTradeState {
|
||||
|
|
@ -44,35 +45,35 @@ func newLendingTradeState(orderBook common.Hash, tradeId common.Hash, data Lendi
|
|||
}
|
||||
|
||||
// EncodeRLP implements rlp.Encoder.
|
||||
func (c *lendingTradeState) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, c.data)
|
||||
func (lt *lendingTradeState) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, lt.data)
|
||||
}
|
||||
|
||||
func (self *lendingTradeState) deepCopy(onDirty func(orderId common.Hash)) *lendingTradeState {
|
||||
stateOrderList := newLendingTradeState(self.orderBook, self.tradeId, self.data, onDirty)
|
||||
func (lt *lendingTradeState) deepCopy(onDirty func(orderId common.Hash)) *lendingTradeState {
|
||||
stateOrderList := newLendingTradeState(lt.orderBook, lt.tradeId, lt.data, onDirty)
|
||||
return stateOrderList
|
||||
}
|
||||
|
||||
func (self *lendingTradeState) SetCollateralLockedAmount(amount *big.Int) {
|
||||
self.data.CollateralLockedAmount = amount
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.tradeId)
|
||||
self.onDirty = nil
|
||||
func (lt *lendingTradeState) SetCollateralLockedAmount(amount *big.Int) {
|
||||
lt.data.CollateralLockedAmount = amount
|
||||
if lt.onDirty != nil {
|
||||
lt.onDirty(lt.tradeId)
|
||||
lt.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *lendingTradeState) SetLiquidationPrice(price *big.Int) {
|
||||
self.data.LiquidationPrice = price
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.tradeId)
|
||||
self.onDirty = nil
|
||||
func (lt *lendingTradeState) SetLiquidationPrice(price *big.Int) {
|
||||
lt.data.LiquidationPrice = price
|
||||
if lt.onDirty != nil {
|
||||
lt.onDirty(lt.tradeId)
|
||||
lt.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *lendingTradeState) SetAmount(amount *big.Int) {
|
||||
self.data.Amount = amount
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.tradeId)
|
||||
self.onDirty = nil
|
||||
func (lt *lendingTradeState) SetAmount(amount *big.Int) {
|
||||
lt.data.Amount = amount
|
||||
if lt.onDirty != nil {
|
||||
lt.onDirty(lt.tradeId)
|
||||
lt.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,11 +19,12 @@ package lendingstate
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||
"github.com/XinFinOrg/XDPoSChain/trie"
|
||||
"io"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type liquidationTimeState struct {
|
||||
|
|
@ -47,8 +48,8 @@ type liquidationTimeState struct {
|
|||
onDirty func(time common.Hash) // Callback method to mark a state object newly dirty
|
||||
}
|
||||
|
||||
func (s *liquidationTimeState) empty() bool {
|
||||
return s.data.Volume == nil || s.data.Volume.Sign() == 0
|
||||
func (lt *liquidationTimeState) empty() bool {
|
||||
return lt.data.Volume == nil || lt.data.Volume.Sign() == 0
|
||||
}
|
||||
|
||||
func newLiquidationTimeState(time common.Hash, lendingBook common.Hash, data itemList, onDirty func(time common.Hash)) *liquidationTimeState {
|
||||
|
|
@ -62,59 +63,59 @@ func newLiquidationTimeState(time common.Hash, lendingBook common.Hash, data ite
|
|||
}
|
||||
}
|
||||
|
||||
func (self *liquidationTimeState) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, self.data)
|
||||
func (lt *liquidationTimeState) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, lt.data)
|
||||
}
|
||||
|
||||
func (self *liquidationTimeState) setError(err error) {
|
||||
if self.dbErr == nil {
|
||||
self.dbErr = err
|
||||
func (lt *liquidationTimeState) setError(err error) {
|
||||
if lt.dbErr == nil {
|
||||
lt.dbErr = err
|
||||
}
|
||||
}
|
||||
|
||||
func (self *liquidationTimeState) getTrie(db Database) Trie {
|
||||
if self.trie == nil {
|
||||
func (lt *liquidationTimeState) getTrie(db Database) Trie {
|
||||
if lt.trie == nil {
|
||||
var err error
|
||||
self.trie, err = db.OpenStorageTrie(self.lendingBook, self.data.Root)
|
||||
lt.trie, err = db.OpenStorageTrie(lt.lendingBook, lt.data.Root)
|
||||
if err != nil {
|
||||
self.trie, _ = db.OpenStorageTrie(self.time, EmptyHash)
|
||||
self.setError(fmt.Errorf("can't create storage trie: %v", err))
|
||||
lt.trie, _ = db.OpenStorageTrie(lt.time, EmptyHash)
|
||||
lt.setError(fmt.Errorf("can't create storage trie: %v", err))
|
||||
}
|
||||
}
|
||||
return self.trie
|
||||
return lt.trie
|
||||
}
|
||||
|
||||
func (self *liquidationTimeState) Exist(db Database, tradeId common.Hash) bool {
|
||||
amount, exists := self.cachedStorage[tradeId]
|
||||
func (lt *liquidationTimeState) Exist(db Database, tradeId common.Hash) bool {
|
||||
amount, exists := lt.cachedStorage[tradeId]
|
||||
if exists {
|
||||
return true
|
||||
}
|
||||
// Load from DB in case it is missing.
|
||||
enc, err := self.getTrie(db).TryGet(tradeId[:])
|
||||
enc, err := lt.getTrie(db).TryGet(tradeId[:])
|
||||
if err != nil {
|
||||
self.setError(err)
|
||||
lt.setError(err)
|
||||
return false
|
||||
}
|
||||
if len(enc) > 0 {
|
||||
_, content, _, err := rlp.Split(enc)
|
||||
if err != nil {
|
||||
self.setError(err)
|
||||
lt.setError(err)
|
||||
}
|
||||
amount.SetBytes(content)
|
||||
}
|
||||
if (amount != common.Hash{}) {
|
||||
self.cachedStorage[tradeId] = amount
|
||||
lt.cachedStorage[tradeId] = amount
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *liquidationTimeState) getAllTradeIds(db Database) []common.Hash {
|
||||
func (lt *liquidationTimeState) getAllTradeIds(db Database) []common.Hash {
|
||||
tradeIds := []common.Hash{}
|
||||
lendingBookTrie := self.getTrie(db)
|
||||
lendingBookTrie := lt.getTrie(db)
|
||||
if lendingBookTrie == nil {
|
||||
return tradeIds
|
||||
}
|
||||
for id, value := range self.cachedStorage {
|
||||
for id, value := range lt.cachedStorage {
|
||||
if !common.EmptyHash(value) {
|
||||
tradeIds = append(tradeIds, id)
|
||||
}
|
||||
|
|
@ -122,7 +123,7 @@ func (self *liquidationTimeState) getAllTradeIds(db Database) []common.Hash {
|
|||
orderListIt := trie.NewIterator(lendingBookTrie.NodeIterator(nil))
|
||||
for orderListIt.Next() {
|
||||
id := common.BytesToHash(orderListIt.Key)
|
||||
if _, exist := self.cachedStorage[id]; exist {
|
||||
if _, exist := lt.cachedStorage[id]; exist {
|
||||
continue
|
||||
}
|
||||
tradeIds = append(tradeIds, id)
|
||||
|
|
@ -130,83 +131,83 @@ func (self *liquidationTimeState) getAllTradeIds(db Database) []common.Hash {
|
|||
return tradeIds
|
||||
}
|
||||
|
||||
func (self *liquidationTimeState) insertTradeId(db Database, tradeId common.Hash) {
|
||||
self.setTradeId(tradeId, tradeId)
|
||||
self.setError(self.getTrie(db).TryUpdate(tradeId[:], tradeId[:]))
|
||||
func (lt *liquidationTimeState) insertTradeId(db Database, tradeId common.Hash) {
|
||||
lt.setTradeId(tradeId, tradeId)
|
||||
lt.setError(lt.getTrie(db).TryUpdate(tradeId[:], tradeId[:]))
|
||||
}
|
||||
|
||||
func (self *liquidationTimeState) removeTradeId(db Database, tradeId common.Hash) {
|
||||
tr := self.getTrie(db)
|
||||
self.setError(tr.TryDelete(tradeId[:]))
|
||||
self.setTradeId(tradeId, EmptyHash)
|
||||
func (lt *liquidationTimeState) removeTradeId(db Database, tradeId common.Hash) {
|
||||
tr := lt.getTrie(db)
|
||||
lt.setError(tr.TryDelete(tradeId[:]))
|
||||
lt.setTradeId(tradeId, EmptyHash)
|
||||
}
|
||||
|
||||
func (self *liquidationTimeState) setTradeId(tradeId common.Hash, value common.Hash) {
|
||||
self.cachedStorage[tradeId] = value
|
||||
self.dirtyStorage[tradeId] = value
|
||||
func (lt *liquidationTimeState) setTradeId(tradeId common.Hash, value common.Hash) {
|
||||
lt.cachedStorage[tradeId] = value
|
||||
lt.dirtyStorage[tradeId] = value
|
||||
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.lendingBook)
|
||||
self.onDirty = nil
|
||||
if lt.onDirty != nil {
|
||||
lt.onDirty(lt.lendingBook)
|
||||
lt.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *liquidationTimeState) updateTrie(db Database) Trie {
|
||||
tr := self.getTrie(db)
|
||||
for key, value := range self.dirtyStorage {
|
||||
delete(self.dirtyStorage, key)
|
||||
func (lt *liquidationTimeState) updateTrie(db Database) Trie {
|
||||
tr := lt.getTrie(db)
|
||||
for key, value := range lt.dirtyStorage {
|
||||
delete(lt.dirtyStorage, key)
|
||||
if value == EmptyHash {
|
||||
self.setError(tr.TryDelete(key[:]))
|
||||
lt.setError(tr.TryDelete(key[:]))
|
||||
continue
|
||||
}
|
||||
v, _ := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00"))
|
||||
self.setError(tr.TryUpdate(key[:], v))
|
||||
lt.setError(tr.TryUpdate(key[:], v))
|
||||
}
|
||||
return tr
|
||||
}
|
||||
|
||||
func (self *liquidationTimeState) updateRoot(db Database) error {
|
||||
self.updateTrie(db)
|
||||
if self.dbErr != nil {
|
||||
return self.dbErr
|
||||
func (lt *liquidationTimeState) updateRoot(db Database) error {
|
||||
lt.updateTrie(db)
|
||||
if lt.dbErr != nil {
|
||||
return lt.dbErr
|
||||
}
|
||||
root, err := self.trie.Commit(nil)
|
||||
root, err := lt.trie.Commit(nil)
|
||||
if err == nil {
|
||||
self.data.Root = root
|
||||
lt.data.Root = root
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *liquidationTimeState) deepCopy(db *LendingStateDB, onDirty func(time common.Hash)) *liquidationTimeState {
|
||||
stateLendingBook := newLiquidationTimeState(self.lendingBook, self.time, self.data, onDirty)
|
||||
if self.trie != nil {
|
||||
stateLendingBook.trie = db.db.CopyTrie(self.trie)
|
||||
func (lt *liquidationTimeState) deepCopy(db *LendingStateDB, onDirty func(time common.Hash)) *liquidationTimeState {
|
||||
stateLendingBook := newLiquidationTimeState(lt.lendingBook, lt.time, lt.data, onDirty)
|
||||
if lt.trie != nil {
|
||||
stateLendingBook.trie = db.db.CopyTrie(lt.trie)
|
||||
}
|
||||
for key, value := range self.dirtyStorage {
|
||||
for key, value := range lt.dirtyStorage {
|
||||
stateLendingBook.dirtyStorage[key] = value
|
||||
}
|
||||
for key, value := range self.cachedStorage {
|
||||
for key, value := range lt.cachedStorage {
|
||||
stateLendingBook.cachedStorage[key] = value
|
||||
}
|
||||
return stateLendingBook
|
||||
}
|
||||
|
||||
func (c *liquidationTimeState) AddVolume(amount *big.Int) {
|
||||
c.setVolume(new(big.Int).Add(c.data.Volume, amount))
|
||||
func (lt *liquidationTimeState) AddVolume(amount *big.Int) {
|
||||
lt.setVolume(new(big.Int).Add(lt.data.Volume, amount))
|
||||
}
|
||||
|
||||
func (c *liquidationTimeState) subVolume(amount *big.Int) {
|
||||
c.setVolume(new(big.Int).Sub(c.data.Volume, amount))
|
||||
func (lt *liquidationTimeState) subVolume(amount *big.Int) {
|
||||
lt.setVolume(new(big.Int).Sub(lt.data.Volume, amount))
|
||||
}
|
||||
|
||||
func (self *liquidationTimeState) setVolume(volume *big.Int) {
|
||||
self.data.Volume = volume
|
||||
if self.onDirty != nil {
|
||||
self.onDirty(self.lendingBook)
|
||||
self.onDirty = nil
|
||||
func (lt *liquidationTimeState) setVolume(volume *big.Int) {
|
||||
lt.data.Volume = volume
|
||||
if lt.onDirty != nil {
|
||||
lt.onDirty(lt.lendingBook)
|
||||
lt.onDirty = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *liquidationTimeState) Volume() *big.Int {
|
||||
return self.data.Volume
|
||||
func (lt *liquidationTimeState) Volume() *big.Int {
|
||||
return lt.data.Volume
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,39 +73,39 @@ func New(root common.Hash, db Database) (*LendingStateDB, error) {
|
|||
}
|
||||
|
||||
// setError remembers the first non-nil error it is called with.
|
||||
func (self *LendingStateDB) setError(err error) {
|
||||
if self.dbErr == nil {
|
||||
self.dbErr = err
|
||||
func (ls *LendingStateDB) setError(err error) {
|
||||
if ls.dbErr == nil {
|
||||
ls.dbErr = err
|
||||
}
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) Error() error {
|
||||
return self.dbErr
|
||||
func (ls *LendingStateDB) Error() error {
|
||||
return ls.dbErr
|
||||
}
|
||||
|
||||
// Exist reports whether the given tradeId address exists in the state.
|
||||
// Notably this also returns true for suicided lenddinges.
|
||||
func (self *LendingStateDB) Exist(addr common.Hash) bool {
|
||||
return self.getLendingExchange(addr) != nil
|
||||
func (ls *LendingStateDB) Exist(addr common.Hash) bool {
|
||||
return ls.getLendingExchange(addr) != nil
|
||||
}
|
||||
|
||||
// Empty returns whether the state object is either non-existent
|
||||
// or empty according to the EIP161 specification (balance = nonce = code = 0)
|
||||
func (self *LendingStateDB) Empty(addr common.Hash) bool {
|
||||
so := self.getLendingExchange(addr)
|
||||
func (ls *LendingStateDB) Empty(addr common.Hash) bool {
|
||||
so := ls.getLendingExchange(addr)
|
||||
return so == nil || so.empty()
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) GetNonce(addr common.Hash) uint64 {
|
||||
stateObject := self.getLendingExchange(addr)
|
||||
func (ls *LendingStateDB) GetNonce(addr common.Hash) uint64 {
|
||||
stateObject := ls.getLendingExchange(addr)
|
||||
if stateObject != nil {
|
||||
return stateObject.Nonce()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) GetTradeNonce(addr common.Hash) uint64 {
|
||||
stateObject := self.getLendingExchange(addr)
|
||||
func (ls *LendingStateDB) GetTradeNonce(addr common.Hash) uint64 {
|
||||
stateObject := ls.getLendingExchange(addr)
|
||||
if stateObject != nil {
|
||||
return stateObject.TradeNonce()
|
||||
}
|
||||
|
|
@ -113,14 +113,14 @@ func (self *LendingStateDB) GetTradeNonce(addr common.Hash) uint64 {
|
|||
}
|
||||
|
||||
// Database retrieves the low level database supporting the lower level trie ops.
|
||||
func (self *LendingStateDB) Database() Database {
|
||||
return self.db
|
||||
func (ls *LendingStateDB) Database() Database {
|
||||
return ls.db
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) SetNonce(addr common.Hash, nonce uint64) {
|
||||
stateObject := self.GetOrNewLendingExchangeObject(addr)
|
||||
func (ls *LendingStateDB) SetNonce(addr common.Hash, nonce uint64) {
|
||||
stateObject := ls.GetOrNewLendingExchangeObject(addr)
|
||||
if stateObject != nil {
|
||||
self.journal = append(self.journal, nonceChange{
|
||||
ls.journal = append(ls.journal, nonceChange{
|
||||
hash: addr,
|
||||
prev: stateObject.Nonce(),
|
||||
})
|
||||
|
|
@ -128,10 +128,10 @@ func (self *LendingStateDB) SetNonce(addr common.Hash, nonce uint64) {
|
|||
}
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) SetTradeNonce(addr common.Hash, nonce uint64) {
|
||||
stateObject := self.GetOrNewLendingExchangeObject(addr)
|
||||
func (ls *LendingStateDB) SetTradeNonce(addr common.Hash, nonce uint64) {
|
||||
stateObject := ls.GetOrNewLendingExchangeObject(addr)
|
||||
if stateObject != nil {
|
||||
self.journal = append(self.journal, tradeNonceChange{
|
||||
ls.journal = append(ls.journal, tradeNonceChange{
|
||||
hash: addr,
|
||||
prev: stateObject.TradeNonce(),
|
||||
})
|
||||
|
|
@ -139,45 +139,45 @@ func (self *LendingStateDB) SetTradeNonce(addr common.Hash, nonce uint64) {
|
|||
}
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) InsertLendingItem(orderBook common.Hash, orderId common.Hash, order LendingItem) {
|
||||
func (ls *LendingStateDB) InsertLendingItem(orderBook common.Hash, orderId common.Hash, order LendingItem) {
|
||||
interestHash := common.BigToHash(order.Interest)
|
||||
stateExchange := self.getLendingExchange(orderBook)
|
||||
stateExchange := ls.getLendingExchange(orderBook)
|
||||
if stateExchange == nil {
|
||||
stateExchange = self.createLendingExchangeObject(orderBook)
|
||||
stateExchange = ls.createLendingExchangeObject(orderBook)
|
||||
}
|
||||
var stateOrderList *itemListState
|
||||
switch order.Side {
|
||||
case Investing:
|
||||
stateOrderList = stateExchange.getInvestingOrderList(self.db, interestHash)
|
||||
stateOrderList = stateExchange.getInvestingOrderList(ls.db, interestHash)
|
||||
if stateOrderList == nil {
|
||||
stateOrderList = stateExchange.createInvestingOrderList(self.db, interestHash)
|
||||
stateOrderList = stateExchange.createInvestingOrderList(ls.db, interestHash)
|
||||
}
|
||||
case Borrowing:
|
||||
stateOrderList = stateExchange.getBorrowingOrderList(self.db, interestHash)
|
||||
stateOrderList = stateExchange.getBorrowingOrderList(ls.db, interestHash)
|
||||
if stateOrderList == nil {
|
||||
stateOrderList = stateExchange.createBorrowingOrderList(self.db, interestHash)
|
||||
stateOrderList = stateExchange.createBorrowingOrderList(ls.db, interestHash)
|
||||
}
|
||||
default:
|
||||
return
|
||||
}
|
||||
self.journal = append(self.journal, insertOrder{
|
||||
ls.journal = append(ls.journal, insertOrder{
|
||||
orderBook: orderBook,
|
||||
orderId: orderId,
|
||||
order: &order,
|
||||
})
|
||||
stateExchange.createLendingItem(self.db, orderId, order)
|
||||
stateOrderList.insertLendingItem(self.db, orderId, common.BigToHash(order.Quantity))
|
||||
stateExchange.createLendingItem(ls.db, orderId, order)
|
||||
stateOrderList.insertLendingItem(ls.db, orderId, common.BigToHash(order.Quantity))
|
||||
stateOrderList.AddVolume(order.Quantity)
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) InsertTradingItem(orderBook common.Hash, tradeId uint64, order LendingTrade) {
|
||||
func (ls *LendingStateDB) InsertTradingItem(orderBook common.Hash, tradeId uint64, order LendingTrade) {
|
||||
tradeIdHash := common.Uint64ToHash(tradeId)
|
||||
stateExchange := self.getLendingExchange(orderBook)
|
||||
stateExchange := ls.getLendingExchange(orderBook)
|
||||
if stateExchange == nil {
|
||||
stateExchange = self.createLendingExchangeObject(orderBook)
|
||||
stateExchange = ls.createLendingExchangeObject(orderBook)
|
||||
}
|
||||
prvTrade := self.GetLendingTrade(orderBook, tradeIdHash)
|
||||
self.journal = append(self.journal, insertTrading{
|
||||
prvTrade := ls.GetLendingTrade(orderBook, tradeIdHash)
|
||||
ls.journal = append(ls.journal, insertTrading{
|
||||
orderBook: orderBook,
|
||||
tradeId: tradeId,
|
||||
prvTrade: &prvTrade,
|
||||
|
|
@ -185,88 +185,90 @@ func (self *LendingStateDB) InsertTradingItem(orderBook common.Hash, tradeId uin
|
|||
stateExchange.insertLendingTrade(tradeIdHash, order)
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) UpdateLiquidationPrice(orderBook common.Hash, tradeId uint64, price *big.Int) {
|
||||
func (ls *LendingStateDB) UpdateLiquidationPrice(orderBook common.Hash, tradeId uint64, price *big.Int) {
|
||||
tradeIdHash := common.Uint64ToHash(tradeId)
|
||||
stateExchange := self.getLendingExchange(orderBook)
|
||||
stateExchange := ls.getLendingExchange(orderBook)
|
||||
if stateExchange == nil {
|
||||
stateExchange = self.createLendingExchangeObject(orderBook)
|
||||
stateExchange = ls.createLendingExchangeObject(orderBook)
|
||||
}
|
||||
stateLendingTrade := stateExchange.getLendingTrade(self.db, tradeIdHash)
|
||||
self.journal = append(self.journal, liquidationPriceChange{
|
||||
stateLendingTrade := stateExchange.getLendingTrade(ls.db, tradeIdHash)
|
||||
ls.journal = append(ls.journal, liquidationPriceChange{
|
||||
orderBook: orderBook,
|
||||
tradeId: tradeIdHash,
|
||||
prev: stateLendingTrade.data.LiquidationPrice,
|
||||
})
|
||||
stateLendingTrade.SetLiquidationPrice(price)
|
||||
}
|
||||
func (self *LendingStateDB) UpdateCollateralLockedAmount(orderBook common.Hash, tradeId uint64, amount *big.Int) {
|
||||
|
||||
func (ls *LendingStateDB) UpdateCollateralLockedAmount(orderBook common.Hash, tradeId uint64, amount *big.Int) {
|
||||
tradeIdHash := common.Uint64ToHash(tradeId)
|
||||
stateExchange := self.getLendingExchange(orderBook)
|
||||
stateExchange := ls.getLendingExchange(orderBook)
|
||||
if stateExchange == nil {
|
||||
stateExchange = self.createLendingExchangeObject(orderBook)
|
||||
stateExchange = ls.createLendingExchangeObject(orderBook)
|
||||
}
|
||||
stateLendingTrade := stateExchange.getLendingTrade(self.db, tradeIdHash)
|
||||
self.journal = append(self.journal, collateralLockedAmount{
|
||||
stateLendingTrade := stateExchange.getLendingTrade(ls.db, tradeIdHash)
|
||||
ls.journal = append(ls.journal, collateralLockedAmount{
|
||||
orderBook: orderBook,
|
||||
tradeId: tradeIdHash,
|
||||
prev: stateLendingTrade.data.CollateralLockedAmount,
|
||||
})
|
||||
stateLendingTrade.SetCollateralLockedAmount(amount)
|
||||
}
|
||||
func (self *LendingStateDB) GetLendingOrder(orderBook common.Hash, orderId common.Hash) LendingItem {
|
||||
stateObject := self.GetOrNewLendingExchangeObject(orderBook)
|
||||
|
||||
func (ls *LendingStateDB) GetLendingOrder(orderBook common.Hash, orderId common.Hash) LendingItem {
|
||||
stateObject := ls.GetOrNewLendingExchangeObject(orderBook)
|
||||
if stateObject == nil {
|
||||
return EmptyLendingOrder
|
||||
}
|
||||
stateOrderItem := stateObject.getLendingItem(self.db, orderId)
|
||||
stateOrderItem := stateObject.getLendingItem(ls.db, orderId)
|
||||
if stateOrderItem == nil {
|
||||
return EmptyLendingOrder
|
||||
}
|
||||
return stateOrderItem.data
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) GetLendingTrade(orderBook common.Hash, tradeId common.Hash) LendingTrade {
|
||||
stateObject := self.GetOrNewLendingExchangeObject(orderBook)
|
||||
func (ls *LendingStateDB) GetLendingTrade(orderBook common.Hash, tradeId common.Hash) LendingTrade {
|
||||
stateObject := ls.GetOrNewLendingExchangeObject(orderBook)
|
||||
if stateObject == nil {
|
||||
return EmptyLendingTrade
|
||||
}
|
||||
stateOrderItem := stateObject.getLendingTrade(self.db, tradeId)
|
||||
stateOrderItem := stateObject.getLendingTrade(ls.db, tradeId)
|
||||
if stateOrderItem == nil || stateOrderItem.empty() {
|
||||
return EmptyLendingTrade
|
||||
}
|
||||
return stateOrderItem.data
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) SubAmountLendingItem(orderBook common.Hash, orderId common.Hash, price *big.Int, amount *big.Int, side string) error {
|
||||
func (ls *LendingStateDB) SubAmountLendingItem(orderBook common.Hash, orderId common.Hash, price *big.Int, amount *big.Int, side string) error {
|
||||
priceHash := common.BigToHash(price)
|
||||
lendingExchange := self.GetOrNewLendingExchangeObject(orderBook)
|
||||
lendingExchange := ls.GetOrNewLendingExchangeObject(orderBook)
|
||||
if lendingExchange == nil {
|
||||
return fmt.Errorf("Order book not found : %s ", orderBook.Hex())
|
||||
return fmt.Errorf("not found order book: %s", orderBook.Hex())
|
||||
}
|
||||
var orderList *itemListState
|
||||
switch side {
|
||||
case Investing:
|
||||
orderList = lendingExchange.getInvestingOrderList(self.db, priceHash)
|
||||
orderList = lendingExchange.getInvestingOrderList(ls.db, priceHash)
|
||||
case Borrowing:
|
||||
orderList = lendingExchange.getBorrowingOrderList(self.db, priceHash)
|
||||
orderList = lendingExchange.getBorrowingOrderList(ls.db, priceHash)
|
||||
default:
|
||||
return fmt.Errorf("Order type not found : %s ", side)
|
||||
return fmt.Errorf("not found order type: %s", side)
|
||||
}
|
||||
if orderList == nil || orderList.empty() {
|
||||
return fmt.Errorf("Order list empty order book : %s , order id : %s , key : %s ", orderBook, orderId.Hex(), priceHash.Hex())
|
||||
return fmt.Errorf("empty orderList: order book : %s , order id : %s , key : %s", orderBook, orderId.Hex(), priceHash.Hex())
|
||||
}
|
||||
lendingItem := lendingExchange.getLendingItem(self.db, orderId)
|
||||
lendingItem := lendingExchange.getLendingItem(ls.db, orderId)
|
||||
if lendingItem == nil || lendingItem.empty() {
|
||||
return fmt.Errorf("Order item empty order book : %s , order id : %s , key : %s ", orderBook, orderId.Hex(), priceHash.Hex())
|
||||
return fmt.Errorf("empty order item: order book : %s , order id : %s , key : %s", orderBook, orderId.Hex(), priceHash.Hex())
|
||||
}
|
||||
currentAmount := new(big.Int).SetBytes(orderList.GetOrderAmount(self.db, orderId).Bytes()[:])
|
||||
currentAmount := new(big.Int).SetBytes(orderList.GetOrderAmount(ls.db, orderId).Bytes()[:])
|
||||
if currentAmount.Cmp(amount) < 0 {
|
||||
return fmt.Errorf("Order amount not enough : %s , have : %d , want : %d ", orderId.Hex(), currentAmount, amount)
|
||||
return fmt.Errorf("not enough order amount %s: have : %d , want : %d", orderId.Hex(), currentAmount, amount)
|
||||
}
|
||||
self.journal = append(self.journal, subAmountOrder{
|
||||
ls.journal = append(ls.journal, subAmountOrder{
|
||||
orderBook: orderBook,
|
||||
orderId: orderId,
|
||||
order: self.GetLendingOrder(orderBook, orderId),
|
||||
order: ls.GetLendingOrder(orderBook, orderId),
|
||||
amount: amount,
|
||||
})
|
||||
newAmount := new(big.Int).Sub(currentAmount, amount)
|
||||
|
|
@ -274,77 +276,77 @@ func (self *LendingStateDB) SubAmountLendingItem(orderBook common.Hash, orderId
|
|||
log.Debug("SubAmountOrderItem", "tradeId", orderId.Hex(), "side", side, "key", price.Uint64(), "amount", amount.Uint64(), "new amount", newAmount.Uint64())
|
||||
orderList.subVolume(amount)
|
||||
if newAmount.Sign() == 0 {
|
||||
orderList.removeOrderItem(self.db, orderId)
|
||||
orderList.removeOrderItem(ls.db, orderId)
|
||||
} else {
|
||||
orderList.setOrderItem(orderId, common.BigToHash(newAmount))
|
||||
}
|
||||
if orderList.empty() {
|
||||
switch side {
|
||||
case Investing:
|
||||
lendingExchange.removeInvestingOrderList(self.db, orderList)
|
||||
lendingExchange.removeInvestingOrderList(ls.db, orderList)
|
||||
case Borrowing:
|
||||
lendingExchange.removeBorrowingOrderList(self.db, orderList)
|
||||
lendingExchange.removeBorrowingOrderList(ls.db, orderList)
|
||||
default:
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) CancelLendingOrder(orderBook common.Hash, order *LendingItem) error {
|
||||
func (ls *LendingStateDB) CancelLendingOrder(orderBook common.Hash, order *LendingItem) error {
|
||||
interestHash := common.BigToHash(order.Interest)
|
||||
orderIdHash := common.BigToHash(new(big.Int).SetUint64(order.LendingId))
|
||||
stateObject := self.GetOrNewLendingExchangeObject(orderBook)
|
||||
stateObject := ls.GetOrNewLendingExchangeObject(orderBook)
|
||||
if stateObject == nil {
|
||||
return fmt.Errorf("Order book not found : %s ", orderBook.Hex())
|
||||
return fmt.Errorf("not found order book: %s", orderBook.Hex())
|
||||
}
|
||||
lendingItem := stateObject.getLendingItem(self.db, orderIdHash)
|
||||
lendingItem := stateObject.getLendingItem(ls.db, orderIdHash)
|
||||
var orderList *itemListState
|
||||
switch lendingItem.data.Side {
|
||||
case Investing:
|
||||
orderList = stateObject.getInvestingOrderList(self.db, interestHash)
|
||||
orderList = stateObject.getInvestingOrderList(ls.db, interestHash)
|
||||
case Borrowing:
|
||||
orderList = stateObject.getBorrowingOrderList(self.db, interestHash)
|
||||
orderList = stateObject.getBorrowingOrderList(ls.db, interestHash)
|
||||
default:
|
||||
return fmt.Errorf("Order side not found : %s ", order.Side)
|
||||
return fmt.Errorf("not found order side: %s", order.Side)
|
||||
}
|
||||
if orderList == nil || orderList.empty() {
|
||||
return fmt.Errorf("Order list empty order book : %s , order id : %s , key : %s ", orderBook, orderIdHash.Hex(), interestHash.Hex())
|
||||
return fmt.Errorf("empty OrderList: order book : %s , order id : %s , key : %s", orderBook, orderIdHash.Hex(), interestHash.Hex())
|
||||
}
|
||||
if lendingItem == nil || lendingItem.empty() {
|
||||
return fmt.Errorf("Order item empty order book : %s , order id : %s , key : %s ", orderBook, orderIdHash.Hex(), interestHash.Hex())
|
||||
return fmt.Errorf("empty order item: order book : %s , order id : %s , key : %s", orderBook, orderIdHash.Hex(), interestHash.Hex())
|
||||
}
|
||||
if lendingItem.data.UserAddress != order.UserAddress {
|
||||
return fmt.Errorf("Error Order User Address mismatch when cancel order book : %s , order id : %s , got : %s , expect : %s ", orderBook, orderIdHash.Hex(), lendingItem.data.UserAddress.Hex(), order.UserAddress.Hex())
|
||||
return fmt.Errorf("error Order UserAddress mismatch when cancel order book: %s , order id : %s , got : %s , expect : %s", orderBook, orderIdHash.Hex(), lendingItem.data.UserAddress.Hex(), order.UserAddress.Hex())
|
||||
}
|
||||
self.journal = append(self.journal, cancelOrder{
|
||||
ls.journal = append(ls.journal, cancelOrder{
|
||||
orderBook: orderBook,
|
||||
orderId: orderIdHash,
|
||||
order: self.GetLendingOrder(orderBook, orderIdHash),
|
||||
order: ls.GetLendingOrder(orderBook, orderIdHash),
|
||||
})
|
||||
lendingItem.setVolume(big.NewInt(0))
|
||||
currentAmount := new(big.Int).SetBytes(orderList.GetOrderAmount(self.db, orderIdHash).Bytes()[:])
|
||||
currentAmount := new(big.Int).SetBytes(orderList.GetOrderAmount(ls.db, orderIdHash).Bytes()[:])
|
||||
orderList.subVolume(currentAmount)
|
||||
orderList.removeOrderItem(self.db, orderIdHash)
|
||||
orderList.removeOrderItem(ls.db, orderIdHash)
|
||||
if orderList.empty() {
|
||||
switch order.Side {
|
||||
case Investing:
|
||||
stateObject.removeInvestingOrderList(self.db, orderList)
|
||||
stateObject.removeInvestingOrderList(ls.db, orderList)
|
||||
case Borrowing:
|
||||
stateObject.removeBorrowingOrderList(self.db, orderList)
|
||||
stateObject.removeBorrowingOrderList(ls.db, orderList)
|
||||
default:
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) GetBestInvestingRate(orderBook common.Hash) (*big.Int, *big.Int) {
|
||||
stateObject := self.getLendingExchange(orderBook)
|
||||
func (ls *LendingStateDB) GetBestInvestingRate(orderBook common.Hash) (*big.Int, *big.Int) {
|
||||
stateObject := ls.getLendingExchange(orderBook)
|
||||
if stateObject != nil {
|
||||
investingHash := stateObject.getBestInvestingInterest(self.db)
|
||||
investingHash := stateObject.getBestInvestingInterest(ls.db)
|
||||
if common.EmptyHash(investingHash) {
|
||||
return Zero, Zero
|
||||
}
|
||||
orderList := stateObject.getInvestingOrderList(self.db, investingHash)
|
||||
orderList := stateObject.getInvestingOrderList(ls.db, investingHash)
|
||||
if orderList == nil {
|
||||
log.Error("order list investing not found", "key", investingHash.Hex())
|
||||
return Zero, Zero
|
||||
|
|
@ -354,14 +356,14 @@ func (self *LendingStateDB) GetBestInvestingRate(orderBook common.Hash) (*big.In
|
|||
return Zero, Zero
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) GetBestBorrowRate(orderBook common.Hash) (*big.Int, *big.Int) {
|
||||
stateObject := self.getLendingExchange(orderBook)
|
||||
func (ls *LendingStateDB) GetBestBorrowRate(orderBook common.Hash) (*big.Int, *big.Int) {
|
||||
stateObject := ls.getLendingExchange(orderBook)
|
||||
if stateObject != nil {
|
||||
priceHash := stateObject.getBestBorrowingInterest(self.db)
|
||||
priceHash := stateObject.getBestBorrowingInterest(ls.db)
|
||||
if common.EmptyHash(priceHash) {
|
||||
return Zero, Zero
|
||||
}
|
||||
orderList := stateObject.getBorrowingOrderList(self.db, priceHash)
|
||||
orderList := stateObject.getBorrowingOrderList(ls.db, priceHash)
|
||||
if orderList == nil {
|
||||
log.Error("order list ask not found", "key", priceHash.Hex())
|
||||
return Zero, Zero
|
||||
|
|
@ -371,52 +373,52 @@ func (self *LendingStateDB) GetBestBorrowRate(orderBook common.Hash) (*big.Int,
|
|||
return Zero, Zero
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) GetBestLendingIdAndAmount(orderBook common.Hash, price *big.Int, side string) (common.Hash, *big.Int, error) {
|
||||
stateObject := self.GetOrNewLendingExchangeObject(orderBook)
|
||||
func (ls *LendingStateDB) GetBestLendingIdAndAmount(orderBook common.Hash, price *big.Int, side string) (common.Hash, *big.Int, error) {
|
||||
stateObject := ls.GetOrNewLendingExchangeObject(orderBook)
|
||||
if stateObject != nil {
|
||||
var stateOrderList *itemListState
|
||||
switch side {
|
||||
case Investing:
|
||||
stateOrderList = stateObject.getInvestingOrderList(self.db, common.BigToHash(price))
|
||||
stateOrderList = stateObject.getInvestingOrderList(ls.db, common.BigToHash(price))
|
||||
case Borrowing:
|
||||
stateOrderList = stateObject.getBorrowingOrderList(self.db, common.BigToHash(price))
|
||||
stateOrderList = stateObject.getBorrowingOrderList(ls.db, common.BigToHash(price))
|
||||
default:
|
||||
return EmptyHash, Zero, fmt.Errorf("not found side :%s ", side)
|
||||
return EmptyHash, Zero, fmt.Errorf("not found side: %s", side)
|
||||
}
|
||||
if stateOrderList != nil {
|
||||
key, _, err := stateOrderList.getTrie(self.db).TryGetBestLeftKeyAndValue()
|
||||
key, _, err := stateOrderList.getTrie(ls.db).TryGetBestLeftKeyAndValue()
|
||||
if err != nil {
|
||||
return EmptyHash, Zero, err
|
||||
}
|
||||
orderId := common.BytesToHash(key)
|
||||
amount := stateOrderList.GetOrderAmount(self.db, orderId)
|
||||
amount := stateOrderList.GetOrderAmount(ls.db, orderId)
|
||||
return orderId, new(big.Int).SetBytes(amount.Bytes()), nil
|
||||
}
|
||||
return EmptyHash, Zero, fmt.Errorf("not found order list with orderBook : %s , key : %d , side :%s ", orderBook.Hex(), price, side)
|
||||
return EmptyHash, Zero, fmt.Errorf("not found order list with orderBook: %s , key : %d , side : %s", orderBook.Hex(), price, side)
|
||||
}
|
||||
return EmptyHash, Zero, fmt.Errorf("not found orderBook : %s ", orderBook.Hex())
|
||||
return EmptyHash, Zero, fmt.Errorf("not found orderBook: %s", orderBook.Hex())
|
||||
}
|
||||
|
||||
// updateLendingExchange writes the given object to the trie.
|
||||
func (self *LendingStateDB) updateLendingExchange(stateObject *lendingExchangeState) {
|
||||
func (ls *LendingStateDB) updateLendingExchange(stateObject *lendingExchangeState) {
|
||||
addr := stateObject.Hash()
|
||||
data, err := rlp.EncodeToBytes(stateObject)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err))
|
||||
}
|
||||
self.setError(self.trie.TryUpdate(addr[:], data))
|
||||
ls.setError(ls.trie.TryUpdate(addr[:], data))
|
||||
}
|
||||
|
||||
// Retrieve a state object given my the address. Returns nil if not found.
|
||||
func (self *LendingStateDB) getLendingExchange(addr common.Hash) (stateObject *lendingExchangeState) {
|
||||
func (ls *LendingStateDB) getLendingExchange(addr common.Hash) (stateObject *lendingExchangeState) {
|
||||
// Prefer 'live' objects.
|
||||
if obj := self.lendingExchangeStates[addr]; obj != nil {
|
||||
if obj := ls.lendingExchangeStates[addr]; obj != nil {
|
||||
return obj
|
||||
}
|
||||
// Load the object from the database.
|
||||
enc, err := self.trie.TryGet(addr[:])
|
||||
enc, err := ls.trie.TryGet(addr[:])
|
||||
if len(enc) == 0 {
|
||||
self.setError(err)
|
||||
ls.setError(err)
|
||||
return nil
|
||||
}
|
||||
var data lendingObject
|
||||
|
|
@ -425,176 +427,176 @@ func (self *LendingStateDB) getLendingExchange(addr common.Hash) (stateObject *l
|
|||
return nil
|
||||
}
|
||||
// Insert into the live set.
|
||||
obj := newStateExchanges(self, addr, data, self.MarkLendingExchangeObjectDirty)
|
||||
self.lendingExchangeStates[addr] = obj
|
||||
obj := newStateExchanges(ls, addr, data, ls.MarkLendingExchangeObjectDirty)
|
||||
ls.lendingExchangeStates[addr] = obj
|
||||
return obj
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) setLendingExchangeObject(object *lendingExchangeState) {
|
||||
self.lendingExchangeStates[object.Hash()] = object
|
||||
self.lendingExchangeStatesDirty[object.Hash()] = struct{}{}
|
||||
func (ls *LendingStateDB) setLendingExchangeObject(object *lendingExchangeState) {
|
||||
ls.lendingExchangeStates[object.Hash()] = object
|
||||
ls.lendingExchangeStatesDirty[object.Hash()] = struct{}{}
|
||||
}
|
||||
|
||||
// Retrieve a state object or create a new state object if nil.
|
||||
func (self *LendingStateDB) GetOrNewLendingExchangeObject(addr common.Hash) *lendingExchangeState {
|
||||
stateExchangeObject := self.getLendingExchange(addr)
|
||||
func (ls *LendingStateDB) GetOrNewLendingExchangeObject(addr common.Hash) *lendingExchangeState {
|
||||
stateExchangeObject := ls.getLendingExchange(addr)
|
||||
if stateExchangeObject == nil {
|
||||
stateExchangeObject = self.createLendingExchangeObject(addr)
|
||||
stateExchangeObject = ls.createLendingExchangeObject(addr)
|
||||
}
|
||||
return stateExchangeObject
|
||||
}
|
||||
|
||||
// MarkStateLendObjectDirty adds the specified object to the dirty map to avoid costly
|
||||
// state object cache iteration to find a handful of modified ones.
|
||||
func (self *LendingStateDB) MarkLendingExchangeObjectDirty(addr common.Hash) {
|
||||
self.lendingExchangeStatesDirty[addr] = struct{}{}
|
||||
func (ls *LendingStateDB) MarkLendingExchangeObjectDirty(addr common.Hash) {
|
||||
ls.lendingExchangeStatesDirty[addr] = struct{}{}
|
||||
}
|
||||
|
||||
// createStateOrderListObject creates a new state object. If there is an existing tradeId with
|
||||
// the given address, it is overwritten and returned as the second return value.
|
||||
func (self *LendingStateDB) createLendingExchangeObject(hash common.Hash) (newobj *lendingExchangeState) {
|
||||
newobj = newStateExchanges(self, hash, lendingObject{}, self.MarkLendingExchangeObjectDirty)
|
||||
func (ls *LendingStateDB) createLendingExchangeObject(hash common.Hash) (newobj *lendingExchangeState) {
|
||||
newobj = newStateExchanges(ls, hash, lendingObject{}, ls.MarkLendingExchangeObjectDirty)
|
||||
newobj.setNonce(0) // sets the object to dirty
|
||||
self.setLendingExchangeObject(newobj)
|
||||
ls.setLendingExchangeObject(newobj)
|
||||
return newobj
|
||||
}
|
||||
|
||||
// Copy creates a deep, independent copy of the state.
|
||||
// Snapshots of the copied state cannot be applied to the copy.
|
||||
func (self *LendingStateDB) Copy() *LendingStateDB {
|
||||
self.lock.Lock()
|
||||
defer self.lock.Unlock()
|
||||
func (ls *LendingStateDB) Copy() *LendingStateDB {
|
||||
ls.lock.Lock()
|
||||
defer ls.lock.Unlock()
|
||||
|
||||
// Copy all the basic fields, initialize the memory ones
|
||||
state := &LendingStateDB{
|
||||
db: self.db,
|
||||
trie: self.db.CopyTrie(self.trie),
|
||||
lendingExchangeStates: make(map[common.Hash]*lendingExchangeState, len(self.lendingExchangeStatesDirty)),
|
||||
lendingExchangeStatesDirty: make(map[common.Hash]struct{}, len(self.lendingExchangeStatesDirty)),
|
||||
db: ls.db,
|
||||
trie: ls.db.CopyTrie(ls.trie),
|
||||
lendingExchangeStates: make(map[common.Hash]*lendingExchangeState, len(ls.lendingExchangeStatesDirty)),
|
||||
lendingExchangeStatesDirty: make(map[common.Hash]struct{}, len(ls.lendingExchangeStatesDirty)),
|
||||
}
|
||||
// Copy the dirty states, logs, and preimages
|
||||
for addr := range self.lendingExchangeStatesDirty {
|
||||
for addr := range ls.lendingExchangeStatesDirty {
|
||||
state.lendingExchangeStatesDirty[addr] = struct{}{}
|
||||
}
|
||||
for addr, exchangeObject := range self.lendingExchangeStates {
|
||||
for addr, exchangeObject := range ls.lendingExchangeStates {
|
||||
state.lendingExchangeStates[addr] = exchangeObject.deepCopy(state, state.MarkLendingExchangeObjectDirty)
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
func (s *LendingStateDB) clearJournalAndRefund() {
|
||||
s.journal = nil
|
||||
s.validRevisions = s.validRevisions[:0]
|
||||
func (ls *LendingStateDB) clearJournalAndRefund() {
|
||||
ls.journal = nil
|
||||
ls.validRevisions = ls.validRevisions[:0]
|
||||
}
|
||||
|
||||
// Snapshot returns an identifier for the current revision of the state.
|
||||
func (self *LendingStateDB) Snapshot() int {
|
||||
id := self.nextRevisionId
|
||||
self.nextRevisionId++
|
||||
self.validRevisions = append(self.validRevisions, revision{id, len(self.journal)})
|
||||
func (ls *LendingStateDB) Snapshot() int {
|
||||
id := ls.nextRevisionId
|
||||
ls.nextRevisionId++
|
||||
ls.validRevisions = append(ls.validRevisions, revision{id, len(ls.journal)})
|
||||
return id
|
||||
}
|
||||
|
||||
// RevertToSnapshot reverts all state changes made since the given revision.
|
||||
func (self *LendingStateDB) RevertToSnapshot(revid int) {
|
||||
func (ls *LendingStateDB) RevertToSnapshot(revid int) {
|
||||
// Find the snapshot in the stack of valid snapshots.
|
||||
idx := sort.Search(len(self.validRevisions), func(i int) bool {
|
||||
return self.validRevisions[i].id >= revid
|
||||
idx := sort.Search(len(ls.validRevisions), func(i int) bool {
|
||||
return ls.validRevisions[i].id >= revid
|
||||
})
|
||||
if idx == len(self.validRevisions) || self.validRevisions[idx].id != revid {
|
||||
if idx == len(ls.validRevisions) || ls.validRevisions[idx].id != revid {
|
||||
panic(fmt.Errorf("revision id %v cannot be reverted", revid))
|
||||
}
|
||||
snapshot := self.validRevisions[idx].journalIndex
|
||||
snapshot := ls.validRevisions[idx].journalIndex
|
||||
|
||||
// Replay the journal to undo changes.
|
||||
for i := len(self.journal) - 1; i >= snapshot; i-- {
|
||||
self.journal[i].undo(self)
|
||||
for i := len(ls.journal) - 1; i >= snapshot; i-- {
|
||||
ls.journal[i].undo(ls)
|
||||
}
|
||||
self.journal = self.journal[:snapshot]
|
||||
ls.journal = ls.journal[:snapshot]
|
||||
|
||||
// Remove invalidated snapshots from the stack.
|
||||
self.validRevisions = self.validRevisions[:idx]
|
||||
ls.validRevisions = ls.validRevisions[:idx]
|
||||
}
|
||||
|
||||
// Finalise finalises the state by removing the self destructed objects
|
||||
// and clears the journal as well as the refunds.
|
||||
func (s *LendingStateDB) Finalise() {
|
||||
func (ls *LendingStateDB) Finalise() {
|
||||
// Commit objects to the trie.
|
||||
for addr, stateObject := range s.lendingExchangeStates {
|
||||
if _, isDirty := s.lendingExchangeStatesDirty[addr]; isDirty {
|
||||
for addr, stateObject := range ls.lendingExchangeStates {
|
||||
if _, isDirty := ls.lendingExchangeStatesDirty[addr]; isDirty {
|
||||
// Write any storage changes in the state object to its storage trie.
|
||||
err := stateObject.updateInvestingRoot(s.db)
|
||||
err := stateObject.updateInvestingRoot(ls.db)
|
||||
if err != nil {
|
||||
log.Warn("Finalise updateInvestingRoot", "err", err, "addr", addr, "stateObject", *stateObject)
|
||||
}
|
||||
stateObject.updateBorrowingRoot(s.db)
|
||||
stateObject.updateOrderRoot(s.db)
|
||||
stateObject.updateLendingTradeRoot(s.db)
|
||||
stateObject.updateLiquidationTimeRoot(s.db)
|
||||
stateObject.updateBorrowingRoot(ls.db)
|
||||
stateObject.updateOrderRoot(ls.db)
|
||||
stateObject.updateLendingTradeRoot(ls.db)
|
||||
stateObject.updateLiquidationTimeRoot(ls.db)
|
||||
// Update the object in the main tradeId trie.
|
||||
s.updateLendingExchange(stateObject)
|
||||
ls.updateLendingExchange(stateObject)
|
||||
//delete(s.investingStatesDirty, addr)
|
||||
}
|
||||
}
|
||||
s.clearJournalAndRefund()
|
||||
ls.clearJournalAndRefund()
|
||||
}
|
||||
|
||||
// IntermediateRoot computes the current root orderBook of the state trie.
|
||||
// It is called in between transactions to get the root orderBook that
|
||||
// goes into transaction receipts.
|
||||
func (s *LendingStateDB) IntermediateRoot() common.Hash {
|
||||
s.Finalise()
|
||||
return s.trie.Hash()
|
||||
func (ls *LendingStateDB) IntermediateRoot() common.Hash {
|
||||
ls.Finalise()
|
||||
return ls.trie.Hash()
|
||||
}
|
||||
|
||||
// Commit writes the state to the underlying in-memory trie database.
|
||||
func (s *LendingStateDB) Commit() (root common.Hash, err error) {
|
||||
defer s.clearJournalAndRefund()
|
||||
func (ls *LendingStateDB) Commit() (root common.Hash, err error) {
|
||||
defer ls.clearJournalAndRefund()
|
||||
// Commit objects to the trie.
|
||||
for addr, stateObject := range s.lendingExchangeStates {
|
||||
if _, isDirty := s.lendingExchangeStatesDirty[addr]; isDirty {
|
||||
for addr, stateObject := range ls.lendingExchangeStates {
|
||||
if _, isDirty := ls.lendingExchangeStatesDirty[addr]; isDirty {
|
||||
// Write any storage changes in the state object to its storage trie.
|
||||
if err := stateObject.CommitInvestingTrie(s.db); err != nil {
|
||||
if err := stateObject.CommitInvestingTrie(ls.db); err != nil {
|
||||
return EmptyHash, err
|
||||
}
|
||||
if err := stateObject.CommitBorrowingTrie(s.db); err != nil {
|
||||
if err := stateObject.CommitBorrowingTrie(ls.db); err != nil {
|
||||
return EmptyHash, err
|
||||
}
|
||||
if err := stateObject.CommitLendingItemTrie(s.db); err != nil {
|
||||
if err := stateObject.CommitLendingItemTrie(ls.db); err != nil {
|
||||
return EmptyHash, err
|
||||
}
|
||||
if err := stateObject.CommitLendingTradeTrie(s.db); err != nil {
|
||||
if err := stateObject.CommitLendingTradeTrie(ls.db); err != nil {
|
||||
return EmptyHash, err
|
||||
}
|
||||
if err := stateObject.CommitLiquidationTimeTrie(s.db); err != nil {
|
||||
if err := stateObject.CommitLiquidationTimeTrie(ls.db); err != nil {
|
||||
return EmptyHash, err
|
||||
}
|
||||
// Update the object in the main tradeId trie.
|
||||
s.updateLendingExchange(stateObject)
|
||||
delete(s.lendingExchangeStatesDirty, addr)
|
||||
ls.updateLendingExchange(stateObject)
|
||||
delete(ls.lendingExchangeStatesDirty, addr)
|
||||
}
|
||||
}
|
||||
// Write trie changes.
|
||||
root, err = s.trie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
root, err = ls.trie.Commit(func(leaf []byte, parent common.Hash) error {
|
||||
var exchange lendingObject
|
||||
if err := rlp.DecodeBytes(leaf, &exchange); err != nil {
|
||||
return nil
|
||||
}
|
||||
if exchange.InvestingRoot != EmptyRoot {
|
||||
s.db.TrieDB().Reference(exchange.InvestingRoot, parent)
|
||||
ls.db.TrieDB().Reference(exchange.InvestingRoot, parent)
|
||||
}
|
||||
if exchange.BorrowingRoot != EmptyRoot {
|
||||
s.db.TrieDB().Reference(exchange.BorrowingRoot, parent)
|
||||
ls.db.TrieDB().Reference(exchange.BorrowingRoot, parent)
|
||||
}
|
||||
if exchange.LendingItemRoot != EmptyRoot {
|
||||
s.db.TrieDB().Reference(exchange.LendingItemRoot, parent)
|
||||
ls.db.TrieDB().Reference(exchange.LendingItemRoot, parent)
|
||||
}
|
||||
if exchange.LendingTradeRoot != EmptyRoot {
|
||||
s.db.TrieDB().Reference(exchange.LendingTradeRoot, parent)
|
||||
ls.db.TrieDB().Reference(exchange.LendingTradeRoot, parent)
|
||||
}
|
||||
if exchange.LiquidationTimeRoot != EmptyRoot {
|
||||
s.db.TrieDB().Reference(exchange.LiquidationTimeRoot, parent)
|
||||
ls.db.TrieDB().Reference(exchange.LiquidationTimeRoot, parent)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
|
@ -602,38 +604,38 @@ func (s *LendingStateDB) Commit() (root common.Hash, err error) {
|
|||
return root, err
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) InsertLiquidationTime(lendingBook common.Hash, time *big.Int, tradeId uint64) {
|
||||
func (ls *LendingStateDB) InsertLiquidationTime(lendingBook common.Hash, time *big.Int, tradeId uint64) {
|
||||
timeHash := common.BigToHash(time)
|
||||
lendingExchangeState := self.getLendingExchange(lendingBook)
|
||||
lendingExchangeState := ls.getLendingExchange(lendingBook)
|
||||
if lendingExchangeState == nil {
|
||||
lendingExchangeState = self.createLendingExchangeObject(lendingBook)
|
||||
lendingExchangeState = ls.createLendingExchangeObject(lendingBook)
|
||||
}
|
||||
liquidationTime := lendingExchangeState.getLiquidationTimeOrderList(self.db, timeHash)
|
||||
liquidationTime := lendingExchangeState.getLiquidationTimeOrderList(ls.db, timeHash)
|
||||
if liquidationTime == nil {
|
||||
liquidationTime = lendingExchangeState.createLiquidationTime(self.db, timeHash)
|
||||
liquidationTime = lendingExchangeState.createLiquidationTime(ls.db, timeHash)
|
||||
}
|
||||
liquidationTime.insertTradeId(self.db, common.Uint64ToHash(tradeId))
|
||||
liquidationTime.insertTradeId(ls.db, common.Uint64ToHash(tradeId))
|
||||
liquidationTime.AddVolume(One)
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) RemoveLiquidationTime(lendingBook common.Hash, tradeId uint64, time uint64) error {
|
||||
func (ls *LendingStateDB) RemoveLiquidationTime(lendingBook common.Hash, tradeId uint64, time uint64) error {
|
||||
timeHash := common.Uint64ToHash(time)
|
||||
tradeIdHash := common.Uint64ToHash(tradeId)
|
||||
lendingExchangeState := self.getLendingExchange(lendingBook)
|
||||
lendingExchangeState := ls.getLendingExchange(lendingBook)
|
||||
if lendingExchangeState == nil {
|
||||
return fmt.Errorf("lending book not found : %s ", lendingBook.Hex())
|
||||
return fmt.Errorf("lending book not found: %s", lendingBook.Hex())
|
||||
}
|
||||
liquidationTime := lendingExchangeState.getLiquidationTimeOrderList(self.db, timeHash)
|
||||
liquidationTime := lendingExchangeState.getLiquidationTimeOrderList(ls.db, timeHash)
|
||||
if liquidationTime == nil {
|
||||
return fmt.Errorf("liquidation time not found : %s , %d ", lendingBook.Hex(), time)
|
||||
return fmt.Errorf("not found liquidation time: %s , %d", lendingBook.Hex(), time)
|
||||
}
|
||||
if !liquidationTime.Exist(self.db, tradeIdHash) {
|
||||
return fmt.Errorf("tradeId not exist : %s , %d , %d ", lendingBook.Hex(), time, tradeId)
|
||||
if !liquidationTime.Exist(ls.db, tradeIdHash) {
|
||||
return fmt.Errorf("not exist tradeId: %s, %d, %d", lendingBook.Hex(), time, tradeId)
|
||||
}
|
||||
liquidationTime.removeTradeId(self.db, tradeIdHash)
|
||||
liquidationTime.removeTradeId(ls.db, tradeIdHash)
|
||||
liquidationTime.subVolume(One)
|
||||
if liquidationTime.Volume().Sign() == 0 {
|
||||
err := lendingExchangeState.getLiquidationTimeTrie(self.db).TryDelete(timeHash[:])
|
||||
err := lendingExchangeState.getLiquidationTimeTrie(ls.db).TryDelete(timeHash[:])
|
||||
if err != nil {
|
||||
log.Warn("RemoveLiquidationTime getLiquidationTimeTrie.TryDelete", "err", err, "timeHash[:]", timeHash[:])
|
||||
}
|
||||
|
|
@ -641,33 +643,33 @@ func (self *LendingStateDB) RemoveLiquidationTime(lendingBook common.Hash, trade
|
|||
return nil
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) GetLowestLiquidationTime(lendingBook common.Hash, time *big.Int) (*big.Int, []common.Hash) {
|
||||
func (ls *LendingStateDB) GetLowestLiquidationTime(lendingBook common.Hash, time *big.Int) (*big.Int, []common.Hash) {
|
||||
liquidationData := []common.Hash{}
|
||||
lendingExchangeState := self.getLendingExchange(lendingBook)
|
||||
lendingExchangeState := ls.getLendingExchange(lendingBook)
|
||||
if lendingExchangeState == nil {
|
||||
return common.Big0, liquidationData
|
||||
}
|
||||
lowestPriceHash, liquidationState := lendingExchangeState.getLowestLiquidationTime(self.db)
|
||||
lowestPriceHash, liquidationState := lendingExchangeState.getLowestLiquidationTime(ls.db)
|
||||
lowestTime := new(big.Int).SetBytes(lowestPriceHash[:])
|
||||
if liquidationState != nil && lowestTime.Sign() > 0 && lowestTime.Cmp(time) <= 0 {
|
||||
liquidationData = liquidationState.getAllTradeIds(self.db)
|
||||
liquidationData = liquidationState.getAllTradeIds(ls.db)
|
||||
}
|
||||
return lowestTime, liquidationData
|
||||
}
|
||||
|
||||
func (self *LendingStateDB) CancelLendingTrade(orderBook common.Hash, tradeId uint64) error {
|
||||
func (ls *LendingStateDB) CancelLendingTrade(orderBook common.Hash, tradeId uint64) error {
|
||||
tradeIdHash := common.Uint64ToHash(tradeId)
|
||||
stateObject := self.GetOrNewLendingExchangeObject(orderBook)
|
||||
stateObject := ls.GetOrNewLendingExchangeObject(orderBook)
|
||||
if stateObject == nil {
|
||||
return fmt.Errorf("Order book not found : %s ", orderBook.Hex())
|
||||
return fmt.Errorf("not found order book: %s", orderBook.Hex())
|
||||
}
|
||||
lendingTrade := stateObject.getLendingTrade(self.db, tradeIdHash)
|
||||
lendingTrade := stateObject.getLendingTrade(ls.db, tradeIdHash)
|
||||
if lendingTrade == nil || lendingTrade.empty() {
|
||||
return fmt.Errorf("lending trade empty order book : %s , trade id : %s , trade id hash : %s ", orderBook, tradeIdHash.Hex(), tradeIdHash.Hex())
|
||||
return fmt.Errorf("lending trade empty order book: %s , trade id : %s , trade id hash : %s", orderBook, tradeIdHash.Hex(), tradeIdHash.Hex())
|
||||
}
|
||||
self.journal = append(self.journal, cancelTrading{
|
||||
ls.journal = append(ls.journal, cancelTrading{
|
||||
orderBook: orderBook,
|
||||
order: self.GetLendingTrade(orderBook, tradeIdHash),
|
||||
order: ls.GetLendingTrade(orderBook, tradeIdHash),
|
||||
})
|
||||
lendingTrade.SetAmount(Zero)
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -18,10 +18,11 @@ package lendingstate
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||
)
|
||||
|
||||
func TestEchangeStates(t *testing.T) {
|
||||
|
|
@ -225,9 +226,7 @@ func TestDumpStates(t *testing.T) {
|
|||
orderBook := common.StringToHash("BTC/XDC")
|
||||
numberOrder := 20
|
||||
orderItems := []LendingItem{}
|
||||
relayers := []common.Hash{}
|
||||
for i := 0; i < numberOrder; i++ {
|
||||
relayers = append(relayers, common.BigToHash(big.NewInt(int64(i))))
|
||||
id := new(big.Int).SetUint64(uint64(i) + 1)
|
||||
orderItems = append(orderItems, LendingItem{LendingId: id.Uint64(), Quantity: big.NewInt(int64(2*i + 1)), Interest: big.NewInt(1), Side: Investing, Signature: &Signature{V: 1, R: common.HexToHash("111111"), S: common.HexToHash("222222222222")}})
|
||||
orderItems = append(orderItems, LendingItem{LendingId: id.Uint64(), Quantity: big.NewInt(int64(2*i + 1)), Interest: big.NewInt(1), Side: Borrowing, Signature: &Signature{V: 1, R: common.HexToHash("3333333333"), S: common.HexToHash("22222222222222222")}})
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@ package lendingstate
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto/sha3"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -183,7 +183,7 @@ func (t *LendingTrade) SetBSON(raw bson.Raw) error {
|
|||
}
|
||||
|
||||
func (t *LendingTrade) ComputeHash() common.Hash {
|
||||
sha := sha3.NewKeccak256()
|
||||
sha := sha3.NewLegacyKeccak256()
|
||||
sha.Write(t.InvestingOrderHash.Bytes())
|
||||
sha.Write(t.BorrowingOrderHash.Bytes())
|
||||
return common.BytesToHash(sha.Sum(nil))
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ func (l *Lending) ApplyOrder(header *types.Header, coinbase common.Address, chai
|
|||
|
||||
switch order.Type {
|
||||
case lendingstate.TopUp:
|
||||
err, reject, newLendingTrade := l.ProcessTopUp(lendingStateDB, statedb, tradingStateDb, order)
|
||||
reject, newLendingTrade, err := l.ProcessTopUp(lendingStateDB, statedb, tradingStateDb, order)
|
||||
if err != nil || reject {
|
||||
rejects = append(rejects, order)
|
||||
}
|
||||
|
|
@ -438,7 +438,7 @@ func (l *Lending) getLendQuantity(
|
|||
}
|
||||
LendingTokenDecimal, err := l.XDCx.GetTokenDecimal(chain, statedb, makerOrder.LendingToken)
|
||||
if err != nil || LendingTokenDecimal.Sign() == 0 {
|
||||
return lendingstate.Zero, lendingstate.Zero, false, nil, fmt.Errorf("Fail to get tokenDecimal. Token: %v . Err: %v", makerOrder.LendingToken.String(), err)
|
||||
return lendingstate.Zero, lendingstate.Zero, false, nil, fmt.Errorf("fail to get tokenDecimal: Token: %v . Err: %v", makerOrder.LendingToken.String(), err)
|
||||
}
|
||||
collateralToken := makerOrder.CollateralToken
|
||||
if takerOrder.Side == lendingstate.Borrowing {
|
||||
|
|
@ -446,7 +446,7 @@ func (l *Lending) getLendQuantity(
|
|||
}
|
||||
collateralTokenDecimal, err := l.XDCx.GetTokenDecimal(chain, statedb, collateralToken)
|
||||
if err != nil || collateralTokenDecimal.Sign() == 0 {
|
||||
return lendingstate.Zero, lendingstate.Zero, false, nil, fmt.Errorf("fail to get tokenDecimal. Token: %v . Err: %v", collateralToken.String(), err)
|
||||
return lendingstate.Zero, lendingstate.Zero, false, nil, fmt.Errorf("fail to get tokenDecimal: Token: %v . Err: %v", collateralToken.String(), err)
|
||||
}
|
||||
if takerOrder.Relayer == makerOrder.Relayer {
|
||||
if err := lendingstate.CheckRelayerFee(takerOrder.Relayer, new(big.Int).Mul(common.RelayerLendingFee, big.NewInt(2)), statedb); err != nil {
|
||||
|
|
@ -582,7 +582,7 @@ func DoSettleBalance(coinbase common.Address, takerOrder, makerOrder *lendingsta
|
|||
matchingFee = new(big.Int).Add(matchingFee, common.RelayerLendingFee)
|
||||
|
||||
if common.EmptyHash(takerExOwner.Hash()) || common.EmptyHash(makerExOwner.Hash()) {
|
||||
return fmt.Errorf("Echange owner empty , Taker: %v , maker : %v ", takerExOwner, makerExOwner)
|
||||
return fmt.Errorf("empty echange owner: taker: %v , maker : %v", takerExOwner, makerExOwner)
|
||||
}
|
||||
mapBalances := map[common.Address]map[common.Address]*big.Int{}
|
||||
//Checking balance
|
||||
|
|
@ -727,9 +727,10 @@ func (l *Lending) ProcessCancelOrder(header *types.Header, lendingStateDB *lendi
|
|||
}
|
||||
}
|
||||
feeRate := lendingstate.GetFee(statedb, originOrder.Relayer)
|
||||
tokenCancelFee, tokenPriceInXDC := common.Big0, common.Big0
|
||||
var tokenCancelFee, tokenPriceInXDC *big.Int
|
||||
if !chain.Config().IsTIPXDCXCancellationFee(header.Number) {
|
||||
tokenCancelFee = getCancelFeeV1(collateralTokenDecimal, collateralPrice, feeRate, &originOrder)
|
||||
tokenPriceInXDC = common.Big0
|
||||
} else {
|
||||
tokenCancelFee, tokenPriceInXDC = l.getCancelFee(chain, statedb, tradingStateDb, &originOrder, feeRate)
|
||||
}
|
||||
|
|
@ -783,22 +784,22 @@ func (l *Lending) ProcessCancelOrder(header *types.Header, lendingStateDB *lendi
|
|||
return nil, false
|
||||
}
|
||||
|
||||
func (l *Lending) ProcessTopUp(lendingStateDB *lendingstate.LendingStateDB, statedb *state.StateDB, tradingStateDb *tradingstate.TradingStateDB, order *lendingstate.LendingItem) (error, bool, *lendingstate.LendingTrade) {
|
||||
func (l *Lending) ProcessTopUp(lendingStateDB *lendingstate.LendingStateDB, statedb *state.StateDB, tradingStateDb *tradingstate.TradingStateDB, order *lendingstate.LendingItem) (bool, *lendingstate.LendingTrade, error) {
|
||||
lendingTradeId := common.Uint64ToHash(order.LendingTradeId)
|
||||
lendingBook := lendingstate.GetLendingOrderBookHash(order.LendingToken, order.Term)
|
||||
lendingTrade := lendingStateDB.GetLendingTrade(lendingBook, lendingTradeId)
|
||||
if lendingTrade == lendingstate.EmptyLendingTrade {
|
||||
return fmt.Errorf("process deposit for emptyLendingTrade is not allowed. lendingTradeId: %v", lendingTradeId.Hex()), true, nil
|
||||
return true, nil, fmt.Errorf("process deposit for emptyLendingTrade is not allowed. lendingTradeId: %v", lendingTradeId.Hex())
|
||||
}
|
||||
if order.UserAddress != lendingTrade.Borrower {
|
||||
return fmt.Errorf("ProcessTopUp: invalid userAddress . UserAddress: %s . Borrower: %s", order.UserAddress.Hex(), lendingTrade.Borrower.Hex()), true, nil
|
||||
return true, nil, fmt.Errorf("ProcessTopUp: invalid userAddress . UserAddress: %s . Borrower: %s", order.UserAddress.Hex(), lendingTrade.Borrower.Hex())
|
||||
}
|
||||
if order.Relayer != lendingTrade.BorrowingRelayer {
|
||||
return fmt.Errorf("ProcessTopUp: invalid relayerAddress . Got: %s . Expect: %s", order.Relayer.Hex(), lendingTrade.BorrowingRelayer.Hex()), true, nil
|
||||
return true, nil, fmt.Errorf("ProcessTopUp: invalid relayerAddress . Got: %s . Expect: %s", order.Relayer.Hex(), lendingTrade.BorrowingRelayer.Hex())
|
||||
}
|
||||
if order.Quantity.Sign() <= 0 || lendingTrade.TradeId != lendingTradeId.Big().Uint64() {
|
||||
log.Debug("ProcessTopUp: invalid quantity", "Quantity", order.Quantity, "lendingTradeId", lendingTradeId.Hex())
|
||||
return nil, true, nil
|
||||
return true, nil, nil
|
||||
}
|
||||
return l.ProcessTopUpLendingTrade(lendingStateDB, statedb, tradingStateDb, lendingTradeId, lendingBook, order.Quantity)
|
||||
}
|
||||
|
|
@ -927,7 +928,7 @@ func (l *Lending) LiquidationTrade(lendingStateDB *lendingstate.LendingStateDB,
|
|||
// cancellation fee = 1/10 borrowing fee
|
||||
// deprecated after hardfork at TIPXDCXCancellationFee
|
||||
func getCancelFeeV1(collateralTokenDecimal *big.Int, collateralPrice, borrowFee *big.Int, order *lendingstate.LendingItem) *big.Int {
|
||||
cancelFee := big.NewInt(0)
|
||||
var cancelFee *big.Int
|
||||
if order.Side == lendingstate.Investing {
|
||||
// cancel fee = quantityToLend*borrowFee/LendingCancelFee
|
||||
cancelFee = new(big.Int).Mul(order.Quantity, borrowFee)
|
||||
|
|
@ -947,7 +948,7 @@ func (l *Lending) getCancelFee(chain consensus.ChainContext, statedb *state.Stat
|
|||
if feeRate == nil || feeRate.Sign() == 0 {
|
||||
return common.Big0, common.Big0
|
||||
}
|
||||
cancelFee, tokenPriceInXDC := common.Big0, common.Big0
|
||||
var cancelFee, tokenPriceInXDC *big.Int
|
||||
var err error
|
||||
if order.Side == lendingstate.Investing {
|
||||
cancelFee, tokenPriceInXDC, err = l.XDCx.ConvertXDCToToken(chain, statedb, tradingStateDb, order.LendingToken, common.RelayerLendingCancelFee)
|
||||
|
|
@ -971,11 +972,11 @@ func (l *Lending) GetMediumTradePriceBeforeEpoch(chain consensus.ChainContext, s
|
|||
if inversePrice != nil && inversePrice.Sign() > 0 {
|
||||
quoteTokenDecimal, err := l.XDCx.GetTokenDecimal(chain, statedb, quoteToken)
|
||||
if err != nil || quoteTokenDecimal.Sign() == 0 {
|
||||
return nil, fmt.Errorf("Fail to get tokenDecimal. Token: %v . Err: %v", quoteToken.String(), err)
|
||||
return nil, fmt.Errorf("fail to get tokenDecimal: Token: %v . Err: %v", quoteToken.String(), err)
|
||||
}
|
||||
baseTokenDecimal, err := l.XDCx.GetTokenDecimal(chain, statedb, baseToken)
|
||||
if err != nil || baseTokenDecimal.Sign() == 0 {
|
||||
return nil, fmt.Errorf("Fail to get tokenDecimal. Token: %v . Err: %v", baseToken, err)
|
||||
return nil, fmt.Errorf("fail to get tokenDecimal: Token: %v . Err: %v", baseToken, err)
|
||||
}
|
||||
price = new(big.Int).Mul(baseTokenDecimal, quoteTokenDecimal)
|
||||
price = new(big.Int).Div(price, inversePrice)
|
||||
|
|
@ -1098,7 +1099,7 @@ func (l *Lending) AutoTopUp(statedb *state.StateDB, tradingState *tradingstate.T
|
|||
return nil, fmt.Errorf("process deposit for emptyLendingTrade is not allowed. lendingTradeId: %v", lendingTradeId.Hex())
|
||||
}
|
||||
if currentPrice.Cmp(lendingTrade.LiquidationPrice) >= 0 {
|
||||
return nil, fmt.Errorf("CurrentPrice is still higher than or equal to LiquidationPrice. current price: %v , liquidation price : %v ", currentPrice, lendingTrade.LiquidationPrice)
|
||||
return nil, fmt.Errorf("currentPrice is still higher than or equal to LiquidationPrice. current price: %v , liquidation price : %v ", currentPrice, lendingTrade.LiquidationPrice)
|
||||
}
|
||||
// newLiquidationPrice = currentPrice * 90%
|
||||
newLiquidationPrice := new(big.Int).Mul(currentPrice, common.RateTopUp)
|
||||
|
|
@ -1112,23 +1113,23 @@ func (l *Lending) AutoTopUp(statedb *state.StateDB, tradingState *tradingstate.T
|
|||
if tokenBalance.Cmp(requiredDepositAmount) < 0 {
|
||||
return nil, fmt.Errorf("not enough balance to AutoTopUp. requiredDepositAmount: %v . tokenBalance: %v . Token: %s", requiredDepositAmount, tokenBalance, lendingTrade.CollateralToken.Hex())
|
||||
}
|
||||
err, _, newTrade := l.ProcessTopUpLendingTrade(lendingState, statedb, tradingState, lendingTradeId, lendingBook, requiredDepositAmount)
|
||||
_, newTrade, err := l.ProcessTopUpLendingTrade(lendingState, statedb, tradingState, lendingTradeId, lendingBook, requiredDepositAmount)
|
||||
return newTrade, err
|
||||
}
|
||||
|
||||
func (l *Lending) ProcessTopUpLendingTrade(lendingStateDB *lendingstate.LendingStateDB, statedb *state.StateDB, tradingStateDb *tradingstate.TradingStateDB, lendingTradeId common.Hash, lendingBook common.Hash, quantity *big.Int) (error, bool, *lendingstate.LendingTrade) {
|
||||
func (l *Lending) ProcessTopUpLendingTrade(lendingStateDB *lendingstate.LendingStateDB, statedb *state.StateDB, tradingStateDb *tradingstate.TradingStateDB, lendingTradeId common.Hash, lendingBook common.Hash, quantity *big.Int) (bool, *lendingstate.LendingTrade, error) {
|
||||
lendingTrade := lendingStateDB.GetLendingTrade(lendingBook, lendingTradeId)
|
||||
if lendingTrade == lendingstate.EmptyLendingTrade {
|
||||
return fmt.Errorf("process deposit for emptyLendingTrade is not allowed. lendingTradeId: %v", lendingTradeId.Hex()), true, nil
|
||||
return true, nil, fmt.Errorf("process deposit for emptyLendingTrade is not allowed. lendingTradeId: %v", lendingTradeId.Hex())
|
||||
}
|
||||
tokenBalance := lendingstate.GetTokenBalance(lendingTrade.Borrower, lendingTrade.CollateralToken, statedb)
|
||||
if tokenBalance.Cmp(quantity) < 0 {
|
||||
log.Debug("not enough balance deposit", "Quantity", quantity, "tokenBalance", tokenBalance)
|
||||
return fmt.Errorf("not enough balance deposit. lendingTradeId: %v , Quantity : %v , tokenBalance : %v", lendingTradeId.Hex(), quantity, tokenBalance), true, nil
|
||||
return true, nil, fmt.Errorf("not enough balance deposit. lendingTradeId: %v , Quantity : %v , tokenBalance : %v", lendingTradeId.Hex(), quantity, tokenBalance)
|
||||
}
|
||||
err := tradingStateDb.RemoveLiquidationPrice(tradingstate.GetTradingOrderBookHash(lendingTrade.CollateralToken, lendingTrade.LendingToken), lendingTrade.LiquidationPrice, lendingBook, lendingTrade.TradeId)
|
||||
if err != nil {
|
||||
return err, true, nil
|
||||
return true, nil, err
|
||||
}
|
||||
err = lendingstate.SubTokenBalance(lendingTrade.Borrower, quantity, lendingTrade.CollateralToken, statedb)
|
||||
if err != nil {
|
||||
|
|
@ -1149,7 +1150,7 @@ func (l *Lending) ProcessTopUpLendingTrade(lendingStateDB *lendingstate.LendingS
|
|||
newLendingTrade.LiquidationPrice = newLiquidationPrice
|
||||
newLendingTrade.CollateralLockedAmount = newLockedAmount
|
||||
log.Debug("ProcessTopUp successfully", "price", newLiquidationPrice, "lockAmount", newLockedAmount)
|
||||
return nil, false, &newLendingTrade
|
||||
return false, &newLendingTrade, nil
|
||||
}
|
||||
|
||||
func (l *Lending) ProcessRepayLendingTrade(header *types.Header, chain consensus.ChainContext, lendingStateDB *lendingstate.LendingStateDB, statedb *state.StateDB, tradingstateDB *tradingstate.TradingStateDB, lendingBook common.Hash, lendingTradeId uint64) (trade *lendingstate.LendingTrade, err error) {
|
||||
|
|
@ -1165,7 +1166,7 @@ func (l *Lending) ProcessRepayLendingTrade(header *types.Header, chain consensus
|
|||
|
||||
if tokenBalance.Cmp(paymentBalance) < 0 {
|
||||
if lendingTrade.LiquidationTime > time {
|
||||
return nil, fmt.Errorf("Not enough balance need : %s , have : %s ", paymentBalance, tokenBalance)
|
||||
return nil, fmt.Errorf("not enough balance need : %s , have : %s", paymentBalance, tokenBalance)
|
||||
}
|
||||
newLendingTrade := &lendingstate.LendingTrade{}
|
||||
var err error
|
||||
|
|
@ -1235,14 +1236,14 @@ func (l *Lending) ProcessRepayLendingTrade(header *types.Header, chain consensus
|
|||
return &lendingTrade, nil
|
||||
}
|
||||
|
||||
func (l *Lending) ProcessRecallLendingTrade(lendingStateDB *lendingstate.LendingStateDB, statedb *state.StateDB, tradingStateDb *tradingstate.TradingStateDB, lendingBook common.Hash, lendingTradeId common.Hash, newLiquidationPrice *big.Int) (error, bool, *lendingstate.LendingTrade) {
|
||||
func (l *Lending) ProcessRecallLendingTrade(lendingStateDB *lendingstate.LendingStateDB, statedb *state.StateDB, tradingStateDb *tradingstate.TradingStateDB, lendingBook common.Hash, lendingTradeId common.Hash, newLiquidationPrice *big.Int) (bool, *lendingstate.LendingTrade, error) {
|
||||
log.Debug("ProcessRecallLendingTrade", "lendingTradeId", lendingTradeId.Hex(), "lendingBook", lendingBook.Hex(), "newLiquidationPrice", newLiquidationPrice)
|
||||
lendingTrade := lendingStateDB.GetLendingTrade(lendingBook, lendingTradeId)
|
||||
if lendingTrade == lendingstate.EmptyLendingTrade {
|
||||
return fmt.Errorf("process recall for emptyLendingTrade is not allowed. lendingTradeId: %v", lendingTradeId.Hex()), true, nil
|
||||
return true, nil, fmt.Errorf("process recall for emptyLendingTrade is not allowed. lendingTradeId: %v", lendingTradeId.Hex())
|
||||
}
|
||||
if newLiquidationPrice.Cmp(lendingTrade.LiquidationPrice) <= 0 {
|
||||
return fmt.Errorf("New liquidation price must higher than old liquidation price. current liquidation price: %v , new liquidation price : %v ", lendingTrade.LiquidationPrice, newLiquidationPrice), true, nil
|
||||
return true, nil, fmt.Errorf("New liquidation price must higher than old liquidation price. current liquidation price: %v , new liquidation price : %v ", lendingTrade.LiquidationPrice, newLiquidationPrice)
|
||||
}
|
||||
newLockedAmount := new(big.Int).Mul(lendingTrade.CollateralLockedAmount, lendingTrade.LiquidationPrice)
|
||||
newLockedAmount = new(big.Int).Div(newLockedAmount, newLiquidationPrice)
|
||||
|
|
@ -1250,7 +1251,7 @@ func (l *Lending) ProcessRecallLendingTrade(lendingStateDB *lendingstate.Lending
|
|||
log.Debug("ProcessRecallLendingTrade", "newLockedAmount", newLockedAmount, "recallAmount", recallAmount, "oldLiquidationPrice", lendingTrade.LiquidationPrice, "newLiquidationPrice", newLiquidationPrice)
|
||||
err := tradingStateDb.RemoveLiquidationPrice(tradingstate.GetTradingOrderBookHash(lendingTrade.CollateralToken, lendingTrade.LendingToken), lendingTrade.LiquidationPrice, lendingBook, lendingTrade.TradeId)
|
||||
if err != nil {
|
||||
return err, true, nil
|
||||
return true, nil, err
|
||||
}
|
||||
err = lendingstate.AddTokenBalance(lendingTrade.Borrower, recallAmount, lendingTrade.CollateralToken, statedb)
|
||||
if err != nil {
|
||||
|
|
@ -1268,5 +1269,5 @@ func (l *Lending) ProcessRecallLendingTrade(lendingStateDB *lendingstate.Lending
|
|||
newLendingTrade.LiquidationPrice = newLiquidationPrice
|
||||
newLendingTrade.CollateralLockedAmount = newLockedAmount
|
||||
log.Debug("ProcessRecall", "price", newLiquidationPrice, "lockAmount", newLockedAmount, "recall amount", recallAmount)
|
||||
return nil, false, &newLendingTrade
|
||||
return false, &newLendingTrade, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package abi
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/big"
|
||||
|
|
@ -713,3 +714,34 @@ func TestABI_MethodById(t *testing.T) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func TestUnpackRevert(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var cases = []struct {
|
||||
input string
|
||||
expect string
|
||||
expectErr error
|
||||
}{
|
||||
{"", "", errors.New("invalid data for unpacking")},
|
||||
{"08c379a1", "", errors.New("invalid data for unpacking")},
|
||||
{"08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d72657665727420726561736f6e00000000000000000000000000000000000000", "revert reason", nil},
|
||||
}
|
||||
for index, c := range cases {
|
||||
t.Run(fmt.Sprintf("case %d", index), func(t *testing.T) {
|
||||
got, err := UnpackRevert(common.Hex2Bytes(c.input))
|
||||
if c.expectErr != nil {
|
||||
if err == nil {
|
||||
t.Fatalf("Expected non-nil error")
|
||||
}
|
||||
if err.Error() != c.expectErr.Error() {
|
||||
t.Fatalf("Expected error mismatch, want %v, got %v", c.expectErr, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if c.expect != got {
|
||||
t.Fatalf("Output mismatch, want %v, got %v", c.expect, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts"
|
||||
|
|
@ -80,7 +79,7 @@ func NewKeyedTransactor(key *ecdsa.PrivateKey) *TransactOpts {
|
|||
// NewTransactorWithChainID is a utility method to easily create a transaction signer from
|
||||
// an encrypted json key stream and the associated passphrase.
|
||||
func NewTransactorWithChainID(keyin io.Reader, passphrase string, chainID *big.Int) (*TransactOpts, error) {
|
||||
json, err := ioutil.ReadAll(keyin)
|
||||
json, err := io.ReadAll(keyin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,12 +32,12 @@ var (
|
|||
// have any code associated with it (i.e. suicided).
|
||||
ErrNoCode = errors.New("no contract code at given address")
|
||||
|
||||
// This error is raised when attempting to perform a pending state action
|
||||
// ErrNoPendingState is raised when attempting to perform a pending state action
|
||||
// on a backend that doesn't implement PendingContractCaller.
|
||||
ErrNoPendingState = errors.New("backend does not support pending state")
|
||||
|
||||
// This error is returned by WaitDeployed if contract creation leaves an
|
||||
// empty contract behind.
|
||||
// ErrNoCodeAfterDeploy is returned by WaitDeployed if contract creation leaves
|
||||
// an empty contract behind.
|
||||
ErrNoCodeAfterDeploy = errors.New("no contract code after deployment")
|
||||
)
|
||||
|
||||
|
|
@ -47,7 +47,8 @@ type ContractCaller interface {
|
|||
// CodeAt returns the code of the given account. This is needed to differentiate
|
||||
// between contract internal errors and the local chain being out of sync.
|
||||
CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error)
|
||||
// ContractCall executes an Ethereum contract call with the specified data as the
|
||||
|
||||
// CallContract executes an Ethereum contract call with the specified data as the
|
||||
// input.
|
||||
CallContract(ctx context.Context, call XDPoSChain.CallMsg, blockNumber *big.Int) ([]byte, error)
|
||||
}
|
||||
|
|
@ -58,6 +59,7 @@ type ContractCaller interface {
|
|||
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 XDPoSChain.CallMsg) ([]byte, error)
|
||||
}
|
||||
|
|
@ -67,19 +69,31 @@ type PendingContractCaller interface {
|
|||
// used when the user does not provide some needed values, but rather leaves it up
|
||||
// to the transactor to decide.
|
||||
type ContractTransactor interface {
|
||||
// HeaderByNumber returns a block header from the current canonical chain. If
|
||||
// number is nil, the latest known header is returned.
|
||||
HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
|
||||
|
||||
// PendingCodeAt returns the code of the given account in the pending state.
|
||||
PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error)
|
||||
|
||||
// PendingNonceAt retrieves the current pending nonce associated with an account.
|
||||
PendingNonceAt(ctx context.Context, account common.Address) (uint64, error)
|
||||
|
||||
// SuggestGasPrice retrieves the currently suggested gas price to allow a timely
|
||||
// execution of a transaction.
|
||||
SuggestGasPrice(ctx context.Context) (*big.Int, error)
|
||||
|
||||
// SuggestGasTipCap retrieves the currently suggested 1559 priority fee to allow
|
||||
// a timely execution of a transaction.
|
||||
SuggestGasTipCap(ctx context.Context) (*big.Int, error)
|
||||
|
||||
// EstimateGas tries to estimate the gas needed to execute a specific
|
||||
// transaction based on the current pending state of the backend blockchain.
|
||||
// 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 XDPoSChain.CallMsg) (gas uint64, err error)
|
||||
|
||||
// SendTransaction injects the transaction into the pending pool for execution.
|
||||
SendTransaction(ctx context.Context, tx *types.Transaction) error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/XDCx"
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCxlending"
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts"
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts/abi"
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts/keystore"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
|
|
@ -42,6 +43,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/eth/filters"
|
||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||
"github.com/XinFinOrg/XDPoSChain/event"
|
||||
|
|
@ -53,7 +55,6 @@ import (
|
|||
var _ bind.ContractBackend = (*SimulatedBackend)(nil)
|
||||
|
||||
var errBlockNumberUnsupported = errors.New("SimulatedBackend cannot access blocks other than the latest block")
|
||||
var errGasEstimationFailed = errors.New("gas required exceeds allowance or always failing transaction")
|
||||
|
||||
// SimulatedBackend implements bind.ContractBackend, simulating a blockchain in
|
||||
// the background. Its main purpose is to allow easily testing contract bindings.
|
||||
|
|
@ -86,10 +87,10 @@ func SimulateWalletAddressAndSignFn() (common.Address, func(account accounts.Acc
|
|||
pass := "" // not used but required by API
|
||||
a1, err := ks.NewAccount(pass)
|
||||
if err != nil {
|
||||
return common.Address{}, nil, fmt.Errorf(err.Error())
|
||||
return common.Address{}, nil, err
|
||||
}
|
||||
if err := ks.Unlock(a1, ""); err != nil {
|
||||
return a1.Address, nil, fmt.Errorf(err.Error())
|
||||
return a1.Address, nil, err
|
||||
}
|
||||
return a1.Address, ks.SignHash, nil
|
||||
}
|
||||
|
|
@ -101,7 +102,7 @@ func NewXDCSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64, chainConfi
|
|||
GasLimit: gasLimit, // need this big, support initial smart contract
|
||||
Config: chainConfig,
|
||||
Alloc: alloc,
|
||||
ExtraData: append(make([]byte, 32), make([]byte, 65)...),
|
||||
ExtraData: append(make([]byte, 32), make([]byte, crypto.SignatureLength)...),
|
||||
}
|
||||
genesis.MustCommit(database)
|
||||
consensus := XDPoS.NewFaker(database, chainConfig)
|
||||
|
|
@ -160,6 +161,12 @@ func NewSimulatedBackend(alloc core.GenesisAlloc) *SimulatedBackend {
|
|||
return backend
|
||||
}
|
||||
|
||||
// Close terminates the underlying blockchain's update loop.
|
||||
func (b *SimulatedBackend) Close() error {
|
||||
b.blockchain.Stop()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Commit imports all the pending transactions as a single block and starts a
|
||||
// fresh new state.
|
||||
func (b *SimulatedBackend) Commit() {
|
||||
|
|
@ -256,6 +263,19 @@ func (b *SimulatedBackend) TransactionReceipt(ctx context.Context, txHash common
|
|||
return receipt, nil
|
||||
}
|
||||
|
||||
// HeaderByNumber returns a block header from the current canonical chain. If number is
|
||||
// nil, the latest known header is returned.
|
||||
func (b *SimulatedBackend) HeaderByNumber(ctx context.Context, block *big.Int) (*types.Header, error) {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
|
||||
if block == nil || block.Cmp(b.pendingBlock.Number()) == 0 {
|
||||
return b.blockchain.CurrentHeader(), nil
|
||||
}
|
||||
|
||||
return b.blockchain.GetHeaderByNumber(uint64(block.Int64())), nil
|
||||
}
|
||||
|
||||
// PendingCodeAt returns the code associated with an account in the pending state.
|
||||
func (b *SimulatedBackend) PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) {
|
||||
b.mu.Lock()
|
||||
|
|
@ -276,8 +296,11 @@ func (b *SimulatedBackend) CallContract(ctx context.Context, call XDPoSChain.Cal
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rval, _, _, err := b.callContract(ctx, call, b.blockchain.CurrentBlock(), state)
|
||||
return rval, err
|
||||
res, err := b.callContract(ctx, call, b.blockchain.CurrentBlock(), state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res.Return(), nil
|
||||
}
|
||||
|
||||
// PendingCallContract executes a contract call on the pending state.
|
||||
|
|
@ -286,8 +309,11 @@ func (b *SimulatedBackend) PendingCallContract(ctx context.Context, call XDPoSCh
|
|||
defer b.mu.Unlock()
|
||||
defer b.pendingState.RevertToSnapshot(b.pendingState.Snapshot())
|
||||
|
||||
rval, _, _, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
|
||||
return rval, err
|
||||
res, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res.Return(), nil
|
||||
}
|
||||
|
||||
// PendingNonceAt implements PendingStateReader.PendingNonceAt, retrieving
|
||||
|
|
@ -300,8 +326,17 @@ func (b *SimulatedBackend) PendingNonceAt(ctx context.Context, account common.Ad
|
|||
}
|
||||
|
||||
// SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated
|
||||
// chain doens't have miners, we just return a gas price of 1 for any call.
|
||||
// chain doesn't have miners, we just return a gas price of 1 for any call.
|
||||
func (b *SimulatedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
|
||||
if b.pendingBlock.Header().BaseFee != nil {
|
||||
return b.pendingBlock.Header().BaseFee, nil
|
||||
}
|
||||
return big.NewInt(1), nil
|
||||
}
|
||||
|
||||
// SuggestGasTipCap implements ContractTransactor.SuggestGasTipCap. Since the simulated
|
||||
// chain doesn't have miners, we just return a gas tip of 1 for any call.
|
||||
func (b *SimulatedBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
|
||||
return big.NewInt(1), nil
|
||||
}
|
||||
|
||||
|
|
@ -325,22 +360,33 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call XDPoSChain.Call
|
|||
cap = hi
|
||||
|
||||
// Create a helper to check if a gas allowance results in an executable transaction
|
||||
executable := func(gas uint64) bool {
|
||||
executable := func(gas uint64) (bool, *core.ExecutionResult, error) {
|
||||
call.Gas = gas
|
||||
|
||||
snapshot := b.pendingState.Snapshot()
|
||||
_, _, failed, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
|
||||
res, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
|
||||
b.pendingState.RevertToSnapshot(snapshot)
|
||||
|
||||
if err != nil || failed {
|
||||
return false
|
||||
if err != nil {
|
||||
if err == core.ErrIntrinsicGas {
|
||||
return true, nil, nil // Special case, raise gas limit
|
||||
}
|
||||
return true, nil, err // Bail out
|
||||
}
|
||||
return true
|
||||
return res.Failed(), res, nil
|
||||
}
|
||||
// Execute the binary search and hone in on an executable gas limit
|
||||
for lo+1 < hi {
|
||||
mid := (hi + lo) / 2
|
||||
if !executable(mid) {
|
||||
failed, _, err := executable(mid)
|
||||
|
||||
// If the error is not nil(consensus error), it means the provided message
|
||||
// call or transaction will never be accepted no matter how much gas it is
|
||||
// assigned. Return the error directly, don't struggle any more
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if failed {
|
||||
lo = mid
|
||||
} else {
|
||||
hi = mid
|
||||
|
|
@ -348,8 +394,25 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call XDPoSChain.Call
|
|||
}
|
||||
// Reject the transaction as invalid if it still fails at the highest allowance
|
||||
if hi == cap {
|
||||
if !executable(hi) {
|
||||
return 0, errGasEstimationFailed
|
||||
failed, result, err := executable(hi)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if failed {
|
||||
if result != nil && result.Err != vm.ErrOutOfGas {
|
||||
errMsg := fmt.Sprintf("always failing transaction (%v)", result.Err)
|
||||
if len(result.Revert()) > 0 {
|
||||
ret, err := abi.UnpackRevert(result.Revert())
|
||||
if err != nil {
|
||||
errMsg += fmt.Sprintf(" (%#x)", result.Revert())
|
||||
} else {
|
||||
errMsg += fmt.Sprintf(" (%s)", ret)
|
||||
}
|
||||
}
|
||||
return 0, errors.New(errMsg)
|
||||
}
|
||||
// Otherwise, the specified gas cap is too low
|
||||
return 0, fmt.Errorf("gas required exceeds allowance (%d)", cap)
|
||||
}
|
||||
}
|
||||
return hi, nil
|
||||
|
|
@ -357,11 +420,39 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call XDPoSChain.Call
|
|||
|
||||
// callContract implements common code between normal and pending contract calls.
|
||||
// state is modified during execution, make sure to copy it if necessary.
|
||||
func (b *SimulatedBackend) callContract(ctx context.Context, call XDPoSChain.CallMsg, block *types.Block, statedb *state.StateDB) (ret []byte, usedGas uint64, failed bool, err error) {
|
||||
// Ensure message is initialized properly.
|
||||
if call.GasPrice == nil {
|
||||
call.GasPrice = big.NewInt(1)
|
||||
func (b *SimulatedBackend) callContract(ctx context.Context, call XDPoSChain.CallMsg, block *types.Block, statedb *state.StateDB) (*core.ExecutionResult, error) {
|
||||
// Gas prices post 1559 need to be initialized
|
||||
if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) {
|
||||
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
|
||||
}
|
||||
head := b.blockchain.CurrentHeader()
|
||||
if !b.blockchain.Config().IsEIP1559(head.Number) {
|
||||
// If there's no basefee, then it must be a non-1559 execution
|
||||
if call.GasPrice == nil {
|
||||
call.GasPrice = new(big.Int)
|
||||
}
|
||||
call.GasFeeCap, call.GasTipCap = call.GasPrice, call.GasPrice
|
||||
} else {
|
||||
// A basefee is provided, necessitating 1559-type execution
|
||||
if call.GasPrice != nil {
|
||||
// User specified the legacy gas field, convert to 1559 gas typing
|
||||
call.GasFeeCap, call.GasTipCap = call.GasPrice, call.GasPrice
|
||||
} else {
|
||||
// User specified 1559 gas feilds (or none), use those
|
||||
if call.GasFeeCap == nil {
|
||||
call.GasFeeCap = new(big.Int)
|
||||
}
|
||||
if call.GasTipCap == nil {
|
||||
call.GasTipCap = new(big.Int)
|
||||
}
|
||||
// Backfill the legacy gasPrice for EVM execution, unless we're all zeroes
|
||||
call.GasPrice = new(big.Int)
|
||||
if call.GasFeeCap.BitLen() > 0 || call.GasTipCap.BitLen() > 0 {
|
||||
call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, head.BaseFee), call.GasFeeCap)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Ensure message is initialized properly.
|
||||
if call.Gas == 0 {
|
||||
call.Gas = 50000000
|
||||
}
|
||||
|
|
@ -379,14 +470,16 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call XDPoSChain.Cal
|
|||
msg.CallMsg.BalanceTokenFee = value
|
||||
}
|
||||
}
|
||||
evmContext := core.NewEVMContext(msg, block.Header(), b.blockchain, nil)
|
||||
|
||||
txContext := core.NewEVMTxContext(msg)
|
||||
evmContext := core.NewEVMBlockContext(block.Header(), b.blockchain, nil)
|
||||
// Create a new environment which holds all relevant information
|
||||
// about the transaction and calling mechanisms.
|
||||
vmenv := vm.NewEVM(evmContext, statedb, nil, b.config, vm.Config{})
|
||||
vmenv := vm.NewEVM(evmContext, txContext, statedb, nil, b.config, vm.Config{NoBaseFee: true})
|
||||
gaspool := new(core.GasPool).AddGas(math.MaxUint64)
|
||||
owner := common.Address{}
|
||||
ret, usedGas, failed, err, _ = core.NewStateTransition(vmenv, msg, gaspool).TransitionDb(owner)
|
||||
return
|
||||
res, err, _ := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb(owner)
|
||||
return res, err
|
||||
}
|
||||
|
||||
// SendTransaction updates the pending block to include the given transaction.
|
||||
|
|
@ -520,9 +613,11 @@ type callMsg struct {
|
|||
|
||||
func (m callMsg) From() common.Address { return m.CallMsg.From }
|
||||
func (m callMsg) Nonce() uint64 { return 0 }
|
||||
func (m callMsg) CheckNonce() bool { return false }
|
||||
func (m callMsg) IsFake() bool { return true }
|
||||
func (m callMsg) To() *common.Address { return m.CallMsg.To }
|
||||
func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
|
||||
func (m callMsg) GasFeeCap() *big.Int { return m.CallMsg.GasFeeCap }
|
||||
func (m callMsg) GasTipCap() *big.Int { return m.CallMsg.GasTipCap }
|
||||
func (m callMsg) Gas() uint64 { return m.CallMsg.Gas }
|
||||
func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
|
||||
func (m callMsg) Data() []byte { return m.CallMsg.Data }
|
||||
|
|
@ -552,7 +647,11 @@ func (fb *filterBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*t
|
|||
}
|
||||
|
||||
func (fb *filterBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
|
||||
return core.GetBlockReceipts(fb.db, hash, core.GetBlockNumber(fb.db, hash)), nil
|
||||
number := rawdb.ReadHeaderNumber(fb.db, hash)
|
||||
if number == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return rawdb.ReadReceipts(fb.db, hash, *number, fb.bc.Config()), nil
|
||||
}
|
||||
|
||||
func (fb *filterBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) {
|
||||
|
|
|
|||
154
accounts/abi/bind/backends/simulated_test.go
Normal file
154
accounts/abi/bind/backends/simulated_test.go
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
// Copyright 2019 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package backends
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"math/big"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain"
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts/abi"
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
)
|
||||
|
||||
func TestSimulatedBackend_EstimateGas(t *testing.T) {
|
||||
/*
|
||||
pragma solidity ^0.6.4;
|
||||
contract GasEstimation {
|
||||
function PureRevert() public { revert(); }
|
||||
function Revert() public { revert("revert reason");}
|
||||
function OOG() public { for (uint i = 0; ; i++) {}}
|
||||
function Assert() public { assert(false);}
|
||||
function Valid() public {}
|
||||
}*/
|
||||
const contractAbi = "[{\"inputs\":[],\"name\":\"Assert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"OOG\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PureRevert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"Revert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"Valid\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"
|
||||
const contractBin = "0x60806040523480156100115760006000fd5b50610017565b61016e806100266000396000f3fe60806040523480156100115760006000fd5b506004361061005c5760003560e01c806350f6fe3414610062578063aa8b1d301461006c578063b9b046f914610076578063d8b9839114610080578063e09fface1461008a5761005c565b60006000fd5b61006a610094565b005b6100746100ad565b005b61007e6100b5565b005b6100886100c2565b005b610092610135565b005b6000600090505b5b808060010191505061009b565b505b565b60006000fd5b565b600015156100bf57fe5b5b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f72657665727420726561736f6e0000000000000000000000000000000000000081526020015060200191505060405180910390fd5b565b5b56fea2646970667358221220345bbcbb1a5ecf22b53a78eaebf95f8ee0eceff6d10d4b9643495084d2ec934a64736f6c63430006040033"
|
||||
|
||||
key, _ := crypto.GenerateKey()
|
||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||
opts := bind.NewKeyedTransactor(key)
|
||||
|
||||
sim := NewXDCSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(params.Ether)}}, 10000000, ¶ms.ChainConfig{
|
||||
ConstantinopleBlock: big.NewInt(0),
|
||||
XDPoS: ¶ms.XDPoSConfig{
|
||||
Epoch: 900,
|
||||
SkipV1Validation: true,
|
||||
V2: ¶ms.V2{
|
||||
SwitchBlock: big.NewInt(900),
|
||||
CurrentConfig: params.UnitTestV2Configs[0],
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
defer sim.Close()
|
||||
|
||||
parsed, _ := abi.JSON(strings.NewReader(contractAbi))
|
||||
contractAddr, _, _, _ := bind.DeployContract(opts, parsed, common.FromHex(contractBin), sim)
|
||||
sim.Commit()
|
||||
|
||||
var cases = []struct {
|
||||
name string
|
||||
message XDPoSChain.CallMsg
|
||||
expect uint64
|
||||
expectError error
|
||||
}{
|
||||
{"plain transfer(valid)", XDPoSChain.CallMsg{
|
||||
From: addr,
|
||||
To: &addr,
|
||||
Gas: 0,
|
||||
GasPrice: big.NewInt(0),
|
||||
Value: big.NewInt(1),
|
||||
Data: nil,
|
||||
}, params.TxGas, nil},
|
||||
|
||||
{"plain transfer(invalid)", XDPoSChain.CallMsg{
|
||||
From: addr,
|
||||
To: &contractAddr,
|
||||
Gas: 0,
|
||||
GasPrice: big.NewInt(0),
|
||||
Value: big.NewInt(1),
|
||||
Data: nil,
|
||||
}, 0, errors.New("always failing transaction (execution reverted)")},
|
||||
|
||||
{"Revert", XDPoSChain.CallMsg{
|
||||
From: addr,
|
||||
To: &contractAddr,
|
||||
Gas: 0,
|
||||
GasPrice: big.NewInt(0),
|
||||
Value: nil,
|
||||
Data: common.Hex2Bytes("d8b98391"),
|
||||
}, 0, errors.New("always failing transaction (execution reverted) (revert reason)")},
|
||||
|
||||
{"PureRevert", XDPoSChain.CallMsg{
|
||||
From: addr,
|
||||
To: &contractAddr,
|
||||
Gas: 0,
|
||||
GasPrice: big.NewInt(0),
|
||||
Value: nil,
|
||||
Data: common.Hex2Bytes("aa8b1d30"),
|
||||
}, 0, errors.New("always failing transaction (execution reverted)")},
|
||||
|
||||
{"OOG", XDPoSChain.CallMsg{
|
||||
From: addr,
|
||||
To: &contractAddr,
|
||||
Gas: 100000,
|
||||
GasPrice: big.NewInt(0),
|
||||
Value: nil,
|
||||
Data: common.Hex2Bytes("50f6fe34"),
|
||||
}, 0, errors.New("gas required exceeds allowance (100000)")},
|
||||
|
||||
{"Assert", XDPoSChain.CallMsg{
|
||||
From: addr,
|
||||
To: &contractAddr,
|
||||
Gas: 100000,
|
||||
GasPrice: big.NewInt(0),
|
||||
Value: nil,
|
||||
Data: common.Hex2Bytes("b9b046f9"),
|
||||
}, 0, errors.New("always failing transaction (invalid opcode: INVALID)")},
|
||||
|
||||
{"Valid", XDPoSChain.CallMsg{
|
||||
From: addr,
|
||||
To: &contractAddr,
|
||||
Gas: 100000,
|
||||
GasPrice: big.NewInt(0),
|
||||
Value: nil,
|
||||
Data: common.Hex2Bytes("e09fface"),
|
||||
}, 21483, nil},
|
||||
}
|
||||
for _, c := range cases {
|
||||
got, err := sim.EstimateGas(context.Background(), c.message)
|
||||
if c.expectError != nil {
|
||||
if err == nil {
|
||||
t.Fatalf("Expect error, got nil")
|
||||
}
|
||||
if c.expectError.Error() != err.Error() {
|
||||
t.Fatalf("Expect error, want %v, got %v", c.expectError, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if got != c.expect {
|
||||
t.Fatalf("Gas estimation mismatch, want %d, got %d", c.expect, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -53,11 +53,15 @@ type TransactOpts struct {
|
|||
Nonce *big.Int // Nonce to use for the transaction execution (nil = use pending state)
|
||||
Signer SignerFn // Method to use for signing the transaction (mandatory)
|
||||
|
||||
Value *big.Int // Funds to transfer along along the transaction (nil = 0 = no funds)
|
||||
GasPrice *big.Int // Gas price to use for the transaction execution (nil = gas price oracle)
|
||||
GasLimit uint64 // Gas limit to set for the transaction execution (0 = estimate)
|
||||
Value *big.Int // Funds to transfer along along the transaction (nil = 0 = no funds)
|
||||
GasPrice *big.Int // Gas price to use for the transaction execution (nil = gas price oracle)
|
||||
GasFeeCap *big.Int // Gas fee cap to use for the 1559 transaction execution (nil = gas price oracle)
|
||||
GasTipCap *big.Int // Gas priority fee cap to use for the 1559 transaction execution (nil = gas price oracle)
|
||||
GasLimit uint64 // Gas limit to set for the transaction execution (0 = estimate)
|
||||
|
||||
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
|
||||
|
||||
NoSend bool // Do all transact steps but do not send the transaction
|
||||
}
|
||||
|
||||
// FilterOpts is the collection of options to fine tune filtering for events
|
||||
|
|
@ -184,57 +188,158 @@ func (c *BoundContract) Transfer(opts *TransactOpts) (*types.Transaction, error)
|
|||
return c.transact(opts, &c.address, nil)
|
||||
}
|
||||
|
||||
// transact executes an actual transaction invocation, first deriving any missing
|
||||
// authorization fields, and then scheduling the transaction for execution.
|
||||
func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, input []byte) (*types.Transaction, error) {
|
||||
var err error
|
||||
|
||||
// Ensure a valid value field and resolve the account nonce
|
||||
func (c *BoundContract) createDynamicTx(opts *TransactOpts, contract *common.Address, input []byte, head *types.Header) (*types.Transaction, error) {
|
||||
// Normalize value
|
||||
value := opts.Value
|
||||
if value == nil {
|
||||
value = new(big.Int)
|
||||
}
|
||||
var nonce uint64
|
||||
if opts.Nonce == nil {
|
||||
nonce, err = c.transactor.PendingNonceAt(ensureContext(opts.Context), opts.From)
|
||||
// Estimate TipCap
|
||||
gasTipCap := opts.GasTipCap
|
||||
if gasTipCap == nil {
|
||||
tip, err := c.transactor.SuggestGasTipCap(ensureContext(opts.Context))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve account nonce: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
nonce = opts.Nonce.Uint64()
|
||||
gasTipCap = tip
|
||||
}
|
||||
// Figure out the gas allowance and gas price values
|
||||
// Estimate FeeCap
|
||||
gasFeeCap := opts.GasFeeCap
|
||||
if gasFeeCap == nil {
|
||||
gasFeeCap = new(big.Int).Add(
|
||||
gasTipCap,
|
||||
new(big.Int).Mul(head.BaseFee, big.NewInt(2)),
|
||||
)
|
||||
}
|
||||
if gasFeeCap.Cmp(gasTipCap) < 0 {
|
||||
return nil, fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", gasFeeCap, gasTipCap)
|
||||
}
|
||||
// Estimate GasLimit
|
||||
gasLimit := opts.GasLimit
|
||||
if opts.GasLimit == 0 {
|
||||
var err error
|
||||
gasLimit, err = c.estimateGasLimit(opts, contract, input, nil, gasTipCap, gasFeeCap, value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// create the transaction
|
||||
nonce, err := c.getNonce(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
baseTx := &types.DynamicFeeTx{
|
||||
To: contract,
|
||||
Nonce: nonce,
|
||||
GasFeeCap: gasFeeCap,
|
||||
GasTipCap: gasTipCap,
|
||||
Gas: gasLimit,
|
||||
Value: value,
|
||||
Data: input,
|
||||
}
|
||||
return types.NewTx(baseTx), nil
|
||||
}
|
||||
|
||||
func (c *BoundContract) createLegacyTx(opts *TransactOpts, contract *common.Address, input []byte) (*types.Transaction, error) {
|
||||
if opts.GasFeeCap != nil || opts.GasTipCap != nil {
|
||||
return nil, errors.New("maxFeePerGas or maxPriorityFeePerGas specified but EIP-1559 is not active yet")
|
||||
}
|
||||
// Normalize value
|
||||
value := opts.Value
|
||||
if value == nil {
|
||||
value = new(big.Int)
|
||||
}
|
||||
// Estimate GasPrice
|
||||
gasPrice := opts.GasPrice
|
||||
if gasPrice == nil {
|
||||
gasPrice, err = c.transactor.SuggestGasPrice(ensureContext(opts.Context))
|
||||
price, err := c.transactor.SuggestGasPrice(ensureContext(opts.Context))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to suggest gas price: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
gasPrice = price
|
||||
}
|
||||
// Estimate GasLimit
|
||||
gasLimit := opts.GasLimit
|
||||
if gasLimit == 0 {
|
||||
// Gas estimation cannot succeed without code for method invocations
|
||||
if contract != nil {
|
||||
if code, err := c.transactor.PendingCodeAt(ensureContext(opts.Context), c.address); err != nil {
|
||||
return nil, err
|
||||
} else if len(code) == 0 {
|
||||
return nil, ErrNoCode
|
||||
}
|
||||
}
|
||||
// If the contract surely has code (or code is not needed), estimate the transaction
|
||||
msg := XDPoSChain.CallMsg{From: opts.From, To: contract, Value: value, Data: input}
|
||||
gasLimit, err = c.transactor.EstimateGas(ensureContext(opts.Context), msg)
|
||||
if opts.GasLimit == 0 {
|
||||
var err error
|
||||
gasLimit, err = c.estimateGasLimit(opts, contract, input, gasPrice, nil, nil, value)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to estimate gas needed: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// Create the transaction, sign it and schedule it for execution
|
||||
var rawTx *types.Transaction
|
||||
if contract == nil {
|
||||
rawTx = types.NewContractCreation(nonce, value, gasLimit, gasPrice, input)
|
||||
} else {
|
||||
rawTx = types.NewTransaction(nonce, c.address, value, gasLimit, gasPrice, input)
|
||||
// create the transaction
|
||||
nonce, err := c.getNonce(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
baseTx := &types.LegacyTx{
|
||||
To: contract,
|
||||
Nonce: nonce,
|
||||
GasPrice: gasPrice,
|
||||
Gas: gasLimit,
|
||||
Value: value,
|
||||
Data: input,
|
||||
}
|
||||
return types.NewTx(baseTx), nil
|
||||
}
|
||||
|
||||
func (c *BoundContract) estimateGasLimit(opts *TransactOpts, contract *common.Address, input []byte, gasPrice, gasTipCap, gasFeeCap, value *big.Int) (uint64, error) {
|
||||
if contract != nil {
|
||||
// Gas estimation cannot succeed without code for method invocations.
|
||||
if code, err := c.transactor.PendingCodeAt(ensureContext(opts.Context), c.address); err != nil {
|
||||
return 0, err
|
||||
} else if len(code) == 0 {
|
||||
return 0, ErrNoCode
|
||||
}
|
||||
}
|
||||
msg := XDPoSChain.CallMsg{
|
||||
From: opts.From,
|
||||
To: contract,
|
||||
GasPrice: gasPrice,
|
||||
GasTipCap: gasTipCap,
|
||||
GasFeeCap: gasFeeCap,
|
||||
Value: value,
|
||||
Data: input,
|
||||
}
|
||||
return c.transactor.EstimateGas(ensureContext(opts.Context), msg)
|
||||
}
|
||||
|
||||
func (c *BoundContract) getNonce(opts *TransactOpts) (uint64, error) {
|
||||
if opts.Nonce == nil {
|
||||
return c.transactor.PendingNonceAt(ensureContext(opts.Context), opts.From)
|
||||
} else {
|
||||
return opts.Nonce.Uint64(), nil
|
||||
}
|
||||
}
|
||||
|
||||
// transact executes an actual transaction invocation, first deriving any missing
|
||||
// authorization fields, and then scheduling the transaction for execution.
|
||||
func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, input []byte) (*types.Transaction, error) {
|
||||
if opts.GasPrice != nil && (opts.GasFeeCap != nil || opts.GasTipCap != nil) {
|
||||
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
|
||||
}
|
||||
// Create the transaction
|
||||
var (
|
||||
rawTx *types.Transaction
|
||||
err error
|
||||
)
|
||||
if opts.GasPrice != nil {
|
||||
rawTx, err = c.createLegacyTx(opts, contract, input)
|
||||
} else {
|
||||
// Only query for basefee if gasPrice not specified
|
||||
if head, errHead := c.transactor.HeaderByNumber(ensureContext(opts.Context), nil); errHead != nil {
|
||||
return nil, errHead
|
||||
} else if head.BaseFee != nil {
|
||||
rawTx, err = c.createDynamicTx(opts, contract, input, head)
|
||||
} else {
|
||||
// Chain is not London ready -> use legacy transaction
|
||||
rawTx, err = c.createLegacyTx(opts, contract, input)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Sign the transaction and schedule it for execution
|
||||
if opts.Signer == nil {
|
||||
return nil, errors.New("no signer to authorize the transaction with")
|
||||
}
|
||||
|
|
@ -242,6 +347,9 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if opts.NoSend {
|
||||
return signedTx, nil
|
||||
}
|
||||
if err := c.transactor.SendTransaction(ensureContext(opts.Context), signedTx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -280,7 +388,7 @@ func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]int
|
|||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
sub, err := event.NewSubscription(func(quit <-chan struct{}) error {
|
||||
sub := event.NewSubscription(func(quit <-chan struct{}) error {
|
||||
for _, log := range buff {
|
||||
select {
|
||||
case logs <- log:
|
||||
|
|
@ -289,11 +397,8 @@ func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]int
|
|||
}
|
||||
}
|
||||
return nil
|
||||
}), nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return logs, sub, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
177
accounts/abi/bind/base_test.go
Normal file
177
accounts/abi/bind/base_test.go
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
// Copyright 2019 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package bind_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain"
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts/abi"
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func mockSign(addr common.Address, tx *types.Transaction) (*types.Transaction, error) { return tx, nil }
|
||||
|
||||
type mockTransactor struct {
|
||||
baseFee *big.Int
|
||||
gasTipCap *big.Int
|
||||
gasPrice *big.Int
|
||||
suggestGasTipCapCalled bool
|
||||
suggestGasPriceCalled bool
|
||||
}
|
||||
|
||||
func (mt *mockTransactor) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
|
||||
return &types.Header{BaseFee: mt.baseFee}, nil
|
||||
}
|
||||
|
||||
func (mt *mockTransactor) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) {
|
||||
return []byte{1}, nil
|
||||
}
|
||||
|
||||
func (mt *mockTransactor) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (mt *mockTransactor) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
|
||||
mt.suggestGasPriceCalled = true
|
||||
return mt.gasPrice, nil
|
||||
}
|
||||
|
||||
func (mt *mockTransactor) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
|
||||
mt.suggestGasTipCapCalled = true
|
||||
return mt.gasTipCap, nil
|
||||
}
|
||||
|
||||
func (mt *mockTransactor) EstimateGas(ctx context.Context, call XDPoSChain.CallMsg) (gas uint64, err error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (mt *mockTransactor) SendTransaction(ctx context.Context, tx *types.Transaction) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type mockCaller struct {
|
||||
codeAtBlockNumber *big.Int
|
||||
callContractBlockNumber *big.Int
|
||||
pendingCodeAtCalled bool
|
||||
pendingCallContractCalled bool
|
||||
}
|
||||
|
||||
func (mc *mockCaller) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) {
|
||||
mc.codeAtBlockNumber = blockNumber
|
||||
return []byte{1, 2, 3}, nil
|
||||
}
|
||||
|
||||
func (mc *mockCaller) CallContract(ctx context.Context, call XDPoSChain.CallMsg, blockNumber *big.Int) ([]byte, error) {
|
||||
mc.callContractBlockNumber = blockNumber
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (mc *mockCaller) PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) {
|
||||
mc.pendingCodeAtCalled = true
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (mc *mockCaller) PendingCallContract(ctx context.Context, call XDPoSChain.CallMsg) ([]byte, error) {
|
||||
mc.pendingCallContractCalled = true
|
||||
return nil, nil
|
||||
}
|
||||
func TestPassingBlockNumber(t *testing.T) {
|
||||
|
||||
mc := &mockCaller{}
|
||||
|
||||
bc := bind.NewBoundContract(common.HexToAddress("0x0"), abi.ABI{
|
||||
Methods: map[string]abi.Method{
|
||||
"something": {
|
||||
Name: "something",
|
||||
Outputs: abi.Arguments{},
|
||||
},
|
||||
},
|
||||
}, mc, nil, nil)
|
||||
|
||||
bc.Call(&bind.CallOpts{}, nil, "something")
|
||||
|
||||
bc.Call(&bind.CallOpts{}, nil, "something")
|
||||
|
||||
if mc.callContractBlockNumber != nil {
|
||||
t.Fatalf("CallContract() was passed a block number when it should not have been")
|
||||
}
|
||||
|
||||
if mc.codeAtBlockNumber != nil {
|
||||
t.Fatalf("CodeAt() was passed a block number when it should not have been")
|
||||
}
|
||||
|
||||
bc.Call(&bind.CallOpts{Pending: true}, nil, "something")
|
||||
|
||||
if !mc.pendingCallContractCalled {
|
||||
t.Fatalf("CallContract() was not passed the block number")
|
||||
}
|
||||
|
||||
if !mc.pendingCodeAtCalled {
|
||||
t.Fatalf("CodeAt() was not passed the block number")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransactGasFee(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
// GasTipCap and GasFeeCap
|
||||
// When opts.GasTipCap and opts.GasFeeCap are nil
|
||||
mt := &mockTransactor{baseFee: big.NewInt(100), gasTipCap: big.NewInt(5)}
|
||||
bc := bind.NewBoundContract(common.Address{}, abi.ABI{}, nil, mt, nil)
|
||||
opts := &bind.TransactOpts{Signer: mockSign}
|
||||
tx, err := bc.Transact(opts, "")
|
||||
assert.Nil(err)
|
||||
assert.Equal(big.NewInt(5), tx.GasTipCap())
|
||||
assert.Equal(big.NewInt(205), tx.GasFeeCap())
|
||||
assert.Nil(opts.GasTipCap)
|
||||
assert.Nil(opts.GasFeeCap)
|
||||
assert.True(mt.suggestGasTipCapCalled)
|
||||
|
||||
// Second call to Transact should use latest suggested GasTipCap
|
||||
mt.gasTipCap = big.NewInt(6)
|
||||
mt.suggestGasTipCapCalled = false
|
||||
tx, err = bc.Transact(opts, "")
|
||||
assert.Nil(err)
|
||||
assert.Equal(big.NewInt(6), tx.GasTipCap())
|
||||
assert.Equal(big.NewInt(206), tx.GasFeeCap())
|
||||
assert.True(mt.suggestGasTipCapCalled)
|
||||
|
||||
// GasPrice
|
||||
// When opts.GasPrice is nil
|
||||
mt = &mockTransactor{gasPrice: big.NewInt(5)}
|
||||
bc = bind.NewBoundContract(common.Address{}, abi.ABI{}, nil, mt, nil)
|
||||
opts = &bind.TransactOpts{Signer: mockSign}
|
||||
tx, err = bc.Transact(opts, "")
|
||||
assert.Nil(err)
|
||||
assert.Equal(big.NewInt(5), tx.GasPrice())
|
||||
assert.Nil(opts.GasPrice)
|
||||
assert.True(mt.suggestGasPriceCalled)
|
||||
|
||||
// Second call to Transact should use latest suggested GasPrice
|
||||
mt.gasPrice = big.NewInt(6)
|
||||
mt.suggestGasPriceCalled = false
|
||||
tx, err = bc.Transact(opts, "")
|
||||
assert.Nil(err)
|
||||
assert.Equal(big.NewInt(6), tx.GasPrice())
|
||||
assert.True(mt.suggestGasPriceCalled)
|
||||
}
|
||||
|
|
@ -37,8 +37,6 @@ type Lang int
|
|||
|
||||
const (
|
||||
LangGo Lang = iota
|
||||
LangJava
|
||||
LangObjC
|
||||
)
|
||||
|
||||
// Bind generates a Go wrapper around a contract ABI. This wrapper isn't meant
|
||||
|
|
@ -119,7 +117,7 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La
|
|||
}
|
||||
contracts[types[i]] = &tmplContract{
|
||||
Type: capitalise(types[i]),
|
||||
InputABI: strings.Replace(strippedABI, "\"", "\\\"", -1),
|
||||
InputABI: strings.ReplaceAll(strippedABI, "\"", "\\\""),
|
||||
InputBin: strings.TrimSpace(bytecodes[i]),
|
||||
Constructor: evmABI.Constructor,
|
||||
Calls: calls,
|
||||
|
|
@ -160,15 +158,15 @@ func Bind(types []string, abis []string, bytecodes []string, pkg string, lang La
|
|||
// bindType is a set of type binders that convert Solidity types to some supported
|
||||
// programming language types.
|
||||
var bindType = map[Lang]func(kind abi.Type) string{
|
||||
LangGo: bindTypeGo,
|
||||
LangJava: bindTypeJava,
|
||||
LangGo: bindTypeGo,
|
||||
}
|
||||
|
||||
// Helper function for the binding generators.
|
||||
// It reads the unmatched characters after the inner type-match,
|
||||
// (since the inner type is a prefix of the total type declaration),
|
||||
// looks for valid arrays (possibly a dynamic one) wrapping the inner type,
|
||||
// and returns the sizes of these arrays.
|
||||
//
|
||||
// (since the inner type is a prefix of the total type declaration),
|
||||
// looks for valid arrays (possibly a dynamic one) wrapping the inner type,
|
||||
// and returns the sizes of these arrays.
|
||||
//
|
||||
// Returned array sizes are in the same order as solidity signatures; inner array size first.
|
||||
// Array sizes may also be "", indicating a dynamic array.
|
||||
|
|
@ -244,15 +242,6 @@ func arrayBindingJava(inner string, arraySizes []string) string {
|
|||
return inner + strings.Repeat("[]", len(arraySizes))
|
||||
}
|
||||
|
||||
// bindTypeJava converts a Solidity type to a Java one. Since there is no clear mapping
|
||||
// from all Solidity types to Java ones (e.g. uint17), those that cannot be exactly
|
||||
// mapped will use an upscaled type (e.g. BigDecimal).
|
||||
func bindTypeJava(kind abi.Type) string {
|
||||
stringKind := kind.String()
|
||||
innerLen, innerMapping := bindUnnestedTypeJava(stringKind)
|
||||
return arrayBindingJava(wrapArray(stringKind, innerLen, innerMapping))
|
||||
}
|
||||
|
||||
// The inner function of bindTypeJava, this finds the inner type of stringKind.
|
||||
// (Or just the type itself if it is not an array or slice)
|
||||
// The length of the matched part is returned, with the the translated type.
|
||||
|
|
@ -311,8 +300,7 @@ func bindUnnestedTypeJava(stringKind string) (int, string) {
|
|||
// bindTopicType is a set of type binders that convert Solidity types to some
|
||||
// supported programming language topic types.
|
||||
var bindTopicType = map[Lang]func(kind abi.Type) string{
|
||||
LangGo: bindTopicTypeGo,
|
||||
LangJava: bindTopicTypeJava,
|
||||
LangGo: bindTopicTypeGo,
|
||||
}
|
||||
|
||||
// bindTypeGo converts a Solidity topic type to a Go one. It is almost the same
|
||||
|
|
@ -325,64 +313,16 @@ func bindTopicTypeGo(kind abi.Type) string {
|
|||
return bound
|
||||
}
|
||||
|
||||
// bindTypeGo converts a Solidity topic type to a Java one. It is almost the same
|
||||
// funcionality as for simple types, but dynamic types get converted to hashes.
|
||||
func bindTopicTypeJava(kind abi.Type) string {
|
||||
bound := bindTypeJava(kind)
|
||||
if bound == "String" || bound == "Bytes" {
|
||||
bound = "Hash"
|
||||
}
|
||||
return bound
|
||||
}
|
||||
|
||||
// namedType is a set of functions that transform language specific types to
|
||||
// named versions that my be used inside method names.
|
||||
var namedType = map[Lang]func(string, abi.Type) string{
|
||||
LangGo: func(string, abi.Type) string { panic("this shouldn't be needed") },
|
||||
LangJava: namedTypeJava,
|
||||
}
|
||||
|
||||
// namedTypeJava converts some primitive data types to named variants that can
|
||||
// be used as parts of method names.
|
||||
func namedTypeJava(javaKind string, solKind abi.Type) string {
|
||||
switch javaKind {
|
||||
case "byte[]":
|
||||
return "Binary"
|
||||
case "byte[][]":
|
||||
return "Binaries"
|
||||
case "string":
|
||||
return "String"
|
||||
case "string[]":
|
||||
return "Strings"
|
||||
case "boolean":
|
||||
return "Bool"
|
||||
case "boolean[]":
|
||||
return "Bools"
|
||||
case "BigInt[]":
|
||||
return "BigInts"
|
||||
default:
|
||||
parts := regexp.MustCompile(`(u)?int([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(solKind.String())
|
||||
if len(parts) != 4 {
|
||||
return javaKind
|
||||
}
|
||||
switch parts[2] {
|
||||
case "8", "16", "32", "64":
|
||||
if parts[3] == "" {
|
||||
return capitalise(fmt.Sprintf("%sint%s", parts[1], parts[2]))
|
||||
}
|
||||
return capitalise(fmt.Sprintf("%sint%ss", parts[1], parts[2]))
|
||||
|
||||
default:
|
||||
return javaKind
|
||||
}
|
||||
}
|
||||
LangGo: func(string, abi.Type) string { panic("this shouldn't be needed") },
|
||||
}
|
||||
|
||||
// methodNormalizer is a name transformer that modifies Solidity method names to
|
||||
// conform to target language naming concentions.
|
||||
var methodNormalizer = map[Lang]func(string) string{
|
||||
LangGo: capitalise,
|
||||
LangJava: decapitalise,
|
||||
LangGo: capitalise,
|
||||
}
|
||||
|
||||
// capitalise makes a camel-case string which starts with an upper case character.
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy an interaction tester contract and call a transaction on it
|
||||
_, _, interactor, err := DeployInteractor(auth, sim, "Deploy string")
|
||||
|
|
@ -270,7 +270,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy a tuple tester contract and execute a structured call on it
|
||||
_, _, getter, err := DeployGetter(auth, sim)
|
||||
|
|
@ -302,7 +302,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy a tuple tester contract and execute a structured call on it
|
||||
_, _, tupler, err := DeployTupler(auth, sim)
|
||||
|
|
@ -344,7 +344,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy a slice tester contract and execute a n array call on it
|
||||
_, _, slicer, err := DeploySlicer(auth, sim)
|
||||
|
|
@ -378,7 +378,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy a default method invoker contract and execute its default method
|
||||
_, _, defaulter, err := DeployDefaulter(auth, sim)
|
||||
|
|
@ -447,7 +447,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy a funky gas pattern contract
|
||||
_, _, limiter, err := DeployFunkyGasPattern(auth, sim)
|
||||
|
|
@ -482,7 +482,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy a sender tester contract and execute a structured call on it
|
||||
_, _, callfrom, err := DeployCallFrom(auth, sim)
|
||||
|
|
@ -542,7 +542,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy a underscorer tester contract and execute a structured call on it
|
||||
_, _, underscorer, err := DeployUnderscorer(auth, sim)
|
||||
|
|
@ -612,7 +612,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
// Deploy an eventer contract
|
||||
_, _, eventer, err := DeployEventer(auth, sim)
|
||||
|
|
@ -761,7 +761,7 @@ var bindTests = []struct {
|
|||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth, _ := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
sim := backends.NewXDCSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000000000)}}, 10000000, params.TestXDPoSMockChainConfig)
|
||||
|
||||
//deploy the test contract
|
||||
_, _, testContract, err := DeployDeeplyNestedArray(auth, sim)
|
||||
|
|
@ -821,7 +821,7 @@ func TestBindings(t *testing.T) {
|
|||
}
|
||||
t.Log("Using config", params.TestXDPoSMockChainConfig)
|
||||
// Skip the test if the go-ethereum sources are symlinked (https://github.com/golang/go/issues/14845)
|
||||
linkTestCode := fmt.Sprintf("package linktest\nfunc CheckSymlinks(){\nfmt.Println(backends.NewSimulatedBackend(nil))\n}")
|
||||
linkTestCode := "package linktest\nfunc CheckSymlinks(){\nfmt.Println(backends.NewSimulatedBackend(nil))\n}"
|
||||
linkTestDeps, err := imports.Process(os.TempDir(), []byte(linkTestCode), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("failed check for goimports symlink bug: %v", err)
|
||||
|
|
|
|||
|
|
@ -52,8 +52,7 @@ type tmplEvent struct {
|
|||
// tmplSource is language to template mapping containing all the supported
|
||||
// programming languages the package can generate to.
|
||||
var tmplSource = map[Lang]string{
|
||||
LangGo: tmplSourceGo,
|
||||
LangJava: tmplSourceJava,
|
||||
LangGo: tmplSourceGo,
|
||||
}
|
||||
|
||||
// tmplSourceGo is the Go source template use to generate the contract binding
|
||||
|
|
@ -418,105 +417,3 @@ package {{.Package}}
|
|||
{{end}}
|
||||
{{end}}
|
||||
`
|
||||
|
||||
// tmplSourceJava is the Java source template use to generate the contract binding
|
||||
// based on.
|
||||
const tmplSourceJava = `
|
||||
// This file is an automatically generated Java binding. Do not modify as any
|
||||
// change will likely be lost upon the next re-generation!
|
||||
|
||||
package {{.Package}};
|
||||
|
||||
import org.ethereum.geth.*;
|
||||
import org.ethereum.geth.internal.*;
|
||||
|
||||
{{range $contract := .Contracts}}
|
||||
public class {{.Type}} {
|
||||
// ABI is the input ABI used to generate the binding from.
|
||||
public final static String ABI = "{{.InputABI}}";
|
||||
|
||||
{{if .InputBin}}
|
||||
// BYTECODE is the compiled bytecode used for deploying new contracts.
|
||||
public final static byte[] BYTECODE = "{{.InputBin}}".getBytes();
|
||||
|
||||
// deploy deploys a new Ethereum contract, binding an instance of {{.Type}} to it.
|
||||
public static {{.Type}} deploy(TransactOpts auth, EthereumClient client{{range .Constructor.Inputs}}, {{bindtype .Type}} {{.Name}}{{end}}) throws Exception {
|
||||
Interfaces args = Geth.newInterfaces({{(len .Constructor.Inputs)}});
|
||||
{{range $index, $element := .Constructor.Inputs}}
|
||||
args.set({{$index}}, Geth.newInterface()); args.get({{$index}}).set{{namedtype (bindtype .Type) .Type}}({{.Name}});
|
||||
{{end}}
|
||||
return new {{.Type}}(Geth.deployContract(auth, ABI, BYTECODE, client, args));
|
||||
}
|
||||
|
||||
// Internal constructor used by contract deployment.
|
||||
private {{.Type}}(BoundContract deployment) {
|
||||
this.Address = deployment.getAddress();
|
||||
this.Deployer = deployment.getDeployer();
|
||||
this.Contract = deployment;
|
||||
}
|
||||
{{end}}
|
||||
|
||||
// Ethereum address where this contract is located at.
|
||||
public final Address Address;
|
||||
|
||||
// Ethereum transaction in which this contract was deployed (if known!).
|
||||
public final Transaction Deployer;
|
||||
|
||||
// Contract instance bound to a blockchain address.
|
||||
private final BoundContract Contract;
|
||||
|
||||
// Creates a new instance of {{.Type}}, bound to a specific deployed contract.
|
||||
public {{.Type}}(Address address, EthereumClient client) throws Exception {
|
||||
this(Geth.bindContract(address, ABI, client));
|
||||
}
|
||||
|
||||
{{range .Calls}}
|
||||
{{if gt (len .Normalized.Outputs) 1}}
|
||||
// {{capitalise .Normalized.Name}}Results is the output of a call to {{.Normalized.Name}}.
|
||||
public class {{capitalise .Normalized.Name}}Results {
|
||||
{{range $index, $item := .Normalized.Outputs}}public {{bindtype .Type}} {{if ne .Name ""}}{{.Name}}{{else}}Return{{$index}}{{end}};
|
||||
{{end}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.Id}}.
|
||||
//
|
||||
// Solidity: {{.Original.String}}
|
||||
public {{if gt (len .Normalized.Outputs) 1}}{{capitalise .Normalized.Name}}Results{{else}}{{range .Normalized.Outputs}}{{bindtype .Type}}{{end}}{{end}} {{.Normalized.Name}}(CallOpts opts{{range .Normalized.Inputs}}, {{bindtype .Type}} {{.Name}}{{end}}) throws Exception {
|
||||
Interfaces args = Geth.newInterfaces({{(len .Normalized.Inputs)}});
|
||||
{{range $index, $item := .Normalized.Inputs}}args.set({{$index}}, Geth.newInterface()); args.get({{$index}}).set{{namedtype (bindtype .Type) .Type}}({{.Name}});
|
||||
{{end}}
|
||||
|
||||
Interfaces results = Geth.newInterfaces({{(len .Normalized.Outputs)}});
|
||||
{{range $index, $item := .Normalized.Outputs}}Interface result{{$index}} = Geth.newInterface(); result{{$index}}.setDefault{{namedtype (bindtype .Type) .Type}}(); results.set({{$index}}, result{{$index}});
|
||||
{{end}}
|
||||
|
||||
if (opts == null) {
|
||||
opts = Geth.newCallOpts();
|
||||
}
|
||||
this.Contract.call(opts, results, "{{.Original.Name}}", args);
|
||||
{{if gt (len .Normalized.Outputs) 1}}
|
||||
{{capitalise .Normalized.Name}}Results result = new {{capitalise .Normalized.Name}}Results();
|
||||
{{range $index, $item := .Normalized.Outputs}}result.{{if ne .Name ""}}{{.Name}}{{else}}Return{{$index}}{{end}} = results.get({{$index}}).get{{namedtype (bindtype .Type) .Type}}();
|
||||
{{end}}
|
||||
return result;
|
||||
{{else}}{{range .Normalized.Outputs}}return results.get(0).get{{namedtype (bindtype .Type) .Type}}();{{end}}
|
||||
{{end}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{range .Transacts}}
|
||||
// {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.Id}}.
|
||||
//
|
||||
// Solidity: {{.Original.String}}
|
||||
public Transaction {{.Normalized.Name}}(TransactOpts opts{{range .Normalized.Inputs}}, {{bindtype .Type}} {{.Name}}{{end}}) throws Exception {
|
||||
Interfaces args = Geth.newInterfaces({{(len .Normalized.Inputs)}});
|
||||
{{range $index, $item := .Normalized.Inputs}}args.set({{$index}}, Geth.newInterface()); args.get({{$index}}).set{{namedtype (bindtype .Type) .Type}}({{.Name}});
|
||||
{{end}}
|
||||
|
||||
return this.Contract.transact(opts, "{{.Original.Name}}" , args);
|
||||
}
|
||||
{{end}}
|
||||
}
|
||||
{{end}}
|
||||
`
|
||||
|
|
|
|||
|
|
@ -53,15 +53,20 @@ var waitDeployedTests = map[string]struct {
|
|||
}
|
||||
|
||||
func TestWaitDeployed(t *testing.T) {
|
||||
config := *params.TestXDPoSMockChainConfig
|
||||
config.Eip1559Block = big.NewInt(0)
|
||||
for name, test := range waitDeployedTests {
|
||||
backend := backends.NewXDCSimulatedBackend(
|
||||
core.GenesisAlloc{
|
||||
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000)},
|
||||
}, 10000000, params.TestXDPoSMockChainConfig,
|
||||
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(100000000000000000)},
|
||||
}, 10000000, &config,
|
||||
)
|
||||
|
||||
// Create the transaction.
|
||||
tx := types.NewContractCreation(0, big.NewInt(0), test.gas, big.NewInt(1), common.FromHex(test.code))
|
||||
// Create the transaction
|
||||
head, _ := backend.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
|
||||
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
|
||||
|
||||
tx := types.NewContractCreation(0, big.NewInt(0), test.gas, gasPrice, common.FromHex(test.code))
|
||||
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
|
||||
|
||||
// Wait for it to get mined in the background.
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ func TestTypeRegexp(t *testing.T) {
|
|||
t.Errorf("type %q: failed to parse type string: %v", tt.blob, err)
|
||||
}
|
||||
if !reflect.DeepEqual(typ, tt.kind) {
|
||||
t.Errorf("type %q: parsed type mismatch:\nGOT %s\nWANT %s ", tt.blob, spew.Sdump(typeWithoutStringer(typ)), spew.Sdump(typeWithoutStringer(tt.kind)))
|
||||
t.Errorf("type %q: parsed type mismatch:\nGOT %s\nWANT %s", tt.blob, spew.Sdump(typeWithoutStringer(typ)), spew.Sdump(typeWithoutStringer(tt.kind)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -201,11 +201,11 @@ func DecryptKey(keyjson []byte, auth string) (*Key, error) {
|
|||
|
||||
func decryptKeyV3(keyProtected *encryptedKeyJSONV3, auth string) (keyBytes []byte, keyId []byte, err error) {
|
||||
if keyProtected.Version != version {
|
||||
return nil, nil, fmt.Errorf("Version not supported: %v", keyProtected.Version)
|
||||
return nil, nil, fmt.Errorf("not supported Version: %v", keyProtected.Version)
|
||||
}
|
||||
|
||||
if keyProtected.Crypto.Cipher != "aes-128-ctr" {
|
||||
return nil, nil, fmt.Errorf("Cipher not supported: %v", keyProtected.Crypto.Cipher)
|
||||
return nil, nil, fmt.Errorf("not supported Cipher: %v", keyProtected.Crypto.Cipher)
|
||||
}
|
||||
|
||||
keyId = uuid.Parse(keyProtected.Id)
|
||||
|
|
@ -293,13 +293,13 @@ func getKDFKey(cryptoJSON cryptoJSON, auth string) ([]byte, error) {
|
|||
c := ensureInt(cryptoJSON.KDFParams["c"])
|
||||
prf := cryptoJSON.KDFParams["prf"].(string)
|
||||
if prf != "hmac-sha256" {
|
||||
return nil, fmt.Errorf("Unsupported PBKDF2 PRF: %s", prf)
|
||||
return nil, fmt.Errorf("unsupported PBKDF2 PRF: %s", prf)
|
||||
}
|
||||
key := pbkdf2.Key(authArray, salt, c, dkLen, sha256.New)
|
||||
return key, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("Unsupported KDF: %s", cryptoJSON.KDF)
|
||||
return nil, fmt.Errorf("unsupported KDF: %s", cryptoJSON.KDF)
|
||||
}
|
||||
|
||||
// TODO: can we do without this when unmarshalling dynamic JSON?
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ func testDecryptV3(test KeyStoreTestV3, t *testing.T) {
|
|||
}
|
||||
privHex := hex.EncodeToString(privBytes)
|
||||
if test.Priv != privHex {
|
||||
t.Fatal(fmt.Errorf("Decrypted bytes not equal to test, expected %v have %v", test.Priv, privHex))
|
||||
t.Fatal(fmt.Errorf("decrypted bytes not equal to test, expected %v have %v", test.Priv, privHex))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -222,7 +222,7 @@ func testDecryptV1(test KeyStoreTestV1, t *testing.T) {
|
|||
}
|
||||
privHex := hex.EncodeToString(privBytes)
|
||||
if test.Priv != privHex {
|
||||
t.Fatal(fmt.Errorf("Decrypted bytes not equal to test, expected %v have %v", test.Priv, privHex))
|
||||
t.Fatal(fmt.Errorf("decrypted bytes not equal to test, expected %v have %v", test.Priv, privHex))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ func (u URL) String() string {
|
|||
func (u URL) TerminalString() string {
|
||||
url := u.String()
|
||||
if len(url) > 32 {
|
||||
return url[:31] + "…"
|
||||
return url[:31] + ".."
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
|
@ -76,10 +76,9 @@ func (u URL) MarshalJSON() ([]byte, error) {
|
|||
|
||||
// Cmp compares x and y and returns:
|
||||
//
|
||||
// -1 if x < y
|
||||
// 0 if x == y
|
||||
// +1 if x > y
|
||||
//
|
||||
// -1 if x < y
|
||||
// 0 if x == y
|
||||
// +1 if x > y
|
||||
func (u URL) Cmp(url URL) int {
|
||||
if u.Scheme == url.Scheme {
|
||||
return strings.Compare(u.Path, url.Path)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||
)
|
||||
|
|
@ -164,7 +165,7 @@ func (w *ledgerDriver) SignTx(path accounts.DerivationPath, tx *types.Transactio
|
|||
}
|
||||
// Ensure the wallet is capable of signing the given transaction
|
||||
if chainID != nil && w.version[0] <= 1 && w.version[1] <= 0 && w.version[2] <= 2 {
|
||||
return common.Address{}, nil, fmt.Errorf("Ledger v%d.%d.%d doesn't support signing this transaction, please update to v1.0.3 at least", w.version[0], w.version[1], w.version[2])
|
||||
return common.Address{}, nil, fmt.Errorf("ledger v%d.%d.%d doesn't support signing this transaction, please update to v1.0.3 at least", w.version[0], w.version[1], w.version[2])
|
||||
}
|
||||
// All infos gathered and metadata checks out, request signing
|
||||
return w.ledgerSign(path, tx, chainID)
|
||||
|
|
@ -175,18 +176,18 @@ func (w *ledgerDriver) SignTx(path accounts.DerivationPath, tx *types.Transactio
|
|||
//
|
||||
// The version retrieval protocol is defined as follows:
|
||||
//
|
||||
// CLA | INS | P1 | P2 | Lc | Le
|
||||
// ----+-----+----+----+----+---
|
||||
// E0 | 06 | 00 | 00 | 00 | 04
|
||||
// CLA | INS | P1 | P2 | Lc | Le
|
||||
// ----+-----+----+----+----+---
|
||||
// E0 | 06 | 00 | 00 | 00 | 04
|
||||
//
|
||||
// With no input data, and the output data being:
|
||||
//
|
||||
// Description | Length
|
||||
// ---------------------------------------------------+--------
|
||||
// Flags 01: arbitrary data signature enabled by user | 1 byte
|
||||
// Application major version | 1 byte
|
||||
// Application minor version | 1 byte
|
||||
// Application patch version | 1 byte
|
||||
// Description | Length
|
||||
// ---------------------------------------------------+--------
|
||||
// Flags 01: arbitrary data signature enabled by user | 1 byte
|
||||
// Application major version | 1 byte
|
||||
// Application minor version | 1 byte
|
||||
// Application patch version | 1 byte
|
||||
func (w *ledgerDriver) ledgerVersion() ([3]byte, error) {
|
||||
// Send the request and wait for the response
|
||||
reply, err := w.ledgerExchange(ledgerOpGetConfiguration, 0, 0, nil)
|
||||
|
|
@ -207,32 +208,32 @@ func (w *ledgerDriver) ledgerVersion() ([3]byte, error) {
|
|||
//
|
||||
// The address derivation protocol is defined as follows:
|
||||
//
|
||||
// CLA | INS | P1 | P2 | Lc | Le
|
||||
// ----+-----+----+----+-----+---
|
||||
// E0 | 02 | 00 return address
|
||||
// 01 display address and confirm before returning
|
||||
// | 00: do not return the chain code
|
||||
// | 01: return the chain code
|
||||
// | var | 00
|
||||
// CLA | INS | P1 | P2 | Lc | Le
|
||||
// ----+-----+----+----+-----+---
|
||||
// E0 | 02 | 00 return address
|
||||
// 01 display address and confirm before returning
|
||||
// | 00: do not return the chain code
|
||||
// | 01: return the chain code
|
||||
// | var | 00
|
||||
//
|
||||
// Where the input data is:
|
||||
//
|
||||
// Description | Length
|
||||
// -------------------------------------------------+--------
|
||||
// Number of BIP 32 derivations to perform (max 10) | 1 byte
|
||||
// First derivation index (big endian) | 4 bytes
|
||||
// ... | 4 bytes
|
||||
// Last derivation index (big endian) | 4 bytes
|
||||
// Description | Length
|
||||
// -------------------------------------------------+--------
|
||||
// Number of BIP 32 derivations to perform (max 10) | 1 byte
|
||||
// First derivation index (big endian) | 4 bytes
|
||||
// ... | 4 bytes
|
||||
// Last derivation index (big endian) | 4 bytes
|
||||
//
|
||||
// And the output data is:
|
||||
//
|
||||
// Description | Length
|
||||
// ------------------------+-------------------
|
||||
// Public Key length | 1 byte
|
||||
// Uncompressed Public Key | arbitrary
|
||||
// Ethereum address length | 1 byte
|
||||
// Ethereum address | 40 bytes hex ascii
|
||||
// Chain code if requested | 32 bytes
|
||||
// Description | Length
|
||||
// ------------------------+-------------------
|
||||
// Public Key length | 1 byte
|
||||
// Uncompressed Public Key | arbitrary
|
||||
// Ethereum address length | 1 byte
|
||||
// Ethereum address | 40 bytes hex ascii
|
||||
// Chain code if requested | 32 bytes
|
||||
func (w *ledgerDriver) ledgerDerive(derivationPath []uint32) (common.Address, error) {
|
||||
// Flatten the derivation path into the Ledger request
|
||||
path := make([]byte, 1+4*len(derivationPath))
|
||||
|
|
@ -268,35 +269,35 @@ func (w *ledgerDriver) ledgerDerive(derivationPath []uint32) (common.Address, er
|
|||
//
|
||||
// The transaction signing protocol is defined as follows:
|
||||
//
|
||||
// CLA | INS | P1 | P2 | Lc | Le
|
||||
// ----+-----+----+----+-----+---
|
||||
// E0 | 04 | 00: first transaction data block
|
||||
// 80: subsequent transaction data block
|
||||
// | 00 | variable | variable
|
||||
// CLA | INS | P1 | P2 | Lc | Le
|
||||
// ----+-----+----+----+-----+---
|
||||
// E0 | 04 | 00: first transaction data block
|
||||
// 80: subsequent transaction data block
|
||||
// | 00 | variable | variable
|
||||
//
|
||||
// Where the input for the first transaction block (first 255 bytes) is:
|
||||
//
|
||||
// Description | Length
|
||||
// -------------------------------------------------+----------
|
||||
// Number of BIP 32 derivations to perform (max 10) | 1 byte
|
||||
// First derivation index (big endian) | 4 bytes
|
||||
// ... | 4 bytes
|
||||
// Last derivation index (big endian) | 4 bytes
|
||||
// RLP transaction chunk | arbitrary
|
||||
// Description | Length
|
||||
// -------------------------------------------------+----------
|
||||
// Number of BIP 32 derivations to perform (max 10) | 1 byte
|
||||
// First derivation index (big endian) | 4 bytes
|
||||
// ... | 4 bytes
|
||||
// Last derivation index (big endian) | 4 bytes
|
||||
// RLP transaction chunk | arbitrary
|
||||
//
|
||||
// And the input for subsequent transaction blocks (first 255 bytes) are:
|
||||
//
|
||||
// Description | Length
|
||||
// ----------------------+----------
|
||||
// RLP transaction chunk | arbitrary
|
||||
// Description | Length
|
||||
// ----------------------+----------
|
||||
// RLP transaction chunk | arbitrary
|
||||
//
|
||||
// And the output data is:
|
||||
//
|
||||
// Description | Length
|
||||
// ------------+---------
|
||||
// signature V | 1 byte
|
||||
// signature R | 32 bytes
|
||||
// signature S | 32 bytes
|
||||
// Description | Length
|
||||
// ------------+---------
|
||||
// signature V | 1 byte
|
||||
// signature R | 32 bytes
|
||||
// signature S | 32 bytes
|
||||
func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error) {
|
||||
// Flatten the derivation path into the Ledger request
|
||||
path := make([]byte, 1+4*len(derivationPath))
|
||||
|
|
@ -341,7 +342,7 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
|
|||
op = ledgerP1ContTransactionData
|
||||
}
|
||||
// Extract the Ethereum signature and do a sanity validation
|
||||
if len(reply) != 65 {
|
||||
if len(reply) != crypto.SignatureLength {
|
||||
return common.Address{}, nil, errors.New("reply lacks signature")
|
||||
}
|
||||
signature := append(reply[1:], reply[0])
|
||||
|
|
@ -352,7 +353,7 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
|
|||
signer = new(types.HomesteadSigner)
|
||||
} else {
|
||||
signer = types.NewEIP155Signer(chainID)
|
||||
signature[64] = signature[64] - byte(chainID.Uint64()*2+35)
|
||||
signature[crypto.RecoveryIDOffset] = signature[crypto.RecoveryIDOffset] - byte(chainID.Uint64()*2+35)
|
||||
}
|
||||
signed, err := tx.WithSignature(signer, signature)
|
||||
if err != nil {
|
||||
|
|
@ -370,12 +371,12 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
|
|||
//
|
||||
// The common transport header is defined as follows:
|
||||
//
|
||||
// Description | Length
|
||||
// --------------------------------------+----------
|
||||
// Communication channel ID (big endian) | 2 bytes
|
||||
// Command tag | 1 byte
|
||||
// Packet sequence index (big endian) | 2 bytes
|
||||
// Payload | arbitrary
|
||||
// Description | Length
|
||||
// --------------------------------------+----------
|
||||
// Communication channel ID (big endian) | 2 bytes
|
||||
// Command tag | 1 byte
|
||||
// Packet sequence index (big endian) | 2 bytes
|
||||
// Payload | arbitrary
|
||||
//
|
||||
// The Communication channel ID allows commands multiplexing over the same
|
||||
// physical link. It is not used for the time being, and should be set to 0101
|
||||
|
|
@ -389,15 +390,15 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
|
|||
//
|
||||
// APDU Command payloads are encoded as follows:
|
||||
//
|
||||
// Description | Length
|
||||
// -----------------------------------
|
||||
// APDU length (big endian) | 2 bytes
|
||||
// APDU CLA | 1 byte
|
||||
// APDU INS | 1 byte
|
||||
// APDU P1 | 1 byte
|
||||
// APDU P2 | 1 byte
|
||||
// APDU length | 1 byte
|
||||
// Optional APDU data | arbitrary
|
||||
// Description | Length
|
||||
// -----------------------------------
|
||||
// APDU length (big endian) | 2 bytes
|
||||
// APDU CLA | 1 byte
|
||||
// APDU INS | 1 byte
|
||||
// APDU P1 | 1 byte
|
||||
// APDU P2 | 1 byte
|
||||
// APDU length | 1 byte
|
||||
// Optional APDU data | arbitrary
|
||||
func (w *ledgerDriver) ledgerExchange(opcode ledgerOpcode, p1 ledgerParam1, p2 ledgerParam2, data []byte) ([]byte, error) {
|
||||
// Construct the message payload, possibly split into multiple chunks
|
||||
apdu := make([]byte, 2, 7+len(data))
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
|
@ -222,7 +223,7 @@ func (w *trezorDriver) trezorSign(derivationPath []uint32, tx *types.Transaction
|
|||
} else {
|
||||
// Trezor backend does not support typed transactions yet.
|
||||
signer = types.NewEIP155Signer(chainID)
|
||||
signature[64] = signature[64] - byte(chainID.Uint64()*2+35)
|
||||
signature[crypto.RecoveryIDOffset] = signature[crypto.RecoveryIDOffset] - byte(chainID.Uint64()*2+35)
|
||||
}
|
||||
|
||||
// Inject the final signature into the transaction and sanity check the sender
|
||||
|
|
|
|||
167
bmt/bmt.go
167
bmt/bmt.go
|
|
@ -150,29 +150,29 @@ func NewTreePool(hasher BaseHasher, segmentCount, capacity int) *TreePool {
|
|||
}
|
||||
|
||||
// Drain drains the pool uptil it has no more than n resources
|
||||
func (self *TreePool) Drain(n int) {
|
||||
self.lock.Lock()
|
||||
defer self.lock.Unlock()
|
||||
for len(self.c) > n {
|
||||
<-self.c
|
||||
self.count--
|
||||
func (tp *TreePool) Drain(n int) {
|
||||
tp.lock.Lock()
|
||||
defer tp.lock.Unlock()
|
||||
for len(tp.c) > n {
|
||||
<-tp.c
|
||||
tp.count--
|
||||
}
|
||||
}
|
||||
|
||||
// Reserve is blocking until it returns an available Tree
|
||||
// it reuses free Trees or creates a new one if size is not reached
|
||||
func (self *TreePool) Reserve() *Tree {
|
||||
self.lock.Lock()
|
||||
defer self.lock.Unlock()
|
||||
func (tp *TreePool) Reserve() *Tree {
|
||||
tp.lock.Lock()
|
||||
defer tp.lock.Unlock()
|
||||
var t *Tree
|
||||
if self.count == self.Capacity {
|
||||
return <-self.c
|
||||
if tp.count == tp.Capacity {
|
||||
return <-tp.c
|
||||
}
|
||||
select {
|
||||
case t = <-self.c:
|
||||
case t = <-tp.c:
|
||||
default:
|
||||
t = NewTree(self.hasher, self.SegmentSize, self.SegmentCount)
|
||||
self.count++
|
||||
t = NewTree(tp.hasher, tp.SegmentSize, tp.SegmentCount)
|
||||
tp.count++
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
|
@ -180,8 +180,8 @@ func (self *TreePool) Reserve() *Tree {
|
|||
// Release gives back a Tree to the pool.
|
||||
// This Tree is guaranteed to be in reusable state
|
||||
// does not need locking
|
||||
func (self *TreePool) Release(t *Tree) {
|
||||
self.c <- t // can never fail but...
|
||||
func (tp *TreePool) Release(t *Tree) {
|
||||
tp.c <- t // can never fail but...
|
||||
}
|
||||
|
||||
// Tree is a reusable control structure representing a BMT
|
||||
|
|
@ -193,17 +193,14 @@ type Tree struct {
|
|||
}
|
||||
|
||||
// Draw draws the BMT (badly)
|
||||
func (self *Tree) Draw(hash []byte, d int) string {
|
||||
func (t *Tree) Draw(hash []byte, d int) string {
|
||||
var left, right []string
|
||||
var anc []*Node
|
||||
for i, n := range self.leaves {
|
||||
for _, n := range t.leaves {
|
||||
left = append(left, fmt.Sprintf("%v", hashstr(n.left)))
|
||||
if i%2 == 0 {
|
||||
anc = append(anc, n.parent)
|
||||
}
|
||||
right = append(right, fmt.Sprintf("%v", hashstr(n.right)))
|
||||
}
|
||||
anc = self.leaves
|
||||
anc = t.leaves
|
||||
var hashes [][]string
|
||||
for l := 0; len(anc) > 0; l++ {
|
||||
var nodes []*Node
|
||||
|
|
@ -277,42 +274,42 @@ func NewTree(hasher BaseHasher, segmentSize, segmentCount int) *Tree {
|
|||
// methods needed by hash.Hash
|
||||
|
||||
// Size returns the size
|
||||
func (self *Hasher) Size() int {
|
||||
return self.size
|
||||
func (ha *Hasher) Size() int {
|
||||
return ha.size
|
||||
}
|
||||
|
||||
// BlockSize returns the block size
|
||||
func (self *Hasher) BlockSize() int {
|
||||
return self.blocksize
|
||||
func (ha *Hasher) BlockSize() int {
|
||||
return ha.blocksize
|
||||
}
|
||||
|
||||
// Sum returns the hash of the buffer
|
||||
// hash.Hash interface Sum method appends the byte slice to the underlying
|
||||
// data before it calculates and returns the hash of the chunk
|
||||
func (self *Hasher) Sum(b []byte) (r []byte) {
|
||||
t := self.bmt
|
||||
i := self.cur
|
||||
func (ha *Hasher) Sum(b []byte) (r []byte) {
|
||||
t := ha.bmt
|
||||
i := ha.cur
|
||||
n := t.leaves[i]
|
||||
j := i
|
||||
// must run strictly before all nodes calculate
|
||||
// datanodes are guaranteed to have a parent
|
||||
if len(self.segment) > self.size && i > 0 && n.parent != nil {
|
||||
if len(ha.segment) > ha.size && i > 0 && n.parent != nil {
|
||||
n = n.parent
|
||||
} else {
|
||||
i *= 2
|
||||
}
|
||||
d := self.finalise(n, i)
|
||||
self.writeSegment(j, self.segment, d)
|
||||
c := <-self.result
|
||||
self.releaseTree()
|
||||
d := ha.finalise(n, i)
|
||||
ha.writeSegment(j, ha.segment, d)
|
||||
c := <-ha.result
|
||||
ha.releaseTree()
|
||||
|
||||
// sha3(length + BMT(pure_chunk))
|
||||
if self.blockLength == nil {
|
||||
if ha.blockLength == nil {
|
||||
return c
|
||||
}
|
||||
res := self.pool.hasher()
|
||||
res := ha.pool.hasher()
|
||||
res.Reset()
|
||||
res.Write(self.blockLength)
|
||||
res.Write(ha.blockLength)
|
||||
res.Write(c)
|
||||
return res.Sum(nil)
|
||||
}
|
||||
|
|
@ -321,8 +318,8 @@ func (self *Hasher) Sum(b []byte) (r []byte) {
|
|||
|
||||
// Hash waits for the hasher result and returns it
|
||||
// caller must call this on a BMT Hasher being written to
|
||||
func (self *Hasher) Hash() []byte {
|
||||
return <-self.result
|
||||
func (ha *Hasher) Hash() []byte {
|
||||
return <-ha.result
|
||||
}
|
||||
|
||||
// Hasher implements the io.Writer interface
|
||||
|
|
@ -330,16 +327,16 @@ func (self *Hasher) Hash() []byte {
|
|||
// Write fills the buffer to hash
|
||||
// with every full segment complete launches a hasher go routine
|
||||
// that shoots up the BMT
|
||||
func (self *Hasher) Write(b []byte) (int, error) {
|
||||
func (ha *Hasher) Write(b []byte) (int, error) {
|
||||
l := len(b)
|
||||
if l <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
s := self.segment
|
||||
i := self.cur
|
||||
count := (self.count + 1) / 2
|
||||
need := self.count*self.size - self.cur*2*self.size
|
||||
size := self.size
|
||||
s := ha.segment
|
||||
i := ha.cur
|
||||
count := (ha.count + 1) / 2
|
||||
need := ha.count*ha.size - ha.cur*2*ha.size
|
||||
size := ha.size
|
||||
if need > size {
|
||||
size *= 2
|
||||
}
|
||||
|
|
@ -356,7 +353,7 @@ func (self *Hasher) Write(b []byte) (int, error) {
|
|||
// read full segments and the last possibly partial segment
|
||||
for need > 0 && i < count-1 {
|
||||
// push all finished chunks we read
|
||||
self.writeSegment(i, s, self.depth)
|
||||
ha.writeSegment(i, s, ha.depth)
|
||||
need -= size
|
||||
if need < 0 {
|
||||
size += need
|
||||
|
|
@ -365,8 +362,8 @@ func (self *Hasher) Write(b []byte) (int, error) {
|
|||
rest += size
|
||||
i++
|
||||
}
|
||||
self.segment = s
|
||||
self.cur = i
|
||||
ha.segment = s
|
||||
ha.cur = i
|
||||
// otherwise, we can assume len(s) == 0, so all buffer is read and chunk is not yet full
|
||||
return l, nil
|
||||
}
|
||||
|
|
@ -376,8 +373,8 @@ func (self *Hasher) Write(b []byte) (int, error) {
|
|||
// ReadFrom reads from io.Reader and appends to the data to hash using Write
|
||||
// it reads so that chunk to hash is maximum length or reader reaches EOF
|
||||
// caller must Reset the hasher prior to call
|
||||
func (self *Hasher) ReadFrom(r io.Reader) (m int64, err error) {
|
||||
bufsize := self.size*self.count - self.size*self.cur - len(self.segment)
|
||||
func (ha *Hasher) ReadFrom(r io.Reader) (m int64, err error) {
|
||||
bufsize := ha.size*ha.count - ha.size*ha.cur - len(ha.segment)
|
||||
buf := make([]byte, bufsize)
|
||||
var read int
|
||||
for {
|
||||
|
|
@ -385,7 +382,7 @@ func (self *Hasher) ReadFrom(r io.Reader) (m int64, err error) {
|
|||
n, err = r.Read(buf)
|
||||
read += n
|
||||
if err == io.EOF || read == len(buf) {
|
||||
hash := self.Sum(buf[:n])
|
||||
hash := ha.Sum(buf[:n])
|
||||
if read == len(buf) {
|
||||
err = NewEOC(hash)
|
||||
}
|
||||
|
|
@ -394,7 +391,7 @@ func (self *Hasher) ReadFrom(r io.Reader) (m int64, err error) {
|
|||
if err != nil {
|
||||
break
|
||||
}
|
||||
n, err = self.Write(buf[:n])
|
||||
_, err = ha.Write(buf[:n])
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
|
@ -403,9 +400,9 @@ func (self *Hasher) ReadFrom(r io.Reader) (m int64, err error) {
|
|||
}
|
||||
|
||||
// Reset needs to be called before writing to the hasher
|
||||
func (self *Hasher) Reset() {
|
||||
self.getTree()
|
||||
self.blockLength = nil
|
||||
func (ha *Hasher) Reset() {
|
||||
ha.getTree()
|
||||
ha.blockLength = nil
|
||||
}
|
||||
|
||||
// Hasher implements the SwarmHash interface
|
||||
|
|
@ -413,53 +410,53 @@ func (self *Hasher) Reset() {
|
|||
// ResetWithLength needs to be called before writing to the hasher
|
||||
// the argument is supposed to be the byte slice binary representation of
|
||||
// the legth of the data subsumed under the hash
|
||||
func (self *Hasher) ResetWithLength(l []byte) {
|
||||
self.Reset()
|
||||
self.blockLength = l
|
||||
func (ha *Hasher) ResetWithLength(l []byte) {
|
||||
ha.Reset()
|
||||
ha.blockLength = l
|
||||
|
||||
}
|
||||
|
||||
// Release gives back the Tree to the pool whereby it unlocks
|
||||
// it resets tree, segment and index
|
||||
func (self *Hasher) releaseTree() {
|
||||
if self.bmt != nil {
|
||||
n := self.bmt.leaves[self.cur]
|
||||
func (ha *Hasher) releaseTree() {
|
||||
if ha.bmt != nil {
|
||||
n := ha.bmt.leaves[ha.cur]
|
||||
for ; n != nil; n = n.parent {
|
||||
n.unbalanced = false
|
||||
if n.parent != nil {
|
||||
n.root = false
|
||||
}
|
||||
}
|
||||
self.pool.Release(self.bmt)
|
||||
self.bmt = nil
|
||||
ha.pool.Release(ha.bmt)
|
||||
ha.bmt = nil
|
||||
|
||||
}
|
||||
self.cur = 0
|
||||
self.segment = nil
|
||||
ha.cur = 0
|
||||
ha.segment = nil
|
||||
}
|
||||
|
||||
func (self *Hasher) writeSegment(i int, s []byte, d int) {
|
||||
h := self.pool.hasher()
|
||||
n := self.bmt.leaves[i]
|
||||
func (ha *Hasher) writeSegment(i int, s []byte, d int) {
|
||||
h := ha.pool.hasher()
|
||||
n := ha.bmt.leaves[i]
|
||||
|
||||
if len(s) > self.size && n.parent != nil {
|
||||
if len(s) > ha.size && n.parent != nil {
|
||||
go func() {
|
||||
h.Reset()
|
||||
h.Write(s)
|
||||
s = h.Sum(nil)
|
||||
|
||||
if n.root {
|
||||
self.result <- s
|
||||
ha.result <- s
|
||||
return
|
||||
}
|
||||
self.run(n.parent, h, d, n.index, s)
|
||||
ha.run(n.parent, h, d, n.index, s)
|
||||
}()
|
||||
return
|
||||
}
|
||||
go self.run(n, h, d, i*2, s)
|
||||
go ha.run(n, h, d, i*2, s)
|
||||
}
|
||||
|
||||
func (self *Hasher) run(n *Node, h hash.Hash, d int, i int, s []byte) {
|
||||
func (ha *Hasher) run(n *Node, h hash.Hash, d int, i int, s []byte) {
|
||||
isLeft := i%2 == 0
|
||||
for {
|
||||
if isLeft {
|
||||
|
|
@ -480,9 +477,9 @@ func (self *Hasher) run(n *Node, h hash.Hash, d int, i int, s []byte) {
|
|||
s = append(n.left, n.right...)
|
||||
}
|
||||
|
||||
self.hash = s
|
||||
ha.hash = s
|
||||
if n.root {
|
||||
self.result <- s
|
||||
ha.result <- s
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -493,20 +490,20 @@ func (self *Hasher) run(n *Node, h hash.Hash, d int, i int, s []byte) {
|
|||
}
|
||||
|
||||
// getTree obtains a BMT resource by reserving one from the pool
|
||||
func (self *Hasher) getTree() *Tree {
|
||||
if self.bmt != nil {
|
||||
return self.bmt
|
||||
func (ha *Hasher) getTree() *Tree {
|
||||
if ha.bmt != nil {
|
||||
return ha.bmt
|
||||
}
|
||||
t := self.pool.Reserve()
|
||||
self.bmt = t
|
||||
t := ha.pool.Reserve()
|
||||
ha.bmt = t
|
||||
return t
|
||||
}
|
||||
|
||||
// atomic bool toggle implementing a concurrent reusable 2-state object
|
||||
// atomic addint with %2 implements atomic bool toggle
|
||||
// it returns true if the toggler just put it in the active/waiting state
|
||||
func (self *Node) toggle() bool {
|
||||
return atomic.AddInt32(&self.state, 1)%2 == 1
|
||||
func (n *Node) toggle() bool {
|
||||
return atomic.AddInt32(&n.state, 1)%2 == 1
|
||||
}
|
||||
|
||||
func hashstr(b []byte) string {
|
||||
|
|
@ -526,7 +523,7 @@ func depth(n int) (d int) {
|
|||
|
||||
// finalise is following the zigzags on the tree belonging
|
||||
// to the final datasegment
|
||||
func (self *Hasher) finalise(n *Node, i int) (d int) {
|
||||
func (ha *Hasher) finalise(n *Node, i int) (d int) {
|
||||
isLeft := i%2 == 0
|
||||
for {
|
||||
// when the final segment's path is going via left segments
|
||||
|
|
@ -551,8 +548,8 @@ type EOC struct {
|
|||
}
|
||||
|
||||
// Error returns the error string
|
||||
func (self *EOC) Error() string {
|
||||
return fmt.Sprintf("hasher limit reached, chunk hash: %x", self.Hash)
|
||||
func (e *EOC) Error() string {
|
||||
return fmt.Sprintf("hasher limit reached, chunk hash: %x", e.Hash)
|
||||
}
|
||||
|
||||
// NewEOC creates new end of chunk error with the hash
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto/sha3"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -39,7 +39,7 @@ const (
|
|||
// TestRefHasher tests that the RefHasher computes the expected BMT hash for
|
||||
// all data lengths between 0 and 256 bytes
|
||||
func TestRefHasher(t *testing.T) {
|
||||
hashFunc := sha3.NewKeccak256
|
||||
hashFunc := sha3.NewLegacyKeccak256
|
||||
|
||||
sha3 := func(data ...[]byte) []byte {
|
||||
h := hashFunc()
|
||||
|
|
@ -212,7 +212,7 @@ func testHasher(f func(BaseHasher, []byte, int, int) error) error {
|
|||
tdata := testDataReader(4128)
|
||||
data := make([]byte, 4128)
|
||||
tdata.Read(data)
|
||||
hasher := sha3.NewKeccak256
|
||||
hasher := sha3.NewLegacyKeccak256
|
||||
size := hasher().Size()
|
||||
counts := []int{1, 2, 3, 4, 5, 8, 16, 32, 64, 128}
|
||||
|
||||
|
|
@ -239,7 +239,7 @@ func TestHasherReuseWithRelease(t *testing.T) {
|
|||
}
|
||||
|
||||
func testHasherReuse(i int, t *testing.T) {
|
||||
hasher := sha3.NewKeccak256
|
||||
hasher := sha3.NewLegacyKeccak256
|
||||
pool := NewTreePool(hasher, 128, i)
|
||||
defer pool.Drain(0)
|
||||
bmt := New(pool)
|
||||
|
|
@ -258,7 +258,7 @@ func testHasherReuse(i int, t *testing.T) {
|
|||
}
|
||||
|
||||
func TestHasherConcurrency(t *testing.T) {
|
||||
hasher := sha3.NewKeccak256
|
||||
hasher := sha3.NewLegacyKeccak256
|
||||
pool := NewTreePool(hasher, 128, maxproccnt)
|
||||
defer pool.Drain(0)
|
||||
wg := sync.WaitGroup{}
|
||||
|
|
@ -379,7 +379,7 @@ func benchmarkBMTBaseline(n int, t *testing.B) {
|
|||
tdata := testDataReader(64)
|
||||
data := make([]byte, 64)
|
||||
tdata.Read(data)
|
||||
hasher := sha3.NewKeccak256
|
||||
hasher := sha3.NewLegacyKeccak256
|
||||
|
||||
t.ReportAllocs()
|
||||
t.ResetTimer()
|
||||
|
|
@ -409,7 +409,7 @@ func benchmarkHasher(n int, t *testing.B) {
|
|||
tdata.Read(data)
|
||||
|
||||
size := 1
|
||||
hasher := sha3.NewKeccak256
|
||||
hasher := sha3.NewLegacyKeccak256
|
||||
segmentCount := 128
|
||||
pool := NewTreePool(hasher, segmentCount, size)
|
||||
bmt := New(pool)
|
||||
|
|
@ -428,7 +428,7 @@ func benchmarkHasherReuse(poolsize, n int, t *testing.B) {
|
|||
data := make([]byte, n)
|
||||
tdata.Read(data)
|
||||
|
||||
hasher := sha3.NewKeccak256
|
||||
hasher := sha3.NewLegacyKeccak256
|
||||
segmentCount := 128
|
||||
pool := NewTreePool(hasher, segmentCount, poolsize)
|
||||
cycles := 200
|
||||
|
|
@ -455,7 +455,7 @@ func benchmarkSHA3(n int, t *testing.B) {
|
|||
data := make([]byte, n)
|
||||
tdata := testDataReader(n)
|
||||
tdata.Read(data)
|
||||
hasher := sha3.NewKeccak256
|
||||
hasher := sha3.NewLegacyKeccak256
|
||||
h := hasher()
|
||||
|
||||
t.ReportAllocs()
|
||||
|
|
@ -471,7 +471,7 @@ func benchmarkRefHasher(n int, t *testing.B) {
|
|||
data := make([]byte, n)
|
||||
tdata := testDataReader(n)
|
||||
tdata.Read(data)
|
||||
hasher := sha3.NewKeccak256
|
||||
hasher := sha3.NewLegacyKeccak256
|
||||
rbmt := NewRefHasher(hasher, 128)
|
||||
|
||||
t.ReportAllocs()
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ func doInstall(cmdline []string) {
|
|||
|
||||
if minor < 21 {
|
||||
log.Println("You have Go version", runtime.Version())
|
||||
log.Println("XDC requires at least Go version 1.21 and cannot")
|
||||
log.Println("XDC requires at least Go version 1.22 and cannot")
|
||||
log.Println("be compiled with an earlier version. Please upgrade your Go installation.")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.21-alpine as builder
|
||||
FROM golang:1.22-alpine as builder
|
||||
|
||||
RUN apk add make build-base linux-headers
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,2 @@
|
|||
enode://207f812067141e038439acbd18a6e3b5f38fcff7de362d8fe0eb5f153f828ae99cae3270ed653beaa197e3946223d9e2f4a22a5e948177209d046fd095b89626@66.94.121.151:30301
|
||||
enode://ec569f5d52cefee5c5405a0c5db720dc7061f3085e0682dd8321413430ddda6a177b85db75b0daf83d2e68760ba3f5beb4ba9e333e7d52072fba4d39b05a0451@194.233.77.19:30301
|
||||
enode://cab457c58bc9b94ea9afa428d018179b4773fe90fec16ef958951f5a23adb9627350cea8b56709351766183d85574fc54ba504816b200fa31675a04c25226e9f@66.94.98.186:30301
|
||||
enode://751de9e39fe0b8f18585bb4a8b50aa5631fe262e14f579753709631eddcac30be901ca0b5a3878b7686838da7ddca2c61e6d2c5eb3745e6b855289e692068e8d@144.126.140.3:30301
|
||||
enode://6bd073ee1085c1dc09427d9f65f0125a75393ac89f0db36f884cc22d61f441403a4c06d8f9a9d3c8e8c08368122bceeeac5f48c83f3d2e87c0da6d5c0eb7cd7e@194.163.167.177:30301
|
||||
enode://00d49d72a48164681906ad61924568da0d3049937efdbaed0b7533e34a99f55814f1839d909cdc82f78e04a36ac04737d80b41b22905c7d6cac3c80bb5cdbbc4@66.94.98.186:30301
|
||||
enode://d6793b02a478f13ed6d01c30778935f6f8f7461a75aebedcb310def4ed9b066f995a0dca046d0c7ea7f5ffdd8e3f1f53c6b6dce909d1693650504921aad62f1a@194.163.167.177:30301
|
||||
|
|
|
|||
|
|
@ -46,17 +46,17 @@ else
|
|||
log_level=$LOG_LEVEL
|
||||
fi
|
||||
|
||||
netstats="${NODE_NAME}-${wallet}-local:xinfin_xdpos_hybrid_network_stats@devnetstats.apothem.network:2000"
|
||||
netstats="${NODE_NAME}-${wallet}-local:xinfin_xdpos_hybrid_network_stats@devnetstats.hashlabs.apothem.network:1999"
|
||||
|
||||
echo "Running a node with wallet: ${wallet} at local"
|
||||
|
||||
../../build/bin/XDC --ethstats ${netstats} --gcmode=archive \
|
||||
--bootnodes ${bootnodes} --syncmode full \
|
||||
--datadir ./tmp/xdcchain --networkid 551 \
|
||||
-port 30303 --rpc --rpccorsdomain "*" --rpcaddr 0.0.0.0 \
|
||||
--rpcport 8545 \
|
||||
--rpcapi db,eth,debug,miner,net,shh,txpool,personal,web3,XDPoS \
|
||||
--rpcvhosts "*" --unlock "${wallet}" --password ./tmp/.pwd --mine \
|
||||
--gasprice "1" --targetgaslimit "420000000" --verbosity ${log_level} \
|
||||
--ws --wsaddr=0.0.0.0 --wsport 8555 \
|
||||
--wsorigins "*" 2>&1 >>./tmp/xdc.log
|
||||
--port 30303 --http --http-corsdomain "*" --http-addr 0.0.0.0 \
|
||||
--http-port 8545 \
|
||||
--http-api db,eth,debug,miner,net,shh,txpool,personal,web3,XDPoS \
|
||||
--http-vhosts "*" --unlock "${wallet}" --password ./tmp/.pwd --mine \
|
||||
--miner-gasprice "1" --miner-gaslimit "420000000" --verbosity ${log_level} \
|
||||
--ws --ws-addr=0.0.0.0 --ws-port 8555 \
|
||||
--ws-origins "*" 2>&1 >>./tmp/xdc.log
|
||||
|
|
|
|||
|
|
@ -24,6 +24,13 @@ do
|
|||
bootnodes="${bootnodes},$line"
|
||||
fi
|
||||
done < "$input"
|
||||
#check last line since it's not included in "read" command https://stackoverflow.com/questions/12916352/shell-script-read-missing-last-line
|
||||
if [ -z "${bootnodes}" ]
|
||||
then
|
||||
bootnodes=$line
|
||||
else
|
||||
bootnodes="${bootnodes},$line"
|
||||
fi
|
||||
|
||||
log_level=3
|
||||
if test -z "$LOG_LEVEL"
|
||||
|
|
@ -62,7 +69,7 @@ else
|
|||
fi
|
||||
|
||||
INSTANCE_IP=$(curl https://checkip.amazonaws.com)
|
||||
netstats="${NODE_NAME}-${wallet}-${INSTANCE_IP}:xinfin_xdpos_hybrid_network_stats@devnetstats.apothem.network:2000"
|
||||
netstats="${NODE_NAME}-${wallet}-${INSTANCE_IP}:xinfin_xdpos_hybrid_network_stats@devnetstats.hashlabs.apothem.network:1999"
|
||||
|
||||
|
||||
echo "Running a node with wallet: ${wallet} at IP: ${INSTANCE_IP}"
|
||||
|
|
@ -75,11 +82,12 @@ XDC --ethstats ${netstats} --gcmode archive \
|
|||
--nat extip:${INSTANCE_IP} \
|
||||
--bootnodes ${bootnodes} --syncmode full \
|
||||
--datadir /work/xdcchain --networkid 551 \
|
||||
-port $port --rpc --rpccorsdomain "*" --rpcaddr 0.0.0.0 \
|
||||
--rpcport $rpc_port \
|
||||
--rpcapi db,eth,debug,net,shh,txpool,personal,web3,XDPoS \
|
||||
--rpcvhosts "*" --unlock "${wallet}" --password /work/.pwd --mine \
|
||||
--gasprice "1" --targetgaslimit "420000000" --verbosity ${log_level} \
|
||||
--port $port --http --http-corsdomain "*" --http-addr 0.0.0.0 \
|
||||
--http-port $rpc_port \
|
||||
--http-api db,eth,debug,net,shh,txpool,personal,web3,XDPoS \
|
||||
--http-vhosts "*" --unlock "${wallet}" --password /work/.pwd --mine \
|
||||
--miner-gasprice "1" --miner-gaslimit "420000000" --verbosity ${log_level} \
|
||||
--debugdatadir /work/xdcchain \
|
||||
--ws --wsaddr=0.0.0.0 --wsport $ws_port \
|
||||
--wsorigins "*" 2>&1 >>/work/xdcchain/xdc.log | tee -a /work/xdcchain/xdc.log
|
||||
--store-reward \
|
||||
--ws --ws-addr=0.0.0.0 --ws-port $ws_port \
|
||||
--ws-origins "*" 2>&1 >>/work/xdcchain/xdc.log | tee -a /work/xdcchain/xdc.log
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ terraform {
|
|||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = "~> 5.13.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ terraform {
|
|||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = "~> 5.13.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
# Bucket need to be created first. If first time run terraform init, need to comment out the below section
|
||||
terraform {
|
||||
backend "s3" {
|
||||
bucket = "tf-xinfin-bucket" // This name need to be updated to be the same as local.s3BucketName. We can't use variable here.
|
||||
|
|
|
|||
|
|
@ -5,15 +5,6 @@ variable docker_tag {
|
|||
}
|
||||
|
||||
locals {
|
||||
/**
|
||||
Load the nodes data from s3
|
||||
Below is the the format the config needs to follow:
|
||||
{{Name of the node, in a pattern of 'xdc'+ number. i.e xdc50}}: {
|
||||
pk: {{Value of the node private key}},
|
||||
... any other configuration we want to pass.
|
||||
}
|
||||
Note: No `n` is allowed in the node name
|
||||
**/
|
||||
predefinedNodesConfig = jsondecode(data.aws_s3_object.devnet_xdc_node_config.body)
|
||||
envs = { for tuple in regexall("(.*)=(.*)", file(".env")) : tuple[0] => tuple[1] }
|
||||
logLevel = local.envs["log_level"]
|
||||
|
|
@ -37,12 +28,12 @@ locals {
|
|||
]
|
||||
|
||||
keyNames = {
|
||||
for r in local.regions :
|
||||
for r in local.regions :
|
||||
r.name => [for i in range(r.start, r.end+1) : "xdc${i}"]
|
||||
}
|
||||
|
||||
devnetNodeKeys = {
|
||||
for r in local.regions :
|
||||
for r in local.regions :
|
||||
r.name => { for i in local.keyNames[r.name]: i => local.predefinedNodesConfig[i] }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,13 @@ do
|
|||
bootnodes="${bootnodes},$line"
|
||||
fi
|
||||
done < "$input"
|
||||
#check last line since it's not included in "read" command https://stackoverflow.com/questions/12916352/shell-script-read-missing-last-line
|
||||
if [ -z "${bootnodes}" ]
|
||||
then
|
||||
bootnodes=$line
|
||||
else
|
||||
bootnodes="${bootnodes},$line"
|
||||
fi
|
||||
|
||||
log_level=3
|
||||
if test -z "$LOG_LEVEL"
|
||||
|
|
@ -74,11 +81,12 @@ XDC --ethstats ${netstats} --gcmode archive \
|
|||
--nat extip:${INSTANCE_IP} \
|
||||
--bootnodes ${bootnodes} --syncmode full \
|
||||
--datadir /work/xdcchain --networkid 50 \
|
||||
-port $port --rpc --rpccorsdomain "*" --rpcaddr 0.0.0.0 \
|
||||
--rpcport $rpc_port \
|
||||
--rpcapi db,eth,debug,net,shh,txpool,personal,web3,XDPoS \
|
||||
--rpcvhosts "*" --unlock "${wallet}" --password /work/.pwd --mine \
|
||||
--gasprice "1" --targetgaslimit "420000000" --verbosity ${log_level} \
|
||||
--port $port --http --http-corsdomain "*" --http-addr 0.0.0.0 \
|
||||
--http-port $rpc_port \
|
||||
--http-api db,eth,debug,net,shh,txpool,personal,web3,XDPoS \
|
||||
--http-vhosts "*" --unlock "${wallet}" --password /work/.pwd --mine \
|
||||
--miner-gasprice "1" --miner-gaslimit "420000000" --verbosity ${log_level} \
|
||||
--debugdatadir /work/xdcchain \
|
||||
--ws --wsaddr=0.0.0.0 --wsport $ws_port \
|
||||
--wsorigins "*" 2>&1 >>/work/xdcchain/xdc.log | tee -a /work/xdcchain/xdc.log
|
||||
--store-reward \
|
||||
--ws --ws-addr=0.0.0.0 --ws-port $ws_port \
|
||||
--ws-origins "*" 2>&1 >>/work/xdcchain/xdc.log | tee -a /work/xdcchain/xdc.log
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ provider "aws" {
|
|||
region = "us-east-1"
|
||||
}
|
||||
|
||||
# WARNING: APSE-1 will only be used to host rpc node
|
||||
# Workaround to avoid conflicts with existing ecs cluster in existing regions
|
||||
provider "aws" {
|
||||
alias = "ap-southeast-1"
|
||||
region = "ap-southeast-1"
|
||||
|
|
@ -25,9 +23,9 @@ module "devnet_rpc" {
|
|||
vpc_id = local.vpc_id
|
||||
aws_subnet_id = local.aws_subnet_id
|
||||
ami_id = local.ami_id
|
||||
instance_type = "t3.xlarge"
|
||||
instance_type = "t3.large"
|
||||
ssh_key_name = local.ssh_key_name
|
||||
rpc_image = local.rpc_image
|
||||
rpc_image = local.rpc_image
|
||||
volume_size = 1500
|
||||
|
||||
providers = {
|
||||
|
|
@ -43,7 +41,7 @@ module "testnet_rpc" {
|
|||
ami_id = local.ami_id
|
||||
instance_type = "t3.large"
|
||||
ssh_key_name = local.ssh_key_name
|
||||
rpc_image = local.rpc_image
|
||||
rpc_image = local.rpc_image
|
||||
volume_size = 1500
|
||||
|
||||
providers = {
|
||||
|
|
@ -59,7 +57,7 @@ module "mainnet_rpc" {
|
|||
ami_id = local.ami_id
|
||||
instance_type = "t3.large"
|
||||
ssh_key_name = local.ssh_key_name
|
||||
rpc_image = local.rpc_image
|
||||
rpc_image = local.rpc_image
|
||||
volume_size = 3000
|
||||
|
||||
providers = {
|
||||
|
|
|
|||
|
|
@ -1,41 +1,14 @@
|
|||
locals {
|
||||
/**
|
||||
Load the nodes data from s3
|
||||
Below is the the format the config needs to follow:
|
||||
{{Name of the node, in a pattern of 'xdc'+ number. i.e xdc50}}: {
|
||||
pk: {{Value of the node private key}},
|
||||
... any other configuration we want to pass.
|
||||
}
|
||||
Note: No `n` is allowed in the node name
|
||||
**/
|
||||
predefinedNodesConfig = jsondecode(data.aws_s3_object.xdc_node_config.body)
|
||||
envs = { for tuple in regexall("(.*)=(.*)", file(".env")) : tuple[0] => tuple[1] }
|
||||
logLevel = local.envs["log_level"]
|
||||
|
||||
# regions = [
|
||||
# {
|
||||
# "name": "us-east-2", // Ohio
|
||||
# "start": local.envs["us_east_2_start"],
|
||||
# "end": local.envs["us_east_2_end"],
|
||||
# }
|
||||
# ]
|
||||
|
||||
# keyNames = {
|
||||
# for r in local.regions :
|
||||
# r.name => [for i in range(r.start, r.end+1) : "xdc${i}"]
|
||||
# }
|
||||
|
||||
# nodeKeys = {
|
||||
# for r in local.regions :
|
||||
# r.name => { for i in local.keyNames[r.name]: i => local.predefinedNodesConfig[i] }
|
||||
# }
|
||||
|
||||
rpcDevnetNodeKeys = { "devnet-rpc1": local.predefinedNodesConfig["devnet-rpc1"]} // we hardcode the rpc to a single node for now
|
||||
rpcTestnetNodeKeys = { "testnet-rpc1": local.predefinedNodesConfig["testnet-rpc1"]} // we hardcode the rpc to a single node for now
|
||||
rpcMainnetNodeKeys = { "mainnet-rpc1": local.predefinedNodesConfig["mainnet-rpc1"]} // we hardcode the rpc to a single node for now
|
||||
}
|
||||
|
||||
locals { //ec2_rpc values
|
||||
locals {
|
||||
ami_id = "ami-097c4e1feeea169e5"
|
||||
rpc_image = "xinfinorg/xdposchain:v2.2.0-beta1"
|
||||
vpc_id = "vpc-20a06846"
|
||||
|
|
|
|||
|
|
@ -25,6 +25,13 @@ do
|
|||
bootnodes="${bootnodes},$line"
|
||||
fi
|
||||
done < "$input"
|
||||
#check last line since it's not included in "read" command https://stackoverflow.com/questions/12916352/shell-script-read-missing-last-line
|
||||
if [ -z "${bootnodes}" ]
|
||||
then
|
||||
bootnodes=$line
|
||||
else
|
||||
bootnodes="${bootnodes},$line"
|
||||
fi
|
||||
|
||||
log_level=3
|
||||
if test -z "$LOG_LEVEL"
|
||||
|
|
@ -76,11 +83,12 @@ XDC --ethstats ${netstats} --gcmode archive \
|
|||
--nat extip:${INSTANCE_IP} \
|
||||
--bootnodes ${bootnodes} --syncmode full \
|
||||
--datadir /work/xdcchain --networkid 51 \
|
||||
-port $port --rpc --rpccorsdomain "*" --rpcaddr 0.0.0.0 \
|
||||
--rpcport $rpc_port \
|
||||
--rpcapi db,eth,debug,net,shh,txpool,personal,web3,XDPoS \
|
||||
--rpcvhosts "*" --unlock "${wallet}" --password /work/.pwd --mine \
|
||||
--gasprice "1" --targetgaslimit "420000000" --verbosity ${log_level} \
|
||||
--port $port --http --http-corsdomain "*" --http-addr 0.0.0.0 \
|
||||
--http-port $rpc_port \
|
||||
--http-api db,eth,debug,net,shh,txpool,personal,web3,XDPoS \
|
||||
--http-vhosts "*" --unlock "${wallet}" --password /work/.pwd --mine \
|
||||
--miner-gasprice "1" --miner-gaslimit "420000000" --verbosity ${log_level} \
|
||||
--debugdatadir /work/xdcchain \
|
||||
--ws --wsaddr=0.0.0.0 --wsport $ws_port \
|
||||
--wsorigins "*" 2>&1 >>/work/xdcchain/xdc.log | tee -a /work/xdcchain/xdc.log
|
||||
--store-reward \
|
||||
--ws --ws-addr=0.0.0.0 --ws-port $ws_port \
|
||||
--ws-origins "*" 2>&1 >>/work/xdcchain/xdc.log | tee -a /work/xdcchain/xdc.log
|
||||
|
|
|
|||
|
|
@ -26,31 +26,31 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/console"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
walletCommand = cli.Command{
|
||||
walletCommand = &cli.Command{
|
||||
Name: "wallet",
|
||||
Usage: "Manage XDPoSChain presale wallets",
|
||||
ArgsUsage: "",
|
||||
Category: "ACCOUNT COMMANDS",
|
||||
Description: `
|
||||
XDC wallet import /path/to/my/presale.wallet
|
||||
|
||||
will prompt for your password and imports your ether presale account.
|
||||
It can be used non-interactively with the --password option taking a
|
||||
passwordfile as argument containing the wallet password in plaintext.`,
|
||||
Subcommands: []cli.Command{
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
|
||||
Name: "import",
|
||||
Usage: "Import XDPoSChain presale wallet",
|
||||
ArgsUsage: "<keyFile>",
|
||||
Action: utils.MigrateFlags(importWallet),
|
||||
Action: importWallet,
|
||||
Category: "ACCOUNT COMMANDS",
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.XDCXDataDirFlag,
|
||||
utils.KeyStoreDirFlag,
|
||||
utils.PasswordFileFlag,
|
||||
utils.LightKDFFlag,
|
||||
|
|
@ -65,10 +65,9 @@ passwordfile as argument containing the wallet password in plaintext.`,
|
|||
},
|
||||
}
|
||||
|
||||
accountCommand = cli.Command{
|
||||
Name: "account",
|
||||
Usage: "Manage accounts",
|
||||
Category: "ACCOUNT COMMANDS",
|
||||
accountCommand = &cli.Command{
|
||||
Name: "account",
|
||||
Usage: "Manage accounts",
|
||||
Description: `
|
||||
|
||||
Manage accounts, list all existing accounts, import a private key into a new
|
||||
|
|
@ -89,13 +88,14 @@ It is safe to transfer the entire directory or the individual keys therein
|
|||
between ethereum nodes by simply copying.
|
||||
|
||||
Make sure you backup your keys regularly.`,
|
||||
Subcommands: []cli.Command{
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "list",
|
||||
Usage: "Print summary of existing accounts",
|
||||
Action: utils.MigrateFlags(accountList),
|
||||
Action: accountList,
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.XDCXDataDirFlag,
|
||||
utils.KeyStoreDirFlag,
|
||||
},
|
||||
Description: `
|
||||
|
|
@ -104,9 +104,10 @@ Print a short summary of all accounts`,
|
|||
{
|
||||
Name: "new",
|
||||
Usage: "Create a new account",
|
||||
Action: utils.MigrateFlags(accountCreate),
|
||||
Action: accountCreate,
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.XDCXDataDirFlag,
|
||||
utils.KeyStoreDirFlag,
|
||||
utils.PasswordFileFlag,
|
||||
utils.LightKDFFlag,
|
||||
|
|
@ -129,10 +130,11 @@ password to file or expose in any other way.
|
|||
{
|
||||
Name: "update",
|
||||
Usage: "Update an existing account",
|
||||
Action: utils.MigrateFlags(accountUpdate),
|
||||
Action: accountUpdate,
|
||||
ArgsUsage: "<address>",
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.XDCXDataDirFlag,
|
||||
utils.KeyStoreDirFlag,
|
||||
utils.LightKDFFlag,
|
||||
},
|
||||
|
|
@ -158,9 +160,10 @@ changing your password is only possible interactively.
|
|||
{
|
||||
Name: "import",
|
||||
Usage: "Import a private key into a new account",
|
||||
Action: utils.MigrateFlags(accountImport),
|
||||
Action: accountImport,
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.XDCXDataDirFlag,
|
||||
utils.KeyStoreDirFlag,
|
||||
utils.PasswordFileFlag,
|
||||
utils.LightKDFFlag,
|
||||
|
|
@ -293,7 +296,7 @@ func ambiguousAddrRecovery(ks *keystore.KeyStore, err *keystore.AmbiguousAddrErr
|
|||
func accountCreate(ctx *cli.Context) error {
|
||||
cfg := XDCConfig{Node: defaultNodeConfig()}
|
||||
// Load config file.
|
||||
if file := ctx.GlobalString(configFileFlag.Name); file != "" {
|
||||
if file := ctx.String(configFileFlag.Name); file != "" {
|
||||
if err := loadConfig(file, &cfg); err != nil {
|
||||
utils.Fatalf("%v", err)
|
||||
}
|
||||
|
|
@ -319,13 +322,13 @@ func accountCreate(ctx *cli.Context) error {
|
|||
// accountUpdate transitions an account from a previous format to the current
|
||||
// one, also providing the possibility to change the pass-phrase.
|
||||
func accountUpdate(ctx *cli.Context) error {
|
||||
if len(ctx.Args()) == 0 {
|
||||
if ctx.Args().Len() == 0 {
|
||||
utils.Fatalf("No accounts specified to update")
|
||||
}
|
||||
stack, _ := makeConfigNode(ctx)
|
||||
ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
|
||||
|
||||
for _, addr := range ctx.Args() {
|
||||
for _, addr := range ctx.Args().Slice() {
|
||||
account, oldPassword := unlockAccount(ctx, ks, addr, 0, nil)
|
||||
newPassword := getPassPhrase("Please give a new password. Do not forget this password.", true, 0, nil)
|
||||
if err := ks.Update(account, oldPassword, newPassword); err != nil {
|
||||
|
|
@ -336,10 +339,10 @@ func accountUpdate(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
func importWallet(ctx *cli.Context) error {
|
||||
keyfile := ctx.Args().First()
|
||||
if len(keyfile) == 0 {
|
||||
utils.Fatalf("keyfile must be given as argument")
|
||||
if ctx.Args().Len() != 1 {
|
||||
utils.Fatalf("keyfile must be given as the only argument")
|
||||
}
|
||||
keyfile := ctx.Args().First()
|
||||
keyJson, err := os.ReadFile(keyfile)
|
||||
if err != nil {
|
||||
utils.Fatalf("Could not read wallet file: %v", err)
|
||||
|
|
@ -358,10 +361,10 @@ func importWallet(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
func accountImport(ctx *cli.Context) error {
|
||||
keyfile := ctx.Args().First()
|
||||
if len(keyfile) == 0 {
|
||||
utils.Fatalf("keyfile must be given as argument")
|
||||
if ctx.Args().Len() != 1 {
|
||||
utils.Fatalf("keyfile must be given as the only argument")
|
||||
}
|
||||
keyfile := ctx.Args().First()
|
||||
key, err := crypto.LoadECDSA(keyfile)
|
||||
if err != nil {
|
||||
utils.Fatalf("Failed to load the private key: %v", err)
|
||||
|
|
|
|||
|
|
@ -43,26 +43,31 @@ func tmpDatadirWithKeystore(t *testing.T) string {
|
|||
}
|
||||
|
||||
func TestAccountListEmpty(t *testing.T) {
|
||||
XDC := runXDC(t, "account", "list")
|
||||
datadir := tmpdir(t)
|
||||
defer os.RemoveAll(datadir)
|
||||
XDC := runXDC(t, "account", "list", "--datadir", datadir)
|
||||
XDC.ExpectExit()
|
||||
}
|
||||
|
||||
func TestAccountList(t *testing.T) {
|
||||
datadir := tmpDatadirWithKeystore(t)
|
||||
XDC := runXDC(t, "account", "list", "--datadir", datadir)
|
||||
defer XDC.ExpectExit()
|
||||
if runtime.GOOS == "windows" {
|
||||
XDC.Expect(`
|
||||
Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore://{{.Datadir}}\keystore\UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8
|
||||
Account #1: {f466859ead1932d743d622cb74fc058882e8648a} keystore://{{.Datadir}}\keystore\aaa
|
||||
Account #2: {289d485d9771714cce91d3393d764e1311907acc} keystore://{{.Datadir}}\keystore\zzz
|
||||
`)
|
||||
} else {
|
||||
XDC.Expect(`
|
||||
defer os.RemoveAll(datadir)
|
||||
var want = `
|
||||
Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore://{{.Datadir}}/keystore/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8
|
||||
Account #1: {f466859ead1932d743d622cb74fc058882e8648a} keystore://{{.Datadir}}/keystore/aaa
|
||||
Account #2: {289d485d9771714cce91d3393d764e1311907acc} keystore://{{.Datadir}}/keystore/zzz
|
||||
`)
|
||||
`
|
||||
if runtime.GOOS == "windows" {
|
||||
want = `
|
||||
Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore://{{.Datadir}}\keystore\UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8
|
||||
Account #1: {f466859ead1932d743d622cb74fc058882e8648a} keystore://{{.Datadir}}\keystore\aaa
|
||||
Account #2: {289d485d9771714cce91d3393d764e1311907acc} keystore://{{.Datadir}}\keystore\zzz
|
||||
`
|
||||
}
|
||||
{
|
||||
geth := runXDC(t, "account", "list", "--datadir", datadir)
|
||||
geth.Expect(want)
|
||||
geth.ExpectExit()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -92,9 +97,8 @@ Fatal: Passphrases do not match
|
|||
|
||||
func TestAccountUpdate(t *testing.T) {
|
||||
datadir := tmpDatadirWithKeystore(t)
|
||||
XDC := runXDC(t, "account", "update",
|
||||
"--datadir", datadir, "--lightkdf",
|
||||
"f466859ead1932d743d622cb74fc058882e8648a")
|
||||
defer os.RemoveAll(datadir)
|
||||
XDC := runXDC(t, "account", "update", "--datadir", datadir, "--lightkdf", "f466859ead1932d743d622cb74fc058882e8648a")
|
||||
defer XDC.ExpectExit()
|
||||
XDC.Expect(`
|
||||
Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
|
||||
|
|
@ -107,7 +111,9 @@ Repeat passphrase: {{.InputLine "foobar2"}}
|
|||
}
|
||||
|
||||
func TestWalletImport(t *testing.T) {
|
||||
XDC := runXDC(t, "wallet", "import", "--lightkdf", "testdata/guswallet.json")
|
||||
datadir := tmpdir(t)
|
||||
defer os.RemoveAll(datadir)
|
||||
XDC := runXDC(t, "wallet", "import", "--datadir", datadir, "--lightkdf", "testdata/guswallet.json")
|
||||
defer XDC.ExpectExit()
|
||||
XDC.Expect(`
|
||||
!! Unsupported terminal, password will be echoed.
|
||||
|
|
@ -121,6 +127,36 @@ Address: {xdcd4584b5f6229b7be90727b0fc8c6b91bb427821f}
|
|||
}
|
||||
}
|
||||
|
||||
func TestAccountHelp(t *testing.T) {
|
||||
geth := runXDC(t, "account", "-h")
|
||||
geth.WaitExit()
|
||||
if have, want := geth.ExitStatus(), 0; have != want {
|
||||
t.Errorf("exit error, have %d want %d", have, want)
|
||||
}
|
||||
|
||||
geth = runXDC(t, "account", "import", "-h")
|
||||
geth.WaitExit()
|
||||
if have, want := geth.ExitStatus(), 0; have != want {
|
||||
t.Errorf("exit error, have %d want %d", have, want)
|
||||
}
|
||||
}
|
||||
|
||||
func importAccountWithExpect(t *testing.T, key string, expected string) {
|
||||
dir := t.TempDir()
|
||||
defer os.RemoveAll(dir)
|
||||
keyfile := filepath.Join(dir, "key.prv")
|
||||
if err := os.WriteFile(keyfile, []byte(key), 0600); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
passwordFile := filepath.Join(dir, "password.txt")
|
||||
if err := os.WriteFile(passwordFile, []byte("foobar"), 0600); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
geth := runXDC(t, "account", "import", "--lightkdf", "-password", passwordFile, keyfile)
|
||||
defer geth.ExpectExit()
|
||||
geth.Expect(expected)
|
||||
}
|
||||
|
||||
func TestWalletImportBadPassword(t *testing.T) {
|
||||
XDC := runXDC(t, "wallet", "import", "--lightkdf", "testdata/guswallet.json")
|
||||
defer XDC.ExpectExit()
|
||||
|
|
@ -133,10 +169,11 @@ Fatal: could not decrypt key with given passphrase
|
|||
|
||||
func TestUnlockFlag(t *testing.T) {
|
||||
datadir := tmpDatadirWithKeystore(t)
|
||||
defer os.RemoveAll(datadir)
|
||||
XDC := runXDC(t,
|
||||
"--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0",
|
||||
"--unlock", "f466859ead1932d743d622cb74fc058882e8648a",
|
||||
"js", "testdata/empty.js")
|
||||
"js", "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0",
|
||||
"--port", "0", "--unlock", "f466859ead1932d743d622cb74fc058882e8648a",
|
||||
"testdata/empty.js")
|
||||
XDC.Expect(`
|
||||
Unlocking account f466859ead1932d743d622cb74fc058882e8648a | Attempt 1/3
|
||||
!! Unsupported terminal, password will be echoed.
|
||||
|
|
@ -157,6 +194,7 @@ Passphrase: {{.InputLine "foobar"}}
|
|||
|
||||
func TestUnlockFlagWrongPassword(t *testing.T) {
|
||||
datadir := tmpDatadirWithKeystore(t)
|
||||
defer os.RemoveAll(datadir)
|
||||
XDC := runXDC(t,
|
||||
"--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0",
|
||||
"--unlock", "f466859ead1932d743d622cb74fc058882e8648a")
|
||||
|
|
@ -176,10 +214,11 @@ Fatal: Failed to unlock account f466859ead1932d743d622cb74fc058882e8648a (could
|
|||
// https://github.com/XinFinOrg/XDPoSChain/issues/1785
|
||||
func TestUnlockFlagMultiIndex(t *testing.T) {
|
||||
datadir := tmpDatadirWithKeystore(t)
|
||||
defer os.RemoveAll(datadir)
|
||||
XDC := runXDC(t,
|
||||
"--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0",
|
||||
"--unlock", "0,2",
|
||||
"js", "testdata/empty.js")
|
||||
"js", "--datadir", datadir, "--nat", "none", "--nodiscover",
|
||||
"--maxpeers", "0", "--port", "0", "--unlock", "0,2",
|
||||
"testdata/empty.js")
|
||||
XDC.Expect(`
|
||||
Unlocking account 0 | Attempt 1/3
|
||||
!! Unsupported terminal, password will be echoed.
|
||||
|
|
@ -203,10 +242,11 @@ Passphrase: {{.InputLine "foobar"}}
|
|||
|
||||
func TestUnlockFlagPasswordFile(t *testing.T) {
|
||||
datadir := tmpDatadirWithKeystore(t)
|
||||
defer os.RemoveAll(datadir)
|
||||
XDC := runXDC(t,
|
||||
"--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0",
|
||||
"--password", "testdata/passwords.txt", "--unlock", "0,2",
|
||||
"js", "testdata/empty.js")
|
||||
"js", "--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0",
|
||||
"--port", "0", "--password", "testdata/passwords.txt", "--unlock", "0,2",
|
||||
"testdata/empty.js")
|
||||
XDC.ExpectExit()
|
||||
|
||||
wantMessages := []string{
|
||||
|
|
@ -223,6 +263,7 @@ func TestUnlockFlagPasswordFile(t *testing.T) {
|
|||
|
||||
func TestUnlockFlagPasswordFileWrongPassword(t *testing.T) {
|
||||
datadir := tmpDatadirWithKeystore(t)
|
||||
defer os.RemoveAll(datadir)
|
||||
XDC := runXDC(t,
|
||||
"--datadir", datadir, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0",
|
||||
"--password", "testdata/wrong-passwords.txt", "--unlock", "0,2")
|
||||
|
|
@ -235,9 +276,9 @@ 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")
|
||||
XDC := runXDC(t,
|
||||
"--keystore", store, "--nat", "none", "--nodiscover", "--maxpeers", "0", "--port", "0",
|
||||
"--unlock", "f466859ead1932d743d622cb74fc058882e8648a",
|
||||
"js", "testdata/empty.js")
|
||||
"js", "--keystore", store, "--nat", "none", "--nodiscover", "--maxpeers", "0",
|
||||
"--port", "0", "--unlock", "f466859ead1932d743d622cb74fc058882e8648a",
|
||||
"testdata/empty.js")
|
||||
defer XDC.ExpectExit()
|
||||
|
||||
// Helper for the expect template, returns absolute keystore path.
|
||||
|
|
|
|||
|
|
@ -28,17 +28,14 @@ import (
|
|||
|
||||
"github.com/XinFinOrg/XDPoSChain/cmd/internal/browser"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/cmd/utils"
|
||||
cli "gopkg.in/urfave/cli.v1"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var bugCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(reportBug),
|
||||
var bugCommand = &cli.Command{
|
||||
Action: reportBug,
|
||||
Name: "bug",
|
||||
Usage: "opens a window to report a bug on the XDC repo",
|
||||
ArgsUsage: " ",
|
||||
Category: "MISCELLANEOUS COMMANDS",
|
||||
}
|
||||
|
||||
const issueUrl = "https://github.com/XinFinOrg/XDPoSChain/issues/new"
|
||||
|
|
|
|||
|
|
@ -35,22 +35,21 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
|
||||
"github.com/XinFinOrg/XDPoSChain/event"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/XinFinOrg/XDPoSChain/metrics"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
initCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(initGenesis),
|
||||
initCommand = &cli.Command{
|
||||
Action: initGenesis,
|
||||
Name: "init",
|
||||
Usage: "Bootstrap and initialize a new genesis block",
|
||||
ArgsUsage: "<genesisPath>",
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.XDCXDataDirFlag,
|
||||
utils.LightModeFlag,
|
||||
utils.XDCTestnetFlag,
|
||||
},
|
||||
Category: "BLOCKCHAIN COMMANDS",
|
||||
Description: `
|
||||
The init command initializes a new genesis block and definition for the network.
|
||||
This is a destructive action and changes the network in which you will be
|
||||
|
|
@ -58,20 +57,32 @@ participating.
|
|||
|
||||
It expects the genesis file as argument.`,
|
||||
}
|
||||
importCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(importChain),
|
||||
importCommand = &cli.Command{
|
||||
Action: importChain,
|
||||
Name: "import",
|
||||
Usage: "Import a blockchain file",
|
||||
ArgsUsage: "<filename> (<filename 2> ... <filename N>) ",
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.XDCXDataDirFlag,
|
||||
utils.CacheFlag,
|
||||
utils.LightModeFlag,
|
||||
utils.GCModeFlag,
|
||||
utils.CacheDatabaseFlag,
|
||||
utils.CacheGCFlag,
|
||||
utils.MetricsEnabledFlag,
|
||||
utils.MetricsEnabledExpensiveFlag,
|
||||
utils.MetricsEnableInfluxDBFlag,
|
||||
utils.MetricsEnableInfluxDBV2Flag,
|
||||
utils.MetricsInfluxDBEndpointFlag,
|
||||
utils.MetricsInfluxDBDatabaseFlag,
|
||||
utils.MetricsInfluxDBUsernameFlag,
|
||||
utils.MetricsInfluxDBPasswordFlag,
|
||||
utils.MetricsInfluxDBTagsFlag,
|
||||
utils.MetricsInfluxDBTokenFlag,
|
||||
utils.MetricsInfluxDBBucketFlag,
|
||||
utils.MetricsInfluxDBOrganizationFlag,
|
||||
},
|
||||
Category: "BLOCKCHAIN COMMANDS",
|
||||
Description: `
|
||||
The import command imports blocks from an RLP-encoded form. The form can be one file
|
||||
with several RLP-encoded blocks, or several files can be used.
|
||||
|
|
@ -79,30 +90,31 @@ with several RLP-encoded blocks, or several files can be used.
|
|||
If only one file is used, import error will result in failure. If several files are used,
|
||||
processing will proceed even if an individual RLP-file import failure occurs.`,
|
||||
}
|
||||
exportCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(exportChain),
|
||||
exportCommand = &cli.Command{
|
||||
Action: exportChain,
|
||||
Name: "export",
|
||||
Usage: "Export blockchain into file",
|
||||
ArgsUsage: "<filename> [<blockNumFirst> <blockNumLast>]",
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.XDCXDataDirFlag,
|
||||
utils.CacheFlag,
|
||||
utils.LightModeFlag,
|
||||
},
|
||||
Category: "BLOCKCHAIN COMMANDS",
|
||||
Description: `
|
||||
Requires a first argument of the file to write to.
|
||||
Optional second and third arguments control the first and
|
||||
last block to write. In this mode, the file will be appended
|
||||
if already existing.`,
|
||||
}
|
||||
importPreimagesCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(importPreimages),
|
||||
importPreimagesCommand = &cli.Command{
|
||||
Action: importPreimages,
|
||||
Name: "import-preimages",
|
||||
Usage: "Import the preimage database from an RLP stream",
|
||||
ArgsUsage: "<datafile>",
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.XDCXDataDirFlag,
|
||||
utils.CacheFlag,
|
||||
utils.LightModeFlag,
|
||||
},
|
||||
|
|
@ -110,57 +122,58 @@ if already existing.`,
|
|||
Description: `
|
||||
The import-preimages command imports hash preimages from an RLP encoded stream.`,
|
||||
}
|
||||
exportPreimagesCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(exportPreimages),
|
||||
exportPreimagesCommand = &cli.Command{
|
||||
Action: exportPreimages,
|
||||
Name: "export-preimages",
|
||||
Usage: "Export the preimage database into an RLP stream",
|
||||
ArgsUsage: "<dumpfile>",
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.XDCXDataDirFlag,
|
||||
utils.CacheFlag,
|
||||
utils.LightModeFlag,
|
||||
},
|
||||
Category: "BLOCKCHAIN COMMANDS",
|
||||
Description: `
|
||||
The export-preimages command export hash preimages to an RLP encoded stream`,
|
||||
}
|
||||
copydbCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(copyDb),
|
||||
copydbCommand = &cli.Command{
|
||||
Action: copyDb,
|
||||
Name: "copydb",
|
||||
Usage: "Create a local chain from a target chaindata folder",
|
||||
ArgsUsage: "<sourceChaindataDir>",
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.XDCXDataDirFlag,
|
||||
utils.CacheFlag,
|
||||
utils.SyncModeFlag,
|
||||
utils.FakePoWFlag,
|
||||
utils.TestnetFlag,
|
||||
utils.RinkebyFlag,
|
||||
},
|
||||
Category: "BLOCKCHAIN COMMANDS",
|
||||
Description: `
|
||||
The first argument must be the directory containing the blockchain to download from`,
|
||||
}
|
||||
removedbCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(removeDB),
|
||||
removedbCommand = &cli.Command{
|
||||
Action: removeDB,
|
||||
Name: "removedb",
|
||||
Usage: "Remove blockchain and state databases",
|
||||
ArgsUsage: " ",
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.XDCXDataDirFlag,
|
||||
utils.LightModeFlag,
|
||||
},
|
||||
Category: "BLOCKCHAIN COMMANDS",
|
||||
Description: `
|
||||
Remove blockchain and state databases`,
|
||||
}
|
||||
dumpCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(dump),
|
||||
dumpCommand = &cli.Command{
|
||||
Action: dump,
|
||||
Name: "dump",
|
||||
Usage: "Dump a specific block from storage",
|
||||
ArgsUsage: "[<blockHash> | <blockNum>]...",
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.XDCXDataDirFlag,
|
||||
utils.CacheFlag,
|
||||
utils.LightModeFlag,
|
||||
},
|
||||
|
|
@ -174,12 +187,10 @@ Use "ethereum dump 0" to dump the genesis block.`,
|
|||
// initGenesis will initialise the given JSON format genesis file and writes it as
|
||||
// the zero'd block (i.e. genesis) or will fail hard if it can't succeed.
|
||||
func initGenesis(ctx *cli.Context) error {
|
||||
// Make sure we have a valid genesis JSON
|
||||
genesisPath := ctx.Args().First()
|
||||
genesis := new(core.Genesis)
|
||||
|
||||
if ctx.GlobalBool(utils.XDCTestnetFlag.Name) {
|
||||
if len(genesisPath) > 0 {
|
||||
if ctx.Bool(utils.XDCTestnetFlag.Name) {
|
||||
if ctx.Args().Len() > 0 {
|
||||
utils.Fatalf("Flags --apothem and genesis file can't be used at the same time")
|
||||
}
|
||||
err := json.Unmarshal(apothemGenesis, &genesis)
|
||||
|
|
@ -187,8 +198,12 @@ func initGenesis(ctx *cli.Context) error {
|
|||
utils.Fatalf("invalid genesis json: %v", err)
|
||||
}
|
||||
} else {
|
||||
if ctx.Args().Len() != 1 {
|
||||
utils.Fatalf("need genesis.json file as the only argument")
|
||||
}
|
||||
genesisPath := ctx.Args().First()
|
||||
if len(genesisPath) == 0 {
|
||||
utils.Fatalf("Must supply path to genesis JSON file")
|
||||
utils.Fatalf("invalid path to genesis file")
|
||||
}
|
||||
file, err := os.Open(genesisPath)
|
||||
if err != nil {
|
||||
|
|
@ -203,6 +218,8 @@ func initGenesis(ctx *cli.Context) error {
|
|||
|
||||
// Open an initialise both full and light databases
|
||||
stack, _ := makeFullNode(ctx)
|
||||
defer stack.Close()
|
||||
|
||||
for _, name := range []string{"chaindata", "lightchaindata"} {
|
||||
chaindb, err := stack.OpenDatabase(name, 0, 0, "")
|
||||
if err != nil {
|
||||
|
|
@ -218,16 +235,15 @@ func initGenesis(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
func importChain(ctx *cli.Context) error {
|
||||
if len(ctx.Args()) < 1 {
|
||||
if ctx.Args().Len() < 1 {
|
||||
utils.Fatalf("This command requires an argument.")
|
||||
}
|
||||
stack, cfg := makeFullNode(ctx)
|
||||
defer stack.Close()
|
||||
|
||||
// Start metrics export if enabled
|
||||
utils.SetupMetrics(ctx)
|
||||
// Start system runtime metrics collection
|
||||
go metrics.CollectProcessMetrics(3 * time.Second)
|
||||
utils.SetupMetrics(&cfg.Metrics)
|
||||
|
||||
stack, _ := makeFullNode(ctx)
|
||||
chain, chainDb := utils.MakeChain(ctx, stack)
|
||||
defer chainDb.Close()
|
||||
|
||||
|
|
@ -249,12 +265,12 @@ func importChain(ctx *cli.Context) error {
|
|||
// Import the chain
|
||||
start := time.Now()
|
||||
|
||||
if len(ctx.Args()) == 1 {
|
||||
if ctx.Args().Len() == 1 {
|
||||
if err := utils.ImportChain(chain, ctx.Args().First()); err != nil {
|
||||
log.Error("Import error", "err", err)
|
||||
}
|
||||
} else {
|
||||
for _, arg := range ctx.Args() {
|
||||
for _, arg := range ctx.Args().Slice() {
|
||||
if err := utils.ImportChain(chain, arg); err != nil {
|
||||
log.Error("Import error", "file", arg, "err", err)
|
||||
}
|
||||
|
|
@ -287,7 +303,7 @@ func importChain(ctx *cli.Context) error {
|
|||
fmt.Printf("Allocations: %.3f million\n", float64(mem.Mallocs)/1000000)
|
||||
fmt.Printf("GC pause: %v\n\n", time.Duration(mem.PauseTotalNs))
|
||||
|
||||
if ctx.GlobalIsSet(utils.NoCompactionFlag.Name) {
|
||||
if ctx.IsSet(utils.NoCompactionFlag.Name) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -315,17 +331,20 @@ func importChain(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
func exportChain(ctx *cli.Context) error {
|
||||
if len(ctx.Args()) < 1 {
|
||||
if ctx.Args().Len() < 1 {
|
||||
utils.Fatalf("This command requires an argument.")
|
||||
}
|
||||
|
||||
stack, _ := makeFullNode(ctx)
|
||||
defer stack.Close()
|
||||
|
||||
chain, db := utils.MakeChain(ctx, stack)
|
||||
defer db.Close()
|
||||
start := time.Now()
|
||||
|
||||
var err error
|
||||
fp := ctx.Args().First()
|
||||
if len(ctx.Args()) < 3 {
|
||||
if ctx.Args().Len() < 3 {
|
||||
err = utils.ExportChain(chain, fp)
|
||||
} else {
|
||||
// This can be improved to allow for numbers larger than 9223372036854775807
|
||||
|
|
@ -349,10 +368,13 @@ func exportChain(ctx *cli.Context) error {
|
|||
|
||||
// importPreimages imports preimage data from the specified file.
|
||||
func importPreimages(ctx *cli.Context) error {
|
||||
if len(ctx.Args()) < 1 {
|
||||
if ctx.Args().Len() < 1 {
|
||||
utils.Fatalf("This command requires an argument.")
|
||||
}
|
||||
|
||||
stack, _ := makeFullNode(ctx)
|
||||
defer stack.Close()
|
||||
|
||||
diskdb := utils.MakeChainDatabase(ctx, stack)
|
||||
defer diskdb.Close()
|
||||
|
||||
|
|
@ -366,10 +388,12 @@ func importPreimages(ctx *cli.Context) error {
|
|||
|
||||
// exportPreimages dumps the preimage data to specified json file in streaming way.
|
||||
func exportPreimages(ctx *cli.Context) error {
|
||||
if len(ctx.Args()) < 1 {
|
||||
if ctx.Args().Len() < 1 {
|
||||
utils.Fatalf("This command requires an argument.")
|
||||
}
|
||||
stack, _ := makeFullNode(ctx)
|
||||
defer stack.Close()
|
||||
|
||||
diskdb := utils.MakeChainDatabase(ctx, stack)
|
||||
defer diskdb.Close()
|
||||
|
||||
|
|
@ -383,19 +407,24 @@ func exportPreimages(ctx *cli.Context) error {
|
|||
|
||||
func copyDb(ctx *cli.Context) error {
|
||||
// Ensure we have a source chain directory to copy
|
||||
if len(ctx.Args()) != 1 {
|
||||
if ctx.Args().Len() != 1 {
|
||||
utils.Fatalf("Source chaindata directory path argument missing")
|
||||
}
|
||||
// Initialize a new chain for the running node to sync into
|
||||
stack, _ := makeFullNode(ctx)
|
||||
defer stack.Close()
|
||||
|
||||
chain, chainDb := utils.MakeChain(ctx, stack)
|
||||
defer chainDb.Close()
|
||||
|
||||
syncmode := *utils.GlobalTextMarshaler(ctx, utils.SyncModeFlag.Name).(*downloader.SyncMode)
|
||||
var syncmode downloader.SyncMode
|
||||
if err := syncmode.UnmarshalText([]byte(ctx.String(utils.SyncModeFlag.Name))); err != nil {
|
||||
utils.Fatalf("invalid --syncmode flag: %v", err)
|
||||
}
|
||||
dl := downloader.New(syncmode, chainDb, new(event.TypeMux), chain, nil, nil, nil)
|
||||
|
||||
// Create a source peer to satisfy downloader requests from
|
||||
db, err := rawdb.NewLevelDBDatabase(ctx.Args().First(), ctx.GlobalInt(utils.CacheFlag.Name), 256, "")
|
||||
db, err := rawdb.NewLevelDBDatabase(ctx.Args().First(), ctx.Int(utils.CacheFlag.Name), 256, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -461,10 +490,12 @@ func removeDB(ctx *cli.Context) error {
|
|||
|
||||
func dump(ctx *cli.Context) error {
|
||||
stack, _ := makeFullNode(ctx)
|
||||
defer stack.Close()
|
||||
|
||||
chain, chainDb := utils.MakeChain(ctx, stack)
|
||||
defer chainDb.Close()
|
||||
|
||||
for _, arg := range ctx.Args() {
|
||||
|
||||
for _, arg := range ctx.Args().Slice() {
|
||||
var block *types.Block
|
||||
if hashish(arg) {
|
||||
block = chain.GetBlockByHash(common.HexToHash(arg))
|
||||
|
|
|
|||
|
|
@ -27,34 +27,33 @@ import (
|
|||
"strings"
|
||||
"unicode"
|
||||
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCx"
|
||||
"github.com/XinFinOrg/XDPoSChain/cmd/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/eth/ethconfig"
|
||||
"github.com/XinFinOrg/XDPoSChain/internal/debug"
|
||||
"github.com/XinFinOrg/XDPoSChain/internal/flags"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/XinFinOrg/XDPoSChain/metrics"
|
||||
"github.com/XinFinOrg/XDPoSChain/node"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
whisper "github.com/XinFinOrg/XDPoSChain/whisper/whisperv6"
|
||||
"github.com/naoina/toml"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
dumpConfigCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(dumpConfig),
|
||||
dumpConfigCommand = &cli.Command{
|
||||
Action: dumpConfig,
|
||||
Name: "dumpconfig",
|
||||
Usage: "Show configuration values",
|
||||
ArgsUsage: "",
|
||||
Flags: append(append(nodeFlags, rpcFlags...), whisperFlags...),
|
||||
Category: "MISCELLANEOUS COMMANDS",
|
||||
Flags: utils.GroupFlags(nodeFlags, rpcFlags),
|
||||
Description: `The dumpconfig command shows configuration values.`,
|
||||
}
|
||||
|
||||
configFileFlag = cli.StringFlag{
|
||||
Name: "config",
|
||||
Usage: "TOML configuration file",
|
||||
configFileFlag = &cli.StringFlag{
|
||||
Name: "config",
|
||||
Usage: "TOML configuration file",
|
||||
Category: flags.EthCategory,
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -91,9 +90,9 @@ type Bootnodes struct {
|
|||
|
||||
type XDCConfig struct {
|
||||
Eth ethconfig.Config
|
||||
Shh whisper.Config
|
||||
Node node.Config
|
||||
Ethstats ethstatsConfig
|
||||
Metrics metrics.Config
|
||||
XDCX XDCx.Config
|
||||
Account account
|
||||
StakeEnable bool
|
||||
|
|
@ -120,42 +119,43 @@ func defaultNodeConfig() node.Config {
|
|||
cfg := node.DefaultConfig
|
||||
cfg.Name = clientIdentifier
|
||||
cfg.Version = params.VersionWithCommit(gitCommit)
|
||||
cfg.HTTPModules = append(cfg.HTTPModules, "eth", "shh")
|
||||
cfg.WSModules = append(cfg.WSModules, "eth", "shh")
|
||||
cfg.HTTPModules = append(cfg.HTTPModules, "eth")
|
||||
cfg.WSModules = append(cfg.WSModules, "eth")
|
||||
cfg.IPCPath = "XDC.ipc"
|
||||
return cfg
|
||||
}
|
||||
|
||||
// makeConfigNode loads geth configuration and creates a blank node instance.
|
||||
func makeConfigNode(ctx *cli.Context) (*node.Node, XDCConfig) {
|
||||
// Load defaults.
|
||||
cfg := XDCConfig{
|
||||
Eth: ethconfig.Defaults,
|
||||
Shh: whisper.DefaultConfig,
|
||||
XDCX: XDCx.DefaultConfig,
|
||||
Node: defaultNodeConfig(),
|
||||
Metrics: metrics.DefaultConfig,
|
||||
StakeEnable: true,
|
||||
Verbosity: 3,
|
||||
NAT: "",
|
||||
}
|
||||
// Load config file.
|
||||
if file := ctx.GlobalString(configFileFlag.Name); file != "" {
|
||||
if file := ctx.String(configFileFlag.Name); file != "" {
|
||||
if err := loadConfig(file, &cfg); err != nil {
|
||||
utils.Fatalf("%v", err)
|
||||
}
|
||||
}
|
||||
if ctx.GlobalIsSet(utils.StakingEnabledFlag.Name) {
|
||||
cfg.StakeEnable = ctx.GlobalBool(utils.StakingEnabledFlag.Name)
|
||||
}
|
||||
if !ctx.GlobalIsSet(debug.VerbosityFlag.Name) {
|
||||
debug.Glogger.Verbosity(log.Lvl(cfg.Verbosity))
|
||||
if ctx.IsSet(utils.MiningEnabledFlag.Name) {
|
||||
cfg.StakeEnable = ctx.Bool(utils.MiningEnabledFlag.Name)
|
||||
}
|
||||
// if !ctx.IsSet(debug.VerbosityFlag.Name) {
|
||||
// debug.Verbosity(log.Lvl(cfg.Verbosity))
|
||||
// }
|
||||
|
||||
if !ctx.GlobalIsSet(utils.NATFlag.Name) && cfg.NAT != "" {
|
||||
if !ctx.IsSet(utils.NATFlag.Name) && cfg.NAT != "" {
|
||||
ctx.Set(utils.NATFlag.Name, cfg.NAT)
|
||||
}
|
||||
|
||||
// Check testnet is enable.
|
||||
if ctx.GlobalBool(utils.XDCTestnetFlag.Name) {
|
||||
if ctx.Bool(utils.XDCTestnetFlag.Name) {
|
||||
common.IsTestnet = true
|
||||
common.TRC21IssuerSMC = common.TRC21IssuerSMCTestNet
|
||||
cfg.Eth.NetworkId = 51
|
||||
|
|
@ -164,24 +164,24 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, XDCConfig) {
|
|||
common.TIPXDCXCancellationFee = common.TIPXDCXCancellationFeeTestnet
|
||||
}
|
||||
|
||||
if ctx.GlobalBool(utils.EnableXDCPrefixFlag.Name) {
|
||||
if ctx.Bool(utils.EnableXDCPrefixFlag.Name) {
|
||||
common.Enable0xPrefix = false
|
||||
}
|
||||
|
||||
// Rewound
|
||||
if rewound := ctx.GlobalInt(utils.RewoundFlag.Name); rewound != 0 {
|
||||
if rewound := ctx.Int(utils.RewoundFlag.Name); rewound != 0 {
|
||||
common.Rewound = uint64(rewound)
|
||||
}
|
||||
|
||||
// Check rollback hash exist.
|
||||
if rollbackHash := ctx.GlobalString(utils.RollbackFlag.Name); rollbackHash != "" {
|
||||
if rollbackHash := ctx.String(utils.RollbackFlag.Name); rollbackHash != "" {
|
||||
common.RollbackHash = common.HexToHash(rollbackHash)
|
||||
}
|
||||
|
||||
// Check GasPrice
|
||||
common.MinGasPrice = big.NewInt(common.DefaultMinGasPrice)
|
||||
if ctx.GlobalIsSet(utils.GasPriceFlag.Name) {
|
||||
if gasPrice := int64(ctx.GlobalInt(utils.GasPriceFlag.Name)); gasPrice > common.DefaultMinGasPrice {
|
||||
if ctx.IsSet(utils.MinerGasPriceFlag.Name) {
|
||||
if gasPrice := int64(ctx.Int(utils.MinerGasPriceFlag.Name)); gasPrice > common.DefaultMinGasPrice {
|
||||
common.MinGasPrice = big.NewInt(gasPrice)
|
||||
}
|
||||
}
|
||||
|
|
@ -208,12 +208,14 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, XDCConfig) {
|
|||
utils.Fatalf("Failed to create the protocol stack: %v", err)
|
||||
}
|
||||
utils.SetEthConfig(ctx, stack, &cfg.Eth)
|
||||
if ctx.GlobalIsSet(utils.EthStatsURLFlag.Name) {
|
||||
cfg.Ethstats.URL = ctx.GlobalString(utils.EthStatsURLFlag.Name)
|
||||
if ctx.IsSet(utils.EthStatsURLFlag.Name) {
|
||||
cfg.Ethstats.URL = ctx.String(utils.EthStatsURLFlag.Name)
|
||||
}
|
||||
|
||||
utils.SetShhConfig(ctx, stack, &cfg.Shh)
|
||||
utils.SetXDCXConfig(ctx, &cfg.XDCX, cfg.Node.DataDir)
|
||||
|
||||
applyMetricConfig(ctx, &cfg)
|
||||
|
||||
return stack, cfg
|
||||
}
|
||||
|
||||
|
|
@ -230,36 +232,16 @@ func applyValues(values []string, params *[]string) {
|
|||
|
||||
}
|
||||
|
||||
// enableWhisper returns true in case one of the whisper flags is set.
|
||||
func enableWhisper(ctx *cli.Context) bool {
|
||||
for _, flag := range whisperFlags {
|
||||
if ctx.GlobalIsSet(flag.GetName()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func makeFullNode(ctx *cli.Context) (*node.Node, XDCConfig) {
|
||||
stack, cfg := makeConfigNode(ctx)
|
||||
|
||||
// Start metrics export if enabled
|
||||
utils.SetupMetrics(&cfg.Metrics)
|
||||
|
||||
// Register XDCX's OrderBook service if requested.
|
||||
// enable in default
|
||||
utils.RegisterXDCXService(stack, &cfg.XDCX)
|
||||
utils.RegisterEthService(stack, &cfg.Eth)
|
||||
|
||||
// Whisper must be explicitly enabled by specifying at least 1 whisper flag or in dev mode
|
||||
shhEnabled := enableWhisper(ctx)
|
||||
shhAutoEnabled := !ctx.GlobalIsSet(utils.WhisperEnabledFlag.Name) && ctx.GlobalIsSet(utils.DeveloperFlag.Name)
|
||||
if shhEnabled || shhAutoEnabled {
|
||||
if ctx.GlobalIsSet(utils.WhisperMaxMessageSizeFlag.Name) {
|
||||
cfg.Shh.MaxMessageSize = uint32(ctx.Int(utils.WhisperMaxMessageSizeFlag.Name))
|
||||
}
|
||||
if ctx.GlobalIsSet(utils.WhisperMinPOWFlag.Name) {
|
||||
cfg.Shh.MinimumAcceptedPOW = ctx.Float64(utils.WhisperMinPOWFlag.Name)
|
||||
}
|
||||
utils.RegisterShhService(stack, &cfg.Shh)
|
||||
}
|
||||
utils.RegisterEthService(stack, &cfg.Eth, cfg.Node.Version)
|
||||
|
||||
// Add the Ethereum Stats daemon if requested.
|
||||
if cfg.Ethstats.URL != "" {
|
||||
|
|
@ -287,3 +269,69 @@ func dumpConfig(ctx *cli.Context) error {
|
|||
os.Stdout.Write(out)
|
||||
return nil
|
||||
}
|
||||
|
||||
func applyMetricConfig(ctx *cli.Context, cfg *XDCConfig) {
|
||||
if ctx.IsSet(utils.MetricsEnabledFlag.Name) {
|
||||
cfg.Metrics.Enabled = ctx.Bool(utils.MetricsEnabledFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.MetricsEnabledExpensiveFlag.Name) {
|
||||
log.Warn("Expensive metrics are collected by default, please remove this flag", "flag", utils.MetricsEnabledExpensiveFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.MetricsHTTPFlag.Name) {
|
||||
cfg.Metrics.HTTP = ctx.String(utils.MetricsHTTPFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.MetricsPortFlag.Name) {
|
||||
cfg.Metrics.Port = ctx.Int(utils.MetricsPortFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.MetricsEnableInfluxDBFlag.Name) {
|
||||
cfg.Metrics.EnableInfluxDB = ctx.Bool(utils.MetricsEnableInfluxDBFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.MetricsInfluxDBEndpointFlag.Name) {
|
||||
cfg.Metrics.InfluxDBEndpoint = ctx.String(utils.MetricsInfluxDBEndpointFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.MetricsInfluxDBDatabaseFlag.Name) {
|
||||
cfg.Metrics.InfluxDBDatabase = ctx.String(utils.MetricsInfluxDBDatabaseFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.MetricsInfluxDBUsernameFlag.Name) {
|
||||
cfg.Metrics.InfluxDBUsername = ctx.String(utils.MetricsInfluxDBUsernameFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.MetricsInfluxDBPasswordFlag.Name) {
|
||||
cfg.Metrics.InfluxDBPassword = ctx.String(utils.MetricsInfluxDBPasswordFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.MetricsInfluxDBTagsFlag.Name) {
|
||||
cfg.Metrics.InfluxDBTags = ctx.String(utils.MetricsInfluxDBTagsFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.MetricsEnableInfluxDBV2Flag.Name) {
|
||||
cfg.Metrics.EnableInfluxDBV2 = ctx.Bool(utils.MetricsEnableInfluxDBV2Flag.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.MetricsInfluxDBTokenFlag.Name) {
|
||||
cfg.Metrics.InfluxDBToken = ctx.String(utils.MetricsInfluxDBTokenFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.MetricsInfluxDBBucketFlag.Name) {
|
||||
cfg.Metrics.InfluxDBBucket = ctx.String(utils.MetricsInfluxDBBucketFlag.Name)
|
||||
}
|
||||
if ctx.IsSet(utils.MetricsInfluxDBOrganizationFlag.Name) {
|
||||
cfg.Metrics.InfluxDBOrganization = ctx.String(utils.MetricsInfluxDBOrganizationFlag.Name)
|
||||
}
|
||||
// Sanity-check the commandline flags. It is fine if some unused fields is part
|
||||
// of the toml-config, but we expect the commandline to only contain relevant
|
||||
// arguments, otherwise it indicates an error.
|
||||
var (
|
||||
enableExport = ctx.Bool(utils.MetricsEnableInfluxDBFlag.Name)
|
||||
enableExportV2 = ctx.Bool(utils.MetricsEnableInfluxDBV2Flag.Name)
|
||||
)
|
||||
if enableExport || enableExportV2 {
|
||||
v1FlagIsSet := ctx.IsSet(utils.MetricsInfluxDBUsernameFlag.Name) ||
|
||||
ctx.IsSet(utils.MetricsInfluxDBPasswordFlag.Name)
|
||||
|
||||
v2FlagIsSet := ctx.IsSet(utils.MetricsInfluxDBTokenFlag.Name) ||
|
||||
ctx.IsSet(utils.MetricsInfluxDBOrganizationFlag.Name) ||
|
||||
ctx.IsSet(utils.MetricsInfluxDBBucketFlag.Name)
|
||||
|
||||
if enableExport && v2FlagIsSet {
|
||||
utils.Fatalf("Flags --influxdb-metrics.organization, --influxdb-metrics.token, --influxdb-metrics.bucket are only available for influxdb-v2")
|
||||
} else if enableExportV2 && v1FlagIsSet {
|
||||
utils.Fatalf("Flags --influxdb-metrics.username, --influxdb-metrics.password are only available for influxdb-v1")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,31 +28,29 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/console"
|
||||
"github.com/XinFinOrg/XDPoSChain/node"
|
||||
"github.com/XinFinOrg/XDPoSChain/rpc"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
consoleFlags = []cli.Flag{utils.JSpathFlag, utils.ExecFlag, utils.PreloadJSFlag}
|
||||
|
||||
consoleCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(localConsole),
|
||||
Name: "console",
|
||||
Usage: "Start an interactive JavaScript environment",
|
||||
Flags: append(append(append(nodeFlags, rpcFlags...), consoleFlags...), whisperFlags...),
|
||||
Category: "CONSOLE COMMANDS",
|
||||
consoleCommand = &cli.Command{
|
||||
Action: localConsole,
|
||||
Name: "console",
|
||||
Usage: "Start an interactive JavaScript environment",
|
||||
Flags: utils.GroupFlags(nodeFlags, rpcFlags, consoleFlags),
|
||||
Description: `
|
||||
The XDC console is an interactive shell for the JavaScript runtime environment
|
||||
which exposes a node admin interface as well as the Ðapp JavaScript API.
|
||||
See https://github.com/XinFinOrg/XDPoSChain/wiki/JavaScript-Console.`,
|
||||
}
|
||||
|
||||
attachCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(remoteConsole),
|
||||
attachCommand = &cli.Command{
|
||||
Action: remoteConsole,
|
||||
Name: "attach",
|
||||
Usage: "Start an interactive JavaScript environment (connect to node)",
|
||||
ArgsUsage: "[endpoint]",
|
||||
Flags: append(consoleFlags, utils.DataDirFlag),
|
||||
Category: "CONSOLE COMMANDS",
|
||||
Flags: utils.GroupFlags([]cli.Flag{utils.DataDirFlag}, consoleFlags),
|
||||
Description: `
|
||||
The XDC console is an interactive shell for the JavaScript runtime environment
|
||||
which exposes a node admin interface as well as the Ðapp JavaScript API.
|
||||
|
|
@ -60,13 +58,12 @@ See https://github.com/XinFinOrg/XDPoSChain/wiki/JavaScript-Console.
|
|||
This command allows to open a console on a running XDC node.`,
|
||||
}
|
||||
|
||||
javascriptCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(ephemeralConsole),
|
||||
javascriptCommand = &cli.Command{
|
||||
Action: ephemeralConsole,
|
||||
Name: "js",
|
||||
Usage: "Execute the specified JavaScript files",
|
||||
ArgsUsage: "<jsfile> [jsfile...]",
|
||||
Flags: append(nodeFlags, consoleFlags...),
|
||||
Category: "CONSOLE COMMANDS",
|
||||
Flags: utils.GroupFlags(nodeFlags, consoleFlags),
|
||||
Description: `
|
||||
The JavaScript VM exposes a node admin interface as well as the Ðapp
|
||||
JavaScript API. See https://github.com/XinFinOrg/XDPoSChain/wiki/JavaScript-Console`,
|
||||
|
|
@ -79,7 +76,7 @@ func localConsole(ctx *cli.Context) error {
|
|||
// Create and start the node based on the CLI flags
|
||||
node, cfg := makeFullNode(ctx)
|
||||
startNode(ctx, node, cfg)
|
||||
defer node.Stop()
|
||||
defer node.Close()
|
||||
|
||||
// Attach to the newly started node and start the JavaScript console
|
||||
client, err := node.Attach()
|
||||
|
|
@ -88,7 +85,7 @@ func localConsole(ctx *cli.Context) error {
|
|||
}
|
||||
config := console.Config{
|
||||
DataDir: utils.MakeDataDir(ctx),
|
||||
DocRoot: ctx.GlobalString(utils.JSpathFlag.Name),
|
||||
DocRoot: ctx.String(utils.JSpathFlag.Name),
|
||||
Client: client,
|
||||
Preload: utils.MakeConsolePreloads(ctx),
|
||||
}
|
||||
|
|
@ -100,7 +97,7 @@ func localConsole(ctx *cli.Context) error {
|
|||
defer console.Stop(false)
|
||||
|
||||
// If only a short execution was requested, evaluate and return
|
||||
if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" {
|
||||
if script := ctx.String(utils.ExecFlag.Name); script != "" {
|
||||
console.Evaluate(script)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -114,17 +111,20 @@ func localConsole(ctx *cli.Context) error {
|
|||
// remoteConsole will connect to a remote XDC instance, attaching a JavaScript
|
||||
// console to it.
|
||||
func remoteConsole(ctx *cli.Context) error {
|
||||
// Attach to a remotely running XDC instance and start the JavaScript console
|
||||
if ctx.Args().Len() > 1 {
|
||||
utils.Fatalf("invalid command-line: too many arguments")
|
||||
}
|
||||
|
||||
endpoint := ctx.Args().First()
|
||||
if endpoint == "" {
|
||||
path := node.DefaultDataDir()
|
||||
if ctx.GlobalIsSet(utils.DataDirFlag.Name) {
|
||||
path = ctx.GlobalString(utils.DataDirFlag.Name)
|
||||
if ctx.IsSet(utils.DataDirFlag.Name) {
|
||||
path = ctx.String(utils.DataDirFlag.Name)
|
||||
}
|
||||
if path != "" {
|
||||
if ctx.GlobalBool(utils.TestnetFlag.Name) {
|
||||
if ctx.Bool(utils.TestnetFlag.Name) {
|
||||
path = filepath.Join(path, "testnet")
|
||||
} else if ctx.GlobalBool(utils.RinkebyFlag.Name) {
|
||||
} else if ctx.Bool(utils.RinkebyFlag.Name) {
|
||||
path = filepath.Join(path, "rinkeby")
|
||||
}
|
||||
}
|
||||
|
|
@ -137,7 +137,7 @@ func remoteConsole(ctx *cli.Context) error {
|
|||
}
|
||||
config := console.Config{
|
||||
DataDir: utils.MakeDataDir(ctx),
|
||||
DocRoot: ctx.GlobalString(utils.JSpathFlag.Name),
|
||||
DocRoot: ctx.String(utils.JSpathFlag.Name),
|
||||
Client: client,
|
||||
Preload: utils.MakeConsolePreloads(ctx),
|
||||
}
|
||||
|
|
@ -148,7 +148,7 @@ func remoteConsole(ctx *cli.Context) error {
|
|||
}
|
||||
defer console.Stop(false)
|
||||
|
||||
if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" {
|
||||
if script := ctx.String(utils.ExecFlag.Name); script != "" {
|
||||
console.Evaluate(script)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -181,7 +181,7 @@ func ephemeralConsole(ctx *cli.Context) error {
|
|||
// Create and start the node based on the CLI flags
|
||||
node, cfg := makeFullNode(ctx)
|
||||
startNode(ctx, node, cfg)
|
||||
defer node.Stop()
|
||||
defer node.Close()
|
||||
|
||||
// Attach to the newly started node and start the JavaScript console
|
||||
client, err := node.Attach()
|
||||
|
|
@ -190,7 +190,7 @@ func ephemeralConsole(ctx *cli.Context) error {
|
|||
}
|
||||
config := console.Config{
|
||||
DataDir: utils.MakeDataDir(ctx),
|
||||
DocRoot: ctx.GlobalString(utils.JSpathFlag.Name),
|
||||
DocRoot: ctx.String(utils.JSpathFlag.Name),
|
||||
Client: client,
|
||||
Preload: utils.MakeConsolePreloads(ctx),
|
||||
}
|
||||
|
|
@ -202,7 +202,7 @@ func ephemeralConsole(ctx *cli.Context) error {
|
|||
defer console.Stop(false)
|
||||
|
||||
// Evaluate each of the specified JavaScript files
|
||||
for _, file := range ctx.Args() {
|
||||
for _, file := range ctx.Args().Slice() {
|
||||
if err = console.Execute(file); err != nil {
|
||||
utils.Fatalf("Failed to execute %s: %v", file, err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,13 +39,14 @@ const (
|
|||
// then terminated by closing the input stream.
|
||||
func TestConsoleWelcome(t *testing.T) {
|
||||
coinbase := "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182"
|
||||
datadir := tmpdir(t)
|
||||
defer os.RemoveAll(datadir)
|
||||
|
||||
// Start a XDC console, make sure it's cleaned up and terminate the console
|
||||
XDC := runXDC(t,
|
||||
"--XDCx.datadir", tmpdir(t)+"XDCx/"+time.Now().String(),
|
||||
"console", "--datadir", datadir, "--XDCx-datadir", datadir+"/XDCx/"+time.Now().String(),
|
||||
"--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none",
|
||||
"--etherbase", coinbase,
|
||||
"console")
|
||||
"--miner-etherbase", coinbase)
|
||||
|
||||
// Gather all the infos the welcome message needs to contain
|
||||
XDC.SetTemplateFunc("goos", func() string { return runtime.GOOS })
|
||||
|
|
@ -76,18 +77,18 @@ at block: 0 ({{niltime}})
|
|||
func TestIPCAttachWelcome(t *testing.T) {
|
||||
// Configure the instance for IPC attachement
|
||||
coinbase := "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182"
|
||||
datadir := tmpdir(t)
|
||||
defer os.RemoveAll(datadir)
|
||||
var ipc string
|
||||
if runtime.GOOS == "windows" {
|
||||
ipc = `\\.\pipe\XDC` + strconv.Itoa(trulyRandInt(100000, 999999))
|
||||
} else {
|
||||
ws := tmpdir(t)
|
||||
defer os.RemoveAll(ws)
|
||||
ipc = filepath.Join(ws, "XDC.ipc")
|
||||
ipc = filepath.Join(datadir, "XDC.ipc")
|
||||
}
|
||||
XDC := runXDC(t,
|
||||
"--XDCx.datadir", tmpdir(t)+"XDCx/"+time.Now().String(),
|
||||
"--datadir", datadir, "--XDCx-datadir", datadir+"/XDCx/"+time.Now().String(),
|
||||
"--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none",
|
||||
"--etherbase", coinbase, "--ipcpath", ipc)
|
||||
"--miner-etherbase", coinbase, "--ipcpath", ipc)
|
||||
|
||||
time.Sleep(2 * time.Second) // Simple way to wait for the RPC endpoint to open
|
||||
testAttachWelcome(t, XDC, "ipc:"+ipc, ipcAPIs)
|
||||
|
|
@ -99,10 +100,12 @@ func TestIPCAttachWelcome(t *testing.T) {
|
|||
func TestHTTPAttachWelcome(t *testing.T) {
|
||||
coinbase := "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182"
|
||||
port := strconv.Itoa(trulyRandInt(1024, 65536)) // Yeah, sometimes this will fail, sorry :P
|
||||
datadir := tmpdir(t)
|
||||
defer os.RemoveAll(datadir)
|
||||
XDC := runXDC(t,
|
||||
"--XDCx.datadir", tmpdir(t)+"XDCx/"+time.Now().String(),
|
||||
"--datadir", datadir, "--XDCx-datadir", datadir+"/XDCx/"+time.Now().String(),
|
||||
"--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none",
|
||||
"--etherbase", coinbase, "--rpc", "--rpcport", port)
|
||||
"--miner-etherbase", coinbase, "--http", "--http-port", port)
|
||||
|
||||
time.Sleep(2 * time.Second) // Simple way to wait for the RPC endpoint to open
|
||||
testAttachWelcome(t, XDC, "http://localhost:"+port, httpAPIs)
|
||||
|
|
@ -114,11 +117,12 @@ func TestHTTPAttachWelcome(t *testing.T) {
|
|||
func TestWSAttachWelcome(t *testing.T) {
|
||||
coinbase := "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182"
|
||||
port := strconv.Itoa(trulyRandInt(1024, 65536)) // Yeah, sometimes this will fail, sorry :P
|
||||
|
||||
datadir := tmpdir(t)
|
||||
defer os.RemoveAll(datadir)
|
||||
XDC := runXDC(t,
|
||||
"--XDCx.datadir", tmpdir(t)+"XDCx/"+time.Now().String(),
|
||||
"--datadir", datadir, "--XDCx-datadir", datadir+"/XDCx/"+time.Now().String(),
|
||||
"--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none",
|
||||
"--etherbase", coinbase, "--ws", "--wsport", port)
|
||||
"--miner-etherbase", coinbase, "--ws", "--ws-port", port)
|
||||
|
||||
time.Sleep(2 * time.Second) // Simple way to wait for the RPC endpoint to open
|
||||
testAttachWelcome(t, XDC, "ws://localhost:"+port, httpAPIs)
|
||||
|
|
|
|||
|
|
@ -111,11 +111,10 @@ func testDAOForkBlockNewChain(t *testing.T, test int, genesis string, expectBloc
|
|||
if err := os.WriteFile(json, []byte(genesis), 0600); err != nil {
|
||||
t.Fatalf("test %d: failed to write genesis file: %v", test, err)
|
||||
}
|
||||
runXDC(t, "--datadir", datadir, "init", json).WaitExit()
|
||||
runXDC(t, "init", "--datadir", datadir, json).WaitExit()
|
||||
} else {
|
||||
// Force chain initialization
|
||||
args := []string{"--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none", "--ipcdisable", "--datadir", datadir}
|
||||
XDC := runXDC(t, append(args, []string{"--exec", "2+2", "console"}...)...)
|
||||
XDC := runXDC(t, "console", "--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none", "--ipcdisable", "--datadir", datadir, "--exec", "2+2")
|
||||
XDC.WaitExit()
|
||||
}
|
||||
// Retrieve the DAO config flag from the database
|
||||
|
|
|
|||
|
|
@ -33,14 +33,14 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/eth"
|
||||
"github.com/XinFinOrg/XDPoSChain/ethclient"
|
||||
"github.com/XinFinOrg/XDPoSChain/internal/debug"
|
||||
"github.com/XinFinOrg/XDPoSChain/internal/flags"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/XinFinOrg/XDPoSChain/metrics"
|
||||
"github.com/XinFinOrg/XDPoSChain/node"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
// Force-load the native, to trigger registration
|
||||
_ "github.com/XinFinOrg/XDPoSChain/eth/tracers/native"
|
||||
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -51,7 +51,7 @@ var (
|
|||
// Git SHA1 commit hash of the release (set via linker flags)
|
||||
gitCommit = ""
|
||||
// The app that holds all commands and flags.
|
||||
app = utils.NewApp(gitCommit, "the XDPoSChain command line interface")
|
||||
app = flags.NewApp(gitCommit, "the XDPoSChain command line interface")
|
||||
// flags that configure the node
|
||||
nodeFlags = []cli.Flag{
|
||||
utils.IdentityFlag,
|
||||
|
|
@ -98,14 +98,15 @@ var (
|
|||
//utils.TrieCacheGenFlag,
|
||||
utils.CacheLogSizeFlag,
|
||||
utils.FDLimitFlag,
|
||||
utils.CryptoKZGFlag,
|
||||
utils.ListenPortFlag,
|
||||
utils.MaxPeersFlag,
|
||||
utils.MaxPendingPeersFlag,
|
||||
utils.EtherbaseFlag,
|
||||
utils.GasPriceFlag,
|
||||
utils.StakerThreadsFlag,
|
||||
utils.StakingEnabledFlag,
|
||||
utils.TargetGasLimitFlag,
|
||||
utils.MinerEtherbaseFlag,
|
||||
utils.MinerGasPriceFlag,
|
||||
utils.MinerThreadsFlag,
|
||||
utils.MiningEnabledFlag,
|
||||
utils.MinerGasLimitFlag,
|
||||
utils.NATFlag,
|
||||
utils.NoDiscoverFlag,
|
||||
//utils.DiscoveryV5Flag,
|
||||
|
|
@ -122,12 +123,9 @@ var (
|
|||
utils.EnableXDCPrefixFlag,
|
||||
utils.RewoundFlag,
|
||||
utils.NetworkIdFlag,
|
||||
utils.RPCCORSDomainFlag,
|
||||
utils.RPCVirtualHostsFlag,
|
||||
utils.HTTPCORSDomainFlag,
|
||||
utils.HTTPVirtualHostsFlag,
|
||||
utils.EthStatsURLFlag,
|
||||
utils.MetricsEnabledFlag,
|
||||
utils.MetricsHTTPFlag,
|
||||
utils.MetricsPortFlag,
|
||||
//utils.FakePoWFlag,
|
||||
//utils.NoCompactionFlag,
|
||||
//utils.GpoBlocksFlag,
|
||||
|
|
@ -136,6 +134,8 @@ var (
|
|||
utils.GpoIgnoreGasPriceFlag,
|
||||
//utils.ExtraDataFlag,
|
||||
configFileFlag,
|
||||
utils.LogDebugFlag,
|
||||
utils.LogBacktraceAtFlag,
|
||||
utils.AnnounceTxsFlag,
|
||||
utils.StoreRewardFlag,
|
||||
utils.RollbackFlag,
|
||||
|
|
@ -143,12 +143,14 @@ var (
|
|||
}
|
||||
|
||||
rpcFlags = []cli.Flag{
|
||||
utils.RPCEnabledFlag,
|
||||
utils.HTTPEnabledFlag,
|
||||
utils.RPCGlobalGasCapFlag,
|
||||
utils.RPCListenAddrFlag,
|
||||
utils.RPCPortFlag,
|
||||
utils.RPCHttpWriteTimeoutFlag,
|
||||
utils.RPCApiFlag,
|
||||
utils.HTTPListenAddrFlag,
|
||||
utils.HTTPPortFlag,
|
||||
utils.HTTPReadTimeoutFlag,
|
||||
utils.HTTPWriteTimeoutFlag,
|
||||
utils.HTTPIdleTimeoutFlag,
|
||||
utils.HTTPApiFlag,
|
||||
utils.WSEnabledFlag,
|
||||
utils.WSListenAddrFlag,
|
||||
utils.WSPortFlag,
|
||||
|
|
@ -159,19 +161,29 @@ var (
|
|||
utils.RPCGlobalTxFeeCap,
|
||||
}
|
||||
|
||||
whisperFlags = []cli.Flag{
|
||||
utils.WhisperEnabledFlag,
|
||||
utils.WhisperMaxMessageSizeFlag,
|
||||
utils.WhisperMinPOWFlag,
|
||||
metricsFlags = []cli.Flag{
|
||||
utils.MetricsEnabledFlag,
|
||||
utils.MetricsEnabledExpensiveFlag,
|
||||
utils.MetricsHTTPFlag,
|
||||
utils.MetricsPortFlag,
|
||||
utils.MetricsEnableInfluxDBFlag,
|
||||
utils.MetricsInfluxDBEndpointFlag,
|
||||
utils.MetricsInfluxDBDatabaseFlag,
|
||||
utils.MetricsInfluxDBUsernameFlag,
|
||||
utils.MetricsInfluxDBPasswordFlag,
|
||||
utils.MetricsInfluxDBTagsFlag,
|
||||
utils.MetricsEnableInfluxDBV2Flag,
|
||||
utils.MetricsInfluxDBTokenFlag,
|
||||
utils.MetricsInfluxDBBucketFlag,
|
||||
utils.MetricsInfluxDBOrganizationFlag,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Initialize the CLI app and start XDC
|
||||
app.Action = XDC
|
||||
app.HideVersion = true // we have a command to print the version
|
||||
app.Copyright = "Copyright (c) 2018 XDPoSChain"
|
||||
app.Commands = []cli.Command{
|
||||
app.Copyright = "Copyright (c) 2024 XDPoSChain"
|
||||
app.Commands = []*cli.Command{
|
||||
// See chaincmd.go:
|
||||
initCommand,
|
||||
importCommand,
|
||||
|
|
@ -196,13 +208,17 @@ func init() {
|
|||
app.Flags = append(app.Flags, rpcFlags...)
|
||||
app.Flags = append(app.Flags, consoleFlags...)
|
||||
app.Flags = append(app.Flags, debug.Flags...)
|
||||
app.Flags = append(app.Flags, whisperFlags...)
|
||||
app.Flags = append(app.Flags, metricsFlags...)
|
||||
flags.AutoEnvVars(app.Flags, "XDC")
|
||||
|
||||
app.Before = func(ctx *cli.Context) error {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
flags.MigrateGlobalFlags(ctx)
|
||||
if err := debug.Setup(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
flags.CheckEnvVars(ctx, app.Flags, "XDC")
|
||||
|
||||
// Start system runtime metrics collection
|
||||
go metrics.CollectProcessMetrics(3 * time.Second)
|
||||
|
||||
|
|
@ -229,6 +245,7 @@ func main() {
|
|||
// blocking mode, waiting for it to be shut down.
|
||||
func XDC(ctx *cli.Context) error {
|
||||
node, cfg := makeFullNode(ctx)
|
||||
defer node.Close()
|
||||
startNode(ctx, node, cfg)
|
||||
node.Wait()
|
||||
return nil
|
||||
|
|
@ -244,11 +261,11 @@ func startNode(ctx *cli.Context, stack *node.Node, cfg XDCConfig) {
|
|||
// Unlock any account specifically requested
|
||||
ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
|
||||
|
||||
if ctx.GlobalIsSet(utils.UnlockedAccountFlag.Name) {
|
||||
cfg.Account.Unlocks = strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
|
||||
if ctx.IsSet(utils.UnlockedAccountFlag.Name) {
|
||||
cfg.Account.Unlocks = strings.Split(ctx.String(utils.UnlockedAccountFlag.Name), ",")
|
||||
}
|
||||
|
||||
if ctx.GlobalIsSet(utils.PasswordFileFlag.Name) {
|
||||
if ctx.IsSet(utils.PasswordFileFlag.Name) {
|
||||
cfg.Account.Passwords = utils.MakePasswordList(ctx)
|
||||
}
|
||||
|
||||
|
|
@ -301,13 +318,9 @@ func startNode(ctx *cli.Context, stack *node.Node, cfg XDCConfig) {
|
|||
// Start auxiliary services if enabled
|
||||
|
||||
// Mining only makes sense if a full Ethereum node is running
|
||||
if ctx.GlobalBool(utils.LightModeFlag.Name) || ctx.GlobalString(utils.SyncModeFlag.Name) == "light" {
|
||||
if ctx.Bool(utils.LightModeFlag.Name) || ctx.String(utils.SyncModeFlag.Name) == "light" {
|
||||
utils.Fatalf("Light clients do not support staking")
|
||||
}
|
||||
// Start metrics export if enabled
|
||||
utils.SetupMetrics(ctx)
|
||||
// Start system runtime metrics collection
|
||||
go metrics.CollectProcessMetrics(3 * time.Second)
|
||||
|
||||
var ethereum *eth.Ethereum
|
||||
if err := stack.Service(ðereum); err != nil {
|
||||
|
|
@ -317,7 +330,7 @@ func startNode(ctx *cli.Context, stack *node.Node, cfg XDCConfig) {
|
|||
go func() {
|
||||
started := false
|
||||
ok := false
|
||||
slaveMode := ctx.GlobalIsSet(utils.XDCSlaveModeFlag.Name)
|
||||
slaveMode := ctx.IsSet(utils.XDCSlaveModeFlag.Name)
|
||||
var err error
|
||||
ok, err = ethereum.ValidateMasternode()
|
||||
if err != nil {
|
||||
|
|
@ -330,7 +343,7 @@ func startNode(ctx *cli.Context, stack *node.Node, cfg XDCConfig) {
|
|||
} else {
|
||||
log.Info("Masternode found. Enabling staking mode...")
|
||||
// Use a reduced number of threads if requested
|
||||
if threads := ctx.GlobalInt(utils.StakerThreadsFlag.Name); threads > 0 {
|
||||
if threads := ctx.Int(utils.MinerThreadsFlag.Name); threads > 0 {
|
||||
type threaded interface {
|
||||
SetThreads(threads int)
|
||||
}
|
||||
|
|
@ -372,7 +385,7 @@ func startNode(ctx *cli.Context, stack *node.Node, cfg XDCConfig) {
|
|||
} else {
|
||||
log.Info("Masternode found. Enabling staking mode...")
|
||||
// Use a reduced number of threads if requested
|
||||
if threads := ctx.GlobalInt(utils.StakerThreadsFlag.Name); threads > 0 {
|
||||
if threads := ctx.Int(utils.MinerThreadsFlag.Name); threads > 0 {
|
||||
type threaded interface {
|
||||
SetThreads(threads int)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,16 +28,15 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/eth"
|
||||
"github.com/XinFinOrg/XDPoSChain/eth/ethconfig"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
makecacheCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(makecache),
|
||||
makecacheCommand = &cli.Command{
|
||||
Action: makecache,
|
||||
Name: "makecache",
|
||||
Usage: "Generate ethash verification cache (for testing)",
|
||||
ArgsUsage: "<blockNum> <outputDir>",
|
||||
Category: "MISCELLANEOUS COMMANDS",
|
||||
Description: `
|
||||
The makecache command generates an ethash cache in <outputDir>.
|
||||
|
||||
|
|
@ -45,12 +44,11 @@ This command exists to support the system testing project.
|
|||
Regular users do not need to execute it.
|
||||
`,
|
||||
}
|
||||
makedagCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(makedag),
|
||||
makedagCommand = &cli.Command{
|
||||
Action: makedag,
|
||||
Name: "makedag",
|
||||
Usage: "Generate ethash mining DAG (for testing)",
|
||||
ArgsUsage: "<blockNum> <outputDir>",
|
||||
Category: "MISCELLANEOUS COMMANDS",
|
||||
Description: `
|
||||
The makedag command generates an ethash DAG in <outputDir>.
|
||||
|
||||
|
|
@ -58,28 +56,26 @@ This command exists to support the system testing project.
|
|||
Regular users do not need to execute it.
|
||||
`,
|
||||
}
|
||||
versionCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(version),
|
||||
versionCommand = &cli.Command{
|
||||
Action: version,
|
||||
Name: "version",
|
||||
Usage: "Print version numbers",
|
||||
ArgsUsage: " ",
|
||||
Category: "MISCELLANEOUS COMMANDS",
|
||||
Description: `
|
||||
The output of this command is supposed to be machine-readable.
|
||||
`,
|
||||
}
|
||||
licenseCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(license),
|
||||
licenseCommand = &cli.Command{
|
||||
Action: license,
|
||||
Name: "license",
|
||||
Usage: "Display license information",
|
||||
ArgsUsage: " ",
|
||||
Category: "MISCELLANEOUS COMMANDS",
|
||||
}
|
||||
)
|
||||
|
||||
// makecache generates an ethash verification cache into the provided folder.
|
||||
func makecache(ctx *cli.Context) error {
|
||||
args := ctx.Args()
|
||||
args := ctx.Args().Slice()
|
||||
if len(args) != 2 {
|
||||
utils.Fatalf(`Usage: XDC makecache <block number> <outputdir>`)
|
||||
}
|
||||
|
|
@ -94,7 +90,7 @@ func makecache(ctx *cli.Context) error {
|
|||
|
||||
// makedag generates an ethash mining DAG into the provided folder.
|
||||
func makedag(ctx *cli.Context) error {
|
||||
args := ctx.Args()
|
||||
args := ctx.Args().Slice()
|
||||
if len(args) != 2 {
|
||||
utils.Fatalf(`Usage: XDC makedag <block number> <outputdir>`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,351 +0,0 @@
|
|||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of go-ethereum.
|
||||
//
|
||||
// go-ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// go-ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/cmd/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/node"
|
||||
"github.com/XinFinOrg/XDPoSChain/rpc"
|
||||
"github.com/gizak/termui"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
)
|
||||
|
||||
var (
|
||||
monitorCommandAttachFlag = cli.StringFlag{
|
||||
Name: "attach",
|
||||
Value: node.DefaultIPCEndpoint(clientIdentifier),
|
||||
Usage: "API endpoint to attach to",
|
||||
}
|
||||
monitorCommandRowsFlag = cli.IntFlag{
|
||||
Name: "rows",
|
||||
Value: 5,
|
||||
Usage: "Maximum rows in the chart grid",
|
||||
}
|
||||
monitorCommandRefreshFlag = cli.IntFlag{
|
||||
Name: "refresh",
|
||||
Value: 3,
|
||||
Usage: "Refresh interval in seconds",
|
||||
}
|
||||
monitorCommand = cli.Command{
|
||||
Action: utils.MigrateFlags(monitor), // keep track of migration progress
|
||||
Name: "monitor",
|
||||
Usage: "Monitor and visualize node metrics",
|
||||
ArgsUsage: " ",
|
||||
Category: "MONITOR COMMANDS",
|
||||
Description: `
|
||||
The XDC monitor is a tool to collect and visualize various internal metrics
|
||||
gathered by the node, supporting different chart types as well as the capacity
|
||||
to display multiple metrics simultaneously.
|
||||
`,
|
||||
Flags: []cli.Flag{
|
||||
monitorCommandAttachFlag,
|
||||
monitorCommandRowsFlag,
|
||||
monitorCommandRefreshFlag,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// monitor starts a terminal UI based monitoring tool for the requested metrics.
|
||||
func monitor(ctx *cli.Context) error {
|
||||
var (
|
||||
client *rpc.Client
|
||||
err error
|
||||
)
|
||||
// Attach to an Ethereum node over IPC or RPC
|
||||
endpoint := ctx.String(monitorCommandAttachFlag.Name)
|
||||
if client, err = dialRPC(endpoint); err != nil {
|
||||
utils.Fatalf("Unable to attach to XDC node: %v", err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// Retrieve all the available metrics and resolve the user pattens
|
||||
metrics, err := retrieveMetrics(client)
|
||||
if err != nil {
|
||||
utils.Fatalf("Failed to retrieve system metrics: %v", err)
|
||||
}
|
||||
monitored := resolveMetrics(metrics, ctx.Args())
|
||||
if len(monitored) == 0 {
|
||||
list := expandMetrics(metrics, "")
|
||||
sort.Strings(list)
|
||||
|
||||
if len(list) > 0 {
|
||||
utils.Fatalf("No metrics specified.\n\nAvailable:\n - %s", strings.Join(list, "\n - "))
|
||||
} else {
|
||||
utils.Fatalf("No metrics collected by XDC (--%s).\n", utils.MetricsEnabledFlag.Name)
|
||||
}
|
||||
}
|
||||
sort.Strings(monitored)
|
||||
if cols := len(monitored) / ctx.Int(monitorCommandRowsFlag.Name); cols > 6 {
|
||||
utils.Fatalf("Requested metrics (%d) spans more that 6 columns:\n - %s", len(monitored), strings.Join(monitored, "\n - "))
|
||||
}
|
||||
// Create and configure the chart UI defaults
|
||||
if err := termui.Init(); err != nil {
|
||||
utils.Fatalf("Unable to initialize terminal UI: %v", err)
|
||||
}
|
||||
defer termui.Close()
|
||||
|
||||
rows := len(monitored)
|
||||
if max := ctx.Int(monitorCommandRowsFlag.Name); rows > max {
|
||||
rows = max
|
||||
}
|
||||
cols := (len(monitored) + rows - 1) / rows
|
||||
for i := 0; i < rows; i++ {
|
||||
termui.Body.AddRows(termui.NewRow())
|
||||
}
|
||||
// Create each individual data chart
|
||||
footer := termui.NewPar("")
|
||||
footer.Block.Border = true
|
||||
footer.Height = 3
|
||||
|
||||
charts := make([]*termui.LineChart, len(monitored))
|
||||
units := make([]int, len(monitored))
|
||||
data := make([][]float64, len(monitored))
|
||||
for i := 0; i < len(monitored); i++ {
|
||||
charts[i] = createChart((termui.TermHeight() - footer.Height) / rows)
|
||||
row := termui.Body.Rows[i%rows]
|
||||
row.Cols = append(row.Cols, termui.NewCol(12/cols, 0, charts[i]))
|
||||
}
|
||||
termui.Body.AddRows(termui.NewRow(termui.NewCol(12, 0, footer)))
|
||||
|
||||
refreshCharts(client, monitored, data, units, charts, ctx, footer)
|
||||
termui.Body.Align()
|
||||
termui.Render(termui.Body)
|
||||
|
||||
// Watch for various system events, and periodically refresh the charts
|
||||
termui.Handle("/sys/kbd/C-c", func(termui.Event) {
|
||||
termui.StopLoop()
|
||||
})
|
||||
termui.Handle("/sys/wnd/resize", func(termui.Event) {
|
||||
termui.Body.Width = termui.TermWidth()
|
||||
for _, chart := range charts {
|
||||
chart.Height = (termui.TermHeight() - footer.Height) / rows
|
||||
}
|
||||
termui.Body.Align()
|
||||
termui.Render(termui.Body)
|
||||
})
|
||||
go func() {
|
||||
tick := time.NewTicker(time.Duration(ctx.Int(monitorCommandRefreshFlag.Name)) * time.Second)
|
||||
for range tick.C {
|
||||
if refreshCharts(client, monitored, data, units, charts, ctx, footer) {
|
||||
termui.Body.Align()
|
||||
}
|
||||
termui.Render(termui.Body)
|
||||
}
|
||||
}()
|
||||
termui.Loop()
|
||||
return nil
|
||||
}
|
||||
|
||||
// retrieveMetrics contacts the attached XDC node and retrieves the entire set
|
||||
// of collected system metrics.
|
||||
func retrieveMetrics(client *rpc.Client) (map[string]interface{}, error) {
|
||||
var metrics map[string]interface{}
|
||||
err := client.Call(&metrics, "debug_metrics", true)
|
||||
return metrics, err
|
||||
}
|
||||
|
||||
// resolveMetrics takes a list of input metric patterns, and resolves each to one
|
||||
// or more canonical metric names.
|
||||
func resolveMetrics(metrics map[string]interface{}, patterns []string) []string {
|
||||
res := []string{}
|
||||
for _, pattern := range patterns {
|
||||
res = append(res, resolveMetric(metrics, pattern, "")...)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// resolveMetrics takes a single of input metric pattern, and resolves it to one
|
||||
// or more canonical metric names.
|
||||
func resolveMetric(metrics map[string]interface{}, pattern string, path string) []string {
|
||||
results := []string{}
|
||||
|
||||
// If a nested metric was requested, recurse optionally branching (via comma)
|
||||
parts := strings.SplitN(pattern, "/", 2)
|
||||
if len(parts) > 1 {
|
||||
for _, variation := range strings.Split(parts[0], ",") {
|
||||
if submetrics, ok := metrics[variation].(map[string]interface{}); !ok {
|
||||
utils.Fatalf("Failed to retrieve system metrics: %s", path+variation)
|
||||
return nil
|
||||
} else {
|
||||
results = append(results, resolveMetric(submetrics, parts[1], path+variation+"/")...)
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
// Depending what the last link is, return or expand
|
||||
for _, variation := range strings.Split(pattern, ",") {
|
||||
switch metric := metrics[variation].(type) {
|
||||
case float64:
|
||||
// Final metric value found, return as singleton
|
||||
results = append(results, path+variation)
|
||||
|
||||
case map[string]interface{}:
|
||||
results = append(results, expandMetrics(metric, path+variation+"/")...)
|
||||
|
||||
default:
|
||||
utils.Fatalf("Metric pattern resolved to unexpected type: %v", reflect.TypeOf(metric))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// expandMetrics expands the entire tree of metrics into a flat list of paths.
|
||||
func expandMetrics(metrics map[string]interface{}, path string) []string {
|
||||
// Iterate over all fields and expand individually
|
||||
list := []string{}
|
||||
for name, metric := range metrics {
|
||||
switch metric := metric.(type) {
|
||||
case float64:
|
||||
// Final metric value found, append to list
|
||||
list = append(list, path+name)
|
||||
|
||||
case map[string]interface{}:
|
||||
// Tree of metrics found, expand recursively
|
||||
list = append(list, expandMetrics(metric, path+name+"/")...)
|
||||
|
||||
default:
|
||||
utils.Fatalf("Metric pattern %s resolved to unexpected type: %v", path+name, reflect.TypeOf(metric))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// fetchMetric iterates over the metrics map and retrieves a specific one.
|
||||
func fetchMetric(metrics map[string]interface{}, metric string) float64 {
|
||||
parts := strings.Split(metric, "/")
|
||||
for _, part := range parts[:len(parts)-1] {
|
||||
var found bool
|
||||
metrics, found = metrics[part].(map[string]interface{})
|
||||
if !found {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
if v, ok := metrics[parts[len(parts)-1]].(float64); ok {
|
||||
return v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// refreshCharts retrieves a next batch of metrics, and inserts all the new
|
||||
// values into the active datasets and charts
|
||||
func refreshCharts(client *rpc.Client, metrics []string, data [][]float64, units []int, charts []*termui.LineChart, ctx *cli.Context, footer *termui.Par) (realign bool) {
|
||||
values, err := retrieveMetrics(client)
|
||||
for i, metric := range metrics {
|
||||
if len(data) < 512 {
|
||||
data[i] = append([]float64{fetchMetric(values, metric)}, data[i]...)
|
||||
} else {
|
||||
data[i] = append([]float64{fetchMetric(values, metric)}, data[i][:len(data[i])-1]...)
|
||||
}
|
||||
if updateChart(metric, data[i], &units[i], charts[i], err) {
|
||||
realign = true
|
||||
}
|
||||
}
|
||||
updateFooter(ctx, err, footer)
|
||||
return
|
||||
}
|
||||
|
||||
// updateChart inserts a dataset into a line chart, scaling appropriately as to
|
||||
// not display weird labels, also updating the chart label accordingly.
|
||||
func updateChart(metric string, data []float64, base *int, chart *termui.LineChart, err error) (realign bool) {
|
||||
dataUnits := []string{"", "K", "M", "G", "T", "E"}
|
||||
timeUnits := []string{"ns", "µs", "ms", "s", "ks", "ms"}
|
||||
colors := []termui.Attribute{termui.ColorBlue, termui.ColorCyan, termui.ColorGreen, termui.ColorYellow, termui.ColorRed, termui.ColorRed}
|
||||
|
||||
// Extract only part of the data that's actually visible
|
||||
if chart.Width*2 < len(data) {
|
||||
data = data[:chart.Width*2]
|
||||
}
|
||||
// Find the maximum value and scale under 1K
|
||||
high := 0.0
|
||||
if len(data) > 0 {
|
||||
high = data[0]
|
||||
for _, value := range data[1:] {
|
||||
high = math.Max(high, value)
|
||||
}
|
||||
}
|
||||
unit, scale := 0, 1.0
|
||||
for high >= 1000 && unit+1 < len(dataUnits) {
|
||||
high, unit, scale = high/1000, unit+1, scale*1000
|
||||
}
|
||||
// If the unit changes, re-create the chart (hack to set max height...)
|
||||
if unit != *base {
|
||||
realign, *base, *chart = true, unit, *createChart(chart.Height)
|
||||
}
|
||||
// Update the chart's data points with the scaled values
|
||||
if cap(chart.Data) < len(data) {
|
||||
chart.Data = make([]float64, len(data))
|
||||
}
|
||||
chart.Data = chart.Data[:len(data)]
|
||||
for i, value := range data {
|
||||
chart.Data[i] = value / scale
|
||||
}
|
||||
// Update the chart's label with the scale units
|
||||
units := dataUnits
|
||||
if strings.Contains(metric, "/Percentiles/") || strings.Contains(metric, "/pauses/") || strings.Contains(metric, "/time/") {
|
||||
units = timeUnits
|
||||
}
|
||||
chart.BorderLabel = metric
|
||||
if len(units[unit]) > 0 {
|
||||
chart.BorderLabel += " [" + units[unit] + "]"
|
||||
}
|
||||
chart.LineColor = colors[unit] | termui.AttrBold
|
||||
if err != nil {
|
||||
chart.LineColor = termui.ColorRed | termui.AttrBold
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// createChart creates an empty line chart with the default configs.
|
||||
func createChart(height int) *termui.LineChart {
|
||||
chart := termui.NewLineChart()
|
||||
if runtime.GOOS == "windows" {
|
||||
chart.Mode = "dot"
|
||||
}
|
||||
chart.DataLabels = []string{""}
|
||||
chart.Height = height
|
||||
chart.AxesColor = termui.ColorWhite
|
||||
chart.PaddingBottom = -2
|
||||
|
||||
chart.BorderLabelFg = chart.BorderFg | termui.AttrBold
|
||||
chart.BorderFg = chart.BorderBg
|
||||
|
||||
return chart
|
||||
}
|
||||
|
||||
// updateFooter updates the footer contents based on any encountered errors.
|
||||
func updateFooter(ctx *cli.Context, err error, footer *termui.Par) {
|
||||
// Generate the basic footer
|
||||
refresh := time.Duration(ctx.Int(monitorCommandRefreshFlag.Name)) * time.Second
|
||||
footer.Text = fmt.Sprintf("Press Ctrl+C to quit. Refresh interval: %v.", refresh)
|
||||
footer.TextFgColor = termui.ThemeAttr("par.fg") | termui.AttrBold
|
||||
|
||||
// Append any encountered errors
|
||||
if err != nil {
|
||||
footer.Text = fmt.Sprintf("Error: %v.", err)
|
||||
footer.TextFgColor = termui.ColorRed | termui.AttrBold
|
||||
}
|
||||
}
|
||||
|
|
@ -66,12 +66,12 @@ func runXDC(t *testing.T, args ...string) *testXDC {
|
|||
tt := &testXDC{}
|
||||
tt.TestCmd = cmdtest.NewTestCmd(t, tt)
|
||||
for i, arg := range args {
|
||||
switch {
|
||||
case arg == "-datadir" || arg == "--datadir":
|
||||
switch arg {
|
||||
case "--datadir":
|
||||
if i < len(args)-1 {
|
||||
tt.Datadir = args[i+1]
|
||||
}
|
||||
case arg == "-etherbase" || arg == "--etherbase":
|
||||
case "--miner-etherbase":
|
||||
if i < len(args)-1 {
|
||||
tt.Etherbase = args[i+1]
|
||||
}
|
||||
|
|
@ -80,7 +80,7 @@ func runXDC(t *testing.T, args ...string) *testXDC {
|
|||
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() {
|
||||
|
|
|
|||
20
cmd/XDC/testdata/config.toml
vendored
20
cmd/XDC/testdata/config.toml
vendored
|
|
@ -5,24 +5,24 @@ NAT = "" # flag --nat
|
|||
[Eth]
|
||||
NetworkId = 89 # flag --networkid
|
||||
SyncMode = "full" # flag --syncmode
|
||||
GasPrice = 1 # flag --gasprice
|
||||
GasPrice = 1 # flag --miner-gasprice
|
||||
|
||||
[Shh]
|
||||
|
||||
[Node]
|
||||
DataDir = "node1/" # flag --datadir
|
||||
HTTPPort = 8501 # flag --rpcport
|
||||
HTTPHost = "localhost" # flags --rpcaddr & --rpc
|
||||
HTTPPort = 8501 # flag --http-port
|
||||
HTTPHost = "localhost" # flags --http-addr & --http
|
||||
# in 3 cases :
|
||||
# HTTPHost is "" == --rpc & --rpcaddr is not set
|
||||
# HTTPHost is "localhost" or "127.0.0.1" == only set --rpc
|
||||
# HTTPHost is other IP (ex : 192.168.1.1) = set 2 flags --rpc & --rpcaddr
|
||||
WSHost = "localhost" # flags --wsaddr & --ws . same option HTTPHost
|
||||
WSPort = 8546 # flag --wsport
|
||||
WSModules = ["eth","ssh"] #flag --wsapi
|
||||
# HTTPHost is "" == --http & --http-addr is not set
|
||||
# HTTPHost is "localhost" or "127.0.0.1" == only set --http
|
||||
# HTTPHost is other IP (ex : 192.168.1.1) = set 2 flags --http & --http-addr
|
||||
WSHost = "localhost" # flags --ws-addr & --ws . same option HTTPHost
|
||||
WSPort = 8546 # flag --ws-port
|
||||
WSModules = ["eth","ssh"] #flag --ws-api
|
||||
|
||||
|
||||
HTTPModules = ["personal","db","eth","net","web3","txpool","miner"] # flag --rpcapi
|
||||
HTTPModules = ["personal","db","eth","net","web3","txpool","miner"] # flag --http-api
|
||||
KeyStoreDir = "" # flag --keystore
|
||||
UserIdent = "" # flag --identity
|
||||
|
||||
|
|
|
|||
331
cmd/XDC/usage.go
331
cmd/XDC/usage.go
|
|
@ -1,331 +0,0 @@
|
|||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of go-ethereum.
|
||||
//
|
||||
// go-ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// go-ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Contains the XDC command usage template and generator.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sort"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/cmd/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/internal/debug"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
)
|
||||
|
||||
// AppHelpTemplate is the test template for the default, global app help topic.
|
||||
var AppHelpTemplate = `NAME:
|
||||
{{.App.Name}} - {{.App.Usage}}
|
||||
|
||||
Copyright (c) 2018 XDPoSChain
|
||||
|
||||
USAGE:
|
||||
{{.App.HelpName}} [options]{{if .App.Commands}} command [command options]{{end}} {{if .App.ArgsUsage}}{{.App.ArgsUsage}}{{else}}[arguments...]{{end}}
|
||||
{{if .App.Version}}
|
||||
VERSION:
|
||||
{{.App.Version}}
|
||||
{{end}}{{if len .App.Authors}}
|
||||
AUTHOR(S):
|
||||
{{range .App.Authors}}{{ . }}{{end}}
|
||||
{{end}}{{if .App.Commands}}
|
||||
COMMANDS:
|
||||
{{range .App.Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}}
|
||||
{{end}}{{end}}{{if .FlagGroups}}
|
||||
{{range .FlagGroups}}{{.Name}} OPTIONS:
|
||||
{{range .Flags}}{{.}}
|
||||
{{end}}
|
||||
{{end}}{{end}}{{if .App.Copyright }}
|
||||
COPYRIGHT:
|
||||
{{.App.Copyright}}
|
||||
{{end}}
|
||||
`
|
||||
|
||||
// flagGroup is a collection of flags belonging to a single topic.
|
||||
type flagGroup struct {
|
||||
Name string
|
||||
Flags []cli.Flag
|
||||
}
|
||||
|
||||
// AppHelpFlagGroups is the application flags, grouped by functionality.
|
||||
var AppHelpFlagGroups = []flagGroup{
|
||||
{
|
||||
Name: "XDPoSChain",
|
||||
Flags: []cli.Flag{
|
||||
configFileFlag,
|
||||
utils.DataDirFlag,
|
||||
utils.KeyStoreDirFlag,
|
||||
//utils.NoUSBFlag,
|
||||
utils.NetworkIdFlag,
|
||||
//utils.TestnetFlag,
|
||||
//utils.RinkebyFlag,
|
||||
utils.SyncModeFlag,
|
||||
utils.GCModeFlag,
|
||||
utils.EthStatsURLFlag,
|
||||
utils.IdentityFlag,
|
||||
//utils.LightServFlag,
|
||||
//utils.LightPeersFlag,
|
||||
//utils.LightKDFFlag,
|
||||
},
|
||||
},
|
||||
//{Name: "DEVELOPER CHAIN",
|
||||
// Flags: []cli.Flag{
|
||||
// utils.DeveloperFlag,
|
||||
// utils.DeveloperPeriodFlag,
|
||||
// },
|
||||
//},
|
||||
//{
|
||||
// Name: "ETHASH",
|
||||
// Flags: []cli.Flag{
|
||||
// utils.EthashCacheDirFlag,
|
||||
// utils.EthashCachesInMemoryFlag,
|
||||
// utils.EthashCachesOnDiskFlag,
|
||||
// utils.EthashDatasetDirFlag,
|
||||
// utils.EthashDatasetsInMemoryFlag,
|
||||
// utils.EthashDatasetsOnDiskFlag,
|
||||
// },
|
||||
//},
|
||||
//{
|
||||
// Name: "DASHBOARD",
|
||||
// Flags: []cli.Flag{
|
||||
// utils.DashboardEnabledFlag,
|
||||
// utils.DashboardAddrFlag,
|
||||
// utils.DashboardPortFlag,
|
||||
// utils.DashboardRefreshFlag,
|
||||
// utils.DashboardAssetsFlag,
|
||||
// },
|
||||
//},
|
||||
//{
|
||||
// Name: "TRANSACTION POOL",
|
||||
// Flags: []cli.Flag{
|
||||
// utils.TxPoolNoLocalsFlag,
|
||||
// utils.TxPoolJournalFlag,
|
||||
// utils.TxPoolRejournalFlag,
|
||||
// utils.TxPoolPriceLimitFlag,
|
||||
// utils.TxPoolPriceBumpFlag,
|
||||
// utils.TxPoolAccountSlotsFlag,
|
||||
// utils.TxPoolGlobalSlotsFlag,
|
||||
// utils.TxPoolAccountQueueFlag,
|
||||
// utils.TxPoolGlobalQueueFlag,
|
||||
// utils.TxPoolLifetimeFlag,
|
||||
// },
|
||||
//},
|
||||
{
|
||||
Name: "PERFORMANCE TUNING",
|
||||
Flags: []cli.Flag{
|
||||
utils.CacheFlag,
|
||||
utils.CacheDatabaseFlag,
|
||||
// utils.CacheGCFlag,
|
||||
// utils.TrieCacheGenFlag,
|
||||
utils.FDLimitFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "ACCOUNT",
|
||||
Flags: []cli.Flag{
|
||||
utils.UnlockedAccountFlag,
|
||||
utils.PasswordFileFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "API AND CONSOLE",
|
||||
Flags: []cli.Flag{
|
||||
utils.RPCEnabledFlag,
|
||||
utils.RPCGlobalGasCapFlag,
|
||||
utils.RPCListenAddrFlag,
|
||||
utils.RPCPortFlag,
|
||||
utils.RPCHttpWriteTimeoutFlag,
|
||||
utils.RPCApiFlag,
|
||||
utils.WSEnabledFlag,
|
||||
utils.WSListenAddrFlag,
|
||||
utils.WSPortFlag,
|
||||
utils.WSApiFlag,
|
||||
utils.WSAllowedOriginsFlag,
|
||||
utils.IPCDisabledFlag,
|
||||
utils.IPCPathFlag,
|
||||
utils.RPCCORSDomainFlag,
|
||||
utils.RPCVirtualHostsFlag,
|
||||
utils.RPCGlobalTxFeeCap,
|
||||
utils.JSpathFlag,
|
||||
utils.ExecFlag,
|
||||
utils.PreloadJSFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "NETWORKING",
|
||||
Flags: []cli.Flag{
|
||||
utils.BootnodesFlag,
|
||||
utils.BootnodesV4Flag,
|
||||
utils.BootnodesV5Flag,
|
||||
utils.ListenPortFlag,
|
||||
utils.MaxPeersFlag,
|
||||
utils.MaxPendingPeersFlag,
|
||||
utils.NATFlag,
|
||||
utils.NoDiscoverFlag,
|
||||
//utils.DiscoveryV5Flag,
|
||||
//utils.NetrestrictFlag,
|
||||
utils.NodeKeyFileFlag,
|
||||
utils.NodeKeyHexFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "STAKER",
|
||||
Flags: []cli.Flag{
|
||||
utils.StakingEnabledFlag,
|
||||
utils.StakerThreadsFlag,
|
||||
utils.EtherbaseFlag,
|
||||
utils.TargetGasLimitFlag,
|
||||
utils.GasPriceFlag,
|
||||
utils.ExtraDataFlag,
|
||||
},
|
||||
},
|
||||
//{
|
||||
// Name: "GAS PRICE ORACLE",
|
||||
// Flags: []cli.Flag{
|
||||
// utils.GpoBlocksFlag,
|
||||
// utils.GpoPercentileFlag,
|
||||
// utils.GpoMaxGasPriceFlag,
|
||||
// utils.GpoIgnoreGasPriceFlag,
|
||||
// },
|
||||
//},
|
||||
//{
|
||||
// Name: "VIRTUAL MACHINE",
|
||||
// Flags: []cli.Flag{
|
||||
// utils.VMEnableDebugFlag,
|
||||
// },
|
||||
//},
|
||||
{
|
||||
Name: "LOGGING AND DEBUGGING",
|
||||
Flags: append([]cli.Flag{
|
||||
utils.MetricsEnabledFlag,
|
||||
//utils.FakePoWFlag,
|
||||
//utils.NoCompactionFlag,
|
||||
}, debug.Flags...),
|
||||
},
|
||||
//{
|
||||
// Name: "WHISPER (EXPERIMENTAL)",
|
||||
// Flags: whisperFlags,
|
||||
//},
|
||||
{
|
||||
Name: "DEPRECATED",
|
||||
Flags: []cli.Flag{
|
||||
utils.FastSyncFlag,
|
||||
utils.LightModeFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "MISC",
|
||||
},
|
||||
}
|
||||
|
||||
// byCategory sorts an array of flagGroup by Name in the order
|
||||
// defined in AppHelpFlagGroups.
|
||||
type byCategory []flagGroup
|
||||
|
||||
func (a byCategory) Len() int { return len(a) }
|
||||
func (a byCategory) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a byCategory) Less(i, j int) bool {
|
||||
iCat, jCat := a[i].Name, a[j].Name
|
||||
iIdx, jIdx := len(AppHelpFlagGroups), len(AppHelpFlagGroups) // ensure non categorized flags come last
|
||||
|
||||
for i, group := range AppHelpFlagGroups {
|
||||
if iCat == group.Name {
|
||||
iIdx = i
|
||||
}
|
||||
if jCat == group.Name {
|
||||
jIdx = i
|
||||
}
|
||||
}
|
||||
|
||||
return iIdx < jIdx
|
||||
}
|
||||
|
||||
func flagCategory(flag cli.Flag) string {
|
||||
for _, category := range AppHelpFlagGroups {
|
||||
for _, flg := range category.Flags {
|
||||
if flg.GetName() == flag.GetName() {
|
||||
return category.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
return "MISC"
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Override the default app help template
|
||||
cli.AppHelpTemplate = AppHelpTemplate
|
||||
|
||||
// Define a one shot struct to pass to the usage template
|
||||
type helpData struct {
|
||||
App interface{}
|
||||
FlagGroups []flagGroup
|
||||
}
|
||||
|
||||
// Override the default app help printer, but only for the global app help
|
||||
originalHelpPrinter := cli.HelpPrinter
|
||||
cli.HelpPrinter = func(w io.Writer, tmpl string, data interface{}) {
|
||||
if tmpl == AppHelpTemplate {
|
||||
// Iterate over all the flags and add any uncategorized ones
|
||||
categorized := make(map[string]struct{})
|
||||
for _, group := range AppHelpFlagGroups {
|
||||
for _, flag := range group.Flags {
|
||||
categorized[flag.String()] = struct{}{}
|
||||
}
|
||||
}
|
||||
uncategorized := []cli.Flag{}
|
||||
for _, flag := range data.(*cli.App).Flags {
|
||||
if _, ok := categorized[flag.String()]; !ok {
|
||||
uncategorized = append(uncategorized, flag)
|
||||
}
|
||||
}
|
||||
if len(uncategorized) > 0 {
|
||||
// Append all ungategorized options to the misc group
|
||||
miscs := len(AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags)
|
||||
AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags = append(AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags, uncategorized...)
|
||||
|
||||
// Make sure they are removed afterwards
|
||||
defer func() {
|
||||
AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags = AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags[:miscs]
|
||||
}()
|
||||
}
|
||||
// Render out custom usage screen
|
||||
originalHelpPrinter(w, tmpl, helpData{data, AppHelpFlagGroups})
|
||||
} else if tmpl == utils.CommandHelpTemplate {
|
||||
// Iterate over all command specific flags and categorize them
|
||||
categorized := make(map[string][]cli.Flag)
|
||||
for _, flag := range data.(cli.Command).Flags {
|
||||
if _, ok := categorized[flag.String()]; !ok {
|
||||
categorized[flagCategory(flag)] = append(categorized[flagCategory(flag)], flag)
|
||||
}
|
||||
}
|
||||
|
||||
// sort to get a stable ordering
|
||||
sorted := make([]flagGroup, 0, len(categorized))
|
||||
for cat, flgs := range categorized {
|
||||
sorted = append(sorted, flagGroup{cat, flgs})
|
||||
}
|
||||
sort.Sort(byCategory(sorted))
|
||||
|
||||
// add sorted array to data and render with default printer
|
||||
originalHelpPrinter(w, tmpl, map[string]interface{}{
|
||||
"cmd": data,
|
||||
"categorizedFlags": sorted,
|
||||
})
|
||||
} else {
|
||||
originalHelpPrinter(w, tmpl, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,54 +18,101 @@ package main
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/compiler"
|
||||
"github.com/XinFinOrg/XDPoSChain/internal/flags"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
abiFlag = flag.String("abi", "", "Path to the Ethereum contract ABI json to bind")
|
||||
binFlag = flag.String("bin", "", "Path to the Ethereum contract bytecode (generate deploy method)")
|
||||
typFlag = flag.String("type", "", "Struct name for the binding (default = package name)")
|
||||
// Git SHA1 commit hash of the release (set via linker flags)
|
||||
gitCommit = ""
|
||||
|
||||
solFlag = flag.String("sol", "", "Path to the Ethereum contract Solidity source to build and bind")
|
||||
solcFlag = flag.String("solc", "solc", "Solidity compiler to use if source builds are requested")
|
||||
excFlag = flag.String("exc", "", "Comma separated types to exclude from binding")
|
||||
|
||||
pkgFlag = flag.String("pkg", "", "Package name to generate the binding into")
|
||||
outFlag = flag.String("out", "", "Output file for the generated binding (default = stdout)")
|
||||
langFlag = flag.String("lang", "go", "Destination language for the bindings (go, java, objc)")
|
||||
app *cli.App
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Parse and ensure all needed inputs are specified
|
||||
flag.Parse()
|
||||
var (
|
||||
// Flags needed by abigen
|
||||
abiFlag = &cli.StringFlag{
|
||||
Name: "abi",
|
||||
Usage: "Path to the Ethereum contract ABI json to bind",
|
||||
}
|
||||
binFlag = &cli.StringFlag{
|
||||
Name: "bin",
|
||||
Usage: "Path to the Ethereum contract bytecode (generate deploy method)",
|
||||
}
|
||||
typeFlag = &cli.StringFlag{
|
||||
Name: "type",
|
||||
Usage: "Struct name for the binding (default = package name)",
|
||||
}
|
||||
solFlag = &cli.StringFlag{
|
||||
Name: "sol",
|
||||
Usage: "Path to the Ethereum contract Solidity source to build and bind",
|
||||
}
|
||||
solcFlag = &cli.StringFlag{
|
||||
Name: "solc",
|
||||
Usage: "Solidity compiler to use if source builds are requested",
|
||||
Value: "solc",
|
||||
}
|
||||
excFlag = &cli.StringFlag{
|
||||
Name: "exc",
|
||||
Usage: "Comma separated types to exclude from binding",
|
||||
}
|
||||
pkgFlag = &cli.StringFlag{
|
||||
Name: "pkg",
|
||||
Usage: "Package name to generate the binding into",
|
||||
}
|
||||
outFlag = &cli.StringFlag{
|
||||
Name: "out",
|
||||
Usage: "Output file for the generated binding (default = stdout)",
|
||||
}
|
||||
langFlag = &cli.StringFlag{
|
||||
Name: "lang",
|
||||
Usage: "Destination language for the bindings (go)",
|
||||
Value: "go",
|
||||
}
|
||||
)
|
||||
|
||||
if *abiFlag == "" && *solFlag == "" {
|
||||
func init() {
|
||||
app = flags.NewApp(gitCommit, "ethereum checkpoint helper tool")
|
||||
app.Name = "abigen"
|
||||
app.Flags = []cli.Flag{
|
||||
abiFlag,
|
||||
binFlag,
|
||||
typeFlag,
|
||||
solFlag,
|
||||
solcFlag,
|
||||
excFlag,
|
||||
pkgFlag,
|
||||
outFlag,
|
||||
langFlag,
|
||||
}
|
||||
app.Action = abigen
|
||||
}
|
||||
|
||||
func abigen(c *cli.Context) error {
|
||||
if c.String(abiFlag.Name) == "" && c.String(solFlag.Name) == "" {
|
||||
fmt.Printf("No contract ABI (--abi) or Solidity source (--sol) specified\n")
|
||||
os.Exit(-1)
|
||||
} else if (*abiFlag != "" || *binFlag != "" || *typFlag != "") && *solFlag != "" {
|
||||
} else if (c.String(abiFlag.Name) != "" || c.String(binFlag.Name) != "" || c.String(typeFlag.Name) != "") && c.String(solFlag.Name) != "" {
|
||||
fmt.Printf("Contract ABI (--abi), bytecode (--bin) and type (--type) flags are mutually exclusive with the Solidity source (--sol) flag\n")
|
||||
os.Exit(-1)
|
||||
}
|
||||
if *pkgFlag == "" {
|
||||
if c.String(pkgFlag.Name) == "" {
|
||||
fmt.Printf("No destination package specified (--pkg)\n")
|
||||
os.Exit(-1)
|
||||
}
|
||||
var lang bind.Lang
|
||||
switch *langFlag {
|
||||
switch c.String(langFlag.Name) {
|
||||
case "go":
|
||||
lang = bind.LangGo
|
||||
case "java":
|
||||
lang = bind.LangJava
|
||||
case "objc":
|
||||
lang = bind.LangObjC
|
||||
default:
|
||||
fmt.Printf("Unsupported destination language \"%s\" (--lang)\n", *langFlag)
|
||||
fmt.Printf("Unsupported destination language \"%s\" (--lang)\n", c.String(langFlag.Name))
|
||||
os.Exit(-1)
|
||||
}
|
||||
// If the entire solidity code was specified, build and bind based on that
|
||||
|
|
@ -74,13 +121,13 @@ func main() {
|
|||
bins []string
|
||||
types []string
|
||||
)
|
||||
if *solFlag != "" {
|
||||
if c.String(solFlag.Name) != "" {
|
||||
// Generate the list of types to exclude from binding
|
||||
exclude := make(map[string]bool)
|
||||
for _, kind := range strings.Split(*excFlag, ",") {
|
||||
for _, kind := range strings.Split(c.String(excFlag.Name), ",") {
|
||||
exclude[strings.ToLower(kind)] = true
|
||||
}
|
||||
contracts, err := compiler.CompileSolidity(*solcFlag, *solFlag)
|
||||
contracts, err := compiler.CompileSolidity(c.String(solcFlag.Name), c.String(solFlag.Name))
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to build Solidity contract: %v\n", err)
|
||||
os.Exit(-1)
|
||||
|
|
@ -99,7 +146,7 @@ func main() {
|
|||
}
|
||||
} else {
|
||||
// Otherwise load up the ABI, optional bytecode and type name from the parameters
|
||||
abi, err := os.ReadFile(*abiFlag)
|
||||
abi, err := os.ReadFile(c.String(abiFlag.Name))
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to read input ABI: %v\n", err)
|
||||
os.Exit(-1)
|
||||
|
|
@ -107,33 +154,43 @@ func main() {
|
|||
abis = append(abis, string(abi))
|
||||
|
||||
bin := []byte{}
|
||||
if *binFlag != "" {
|
||||
if bin, err = os.ReadFile(*binFlag); err != nil {
|
||||
if c.String(binFlag.Name) != "" {
|
||||
if bin, err = os.ReadFile(c.String(binFlag.Name)); err != nil {
|
||||
fmt.Printf("Failed to read input bytecode: %v\n", err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
}
|
||||
bins = append(bins, string(bin))
|
||||
|
||||
kind := *typFlag
|
||||
kind := c.String(typeFlag.Name)
|
||||
if kind == "" {
|
||||
kind = *pkgFlag
|
||||
kind = c.String(pkgFlag.Name)
|
||||
}
|
||||
types = append(types, kind)
|
||||
}
|
||||
// Generate the contract binding
|
||||
code, err := bind.Bind(types, abis, bins, *pkgFlag, lang)
|
||||
code, err := bind.Bind(types, abis, bins, c.String(pkgFlag.Name), lang)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to generate ABI binding: %v\n", err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
// Either flush it out to a file or display on the standard output
|
||||
if *outFlag == "" {
|
||||
if c.String(outFlag.Name) == "" {
|
||||
fmt.Printf("%s\n", code)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
if err := os.WriteFile(*outFlag, []byte(code), 0600); err != nil {
|
||||
if err := os.WriteFile(c.String(outFlag.Name), []byte(code), 0600); err != nil {
|
||||
fmt.Printf("Failed to write ABI binding: %v\n", err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,10 +51,10 @@ func main() {
|
|||
)
|
||||
flag.Parse()
|
||||
|
||||
glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
|
||||
glogger.Verbosity(log.Lvl(*verbosity))
|
||||
glogger := log.NewGlogHandler(log.NewTerminalHandler(os.Stderr, false))
|
||||
glogger.Verbosity(log.FromLegacyLevel(*verbosity))
|
||||
glogger.Vmodule(*vmodule)
|
||||
log.Root().SetHandler(glogger)
|
||||
log.SetDefault(log.NewLogger(glogger))
|
||||
|
||||
natm, err := nat.Parse(*natdesc)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/cmd/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/pborman/uuid"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type outputGenerate struct {
|
||||
|
|
@ -34,7 +34,14 @@ type outputGenerate struct {
|
|||
AddressEIP55 string
|
||||
}
|
||||
|
||||
var commandGenerate = cli.Command{
|
||||
var (
|
||||
privateKeyFlag = &cli.StringFlag{
|
||||
Name: "privatekey",
|
||||
Usage: "file containing a raw private key to encrypt",
|
||||
}
|
||||
)
|
||||
|
||||
var commandGenerate = &cli.Command{
|
||||
Name: "generate",
|
||||
Usage: "generate new keyfile",
|
||||
ArgsUsage: "[ <keyfile> ]",
|
||||
|
|
@ -47,10 +54,7 @@ If you want to encrypt an existing private key, it can be specified by setting
|
|||
Flags: []cli.Flag{
|
||||
passphraseFlag,
|
||||
jsonFlag,
|
||||
cli.StringFlag{
|
||||
Name: "privatekey",
|
||||
Usage: "file containing a raw private key to encrypt",
|
||||
},
|
||||
privateKeyFlag,
|
||||
},
|
||||
Action: func(ctx *cli.Context) error {
|
||||
// Check if keyfile path given and make sure it doesn't already exist.
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/accounts/keystore"
|
||||
"github.com/XinFinOrg/XDPoSChain/cmd/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type outputInspect struct {
|
||||
|
|
@ -33,7 +33,14 @@ type outputInspect struct {
|
|||
PrivateKey string
|
||||
}
|
||||
|
||||
var commandInspect = cli.Command{
|
||||
var (
|
||||
privateFlag = &cli.BoolFlag{
|
||||
Name: "private",
|
||||
Usage: "include the private key in the output",
|
||||
}
|
||||
)
|
||||
|
||||
var commandInspect = &cli.Command{
|
||||
Name: "inspect",
|
||||
Usage: "inspect a keyfile",
|
||||
ArgsUsage: "<keyfile>",
|
||||
|
|
@ -45,10 +52,7 @@ make sure to use this feature with great caution!`,
|
|||
Flags: []cli.Flag{
|
||||
passphraseFlag,
|
||||
jsonFlag,
|
||||
cli.BoolFlag{
|
||||
Name: "private",
|
||||
Usage: "include the private key in the output",
|
||||
},
|
||||
privateFlag,
|
||||
},
|
||||
Action: func(ctx *cli.Context) error {
|
||||
keyfilepath := ctx.Args().First()
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/cmd/utils"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
"github.com/XinFinOrg/XDPoSChain/internal/flags"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -34,8 +34,8 @@ var gitCommit = ""
|
|||
var app *cli.App
|
||||
|
||||
func init() {
|
||||
app = utils.NewApp(gitCommit, "an Ethereum key manager")
|
||||
app.Commands = []cli.Command{
|
||||
app = flags.NewApp(gitCommit, "an Ethereum key manager")
|
||||
app.Commands = []*cli.Command{
|
||||
commandGenerate,
|
||||
commandInspect,
|
||||
commandSignMessage,
|
||||
|
|
@ -45,15 +45,15 @@ func init() {
|
|||
|
||||
// Commonly used command line flags.
|
||||
var (
|
||||
passphraseFlag = cli.StringFlag{
|
||||
passphraseFlag = &cli.StringFlag{
|
||||
Name: "passwordfile",
|
||||
Usage: "the file that contains the passphrase for the keyfile",
|
||||
Usage: "the file that contains the password for the keyfile",
|
||||
}
|
||||
jsonFlag = cli.BoolFlag{
|
||||
jsonFlag = &cli.BoolFlag{
|
||||
Name: "json",
|
||||
Usage: "output JSON instead of human-readable format",
|
||||
}
|
||||
messageFlag = cli.StringFlag{
|
||||
messageFlag = &cli.StringFlag{
|
||||
Name: "message",
|
||||
Usage: "the file that contains the message to sign/verify",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,19 +25,19 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/cmd/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type outputSign struct {
|
||||
Signature string
|
||||
}
|
||||
|
||||
var msgfileFlag = cli.StringFlag{
|
||||
var msgfileFlag = &cli.StringFlag{
|
||||
Name: "msgfile",
|
||||
Usage: "file containing the message to sign/verify",
|
||||
}
|
||||
|
||||
var commandSignMessage = cli.Command{
|
||||
var commandSignMessage = &cli.Command{
|
||||
Name: "signmessage",
|
||||
Usage: "sign a message",
|
||||
ArgsUsage: "<keyfile> <message>",
|
||||
|
|
@ -88,7 +88,7 @@ type outputVerify struct {
|
|||
RecoveredPublicKey string
|
||||
}
|
||||
|
||||
var commandVerifyMessage = cli.Command{
|
||||
var commandVerifyMessage = &cli.Command{
|
||||
Name: "verifymessage",
|
||||
Usage: "verify the signature of a signed message",
|
||||
ArgsUsage: "<address> <signature> <message>",
|
||||
|
|
@ -143,7 +143,7 @@ It is possible to refer to a file containing the message.`,
|
|||
|
||||
func getMessage(ctx *cli.Context, msgarg int) []byte {
|
||||
if file := ctx.String("msgfile"); file != "" {
|
||||
if len(ctx.Args()) > msgarg {
|
||||
if ctx.NArg() > msgarg {
|
||||
utils.Fatalf("Can't use --msgfile and message argument at the same time.")
|
||||
}
|
||||
msg, err := os.ReadFile(file)
|
||||
|
|
@ -151,9 +151,9 @@ func getMessage(ctx *cli.Context, msgarg int) []byte {
|
|||
utils.Fatalf("Can't read message file: %v", err)
|
||||
}
|
||||
return msg
|
||||
} else if len(ctx.Args()) == msgarg+1 {
|
||||
} else if ctx.NArg() == msgarg+1 {
|
||||
return []byte(ctx.Args().Get(msgarg))
|
||||
}
|
||||
utils.Fatalf("Invalid number of arguments: want %d, got %d", msgarg+1, len(ctx.Args()))
|
||||
utils.Fatalf("Invalid number of arguments: want %d, got %d", msgarg+1, ctx.NArg())
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/cmd/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/console"
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// getPassPhrase obtains a passphrase given by the user. It first checks the
|
||||
|
|
|
|||
|
|
@ -22,11 +22,10 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/cmd/evm/internal/compiler"
|
||||
|
||||
cli "gopkg.in/urfave/cli.v1"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var compileCommand = cli.Command{
|
||||
var compileCommand = &cli.Command{
|
||||
Action: compileCmd,
|
||||
Name: "compile",
|
||||
Usage: "compiles easm source to evm binary",
|
||||
|
|
@ -34,7 +33,7 @@ var compileCommand = cli.Command{
|
|||
}
|
||||
|
||||
func compileCmd(ctx *cli.Context) error {
|
||||
debug := ctx.GlobalBool(DebugFlag.Name)
|
||||
debug := ctx.Bool(DebugFlag.Name)
|
||||
|
||||
if len(ctx.Args().First()) == 0 {
|
||||
return errors.New("filename required")
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/core/asm"
|
||||
cli "gopkg.in/urfave/cli.v1"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var disasmCommand = cli.Command{
|
||||
var disasmCommand = &cli.Command{
|
||||
Action: disasmCmd,
|
||||
Name: "disasm",
|
||||
Usage: "disassembles evm binary",
|
||||
|
|
@ -34,17 +34,22 @@ var disasmCommand = cli.Command{
|
|||
}
|
||||
|
||||
func disasmCmd(ctx *cli.Context) error {
|
||||
if len(ctx.Args().First()) == 0 {
|
||||
return errors.New("filename required")
|
||||
var in string
|
||||
switch {
|
||||
case len(ctx.Args().First()) > 0:
|
||||
fn := ctx.Args().First()
|
||||
input, err := os.ReadFile(fn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
in = string(input)
|
||||
case ctx.IsSet(InputFlag.Name):
|
||||
in = ctx.String(InputFlag.Name)
|
||||
default:
|
||||
return errors.New("missing filename or --input value")
|
||||
}
|
||||
|
||||
fn := ctx.Args().First()
|
||||
in, err := os.ReadFile(fn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
code := strings.TrimSpace(string(in[:]))
|
||||
code := strings.TrimSpace(in)
|
||||
fmt.Printf("%v\n", code)
|
||||
return asm.PrintDisassembled(code)
|
||||
}
|
||||
|
|
|
|||
165
cmd/evm/main.go
165
cmd/evm/main.go
|
|
@ -22,93 +22,126 @@ import (
|
|||
"math/big"
|
||||
"os"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/cmd/utils"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
"github.com/XinFinOrg/XDPoSChain/internal/flags"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var gitCommit = "" // Git SHA1 commit hash of the release (set via linker flags)
|
||||
var (
|
||||
gitCommit = "" // Git SHA1 commit hash of the release (set via linker flags)
|
||||
|
||||
app = flags.NewApp(gitCommit, "the evm command line interface")
|
||||
)
|
||||
|
||||
var (
|
||||
app = utils.NewApp(gitCommit, "the evm command line interface")
|
||||
|
||||
DebugFlag = cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Usage: "output full trace logs",
|
||||
DebugFlag = &cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Usage: "output full trace logs",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
MemProfileFlag = cli.StringFlag{
|
||||
Name: "memprofile",
|
||||
Usage: "creates a memory profile at the given path",
|
||||
MemProfileFlag = &cli.StringFlag{
|
||||
Name: "memprofile",
|
||||
Usage: "creates a memory profile at the given path",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
CPUProfileFlag = cli.StringFlag{
|
||||
Name: "cpuprofile",
|
||||
Usage: "creates a CPU profile at the given path",
|
||||
CPUProfileFlag = &cli.StringFlag{
|
||||
Name: "cpuprofile",
|
||||
Usage: "creates a CPU profile at the given path",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
StatDumpFlag = cli.BoolFlag{
|
||||
Name: "statdump",
|
||||
Usage: "displays stack and heap memory information",
|
||||
StatDumpFlag = &cli.BoolFlag{
|
||||
Name: "statdump",
|
||||
Usage: "displays stack and heap memory information",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
CodeFlag = cli.StringFlag{
|
||||
Name: "code",
|
||||
Usage: "EVM code",
|
||||
CodeFlag = &cli.StringFlag{
|
||||
Name: "code",
|
||||
Usage: "EVM code",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
CodeFileFlag = cli.StringFlag{
|
||||
Name: "codefile",
|
||||
Usage: "File containing EVM code. If '-' is specified, code is read from stdin ",
|
||||
CodeFileFlag = &cli.StringFlag{
|
||||
Name: "codefile",
|
||||
Usage: "File containing EVM code. If '-' is specified, code is read from stdin ",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
GasFlag = cli.Uint64Flag{
|
||||
Name: "gas",
|
||||
Usage: "gas limit for the evm",
|
||||
Value: 10000000000,
|
||||
GasFlag = &cli.Uint64Flag{
|
||||
Name: "gas",
|
||||
Usage: "gas limit for the evm",
|
||||
Value: 10000000000,
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
PriceFlag = utils.BigFlag{
|
||||
Name: "price",
|
||||
Usage: "price set for the evm",
|
||||
Value: new(big.Int),
|
||||
PriceFlag = &flags.BigFlag{
|
||||
Name: "price",
|
||||
Usage: "price set for the evm",
|
||||
Value: new(big.Int),
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
ValueFlag = utils.BigFlag{
|
||||
Name: "value",
|
||||
Usage: "value set for the evm",
|
||||
Value: new(big.Int),
|
||||
ValueFlag = &flags.BigFlag{
|
||||
Name: "value",
|
||||
Usage: "value set for the evm",
|
||||
Value: new(big.Int),
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
DumpFlag = cli.BoolFlag{
|
||||
Name: "dump",
|
||||
Usage: "dumps the state after the run",
|
||||
DumpFlag = &cli.BoolFlag{
|
||||
Name: "dump",
|
||||
Usage: "dumps the state after the run",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
InputFlag = cli.StringFlag{
|
||||
Name: "input",
|
||||
Usage: "input for the EVM",
|
||||
InputFlag = &cli.StringFlag{
|
||||
Name: "input",
|
||||
Usage: "input for the EVM",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
VerbosityFlag = cli.IntFlag{
|
||||
Name: "verbosity",
|
||||
Usage: "sets the verbosity level",
|
||||
VerbosityFlag = &cli.IntFlag{
|
||||
Name: "verbosity",
|
||||
Usage: "sets the verbosity level",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
CreateFlag = cli.BoolFlag{
|
||||
Name: "create",
|
||||
Usage: "indicates the action should be create rather than call",
|
||||
CreateFlag = &cli.BoolFlag{
|
||||
Name: "create",
|
||||
Usage: "indicates the action should be create rather than call",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
GenesisFlag = cli.StringFlag{
|
||||
Name: "prestate",
|
||||
Usage: "JSON file with prestate (genesis) config",
|
||||
GenesisFlag = &cli.StringFlag{
|
||||
Name: "prestate",
|
||||
Usage: "JSON file with prestate (genesis) config",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
MachineFlag = cli.BoolFlag{
|
||||
Name: "json",
|
||||
Usage: "output trace logs in machine readable format (json)",
|
||||
MachineFlag = &cli.BoolFlag{
|
||||
Name: "json",
|
||||
Usage: "output trace logs in machine readable format (json)",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
SenderFlag = cli.StringFlag{
|
||||
Name: "sender",
|
||||
Usage: "The transaction origin",
|
||||
SenderFlag = &cli.StringFlag{
|
||||
Name: "sender",
|
||||
Usage: "The transaction origin",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
ReceiverFlag = cli.StringFlag{
|
||||
Name: "receiver",
|
||||
Usage: "The transaction receiver (execution context)",
|
||||
ReceiverFlag = &cli.StringFlag{
|
||||
Name: "receiver",
|
||||
Usage: "The transaction receiver (execution context)",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
DisableMemoryFlag = cli.BoolFlag{
|
||||
Name: "nomemory",
|
||||
Usage: "disable memory output",
|
||||
DisableMemoryFlag = &cli.BoolFlag{
|
||||
Name: "nomemory",
|
||||
Value: true,
|
||||
Usage: "disable memory output",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
DisableStackFlag = cli.BoolFlag{
|
||||
Name: "nostack",
|
||||
Usage: "disable stack output",
|
||||
DisableStackFlag = &cli.BoolFlag{
|
||||
Name: "nostack",
|
||||
Usage: "disable stack output",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
DisableStorageFlag = &cli.BoolFlag{
|
||||
Name: "nostorage",
|
||||
Usage: "disable storage output",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
DisableReturnDataFlag = &cli.BoolFlag{
|
||||
Name: "noreturndata",
|
||||
Value: true,
|
||||
Usage: "enable return data output",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -134,7 +167,7 @@ func init() {
|
|||
DisableMemoryFlag,
|
||||
DisableStackFlag,
|
||||
}
|
||||
app.Commands = []cli.Command{
|
||||
app.Commands = []*cli.Command{
|
||||
compileCommand,
|
||||
disasmCommand,
|
||||
runCommand,
|
||||
|
|
|
|||
|
|
@ -22,26 +22,24 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
goruntime "runtime"
|
||||
"runtime/pprof"
|
||||
"time"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||
|
||||
goruntime "runtime"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/cmd/evm/internal/compiler"
|
||||
"github.com/XinFinOrg/XDPoSChain/cmd/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/vm/runtime"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/XinFinOrg/XDPoSChain/internal/flags"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
cli "gopkg.in/urfave/cli.v1"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var runCommand = cli.Command{
|
||||
var runCommand = &cli.Command{
|
||||
Action: runCmd,
|
||||
Name: "run",
|
||||
Usage: "run arbitrary evm binary",
|
||||
|
|
@ -71,12 +69,12 @@ func readGenesis(genesisPath string) *core.Genesis {
|
|||
}
|
||||
|
||||
func runCmd(ctx *cli.Context) error {
|
||||
glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
|
||||
glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name)))
|
||||
log.Root().SetHandler(glogger)
|
||||
logconfig := &vm.LogConfig{
|
||||
EnableMemory: !ctx.GlobalBool(DisableMemoryFlag.Name),
|
||||
DisableStack: ctx.GlobalBool(DisableStackFlag.Name),
|
||||
EnableMemory: !ctx.Bool(DisableMemoryFlag.Name),
|
||||
DisableStack: ctx.Bool(DisableStackFlag.Name),
|
||||
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
|
||||
EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name),
|
||||
Debug: ctx.Bool(DebugFlag.Name),
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
@ -87,16 +85,17 @@ func runCmd(ctx *cli.Context) error {
|
|||
sender = common.StringToAddress("sender")
|
||||
receiver = common.StringToAddress("receiver")
|
||||
)
|
||||
if ctx.GlobalBool(MachineFlag.Name) {
|
||||
if ctx.Bool(MachineFlag.Name) {
|
||||
tracer = vm.NewJSONLogger(logconfig, os.Stdout)
|
||||
} else if ctx.GlobalBool(DebugFlag.Name) {
|
||||
} else if ctx.Bool(DebugFlag.Name) {
|
||||
debugLogger = vm.NewStructLogger(logconfig)
|
||||
tracer = debugLogger
|
||||
} else {
|
||||
debugLogger = vm.NewStructLogger(logconfig)
|
||||
}
|
||||
if ctx.GlobalString(GenesisFlag.Name) != "" {
|
||||
gen := readGenesis(ctx.GlobalString(GenesisFlag.Name))
|
||||
|
||||
if ctx.String(GenesisFlag.Name) != "" {
|
||||
gen := readGenesis(ctx.String(GenesisFlag.Name))
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
genesis := gen.ToBlock(db)
|
||||
statedb, _ = state.New(genesis.Root(), state.NewDatabase(db))
|
||||
|
|
@ -105,13 +104,13 @@ func runCmd(ctx *cli.Context) error {
|
|||
db := rawdb.NewMemoryDatabase()
|
||||
statedb, _ = state.New(common.Hash{}, state.NewDatabase(db))
|
||||
}
|
||||
if ctx.GlobalString(SenderFlag.Name) != "" {
|
||||
sender = common.HexToAddress(ctx.GlobalString(SenderFlag.Name))
|
||||
if ctx.String(SenderFlag.Name) != "" {
|
||||
sender = common.HexToAddress(ctx.String(SenderFlag.Name))
|
||||
}
|
||||
statedb.CreateAccount(sender)
|
||||
|
||||
if ctx.GlobalString(ReceiverFlag.Name) != "" {
|
||||
receiver = common.HexToAddress(ctx.GlobalString(ReceiverFlag.Name))
|
||||
if ctx.String(ReceiverFlag.Name) != "" {
|
||||
receiver = common.HexToAddress(ctx.String(ReceiverFlag.Name))
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
@ -120,11 +119,11 @@ func runCmd(ctx *cli.Context) error {
|
|||
err error
|
||||
)
|
||||
// The '--code' or '--codefile' flag overrides code in state
|
||||
if ctx.GlobalString(CodeFileFlag.Name) != "" {
|
||||
if ctx.String(CodeFileFlag.Name) != "" {
|
||||
var hexcode []byte
|
||||
var err error
|
||||
// If - is specified, it means that code comes from stdin
|
||||
if ctx.GlobalString(CodeFileFlag.Name) == "-" {
|
||||
if ctx.String(CodeFileFlag.Name) == "-" {
|
||||
//Try reading from stdin
|
||||
if hexcode, err = io.ReadAll(os.Stdin); err != nil {
|
||||
fmt.Printf("Could not load code from stdin: %v\n", err)
|
||||
|
|
@ -132,15 +131,15 @@ func runCmd(ctx *cli.Context) error {
|
|||
}
|
||||
} else {
|
||||
// Codefile with hex assembly
|
||||
if hexcode, err = os.ReadFile(ctx.GlobalString(CodeFileFlag.Name)); err != nil {
|
||||
if hexcode, err = os.ReadFile(ctx.String(CodeFileFlag.Name)); err != nil {
|
||||
fmt.Printf("Could not load code from file: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
code = common.Hex2Bytes(string(bytes.TrimRight(hexcode, "\n")))
|
||||
|
||||
} else if ctx.GlobalString(CodeFlag.Name) != "" {
|
||||
code = common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name))
|
||||
} else if ctx.String(CodeFlag.Name) != "" {
|
||||
code = common.Hex2Bytes(ctx.String(CodeFlag.Name))
|
||||
} else if fn := ctx.Args().First(); len(fn) > 0 {
|
||||
// EASM-file to compile
|
||||
src, err := os.ReadFile(fn)
|
||||
|
|
@ -154,20 +153,20 @@ func runCmd(ctx *cli.Context) error {
|
|||
code = common.Hex2Bytes(bin)
|
||||
}
|
||||
|
||||
initialGas := ctx.GlobalUint64(GasFlag.Name)
|
||||
initialGas := ctx.Uint64(GasFlag.Name)
|
||||
runtimeConfig := runtime.Config{
|
||||
Origin: sender,
|
||||
State: statedb,
|
||||
GasLimit: initialGas,
|
||||
GasPrice: utils.GlobalBig(ctx, PriceFlag.Name),
|
||||
Value: utils.GlobalBig(ctx, ValueFlag.Name),
|
||||
GasPrice: flags.GlobalBig(ctx, PriceFlag.Name),
|
||||
Value: flags.GlobalBig(ctx, ValueFlag.Name),
|
||||
EVMConfig: vm.Config{
|
||||
Tracer: tracer,
|
||||
Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name),
|
||||
Debug: ctx.Bool(DebugFlag.Name) || ctx.Bool(MachineFlag.Name),
|
||||
},
|
||||
}
|
||||
|
||||
if cpuProfilePath := ctx.GlobalString(CPUProfileFlag.Name); cpuProfilePath != "" {
|
||||
if cpuProfilePath := ctx.String(CPUProfileFlag.Name); cpuProfilePath != "" {
|
||||
f, err := os.Create(cpuProfilePath)
|
||||
if err != nil {
|
||||
fmt.Println("could not create CPU profile: ", err)
|
||||
|
|
@ -185,23 +184,23 @@ func runCmd(ctx *cli.Context) error {
|
|||
}
|
||||
tstart := time.Now()
|
||||
var leftOverGas uint64
|
||||
if ctx.GlobalBool(CreateFlag.Name) {
|
||||
input := append(code, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name))...)
|
||||
if ctx.Bool(CreateFlag.Name) {
|
||||
input := append(code, common.Hex2Bytes(ctx.String(InputFlag.Name))...)
|
||||
ret, _, leftOverGas, err = runtime.Create(input, &runtimeConfig)
|
||||
} else {
|
||||
if len(code) > 0 {
|
||||
statedb.SetCode(receiver, code)
|
||||
}
|
||||
ret, leftOverGas, err = runtime.Call(receiver, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtimeConfig)
|
||||
ret, leftOverGas, err = runtime.Call(receiver, common.Hex2Bytes(ctx.String(InputFlag.Name)), &runtimeConfig)
|
||||
}
|
||||
execTime := time.Since(tstart)
|
||||
|
||||
if ctx.GlobalBool(DumpFlag.Name) {
|
||||
if ctx.Bool(DumpFlag.Name) {
|
||||
statedb.IntermediateRoot(true)
|
||||
fmt.Println(string(statedb.Dump()))
|
||||
}
|
||||
|
||||
if memProfilePath := ctx.GlobalString(MemProfileFlag.Name); memProfilePath != "" {
|
||||
if memProfilePath := ctx.String(MemProfileFlag.Name); memProfilePath != "" {
|
||||
f, err := os.Create(memProfilePath)
|
||||
if err != nil {
|
||||
fmt.Println("could not create memory profile: ", err)
|
||||
|
|
@ -214,7 +213,7 @@ func runCmd(ctx *cli.Context) error {
|
|||
f.Close()
|
||||
}
|
||||
|
||||
if ctx.GlobalBool(DebugFlag.Name) {
|
||||
if ctx.Bool(DebugFlag.Name) {
|
||||
if debugLogger != nil {
|
||||
fmt.Fprintln(os.Stderr, "#### TRACE ####")
|
||||
vm.WriteTrace(os.Stderr, debugLogger.StructLogs())
|
||||
|
|
@ -223,7 +222,7 @@ func runCmd(ctx *cli.Context) error {
|
|||
vm.WriteLogs(os.Stderr, statedb.Logs())
|
||||
}
|
||||
|
||||
if ctx.GlobalBool(StatDumpFlag.Name) {
|
||||
if ctx.Bool(StatDumpFlag.Name) {
|
||||
var mem goruntime.MemStats
|
||||
goruntime.ReadMemStats(&mem)
|
||||
fmt.Fprintf(os.Stderr, `evm execution time: %v
|
||||
|
|
@ -238,7 +237,7 @@ Gas used: %d
|
|||
if tracer != nil {
|
||||
tracer.CaptureEnd(ret, initialGas-leftOverGas, execTime, err)
|
||||
} else {
|
||||
fmt.Printf("0x%x\n", ret)
|
||||
fmt.Printf("%#x\n", ret)
|
||||
if err != nil {
|
||||
fmt.Printf(" error: %v\n", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,13 +24,11 @@ import (
|
|||
|
||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/vm"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/XinFinOrg/XDPoSChain/tests"
|
||||
|
||||
cli "gopkg.in/urfave/cli.v1"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var stateTestCommand = cli.Command{
|
||||
var stateTestCommand = &cli.Command{
|
||||
Action: stateTestCmd,
|
||||
Name: "statetest",
|
||||
Usage: "executes the given state tests",
|
||||
|
|
@ -49,25 +47,24 @@ func stateTestCmd(ctx *cli.Context) error {
|
|||
if len(ctx.Args().First()) == 0 {
|
||||
return errors.New("path-to-test argument required")
|
||||
}
|
||||
// Configure the go-ethereum logger
|
||||
glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
|
||||
glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name)))
|
||||
log.Root().SetHandler(glogger)
|
||||
|
||||
// Configure the EVM logger
|
||||
config := &vm.LogConfig{
|
||||
EnableMemory: !ctx.GlobalBool(DisableMemoryFlag.Name),
|
||||
DisableStack: ctx.GlobalBool(DisableStackFlag.Name),
|
||||
EnableMemory: !ctx.Bool(DisableMemoryFlag.Name),
|
||||
DisableStack: ctx.Bool(DisableStackFlag.Name),
|
||||
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
|
||||
EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name),
|
||||
}
|
||||
|
||||
var (
|
||||
tracer vm.EVMLogger
|
||||
debugger *vm.StructLogger
|
||||
)
|
||||
switch {
|
||||
case ctx.GlobalBool(MachineFlag.Name):
|
||||
case ctx.Bool(MachineFlag.Name):
|
||||
tracer = vm.NewJSONLogger(config, os.Stderr)
|
||||
|
||||
case ctx.GlobalBool(DebugFlag.Name):
|
||||
case ctx.Bool(DebugFlag.Name):
|
||||
debugger = vm.NewStructLogger(config)
|
||||
tracer = debugger
|
||||
|
||||
|
|
@ -86,7 +83,7 @@ func stateTestCmd(ctx *cli.Context) error {
|
|||
// Iterate over all the tests, run them and aggregate the results
|
||||
cfg := vm.Config{
|
||||
Tracer: tracer,
|
||||
Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name),
|
||||
Debug: ctx.Bool(DebugFlag.Name) || ctx.Bool(MachineFlag.Name),
|
||||
}
|
||||
results := make([]StatetestResult, 0, len(tests))
|
||||
for key, test := range tests {
|
||||
|
|
@ -97,20 +94,20 @@ func stateTestCmd(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
// Test failed, mark as so and dump any state to aid debugging
|
||||
result.Pass, result.Error = false, err.Error()
|
||||
if ctx.GlobalBool(DumpFlag.Name) && state != nil {
|
||||
if ctx.Bool(DumpFlag.Name) && state != nil {
|
||||
dump := state.RawDump()
|
||||
result.State = &dump
|
||||
}
|
||||
}
|
||||
// print state root for evmlab tracing (already committed above, so no need to delete objects again
|
||||
if ctx.GlobalBool(MachineFlag.Name) && state != nil {
|
||||
if ctx.Bool(MachineFlag.Name) && state != nil {
|
||||
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%x\"}\n", state.IntermediateRoot(false))
|
||||
}
|
||||
|
||||
results = append(results, *result)
|
||||
|
||||
// Print any structured logs collected
|
||||
if ctx.GlobalBool(DebugFlag.Name) {
|
||||
if ctx.Bool(DebugFlag.Name) {
|
||||
if debugger != nil {
|
||||
fmt.Fprintln(os.Stderr, "#### TRACE ####")
|
||||
vm.WriteTrace(os.Stderr, debugger.StructLogs())
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ var (
|
|||
func main() {
|
||||
// Parse the flags and set up the logger to print everything requested
|
||||
flag.Parse()
|
||||
log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(*logFlag), log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||
log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.FromLegacyLevel(*logFlag), true)))
|
||||
|
||||
// Construct the payout tiers
|
||||
amounts := make([]string, *tiersFlag)
|
||||
|
|
@ -287,7 +287,7 @@ func newFaucet(genesis *core.Genesis, port int, enodes []*discv5.Node, network u
|
|||
|
||||
// close terminates the Ethereum connection and tears down the faucet.
|
||||
func (f *faucet) close() error {
|
||||
return f.stack.Stop()
|
||||
return f.stack.Close()
|
||||
}
|
||||
|
||||
// listenAndServe registers the HTTP handlers for the faucet and boots it up
|
||||
|
|
@ -396,7 +396,7 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
|
|||
continue
|
||||
}
|
||||
if msg.Tier >= uint(*tiersFlag) {
|
||||
if err = sendError(wsconn, errors.New("Invalid funding tier requested")); err != nil {
|
||||
if err = sendError(wsconn, errors.New("invalid funding tier requested")); err != nil {
|
||||
log.Warn("Failed to send tier error to client", "err", err)
|
||||
return
|
||||
}
|
||||
|
|
@ -433,7 +433,7 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
if !result.Success {
|
||||
log.Warn("Captcha verification failed", "err", string(result.Errors))
|
||||
if err = sendError(wsconn, errors.New("Beep-bop, you're a robot!")); err != nil {
|
||||
if err = sendError(wsconn, errors.New("beep-bop, you're a robot")); err != nil {
|
||||
log.Warn("Failed to send captcha failure to client", "err", err)
|
||||
return
|
||||
}
|
||||
|
|
@ -462,7 +462,7 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
|
|||
case *noauthFlag:
|
||||
username, avatar, address, err = authNoAuth(msg.URL)
|
||||
default:
|
||||
err = errors.New("Something funky happened, please open an issue at https://github.com/XinFinOrg/XDPoSChain/issues")
|
||||
err = errors.New("something funky happened, please open an issue at https://github.com/XinFinOrg/XDPoSChain/issues")
|
||||
}
|
||||
if err != nil {
|
||||
if err = sendError(wsconn, err); err != nil {
|
||||
|
|
@ -517,7 +517,7 @@ func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// Send an error if too frequent funding, othewise a success
|
||||
if !fund {
|
||||
if err = sendError(wsconn, fmt.Errorf("%s left until next allowance", common.PrettyDuration(timeout.Sub(time.Now())))); err != nil { // nolint: gosimple
|
||||
if err = sendError(wsconn, fmt.Errorf("%s left until next allowance", common.PrettyDuration(time.Until(timeout)))); err != nil {
|
||||
log.Warn("Failed to send funding error to client", "err", err)
|
||||
return
|
||||
}
|
||||
|
|
@ -657,7 +657,7 @@ func sendSuccess(conn *wsConn, msg string) error {
|
|||
func authGitHub(url string) (string, string, common.Address, error) {
|
||||
// Retrieve the gist from the GitHub Gist APIs
|
||||
parts := strings.Split(url, "/")
|
||||
req, _ := http.NewRequest("GET", "https://api.github.com/gists/"+parts[len(parts)-1], nil)
|
||||
req, _ := http.NewRequest(http.MethodGet, "https://api.github.com/gists/"+parts[len(parts)-1], nil)
|
||||
if *githubUser != "" {
|
||||
req.SetBasicAuth(*githubUser, *githubToken)
|
||||
}
|
||||
|
|
@ -679,7 +679,7 @@ func authGitHub(url string) (string, string, common.Address, error) {
|
|||
return "", "", common.Address{}, err
|
||||
}
|
||||
if gist.Owner.Login == "" {
|
||||
return "", "", common.Address{}, errors.New("Anonymous Gists not allowed")
|
||||
return "", "", common.Address{}, errors.New("anonymous gists not allowed")
|
||||
}
|
||||
// Iterate over all the files and look for Ethereum addresses
|
||||
var address common.Address
|
||||
|
|
@ -690,7 +690,7 @@ func authGitHub(url string) (string, string, common.Address, error) {
|
|||
}
|
||||
}
|
||||
if address == (common.Address{}) {
|
||||
return "", "", common.Address{}, errors.New("No Ethereum address found to fund")
|
||||
return "", "", common.Address{}, errors.New("no Ethereum address found to fund")
|
||||
}
|
||||
// Validate the user's existence since the API is unhelpful here
|
||||
if res, err = http.Head("https://github.com/" + gist.Owner.Login); err != nil {
|
||||
|
|
@ -699,7 +699,7 @@ func authGitHub(url string) (string, string, common.Address, error) {
|
|||
res.Body.Close()
|
||||
|
||||
if res.StatusCode != 200 {
|
||||
return "", "", common.Address{}, errors.New("Invalid user... boom!")
|
||||
return "", "", common.Address{}, errors.New("invalid user... boom")
|
||||
}
|
||||
// Everything passed validation, return the gathered infos
|
||||
return gist.Owner.Login + "@github", fmt.Sprintf("https://github.com/%s.png?size=64", gist.Owner.Login), address, nil
|
||||
|
|
@ -711,7 +711,7 @@ func authTwitter(url string) (string, string, common.Address, error) {
|
|||
// Ensure the user specified a meaningful URL, no fancy nonsense
|
||||
parts := strings.Split(url, "/")
|
||||
if len(parts) < 4 || parts[len(parts)-2] != "status" {
|
||||
return "", "", common.Address{}, errors.New("Invalid Twitter status URL")
|
||||
return "", "", common.Address{}, errors.New("invalid Twitter status URL")
|
||||
}
|
||||
// Twitter's API isn't really friendly with direct links. Still, we don't
|
||||
// want to do ask read permissions from users, so just load the public posts and
|
||||
|
|
@ -725,7 +725,7 @@ func authTwitter(url string) (string, string, common.Address, error) {
|
|||
// Resolve the username from the final redirect, no intermediate junk
|
||||
parts = strings.Split(res.Request.URL.String(), "/")
|
||||
if len(parts) < 4 || parts[len(parts)-2] != "status" {
|
||||
return "", "", common.Address{}, errors.New("Invalid Twitter status URL")
|
||||
return "", "", common.Address{}, errors.New("invalid Twitter status URL")
|
||||
}
|
||||
username := parts[len(parts)-3]
|
||||
|
||||
|
|
@ -735,7 +735,7 @@ func authTwitter(url string) (string, string, common.Address, error) {
|
|||
}
|
||||
address := common.HexToAddress(string(regexp.MustCompile("0x[0-9a-fA-F]{40}").Find(body)))
|
||||
if address == (common.Address{}) {
|
||||
return "", "", common.Address{}, errors.New("No Ethereum address found to fund")
|
||||
return "", "", common.Address{}, errors.New("no Ethereum address found to fund")
|
||||
}
|
||||
var avatar string
|
||||
if parts = regexp.MustCompile("src=\"([^\"]+twimg.com/profile_images[^\"]+)\"").FindStringSubmatch(string(body)); len(parts) == 2 {
|
||||
|
|
@ -750,7 +750,7 @@ func authGooglePlus(url string) (string, string, common.Address, error) {
|
|||
// Ensure the user specified a meaningful URL, no fancy nonsense
|
||||
parts := strings.Split(url, "/")
|
||||
if len(parts) < 4 || parts[len(parts)-2] != "posts" {
|
||||
return "", "", common.Address{}, errors.New("Invalid Google+ post URL")
|
||||
return "", "", common.Address{}, errors.New("invalid Google+ post URL")
|
||||
}
|
||||
username := parts[len(parts)-3]
|
||||
|
||||
|
|
@ -769,7 +769,7 @@ func authGooglePlus(url string) (string, string, common.Address, error) {
|
|||
}
|
||||
address := common.HexToAddress(string(regexp.MustCompile("0x[0-9a-fA-F]{40}").Find(body)))
|
||||
if address == (common.Address{}) {
|
||||
return "", "", common.Address{}, errors.New("No Ethereum address found to fund")
|
||||
return "", "", common.Address{}, errors.New("no Ethereum address found to fund")
|
||||
}
|
||||
var avatar string
|
||||
if parts = regexp.MustCompile("src=\"([^\"]+googleusercontent.com[^\"]+photo.jpg)\"").FindStringSubmatch(string(body)); len(parts) == 2 {
|
||||
|
|
@ -784,7 +784,7 @@ func authFacebook(url string) (string, string, common.Address, error) {
|
|||
// Ensure the user specified a meaningful URL, no fancy nonsense
|
||||
parts := strings.Split(url, "/")
|
||||
if len(parts) < 4 || parts[len(parts)-2] != "posts" {
|
||||
return "", "", common.Address{}, errors.New("Invalid Facebook post URL")
|
||||
return "", "", common.Address{}, errors.New("invalid Facebook post URL")
|
||||
}
|
||||
username := parts[len(parts)-3]
|
||||
|
||||
|
|
@ -803,7 +803,7 @@ func authFacebook(url string) (string, string, common.Address, error) {
|
|||
}
|
||||
address := common.HexToAddress(string(regexp.MustCompile("0x[0-9a-fA-F]{40}").Find(body)))
|
||||
if address == (common.Address{}) {
|
||||
return "", "", common.Address{}, errors.New("No Ethereum address found to fund")
|
||||
return "", "", common.Address{}, errors.New("no Ethereum address found to fund")
|
||||
}
|
||||
var avatar string
|
||||
if parts = regexp.MustCompile("src=\"([^\"]+fbcdn.net[^\"]+)\"").FindStringSubmatch(string(body)); len(parts) == 2 {
|
||||
|
|
@ -818,7 +818,7 @@ func authFacebook(url string) (string, string, common.Address, error) {
|
|||
func authNoAuth(url string) (string, string, common.Address, error) {
|
||||
address := common.HexToAddress(regexp.MustCompile("0x[0-9a-fA-F]{40}").FindString(url))
|
||||
if address == (common.Address{}) {
|
||||
return "", "", common.Address{}, errors.New("No Ethereum address found to fund")
|
||||
return "", "", common.Address{}, errors.New("no Ethereum address found to fund")
|
||||
}
|
||||
return address.Hex() + "@noauth", "", address, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,15 +92,15 @@ func faucetHtml() (*asset, error) {
|
|||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
func Asset(name string) ([]byte, error) {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
canonicalName := strings.ReplaceAll(name, "\\", "/")
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
|
||||
return nil, fmt.Errorf("can't read Asset %s by error: %v", name, err)
|
||||
}
|
||||
return a.bytes, nil
|
||||
}
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
return nil, fmt.Errorf("not found Asset %s", name)
|
||||
}
|
||||
|
||||
// AssetString returns the asset contents as a string (instead of a []byte).
|
||||
|
|
@ -130,29 +130,29 @@ func MustAssetString(name string) string {
|
|||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
func AssetInfo(name string) (os.FileInfo, error) {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
canonicalName := strings.ReplaceAll(name, "\\", "/")
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
|
||||
return nil, fmt.Errorf("can't read AssetInfo %s by error: %v", name, err)
|
||||
}
|
||||
return a.info, nil
|
||||
}
|
||||
return nil, fmt.Errorf("AssetInfo %s not found", name)
|
||||
return nil, fmt.Errorf("not found AssetInfo %s", name)
|
||||
}
|
||||
|
||||
// AssetDigest returns the digest of the file with the given name. It returns an
|
||||
// error if the asset could not be found or the digest could not be loaded.
|
||||
func AssetDigest(name string) ([sha256.Size]byte, error) {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
canonicalName := strings.ReplaceAll(name, "\\", "/")
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err)
|
||||
return [sha256.Size]byte{}, fmt.Errorf("can't read AssetDigest %s by error: %v", name, err)
|
||||
}
|
||||
return a.digest, nil
|
||||
}
|
||||
return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name)
|
||||
return [sha256.Size]byte{}, fmt.Errorf("not found AssetDigest %s", name)
|
||||
}
|
||||
|
||||
// Digests returns a map of all known files and their checksums.
|
||||
|
|
@ -203,17 +203,17 @@ const AssetDebug = false
|
|||
func AssetDir(name string) ([]string, error) {
|
||||
node := _bintree
|
||||
if len(name) != 0 {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
canonicalName := strings.ReplaceAll(name, "\\", "/")
|
||||
pathList := strings.Split(canonicalName, "/")
|
||||
for _, p := range pathList {
|
||||
node = node.Children[p]
|
||||
if node == nil {
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
return nil, fmt.Errorf("not found Asset %s", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
if node.Func != nil {
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
return nil, fmt.Errorf("not found Asset %s", name)
|
||||
}
|
||||
rv := make([]string, 0, len(node.Children))
|
||||
for childName := range node.Children {
|
||||
|
|
@ -270,6 +270,6 @@ func RestoreAssets(dir, name string) error {
|
|||
}
|
||||
|
||||
func _filePath(dir, name string) string {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
canonicalName := strings.ReplaceAll(name, "\\", "/")
|
||||
return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
"github.com/XinFinOrg/XDPoSChain/cmd/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/lru"
|
||||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
|
|
@ -20,7 +21,6 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/ethdb/leveldb"
|
||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||
"github.com/XinFinOrg/XDPoSChain/trie"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/lru"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -170,7 +170,7 @@ func getAllChilds(n StateNode, db *leveldb.Database) ([17]*StateNode, error) {
|
|||
}
|
||||
if err == nil {
|
||||
childs[i] = &StateNode{node: childNode, path: append(n.path, byte(i))}
|
||||
} else if err != nil {
|
||||
} else {
|
||||
_, ok := err.(*trie.MissingNodeError)
|
||||
if !ok {
|
||||
return childs, err
|
||||
|
|
@ -187,7 +187,7 @@ func getAllChilds(n StateNode, db *leveldb.Database) ([17]*StateNode, error) {
|
|||
}
|
||||
if err == nil {
|
||||
childs[0] = &StateNode{node: childNode, path: append(n.path, node.Key...)}
|
||||
} else if err != nil {
|
||||
} else {
|
||||
_, ok := err.(*trie.MissingNodeError)
|
||||
if !ok {
|
||||
return childs, err
|
||||
|
|
|
|||
|
|
@ -19,21 +19,20 @@
|
|||
// Here is an example of creating a 2 node network with the first node
|
||||
// connected to the second:
|
||||
//
|
||||
// $ p2psim node create
|
||||
// Created node01
|
||||
// $ p2psim node create
|
||||
// Created node01
|
||||
//
|
||||
// $ p2psim node start node01
|
||||
// Started node01
|
||||
// $ p2psim node start node01
|
||||
// Started node01
|
||||
//
|
||||
// $ p2psim node create
|
||||
// Created node02
|
||||
// $ p2psim node create
|
||||
// Created node02
|
||||
//
|
||||
// $ p2psim node start node02
|
||||
// Started node02
|
||||
//
|
||||
// $ p2psim node connect node01 node02
|
||||
// Connected node01 to node02
|
||||
// $ p2psim node start node02
|
||||
// Started node02
|
||||
//
|
||||
// $ p2psim node connect node01 node02
|
||||
// Connected node01 to node02
|
||||
package main
|
||||
|
||||
import (
|
||||
|
|
@ -46,32 +45,77 @@ import (
|
|||
"text/tabwriter"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
"github.com/XinFinOrg/XDPoSChain/internal/flags"
|
||||
"github.com/XinFinOrg/XDPoSChain/p2p"
|
||||
"github.com/XinFinOrg/XDPoSChain/p2p/discover"
|
||||
"github.com/XinFinOrg/XDPoSChain/p2p/simulations"
|
||||
"github.com/XinFinOrg/XDPoSChain/p2p/simulations/adapters"
|
||||
"github.com/XinFinOrg/XDPoSChain/rpc"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var client *simulations.Client
|
||||
|
||||
var (
|
||||
// global command flags
|
||||
apiFlag = &cli.StringFlag{
|
||||
Name: "api",
|
||||
Value: "http://localhost:8888",
|
||||
Usage: "simulation API URL",
|
||||
EnvVars: []string{"P2PSIM_API_URL"},
|
||||
}
|
||||
|
||||
// events subcommand flags
|
||||
currentFlag = &cli.BoolFlag{
|
||||
Name: "current",
|
||||
Usage: "get existing nodes and conns first",
|
||||
}
|
||||
filterFlag = &cli.StringFlag{
|
||||
Name: "filter",
|
||||
Value: "",
|
||||
Usage: "message filter",
|
||||
}
|
||||
|
||||
// node create subcommand flags
|
||||
nameFlag = &cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "",
|
||||
Usage: "node name",
|
||||
}
|
||||
servicesFlag = &cli.StringFlag{
|
||||
Name: "services",
|
||||
Value: "",
|
||||
Usage: "node services (comma separated)",
|
||||
}
|
||||
keyFlag = &cli.StringFlag{
|
||||
Name: "key",
|
||||
Value: "",
|
||||
Usage: "node private key (hex encoded)",
|
||||
}
|
||||
|
||||
// node rpc subcommand flags
|
||||
subscribeFlag = &cli.BoolFlag{
|
||||
Name: "subscribe",
|
||||
Usage: "method is a subscription",
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
// Git information set by linker when building with ci.go.
|
||||
gitCommit string
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app := flags.NewApp(gitCommit, "devp2p simulation command-line client")
|
||||
app.Usage = "devp2p simulation command-line client"
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "api",
|
||||
Value: "http://localhost:8888",
|
||||
Usage: "simulation API URL",
|
||||
EnvVar: "P2PSIM_API_URL",
|
||||
},
|
||||
apiFlag,
|
||||
}
|
||||
app.Before = func(ctx *cli.Context) error {
|
||||
client = simulations.NewClient(ctx.GlobalString("api"))
|
||||
client = simulations.NewClient(ctx.String("api"))
|
||||
return nil
|
||||
}
|
||||
app.Commands = []cli.Command{
|
||||
app.Commands = []*cli.Command{
|
||||
{
|
||||
Name: "show",
|
||||
Usage: "show network information",
|
||||
|
|
@ -82,15 +126,8 @@ func main() {
|
|||
Usage: "stream network events",
|
||||
Action: streamNetwork,
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "current",
|
||||
Usage: "get existing nodes and conns first",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "filter",
|
||||
Value: "",
|
||||
Usage: "message filter",
|
||||
},
|
||||
currentFlag,
|
||||
filterFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -107,7 +144,7 @@ func main() {
|
|||
Name: "node",
|
||||
Usage: "manage simulation nodes",
|
||||
Action: listNodes,
|
||||
Subcommands: []cli.Command{
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "list",
|
||||
Usage: "list nodes",
|
||||
|
|
@ -118,21 +155,9 @@ func main() {
|
|||
Usage: "create a node",
|
||||
Action: createNode,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "",
|
||||
Usage: "node name",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "services",
|
||||
Value: "",
|
||||
Usage: "node services (comma separated)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "key",
|
||||
Value: "",
|
||||
Usage: "node private key (hex encoded)",
|
||||
},
|
||||
nameFlag,
|
||||
servicesFlag,
|
||||
keyFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -171,10 +196,7 @@ func main() {
|
|||
Usage: "call a node RPC method",
|
||||
Action: rpcNode,
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "subscribe",
|
||||
Usage: "method is a subscription",
|
||||
},
|
||||
subscribeFlag,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -184,7 +206,7 @@ func main() {
|
|||
}
|
||||
|
||||
func showNetwork(ctx *cli.Context) error {
|
||||
if len(ctx.Args()) != 0 {
|
||||
if ctx.NArg() != 0 {
|
||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
network, err := client.GetNetwork()
|
||||
|
|
@ -199,7 +221,7 @@ func showNetwork(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
func streamNetwork(ctx *cli.Context) error {
|
||||
if len(ctx.Args()) != 0 {
|
||||
if ctx.NArg() != 0 {
|
||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
events := make(chan *simulations.Event)
|
||||
|
|
@ -225,7 +247,7 @@ func streamNetwork(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
func createSnapshot(ctx *cli.Context) error {
|
||||
if len(ctx.Args()) != 0 {
|
||||
if ctx.NArg() != 0 {
|
||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
snap, err := client.CreateSnapshot()
|
||||
|
|
@ -236,7 +258,7 @@ func createSnapshot(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
func loadSnapshot(ctx *cli.Context) error {
|
||||
if len(ctx.Args()) != 0 {
|
||||
if ctx.NArg() != 0 {
|
||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
snap := &simulations.Snapshot{}
|
||||
|
|
@ -247,7 +269,7 @@ func loadSnapshot(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
func listNodes(ctx *cli.Context) error {
|
||||
if len(ctx.Args()) != 0 {
|
||||
if ctx.NArg() != 0 {
|
||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
nodes, err := client.GetNodes()
|
||||
|
|
@ -272,7 +294,7 @@ func protocolList(node *p2p.NodeInfo) []string {
|
|||
}
|
||||
|
||||
func createNode(ctx *cli.Context) error {
|
||||
if len(ctx.Args()) != 0 {
|
||||
if ctx.NArg() != 0 {
|
||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
config := &adapters.NodeConfig{
|
||||
|
|
@ -298,11 +320,10 @@ func createNode(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
func showNode(ctx *cli.Context) error {
|
||||
args := ctx.Args()
|
||||
if len(args) != 1 {
|
||||
if ctx.NArg() != 1 {
|
||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
nodeName := args[0]
|
||||
nodeName := ctx.Args().First()
|
||||
node, err := client.GetNode(nodeName)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -323,11 +344,10 @@ func showNode(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
func startNode(ctx *cli.Context) error {
|
||||
args := ctx.Args()
|
||||
if len(args) != 1 {
|
||||
if ctx.NArg() != 1 {
|
||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
nodeName := args[0]
|
||||
nodeName := ctx.Args().First()
|
||||
if err := client.StartNode(nodeName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -336,11 +356,10 @@ func startNode(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
func stopNode(ctx *cli.Context) error {
|
||||
args := ctx.Args()
|
||||
if len(args) != 1 {
|
||||
if ctx.NArg() != 1 {
|
||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
nodeName := args[0]
|
||||
nodeName := ctx.Args().First()
|
||||
if err := client.StopNode(nodeName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -349,12 +368,12 @@ func stopNode(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
func connectNode(ctx *cli.Context) error {
|
||||
args := ctx.Args()
|
||||
if len(args) != 2 {
|
||||
if ctx.NArg() != 2 {
|
||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
nodeName := args[0]
|
||||
peerName := args[1]
|
||||
args := ctx.Args()
|
||||
nodeName := args.Get(0)
|
||||
peerName := args.Get(1)
|
||||
if err := client.ConnectNode(nodeName, peerName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -364,11 +383,11 @@ func connectNode(ctx *cli.Context) error {
|
|||
|
||||
func disconnectNode(ctx *cli.Context) error {
|
||||
args := ctx.Args()
|
||||
if len(args) != 2 {
|
||||
if args.Len() != 2 {
|
||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
nodeName := args[0]
|
||||
peerName := args[1]
|
||||
nodeName := args.Get(0)
|
||||
peerName := args.Get(1)
|
||||
if err := client.DisconnectNode(nodeName, peerName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -378,21 +397,21 @@ func disconnectNode(ctx *cli.Context) error {
|
|||
|
||||
func rpcNode(ctx *cli.Context) error {
|
||||
args := ctx.Args()
|
||||
if len(args) < 2 {
|
||||
if args.Len() < 2 {
|
||||
return cli.ShowCommandHelp(ctx, ctx.Command.Name)
|
||||
}
|
||||
nodeName := args[0]
|
||||
method := args[1]
|
||||
nodeName := args.Get(0)
|
||||
method := args.Get(1)
|
||||
rpcClient, err := client.RPCClient(context.Background(), nodeName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ctx.Bool("subscribe") {
|
||||
return rpcSubscribe(rpcClient, ctx.App.Writer, method, args[3:]...)
|
||||
return rpcSubscribe(rpcClient, ctx.App.Writer, method, args.Slice()[3:]...)
|
||||
}
|
||||
var result interface{}
|
||||
params := make([]interface{}, len(args[3:]))
|
||||
for i, v := range args[3:] {
|
||||
params := make([]interface{}, len(args.Slice()[3:]))
|
||||
for i, v := range args.Slice()[3:] {
|
||||
params[i] = v
|
||||
}
|
||||
if err := rpcClient.Call(&result, method, params...); err != nil {
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ func checkExplorer(client *sshClient, network string) (*explorerInfos, error) {
|
|||
// Run a sanity check to see if the devp2p is reachable
|
||||
nodePort := infos.portmap[infos.envvars["NODE_PORT"]]
|
||||
if err = checkPort(client.server, nodePort); err != nil {
|
||||
log.Warn(fmt.Sprintf("Explorer devp2p port seems unreachable"), "server", client.server, "port", nodePort, "err", err)
|
||||
log.Warn("Explorer devp2p port seems unreachable", "server", client.server, "port", nodePort, "err", err)
|
||||
}
|
||||
// Assemble and return the useful infos
|
||||
stats := &explorerInfos{
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue