diff --git a/CHANGELOG.md b/CHANGELOG.md index a93936543..c46d809bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,29 @@ # Changelog -## 0.5.4 +## 0.5.5 IMPROVEMENTS * [\#518](https://github.com/binance-chain/node/pull/518) [Gov] Adapt to changes in cosmos +* [\#521](https://github.com/binance-chain/node/pull/521) [List] Add check for list proposal hook. +* [\#517](https://github.com/binance-chain/node/pull/517) [Validator] Split fee address and operator address +* [\#516](https://github.com/binance-chain/node/pull/516) [Publish] IocNoFill semantic correct +* [\#514](https://github.com/binance-chain/node/pull/514) [Upgrade] Support config for upgrade height +* [\#509](https://github.com/binance-chain/node/pull/509) [MatchEngine] Make the lot size reasonable for low price +* [\#498](https://github.com/binance-chain/node/pull/498) [MatchEngine] Rename price of TradingPair to list_price +* [\#497](https://github.com/binance-chain/node/pull/497) [Build] Support `build-windows` +* [\#496](https://github.com/binance-chain/node/pull/476) [StateSync] Cache latest snapshot in memory +* [\#526](https://github.com/binance-chain/node/pull/518) [ApiServer] Add gov queries in api server + + +BUG FIXES + +* [\#508](https://github.com/binance-chain/node/pull/508) [\#511](https://github.com/binance-chain/node/pull/511) [\#501](https://github.com/binance-chain/node/pull/501) [Dex] Fix all potential int64 overflows, remove all use of float64, and optimize some calculation +* [\#478](https://github.com/binance-chain/node/pull/478) [Publish] Dump order ids for large expire message. + +## 0.5.4 + +IMPROVEMENTS BUG FIXES diff --git a/Gopkg.lock b/Gopkg.lock index 2253a4597..f2ab266e6 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -63,7 +63,7 @@ revision = "d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4" [[projects]] - digest = "1:11e65d085dd48f2752bc3a49823f9973ab706be7c766ca2673d52a8beaa9616d" + digest = "1:f88cbfa75c235b4508c766d23936344eb3c60249c23579ae74a5372d1057e19f" name = "github.com/cosmos/cosmos-sdk" packages = [ "baseapp", @@ -98,6 +98,7 @@ "x/gov", "x/gov/client", "x/gov/client/cli", + "x/gov/client/rest", "x/gov/tags", "x/mock", "x/params", @@ -110,9 +111,9 @@ "x/stake/types", ] pruneopts = "UT" - revision = "ca4e37ce7f5dd9ff5f8385e51ee862cd70fc2024" + revision = "2fbc5aa00f18996e54238236642c437a7a6bc82b" source = "github.com/binance-chain/bnc-cosmos-sdk" - version = "v0.25.0-binance.15" + version = "v0.25.0-binance.16" [[projects]] digest = "1:e8a3550c8786316675ff54ad6f09d265d129c9d986919af7f541afba50d87ce2" @@ -600,7 +601,7 @@ version = "v0.12.0-binance.0" [[projects]] - digest = "1:ecb0b4a897ea8a52195e6df0aa3bc02bd1ce12a2d7bce13c10b506a70969395d" + digest = "1:829d92f88ac59b927dbea5249fc130131200f2f84b2b3a534a2db8f662726247" name = "github.com/tendermint/tendermint" packages = [ "abci/client", @@ -666,9 +667,9 @@ "version", ] pruneopts = "UT" - revision = "14ae0f7facd020c391548dfa226b30cb9fecdfdb" + revision = "eec92053e38f4e2ca99daf07a88da16d1db6c8d9" source = "github.com/binance-chain/bnc-tendermint" - version = "v0.30.1-binance.2" + version = "v0.30.1-binance.4" [[projects]] digest = "1:7886f86064faff6f8d08a3eb0e8c773648ff5a2e27730831e2bfbf07467f6666" @@ -842,6 +843,7 @@ "github.com/cosmos/cosmos-sdk/x/bank/client/rest", "github.com/cosmos/cosmos-sdk/x/gov", "github.com/cosmos/cosmos-sdk/x/gov/client/cli", + "github.com/cosmos/cosmos-sdk/x/gov/client/rest", "github.com/cosmos/cosmos-sdk/x/mock", "github.com/cosmos/cosmos-sdk/x/params", "github.com/cosmos/cosmos-sdk/x/stake", diff --git a/Gopkg.toml b/Gopkg.toml index 6d55bf20f..3a9a49c2e 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -37,12 +37,12 @@ [[override]] name = "github.com/tendermint/tendermint" source = "github.com/binance-chain/bnc-tendermint" - version = "=v0.30.1-binance.2" + version = "=v0.30.1-binance.4" [[constraint]] name = "github.com/cosmos/cosmos-sdk" source = "github.com/binance-chain/bnc-cosmos-sdk" - version = "=v0.25.0-binance.15" + version = "=v0.25.0-binance.16" [[constraint]] name = "github.com/btcsuite/btcd" @@ -87,4 +87,4 @@ [[constraint]] name = "github.com/natefinch/lumberjack" - version = "2.1.0" \ No newline at end of file + version = "2.1.0" diff --git a/admin/handler.go b/admin/handler.go index 3ed3be8ef..ff0cd588d 100644 --- a/admin/handler.go +++ b/admin/handler.go @@ -34,7 +34,7 @@ func GetHandler(config *config.Config) types.AbciQueryHandler { } res := abci.ResponseQuery{ Code: uint32(sdk.ABCICodeOK), - Value: []byte{uint8(runtime.RunningMode)}, + Value: []byte{uint8(runtime.GetRunningMode())}, } return &res } @@ -47,20 +47,26 @@ func GetHandler(config *config.Config) types.AbciQueryHandler { return &res } + var runningMode runtime.Mode if mode == "0" { - runtime.RunningMode = runtime.NormalMode + runningMode = runtime.NormalMode } else if mode == "1" { - runtime.RunningMode = runtime.TransferOnlyMode + runningMode = runtime.TransferOnlyMode } else if mode == "2" { - runtime.RunningMode = runtime.RecoverOnlyMode + runningMode = runtime.RecoverOnlyMode } else { res := sdk.ErrUnknownRequest("invalid mode").QueryResult() return &res } + err = runtime.UpdateRunningMode(config, runningMode) + if err != nil { + res := sdk.ErrUnknownRequest(err.Error()).QueryResult() + return &res + } res := abci.ResponseQuery{ Code: uint32(sdk.ABCICodeOK), - Value: []byte{uint8(runtime.RunningMode)}, + Value: []byte{uint8(runtime.GetRunningMode())}, } return &res } diff --git a/admin/tx.go b/admin/tx.go index ada587add..c69dc05f5 100644 --- a/admin/tx.go +++ b/admin/tx.go @@ -29,24 +29,25 @@ var TxBlackList = map[runtime.Mode][]string{ } func TxNotAllowedError() sdk.Error { - return sdk.ErrInternal(fmt.Sprintf("The tx is not allowed, RunningMode: %v", runtime.RunningMode)) + return sdk.ErrInternal(fmt.Sprintf("The tx is not allowed, RunningMode: %v", runtime.GetRunningMode())) } func IsTxAllowed(tx sdk.Tx) bool { - if runtime.RunningMode == runtime.NormalMode { + mode := runtime.GetRunningMode() + if mode == runtime.NormalMode { return true } for _, msg := range tx.GetMsgs() { - if !isMsgAllowed(msg) { + if !isMsgAllowed(msg, mode) { return false } } return true } -func isMsgAllowed(msg sdk.Msg) bool { - for _, msgType := range TxBlackList[runtime.RunningMode] { +func isMsgAllowed(msg sdk.Msg, mode runtime.Mode) bool { + for _, msgType := range TxBlackList[mode] { if msgType == msg.Type() { return false } diff --git a/app/app.go b/app/app.go index 166ec3399..cacf6f3ac 100644 --- a/app/app.go +++ b/app/app.go @@ -103,11 +103,6 @@ type BinanceChain struct { // NewBinanceChain creates a new instance of the BinanceChain. func NewBinanceChain(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptions ...func(*baseapp.BaseApp)) *BinanceChain { - // set running mode from cmd parameter or config - err := runtime.SetRunningMode(runtime.Mode(ServerContext.StartMode)) - if err != nil { - cmn.Exit(err.Error()) - } // create app-level codec for txs and accounts var cdc = Codec // create composed tx decoder @@ -122,7 +117,10 @@ func NewBinanceChain(logger log.Logger, db dbm.DB, traceStore io.Writer, baseApp upgradeConfig: ServerContext.UpgradeConfig, publicationConfig: ServerContext.PublicationConfig, } + // set upgrade config + app.setUpgradeConfig() app.SetPruning(viper.GetString("pruning")) + app.initRunningMode() app.SetCommitMultiStoreTracer(traceStore) // mappers @@ -135,7 +133,7 @@ func NewBinanceChain(logger log.Logger, db dbm.DB, traceStore io.Writer, baseApp app.stakeKeeper = stake.NewKeeper( cdc, common.StakeStoreKey, common.TStakeStoreKey, - app.CoinKeeper, app.ParamHub.Subspace(stake.DefaultParamspace), + app.CoinKeeper, app.Pool, app.ParamHub.Subspace(stake.DefaultParamspace), app.RegisterCodespace(stake.DefaultCodespace), ) app.ValAddrCache = NewValAddrCache(app.stakeKeeper) @@ -196,6 +194,7 @@ func NewBinanceChain(logger log.Logger, db dbm.DB, traceStore io.Writer, baseApp // finish app initialization app.SetInitChainer(app.initChainerFn()) + app.SetBeginBlocker(app.BeginBlocker) app.SetEndBlocker(app.EndBlocker) app.MountStoresIAVL( common.MainStoreKey, @@ -213,7 +212,7 @@ func NewBinanceChain(logger log.Logger, db dbm.DB, traceStore io.Writer, baseApp app.MountStoresTransient(common.TParamsStoreKey, common.TStakeStoreKey) // block store required to hydrate dex OB - err = app.LoadCMSLatestVersion() + err := app.LoadCMSLatestVersion() if err != nil { cmn.Exit(err.Error()) } @@ -228,10 +227,7 @@ func NewBinanceChain(logger log.Logger, db dbm.DB, traceStore io.Writer, baseApp if err != nil { cmn.Exit(err.Error()) } - - // set upgrade config - app.setUpgradeConfig() - + // remaining plugin init app.initDex(tradingPairMapper) app.initPlugins() @@ -242,8 +238,14 @@ func NewBinanceChain(logger log.Logger, db dbm.DB, traceStore io.Writer, baseApp // setUpgradeConfig will overwrite default upgrade config func (app *BinanceChain) setUpgradeConfig() { - upgrade.Mgr.AddUpgradeHeight(upgrade.FixOrderSeqInPriceLevelName, app.upgradeConfig.FixOrderSeqInPriceLevelHeight) - upgrade.Mgr.AddUpgradeHeight(upgrade.FixDropFilledOrderSeqName, app.upgradeConfig.FixDropFilledOrderSeqHeight) + // upgrade.Mgr.AddUpgradeHeight(,) +} + +func (app *BinanceChain) initRunningMode() { + err := runtime.RecoverFromFile(ServerContext.Config.RootDir, runtime.Mode(ServerContext.StartMode)) + if err != nil { + cmn.Exit(err.Error()) + } } func (app *BinanceChain) initDex(pairMapper dex.TradingPairMapper) { @@ -433,6 +435,11 @@ func (app *BinanceChain) isBreatheBlock(height int64, lastBlockTime time.Time, b } } +func (app *BinanceChain) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { + upgrade.Mgr.BeginBlocker(ctx) + return +} + func (app *BinanceChain) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { // lastBlockTime would be 0 if this is the first block. lastBlockTime := app.CheckState.Ctx.BlockHeader().Time @@ -473,10 +480,20 @@ func (app *BinanceChain) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) a proposals = pub.CollectProposalsForPublish(passed, failed) } + var completedUbd []stake.UnbondingDelegation + var validatorUpdates abci.ValidatorUpdates + if isBreatheBlock || ctx.RouterCallRecord()["stake"] { + // some endblockers without fees will execute after publish to make publication run as early as possible. + validatorUpdates, completedUbd = stake.EndBlocker(ctx, app.stakeKeeper) + app.ValAddrCache.ClearCache() + } + if app.publicationConfig.ShouldPublishAny() && pub.IsLive { + var stakeUpdates pub.StakeUpdates + stakeUpdates = pub.CollectStakeUpdatesForPublish(completedUbd) if height >= app.publicationConfig.FromHeightInclusive { - app.publish(tradesToPublish, &proposals, blockFee, ctx, height, blockTime.UnixNano()) + app.publish(tradesToPublish, &proposals, &stakeUpdates, blockFee, ctx, height, blockTime.UnixNano()) } // clean up intermediate cached data @@ -484,16 +501,6 @@ func (app *BinanceChain) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) a app.DexKeeper.ClearRoundFee() } - var validatorUpdates abci.ValidatorUpdates - // TODO: confirm with zz height == 1 is only to keep consistent with testnet (Binance Chain Commit: d1f295b; Cosmos Release: =v0.25.0-binance.5; Tendermint Release: =v0.29.1-binance.2;), - // otherwise, apphash fail - // I think we don't need it after next reset because at height = 1 validatorUpdates is nil - if isBreatheBlock || height == 1 || ctx.RouterCallRecord()["stake"] { - // some endblockers without fees will execute after publish to make publication run as early as possible. - validatorUpdates = stake.EndBlocker(ctx, app.stakeKeeper) - app.ValAddrCache.ClearCache() - } - //match may end with transaction failure, which is better to save into //the EndBlock response. However, current cosmos doesn't support this. //future TODO: add failure info. @@ -645,7 +652,7 @@ func MakeCodec() *wire.Codec { return cdc } -func (app *BinanceChain) publish(tradesToPublish []*pub.Trade, proposalsToPublish *pub.Proposals, blockFee pub.BlockFee, ctx sdk.Context, height, blockTime int64) { +func (app *BinanceChain) publish(tradesToPublish []*pub.Trade, proposalsToPublish *pub.Proposals, stakeUpdates *pub.StakeUpdates, blockFee pub.BlockFee, ctx sdk.Context, height, blockTime int64) { pub.Logger.Info("start to collect publish information", "height", height) var accountsToPublish map[string]pub.Account @@ -690,6 +697,7 @@ func (app *BinanceChain) publish(tradesToPublish []*pub.Trade, proposalsToPublis blockTime, tradesToPublish, proposalsToPublish, + stakeUpdates, app.DexKeeper.OrderChanges, // thread-safety is guarded by the signal from RemoveDoneCh app.DexKeeper.OrderInfosForPub, // thread-safety is guarded by the signal from RemoveDoneCh accountsToPublish, diff --git a/app/config/config.go b/app/config/config.go index e08df1c2b..d832557be 100644 --- a/app/config/config.go +++ b/app/config/config.go @@ -5,10 +5,11 @@ import ( "path/filepath" "text/template" - "github.com/cosmos/cosmos-sdk/server" "github.com/spf13/viper" "github.com/tendermint/tendermint/libs/cli" "github.com/tendermint/tendermint/libs/common" + + "github.com/cosmos/cosmos-sdk/server" ) var configTemplate *template.Template @@ -44,10 +45,6 @@ orderKeeperConcurrency = {{ .BaseConfig.OrderKeeperConcurrency }} breatheBlockDaysCountBack = {{ .BaseConfig.BreatheBlockDaysCountBack }} [upgrade] -# fixOrderSeqInPriceLevel height -fixOrderSeqInPriceLevelHeight = {{ .UpgradeConfig.FixOrderSeqInPriceLevelHeight }} -# fixDropFilledOrderSeq height -fixDropFilledOrderSeqHeight = {{ .UpgradeConfig.FixDropFilledOrderSeqHeight }} [addr] # Bech32PrefixAccAddr defines the Bech32 prefix of an account's address @@ -284,14 +281,12 @@ func defaultBaseConfig() *BaseConfig { } type UpgradeConfig struct { - FixOrderSeqInPriceLevelHeight int64 - FixDropFilledOrderSeqHeight int64 + // example + // FixXxxHeight int64 `mapstructure:"fixXxxHeight"` } func defaultUpgradeConfig() *UpgradeConfig { return &UpgradeConfig{ - FixDropFilledOrderSeqHeight: 2855000, - FixOrderSeqInPriceLevelHeight: 2855000, } } diff --git a/app/fee_distribution.go b/app/fee_distribution.go index b6d221e33..2d7f2ae2e 100644 --- a/app/fee_distribution.go +++ b/app/fee_distribution.go @@ -8,17 +8,18 @@ import ( "github.com/binance-chain/node/common/fees" "github.com/binance-chain/node/common/log" "github.com/binance-chain/node/common/types" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/stake" ) func NewValAddrCache(stakeKeeper stake.Keeper) *ValAddrCache { - return &ValAddrCache{ + cache := &ValAddrCache{ cache: make(map[string]sdk.AccAddress), stakeKeeper: stakeKeeper, } + + return cache } type ValAddrCache struct { diff --git a/app/genesis.go b/app/genesis.go index 925e47642..fb29d6beb 100644 --- a/app/genesis.go +++ b/app/genesis.go @@ -24,14 +24,14 @@ import ( const DefaultKeyPass = "12345678" var ( - // each genesis validators will self delegate 1000e8 native tokens to become a validator - DefaultSelfDelegationToken = sdk.NewCoin(types.NativeTokenSymbol, 1000e8) + // each genesis validators will self delegate 10000e8 native tokens to become a validator + DefaultSelfDelegationToken = sdk.NewCoin(types.NativeTokenSymbol, 10000e8) // we put 20% of the total supply to the stake pool - DefaultMaxBondedTokenAmount int64 = types.NativeTokenTotalSupply / 5 + DefaultMaxBondedTokenAmount int64 = types.NativeTokenTotalSupply // set default unbonding duration to 7 days DefaultUnbondingTime = 60 * 60 * 24 * 7 * time.Second - // default max validators to 15 - DefaultMaxValidators uint16 = 15 + // default max validators to 21 + DefaultMaxValidators uint16 = 21 // min gov deposit DefaultGovMinDesposit = sdk.Coins{sdk.NewCoin(types.NativeTokenSymbol, 1000e8)} diff --git a/app/pub/helpers.go b/app/pub/helpers.go index 6f661f440..544b4e435 100644 --- a/app/pub/helpers.go +++ b/app/pub/helpers.go @@ -8,6 +8,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/cosmos/cosmos-sdk/x/stake" "github.com/binance-chain/node/common/types" me "github.com/binance-chain/node/plugins/dex/matcheng" @@ -45,6 +46,7 @@ func GetTransferPublished(pool *sdk.Pool, height, blockTime int64) *Transfers { transferToPublish := make([]Transfer, 0, 0) txs := pool.GetTxs() txs.Range(func(key, value interface{}) bool { + txhash := key.(string) t := value.(sdk.Tx) msgs := t.GetMsgs() for _, m := range msgs { @@ -60,7 +62,7 @@ func GetTransferPublished(pool *sdk.Pool, height, blockTime int64) *Transfers { } receivers = append(receivers, Receiver{Addr: o.Address.String(), Coins: coins}) } - transferToPublish = append(transferToPublish, Transfer{From: msg.Inputs[0].Address.String(), To: receivers}) + transferToPublish = append(transferToPublish, Transfer{TxHash: txhash, From: msg.Inputs[0].Address.String(), To: receivers}) } return true }) @@ -215,6 +217,16 @@ func CollectProposalsForPublish(passed, failed []int64) Proposals { return Proposals{totalProposals, ps} } +func CollectStakeUpdatesForPublish(unbondingDelegations []stake.UnbondingDelegation) StakeUpdates { + length := len(unbondingDelegations) + completedUnbondingDelegations := make([]*CompletedUnbondingDelegation, 0, length) + for _, ubd := range unbondingDelegations { + amount := Coin{ubd.Balance.Denom, ubd.Balance.Amount} + completedUnbondingDelegations = append(completedUnbondingDelegations, &CompletedUnbondingDelegation{ubd.ValidatorAddr, ubd.DelegatorAddr,amount}) + } + return StakeUpdates{length, completedUnbondingDelegations} +} + func updateExpireFeeForPublish( dexKeeper *orderPkg.Keeper, wg *sync.WaitGroup, diff --git a/app/pub/msgs.go b/app/pub/msgs.go index 65c852273..e6e151ec9 100644 --- a/app/pub/msgs.go +++ b/app/pub/msgs.go @@ -69,12 +69,13 @@ type EssMsg interface { } type ExecutionResults struct { - Height int64 - Timestamp int64 // milli seconds since Epoch - NumOfMsgs int // number of individual messages we published, consumer can verify messages they received against this field to make sure they does not miss messages - Trades trades - Orders Orders - Proposals Proposals + Height int64 + Timestamp int64 // milli seconds since Epoch + NumOfMsgs int // number of individual messages we published, consumer can verify messages they received against this field to make sure they does not miss messages + Trades trades + Orders Orders + Proposals Proposals + StakeUpdates StakeUpdates } func (msg *ExecutionResults) String() string { @@ -95,6 +96,9 @@ func (msg *ExecutionResults) ToNativeMap() map[string]interface{} { if msg.Proposals.NumOfMsgs > 0 { native["proposals"] = map[string]interface{}{"org.binance.dex.model.avro.Proposals": msg.Proposals.ToNativeMap()} } + if msg.StakeUpdates.NumOfMsgs > 0 { + native["stakeUpdates"] = map[string]interface{}{"org.binance.dex.model.avro.StakeUpdates": msg.StakeUpdates.ToNativeMap()} + } return native } @@ -113,6 +117,7 @@ func (msg *ExecutionResults) EmptyCopy() AvroOrJsonMsg { trades{}, Orders{}, Proposals{}, + StakeUpdates{}, } } @@ -358,6 +363,44 @@ func (msg *Proposal) toNativeMap() map[string]interface{} { return native } +type StakeUpdates struct { + NumOfMsgs int + CompletedUnbondingDelegations []*CompletedUnbondingDelegation +} + +func (msg *StakeUpdates) String() string { + return fmt.Sprintf("StakeUpdates numOfMsgs: %d", msg.NumOfMsgs) +} + +func (msg *StakeUpdates) ToNativeMap() map[string]interface{} { + var native = make(map[string]interface{}) + native["numOfMsgs"] = msg.NumOfMsgs + ps := make([]map[string]interface{}, len(msg.CompletedUnbondingDelegations), len(msg.CompletedUnbondingDelegations)) + for idx, p := range msg.CompletedUnbondingDelegations { + ps[idx] = p.toNativeMap() + } + native["completedUnbondingDelegations"] = ps + return native +} + +type CompletedUnbondingDelegation struct { + Validator sdk.ValAddress + Delegator sdk.AccAddress + Amount Coin +} + +func (msg *CompletedUnbondingDelegation) String() string { + return fmt.Sprintf("CompletedUnbondingDelegation: %v", msg.toNativeMap()) +} + +func (msg *CompletedUnbondingDelegation) toNativeMap() map[string]interface{} { + var native = make(map[string]interface{}) + native["validator"] = msg.Validator.String() + native["delegator"] = msg.Delegator.String() + native["amount"] = msg.Amount.ToNativeMap() + return native +} + type PriceLevel struct { Price int64 LastQty int64 @@ -596,8 +639,9 @@ func (msg Receiver) ToNativeMap() map[string]interface{} { } type Transfer struct { - From string - To []Receiver + TxHash string + From string + To []Receiver } func (msg Transfer) String() string { @@ -606,6 +650,7 @@ func (msg Transfer) String() string { func (msg Transfer) ToNativeMap() map[string]interface{} { var native = make(map[string]interface{}) + native["txhash"] = msg.TxHash native["from"] = msg.From to := make([]map[string]interface{}, len(msg.To), len(msg.To)) for idx, t := range msg.To { diff --git a/app/pub/publisher.go b/app/pub/publisher.go index 2da930be7..45dc97d0f 100644 --- a/app/pub/publisher.go +++ b/app/pub/publisher.go @@ -83,7 +83,8 @@ func Publish( marketData.timestamp, ordersToPublish, marketData.tradesToPublish, - marketData.proposalsToPublish) + marketData.proposalsToPublish, + marketData.stakeUpdates) }) if metrics != nil { @@ -178,11 +179,12 @@ func Stop(publisher MarketDataPublisher) { publisher.Stop() } -func publishExecutionResult(publisher MarketDataPublisher, height int64, timestamp int64, os []*Order, tradesToPublish []*Trade, proposalsToPublish *Proposals) { +func publishExecutionResult(publisher MarketDataPublisher, height int64, timestamp int64, os []*Order, tradesToPublish []*Trade, proposalsToPublish *Proposals, stakeUpdates *StakeUpdates) { numOfOrders := len(os) numOfTrades := len(tradesToPublish) numOfProposals := proposalsToPublish.NumOfMsgs - executionResultsMsg := ExecutionResults{Height: height, Timestamp: timestamp, NumOfMsgs: numOfTrades + numOfOrders + numOfProposals} + numOfStakeUpdatedAccounts := stakeUpdates.NumOfMsgs + executionResultsMsg := ExecutionResults{Height: height, Timestamp: timestamp, NumOfMsgs: numOfTrades + numOfOrders + numOfProposals + numOfStakeUpdatedAccounts} if numOfOrders > 0 { executionResultsMsg.Orders = Orders{numOfOrders, os} } @@ -192,6 +194,9 @@ func publishExecutionResult(publisher MarketDataPublisher, height int64, timesta if numOfProposals > 0 { executionResultsMsg.Proposals = *proposalsToPublish } + if numOfStakeUpdatedAccounts > 0 { + executionResultsMsg.StakeUpdates = *stakeUpdates + } publisher.publish(&executionResultsMsg, executionResultTpe, height, timestamp) } diff --git a/app/pub/schema_test.go b/app/pub/schema_test.go index 740fa5a2c..8a9b0221c 100644 --- a/app/pub/schema_test.go +++ b/app/pub/schema_test.go @@ -4,6 +4,8 @@ import ( "os" "testing" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/binance-chain/node/app/config" "github.com/binance-chain/node/common/log" orderPkg "github.com/binance-chain/node/plugins/dex/order" @@ -43,13 +45,27 @@ func TestExecutionResultsMarshaling(t *testing.T) { {3, Failed}, }, } + + valAddr, _ :=sdk.ValAddressFromBech32("bva1e2y8w2rz957lahwy0y5h3w53sm8d78qexkn3rh") + delAddr, _ :=sdk.AccAddressFromBech32("bnb1e2y8w2rz957lahwy0y5h3w53sm8d78qex2jpan") + stakeUpdates := StakeUpdates{ + NumOfMsgs: 1, + CompletedUnbondingDelegations: []*CompletedUnbondingDelegation{ + { + Validator: valAddr, + Delegator: delAddr, + Amount: Coin{"BNB", 100000000000}, + }, + }, + } msg := ExecutionResults{ Height: 42, Timestamp: 100, - NumOfMsgs: 4, + NumOfMsgs: 8, Trades: trades, Orders: orders, Proposals: proposals, + StakeUpdates: stakeUpdates, } _, err := publisher.marshal(&msg, executionResultTpe) if err != nil { @@ -88,7 +104,7 @@ func TestBlockFeeMarshaling(t *testing.T) { func TestTransferMarshaling(t *testing.T) { publisher := NewKafkaMarketDataPublisher(Logger, "") - msg := Transfers{42, 20, 1000, []Transfer{{From: "", To: []Receiver{Receiver{"bnc1", []Coin{{"BNB", 100}, {"BTC", 100}}}, Receiver{"bnc2", []Coin{{"BNB", 200}, {"BTC", 200}}}}}}} + msg := Transfers{42, 20, 1000, []Transfer{{TxHash: "123456ABCDE", From: "", To: []Receiver{Receiver{"bnc1", []Coin{{"BNB", 100}, {"BTC", 100}}}, Receiver{"bnc2", []Coin{{"BNB", 200}, {"BTC", 200}}}}}}} _, err := publisher.marshal(&msg, transferType) if err != nil { t.Fatal(err) diff --git a/app/pub/schemas.go b/app/pub/schemas.go index cd1811be7..c270e1b8d 100644 --- a/app/pub/schemas.go +++ b/app/pub/schemas.go @@ -99,6 +99,38 @@ const ( } } ] + }], "default": null }, + { "name": "stakeUpdates", "type": ["null", { + "type": "record", + "name": "StakeUpdates", + "namespace": "org.binance.dex.model.avro", + "fields": [ + { "name": "numOfMsgs", "type": "int" }, + { "name": "completedUnbondingDelegations", "type": { + "type": "array", + "items": + { + "type": "record", + "name": "CompletedUnbondingDelegation", + "namespace": "org.binance.dex.model.avro", + "fields": [ + { "name": "validator", "type": "string" }, + { "name": "delegator", "type": "string" }, + { "name": "amount", "type": { + "type": "record", + "name": "Coin", + "namespace": "org.binance.dex.model.avro", + "fields": [ + { "name": "denom", "type": "string" }, + { "name": "amount", "type": "long" } + ] + } + } + ] + } + } + } + ] }], "default": null } ] } @@ -216,7 +248,8 @@ const ( "name": "Transfer", "namespace": "com.company", "fields": [ - { "name": "from", "type": "string"}, + { "name": "txhash", "type": "string" }, + { "name": "from", "type": "string" }, { "name": "to", "type": { "type": "array", diff --git a/app/pub/types.go b/app/pub/types.go index f203dea84..6935d1c26 100644 --- a/app/pub/types.go +++ b/app/pub/types.go @@ -10,6 +10,7 @@ type BlockInfoToPublish struct { timestamp int64 tradesToPublish []*Trade proposalsToPublish *Proposals + stakeUpdates *StakeUpdates orderChanges orderPkg.OrderChanges orderInfos orderPkg.OrderInfoForPublish accounts map[string]Account @@ -24,6 +25,7 @@ func NewBlockInfoToPublish( timestamp int64, tradesToPublish []*Trade, proposalsToPublish *Proposals, + stakeUpdates *StakeUpdates, orderChanges orderPkg.OrderChanges, orderInfos orderPkg.OrderInfoForPublish, accounts map[string]Account, @@ -35,6 +37,7 @@ func NewBlockInfoToPublish( timestamp, tradesToPublish, proposalsToPublish, + stakeUpdates, orderChanges, orderInfos, accounts, diff --git a/app_test/abci_open_orders_test.go b/app_test/abci_open_orders_test.go index 382c98701..2d543e514 100644 --- a/app_test/abci_open_orders_test.go +++ b/app_test/abci_open_orders_test.go @@ -42,7 +42,7 @@ func Test_Success(t *testing.T) { openOrders = issueMustSuccessQuery(pair, buyer, assert) require.Len(openOrders, 1) - expected = store.OpenOrder{"b-1", pair, 102000, 3000000, 1000000, 100, 0, 101, 1} + expected = store.OpenOrder{"b-1", pair, 102000, 3000000, 1000000, 100, 0, 101, 1000000000} assert.Equal(expected, openOrders[0]) openOrders = issueMustSuccessQuery(pair, seller, assert) diff --git a/cmd/bnbchaind/main.go b/cmd/bnbchaind/main.go index 7e5ae40c1..1df8e55e3 100644 --- a/cmd/bnbchaind/main.go +++ b/cmd/bnbchaind/main.go @@ -46,8 +46,6 @@ func main() { server.AddCommands(ctx.ToCosmosServerCtx(), cdc, rootCmd, exportAppStateAndTMValidators) startCmd := server.StartCmd(ctx.ToCosmosServerCtx(), newApp) startCmd.Flags().Int64VarP(&ctx.PublicationConfig.FromHeightInclusive, "fromHeight", "f", 1, "from which height (inclusive) we want publish market data") - startCmd.Flags().Uint8Var(&ctx.BaseConfig.StartMode, "mode", uint8(0), "running mode when start up") - ctx.Viper.BindPFlag("base.startMode", startCmd.Flags().Lookup("mode")) rootCmd.AddCommand(startCmd) // prepare and add flags diff --git a/cmd/pressuremaker/utils/utils.go b/cmd/pressuremaker/utils/utils.go index ad5971928..dc22655c1 100644 --- a/cmd/pressuremaker/utils/utils.go +++ b/cmd/pressuremaker/utils/utils.go @@ -47,7 +47,7 @@ func (mg *MessageGenerator) OneOnOneMessages(height int, timeNow time.Time) (tra orderChanges = make(orderPkg.OrderChanges, mg.NumOfTradesPerBlock*2) timeSeed := float64(timeNow.UnixNano()-mg.TimeStart.UnixNano()) / (float64(time.Hour) / 4) - timePub := timeNow.Unix() + timePub := timeNow.UnixNano() pi2 := 2.0 * math.Pi price := (30 + int64(20*math.Sin(float64(timeSeed)*pi2))) * 100000000 amount := int64(100000000 * rand.Intn(10)) @@ -78,7 +78,7 @@ func (mg *MessageGenerator) OneOnOneMessages(height int, timeNow time.Time) (tra // each big order eat two small orders func (mg *MessageGenerator) TwoOnOneMessages(height int, timeNow time.Time) (tradesToPublish []*pub.Trade, orderChanges orderPkg.OrderChanges, accounts map[string]pub.Account, transfers *pub.Transfers) { - timePub := timeNow.Unix() + timePub := timeNow.UnixNano() if height%2 != 0 { // place small buy orders tradesToPublish = make([]*pub.Trade, 0) @@ -126,7 +126,7 @@ func (mg *MessageGenerator) TwoOnOneMessages(height int, timeNow time.Time) (tra // simulate 1 million expire orders to publish at breathe block func (mg *MessageGenerator) ExpireMessages(height int, timeNow time.Time) (tradesToPublish []*pub.Trade, orderChanges orderPkg.OrderChanges, accounts map[string]pub.Account) { - timePub := timeNow.Unix() + timePub := timeNow.UnixNano() tradesToPublish = make([]*pub.Trade, 0) orderChanges = make(orderPkg.OrderChanges, 0, 100000) accounts = make(map[string]pub.Account) @@ -149,6 +149,7 @@ func (mg MessageGenerator) Publish(height, timePub int64, tradesToPublish []*pub timePub, tradesToPublish, new(pub.Proposals), + new(pub.StakeUpdates), orderChanges, orderChangesCopy, accounts, diff --git a/common/runtime/mode.go b/common/runtime/mode.go index b8f5732f0..20406d622 100644 --- a/common/runtime/mode.go +++ b/common/runtime/mode.go @@ -2,6 +2,12 @@ package runtime import ( "fmt" + "os" + "path/filepath" + "sync" + + "github.com/binance-chain/node/common/log" + "github.com/tendermint/tendermint/config" ) type Mode uint8 @@ -12,12 +18,42 @@ const ( RecoverOnlyMode ) -var RunningMode = NormalMode +var ( + runningMode = NormalMode + mtx = new(sync.RWMutex) +) -func SetRunningMode(mode Mode) error { +func GetRunningMode() Mode { + mtx.RLock() + defer mtx.RUnlock() + return runningMode +} + +func setRunningMode(mode Mode) error { if mode != NormalMode && mode != TransferOnlyMode && mode != RecoverOnlyMode { return fmt.Errorf("invalid mode %v", mode) } - RunningMode = mode + + mtx.Lock() + runningMode = mode + mtx.Unlock() + return nil +} + +func UpdateRunningMode(cfg *config.Config, mode Mode) error { + err := setRunningMode(mode) + if err != nil { + return err + } + var params *runtimeParams + path := filepath.Join(cfg.RootDir, "config", fileName) + if _, err := os.Stat(path); os.IsNotExist(err) { + log.Debug("path does not exist", "path", path) + params = &runtimeParams{Mode:mode} + } else { + params = mustReadFromFile(path) + params.Mode = mode + } + mustSaveToFile(path, params) return nil } diff --git a/common/runtime/recover.go b/common/runtime/recover.go new file mode 100644 index 000000000..e6a96463d --- /dev/null +++ b/common/runtime/recover.go @@ -0,0 +1,56 @@ +package runtime + +import ( + "encoding/json" + "os" + "path/filepath" + + "github.com/tendermint/tendermint/libs/common" + + "github.com/binance-chain/node/common/log" +) + +const fileName = "recover_params.json" + +type runtimeParams struct { + Mode Mode `json:"mode"` +} + +func RecoverFromFile(homeDir string, defaultStartMode Mode) error { + path := filepath.Join(homeDir, "config", fileName) + var mode Mode + if _, err := os.Stat(path); os.IsNotExist(err) { + log.Debug("path does not exist", "path", path) + mode = defaultStartMode + } else { + params := mustReadFromFile(path) + mode = params.Mode + } + + return setRunningMode(mode) +} + +func mustSaveToFile(path string, params *runtimeParams) { + contents, err := json.MarshalIndent(params, "", " ") + if err != nil { + panic(err) + } + err = common.WriteFileAtomic(path, contents, 0600) + if err != nil { + panic(err) + } +} + +func mustReadFromFile(path string) *runtimeParams { + contents, err := common.ReadFile(path) + if err != nil { + panic(err) + } + + var res runtimeParams + err = json.Unmarshal(contents, &res) + if err != nil { + panic(err) + } + return &res +} diff --git a/common/upgrade/upgrade.go b/common/upgrade/upgrade.go index 6c2c0bd77..ed9e93802 100644 --- a/common/upgrade/upgrade.go +++ b/common/upgrade/upgrade.go @@ -6,30 +6,4 @@ var Mgr = sdk.UpgradeMgr // prefix for the upgrade name // bugfix: fix -// improvement: (maybe bip ?) -const FixOrderSeqInPriceLevelName = "fixOrderSeqInPriceLevel" -const FixDropFilledOrderSeqName = "fixDropFilledOrderSeq" - -func Upgrade(name string, before func(), in func(), after func()) { - if sdk.IsUpgradeHeight(name) { - if in != nil { - in() - } - } else if sdk.IsUpgrade(name) { - if after != nil { - after() - } - } else { - if before != nil { - before() - } - } -} - -func FixOrderSeqInPriceLevel(before func(), in func(), after func()) { - Upgrade(FixOrderSeqInPriceLevelName, before, in, after) -} - -func FixDropFilledOrderSeq(before func(), after func()) { - Upgrade(FixDropFilledOrderSeqName, before, nil, after) -} +// improvement: (maybe bep ?) diff --git a/networks/publisher/ordergen.sh b/networks/publisher/ordergen.sh index bed8103a8..d01711a22 100755 --- a/networks/publisher/ordergen.sh +++ b/networks/publisher/ordergen.sh @@ -43,10 +43,10 @@ do pause=$(random 5 7) symbolNum=$(random 1 10) - symbol="NNB-DB5_BNB" + symbol="NNB-3DE_BNB" if [ $symbolNum -lt 4 ] then - symbol="NNB-DB5_BNB" + symbol="NNB-3DE_BNB" fi from="zc" diff --git a/networks/publisher/setup.sh b/networks/publisher/setup.sh index 9c8c0ef29..aa7834e84 100755 --- a/networks/publisher/setup.sh +++ b/networks/publisher/setup.sh @@ -47,8 +47,8 @@ sed -i -e "s/publishOrderUpdates = false/publishOrderUpdates = true/g" ${deamonh sed -i -e "s/publishAccountBalance = false/publishAccountBalance = true/g" ${deamonhome}/config/app.toml sed -i -e "s/publishOrderBook = false/publishOrderBook = true/g" ${deamonhome}/config/app.toml sed -i -e "s/publishBlockFee = false/publishBlockFee = true/g" ${deamonhome}/config/app.toml +sed -i -e "s/publishTransfer = false/publishTransfer = true/g" ${deamonhome}/config/app.toml sed -i -e "s/publishLocal = false/publishLocal = true/g" ${deamonhome}/config/app.toml -sed -i -e 's/"voting_period": "1209600000000000"/"voting_period": "5000000000"/g' ${deamonhome}/config/genesis.json # config witness node cp ${deamonhome}/config/genesis.json ${witnesshome}/config/ @@ -85,7 +85,8 @@ result=$(${cli} token issue --from=zc --token-name="New BNB Coin" --symbol=NNB - nnb_symbol=$(echo "${result}" | tail -n 1 | grep -o "NNB-[0-9A-Z]*") echo ${nnb_symbol} sleep 5 -${cli} gov submit-list-proposal --chain-id ${chain_id} --from zc --deposit 200000000000:BNB --base-asset-symbol ${nnb_symbol} --quote-asset-symbol BNB --init-price 1000000000 --title "list NNB/BNB" --description "list NNB/BNB" --expire-time 1644486400 --json +((expire_time=$(date '+%s')+1000)) +${cli} gov submit-list-proposal --chain-id ${chain_id} --from zc --deposit 200000000000:BNB --base-asset-symbol ${nnb_symbol} --quote-asset-symbol BNB --init-price 1000000000 --title "list NNB/BNB" --description "list NNB/BNB" --expire-time ${expire_time} --voting-period 5 --json sleep 2 ${cli} gov vote --from zc --chain-id ${chain_id} --proposal-id 1 --option Yes --json sleep 6 @@ -95,7 +96,8 @@ result=$(${cli} token issue --from=zc --token-name="ZC Coin" --symbol=ZCB --tota zcb_symbol=$(echo "${result}" | tail -n 1 | grep -o "ZCB-[0-9A-Z]*") echo ${zcb_symbol} sleep 5 -${cli} gov submit-list-proposal --chain-id ${chain_id} --from zc --deposit 200000000000:BNB --base-asset-symbol ${zcb_symbol} --quote-asset-symbol BNB --init-price 1000000000 --title "list NNB/BNB" --description "list NNB/BNB" --expire-time 1644486400 --json +((expire_time=$(date '+%s')+1000)) +${cli} gov submit-list-proposal --chain-id ${chain_id} --from zc --deposit 200000000000:BNB --base-asset-symbol ${zcb_symbol} --quote-asset-symbol BNB --init-price 1000000000 --title "list NNB/BNB" --description "list NNB/BNB" --expire-time ${expire_time} --voting-period 5 --json sleep 2 ${cli} gov vote --from zc --chain-id ${chain_id} --proposal-id 2 --option Yes --json sleep 6 diff --git a/plugins/api/handlers/stake.go b/plugins/api/handlers/stake.go index 5d69409b9..08b1b1ef8 100644 --- a/plugins/api/handlers/stake.go +++ b/plugins/api/handlers/stake.go @@ -18,7 +18,7 @@ import ( func ValidatorQueryReqHandler(cdc *wire.Codec, ctx context.CLIContext) http.HandlerFunc { type ValidatorOutput struct { - AccoutAddr sdk.AccAddress `json:"account_address"` + AccountAddr sdk.AccAddress `json:"account_address"` OperatorAddr sdk.ValAddress `json:"operator_address"` ConsPubKey crypto.PubKey `json:"consensus_pubkey"` ConsAddr cmn.HexBytes `json:"consensus_address"` @@ -38,7 +38,7 @@ func ValidatorQueryReqHandler(cdc *wire.Codec, ctx context.CLIContext) http.Hand convertToValidatorOutputs := func(validators []stake.Validator) (validatorOutputs []ValidatorOutput) { for _, val := range validators { validatorOutputs = append(validatorOutputs, ValidatorOutput{ - AccoutAddr: sdk.AccAddress(val.OperatorAddr), + AccountAddr: val.FeeAddr, OperatorAddr: val.OperatorAddr, ConsPubKey: val.ConsPubKey, ConsAddr: val.ConsPubKey.Address(), diff --git a/plugins/api/routes.go b/plugins/api/routes.go index 4d4923d0e..819ef259b 100644 --- a/plugins/api/routes.go +++ b/plugins/api/routes.go @@ -5,6 +5,7 @@ import ( tx "github.com/cosmos/cosmos-sdk/client/tx" auth "github.com/cosmos/cosmos-sdk/x/auth/client/rest" bank "github.com/cosmos/cosmos-sdk/x/bank/client/rest" + gov "github.com/cosmos/cosmos-sdk/x/gov/client/rest" ) const version = "v1" @@ -75,6 +76,6 @@ func (s *server) bindRoutes() *server { tx.RegisterRoutes(s.ctx, r, s.cdc) auth.RegisterRoutes(s.ctx, r, s.cdc, s.accStoreName) bank.RegisterRoutes(s.ctx, r, s.cdc, s.keyBase) - + gov.RegisterRoutes(s.ctx, r, s.cdc) return s } diff --git a/plugins/dex/list/handler_test.go b/plugins/dex/list/handler_test.go index eebe55704..8ecdbe127 100644 --- a/plugins/dex/list/handler_test.go +++ b/plugins/dex/list/handler_test.go @@ -75,7 +75,7 @@ func MakeKeepers(cdc *codec.Codec) (ms sdkStore.CommitMultiStore, orderKeeper *o stakeKeeper := stake.NewKeeper( cdc, stakeKey, stakeTKey, - bankKeeper, paramsKeeper.Subspace(stake.DefaultParamspace), + bankKeeper, nil, paramsKeeper.Subspace(stake.DefaultParamspace), stake.DefaultCodespace, ) govKeeper = gov.NewKeeper(cdc, govKey, diff --git a/plugins/dex/matcheng/engine.go b/plugins/dex/matcheng/engine.go index 68d0ee983..0d411c92b 100644 --- a/plugins/dex/matcheng/engine.go +++ b/plugins/dex/matcheng/engine.go @@ -2,9 +2,6 @@ package matcheng import ( "math" - "sort" - - "github.com/binance-chain/node/common/upgrade" ) type MatchEng struct { @@ -42,11 +39,6 @@ func (me *MatchEng) fillOrders(i int, j int) { sells := me.overLappedLevel[j].SellOrders origBuyPx := me.overLappedLevel[i].Price - upgrade.FixOrderSeqInPriceLevel(func() { - sort.Slice(buys, func(i, j int) bool { return buys[i].Id < buys[j].Id }) - sort.Slice(sells, func(i, j int) bool { return sells[i].Id < sells[j].Id }) - }, nil, nil) - bLength := len(buys) sLength := len(sells) for k < bLength && h < sLength { @@ -233,17 +225,9 @@ func (me *MatchEng) DropFilledOrder() (droppedIds []string) { if p.BuyTotal == 0 { me.Book.RemovePriceLevel(p.Price, BUYSIDE) } else { - upgrade.FixDropFilledOrderSeq(func() { - for _, o := range p.BuyOrders { - if o.nxtTrade == 0 { - me.Book.RemoveOrder(o.Id, BUYSIDE, p.Price) - } - } - }, func() { - for i := toRemoveStartIdx; i < toRemoveEndIdx; i++ { - me.Book.RemoveOrder(droppedIds[i], BUYSIDE, p.Price) - } - }) + for i := toRemoveStartIdx; i < toRemoveEndIdx; i++ { + me.Book.RemoveOrder(droppedIds[i], BUYSIDE, p.Price) + } } } toRemoveStartIdx = toRemoveEndIdx @@ -258,17 +242,9 @@ func (me *MatchEng) DropFilledOrder() (droppedIds []string) { if p.SellTotal == 0 { me.Book.RemovePriceLevel(p.Price, SELLSIDE) } else { - upgrade.FixDropFilledOrderSeq(func() { - for _, o := range p.SellOrders { - if o.nxtTrade == 0 { - me.Book.RemoveOrder(o.Id, SELLSIDE, p.Price) - } - } - }, func() { - for i := toRemoveStartIdx; i < toRemoveEndIdx; i++ { - me.Book.RemoveOrder(droppedIds[i], SELLSIDE, p.Price) - } - }) + for i := toRemoveStartIdx; i < toRemoveEndIdx; i++ { + me.Book.RemoveOrder(droppedIds[i], SELLSIDE, p.Price) + } } } } diff --git a/plugins/dex/matcheng/match.go b/plugins/dex/matcheng/match.go index 43eb6576e..b7042fb33 100644 --- a/plugins/dex/matcheng/match.go +++ b/plugins/dex/matcheng/match.go @@ -3,9 +3,7 @@ package matcheng import ( "math" "math/big" - "sort" - "github.com/binance-chain/node/common/upgrade" "github.com/binance-chain/node/common/utils" ) @@ -221,11 +219,6 @@ func allocateResidual(toAlloc *int64, orders []OrderPart, lotSize int64) bool { } t := sumOrdersTotalLeft(orders, false) - - upgrade.FixOrderSeqInPriceLevel(func() { - sort.Slice(orders, func(i, j int) bool { return orders[i].Id < orders[j].Id }) - }, nil, nil) - residual := *toAlloc if compareBuy(t, residual) > 0 { // not enough to allocate @@ -273,7 +266,7 @@ func allocateResidual(toAlloc *int64, orders []OrderPart, lotSize int64) bool { // totalLot * orderLeft / totalLeft, orderLeft <= totalLeft func calcNumOfLot(totalLot, orderLeft, totalLeft int64) int64 { if tmp, ok := utils.Mul64(totalLot, orderLeft); ok { - return tmp/totalLeft + return tmp / totalLeft } else { var res big.Int res.Quo(res.Mul(big.NewInt(totalLot), big.NewInt(orderLeft)), big.NewInt(totalLeft)) diff --git a/plugins/dex/matcheng/match_test.go b/plugins/dex/matcheng/match_test.go index d88320b87..e75dc991b 100644 --- a/plugins/dex/matcheng/match_test.go +++ b/plugins/dex/matcheng/match_test.go @@ -58,7 +58,7 @@ func Test_prepareMatch_overflow(t *testing.T) { {Price: 961, SellOrders: []OrderPart{{"6.1", 101, 400e16, 0, 0}}}, } execs := []int64{300e16, 400e16, 600e16, math.MaxInt64, 700e16, 400e16} - surpluses := []int64{300e16 - math.MaxInt64, 400e16 - math.MaxInt64, 600e16 - math.MaxInt64, 0, math.MaxInt64-700e16, math.MaxInt64-400e16} + surpluses := []int64{300e16 - math.MaxInt64, 400e16 - math.MaxInt64, 600e16 - math.MaxInt64, 0, math.MaxInt64 - 700e16, math.MaxInt64 - 400e16} assert.Equal(6, prepareMatch(&overlap)) for i, e := range execs { assert.Equal(e, overlap[i].AccumulatedExecutions, fmt.Sprintf("overlap number %d", i)) @@ -473,16 +473,16 @@ func TestMatchEng_fillOrders(t *testing.T) { me.LastTradePrice = 999 me.overLappedLevel = []OverLappedLevel{OverLappedLevel{Price: 1000, BuyOrders: []OrderPart{ - OrderPart{"2", 100, 80, 0, 0}, OrderPart{"1", 100, 70, 0, 0}, - OrderPart{"4", 100, 50, 0, 0}, + OrderPart{"2", 100, 80, 0, 0}, OrderPart{"3", 100, 100, 0, 0}, + OrderPart{"4", 100, 50, 0, 0}, }, SellOrders: []OrderPart{ - OrderPart{"9", 100, 60, 0, 0}, - OrderPart{"8", 100, 70, 0, 0}, - OrderPart{"7", 100, 50, 0, 0}, OrderPart{"6", 100, 100, 0, 0}, + OrderPart{"7", 100, 50, 0, 0}, + OrderPart{"8", 100, 70, 0, 0}, + OrderPart{"9", 100, 60, 0, 0}, }, }} prepareMatch(&me.overLappedLevel) @@ -505,19 +505,19 @@ func TestMatchEng_fillOrders(t *testing.T) { me.overLappedLevel = []OverLappedLevel{ OverLappedLevel{Price: 1000, BuyOrders: []OrderPart{ - OrderPart{"2", 100, 80, 0, 0}, OrderPart{"1", 100, 70, 0, 0}, - OrderPart{"4", 100, 50, 0, 0}, + OrderPart{"2", 100, 80, 0, 0}, OrderPart{"3", 100, 100, 0, 0}, + OrderPart{"4", 100, 50, 0, 0}, }, SellOrders: []OrderPart{}}, OverLappedLevel{Price: 1000, BuyOrders: []OrderPart{}, SellOrders: []OrderPart{ - OrderPart{"9", 100, 60, 0, 0}, - OrderPart{"8", 100, 70, 0, 0}, - OrderPart{"7", 100, 50, 0, 0}, OrderPart{"6", 100, 100, 0, 0}, + OrderPart{"7", 100, 50, 0, 0}, + OrderPart{"8", 100, 70, 0, 0}, + OrderPart{"9", 100, 60, 0, 0}, }}, } prepareMatch(&me.overLappedLevel) @@ -549,8 +549,8 @@ func Test_allocateResidual(t *testing.T) { orders = []OrderPart{ OrderPart{"1", 100, 900, 0, 900}, - OrderPart{"3", 100, 600, 0, 600}, OrderPart{"2", 100, 300, 0, 300}, + OrderPart{"3", 100, 600, 0, 600}, } toAlloc = 600 assert.True(allocateResidual(&toAlloc, orders, 5)) @@ -563,8 +563,8 @@ func Test_allocateResidual(t *testing.T) { orders = []OrderPart{ OrderPart{"1", 100, 900, 0, 900}, - OrderPart{"3", 100, 600, 0, 600}, OrderPart{"2", 100, 300, 0, 300}, + OrderPart{"3", 100, 600, 0, 600}, } toAlloc = 500 assert.True(allocateResidual(&toAlloc, orders, 5)) @@ -577,8 +577,8 @@ func Test_allocateResidual(t *testing.T) { orders = []OrderPart{ OrderPart{"1", 100, 900, 0, 900}, - OrderPart{"3", 100, 600, 0, 600}, OrderPart{"2", 100, 300, 0, 300}, + OrderPart{"3", 100, 600, 0, 600}, } toAlloc = 25 assert.True(allocateResidual(&toAlloc, orders, 5)) @@ -591,8 +591,8 @@ func Test_allocateResidual(t *testing.T) { orders = []OrderPart{ OrderPart{"1", 100, 900, 0, 900}, - OrderPart{"3", 100, 600, 0, 600}, OrderPart{"2", 100, 300, 0, 300}, + OrderPart{"3", 100, 600, 0, 600}, } toAlloc = 35 assert.True(allocateResidual(&toAlloc, orders, 5)) @@ -605,8 +605,8 @@ func Test_allocateResidual(t *testing.T) { orders = []OrderPart{ OrderPart{"1", 100, 900, 0, 900}, - OrderPart{"3", 100, 900, 0, 900}, OrderPart{"2", 100, 900, 0, 900}, + OrderPart{"3", 100, 900, 0, 900}, } toAlloc = 700 assert.True(allocateResidual(&toAlloc, orders, 5)) @@ -637,9 +637,9 @@ func Test_allocateResidualOddLot(t *testing.T) { var toAlloc int64 = 605 orders := []OrderPart{ + OrderPart{"1", 100, 300, 0, 300}, OrderPart{"2", 100, 900, 0, 900}, OrderPart{"3", 100, 600, 0, 600}, - OrderPart{"1", 100, 300, 0, 300}, } assert.True(allocateResidual(&toAlloc, orders, 10)) assert.Equal(int64(105), orders[0].nxtTrade) @@ -651,9 +651,9 @@ func Test_allocateResidualOddLot(t *testing.T) { toAlloc = 5 orders = []OrderPart{ + OrderPart{"1", 100, 300, 0, 300}, OrderPart{"2", 100, 900, 0, 900}, OrderPart{"3", 100, 600, 0, 600}, - OrderPart{"1", 100, 300, 0, 300}, } assert.True(allocateResidual(&toAlloc, orders, 10)) assert.Equal(int64(5), orders[0].nxtTrade) @@ -662,9 +662,9 @@ func Test_allocateResidualOddLot(t *testing.T) { toAlloc = 15 orders = []OrderPart{ + OrderPart{"1", 100, 25, 0, 25}, OrderPart{"2", 100, 25, 0, 25}, OrderPart{"3", 100, 25, 0, 25}, - OrderPart{"1", 100, 25, 0, 25}, } assert.True(allocateResidual(&toAlloc, orders, 10)) assert.Equal(int64(10), orders[0].nxtTrade) @@ -720,8 +720,8 @@ func TestMatchEng_reserveQty(t *testing.T) { OrderPart{"2", 100, 900, 0, 900}, OrderPart{"3", 101, 900, 0, 900}, OrderPart{"6", 101, 900, 0, 900}, - OrderPart{"5", 102, 900, 0, 900}, OrderPart{"4", 102, 900, 0, 900}, + OrderPart{"5", 102, 900, 0, 900}, OrderPart{"7", 102, 900, 0, 900}, } diff --git a/plugins/dex/order/handler.go b/plugins/dex/order/handler.go index 2b9f8d350..f462b0f32 100644 --- a/plugins/dex/order/handler.go +++ b/plugins/dex/order/handler.go @@ -155,7 +155,7 @@ func handleNewOrder( if txHash, ok := ctx.Value(baseapp.TxHashKey).(string); ok { blockHeader := ctx.BlockHeader() height := blockHeader.Height - timestamp := blockHeader.Time.Unix() + timestamp := blockHeader.Time.UnixNano() msg := OrderInfo{ msg, height, timestamp, diff --git a/plugins/dex/order/keeper.go b/plugins/dex/order/keeper.go index 14b591047..3b9aec1e0 100644 --- a/plugins/dex/order/keeper.go +++ b/plugins/dex/order/keeper.go @@ -3,7 +3,6 @@ package order import ( "errors" "fmt" - "sort" "strings" "sync" "time" @@ -17,7 +16,6 @@ import ( "github.com/binance-chain/node/common/fees" bnclog "github.com/binance-chain/node/common/log" "github.com/binance-chain/node/common/types" - "github.com/binance-chain/node/common/upgrade" "github.com/binance-chain/node/common/utils" me "github.com/binance-chain/node/plugins/dex/matcheng" "github.com/binance-chain/node/plugins/dex/store" @@ -345,17 +343,6 @@ func updateOrderMsg(order *OrderInfo, cumQty, height, timestamp int64) { // please note if distributeTrade this method will work in async mode, otherwise in sync mode. func (kp *Keeper) matchAndDistributeTrades(distributeTrade bool, height, timestamp int64) []chan Transfer { - // when we reach the upgrade height, we must sort the orders in each price level even when this pair does not need match in this round. - upgrade.FixOrderSeqInPriceLevel(nil, func() { - priceLevelUpdater := func(pl *me.PriceLevel) { - orders := pl.Orders - sort.Slice(orders, func(i, j int) bool { return orders[i].Time < orders[j].Time }) - } - for _, eng := range kp.engines { - eng.Book.UpdateForEachPriceLevel(me.BUYSIDE, priceLevelUpdater) - eng.Book.UpdateForEachPriceLevel(me.SELLSIDE, priceLevelUpdater) - } - }, nil) size := len(kp.roundOrders) // size is the number of pairs that have new orders, i.e. it should call match() if size == 0 { @@ -668,7 +655,8 @@ func (kp *Keeper) MatchAndAllocateAll( postAlloTransHandler TransferHandler, ) { bnclog.Debug("Start Matching for all...", "symbolNum", len(kp.roundOrders)) - tradeOuts := kp.matchAndDistributeTrades(true, ctx.BlockHeight(), ctx.BlockHeader().Time.Unix()) + timestamp := ctx.BlockHeader().Time.UnixNano() + tradeOuts := kp.matchAndDistributeTrades(true, ctx.BlockHeight(), timestamp) if tradeOuts == nil { kp.logger.Info("No order comes in for the block") return diff --git a/plugins/dex/order/keeper_recovery.go b/plugins/dex/order/keeper_recovery.go index 5f3185502..1823b40a9 100644 --- a/plugins/dex/order/keeper_recovery.go +++ b/plugins/dex/order/keeper_recovery.go @@ -188,6 +188,8 @@ func (kp *Keeper) replayOneBlocks(logger log.Logger, block *tmtypes.Block, txDB logger.Error("No block is loaded. Ignore replay for orderbook") return } + // the time we replay should be consistent with ctx.BlockHeader().Time + t := timestamp.UnixNano() for _, txBytes := range block.Txs { txHash := cmn.HexBytes(tmhash.Sum(txBytes)) skipTxResultCheck := false @@ -221,9 +223,6 @@ func (kp *Keeper) replayOneBlocks(logger log.Logger, block *tmtypes.Block, txDB for _, m := range msgs { switch msg := m.(type) { case NewOrderMsg: - // the time we replay should be consistent with ctx.BlockHeader().Time - // TODO(#118): after upgrade to tendermint 0.24 we should have better and more consistent time representation - t := timestamp.Unix() orderInfo := OrderInfo{ msg, height, t, @@ -246,8 +245,7 @@ func (kp *Keeper) replayOneBlocks(logger log.Logger, block *tmtypes.Block, txDB } } logger.Info("replayed all tx. Starting match", "height", height) - // TODO(#118): after upgrade to tendermint 0.24 we should have better and more consistent time representation - kp.MatchAll(height, timestamp.Unix()) //no need to check result + kp.MatchAll(height, t) //no need to check result } func (kp *Keeper) ReplayOrdersFromBlock(ctx sdk.Context, bc *bc.BlockStore, txDB dbm.DB, lastHeight, breatheHeight int64, diff --git a/plugins/dex/utils/numbers.go b/plugins/dex/utils/numbers.go index 8b28e014f..22bc3f9e5 100644 --- a/plugins/dex/utils/numbers.go +++ b/plugins/dex/utils/numbers.go @@ -13,7 +13,7 @@ func CalBigNotionalInt64(price, qty int64) int64 { res, ok := utils.Mul64(price, qty) if ok { // short cut - return res/1e8 + return res / 1e8 } var bi big.Int diff --git a/plugins/dex/utils/pair.go b/plugins/dex/utils/pair.go index 727193922..ad0443854 100644 --- a/plugins/dex/utils/pair.go +++ b/plugins/dex/utils/pair.go @@ -40,7 +40,7 @@ func CalcPriceWMA(prices *utils.FixedSizeRing) int64 { weightedSum := big.NewInt(0) lenPrices := len(elements) - for i:=0; i < lenPrices; i++ { + for i := 0; i < lenPrices; i++ { var weightedPrice big.Int weightedPrice.Mul(big.NewInt(int64(i+1)), big.NewInt(elements[i].(int64))) weightedSum.Add(weightedSum, &weightedPrice) diff --git a/plugins/param/genesis.go b/plugins/param/genesis.go index c39804ee1..55cb292f7 100644 --- a/plugins/param/genesis.go +++ b/plugins/param/genesis.go @@ -18,8 +18,8 @@ const ( // Operate fee ProposeFee = 10e8 DepositFee = 125e3 - ListingFee = 10000e8 - IssueFee = 2000e8 + ListingFee = 2000e8 + IssueFee = 1000e8 MintFee = 200e8 BurnFee = 1e8 FreezeFee = 1e6 @@ -29,19 +29,19 @@ const ( RemoveValidatorFee = 1e8 // Transfer fee - TransferFee = 125e3 - MultiTransferFee = 100e3 // discount 80% + TransferFee = 62500 + MultiTransferFee = 50000 // discount 80% LowerLimitAsMulti = 2 // Dex fee - ExpireFee = 1e5 - ExpireFeeNative = 2e4 - CancelFee = 1e5 - CancelFeeNative = 2e4 + ExpireFee = 5e4 + ExpireFeeNative = 1e4 + CancelFee = 5e4 + CancelFeeNative = 1e4 FeeRate = 1000 FeeRateNative = 400 - IOCExpireFee = 5e4 - IOCExpireFeeNative = 1e4 + IOCExpireFee = 25e3 + IOCExpireFeeNative = 5e3 ) var DefaultGenesisState = param.GenesisState{ diff --git a/version/version.go b/version/version.go index d64685962..edbb2dea4 100644 --- a/version/version.go +++ b/version/version.go @@ -12,7 +12,7 @@ var ( Version string ) -const NodeVersion = "0.5.4" +const NodeVersion = "0.5.6" func init() { Version = fmt.Sprintf("Binance Chain Release: %s;", NodeVersion)