diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e7666638c..8034c1d65 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,6 +4,7 @@ on: push: branches: - master + - dev pull_request: branches: @@ -14,7 +15,7 @@ jobs: env: CONTAINER_NAME: minter_node CONTAINER_TIMEOUT_SEC: 30 - API_RUN_PORT: 8841 + API_RUN_PORT: 8843 SECRET_DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_PASSWORD }} SECRET_DOCKER_HUB_USER: ${{ secrets.DOCKER_HUB_USER }} SECRET_DOCKER_HUB_REPO: ${{ secrets.DOCKER_HUB_REPO }} @@ -29,6 +30,8 @@ jobs: # if secret DOCKER_HUB_REPO is not set DOCKER_HUB_USER will be used instead of REPO # otherwise secrets are empty and repo "testbuild" will be used - name: Set envs + env: + ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true' run: | echo ::set-env name=VERSION::$(awk -F\" '/Version =/ { print $2; exit }' < version/version.go) echo ::set-env name=DOCKER_REPO::$(if [[ "$SECRET_DOCKER_HUB_REPO" == "" ]]; then if [[ "$SECRET_DOCKER_HUB_USER" == "" ]]; then echo "testbuild"; else echo "$SECRET_DOCKER_HUB_USER"; fi; else echo "$SECRET_DOCKER_HUB_REPO"; fi) @@ -37,13 +40,17 @@ jobs: run: docker build -t $DOCKER_REPO/$DOCKER_IMAGE:$VERSION . -f ./Dockerfile-ci - name: Start docker container - run: docker run -d --name $CONTAINER_NAME -p $API_RUN_PORT:8841 $DOCKER_REPO/$DOCKER_IMAGE:$VERSION + run: docker run -d --name $CONTAINER_NAME -p $API_RUN_PORT:8843 $DOCKER_REPO/$DOCKER_IMAGE:$VERSION - name: Check container is still running + env: + ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true' run: | echo ::set-env name=RUN_TEST_RESULT::$(sleep $CONTAINER_TIMEOUT_SEC && if [[ $(docker inspect -f "{{.State.Running}}" $CONTAINER_NAME 2> /dev/null) == true ]]; then echo OK; else echo FAIL; fi) - name: Check api is available by HTTP (response code is 200) + env: + ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true' run: | echo ::set-env name=API_TEST_RESULT::$(if [[ $(curl -LIs localhost:$API_RUN_PORT -o /dev/null -w '%{http_code}') == 200 ]]; then echo OK; else echo FAIL; fi) diff --git a/CHANGELOG.md b/CHANGELOG.md index c17aa81c8..e8adcadbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [v2.1.0](https://github.com/MinterTeam/minter-go-node/tree/v2.1.0) + +[Full Changelog](https://github.com/MinterTeam/minter-go-node/compare/v2.0.3...v2.1.0) + +### Fixed + +- Correction of votes + ## [v2.0.3](https://github.com/MinterTeam/minter-go-node/tree/v2.0.3) [Full Changelog](https://github.com/MinterTeam/minter-go-node/compare/v2.0.2...v2.0.3) diff --git a/coreV2/appdb/appdb.go b/coreV2/appdb/appdb.go index ff4dd3088..2e257693a 100644 --- a/coreV2/appdb/appdb.go +++ b/coreV2/appdb/appdb.go @@ -248,11 +248,9 @@ type Version struct { Height uint64 } -func (appDB *AppDB) GetVersion(height uint64) string { - appDB.GetVersions() - +func (appDB *AppDB) GetVersionName(height uint64) string { lastVersionName := "" - for _, version := range appDB.versions { + for _, version := range appDB.GetVersions() { if version.Height > height { return lastVersionName } @@ -262,6 +260,18 @@ func (appDB *AppDB) GetVersion(height uint64) string { return lastVersionName } +func (appDB *AppDB) GetVersionHeight(name string) uint64 { + var lastVersionHeight uint64 + for _, version := range appDB.GetVersions() { + if version.Name == name { + return lastVersionHeight + } + lastVersionHeight = version.Height + } + + return lastVersionHeight +} + func (appDB *AppDB) GetVersions() []*Version { if len(appDB.versions) == 0 { result, err := appDB.db.Get([]byte(versionsPath)) diff --git a/coreV2/minter/blockchain.go b/coreV2/minter/blockchain.go index c32f7f848..9f366cb3e 100644 --- a/coreV2/minter/blockchain.go +++ b/coreV2/minter/blockchain.go @@ -18,6 +18,7 @@ import ( tmjson "github.com/tendermint/tendermint/libs/json" tmNode "github.com/tendermint/tendermint/node" rpc "github.com/tendermint/tendermint/rpc/client/local" + "log" "math/big" "sync" "sync/atomic" @@ -64,13 +65,14 @@ type Blockchain struct { // currentMempool is responsive for prevent sending multiple transactions from one address in one block currentMempool *sync.Map - lock sync.RWMutex - haltHeight uint64 - cfg *config.Config - storages *utils.Storage - stopChan context.Context - stopped bool - grace *upgrades.Grace + lock sync.RWMutex + haltHeight uint64 + cfg *config.Config + storages *utils.Storage + stopChan context.Context + stopped bool + grace *upgrades.Grace + knownUpdates map[string]struct{} } // NewMinterBlockchain creates Minter Blockchain instance, should be only called once @@ -107,6 +109,12 @@ func NewMinterBlockchain(storages *utils.Storage, cfg *config.Config, ctx contex return app } +func graceForUpdate(height uint64) *upgrades.GracePeriod { + return upgrades.NewGracePeriod(height, height+120) +} + +const haltBlockV210 = 3431238 + func (blockchain *Blockchain) initState() { initialHeight := blockchain.appDB.GetStartHeight() currentHeight := blockchain.appDB.GetLastHeight() @@ -126,7 +134,15 @@ func (blockchain *Blockchain) initState() { blockchain.stateCheck = state.NewCheckState(stateDeliver) grace := upgrades.NewGrace() - grace.AddGracePeriods(upgrades.NewGracePeriod(initialHeight, initialHeight+120)) + grace.AddGracePeriods(upgrades.NewGracePeriod(initialHeight, initialHeight+120), + upgrades.NewGracePeriod(haltBlockV210, haltBlockV210+120)) + blockchain.knownUpdates = map[string]struct{}{ + "": {}, // default version + // add more for update + } + for _, v := range blockchain.UpdateVersions() { + grace.AddGracePeriods(graceForUpdate(v.Height)) + } blockchain.grace = grace } @@ -196,7 +212,15 @@ func (blockchain *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTy blockchain.calculatePowers(blockchain.stateDeliver.Validators.GetValidators()) - if blockchain.isApplicationHalted(height) { + if blockchain.isApplicationHalted(height) && !blockchain.grace.IsUpgradeBlock(height) { + log.Printf("Application halted at height %d\n", height) + blockchain.stop() + return abciTypes.ResponseBeginBlock{} + } + + versionName := blockchain.appDB.GetVersionName(height) + if _, ok := blockchain.knownUpdates[versionName]; !ok { + log.Printf("Update your node binary to the latest version: %s", versionName) blockchain.stop() return abciTypes.ResponseBeginBlock{} } @@ -290,64 +314,75 @@ func (blockchain *Blockchain) EndBlock(req abciTypes.RequestEndBlock) abciTypes. blockchain.stateDeliver.Validators.PayRewards() } - if prices := blockchain.isUpdateCommissionsBlock(height); len(prices) != 0 { - blockchain.stateDeliver.Commission.SetNewCommissions(prices) - price := blockchain.stateDeliver.Commission.GetCommissions() - blockchain.eventsDB.AddEvent(&eventsdb.UpdateCommissionsEvent{ - Coin: uint64(price.Coin), - PayloadByte: price.PayloadByte.String(), - Send: price.Send.String(), - BuyBancor: price.BuyBancor.String(), - SellBancor: price.SellBancor.String(), - SellAllBancor: price.SellAllBancor.String(), - BuyPoolBase: price.BuyPoolBase.String(), - BuyPoolDelta: price.BuyPoolDelta.String(), - SellPoolBase: price.SellPoolBase.String(), - SellPoolDelta: price.SellPoolDelta.String(), - SellAllPoolBase: price.SellAllPoolBase.String(), - SellAllPoolDelta: price.SellAllPoolDelta.String(), - CreateTicker3: price.CreateTicker3.String(), - CreateTicker4: price.CreateTicker4.String(), - CreateTicker5: price.CreateTicker5.String(), - CreateTicker6: price.CreateTicker6.String(), - CreateTicker7_10: price.CreateTicker7to10.String(), - CreateCoin: price.CreateCoin.String(), - CreateToken: price.CreateToken.String(), - RecreateCoin: price.RecreateCoin.String(), - RecreateToken: price.RecreateToken.String(), - DeclareCandidacy: price.DeclareCandidacy.String(), - Delegate: price.Delegate.String(), - Unbond: price.Unbond.String(), - RedeemCheck: price.RedeemCheck.String(), - SetCandidateOn: price.SetCandidateOn.String(), - SetCandidateOff: price.SetCandidateOff.String(), - CreateMultisig: price.CreateMultisig.String(), - MultisendBase: price.MultisendBase.String(), - MultisendDelta: price.MultisendDelta.String(), - EditCandidate: price.EditCandidate.String(), - SetHaltBlock: price.SetHaltBlock.String(), - EditTickerOwner: price.EditTickerOwner.String(), - EditMultisig: price.EditMultisig.String(), - EditCandidatePublicKey: price.EditCandidatePublicKey.String(), - CreateSwapPool: price.CreateSwapPool.String(), - AddLiquidity: price.AddLiquidity.String(), - RemoveLiquidity: price.RemoveLiquidity.String(), - EditCandidateCommission: price.EditCandidateCommission.String(), - MintToken: price.MintToken.String(), - BurnToken: price.BurnToken.String(), - VoteCommission: price.VoteCommission.String(), - VoteUpdate: price.VoteUpdate.String(), - }) - } - blockchain.stateDeliver.Commission.Delete(height) - - if v, ok := blockchain.isUpdateNetworkBlock(height); ok { - blockchain.appDB.AddVersion(v, height) - blockchain.eventsDB.AddEvent(&eventsdb.UpdateNetworkEvent{ - Version: v, - }) - } - blockchain.stateDeliver.Updates.Delete(height) + { + var updateCommissionsBlockPrices []byte + if height < haltBlockV210 { + updateCommissionsBlockPrices = blockchain.isUpdateCommissionsBlock(height) + } else { + updateCommissionsBlockPrices = blockchain.isUpdateCommissionsBlockV2(height) + } + if prices := updateCommissionsBlockPrices; len(prices) != 0 { + blockchain.stateDeliver.Commission.SetNewCommissions(prices) + price := blockchain.stateDeliver.Commission.GetCommissions() + blockchain.eventsDB.AddEvent(&eventsdb.UpdateCommissionsEvent{ + Coin: uint64(price.Coin), + PayloadByte: price.PayloadByte.String(), + Send: price.Send.String(), + BuyBancor: price.BuyBancor.String(), + SellBancor: price.SellBancor.String(), + SellAllBancor: price.SellAllBancor.String(), + BuyPoolBase: price.BuyPoolBase.String(), + BuyPoolDelta: price.BuyPoolDelta.String(), + SellPoolBase: price.SellPoolBase.String(), + SellPoolDelta: price.SellPoolDelta.String(), + SellAllPoolBase: price.SellAllPoolBase.String(), + SellAllPoolDelta: price.SellAllPoolDelta.String(), + CreateTicker3: price.CreateTicker3.String(), + CreateTicker4: price.CreateTicker4.String(), + CreateTicker5: price.CreateTicker5.String(), + CreateTicker6: price.CreateTicker6.String(), + CreateTicker7_10: price.CreateTicker7to10.String(), + CreateCoin: price.CreateCoin.String(), + CreateToken: price.CreateToken.String(), + RecreateCoin: price.RecreateCoin.String(), + RecreateToken: price.RecreateToken.String(), + DeclareCandidacy: price.DeclareCandidacy.String(), + Delegate: price.Delegate.String(), + Unbond: price.Unbond.String(), + RedeemCheck: price.RedeemCheck.String(), + SetCandidateOn: price.SetCandidateOn.String(), + SetCandidateOff: price.SetCandidateOff.String(), + CreateMultisig: price.CreateMultisig.String(), + MultisendBase: price.MultisendBase.String(), + MultisendDelta: price.MultisendDelta.String(), + EditCandidate: price.EditCandidate.String(), + SetHaltBlock: price.SetHaltBlock.String(), + EditTickerOwner: price.EditTickerOwner.String(), + EditMultisig: price.EditMultisig.String(), + EditCandidatePublicKey: price.EditCandidatePublicKey.String(), + CreateSwapPool: price.CreateSwapPool.String(), + AddLiquidity: price.AddLiquidity.String(), + RemoveLiquidity: price.RemoveLiquidity.String(), + EditCandidateCommission: price.EditCandidateCommission.String(), + MintToken: price.MintToken.String(), + BurnToken: price.BurnToken.String(), + VoteCommission: price.VoteCommission.String(), + VoteUpdate: price.VoteUpdate.String(), + }) + } + blockchain.stateDeliver.Commission.Delete(height) + } + + { + if v, ok := blockchain.isUpdateNetworkBlockV2(height); ok { + blockchain.appDB.AddVersion(v, height) + blockchain.eventsDB.AddEvent(&eventsdb.UpdateNetworkEvent{ + Version: v, + }) + blockchain.grace.AddGracePeriods(graceForUpdate(height)) + } + blockchain.stateDeliver.Updates.Delete(height) + } hasChangedPublicKeys := false if blockchain.stateDeliver.Candidates.IsChangedPublicKeys() { diff --git a/coreV2/minter/minter.go b/coreV2/minter/minter.go index 1ad9e5d31..60d3b4af4 100644 --- a/coreV2/minter/minter.go +++ b/coreV2/minter/minter.go @@ -294,6 +294,7 @@ func (blockchain *Blockchain) isApplicationHalted(height uint64) bool { return false } +// Deprecated func (blockchain *Blockchain) isUpdateCommissionsBlock(height uint64) []byte { commissions := blockchain.stateDeliver.Commission.GetVotes(height) if len(commissions) == 0 { @@ -326,16 +327,49 @@ func (blockchain *Blockchain) isUpdateCommissionsBlock(height uint64) []byte { return nil } -func (blockchain *Blockchain) isUpdateNetworkBlock(height uint64) (string, bool) { +func (blockchain *Blockchain) isUpdateCommissionsBlockV2(height uint64) []byte { + commissions := blockchain.stateDeliver.Commission.GetVotes(height) + if len(commissions) == 0 { + return nil + } + // calculate total power of validators + maxVotingResult := big.NewFloat(0) + + var price string + for _, commission := range commissions { + totalVotedPower := big.NewInt(0) + for _, vote := range commission.Votes { + if power, ok := blockchain.validatorsPowers[vote]; ok { + totalVotedPower.Add(totalVotedPower, power) + } + } + votingResult := new(big.Float).Quo( + new(big.Float).SetInt(totalVotedPower), + new(big.Float).SetInt(blockchain.totalPower), + ) + + if maxVotingResult.Cmp(votingResult) == -1 { + maxVotingResult = votingResult + price = commission.Price + } + } + if maxVotingResult.Cmp(big.NewFloat(votingPowerConsensus)) == 1 { + return []byte(price) + } + + return nil +} + +func (blockchain *Blockchain) isUpdateNetworkBlockV2(height uint64) (string, bool) { versions := blockchain.stateDeliver.Updates.GetVotes(height) if len(versions) == 0 { return "", false } // calculate total power of validators - maxVotingResult, totalVotedPower := big.NewFloat(0), big.NewInt(0) - + maxVotingResult := big.NewFloat(0) var version string for _, v := range versions { + totalVotedPower := big.NewInt(0) for _, vote := range v.Votes { if power, ok := blockchain.validatorsPowers[vote]; ok { totalVotedPower.Add(totalVotedPower, power) diff --git a/coreV2/transaction/sell_coin_test.go b/coreV2/transaction/sell_coin_test.go index bbda9bbd0..5adaf6778 100644 --- a/coreV2/transaction/sell_coin_test.go +++ b/coreV2/transaction/sell_coin_test.go @@ -653,13 +653,14 @@ func TestSellCoinTxCustomToCustomCustom2Commission(t *testing.T) { // check received coins buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuyID) bipReturn := formula.CalculateSaleReturn(initialVolume1, initialReserve1, crr1, toSell) - estimatedReturn := formula.CalculatePurchaseReturn(initialVolume2, initialReserve2, crr2, bipReturn) commissions := cState.Commission.GetCommissions() commissionInBaseCoin := tx.Commission(tx.Price(commissions)) if !commissions.Coin.IsBaseCoin() { commissionInBaseCoin = cState.Swap.GetSwapper(types.GetBaseCoinID(), commissions.Coin).CalculateSellForBuy(commissionInBaseCoin) } - commission := formula.CalculateSaleAmount(big.NewInt(0).Add(initialVolume2, estimatedReturn), big.NewInt(0).Add(initialReserve2, bipReturn), crr2, commissionInBaseCoin) + commission := formula.CalculateSaleAmount(initialVolume2, initialReserve2, crr2, commissionInBaseCoin) + + estimatedReturn := formula.CalculatePurchaseReturn(big.NewInt(0).Sub(initialVolume2, commission), big.NewInt(0).Sub(initialReserve2, commissionInBaseCoin), crr2, bipReturn) estimatedBuyBalance := big.NewInt(0).Set(estimatedReturn) estimatedBuyBalance.Sub(estimatedBuyBalance, commission) @@ -704,7 +705,7 @@ func TestSellCoinTxCustomToCustomCustom2Commission(t *testing.T) { } estimatedSupply := big.NewInt(0).Set(initialVolume2) - estimatedSupply.Add(estimatedSupply, formula.CalculatePurchaseReturn(initialVolume2, initialReserve2, crr2, formula.CalculateSaleReturn(initialVolume1, initialReserve1, crr1, toSell))) + estimatedSupply.Add(estimatedSupply, formula.CalculatePurchaseReturn(big.NewInt(0).Sub(initialVolume2, commission), big.NewInt(0).Sub(initialReserve2, commissionInBaseCoin), crr2, formula.CalculateSaleReturn(initialVolume1, initialReserve1, crr1, toSell))) estimatedSupply.Sub(estimatedSupply, commission) if coinData.Volume().Cmp(estimatedSupply) != 0 { t.Fatalf("Wrong coin supply") diff --git a/tests/byz_test.go b/tests/byz_test.go index 79c0e8f0c..469918aa8 100644 --- a/tests/byz_test.go +++ b/tests/byz_test.go @@ -85,8 +85,8 @@ func TestBlockchain_ByzantineValidators(t *testing.T) { app.BeginBlock(req) // SendBeginBlock(app) // send BeginBlock - SendEndBlock(app) // send EndBlock - SendCommit(app) // send Commit + SendEndBlock(app, 1) // send EndBlock + SendCommit(app) // send Commit if validator := app.CurrentState().Validators().GetByPublicKey([32]byte{1}); validator != nil { t.Error("validator exists") diff --git a/tests/helpers_test.go b/tests/helpers_test.go index 474825852..dc65622d8 100644 --- a/tests/helpers_test.go +++ b/tests/helpers_test.go @@ -27,12 +27,14 @@ func CreateApp(state types.AppState) *minter.Blockchain { cfg := config.GetConfig(storage.GetMinterHome()) cfg.DBBackend = "memdb" app := minter.NewMinterBlockchain(storage, cfg, nil, 120) + var updates []tmTypes.ValidatorUpdate + for _, validator := range state.Validators { + updates = append(updates, tmTypes.Ed25519ValidatorUpdate(validator.PubKey.Bytes(), 1)) + } app.InitChain(tmTypes.RequestInitChain{ - Time: time.Now(), - ChainId: "test", - Validators: []tmTypes.ValidatorUpdate{ - tmTypes.Ed25519ValidatorUpdate([]byte{}, 1), - }, + Time: time.Now(), + ChainId: "test", + Validators: updates, InitialHeight: 1, AppStateBytes: jsonState, }) @@ -46,13 +48,24 @@ func SendCommit(app *minter.Blockchain) tmTypes.ResponseCommit { } // SendBeginBlock sends BeginBlock message to given Blockchain instance -func SendBeginBlock(app *minter.Blockchain) tmTypes.ResponseBeginBlock { +func SendBeginBlock(app *minter.Blockchain, height int64) tmTypes.ResponseBeginBlock { + var voteInfos []tmTypes.VoteInfo + for _, validator := range app.CurrentState().Validators().GetValidators() { + address := validator.GetAddress() + voteInfos = append(voteInfos, tmTypes.VoteInfo{ + Validator: tmTypes.Validator{ + Address: address[:], + Power: 0, + }, + SignedLastBlock: true, + }) + } return app.BeginBlock(tmTypes.RequestBeginBlock{ Hash: nil, Header: tmTypes1.Header{ Version: version.Consensus{}, ChainID: "", - Height: 1, + Height: height, Time: time.Time{}, LastBlockId: tmTypes1.BlockID{}, LastCommitHash: nil, @@ -67,16 +80,16 @@ func SendBeginBlock(app *minter.Blockchain) tmTypes.ResponseBeginBlock { }, LastCommitInfo: tmTypes.LastCommitInfo{ Round: 0, - Votes: nil, + Votes: voteInfos, }, ByzantineValidators: nil, }) } // SendEndBlock sends EndBlock message to given Blockchain instance -func SendEndBlock(app *minter.Blockchain) tmTypes.ResponseEndBlock { +func SendEndBlock(app *minter.Blockchain, height int64) tmTypes.ResponseEndBlock { return app.EndBlock(tmTypes.RequestEndBlock{ - Height: 0, + Height: height, }) } diff --git a/tests/send_test.go b/tests/send_test.go index ca11aca28..69990de08 100644 --- a/tests/send_test.go +++ b/tests/send_test.go @@ -28,7 +28,7 @@ func TestSend(t *testing.T) { }) app := CreateApp(state) // create application - SendBeginBlock(app) // send BeginBlock + SendBeginBlock(app, 1) // send BeginBlock recipient, _ := CreateAddress() // generate recipient value := big.NewInt(1) @@ -46,8 +46,8 @@ func TestSend(t *testing.T) { t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) } - SendEndBlock(app) // send EndBlock - SendCommit(app) // send Commit + SendEndBlock(app, 1) // send EndBlock + SendCommit(app) // send Commit // check recipient's balance { diff --git a/tests/votes_test.go b/tests/votes_test.go new file mode 100644 index 000000000..65ff3ddd5 --- /dev/null +++ b/tests/votes_test.go @@ -0,0 +1,1063 @@ +package tests + +import ( + "github.com/MinterTeam/minter-go-node/coreV2/code" + "github.com/MinterTeam/minter-go-node/coreV2/transaction" + "github.com/MinterTeam/minter-go-node/coreV2/types" + "github.com/MinterTeam/minter-go-node/crypto" + "github.com/MinterTeam/minter-go-node/helpers" + "math/big" + "testing" +) + +func TestVoteupdate(t *testing.T) { + privateKey1, _ := crypto.GenerateKey() // create accounts for test + address1 := crypto.PubkeyToAddress(privateKey1.PublicKey) + privateKey2, _ := crypto.GenerateKey() // create accounts for test + address2 := crypto.PubkeyToAddress(privateKey2.PublicKey) + privateKey3, _ := crypto.GenerateKey() // create accounts for test + address3 := crypto.PubkeyToAddress(privateKey3.PublicKey) + privateKey4, _ := crypto.GenerateKey() // create accounts for test + address4 := crypto.PubkeyToAddress(privateKey4.PublicKey) + privateKey5, _ := crypto.GenerateKey() // create accounts for test + address5 := crypto.PubkeyToAddress(privateKey5.PublicKey) + privateKey6, _ := crypto.GenerateKey() // create accounts for test + address6 := crypto.PubkeyToAddress(privateKey6.PublicKey) + + state := DefaultAppState() // generate default state + + // add address to genesis state + state.Accounts = append(state.Accounts, + types.Account{ + Address: address1, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + types.Account{ + Address: address2, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + types.Account{ + Address: address3, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + types.Account{ + Address: address4, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + types.Account{ + Address: address5, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + types.Account{ + Address: address6, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + ) + stake := helpers.BipToPip(big.NewInt(10000)).String() + state.Validators = append(state.Validators, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{1}, + AccumReward: "10", + AbsentTimes: nil, + }, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{2}, + AccumReward: "10", + AbsentTimes: nil, + }, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{3}, + AccumReward: "10", + AbsentTimes: nil, + }, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{4}, + AccumReward: "10", + AbsentTimes: nil, + }, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{5}, + AccumReward: "10", + AbsentTimes: nil, + }, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{6}, + AccumReward: "10", + AbsentTimes: nil, + }, + ) + state.Candidates = append(state.Candidates, + types.Candidate{ + ID: 1, + RewardAddress: address1, + OwnerAddress: address1, + ControlAddress: address1, + TotalBipStake: stake, + PubKey: types.Pubkey{1}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + types.Candidate{ + ID: 2, + RewardAddress: address2, + OwnerAddress: address2, + ControlAddress: address2, + TotalBipStake: stake, + PubKey: types.Pubkey{2}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + types.Candidate{ + ID: 3, + RewardAddress: address3, + OwnerAddress: address3, + ControlAddress: address3, + TotalBipStake: stake, + PubKey: types.Pubkey{3}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + types.Candidate{ + ID: 4, + RewardAddress: address4, + OwnerAddress: address4, + ControlAddress: address4, + TotalBipStake: stake, + PubKey: types.Pubkey{4}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + types.Candidate{ + ID: 5, + RewardAddress: address5, + OwnerAddress: address5, + ControlAddress: address5, + TotalBipStake: stake, + PubKey: types.Pubkey{5}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + types.Candidate{ + ID: 6, + RewardAddress: address6, + OwnerAddress: address6, + ControlAddress: address6, + TotalBipStake: stake, + PubKey: types.Pubkey{6}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + ) + app := CreateApp(state) // create application + + SendBeginBlock(app, 1) + { + tx := CreateTx(app, address1, transaction.TypeVoteUpdate, transaction.VoteUpdateData{ + PubKey: types.Pubkey{1}, + Height: 2, + Version: "a", + }) + + response := SendTx(app, SignTx(privateKey1, tx)) // compose and send tx + + // check that result is OK + if response.Code != code.OK { + t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) + } + } + { + tx := CreateTx(app, address2, transaction.TypeVoteUpdate, transaction.VoteUpdateData{ + PubKey: types.Pubkey{2}, + Height: 2, + Version: "a", + }) + + response := SendTx(app, SignTx(privateKey2, tx)) // compose and send tx + + // check that result is OK + if response.Code != code.OK { + t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) + } + } + { + tx := CreateTx(app, address3, transaction.TypeVoteUpdate, transaction.VoteUpdateData{ + PubKey: types.Pubkey{3}, + Height: 2, + Version: "a", + }) + + response := SendTx(app, SignTx(privateKey3, tx)) // compose and send tx + + // check that result is OK + if response.Code != code.OK { + t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) + } + } + { + tx := CreateTx(app, address4, transaction.TypeVoteUpdate, transaction.VoteUpdateData{ + PubKey: types.Pubkey{4}, + Height: 2, + Version: "a", + }) + + response := SendTx(app, SignTx(privateKey4, tx)) // compose and send tx + + // check that result is OK + if response.Code != code.OK { + t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) + } + } + { + tx := CreateTx(app, address5, transaction.TypeVoteUpdate, transaction.VoteUpdateData{ + PubKey: types.Pubkey{5}, + Height: 2, + Version: "aA", + }) + + response := SendTx(app, SignTx(privateKey5, tx)) // compose and send tx + + // check that result is OK + if response.Code != code.OK { + t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) + } + } + SendEndBlock(app, 1) // send EndBlock + SendCommit(app) // send Commit + + SendBeginBlock(app, 2) + SendEndBlock(app, 2) // send EndBlock + SendCommit(app) // send Commit + + if len(app.UpdateVersions()) != 1 { + t.Fatalf("not updates") + } + + if app.UpdateVersions()[0].Name != "a" { + t.Fatalf("error update") + } +} + +func TestVoteCommissionFail(t *testing.T) { + privateKey1, _ := crypto.GenerateKey() // create accounts for test + address1 := crypto.PubkeyToAddress(privateKey1.PublicKey) + privateKey2, _ := crypto.GenerateKey() // create accounts for test + address2 := crypto.PubkeyToAddress(privateKey2.PublicKey) + privateKey3, _ := crypto.GenerateKey() // create accounts for test + address3 := crypto.PubkeyToAddress(privateKey3.PublicKey) + privateKey4, _ := crypto.GenerateKey() // create accounts for test + address4 := crypto.PubkeyToAddress(privateKey4.PublicKey) + privateKey5, _ := crypto.GenerateKey() // create accounts for test + address5 := crypto.PubkeyToAddress(privateKey5.PublicKey) + privateKey6, _ := crypto.GenerateKey() // create accounts for test + address6 := crypto.PubkeyToAddress(privateKey6.PublicKey) + + state := DefaultAppState() // generate default state + + // add address to genesis state + state.Accounts = append(state.Accounts, + types.Account{ + Address: address1, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + types.Account{ + Address: address2, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + types.Account{ + Address: address3, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + types.Account{ + Address: address4, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + types.Account{ + Address: address5, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + types.Account{ + Address: address6, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + ) + stake := helpers.BipToPip(big.NewInt(10000)).String() + state.Validators = append(state.Validators, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{1}, + AccumReward: "10", + AbsentTimes: nil, + }, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{2}, + AccumReward: "10", + AbsentTimes: nil, + }, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{3}, + AccumReward: "10", + AbsentTimes: nil, + }, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{4}, + AccumReward: "10", + AbsentTimes: nil, + }, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{5}, + AccumReward: "10", + AbsentTimes: nil, + }, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{6}, + AccumReward: "10", + AbsentTimes: nil, + }, + ) + state.Candidates = append(state.Candidates, + types.Candidate{ + ID: 1, + RewardAddress: address1, + OwnerAddress: address1, + ControlAddress: address1, + TotalBipStake: stake, + PubKey: types.Pubkey{1}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + types.Candidate{ + ID: 2, + RewardAddress: address2, + OwnerAddress: address2, + ControlAddress: address2, + TotalBipStake: stake, + PubKey: types.Pubkey{2}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + types.Candidate{ + ID: 3, + RewardAddress: address3, + OwnerAddress: address3, + ControlAddress: address3, + TotalBipStake: stake, + PubKey: types.Pubkey{3}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + types.Candidate{ + ID: 4, + RewardAddress: address4, + OwnerAddress: address4, + ControlAddress: address4, + TotalBipStake: stake, + PubKey: types.Pubkey{4}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + types.Candidate{ + ID: 5, + RewardAddress: address5, + OwnerAddress: address5, + ControlAddress: address5, + TotalBipStake: stake, + PubKey: types.Pubkey{5}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + types.Candidate{ + ID: 6, + RewardAddress: address6, + OwnerAddress: address6, + ControlAddress: address6, + TotalBipStake: stake, + PubKey: types.Pubkey{6}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + ) + app := CreateApp(state) // create application + + SendBeginBlock(app, 1) + SendEndBlock(app, 1) // send EndBlock + SendCommit(app) // send Commit + + SendBeginBlock(app, 2) + SendEndBlock(app, 2) // send EndBlock + SendCommit(app) // send Commit + + SendBeginBlock(app, 3) // send BeginBlock + { + tx := CreateTx(app, address1, transaction.TypeVoteCommission, transaction.VoteCommissionData{ + PubKey: types.Pubkey{1}, + Coin: types.GetBaseCoinID(), + Height: 5, + Send: big.NewInt(9999), + }) + + response := SendTx(app, SignTx(privateKey1, tx)) // compose and send tx + + // check that result is OK + if response.Code != code.OK { + t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) + } + } + { + tx := CreateTx(app, address2, transaction.TypeVoteCommission, transaction.VoteCommissionData{ + PubKey: types.Pubkey{2}, + Coin: types.GetBaseCoinID(), + Height: 5, + Send: big.NewInt(9999), + }) + + response := SendTx(app, SignTx(privateKey2, tx)) // compose and send tx + + // check that result is OK + if response.Code != code.OK { + t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) + } + } + { + tx := CreateTx(app, address3, transaction.TypeVoteCommission, transaction.VoteCommissionData{ + PubKey: types.Pubkey{3}, + Coin: types.GetBaseCoinID(), + Height: 5, + Send: big.NewInt(9999), + }) + + response := SendTx(app, SignTx(privateKey3, tx)) // compose and send tx + + // check that result is OK + if response.Code != code.OK { + t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) + } + } + SendEndBlock(app, 3) // send EndBlock + SendCommit(app) // send Commit + + SendBeginBlock(app, 4) // send BeginBlock + + { + tx := CreateTx(app, address5, transaction.TypeVoteCommission, transaction.VoteCommissionData{ + PubKey: types.Pubkey{5}, + Coin: types.GetBaseCoinID(), + Height: 5, + Send: big.NewInt(9999), + }) + + response := SendTx(app, SignTx(privateKey5, tx)) // compose and send tx + + // check that result is OK + if response.Code != code.OK { + t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) + } + } + { + tx := CreateTx(app, address6, transaction.TypeVoteCommission, transaction.VoteCommissionData{ + PubKey: types.Pubkey{6}, + Coin: types.GetBaseCoinID(), + Height: 5, + Send: big.NewInt(9999), + }) + + response := SendTx(app, SignTx(privateKey6, tx)) // compose and send tx + + // check that result is OK + if response.Code != code.OK { + t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) + } + } + + { // Diff + tx := CreateTx(app, address4, transaction.TypeVoteCommission, transaction.VoteCommissionData{ + PubKey: types.Pubkey{4}, + Coin: types.GetBaseCoinID(), + Height: 5, + Send: big.NewInt(2e18), // Diff + }) + + response := SendTx(app, SignTx(privateKey4, tx)) // compose and send tx + + // check that result is OK + if response.Code != code.OK { + t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) + } + } + SendEndBlock(app, 4) // send EndBlock + SendCommit(app) // send Commit + + SendBeginBlock(app, 5) + SendEndBlock(app, 5) // send EndBlock + SendCommit(app) // send Commit + + commissions := app.CurrentState().Commission().GetCommissions() + if commissions.Send.Cmp(big.NewInt(9999)) == 0 { + t.Fatalf("comission send want uncorrect. Expected %s, got %s", big.NewInt(2e18), commissions.Send) + } +} + +func TestVoteCommissionOKUpdateVersion(t *testing.T) { + privateKey1, _ := crypto.GenerateKey() // create accounts for test + address1 := crypto.PubkeyToAddress(privateKey1.PublicKey) + privateKey2, _ := crypto.GenerateKey() // create accounts for test + address2 := crypto.PubkeyToAddress(privateKey2.PublicKey) + privateKey3, _ := crypto.GenerateKey() // create accounts for test + address3 := crypto.PubkeyToAddress(privateKey3.PublicKey) + privateKey4, _ := crypto.GenerateKey() // create accounts for test + address4 := crypto.PubkeyToAddress(privateKey4.PublicKey) + privateKey5, _ := crypto.GenerateKey() // create accounts for test + address5 := crypto.PubkeyToAddress(privateKey5.PublicKey) + privateKey6, _ := crypto.GenerateKey() // create accounts for test + address6 := crypto.PubkeyToAddress(privateKey6.PublicKey) + + state := DefaultAppState() // generate default state + + // add address to genesis state + state.Accounts = append(state.Accounts, + types.Account{ + Address: address1, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + types.Account{ + Address: address2, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + types.Account{ + Address: address3, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + types.Account{ + Address: address4, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + types.Account{ + Address: address5, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + types.Account{ + Address: address6, + Balance: []types.Balance{ + { + Coin: uint64(types.GetBaseCoinID()), + Value: helpers.StringToBigInt("100000000000000000000").String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }, + ) + stake := helpers.BipToPip(big.NewInt(10000)).String() + state.Validators = append(state.Validators, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{1}, + AccumReward: "10", + AbsentTimes: nil, + }, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{2}, + AccumReward: "10", + AbsentTimes: nil, + }, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{3}, + AccumReward: "10", + AbsentTimes: nil, + }, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{4}, + AccumReward: "10", + AbsentTimes: nil, + }, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{5}, + AccumReward: "10", + AbsentTimes: nil, + }, + types.Validator{ + TotalBipStake: stake, + PubKey: types.Pubkey{6}, + AccumReward: "10", + AbsentTimes: nil, + }, + ) + state.Candidates = append(state.Candidates, + types.Candidate{ + ID: 1, + RewardAddress: address1, + OwnerAddress: address1, + ControlAddress: address1, + TotalBipStake: stake, + PubKey: types.Pubkey{1}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + types.Candidate{ + ID: 2, + RewardAddress: address2, + OwnerAddress: address2, + ControlAddress: address2, + TotalBipStake: stake, + PubKey: types.Pubkey{2}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + types.Candidate{ + ID: 3, + RewardAddress: address3, + OwnerAddress: address3, + ControlAddress: address3, + TotalBipStake: stake, + PubKey: types.Pubkey{3}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + types.Candidate{ + ID: 4, + RewardAddress: address4, + OwnerAddress: address4, + ControlAddress: address4, + TotalBipStake: stake, + PubKey: types.Pubkey{4}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + types.Candidate{ + ID: 5, + RewardAddress: address5, + OwnerAddress: address5, + ControlAddress: address5, + TotalBipStake: stake, + PubKey: types.Pubkey{5}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + types.Candidate{ + ID: 6, + RewardAddress: address6, + OwnerAddress: address6, + ControlAddress: address6, + TotalBipStake: stake, + PubKey: types.Pubkey{6}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: stake, + BipValue: stake, + }, + }, + Updates: nil, + Status: 2, + }, + ) + app := CreateApp(state) // create application + + const haltBlockV210 = 3431238 + + SendBeginBlock(app, haltBlockV210) + + SendEndBlock(app, haltBlockV210) // send EndBlock + SendCommit(app) // send Commit + + SendBeginBlock(app, haltBlockV210+1) + SendEndBlock(app, haltBlockV210+1) // send EndBlock + SendCommit(app) // send Commit + + SendBeginBlock(app, haltBlockV210+2) // send BeginBlock + { + tx := CreateTx(app, address1, transaction.TypeVoteCommission, transaction.VoteCommissionData{ + PubKey: types.Pubkey{1}, + Coin: types.GetBaseCoinID(), + Height: haltBlockV210 + 4, + Send: big.NewInt(9999), + }) + + response := SendTx(app, SignTx(privateKey1, tx)) // compose and send tx + + // check that result is OK + if response.Code != code.OK { + t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) + } + } + { + tx := CreateTx(app, address2, transaction.TypeVoteCommission, transaction.VoteCommissionData{ + PubKey: types.Pubkey{2}, + Coin: types.GetBaseCoinID(), + Height: haltBlockV210 + 4, + Send: big.NewInt(9999), + }) + + response := SendTx(app, SignTx(privateKey2, tx)) // compose and send tx + + // check that result is OK + if response.Code != code.OK { + t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) + } + } + { + tx := CreateTx(app, address3, transaction.TypeVoteCommission, transaction.VoteCommissionData{ + PubKey: types.Pubkey{3}, + Coin: types.GetBaseCoinID(), + Height: haltBlockV210 + 4, + Send: big.NewInt(9999), + }) + + response := SendTx(app, SignTx(privateKey3, tx)) // compose and send tx + + // check that result is OK + if response.Code != code.OK { + t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) + } + } + SendEndBlock(app, haltBlockV210+2) // send EndBlock + SendCommit(app) // send Commit + + SendBeginBlock(app, haltBlockV210+3) // send BeginBlock + + { + tx := CreateTx(app, address5, transaction.TypeVoteCommission, transaction.VoteCommissionData{ + PubKey: types.Pubkey{5}, + Coin: types.GetBaseCoinID(), + Height: haltBlockV210 + 4, + Send: big.NewInt(9999), + }) + + response := SendTx(app, SignTx(privateKey5, tx)) // compose and send tx + + // check that result is OK + if response.Code != code.OK { + t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) + } + } + { + tx := CreateTx(app, address6, transaction.TypeVoteCommission, transaction.VoteCommissionData{ + PubKey: types.Pubkey{6}, + Coin: types.GetBaseCoinID(), + Height: haltBlockV210 + 4, + Send: big.NewInt(9999), + }) + + response := SendTx(app, SignTx(privateKey6, tx)) // compose and send tx + + // check that result is OK + if response.Code != code.OK { + t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) + } + } + + { // Diff + tx := CreateTx(app, address4, transaction.TypeVoteCommission, transaction.VoteCommissionData{ + PubKey: types.Pubkey{4}, + Coin: types.GetBaseCoinID(), + Height: haltBlockV210 + 4, + Send: big.NewInt(2e18), // Diff + }) + + response := SendTx(app, SignTx(privateKey4, tx)) // compose and send tx + + // check that result is OK + if response.Code != code.OK { + t.Fatalf("Response code is not OK: %s, %d", response.Log, response.Code) + } + } + SendEndBlock(app, haltBlockV210+3) // send EndBlock + SendCommit(app) // send Commit + + SendBeginBlock(app, haltBlockV210+4) + SendEndBlock(app, haltBlockV210+4) // send EndBlock + SendCommit(app) // send Commit + + commissions := app.CurrentState().Commission().GetCommissions() + if commissions.Send.Cmp(big.NewInt(9999)) != 0 { + t.Fatalf("comission send is not correct. Expected %s, got %s", big.NewInt(9999), commissions.Send) + } +} diff --git a/upgrades/blocks.go b/upgrades/blocks.go deleted file mode 100644 index cebe7a27a..000000000 --- a/upgrades/blocks.go +++ /dev/null @@ -1,13 +0,0 @@ -package upgrades - -// func IsUpgradeBlock(height uint64) bool { -// upgradeBlocks := []uint64{} // fill this -// -// for _, block := range upgradeBlocks { -// if height == block { -// return true -// } -// } -// -// return false -// } diff --git a/upgrades/grace.go b/upgrades/grace.go index 2ea5c0970..fe0e90ce3 100644 --- a/upgrades/grace.go +++ b/upgrades/grace.go @@ -4,6 +4,16 @@ type Grace struct { gracePeriods []*GracePeriod } +func (g *Grace) IsUpgradeBlock(height uint64) bool { + for _, period := range g.gracePeriods { + if height == period.from { + return true + } + } + + return false +} + func (g *Grace) AddGracePeriods(gracePeriods ...*GracePeriod) { g.gracePeriods = append(g.gracePeriods, gracePeriods...) } diff --git a/version/version.go b/version/version.go index b3b79c623..07c1973d3 100755 --- a/version/version.go +++ b/version/version.go @@ -7,7 +7,7 @@ const ( var ( // Version must be a string because scripts like dist.sh read this file. - Version = "2.0.3" + Version = "2.1.0" // GitCommit is the current HEAD set using ldflags. GitCommit string