From 3b8e170efa6e53a9049df2dfc49fd05333e90fdc Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 24 Mar 2020 15:40:34 +0300 Subject: [PATCH 001/426] add SetHaltBlock transaction --- api/transaction.go | 2 + api/v2/service/transaction.go | 2 + core/code/code.go | 1 + core/commissions/commissions.go | 1 + core/minter/minter.go | 36 +++++- core/state/bus/bus.go | 9 ++ core/state/bus/halts.go | 7 + core/state/halts/bus.go | 17 +++ core/state/halts/halts.go | 165 ++++++++++++++++++++++++ core/state/halts/model.go | 33 +++++ core/state/state.go | 8 ++ core/transaction/decoder.go | 1 + core/transaction/set_halt_block.go | 142 ++++++++++++++++++++ core/transaction/set_halt_block_test.go | 84 ++++++++++++ core/transaction/transaction.go | 1 + core/types/appstate.go | 7 + 16 files changed, 514 insertions(+), 2 deletions(-) create mode 100644 core/state/bus/halts.go create mode 100644 core/state/halts/bus.go create mode 100644 core/state/halts/halts.go create mode 100644 core/state/halts/model.go create mode 100644 core/transaction/set_halt_block.go create mode 100644 core/transaction/set_halt_block_test.go diff --git a/api/transaction.go b/api/transaction.go index 3997a575d..216352742 100644 --- a/api/transaction.go +++ b/api/transaction.go @@ -75,6 +75,8 @@ func encodeTxData(decodedTx *transaction.Transaction) ([]byte, error) { return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.CreateMultisigData)) case transaction.TypeEditCandidate: return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.EditCandidateData)) + case transaction.TypeSetHaltBlock: + return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.SetHaltBlockData)) } return nil, rpctypes.RPCError{Code: 500, Message: "unknown tx type"} diff --git a/api/v2/service/transaction.go b/api/v2/service/transaction.go index e55f26c18..067d16944 100644 --- a/api/v2/service/transaction.go +++ b/api/v2/service/transaction.go @@ -96,6 +96,8 @@ func (s *Service) encodeTxData(decodedTx *transaction.Transaction) (*_struct.Str b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.CreateMultisigData)) case transaction.TypeEditCandidate: b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.EditCandidateData)) + case transaction.TypeSetHaltBlock: + b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.SetHaltBlockData)) default: return nil, errors.New("unknown tx type") } diff --git a/core/code/code.go b/core/code/code.go index 36deba7eb..12b283a8e 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -17,6 +17,7 @@ const ( TooLowGasPrice uint32 = 114 WrongChainID uint32 = 115 CoinReserveUnderflow uint32 = 116 + WrongHaltHeight uint32 = 117 // coin creation CoinAlreadyExists uint32 = 201 diff --git a/core/commissions/commissions.go b/core/commissions/commissions.go index e90b8e399..13181b60a 100644 --- a/core/commissions/commissions.go +++ b/core/commissions/commissions.go @@ -14,4 +14,5 @@ const ( EditCandidate int64 = 10000 MultisendDelta int64 = 5 RedeemCheckTx int64 = SendTx * 3 + SetHaltBlock int64 = 1000 ) diff --git a/core/minter/minter.go b/core/minter/minter.go index ff3485f37..2d9d2557c 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -43,6 +43,8 @@ const ( DefaultMaxGas = 100000 MinMaxGas = 5000 + + VotingPowerConsensus = 2 / 3 ) var ( @@ -165,8 +167,38 @@ func (app *Blockchain) InitChain(req abciTypes.RequestInitChain) abciTypes.Respo func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.ResponseBeginBlock { height := uint64(req.Header.Height) - if app.haltHeight > 0 && height >= app.haltHeight { - panic(fmt.Sprintf("Application halted at height %d", height)) + halts := app.stateDeliver.Halts.GetHaltBlocks(height) + if halts != nil { + // calculate total power of validators + validators := app.stateDeliver.Validators.GetValidators() + totalPower, totalVotingPower := big.NewInt(0), big.NewInt(0) + for _, val := range validators { + // skip if candidate is not present + if val.IsToDrop() || app.validatorsStatuses[val.GetAddress()] != ValidatorPresent { + continue + } + + for _, halt := range halts.List { + if halt.CandidateKey == val.PubKey { + totalVotingPower.Add(totalVotingPower, val.GetTotalBipStake()) + } + } + + totalPower.Add(totalPower, val.GetTotalBipStake()) + } + + if totalPower.Cmp(types.Big0) == 0 { + totalPower = big.NewInt(1) + } + + votingResult := new(big.Float).Quo( + new(big.Float).SetInt(totalVotingPower), + new(big.Float).SetInt(totalPower), + ) + + if votingResult.Cmp(big.NewFloat(VotingPowerConsensus)) == 1 { + panic(fmt.Sprintf("Application halted at height %d", height)) + } } app.StatisticData().SetStartBlock(height, time.Now(), req.Header.Time) diff --git a/core/state/bus/bus.go b/core/state/bus/bus.go index 699d011bd..89b1379bf 100644 --- a/core/state/bus/bus.go +++ b/core/state/bus/bus.go @@ -8,6 +8,7 @@ type Bus struct { accounts Accounts candidates Candidates frozenfunds FrozenFunds + halts HaltBlocks events eventsdb.IEventsDB checker Checker } @@ -56,6 +57,14 @@ func (b *Bus) FrozenFunds() FrozenFunds { return b.frozenfunds } +func (b *Bus) SetHaltBlocks(halts HaltBlocks) { + b.halts = halts +} + +func (b *Bus) Halts() HaltBlocks { + return b.halts +} + func (b *Bus) SetEvents(events eventsdb.IEventsDB) { b.events = events } diff --git a/core/state/bus/halts.go b/core/state/bus/halts.go new file mode 100644 index 000000000..732ead868 --- /dev/null +++ b/core/state/bus/halts.go @@ -0,0 +1,7 @@ +package bus + +import "github.com/MinterTeam/minter-go-node/core/types" + +type HaltBlocks interface { + AddHaltBlock(uint64, types.Pubkey) +} diff --git a/core/state/halts/bus.go b/core/state/halts/bus.go new file mode 100644 index 000000000..d42cb9c36 --- /dev/null +++ b/core/state/halts/bus.go @@ -0,0 +1,17 @@ +package halts + +import ( + "github.com/MinterTeam/minter-go-node/core/types" +) + +type Bus struct { + halts *HaltBlocks +} + +func (b *Bus) AddHaltBlock(height uint64, pubkey types.Pubkey) { + b.halts.AddHaltBlock(height, pubkey) +} + +func NewBus(halts *HaltBlocks) *Bus { + return &Bus{halts: halts} +} diff --git a/core/state/halts/halts.go b/core/state/halts/halts.go new file mode 100644 index 000000000..4ef1ef89b --- /dev/null +++ b/core/state/halts/halts.go @@ -0,0 +1,165 @@ +package halts + +import ( + "encoding/binary" + "fmt" + "github.com/MinterTeam/minter-go-node/core/state/bus" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/rlp" + "github.com/MinterTeam/minter-go-node/tree" + "sort" + "sync" +) + +const mainPrefix = byte('h') + +type HaltBlocks struct { + list map[uint64]*Model + dirty map[uint64]interface{} + + bus *bus.Bus + iavl tree.Tree + + lock sync.RWMutex +} + +func NewHalts(stateBus *bus.Bus, iavl tree.Tree) (*HaltBlocks, error) { + halts := &HaltBlocks{ + bus: stateBus, + iavl: iavl, + list: map[uint64]*Model{}, + dirty: map[uint64]interface{}{}, + } + + halts.bus.SetHaltBlocks(NewBus(halts)) + + return halts, nil +} + +func (f *HaltBlocks) Commit() error { + dirty := f.getOrderedDirty() + for _, height := range dirty { + ff := f.getFromMap(height) + + f.lock.Lock() + delete(f.dirty, height) + f.lock.Unlock() + + data, err := rlp.EncodeToBytes(ff) + if err != nil { + return fmt.Errorf("can't encode object at %d: %v", height, err) + } + + path := getPath(height) + f.iavl.Set(path, data) + } + + return nil +} + +func (f *HaltBlocks) GetHaltBlocks(height uint64) *Model { + return f.get(height) +} + +func (f *HaltBlocks) GetOrNew(height uint64) *Model { + ff := f.get(height) + if ff == nil { + ff = &Model{ + height: height, + markDirty: f.markDirty, + } + f.setToMap(height, ff) + } + + return ff +} + +func (f *HaltBlocks) get(height uint64) *Model { + if ff := f.getFromMap(height); ff != nil { + return ff + } + + _, enc := f.iavl.Get(getPath(height)) + if len(enc) == 0 { + return nil + } + + ff := &Model{} + if err := rlp.DecodeBytes(enc, ff); err != nil { + panic(fmt.Sprintf("failed to decode halt blocks at height %d: %s", height, err)) + } + + ff.height = height + ff.markDirty = f.markDirty + + f.setToMap(height, ff) + + return ff +} + +func (f *HaltBlocks) markDirty(height uint64) { + f.dirty[height] = struct{}{} +} + +func (f *HaltBlocks) getOrderedDirty() []uint64 { + keys := make([]uint64, 0, len(f.dirty)) + for k := range f.dirty { + keys = append(keys, k) + } + + sort.SliceStable(keys, func(i, j int) bool { + return keys[i] < keys[j] + }) + + return keys +} + +func (f *HaltBlocks) AddHaltBlock(height uint64, pubkey types.Pubkey) { + f.GetOrNew(height).addHaltBlock(pubkey) +} + +func (f *HaltBlocks) Delete(height uint64) { + ff := f.get(height) + if ff == nil { + return + } + + ff.delete() +} + +func (f *HaltBlocks) Export(state *types.AppState, height uint64) { + for i := height; i <= height; i++ { + halts := f.get(i) + if halts == nil { + continue + } + + for _, haltBlock := range halts.List { + state.HaltBlocks = append(state.HaltBlocks, types.HaltBlock{ + Height: i, + CandidateKey: haltBlock.CandidateKey, + }) + } + } +} + +func (f *HaltBlocks) getFromMap(height uint64) *Model { + f.lock.RLock() + defer f.lock.RUnlock() + + return f.list[height] +} + +func (f *HaltBlocks) setToMap(height uint64, model *Model) { + f.lock.Lock() + defer f.lock.Unlock() + + f.list[height] = model +} + +func getPath(height uint64) []byte { + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, height) + + return append([]byte{mainPrefix}, b...) +} diff --git a/core/state/halts/model.go b/core/state/halts/model.go new file mode 100644 index 000000000..07e0a31ec --- /dev/null +++ b/core/state/halts/model.go @@ -0,0 +1,33 @@ +package halts + +import ( + "github.com/MinterTeam/minter-go-node/core/types" +) + +type Item struct { + CandidateKey types.Pubkey +} + +type Model struct { + List []Item + + height uint64 + deleted bool + markDirty func(height uint64) +} + +func (m *Model) delete() { + m.deleted = true + m.markDirty(m.height) +} + +func (m *Model) addHaltBlock(pubkey types.Pubkey) { + m.List = append(m.List, Item{ + CandidateKey: pubkey, + }) + m.markDirty(m.height) +} + +func (m *Model) Height() uint64 { + return m.height +} diff --git a/core/state/state.go b/core/state/state.go index bffdc9cee..3d24417c5 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -12,6 +12,7 @@ import ( "github.com/MinterTeam/minter-go-node/core/state/checks" "github.com/MinterTeam/minter-go-node/core/state/coins" "github.com/MinterTeam/minter-go-node/core/state/frozenfunds" + "github.com/MinterTeam/minter-go-node/core/state/halts" "github.com/MinterTeam/minter-go-node/core/state/validators" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/helpers" @@ -26,6 +27,7 @@ type State struct { Validators *validators.Validators Candidates *candidates.Candidates FrozenFunds *frozenfunds.FrozenFunds + Halts *halts.HaltBlocks Accounts *accounts.Accounts Coins *coins.Coins Checks *checks.Checks @@ -262,6 +264,11 @@ func newStateForTree(iavlTree tree.Tree, events eventsdb.IEventsDB, db db.DB, ke return nil, err } + haltsState, err := halts.NewHalts(stateBus, iavlTree) + if err != nil { + return nil, err + } + state := &State{ Validators: validatorsState, App: appState, @@ -271,6 +278,7 @@ func newStateForTree(iavlTree tree.Tree, events eventsdb.IEventsDB, db db.DB, ke Coins: coinsState, Checks: checksState, Checker: stateChecker, + Halts: haltsState, bus: stateBus, db: db, diff --git a/core/transaction/decoder.go b/core/transaction/decoder.go index 271be9614..193920a7a 100644 --- a/core/transaction/decoder.go +++ b/core/transaction/decoder.go @@ -26,6 +26,7 @@ func init() { TxDecoder.RegisterType(TypeMultisend, MultisendData{}) TxDecoder.RegisterType(TypeCreateMultisig, CreateMultisigData{}) TxDecoder.RegisterType(TypeEditCandidate, EditCandidateData{}) + TxDecoder.RegisterType(TypeSetHaltBlock, SetHaltBlockData{}) } type Decoder struct { diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go new file mode 100644 index 000000000..88d70d1ec --- /dev/null +++ b/core/transaction/set_halt_block.go @@ -0,0 +1,142 @@ +package transaction + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/commissions" + "github.com/MinterTeam/minter-go-node/core/state" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/formula" + "github.com/MinterTeam/minter-go-node/hexutil" + "github.com/tendermint/tendermint/libs/kv" + "math/big" + "strconv" +) + +type SetHaltBlockData struct { + PubKey types.Pubkey + Height uint64 +} + +func (data SetHaltBlockData) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + PubKey string `json:"pub_key"` + Height string `json:"height"` + }{ + PubKey: data.PubKey.String(), + Height: strconv.FormatUint(data.Height, 10), + }) +} + +func (data SetHaltBlockData) GetPubKey() types.Pubkey { + return data.PubKey +} + +func (data SetHaltBlockData) TotalSpend(tx *Transaction, context *state.State) (TotalSpends, []Conversion, *big.Int, *Response) { + panic("implement me") +} + +func (data SetHaltBlockData) BasicCheck(tx *Transaction, context *state.State) *Response { + if !context.Candidates.Exists(data.PubKey) { + return &Response{ + Code: code.CandidateNotFound, + Log: fmt.Sprintf("Candidate with such public key not found"), + Info: EncodeError(map[string]string{ + "pub_key": data.PubKey.String(), + }), + } + } + + return checkCandidateOwnership(data, tx, context) +} + +func (data SetHaltBlockData) String() string { + return fmt.Sprintf("SET HALT BLOCK pubkey:%s height:%d", + hexutil.Encode(data.PubKey[:]), data.Height) +} + +func (data SetHaltBlockData) Gas() int64 { + return commissions.SetHaltBlock +} + +func (data SetHaltBlockData) Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response { + sender, _ := tx.Sender() + + response := data.BasicCheck(tx, context) + if response != nil { + return *response + } + + if data.Height < currentBlock { + return Response{ + Code: code.WrongHaltHeight, + Log: fmt.Sprintf("Halt height should be equal or bigger than current: %d", currentBlock), + Info: EncodeError(map[string]string{ + "height": strconv.FormatUint(data.Height, 10), + }), + } + } + + commissionInBaseCoin := tx.CommissionInBaseCoin() + commission := big.NewInt(0).Set(commissionInBaseCoin) + + if !tx.GasCoin.IsBaseCoin() { + coin := context.Coins.GetCoin(tx.GasCoin) + + errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) + if errResp != nil { + return *errResp + } + + if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { + return Response{ + Code: code.CoinReserveNotSufficient, + Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String()), + Info: EncodeError(map[string]string{ + "has_reserve": coin.Reserve().String(), + "commission": commissionInBaseCoin.String(), + "gas_coin": coin.CName, + }), + } + } + + commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + } + + if context.Accounts.GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + return Response{ + Code: code.InsufficientFunds, + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, tx.GasCoin), + Info: EncodeError(map[string]string{ + "sender": sender.String(), + "needed_value": commission.String(), + "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + }), + } + } + + if !isCheck { + rewardPool.Add(rewardPool, commissionInBaseCoin) + + context.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + context.Coins.SubVolume(tx.GasCoin, commission) + + context.Accounts.SubBalance(sender, tx.GasCoin, commission) + context.Halts.AddHaltBlock(data.Height, data.PubKey) + context.Accounts.SetNonce(sender, tx.Nonce) + } + + tags := kv.Pairs{ + kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeUnbond)}))}, + kv.Pair{Key: []byte("tx.from"), Value: []byte(hex.EncodeToString(sender[:]))}, + } + + return Response{ + Code: code.OK, + GasUsed: tx.Gas(), + GasWanted: tx.Gas(), + Tags: tags, + } +} diff --git a/core/transaction/set_halt_block_test.go b/core/transaction/set_halt_block_test.go new file mode 100644 index 000000000..3fadad944 --- /dev/null +++ b/core/transaction/set_halt_block_test.go @@ -0,0 +1,84 @@ +package transaction + +import ( + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/crypto" + "github.com/MinterTeam/minter-go-node/helpers" + "github.com/MinterTeam/minter-go-node/rlp" + "math/big" + "math/rand" + "sync" + "testing" +) + +func TestSetHaltBlockTx(t *testing.T) { + cState := getState() + + haltHeight := uint64(100) + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoin() + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + cState.Candidates.Create(addr, addr, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1))) + + data := SetHaltBlockData{ + PubKey: pubkey, + Height: haltHeight, + } + + encodedData, err := rlp.EncodeToBytes(data) + + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSetHaltBlock, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != 0 { + t.Fatalf("Response code is not 0. Error %s", response.Log) + } + + targetBalance, _ := big.NewInt(0).SetString("0", 10) + balance := cState.Accounts.GetBalance(addr, coin) + if balance.Cmp(targetBalance) != 0 { + t.Fatalf("Target %s balance is not correct. Expected %s, got %s", coin, targetBalance, balance) + } + + halts := cState.Halts.GetHaltBlocks(haltHeight) + if halts == nil { + t.Fatalf("No halts on the height: %d", haltHeight) + } + + haltBlocks := halts.List + if len(haltBlocks) != 1 { + t.Fatalf("Halt blocks are not correct. Expected halts size: %d, got %d", 1, len(haltBlocks)) + } + + haltBlock := haltBlocks[0] + if haltBlock.CandidateKey != pubkey { + t.Fatalf("Wront halt block pubkey. Expected pubkey: %s, got %s", pubkey, haltBlock.CandidateKey.String()+"asd") + } +} diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index a91f25a59..f1e70dd24 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -33,6 +33,7 @@ const ( TypeCreateMultisig TxType = 0x0C TypeMultisend TxType = 0x0D TypeEditCandidate TxType = 0x0E + TypeSetHaltBlock TxType = 0x10 SigTypeSingle SigType = 0x01 SigTypeMulti SigType = 0x02 diff --git a/core/types/appstate.go b/core/types/appstate.go index 175177ce4..8f320f7b0 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -15,6 +15,7 @@ type AppState struct { Accounts []Account `json:"accounts,omitempty"` Coins []Coin `json:"coins,omitempty"` FrozenFunds []FrozenFund `json:"frozen_funds,omitempty"` + HaltBlocks []HaltBlock `json:"halt_blocks,omitempty"` UsedChecks []UsedCheck `json:"used_checks,omitempty"` MaxGas uint64 `json:"max_gas"` TotalSlashed string `json:"total_slashed"` @@ -260,3 +261,9 @@ type Multisig struct { Threshold uint `json:"threshold"` Addresses []Address `json:"addresses"` } + +type HaltBlock struct { + Height uint64 `json:"height"` + HaltHeight uint64 `json:"halt_height"` + CandidateKey Pubkey `json:"candidate_key"` +} From b03f039eb09ff8aa4cfc88b333fb93612c2df9d7 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 24 Mar 2020 15:45:28 +0300 Subject: [PATCH 002/426] remove HaltHeight from HaltBlock type --- core/types/appstate.go | 1 - 1 file changed, 1 deletion(-) diff --git a/core/types/appstate.go b/core/types/appstate.go index 8f320f7b0..470fcd70b 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -264,6 +264,5 @@ type Multisig struct { type HaltBlock struct { Height uint64 `json:"height"` - HaltHeight uint64 `json:"halt_height"` CandidateKey Pubkey `json:"candidate_key"` } From c41096dc8336e3f37f34a5ae36e85dffb6cac0ac Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 24 Mar 2020 15:49:40 +0300 Subject: [PATCH 003/426] fix --- core/minter/minter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index 2d9d2557c..23ac001c9 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -44,7 +44,7 @@ const ( DefaultMaxGas = 100000 MinMaxGas = 5000 - VotingPowerConsensus = 2 / 3 + VotingPowerConsensus = 2. / 3. ) var ( From ed967e41d672fa5accd03c996c4c2670f9afe426 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Tue, 24 Mar 2020 15:53:34 +0300 Subject: [PATCH 004/426] Small refactor --- core/minter/minter.go | 2 +- core/state/halts/halts.go | 96 ++++++++++++------------- core/state/halts/model.go | 4 +- core/transaction/set_halt_block_test.go | 4 +- 4 files changed, 53 insertions(+), 53 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index 23ac001c9..a1e3ddfc7 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -179,7 +179,7 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res } for _, halt := range halts.List { - if halt.CandidateKey == val.PubKey { + if halt.Pubkey == val.PubKey { totalVotingPower.Add(totalVotingPower, val.GetTotalBipStake()) } } diff --git a/core/state/halts/halts.go b/core/state/halts/halts.go index 4ef1ef89b..7c32acf37 100644 --- a/core/state/halts/halts.go +++ b/core/state/halts/halts.go @@ -36,14 +36,14 @@ func NewHalts(stateBus *bus.Bus, iavl tree.Tree) (*HaltBlocks, error) { return halts, nil } -func (f *HaltBlocks) Commit() error { - dirty := f.getOrderedDirty() +func (hb *HaltBlocks) Commit() error { + dirty := hb.getOrderedDirty() for _, height := range dirty { - ff := f.getFromMap(height) + ff := hb.getFromMap(height) - f.lock.Lock() - delete(f.dirty, height) - f.lock.Unlock() + hb.lock.Lock() + delete(hb.dirty, height) + hb.lock.Unlock() data, err := rlp.EncodeToBytes(ff) if err != nil { @@ -51,59 +51,59 @@ func (f *HaltBlocks) Commit() error { } path := getPath(height) - f.iavl.Set(path, data) + hb.iavl.Set(path, data) } return nil } -func (f *HaltBlocks) GetHaltBlocks(height uint64) *Model { - return f.get(height) +func (hb *HaltBlocks) GetHaltBlocks(height uint64) *Model { + return hb.get(height) } -func (f *HaltBlocks) GetOrNew(height uint64) *Model { - ff := f.get(height) - if ff == nil { - ff = &Model{ +func (hb *HaltBlocks) GetOrNew(height uint64) *Model { + haltBlock := hb.get(height) + if haltBlock == nil { + haltBlock = &Model{ height: height, - markDirty: f.markDirty, + markDirty: hb.markDirty, } - f.setToMap(height, ff) + hb.setToMap(height, haltBlock) } - return ff + return haltBlock } -func (f *HaltBlocks) get(height uint64) *Model { - if ff := f.getFromMap(height); ff != nil { - return ff +func (hb *HaltBlocks) get(height uint64) *Model { + if haltBlock := hb.getFromMap(height); haltBlock != nil { + return haltBlock } - _, enc := f.iavl.Get(getPath(height)) + _, enc := hb.iavl.Get(getPath(height)) if len(enc) == 0 { return nil } - ff := &Model{} - if err := rlp.DecodeBytes(enc, ff); err != nil { + haltBlock := &Model{} + if err := rlp.DecodeBytes(enc, haltBlock); err != nil { panic(fmt.Sprintf("failed to decode halt blocks at height %d: %s", height, err)) } - ff.height = height - ff.markDirty = f.markDirty + haltBlock.height = height + haltBlock.markDirty = hb.markDirty - f.setToMap(height, ff) + hb.setToMap(height, haltBlock) - return ff + return haltBlock } -func (f *HaltBlocks) markDirty(height uint64) { - f.dirty[height] = struct{}{} +func (hb *HaltBlocks) markDirty(height uint64) { + hb.dirty[height] = struct{}{} } -func (f *HaltBlocks) getOrderedDirty() []uint64 { - keys := make([]uint64, 0, len(f.dirty)) - for k := range f.dirty { +func (hb *HaltBlocks) getOrderedDirty() []uint64 { + keys := make([]uint64, 0, len(hb.dirty)) + for k := range hb.dirty { keys = append(keys, k) } @@ -114,22 +114,22 @@ func (f *HaltBlocks) getOrderedDirty() []uint64 { return keys } -func (f *HaltBlocks) AddHaltBlock(height uint64, pubkey types.Pubkey) { - f.GetOrNew(height).addHaltBlock(pubkey) +func (hb *HaltBlocks) AddHaltBlock(height uint64, pubkey types.Pubkey) { + hb.GetOrNew(height).addHaltBlock(pubkey) } -func (f *HaltBlocks) Delete(height uint64) { - ff := f.get(height) - if ff == nil { +func (hb *HaltBlocks) Delete(height uint64) { + haltBlock := hb.get(height) + if haltBlock == nil { return } - ff.delete() + haltBlock.delete() } -func (f *HaltBlocks) Export(state *types.AppState, height uint64) { +func (hb *HaltBlocks) Export(state *types.AppState, height uint64) { for i := height; i <= height; i++ { - halts := f.get(i) + halts := hb.get(i) if halts == nil { continue } @@ -137,24 +137,24 @@ func (f *HaltBlocks) Export(state *types.AppState, height uint64) { for _, haltBlock := range halts.List { state.HaltBlocks = append(state.HaltBlocks, types.HaltBlock{ Height: i, - CandidateKey: haltBlock.CandidateKey, + CandidateKey: haltBlock.Pubkey, }) } } } -func (f *HaltBlocks) getFromMap(height uint64) *Model { - f.lock.RLock() - defer f.lock.RUnlock() +func (hb *HaltBlocks) getFromMap(height uint64) *Model { + hb.lock.RLock() + defer hb.lock.RUnlock() - return f.list[height] + return hb.list[height] } -func (f *HaltBlocks) setToMap(height uint64, model *Model) { - f.lock.Lock() - defer f.lock.Unlock() +func (hb *HaltBlocks) setToMap(height uint64, model *Model) { + hb.lock.Lock() + defer hb.lock.Unlock() - f.list[height] = model + hb.list[height] = model } func getPath(height uint64) []byte { diff --git a/core/state/halts/model.go b/core/state/halts/model.go index 07e0a31ec..932ff6b4e 100644 --- a/core/state/halts/model.go +++ b/core/state/halts/model.go @@ -5,7 +5,7 @@ import ( ) type Item struct { - CandidateKey types.Pubkey + Pubkey types.Pubkey } type Model struct { @@ -23,7 +23,7 @@ func (m *Model) delete() { func (m *Model) addHaltBlock(pubkey types.Pubkey) { m.List = append(m.List, Item{ - CandidateKey: pubkey, + Pubkey: pubkey, }) m.markDirty(m.height) } diff --git a/core/transaction/set_halt_block_test.go b/core/transaction/set_halt_block_test.go index 3fadad944..94d8b7f36 100644 --- a/core/transaction/set_halt_block_test.go +++ b/core/transaction/set_halt_block_test.go @@ -78,7 +78,7 @@ func TestSetHaltBlockTx(t *testing.T) { } haltBlock := haltBlocks[0] - if haltBlock.CandidateKey != pubkey { - t.Fatalf("Wront halt block pubkey. Expected pubkey: %s, got %s", pubkey, haltBlock.CandidateKey.String()+"asd") + if haltBlock.Pubkey != pubkey { + t.Fatalf("Wront halt block pubkey. Expected pubkey: %s, got %s", pubkey, haltBlock.Pubkey.String()+"asd") } } From 85e768b0fdb5999dbfaf0e543ed08e9fcbaeb947 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 24 Mar 2020 15:59:55 +0300 Subject: [PATCH 005/426] commit halts --- core/state/state.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/state/state.go b/core/state/state.go index 3d24417c5..adebaaac4 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -138,6 +138,10 @@ func (s *State) Commit() ([]byte, error) { return nil, err } + if err := s.Halts.Commit(); err != nil { + return nil, err + } + hash, version, err := s.tree.SaveVersion() if s.keepLastStates < version-1 { From b59c97dc8420d25d715cbddc5bc0080b9fe36b2b Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 25 Mar 2020 11:42:05 +0300 Subject: [PATCH 006/426] add test for app stopping by halt blocks --- core/minter/minter.go | 75 ++++++++++++++++++++++---------------- core/minter/minter_test.go | 39 ++++++++++++++++++++ 2 files changed, 82 insertions(+), 32 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index a1e3ddfc7..b3f5f9532 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -167,38 +167,8 @@ func (app *Blockchain) InitChain(req abciTypes.RequestInitChain) abciTypes.Respo func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.ResponseBeginBlock { height := uint64(req.Header.Height) - halts := app.stateDeliver.Halts.GetHaltBlocks(height) - if halts != nil { - // calculate total power of validators - validators := app.stateDeliver.Validators.GetValidators() - totalPower, totalVotingPower := big.NewInt(0), big.NewInt(0) - for _, val := range validators { - // skip if candidate is not present - if val.IsToDrop() || app.validatorsStatuses[val.GetAddress()] != ValidatorPresent { - continue - } - - for _, halt := range halts.List { - if halt.Pubkey == val.PubKey { - totalVotingPower.Add(totalVotingPower, val.GetTotalBipStake()) - } - } - - totalPower.Add(totalPower, val.GetTotalBipStake()) - } - - if totalPower.Cmp(types.Big0) == 0 { - totalPower = big.NewInt(1) - } - - votingResult := new(big.Float).Quo( - new(big.Float).SetInt(totalVotingPower), - new(big.Float).SetInt(totalPower), - ) - - if votingResult.Cmp(big.NewFloat(VotingPowerConsensus)) == 1 { - panic(fmt.Sprintf("Application halted at height %d", height)) - } + if app.isApplicationHalted(height) { + panic(fmt.Sprintf("Application halted at height %d", height)) } app.StatisticData().SetStartBlock(height, time.Now(), req.Header.Time) @@ -272,6 +242,9 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res app.stateDeliver.FrozenFunds.Delete(frozenFunds.Height()) } + // delete halts from db + app.stateDeliver.Halts.Delete(height) + return abciTypes.ResponseBeginBlock{} } @@ -670,3 +643,41 @@ func getDbOpts(memLimit int) *opt.Options { Filter: filter.NewBloomFilter(10), } } + +func (app *Blockchain) isApplicationHalted(height uint64) bool { + halts := app.stateDeliver.Halts.GetHaltBlocks(height) + if halts != nil { + // calculate total power of validators + vals := app.stateDeliver.Validators.GetValidators() + totalPower, totalVotingPower := big.NewInt(0), big.NewInt(0) + for _, val := range vals { + // skip if candidate is not present + if val.IsToDrop() || app.validatorsStatuses[val.GetAddress()] != ValidatorPresent { + continue + } + + for _, halt := range halts.List { + if halt.Pubkey == val.PubKey { + totalVotingPower.Add(totalVotingPower, val.GetTotalBipStake()) + } + } + + totalPower.Add(totalPower, val.GetTotalBipStake()) + } + + if totalPower.Cmp(types.Big0) == 0 { + totalPower = big.NewInt(1) + } + + votingResult := new(big.Float).Quo( + new(big.Float).SetInt(totalVotingPower), + new(big.Float).SetInt(totalPower), + ) + + if votingResult.Cmp(big.NewFloat(VotingPowerConsensus)) == 1 { + return true + } + } + + return false +} diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index 880e214fa..90a5930b9 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -29,6 +29,7 @@ import ( _ "github.com/tendermint/tendermint/types" types2 "github.com/tendermint/tendermint/types" "math/big" + "math/rand" "os" "path/filepath" "sync" @@ -383,6 +384,44 @@ FORLOOP2: } } +func TestStopNetworkByHaltBlocks(t *testing.T) { + haltHeight := uint64(5) + + v1Pubkey := [32]byte{} + v2Pubkey := [32]byte{} + v3Pubkey := [32]byte{} + + rand.Read(v1Pubkey[:]) + rand.Read(v2Pubkey[:]) + rand.Read(v3Pubkey[:]) + + app.stateDeliver.Validators.Create(v1Pubkey, helpers.BipToPip(big.NewInt(3))) + app.stateDeliver.Validators.Create(v2Pubkey, helpers.BipToPip(big.NewInt(5))) + app.stateDeliver.Validators.Create(v3Pubkey, helpers.BipToPip(big.NewInt(3))) + + v1Address := app.stateDeliver.Validators.GetValidators()[1].GetAddress() + v2Address := app.stateDeliver.Validators.GetValidators()[2].GetAddress() + v3Address := app.stateDeliver.Validators.GetValidators()[3].GetAddress() + + app.validatorsStatuses = map[types.TmAddress]int8{} + app.validatorsStatuses[v1Address] = ValidatorPresent + app.validatorsStatuses[v2Address] = ValidatorPresent + app.validatorsStatuses[v3Address] = ValidatorPresent + + app.stateDeliver.Halts.AddHaltBlock(haltHeight, v1Pubkey) + app.stateDeliver.Halts.AddHaltBlock(haltHeight, v3Pubkey) + if app.isApplicationHalted(haltHeight) { + t.Fatalf("Application halted at height %d", haltHeight) + } + + haltHeight++ + app.stateDeliver.Halts.AddHaltBlock(haltHeight, v1Pubkey) + app.stateDeliver.Halts.AddHaltBlock(haltHeight, v2Pubkey) + if !app.isApplicationHalted(haltHeight) { + t.Fatalf("Application not halted at height %d", haltHeight) + } +} + func getGenesis() (*types2.GenesisDoc, error) { appHash := [32]byte{} From 97e5738d2739487ae6977ed46bad0e98a3c3098e Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 25 Mar 2020 12:38:33 +0300 Subject: [PATCH 007/426] enable halts on upgrade block4 --- core/minter/minter.go | 8 +++++--- core/state/candidates_test.go | 2 +- core/transaction/set_halt_block.go | 8 ++++++++ core/transaction/set_halt_block_test.go | 12 +++++++++--- upgrades/blocks.go | 3 ++- upgrades/grace.go | 1 + 6 files changed, 26 insertions(+), 8 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index b3f5f9532..6174adec9 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -167,7 +167,7 @@ func (app *Blockchain) InitChain(req abciTypes.RequestInitChain) abciTypes.Respo func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.ResponseBeginBlock { height := uint64(req.Header.Height) - if app.isApplicationHalted(height) { + if height >= upgrades.UpgradeBlock4 && app.isApplicationHalted(height) { panic(fmt.Sprintf("Application halted at height %d", height)) } @@ -242,8 +242,10 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res app.stateDeliver.FrozenFunds.Delete(frozenFunds.Height()) } - // delete halts from db - app.stateDeliver.Halts.Delete(height) + if height >= upgrades.UpgradeBlock4 { + // delete halts from db + app.stateDeliver.Halts.Delete(height) + } return abciTypes.ResponseBeginBlock{} } diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index 2e9556652..7b7b90a05 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -13,7 +13,7 @@ import ( "testing" ) -const height = upgrades.UpgradeBlock3 +const height = upgrades.UpgradeBlock4 func TestSimpleDelegate(t *testing.T) { st := getState() diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index 88d70d1ec..72d7ef6ca 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -10,6 +10,7 @@ import ( "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/MinterTeam/minter-go-node/hexutil" + "github.com/MinterTeam/minter-go-node/upgrades" "github.com/tendermint/tendermint/libs/kv" "math/big" "strconv" @@ -62,6 +63,13 @@ func (data SetHaltBlockData) Gas() int64 { } func (data SetHaltBlockData) Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response { + if currentBlock < upgrades.UpgradeBlock4 { + return Response{ + Code: code.DecodeError, + Log: fmt.Sprint("Unknown transaction type"), + } + } + sender, _ := tx.Sender() response := data.BasicCheck(tx, context) diff --git a/core/transaction/set_halt_block_test.go b/core/transaction/set_halt_block_test.go index 94d8b7f36..f60cbf6d0 100644 --- a/core/transaction/set_halt_block_test.go +++ b/core/transaction/set_halt_block_test.go @@ -1,10 +1,13 @@ package transaction import ( + "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/rlp" + "github.com/MinterTeam/minter-go-node/upgrades" + db "github.com/tendermint/tm-db" "math/big" "math/rand" "sync" @@ -12,9 +15,12 @@ import ( ) func TestSetHaltBlockTx(t *testing.T) { - cState := getState() + cState, err := state.NewState(upgrades.UpgradeBlock4, db.NewMemDB(), nil, 1, 1) + if err != nil { + t.Fatalf("Cannot load state. Error %s", err) + } - haltHeight := uint64(100) + haltHeight := upgrades.UpgradeBlock4 + uint64(100) privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoin() @@ -56,7 +62,7 @@ func TestSetHaltBlockTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, false, encodedTx, big.NewInt(0), upgrades.UpgradeBlock4, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) } diff --git a/upgrades/blocks.go b/upgrades/blocks.go index 59f410594..b76b7b56e 100644 --- a/upgrades/blocks.go +++ b/upgrades/blocks.go @@ -3,9 +3,10 @@ package upgrades const UpgradeBlock1 = 5000 const UpgradeBlock2 = 38519 const UpgradeBlock3 = 109000 +const UpgradeBlock4 = 500000 // TODO: fix this value func IsUpgradeBlock(height uint64) bool { - upgradeBlocks := []uint64{UpgradeBlock1, UpgradeBlock2, UpgradeBlock3} + upgradeBlocks := []uint64{UpgradeBlock1, UpgradeBlock2, UpgradeBlock3, UpgradeBlock4} for _, block := range upgradeBlocks { if height == block { diff --git a/upgrades/grace.go b/upgrades/grace.go index 869fa4bc0..e350ab55f 100644 --- a/upgrades/grace.go +++ b/upgrades/grace.go @@ -5,6 +5,7 @@ var gracePeriods = []*gracePeriod{ NewGracePeriod(UpgradeBlock1, UpgradeBlock1+120), NewGracePeriod(UpgradeBlock2, UpgradeBlock2+120), NewGracePeriod(UpgradeBlock3, UpgradeBlock3+120), + NewGracePeriod(UpgradeBlock4, UpgradeBlock4+120), } type gracePeriod struct { From 614e3e3c7efb099a6cf473398f495c3b9a119eee Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 25 Mar 2020 12:40:00 +0300 Subject: [PATCH 008/426] fix log --- core/transaction/set_halt_block.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index 72d7ef6ca..6acc89836 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -66,7 +66,7 @@ func (data SetHaltBlockData) Run(tx *Transaction, context *state.State, isCheck if currentBlock < upgrades.UpgradeBlock4 { return Response{ Code: code.DecodeError, - Log: fmt.Sprint("Unknown transaction type"), + Log: "Unknown transaction type", } } From 73c50280a39524a46dfcf9c26558738065e1fa2d Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 25 Mar 2020 12:45:40 +0300 Subject: [PATCH 009/426] fix SetHaltBlock tx type --- core/transaction/transaction.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index f1e70dd24..b58431640 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -33,7 +33,7 @@ const ( TypeCreateMultisig TxType = 0x0C TypeMultisend TxType = 0x0D TypeEditCandidate TxType = 0x0E - TypeSetHaltBlock TxType = 0x10 + TypeSetHaltBlock TxType = 0x0F SigTypeSingle SigType = 0x01 SigTypeMulti SigType = 0x02 From 6d0c7401654b20bad071ed1734983c0823047dc8 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 25 Mar 2020 12:51:10 +0300 Subject: [PATCH 010/426] hardcoded app stop --- core/minter/minter.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index 6174adec9..53f558ac8 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -167,7 +167,7 @@ func (app *Blockchain) InitChain(req abciTypes.RequestInitChain) abciTypes.Respo func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.ResponseBeginBlock { height := uint64(req.Header.Height) - if height >= upgrades.UpgradeBlock4 && app.isApplicationHalted(height) { + if app.isApplicationHalted(height) { panic(fmt.Sprintf("Application halted at height %d", height)) } @@ -647,6 +647,14 @@ func getDbOpts(memLimit int) *opt.Options { } func (app *Blockchain) isApplicationHalted(height uint64) bool { + if app.haltHeight > 0 && height >= app.haltHeight { + return true + } + + if height < upgrades.UpgradeBlock4 { + return false + } + halts := app.stateDeliver.Halts.GetHaltBlocks(height) if halts != nil { // calculate total power of validators From c91ea579ca0b58e24118e736da0a9bbd35f9d666 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 25 Mar 2020 13:12:21 +0300 Subject: [PATCH 011/426] fix TestStopNetworkByHaltBlocks --- core/minter/minter_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index 90a5930b9..4af43627c 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -17,6 +17,7 @@ import ( "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/log" "github.com/MinterTeam/minter-go-node/rlp" + "github.com/MinterTeam/minter-go-node/upgrades" "github.com/tendermint/go-amino" tmConfig "github.com/tendermint/tendermint/config" log2 "github.com/tendermint/tendermint/libs/log" @@ -385,7 +386,7 @@ FORLOOP2: } func TestStopNetworkByHaltBlocks(t *testing.T) { - haltHeight := uint64(5) + haltHeight := upgrades.UpgradeBlock4 + uint64(5) v1Pubkey := [32]byte{} v2Pubkey := [32]byte{} From 3c278fcdcbde80f3e5e1971341c72f10428a33db Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 25 Mar 2020 13:29:45 +0300 Subject: [PATCH 012/426] test SetHaltBlock to candidate ownership, halt height --- core/transaction/set_halt_block_test.go | 122 ++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/core/transaction/set_halt_block_test.go b/core/transaction/set_halt_block_test.go index f60cbf6d0..90b53a624 100644 --- a/core/transaction/set_halt_block_test.go +++ b/core/transaction/set_halt_block_test.go @@ -1,6 +1,7 @@ package transaction import ( + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" @@ -88,3 +89,124 @@ func TestSetHaltBlockTx(t *testing.T) { t.Fatalf("Wront halt block pubkey. Expected pubkey: %s, got %s", pubkey, haltBlock.Pubkey.String()+"asd") } } + +func TestSetHaltBlockTxWithWrongHeight(t *testing.T) { + currentHeight := uint64(upgrades.UpgradeBlock4 + 5) + cState, err := state.NewState(currentHeight, db.NewMemDB(), nil, 1, 1) + if err != nil { + t.Fatalf("Cannot load state. Error %s", err) + } + + haltHeight := currentHeight - 1 + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoin() + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + cState.Candidates.Create(addr, addr, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1))) + + data := SetHaltBlockData{ + PubKey: pubkey, + Height: haltHeight, + } + + encodedData, err := rlp.EncodeToBytes(data) + + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSetHaltBlock, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, false, encodedTx, big.NewInt(0), currentHeight, &sync.Map{}, 0) + if response.Code != code.WrongHaltHeight { + t.Fatalf("Response code is not %d", code.WrongHaltHeight) + } + + halts := cState.Halts.GetHaltBlocks(haltHeight) + if halts != nil { + t.Fatalf("Halts found at height: %d", haltHeight) + } +} + +func TestSetHaltBlockTxWithWrongOwnership(t *testing.T) { + currentHeight := uint64(upgrades.UpgradeBlock4 + 5) + cState, err := state.NewState(currentHeight, db.NewMemDB(), nil, 1, 1) + if err != nil { + t.Fatalf("Cannot load state. Error %s", err) + } + + haltHeight := currentHeight + 1 + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoin() + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + cState.Candidates.Create(addr, addr, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1))) + + data := SetHaltBlockData{ + PubKey: pubkey, + Height: haltHeight, + } + + encodedData, err := rlp.EncodeToBytes(data) + + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSetHaltBlock, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + privateKey2, _ := crypto.GenerateKey() + if err := tx.Sign(privateKey2); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, false, encodedTx, big.NewInt(0), currentHeight, &sync.Map{}, 0) + if response.Code != code.IsNotOwnerOfCandidate { + t.Fatalf("Response code is not %d", code.IsNotOwnerOfCandidate) + } + + halts := cState.Halts.GetHaltBlocks(haltHeight) + if halts != nil { + t.Fatalf("Halts found at height: %d", haltHeight) + } +} From e0ed92b2ec2ea60f2854d6737f0d78614202f0b2 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 31 Mar 2020 19:07:55 +0300 Subject: [PATCH 013/426] refactor --- core/state/halts/halts.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/state/halts/halts.go b/core/state/halts/halts.go index 7c32acf37..64bb0f224 100644 --- a/core/state/halts/halts.go +++ b/core/state/halts/halts.go @@ -39,13 +39,13 @@ func NewHalts(stateBus *bus.Bus, iavl tree.Tree) (*HaltBlocks, error) { func (hb *HaltBlocks) Commit() error { dirty := hb.getOrderedDirty() for _, height := range dirty { - ff := hb.getFromMap(height) + haltBlock := hb.getFromMap(height) hb.lock.Lock() delete(hb.dirty, height) hb.lock.Unlock() - data, err := rlp.EncodeToBytes(ff) + data, err := rlp.EncodeToBytes(haltBlock) if err != nil { return fmt.Errorf("can't encode object at %d: %v", height, err) } From 30d9c2217bb354b6dc1bddf5b3ede507f7ca47fa Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 1 Apr 2020 13:26:51 +0300 Subject: [PATCH 014/426] update api v2, add /halts?height=_ --- api/v2/service/block.go | 11 ++++++----- api/v2/service/events.go | 3 ++- api/v2/service/halts.go | 30 ++++++++++++++++++++++++++++++ api/v2/service/service.go | 4 ++-- api/v2/service/validators.go | 2 +- go.mod | 8 ++++---- go.sum | 14 ++++++++++++++ 7 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 api/v2/service/halts.go diff --git a/api/v2/service/block.go b/api/v2/service/block.go index a443e24cd..845a27d5e 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -17,17 +17,18 @@ import ( ) func (s *Service) Block(_ context.Context, req *pb.BlockRequest) (*pb.BlockResponse, error) { - block, err := s.client.Block(&req.Height) + height := int64(req.Height) + block, err := s.client.Block(&height) if err != nil { return new(pb.BlockResponse), status.Error(codes.NotFound, "Block not found") } - blockResults, err := s.client.BlockResults(&req.Height) + blockResults, err := s.client.BlockResults(&height) if err != nil { return new(pb.BlockResponse), status.Error(codes.NotFound, "Block results not found") } - valHeight := req.Height - 1 + valHeight := height - 1 if valHeight < 1 { valHeight = 1 } @@ -76,7 +77,7 @@ func (s *Service) Block(_ context.Context, req *pb.BlockRequest) (*pb.BlockRespo var validators []*pb.BlockResponse_Validator var proposer string - if req.Height > 1 { + if height > 1 { p, err := getBlockProposer(block, totalValidators) if err != nil { return new(pb.BlockResponse), status.Error(codes.FailedPrecondition, err.Error()) @@ -119,7 +120,7 @@ func (s *Service) Block(_ context.Context, req *pb.BlockRequest) (*pb.BlockRespo Time: block.Block.Time.Format(time.RFC3339Nano), TransactionsCount: fmt.Sprintf("%d", len(block.Block.Txs)), Transactions: txs, - BlockReward: rewards.GetRewardForBlock(uint64(req.Height)).String(), + BlockReward: rewards.GetRewardForBlock(uint64(height)).String(), Size: fmt.Sprintf("%d", len(s.cdc.MustMarshalBinaryLengthPrefixed(block))), Proposer: proposer, Validators: validators, diff --git a/api/v2/service/events.go b/api/v2/service/events.go index eccce3bf2..88151587f 100644 --- a/api/v2/service/events.go +++ b/api/v2/service/events.go @@ -11,7 +11,8 @@ import ( ) func (s *Service) Events(_ context.Context, req *pb.EventsRequest) (*pb.EventsResponse, error) { - events := s.blockchain.GetEventsDB().LoadEvents(req.Height) + height := uint32(req.Height) + events := s.blockchain.GetEventsDB().LoadEvents(height) resultEvents := make([]*pb.EventsResponse_Event, 0, len(events)) for _, event := range events { byteData, err := json.Marshal(event) diff --git a/api/v2/service/halts.go b/api/v2/service/halts.go new file mode 100644 index 000000000..2944b9b9d --- /dev/null +++ b/api/v2/service/halts.go @@ -0,0 +1,30 @@ +package service + +import ( + "context" + pb "github.com/MinterTeam/node-grpc-gateway/api_pb" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (s *Service) Halts(_ context.Context, req *pb.HaltsRequest) (*pb.HaltsResponse, error) { + cState, err := s.blockchain.GetStateForHeight(req.Height) + if err != nil { + return new(pb.HaltsResponse), status.Error(codes.NotFound, err.Error()) + } + + blocks := cState.Halts.GetHaltBlocks(req.Height) + + if blocks == nil { + return &pb.HaltsResponse{}, nil + } + + var votes []string + for _, vote := range blocks.List { + votes = append(votes, vote.Pubkey.String()) + } + + return &pb.HaltsResponse{ + Votes: votes, + }, nil +} diff --git a/api/v2/service/service.go b/api/v2/service/service.go index 360f408b4..0123b138b 100644 --- a/api/v2/service/service.go +++ b/api/v2/service/service.go @@ -26,9 +26,9 @@ func NewService(cdc *amino.Codec, blockchain *minter.Blockchain, client *rpc.Loc return &Service{cdc: cdc, blockchain: blockchain, client: client, minterCfg: minterCfg, version: version, tmNode: node} } -func (s *Service) getStateForHeight(height int32) (*state.State, error) { +func (s *Service) getStateForHeight(height uint64) (*state.State, error) { if height > 0 { - cState, err := s.blockchain.GetStateForHeight(uint64(height)) + cState, err := s.blockchain.GetStateForHeight(height) if err != nil { return nil, err } diff --git a/api/v2/service/validators.go b/api/v2/service/validators.go index 57bbbfbcd..d0d75e19c 100644 --- a/api/v2/service/validators.go +++ b/api/v2/service/validators.go @@ -10,7 +10,7 @@ import ( ) func (s *Service) Validators(_ context.Context, req *pb.ValidatorsRequest) (*pb.ValidatorsResponse, error) { - height := req.Height + height := int64(req.Height) if height == 0 { height = int64(s.blockchain.Height()) } diff --git a/go.mod b/go.mod index e2514ec4e..80d6983c9 100644 --- a/go.mod +++ b/go.mod @@ -4,15 +4,15 @@ go 1.13 require ( github.com/MinterTeam/events-db v0.1.6 - github.com/MinterTeam/node-grpc-gateway v1.0.0 + github.com/MinterTeam/node-grpc-gateway v1.1.0 github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 - github.com/golang/protobuf v1.3.4 + github.com/golang/protobuf v1.3.5 github.com/google/uuid v1.1.1 github.com/gorilla/websocket v1.4.1 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 - github.com/grpc-ecosystem/grpc-gateway v1.12.0 + github.com/grpc-ecosystem/grpc-gateway v1.14.3 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.5.1 github.com/rs/cors v1.7.0 @@ -30,6 +30,6 @@ require ( golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 - google.golang.org/grpc v1.27.1 + google.golang.org/grpc v1.28.0 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 ) diff --git a/go.sum b/go.sum index f19af3eb9..deb13abb6 100644 --- a/go.sum +++ b/go.sum @@ -19,6 +19,8 @@ github.com/MinterTeam/minter-node-cli v0.0.0-20191202172005-309e9d40a5a3 h1:2ndN github.com/MinterTeam/minter-node-cli v0.0.0-20191202172005-309e9d40a5a3/go.mod h1:6iFtZjWsvR9ZaXaogfDkIYVSrQAHQBk/tU1L5yKS5/8= github.com/MinterTeam/node-grpc-gateway v1.0.0 h1:E2Vn3wC0kv/zgzA1biC84+M2Y4h0k2etLXzTM6jJyeI= github.com/MinterTeam/node-grpc-gateway v1.0.0/go.mod h1:LJJNHzYkAbWsoWZw3VMgs+NQTnJ3f0YawF2UZxevTOE= +github.com/MinterTeam/node-grpc-gateway v1.1.0 h1:fEkYq1IpmzQTh1gYopUTTdx6AhVeCd2CVJlDebHxgmY= +github.com/MinterTeam/node-grpc-gateway v1.1.0/go.mod h1:WWdGy/bxMgnaTlDWaemx4Z7tc2/4IjPOKdlmC8QRH2M= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= @@ -70,6 +72,7 @@ github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -100,6 +103,7 @@ github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaB github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/etcd-io/bbolt v1.3.2/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/etcd-io/bbolt v1.3.3 h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM= @@ -154,8 +158,11 @@ github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -193,6 +200,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.12.0 h1:SFRyYOyhgiU1kJG/PmbkWP/iSlizvDJEz531dq5kneg= github.com/grpc-ecosystem/grpc-gateway v1.12.0/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= +github.com/grpc-ecosystem/grpc-gateway v1.14.3 h1:OCJlWkOUoTnl0neNGlf4fUm3TmbEtguw7vR+nGtnDjY= +github.com/grpc-ecosystem/grpc-gateway v1.14.3/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f h1:8N8XWLZelZNibkhM1FuF+3Ad3YIbgirjdMiVA0eUkaM= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= @@ -608,6 +617,8 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2El google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c h1:hrpEMCZ2O7DR5gC1n2AJGVhrwiEjOi35+jxtIuZpTMo= google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940 h1:MRHtG0U6SnaUb+s+LhNE1qt1FQ1wlhqr5E4usBKC0uA= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/grpc v1.13.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -625,8 +636,11 @@ google.golang.org/grpc v1.25.0/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= From 08b074be307c61f6465118331ca7e4c53b6d7ee7 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 15 Apr 2020 00:18:28 +0300 Subject: [PATCH 015/426] use keep_ever and keep_recent for store stage --- cmd/minter/cmd/export.go | 2 +- cmd/minter/cmd/node.go | 4 ++-- config/config.go | 9 ++++++--- config/toml.go | 9 ++++++--- core/minter/minter.go | 4 ++-- core/minter/upgrade3_test.go | 2 +- core/state/candidates_test.go | 2 +- core/state/state.go | 8 ++++---- core/state/state_test.go | 2 +- core/transaction/buy_coin_test.go | 2 +- tree/tree.go | 5 +++-- 11 files changed, 28 insertions(+), 21 deletions(-) diff --git a/cmd/minter/cmd/export.go b/cmd/minter/cmd/export.go index 6d239c961..b05105a9a 100644 --- a/cmd/minter/cmd/export.go +++ b/cmd/minter/cmd/export.go @@ -58,7 +58,7 @@ func export(cmd *cobra.Command, args []string) error { log.Panicf("Cannot load db: %s", err) } - currentState, err := state.NewState(height, ldb, nil, 1, 1) + currentState, err := state.NewState(height, ldb, nil, 1, 1, 0) if err != nil { log.Panicf("Cannot new state at given height: %s", err) } diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index bfa87bf51..312523c2a 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -95,8 +95,8 @@ func runNode(cmd *cobra.Command) error { return err } - if cfg.KeepLastStates < 1 { - panic("keep_last_states field should be greater than 0") + if cfg.StateKeepEver < 1 { + panic("state_keep_ever field should be greater than 0") } app := minter.NewMinterBlockchain(cfg) diff --git a/config/config.go b/config/config.go index b2c775322..8a2fd8ea5 100644 --- a/config/config.go +++ b/config/config.go @@ -235,14 +235,16 @@ type BaseConfig struct { ValidatorMode bool `mapstructure:"validator_mode"` - KeepLastStates int64 `mapstructure:"keep_last_states"` - APISimultaneousRequests int `mapstructure:"api_simultaneous_requests"` LogPath string `mapstructure:"log_path"` StateCacheSize int `mapstructure:"state_cache_size"` + StateKeepEver int64 `mapstructure:"state_keep_ever"` + + StateKeepRecent int64 `mapstructure:"state_keep_recent"` + StateMemAvailable int `mapstructure:"state_mem_available"` HaltHeight int `mapstructure:"halt_height"` @@ -266,8 +268,9 @@ func DefaultBaseConfig() BaseConfig { GRPCListenAddress: "tcp://0.0.0.0:8842", APIv2ListenAddress: "tcp://0.0.0.0:8843", ValidatorMode: false, - KeepLastStates: 120, StateCacheSize: 1000000, + StateKeepEver: 120, + StateKeepRecent: 1200, StateMemAvailable: 1024, APISimultaneousRequests: 100, LogPath: "stdout", diff --git a/config/toml.go b/config/toml.go index 4d2ec5ecd..ae1547c50 100644 --- a/config/toml.go +++ b/config/toml.go @@ -78,12 +78,15 @@ api_v2_listen_addr = "{{ .BaseConfig.APIv2ListenAddress }}" # Sets node to be in validator mode. Disables API, events, history of blocks, indexes, etc. validator_mode = {{ .BaseConfig.ValidatorMode }} -# Sets number of last stated to be saved -keep_last_states = {{ .BaseConfig.KeepLastStates }} - # State cache size state_cache_size = {{ .BaseConfig.StateCacheSize }} +# State keep ever +state_cache_size = {{ .BaseConfig.StateKeepEver }} + +# State keep recent +state_cache_size = {{ .BaseConfig.StateKeepRecent }} + # State memory in MB state_mem_available = {{ .BaseConfig.StateMemAvailable }} diff --git a/core/minter/minter.go b/core/minter/minter.go index 88111abcb..a5c0deb27 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -107,7 +107,7 @@ func NewMinterBlockchain(cfg *config.Config) *Blockchain { } // Set stateDeliver and stateCheck - blockchain.stateDeliver, err = state.NewState(blockchain.height, blockchain.stateDB, blockchain.eventsDB, cfg.KeepLastStates, cfg.StateCacheSize) + blockchain.stateDeliver, err = state.NewState(blockchain.height, blockchain.stateDB, blockchain.eventsDB, cfg.StateCacheSize, cfg.StateKeepEver, cfg.StateKeepRecent) if err != nil { panic(err) } @@ -177,7 +177,7 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res if upgrades.IsUpgradeBlock(height) { var err error - app.stateDeliver, err = state.NewState(app.height, app.stateDB, app.eventsDB, app.cfg.KeepLastStates, app.cfg.StateCacheSize) + app.stateDeliver, err = state.NewState(app.height, app.stateDB, app.eventsDB, app.cfg.StateCacheSize, app.cfg.StateKeepEver, app.cfg.StateKeepRecent) if err != nil { panic(err) } diff --git a/core/minter/upgrade3_test.go b/core/minter/upgrade3_test.go index 8574ac6bb..fda286e01 100644 --- a/core/minter/upgrade3_test.go +++ b/core/minter/upgrade3_test.go @@ -38,7 +38,7 @@ func TestApplyUpgrade3(t *testing.T) { } func getState() *state.State { - s, err := state.NewState(0, db.NewMemDB(), emptyEvents{}, 1, 1) + s, err := state.NewState(0, db.NewMemDB(), emptyEvents{}, 1, 1, 0) if err != nil { panic(err) diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index 2e9556652..91222ee37 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -390,7 +390,7 @@ func TestDelegationAfterUnbond(t *testing.T) { } func getState() *State { - s, err := NewState(0, db.NewMemDB(), emptyEvents{}, 1, 1) + s, err := NewState(0, db.NewMemDB(), emptyEvents{}, 1, 1, 0) if err != nil { panic(err) diff --git a/core/state/state.go b/core/state/state.go index 4c8db5f3c..f0982555b 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -41,14 +41,14 @@ type State struct { lock sync.RWMutex } -func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, keepLastStates int64, cacheSize int) (*State, error) { - iavlTree := tree.NewMutableTree(db, cacheSize) +func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, keepEvery, keepRecent int64) (*State, error) { + iavlTree := tree.NewMutableTree(db, cacheSize, keepEvery, keepRecent) _, err := iavlTree.LoadVersion(int64(height)) if err != nil { return nil, err } - state, err := newStateForTree(iavlTree, events, db, keepLastStates) + state, err := newStateForTree(iavlTree, events, db, keepRecent) if err != nil { return nil, err } @@ -65,7 +65,7 @@ func NewCheckState(state *State) *State { } func NewCheckStateAtHeight(height uint64, db db.DB) (*State, error) { - iavlTree := tree.NewMutableTree(db, 1024) + iavlTree := tree.NewMutableTree(db, 1024, 1, 0) _, err := iavlTree.LazyLoadVersion(int64(height)) if err != nil { return nil, err diff --git a/core/state/state_test.go b/core/state/state_test.go index cc3637c46..6e79377f4 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -15,7 +15,7 @@ import ( func TestStateExport(t *testing.T) { height := uint64(0) - state, err := NewState(height, db.NewMemDB(), emptyEvents{}, 1, 1) + state, err := NewState(height, db.NewMemDB(), emptyEvents{}, 1, 1, 0) if err != nil { log.Panic("Cannot create state") } diff --git a/core/transaction/buy_coin_test.go b/core/transaction/buy_coin_test.go index 6055cef6b..b03e75064 100644 --- a/core/transaction/buy_coin_test.go +++ b/core/transaction/buy_coin_test.go @@ -27,7 +27,7 @@ var ( ) func getState() *state.State { - s, err := state.NewState(0, db.NewMemDB(), nil, 1, 1) + s, err := state.NewState(0, db.NewMemDB(), nil, 1, 1, 0) if err != nil { panic(err) diff --git a/tree/tree.go b/tree/tree.go index 910c48147..bdc6e350b 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -21,11 +21,12 @@ type Tree interface { Iterate(fn func(key []byte, value []byte) bool) (stopped bool) } -func NewMutableTree(db dbm.DB, cacheSize int) *MutableTree { - tree, err := iavl.NewMutableTree(db, cacheSize) +func NewMutableTree(db dbm.DB, cacheSize int, keepEvery, keepRecent int64) *MutableTree { + tree, err := iavl.NewMutableTreeWithOpts(db, dbm.NewMemDB(), cacheSize, iavl.PruningOptions(keepEvery, keepRecent)) if err != nil { panic(err) } + return &MutableTree{ tree: tree, } From 114a0e95c4d629b4767181bae9ea89c24d9fb445 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 15 Apr 2020 00:24:50 +0300 Subject: [PATCH 016/426] optimize, use pointer for arguments, use a buffered channel to process the beginning and end of the block --- core/minter/minter.go | 4 ++-- core/statistics/statistics.go | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index 88111abcb..27ee8194a 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -169,7 +169,7 @@ func (app *Blockchain) InitChain(req abciTypes.RequestInitChain) abciTypes.Respo func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.ResponseBeginBlock { height := uint64(req.Header.Height) - app.StatisticData().PushStartBlock(statistics.StartRequest{Height: int64(height), Now: time.Now(), HeaderTime: req.Header.Time}) + app.StatisticData().PushStartBlock(&statistics.StartRequest{Height: int64(height), Now: time.Now(), HeaderTime: req.Header.Time}) if app.haltHeight > 0 && height >= app.haltHeight { panic(fmt.Sprintf("Application halted at height %d", height)) @@ -380,7 +380,7 @@ func (app *Blockchain) EndBlock(req abciTypes.RequestEndBlock) abciTypes.Respons } defer func() { - app.StatisticData().PushEndBlock(statistics.EndRequest{TimeEnd: time.Now(), Height: int64(app.height)}) + app.StatisticData().PushEndBlock(&statistics.EndRequest{TimeEnd: time.Now(), Height: int64(app.height)}) }() return abciTypes.ResponseEndBlock{ diff --git a/core/statistics/statistics.go b/core/statistics/statistics.go index 3454f6feb..c7f254158 100644 --- a/core/statistics/statistics.go +++ b/core/statistics/statistics.go @@ -77,8 +77,8 @@ type Data struct { headerTimestamp time.Time } BlockEnd blockEnd - cS chan StartRequest - cE chan EndRequest + cS chan *StartRequest + cE chan *EndRequest Speed struct { sync.RWMutex startTime time.Time @@ -170,12 +170,12 @@ func New() *Data { Api: apiResponseTime{responseTime: apiVec}, Peer: peerPing{ping: peerVec}, BlockEnd: blockEnd{HeightProm: height, DurationProm: lastBlockDuration, TimestampProm: timeBlock}, - cS: make(chan StartRequest), - cE: make(chan EndRequest), + cS: make(chan *StartRequest, 120), + cE: make(chan *EndRequest, 120), } } -func (d *Data) PushStartBlock(req StartRequest) { +func (d *Data) PushStartBlock(req *StartRequest) { if d == nil { return } @@ -218,7 +218,7 @@ func (d *Data) handleStartBlocks(ctx context.Context) { } } -func (d *Data) PushEndBlock(req EndRequest) { +func (d *Data) PushEndBlock(req *EndRequest) { if d == nil { return } From 551c230618a85eda6a9a0018ae93bf49fc08c2f8 Mon Sep 17 00:00:00 2001 From: klim0v Date: Sat, 18 Apr 2020 13:18:09 +0300 Subject: [PATCH 017/426] rename fields in template --- config/toml.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/toml.go b/config/toml.go index ae1547c50..b73471fea 100644 --- a/config/toml.go +++ b/config/toml.go @@ -82,10 +82,10 @@ validator_mode = {{ .BaseConfig.ValidatorMode }} state_cache_size = {{ .BaseConfig.StateCacheSize }} # State keep ever -state_cache_size = {{ .BaseConfig.StateKeepEver }} +state_keep_ever = {{ .BaseConfig.StateKeepEver }} # State keep recent -state_cache_size = {{ .BaseConfig.StateKeepRecent }} +state_keep_recent = {{ .BaseConfig.StateKeepRecent }} # State memory in MB state_mem_available = {{ .BaseConfig.StateMemAvailable }} From f6d74d110c6984b7543df6b4457031d6b54e2257 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 21 Apr 2020 14:14:16 +0300 Subject: [PATCH 018/426] remove field KeepLastStates from /status endpoint --- api/status.go | 1 - api/v2/service/status.go | 1 - 2 files changed, 2 deletions(-) diff --git a/api/status.go b/api/status.go index ec7a52b54..94d5f2f51 100644 --- a/api/status.go +++ b/api/status.go @@ -29,7 +29,6 @@ func Status() (*StatusResponse, error) { LatestAppHash: fmt.Sprintf("%X", result.SyncInfo.LatestAppHash), LatestBlockHeight: result.SyncInfo.LatestBlockHeight, LatestBlockTime: result.SyncInfo.LatestBlockTime, - KeepLastStates: minterCfg.BaseConfig.KeepLastStates, TmStatus: result, }, nil } diff --git a/api/v2/service/status.go b/api/v2/service/status.go index 80b452b31..72157e32a 100644 --- a/api/v2/service/status.go +++ b/api/v2/service/status.go @@ -22,7 +22,6 @@ func (s *Service) Status(context.Context, *empty.Empty) (*pb.StatusResponse, err LatestAppHash: fmt.Sprintf("%X", result.SyncInfo.LatestAppHash), LatestBlockHeight: fmt.Sprintf("%d", result.SyncInfo.LatestBlockHeight), LatestBlockTime: result.SyncInfo.LatestBlockTime.Format(time.RFC3339Nano), - KeepLastStates: fmt.Sprintf("%d", s.minterCfg.BaseConfig.KeepLastStates), CatchingUp: result.SyncInfo.CatchingUp, PublicKey: fmt.Sprintf("Mp%x", result.ValidatorInfo.PubKey.Bytes()[5:]), NodeId: string(result.NodeInfo.ID()), From c776ed6b3aa723c740bc93c8ae96e22a770c6ed0 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 22 Apr 2020 16:01:10 +0300 Subject: [PATCH 019/426] remove field KeepLastStates from status console --- cli/service/service.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cli/service/service.go b/cli/service/service.go index e2f34c50d..ac7d986b9 100644 --- a/cli/service/service.go +++ b/cli/service/service.go @@ -119,7 +119,6 @@ func (m *Manager) Status(context.Context, *empty.Empty) (*pb.StatusResponse, err LatestAppHash: fmt.Sprintf("%X", resultStatus.SyncInfo.LatestAppHash), LatestBlockHeight: resultStatus.SyncInfo.LatestBlockHeight, LatestBlockTime: resultStatus.SyncInfo.LatestBlockTime.Format(time.RFC3339), - KeepLastStates: m.cfg.KeepLastStates, TmStatus: &pb.StatusResponse_TmStatus{ NodeInfo: &pb.NodeInfo{ ProtocolVersion: &pb.NodeInfo_ProtocolVersion{ From 3a24e5b1c3c493d3f58a849c102e262ceb933047 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 23 Apr 2020 21:17:36 +0300 Subject: [PATCH 020/426] refactor check and delivery state --- core/minter/minter.go | 2 +- core/state/accounts/accounts.go | 11 +++- core/state/app/app.go | 12 +++- core/state/candidates/candidates.go | 8 ++- core/state/checks/checks.go | 8 ++- core/state/coins/coins.go | 11 +++- core/state/frozenfunds/frozen_funds.go | 8 ++- core/state/state.go | 80 ++++++++++++++++++----- core/state/validators/validators.go | 25 ++++++- core/transaction/buy_coin.go | 56 +++++++++------- core/transaction/executor.go | 16 +++-- core/transaction/sell_all_coin.go | 52 ++++++++------- core/transaction/sell_coin.go | 49 +++++++------- core/transaction/transaction.go | 6 +- tree/tree.go | 90 +++++++++++--------------- 15 files changed, 272 insertions(+), 162 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index a5c0deb27..ddceeefc8 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -63,7 +63,7 @@ type Blockchain struct { appDB *appdb.AppDB eventsDB eventsdb.IEventsDB stateDeliver *state.State - stateCheck *state.State + stateCheck *state.CheckState height uint64 // current Blockchain height rewards *big.Int // Rewards pool validatorsStatuses map[types.TmAddress]int8 diff --git a/core/state/accounts/accounts.go b/core/state/accounts/accounts.go index 57f282257..fca9b01d0 100644 --- a/core/state/accounts/accounts.go +++ b/core/state/accounts/accounts.go @@ -18,17 +18,24 @@ const mainPrefix = byte('a') const coinsPrefix = byte('c') const balancePrefix = byte('b') +type RAccounts interface { + Export(state *types.AppState) + GetAccount(address types.Address) *Model + GetNonce(address types.Address) uint64 + GetBalance(address types.Address, coin types.CoinSymbol) *big.Int +} + type Accounts struct { list map[types.Address]*Model dirty map[types.Address]struct{} - iavl tree.Tree + iavl tree.MTree bus *bus.Bus lock sync.RWMutex } -func NewAccounts(stateBus *bus.Bus, iavl tree.Tree) (*Accounts, error) { +func NewAccounts(stateBus *bus.Bus, iavl tree.MTree) (*Accounts, error) { accounts := &Accounts{iavl: iavl, bus: stateBus, list: map[types.Address]*Model{}, dirty: map[types.Address]struct{}{}} accounts.bus.SetAccounts(NewBus(accounts)) diff --git a/core/state/app/app.go b/core/state/app/app.go index 204095ee7..7668abf5b 100644 --- a/core/state/app/app.go +++ b/core/state/app/app.go @@ -11,15 +11,23 @@ import ( const mainPrefix = 'd' +type RApp interface { + Export(state *types.AppState, height uint64) +} + +func (v *App) Tree() tree.ITree { + return v.iavl +} + type App struct { model *Model isDirty bool bus *bus.Bus - iavl tree.Tree + iavl tree.MTree } -func NewApp(stateBus *bus.Bus, iavl tree.Tree) (*App, error) { +func NewApp(stateBus *bus.Bus, iavl tree.MTree) (*App, error) { app := &App{bus: stateBus, iavl: iavl} app.bus.SetApp(NewBus(app)) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 864be7b8c..08cf3d5fa 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -29,17 +29,21 @@ const ( updatesPrefix = 'u' ) +type RCandidates interface { + Export(state *types.AppState) +} + type Candidates struct { list map[types.Pubkey]*Candidate - iavl tree.Tree + iavl tree.MTree bus *bus.Bus lock sync.RWMutex loaded bool } -func NewCandidates(bus *bus.Bus, iavl tree.Tree) (*Candidates, error) { +func NewCandidates(bus *bus.Bus, iavl tree.MTree) (*Candidates, error) { candidates := &Candidates{iavl: iavl, bus: bus} candidates.bus.SetCandidates(NewBus(candidates)) diff --git a/core/state/checks/checks.go b/core/state/checks/checks.go index c32dc939c..2962fbab4 100644 --- a/core/state/checks/checks.go +++ b/core/state/checks/checks.go @@ -12,15 +12,19 @@ import ( const mainPrefix = byte('t') +type RChecks interface { + Export(state *types.AppState) +} + type Checks struct { usedChecks map[types.Hash]struct{} - iavl tree.Tree + iavl tree.MTree lock sync.RWMutex } -func NewChecks(iavl tree.Tree) (*Checks, error) { +func NewChecks(iavl tree.MTree) (*Checks, error) { return &Checks{iavl: iavl, usedChecks: map[types.Hash]struct{}{}}, nil } diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index 982d490ff..4b033bb7e 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -17,17 +17,24 @@ const ( infoPrefix = byte('i') ) +type RCoins interface { + Export(state *types.AppState) + Exists(symbol types.CoinSymbol) bool + SubReserve(symbol types.CoinSymbol, amount *big.Int) + GetCoin(symbol types.CoinSymbol) *Model +} + type Coins struct { list map[types.CoinSymbol]*Model dirty map[types.CoinSymbol]struct{} bus *bus.Bus - iavl tree.Tree + iavl tree.MTree lock sync.RWMutex } -func NewCoins(stateBus *bus.Bus, iavl tree.Tree) (*Coins, error) { +func NewCoins(stateBus *bus.Bus, iavl tree.MTree) (*Coins, error) { coins := &Coins{bus: stateBus, iavl: iavl, list: map[types.CoinSymbol]*Model{}, dirty: map[types.CoinSymbol]struct{}{}} coins.bus.SetCoins(NewBus(coins)) diff --git a/core/state/frozenfunds/frozen_funds.go b/core/state/frozenfunds/frozen_funds.go index 81b421f09..d1d1cc529 100644 --- a/core/state/frozenfunds/frozen_funds.go +++ b/core/state/frozenfunds/frozen_funds.go @@ -18,17 +18,21 @@ import ( const mainPrefix = byte('f') +type RFrozenFunds interface { + Export(state *types.AppState, height uint64) +} + type FrozenFunds struct { list map[uint64]*Model dirty map[uint64]interface{} bus *bus.Bus - iavl tree.Tree + iavl tree.MTree lock sync.RWMutex } -func NewFrozenFunds(stateBus *bus.Bus, iavl tree.Tree) (*FrozenFunds, error) { +func NewFrozenFunds(stateBus *bus.Bus, iavl tree.MTree) (*FrozenFunds, error) { frozenfunds := &FrozenFunds{bus: stateBus, iavl: iavl, list: map[uint64]*Model{}, dirty: map[uint64]interface{}{}} frozenfunds.bus.SetFrozenFunds(NewBus(frozenfunds)) diff --git a/core/state/state.go b/core/state/state.go index f0982555b..bd434edf5 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -22,6 +22,45 @@ import ( "sync" ) +type Interface interface { + isValue_State() +} + +type CheckState struct { + state *State +} + +func NewCheckState(state *State) *CheckState { + return &CheckState{state: state} +} + +func (cs *CheckState) isValue_State() {} + +func (cs *CheckState) Validators() validators.RValidators { + return cs.state.Validators +} +func (cs *CheckState) App() app.RApp { + return cs.state.App +} +func (cs *CheckState) Candidates() candidates.RCandidates { + return cs.state.Candidates +} +func (cs *CheckState) FrozenFunds() frozenfunds.RFrozenFunds { + return cs.state.FrozenFunds +} +func (cs *CheckState) Accounts() accounts.RAccounts { + return cs.state.Accounts +} +func (cs *CheckState) Coins() coins.RCoins { + return cs.state.Coins +} +func (cs *CheckState) Checks() checks.RChecks { + return cs.state.Checks +} +func (cs *CheckState) Tree() tree.ITree { + return cs.state.Tree() +} + type State struct { App *app.App Validators *validators.Validators @@ -34,13 +73,15 @@ type State struct { db db.DB events eventsdb.IEventsDB - tree tree.Tree + tree tree.MTree keepLastStates int64 bus *bus.Bus lock sync.RWMutex } +func (s *State) isValue_State() {} + func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, keepEvery, keepRecent int64) (*State, error) { iavlTree := tree.NewMutableTree(db, cacheSize, keepEvery, keepRecent) _, err := iavlTree.LoadVersion(int64(height)) @@ -60,18 +101,18 @@ func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, return state, nil } -func NewCheckState(state *State) *State { - return state -} - -func NewCheckStateAtHeight(height uint64, db db.DB) (*State, error) { +func NewCheckStateAtHeight(height uint64, db db.DB) (*CheckState, error) { iavlTree := tree.NewMutableTree(db, 1024, 1, 0) _, err := iavlTree.LazyLoadVersion(int64(height)) if err != nil { return nil, err } - return newStateForTree(iavlTree.GetImmutable(), nil, nil, 0) + return newCheckStateForTree(iavlTree, nil, nil, 0) +} + +func (s *State) Tree() tree.MTree { + return s.tree } func (s *State) Lock() { @@ -211,18 +252,27 @@ func (s *State) Export(height uint64) types.AppState { } appState := new(types.AppState) - state.App.Export(appState, height) - state.Validators.Export(appState) - state.Candidates.Export(appState) - state.FrozenFunds.Export(appState, height) - state.Accounts.Export(appState) - state.Coins.Export(appState) - state.Checks.Export(appState) + state.App().Export(appState, height) + state.Validators().Export(appState) + state.Candidates().Export(appState) + state.FrozenFunds().Export(appState, height) + state.Accounts().Export(appState) + state.Coins().Export(appState) + state.Checks().Export(appState) return *appState } -func newStateForTree(iavlTree tree.Tree, events eventsdb.IEventsDB, db db.DB, keepLastStates int64) (*State, error) { +func newCheckStateForTree(iavlTree tree.MTree, events eventsdb.IEventsDB, db db.DB, keepLastStates int64) (*CheckState, error) { + stateForTree, err := newStateForTree(iavlTree, events, db, keepLastStates) + if err != nil { + return nil, err + } + + return NewCheckState(stateForTree), nil +} + +func newStateForTree(iavlTree tree.MTree, events eventsdb.IEventsDB, db db.DB, keepLastStates int64) (*State, error) { stateBus := bus.NewBus() stateBus.SetEvents(events) diff --git a/core/state/validators/validators.go b/core/state/validators/validators.go index 001d5272b..8ccdf74ce 100644 --- a/core/state/validators/validators.go +++ b/core/state/validators/validators.go @@ -29,11 +29,32 @@ type Validators struct { list []*Validator loaded bool - iavl tree.Tree + iavl tree.MTree bus *bus.Bus } -func NewValidators(bus *bus.Bus, iavl tree.Tree) (*Validators, error) { +type RValidators interface { + GetValidators() []*Validator + Export(state *types.AppState) +} + +func NewReadValidators(bus *bus.Bus, iavl tree.MTree) (RValidators, error) { + validators := &Validators{iavl: iavl, bus: bus} + + return validators, nil +} + +type RWValidators interface { + RValidators + Commit() error + SetValidatorPresent(height uint64, address types.TmAddress) + SetValidatorAbsent(height uint64, address types.TmAddress) + PunishByzantineValidator(tmAddress [20]byte) + PayRewards(height uint64) + SetNewValidators(candidates []candidates.Candidate) +} + +func NewValidators(bus *bus.Bus, iavl tree.MTree) (*Validators, error) { validators := &Validators{iavl: iavl, bus: bus} return validators, nil diff --git a/core/transaction/buy_coin.go b/core/transaction/buy_coin.go index 226562108..eeb1e22d2 100644 --- a/core/transaction/buy_coin.go +++ b/core/transaction/buy_coin.go @@ -43,7 +43,7 @@ func (data BuyCoinData) Gas() int64 { return commissions.ConvertTx } -func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.State) (TotalSpends, +func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { total := TotalSpends{} var conversions []Conversion @@ -52,7 +52,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.State) (Total commissionIncluded := false if !data.CoinToBuy.IsBaseCoin() { - coin := context.Coins.GetCoin(data.CoinToBuy) + coin := context.Coins().GetCoin(data.CoinToBuy) if errResp := CheckForCoinSupplyOverflow(coin.Volume(), data.ValueToBuy, coin.MaxSupply()); errResp != nil { return nil, nil, nil, errResp @@ -63,7 +63,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.State) (Total switch { case data.CoinToSell.IsBaseCoin(): - coin := context.Coins.GetCoin(data.CoinToBuy) + coin := context.Coins().GetCoin(data.CoinToBuy) value = formula.CalculatePurchaseAmount(coin.Volume(), coin.Reserve(), coin.Crr(), data.ValueToBuy) if value.Cmp(data.MaximumValueToSell) == 1 { @@ -130,7 +130,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.State) (Total valueToBuy.Add(valueToBuy, commissionInBaseCoin) } - coin := context.Coins.GetCoin(data.CoinToSell) + coin := context.Coins().GetCoin(data.CoinToSell) value = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), valueToBuy) if value.Cmp(data.MaximumValueToSell) == 1 { @@ -156,8 +156,8 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.State) (Total default: valueToBuy := big.NewInt(0).Set(data.ValueToBuy) - coinFrom := context.Coins.GetCoin(data.CoinToSell) - coinTo := context.Coins.GetCoin(data.CoinToBuy) + coinFrom := context.Coins().GetCoin(data.CoinToSell) + coinTo := context.Coins().GetCoin(data.CoinToBuy) baseCoinNeeded := formula.CalculatePurchaseAmount(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), valueToBuy) if coinFrom.Reserve().Cmp(baseCoinNeeded) < 0 { @@ -289,7 +289,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.State) (Total commission := big.NewInt(0).Set(commissionInBaseCoin) if !tx.GasCoin.IsBaseCoin() { - coin := context.Coins.GetCoin(tx.GasCoin) + coin := context.Coins().GetCoin(tx.GasCoin) if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { return nil, nil, nil, &Response{ @@ -322,7 +322,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.State) (Total return total, conversions, value, nil } -func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.State) *Response { +func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if data.ValueToBuy == nil { return &Response{ Code: code.DecodeError, @@ -335,7 +335,7 @@ func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.State) *Respo Log: fmt.Sprintf("\"From\" coin equals to \"to\" coin")} } - if !context.Coins.Exists(data.CoinToSell) { + if !context.Coins().Exists(data.CoinToSell) { return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.CoinToSell), @@ -345,7 +345,7 @@ func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.State) *Respo } } - if !context.Coins.Exists(data.CoinToBuy) { + if !context.Coins().Exists(data.CoinToBuy) { return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.CoinToBuy), @@ -358,21 +358,27 @@ func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.State) *Respo return nil } -func (data BuyCoinData) Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response { +func (data BuyCoinData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { sender, _ := tx.Sender() - response := data.BasicCheck(tx, context) + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + response := data.BasicCheck(tx, checkState) if response != nil { return *response } - totalSpends, conversions, value, response := data.TotalSpend(tx, context) + totalSpends, conversions, value, response := data.TotalSpend(tx, checkState) if response != nil { return *response } for _, ts := range totalSpends { - if context.Accounts.GetBalance(sender, ts.Coin).Cmp(ts.Value) < 0 { + if checkState.Accounts().GetBalance(sender, ts.Coin).Cmp(ts.Value) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s.", @@ -388,27 +394,27 @@ func (data BuyCoinData) Run(tx *Transaction, context *state.State, isCheck bool, } } - errResp := checkConversionsReserveUnderflow(conversions, context) + errResp := checkConversionsReserveUnderflow(conversions, checkState) if errResp != nil { return *errResp } - if !isCheck { + if deliveryState, ok := context.(*state.State); ok { for _, ts := range totalSpends { - context.Accounts.SubBalance(sender, ts.Coin, ts.Value) + deliveryState.Accounts.SubBalance(sender, ts.Coin, ts.Value) } for _, conversion := range conversions { - context.Coins.SubVolume(conversion.FromCoin, conversion.FromAmount) - context.Coins.SubReserve(conversion.FromCoin, conversion.FromReserve) + deliveryState.Coins.SubVolume(conversion.FromCoin, conversion.FromAmount) + deliveryState.Coins.SubReserve(conversion.FromCoin, conversion.FromReserve) - context.Coins.AddVolume(conversion.ToCoin, conversion.ToAmount) - context.Coins.AddReserve(conversion.ToCoin, conversion.ToReserve) + deliveryState.Coins.AddVolume(conversion.ToCoin, conversion.ToAmount) + deliveryState.Coins.AddReserve(conversion.ToCoin, conversion.ToReserve) } rewardPool.Add(rewardPool, tx.CommissionInBaseCoin()) - context.Accounts.AddBalance(sender, data.CoinToBuy, data.ValueToBuy) - context.Accounts.SetNonce(sender, tx.Nonce) + deliveryState.Accounts.AddBalance(sender, data.CoinToBuy, data.ValueToBuy) + deliveryState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ @@ -427,7 +433,7 @@ func (data BuyCoinData) Run(tx *Transaction, context *state.State, isCheck bool, } } -func checkConversionsReserveUnderflow(conversions []Conversion, context *state.State) *Response { +func checkConversionsReserveUnderflow(conversions []Conversion, context *state.CheckState) *Response { var totalReserveCoins []types.CoinSymbol totalReserveSub := make(map[types.CoinSymbol]*big.Int) for _, conversion := range conversions { @@ -444,7 +450,7 @@ func checkConversionsReserveUnderflow(conversions []Conversion, context *state.S } for _, coinSymbol := range totalReserveCoins { - errResp := CheckReserveUnderflow(context.Coins.GetCoin(coinSymbol), totalReserveSub[coinSymbol]) + errResp := CheckReserveUnderflow(context.Coins().GetCoin(coinSymbol), totalReserveSub[coinSymbol]) if errResp != nil { return errResp } diff --git a/core/transaction/executor.go b/core/transaction/executor.go index 0bcaad683..e1662bdc6 100644 --- a/core/transaction/executor.go +++ b/core/transaction/executor.go @@ -34,7 +34,7 @@ type Response struct { GasPrice uint32 `json:"gas_price"` } -func RunTx(context *state.State, +func RunTx(context state.Interface, isCheck bool, rawTx []byte, rewardPool *big.Int, @@ -72,7 +72,13 @@ func RunTx(context *state.State, } } - if !context.Coins.Exists(tx.GasCoin) { + var checkState *state.CheckState + //var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + if !checkState.Coins().Exists(tx.GasCoin) { return Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", tx.GasCoin), @@ -142,7 +148,7 @@ func RunTx(context *state.State, // check multi-signature if tx.SignatureType == SigTypeMulti { - multisig := context.Accounts.GetAccount(tx.multisig.Multisig) + multisig := checkState.Accounts().GetAccount(tx.multisig.Multisig) if !multisig.IsMultisig() { return Response{ @@ -195,7 +201,7 @@ func RunTx(context *state.State, } - if expectedNonce := context.Accounts.GetNonce(sender) + 1; expectedNonce != tx.Nonce { + if expectedNonce := checkState.Accounts().GetNonce(sender) + 1; expectedNonce != tx.Nonce { return Response{ Code: code.WrongNonce, Log: fmt.Sprintf("Unexpected nonce. Expected: %d, got %d.", expectedNonce, tx.Nonce), @@ -206,7 +212,7 @@ func RunTx(context *state.State, } } - response := tx.decodedData.Run(tx, context, isCheck, rewardPool, currentBlock) + response := tx.decodedData.Run(tx, context, rewardPool, currentBlock) if response.Code != code.TxFromSenderAlreadyInMempool && response.Code != code.OK { currentMempool.Delete(sender) diff --git a/core/transaction/sell_all_coin.go b/core/transaction/sell_all_coin.go index 74653dd3d..04acb7621 100644 --- a/core/transaction/sell_all_coin.go +++ b/core/transaction/sell_all_coin.go @@ -31,14 +31,14 @@ func (data SellAllCoinData) MarshalJSON() ([]byte, error) { }) } -func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.State) (TotalSpends, []Conversion, *big.Int, *Response) { +func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { sender, _ := tx.Sender() total := TotalSpends{} var conversions []Conversion commissionInBaseCoin := tx.CommissionInBaseCoin() - available := context.Accounts.GetBalance(sender, data.CoinToSell) + available := context.Accounts().GetBalance(sender, data.CoinToSell) var value *big.Int total.Add(data.CoinToSell, available) @@ -48,7 +48,7 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.State) (T amountToSell := big.NewInt(0).Set(available) amountToSell.Sub(amountToSell, commissionInBaseCoin) - coin := context.Coins.GetCoin(data.CoinToBuy) + coin := context.Coins().GetCoin(data.CoinToBuy) value = formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), amountToSell) if value.Cmp(data.MinimumValueToBuy) == -1 { @@ -75,7 +75,7 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.State) (T case data.CoinToBuy.IsBaseCoin(): amountToSell := big.NewInt(0).Set(available) - coin := context.Coins.GetCoin(data.CoinToSell) + coin := context.Coins().GetCoin(data.CoinToSell) ret := formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), amountToSell) if ret.Cmp(data.MinimumValueToBuy) == -1 { @@ -108,8 +108,8 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.State) (T default: amountToSell := big.NewInt(0).Set(available) - coinFrom := context.Coins.GetCoin(data.CoinToSell) - coinTo := context.Coins.GetCoin(data.CoinToBuy) + coinFrom := context.Coins().GetCoin(data.CoinToSell) + coinTo := context.Coins().GetCoin(data.CoinToBuy) basecoinValue := formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), amountToSell) if basecoinValue.Cmp(commissionInBaseCoin) == -1 { @@ -150,7 +150,7 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.State) (T return total, conversions, value, nil } -func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.State) *Response { +func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if data.CoinToSell == data.CoinToBuy { return &Response{ Code: code.CrossConvert, @@ -162,7 +162,7 @@ func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.State) *R } } - if !context.Coins.Exists(data.CoinToSell) { + if !context.Coins().Exists(data.CoinToSell) { return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin to sell not exists"), @@ -172,7 +172,7 @@ func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.State) *R } } - if !context.Coins.Exists(data.CoinToBuy) { + if !context.Coins().Exists(data.CoinToBuy) { return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin to buy not exists"), @@ -194,23 +194,27 @@ func (data SellAllCoinData) Gas() int64 { return commissions.ConvertTx } -func (data SellAllCoinData) Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response { +func (data SellAllCoinData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { sender, _ := tx.Sender() - - response := data.BasicCheck(tx, context) + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + response := data.BasicCheck(tx, checkState) if response != nil { return *response } - available := context.Accounts.GetBalance(sender, data.CoinToSell) + available := checkState.Accounts().GetBalance(sender, data.CoinToSell) - totalSpends, conversions, value, response := data.TotalSpend(tx, context) + totalSpends, conversions, value, response := data.TotalSpend(tx, checkState) if response != nil { return *response } for _, ts := range totalSpends { - if context.Accounts.GetBalance(sender, ts.Coin).Cmp(ts.Value) < 0 { + if checkState.Accounts().GetBalance(sender, ts.Coin).Cmp(ts.Value) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s.", @@ -226,27 +230,27 @@ func (data SellAllCoinData) Run(tx *Transaction, context *state.State, isCheck b } } - errResp := checkConversionsReserveUnderflow(conversions, context) + errResp := checkConversionsReserveUnderflow(conversions, checkState) if errResp != nil { return *errResp } - if !isCheck { + if deliveryState, ok := context.(*state.State); ok { for _, ts := range totalSpends { - context.Accounts.SubBalance(sender, ts.Coin, ts.Value) + deliveryState.Accounts.SubBalance(sender, ts.Coin, ts.Value) } for _, conversion := range conversions { - context.Coins.SubVolume(conversion.FromCoin, conversion.FromAmount) - context.Coins.SubReserve(conversion.FromCoin, conversion.FromReserve) + deliveryState.Coins.SubVolume(conversion.FromCoin, conversion.FromAmount) + deliveryState.Coins.SubReserve(conversion.FromCoin, conversion.FromReserve) - context.Coins.AddVolume(conversion.ToCoin, conversion.ToAmount) - context.Coins.AddReserve(conversion.ToCoin, conversion.ToReserve) + deliveryState.Coins.AddVolume(conversion.ToCoin, conversion.ToAmount) + deliveryState.Coins.AddReserve(conversion.ToCoin, conversion.ToReserve) } rewardPool.Add(rewardPool, tx.CommissionInBaseCoin()) - context.Accounts.AddBalance(sender, data.CoinToBuy, value) - context.Accounts.SetNonce(sender, tx.Nonce) + deliveryState.Accounts.AddBalance(sender, data.CoinToBuy, value) + deliveryState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/sell_coin.go b/core/transaction/sell_coin.go index 56b6ebfbd..b2b548a62 100644 --- a/core/transaction/sell_coin.go +++ b/core/transaction/sell_coin.go @@ -34,7 +34,7 @@ func (data SellCoinData) MarshalJSON() ([]byte, error) { }) } -func (data SellCoinData) TotalSpend(tx *Transaction, context *state.State) (TotalSpends, []Conversion, *big.Int, *Response) { +func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { total := TotalSpends{} var conversions []Conversion @@ -45,7 +45,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.State) (Tota switch { case data.CoinToSell.IsBaseCoin(): - coin := context.Coins.GetCoin(data.CoinToBuy) + coin := context.Coins().GetCoin(data.CoinToBuy) value = formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), data.ValueToSell) if value.Cmp(data.MinimumValueToBuy) == -1 { return nil, nil, nil, &Response{ @@ -86,7 +86,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.State) (Tota ToReserve: data.ValueToSell, }) case data.CoinToBuy.IsBaseCoin(): - coin := context.Coins.GetCoin(data.CoinToSell) + coin := context.Coins().GetCoin(data.CoinToSell) value = formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), data.ValueToSell) if value.Cmp(data.MinimumValueToBuy) == -1 { @@ -147,8 +147,8 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.State) (Tota ToCoin: data.CoinToBuy, }) default: - coinFrom := context.Coins.GetCoin(data.CoinToSell) - coinTo := context.Coins.GetCoin(data.CoinToBuy) + coinFrom := context.Coins().GetCoin(data.CoinToSell) + coinTo := context.Coins().GetCoin(data.CoinToBuy) valueToSell := big.NewInt(0).Set(data.ValueToSell) @@ -243,7 +243,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.State) (Tota commission := big.NewInt(0).Set(commissionInBaseCoin) if !tx.GasCoin.IsBaseCoin() { - coin := context.Coins.GetCoin(tx.GasCoin) + coin := context.Coins().GetCoin(tx.GasCoin) if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { return nil, nil, nil, &Response{ @@ -276,7 +276,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.State) (Tota return total, conversions, value, nil } -func (data SellCoinData) BasicCheck(tx *Transaction, context *state.State) *Response { +func (data SellCoinData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if data.ValueToSell == nil { return &Response{ Code: code.DecodeError, @@ -294,7 +294,7 @@ func (data SellCoinData) BasicCheck(tx *Transaction, context *state.State) *Resp } } - if !context.Coins.Exists(data.CoinToSell) { + if !context.Coins().Exists(data.CoinToSell) { return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin not exists"), @@ -304,7 +304,7 @@ func (data SellCoinData) BasicCheck(tx *Transaction, context *state.State) *Resp } } - if !context.Coins.Exists(data.CoinToBuy) { + if !context.Coins().Exists(data.CoinToBuy) { return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin not exists"), @@ -326,21 +326,26 @@ func (data SellCoinData) Gas() int64 { return commissions.ConvertTx } -func (data SellCoinData) Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response { +func (data SellCoinData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { sender, _ := tx.Sender() + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } - response := data.BasicCheck(tx, context) + response := data.BasicCheck(tx, checkState) if response != nil { return *response } - totalSpends, conversions, value, response := data.TotalSpend(tx, context) + totalSpends, conversions, value, response := data.TotalSpend(tx, checkState) if response != nil { return *response } for _, ts := range totalSpends { - if context.Accounts.GetBalance(sender, ts.Coin).Cmp(ts.Value) < 0 { + if checkState.Accounts().GetBalance(sender, ts.Coin).Cmp(ts.Value) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s.", @@ -356,27 +361,27 @@ func (data SellCoinData) Run(tx *Transaction, context *state.State, isCheck bool } } - errResp := checkConversionsReserveUnderflow(conversions, context) + errResp := checkConversionsReserveUnderflow(conversions, checkState) if errResp != nil { return *errResp } - if !isCheck { + if deliveryState, ok := context.(*state.State); ok { for _, ts := range totalSpends { - context.Accounts.SubBalance(sender, ts.Coin, ts.Value) + deliveryState.Accounts.SubBalance(sender, ts.Coin, ts.Value) } for _, conversion := range conversions { - context.Coins.SubVolume(conversion.FromCoin, conversion.FromAmount) - context.Coins.SubReserve(conversion.FromCoin, conversion.FromReserve) + deliveryState.Coins.SubVolume(conversion.FromCoin, conversion.FromAmount) + deliveryState.Coins.SubReserve(conversion.FromCoin, conversion.FromReserve) - context.Coins.AddVolume(conversion.ToCoin, conversion.ToAmount) - context.Coins.AddReserve(conversion.ToCoin, conversion.ToReserve) + deliveryState.Coins.AddVolume(conversion.ToCoin, conversion.ToAmount) + deliveryState.Coins.AddReserve(conversion.ToCoin, conversion.ToReserve) } rewardPool.Add(rewardPool, tx.CommissionInBaseCoin()) - context.Accounts.AddBalance(sender, data.CoinToBuy, value) - context.Accounts.SetNonce(sender, tx.Nonce) + deliveryState.Accounts.AddBalance(sender, data.CoinToBuy, value) + deliveryState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index a91f25a59..f2f2f3fd3 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -106,9 +106,9 @@ type Conversion struct { type Data interface { String() string Gas() int64 - TotalSpend(tx *Transaction, context *state.State) (TotalSpends, []Conversion, *big.Int, *Response) - BasicCheck(tx *Transaction, context *state.State) *Response - Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response + TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) + BasicCheck(tx *Transaction, context *state.CheckState) *Response + Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response } func (tx *Transaction) Serialize() ([]byte, error) { diff --git a/tree/tree.go b/tree/tree.go index bdc6e350b..ee8ce2497 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -6,39 +6,43 @@ import ( "sync" ) -type Tree interface { +type ITree interface { Get(key []byte) (index int64, value []byte) + Version() int64 + Hash() []byte + Iterate(fn func(key []byte, value []byte) bool) (stopped bool) +} + +type MTree interface { + ITree Set(key, value []byte) bool Remove(key []byte) ([]byte, bool) LoadVersion(targetVersion int64) (int64, error) LazyLoadVersion(targetVersion int64) (int64, error) SaveVersion() ([]byte, int64, error) DeleteVersion(version int64) error - GetImmutable() *ImmutableTree - GetImmutableAtHeight(version int64) (*ImmutableTree, error) - Version() int64 - Hash() []byte - Iterate(fn func(key []byte, value []byte) bool) (stopped bool) + GetImmutable() ITree + GetImmutableAtHeight(version int64) (ITree, error) } -func NewMutableTree(db dbm.DB, cacheSize int, keepEvery, keepRecent int64) *MutableTree { +func NewMutableTree(db dbm.DB, cacheSize int, keepEvery, keepRecent int64) MTree { tree, err := iavl.NewMutableTreeWithOpts(db, dbm.NewMemDB(), cacheSize, iavl.PruningOptions(keepEvery, keepRecent)) if err != nil { panic(err) } - return &MutableTree{ + return &mutableTree{ tree: tree, } } -type MutableTree struct { +type mutableTree struct { tree *iavl.MutableTree lock sync.RWMutex } -func (t *MutableTree) GetImmutableAtHeight(version int64) (*ImmutableTree, error) { +func (t *mutableTree) GetImmutableAtHeight(version int64) (ITree, error) { tree, err := t.tree.GetImmutable(version) if err != nil { return nil, err @@ -49,25 +53,25 @@ func (t *MutableTree) GetImmutableAtHeight(version int64) (*ImmutableTree, error }, nil } -func (t *MutableTree) Iterate(fn func(key []byte, value []byte) bool) (stopped bool) { +func (t *mutableTree) Iterate(fn func(key []byte, value []byte) bool) (stopped bool) { return t.tree.Iterate(fn) } -func (t *MutableTree) Hash() []byte { +func (t *mutableTree) Hash() []byte { t.lock.RLock() defer t.lock.RUnlock() return t.tree.Hash() } -func (t *MutableTree) Version() int64 { +func (t *mutableTree) Version() int64 { t.lock.RLock() defer t.lock.RUnlock() return t.tree.Version() } -func (t *MutableTree) GetImmutable() *ImmutableTree { +func (t *mutableTree) GetImmutable() ITree { t.lock.RLock() defer t.lock.RUnlock() @@ -76,55 +80,67 @@ func (t *MutableTree) GetImmutable() *ImmutableTree { } } -func (t *MutableTree) Get(key []byte) (index int64, value []byte) { +func (t *mutableTree) Get(key []byte) (index int64, value []byte) { t.lock.RLock() defer t.lock.RUnlock() return t.tree.Get(key) } -func (t *MutableTree) Set(key, value []byte) bool { +func (t *mutableTree) Set(key, value []byte) bool { t.lock.Lock() defer t.lock.Unlock() return t.tree.Set(key, value) } -func (t *MutableTree) Remove(key []byte) ([]byte, bool) { +func (t *mutableTree) Remove(key []byte) ([]byte, bool) { t.lock.Lock() defer t.lock.Unlock() return t.tree.Remove(key) } -func (t *MutableTree) LoadVersion(targetVersion int64) (int64, error) { +func (t *mutableTree) LoadVersion(targetVersion int64) (int64, error) { t.lock.Lock() defer t.lock.Unlock() return t.tree.LoadVersion(targetVersion) } -func (t *MutableTree) LazyLoadVersion(targetVersion int64) (int64, error) { +func (t *mutableTree) LazyLoadVersion(targetVersion int64) (int64, error) { t.lock.Lock() defer t.lock.Unlock() return t.tree.LazyLoadVersion(targetVersion) } -func (t *MutableTree) SaveVersion() ([]byte, int64, error) { +func (t *mutableTree) SaveVersion() ([]byte, int64, error) { t.lock.Lock() defer t.lock.Unlock() return t.tree.SaveVersion() } -func (t *MutableTree) DeleteVersion(version int64) error { +func (t *mutableTree) DeleteVersion(version int64) error { t.lock.Lock() defer t.lock.Unlock() return t.tree.DeleteVersion(version) } +//todo +//func (t *mutableTree) KeepLastHeight() string { +// t.lock.Lock() +// defer t.lock.Unlock() +// +// versions := t.tree.AvailableVersions() +// //for _, version := range versions { +// // t.tree.LazyLoadVersion() +// //} +// return fmt.Sprint(versions) +//} + func NewImmutableTree(db dbm.DB) *ImmutableTree { return &ImmutableTree{ tree: iavl.NewImmutableTree(db, 1024), @@ -147,38 +163,6 @@ func (t *ImmutableTree) Version() int64 { return t.tree.Version() } -func (t *ImmutableTree) GetImmutable() *ImmutableTree { - return t -} - func (t *ImmutableTree) Get(key []byte) (index int64, value []byte) { return t.tree.Get(key) } - -func (t *ImmutableTree) GetImmutableAtHeight(version int64) (*ImmutableTree, error) { - panic("Not implemented") -} - -func (t *ImmutableTree) Set(key, value []byte) bool { - panic("Not implemented") -} - -func (t *ImmutableTree) Remove(key []byte) ([]byte, bool) { - panic("Not implemented") -} - -func (t *ImmutableTree) LoadVersion(targetVersion int64) (int64, error) { - panic("Not implemented") -} - -func (t *ImmutableTree) LazyLoadVersion(targetVersion int64) (int64, error) { - panic("Not implemented") -} - -func (t *ImmutableTree) SaveVersion() ([]byte, int64, error) { - panic("Not implemented") -} - -func (t *ImmutableTree) DeleteVersion(version int64) error { - panic("Not implemented") -} From 68f8f49280bbe21ca59077deb94c19d09594dc73 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 27 Apr 2020 14:06:18 +0300 Subject: [PATCH 021/426] rework all tx data interface --- api/address.go | 4 +- api/addresses.go | 4 +- api/api.go | 2 +- api/candidate.go | 12 ++-- api/candidates.go | 6 +- api/coin_info.go | 2 +- api/estimate_coin_buy.go | 14 ++--- api/estimate_coin_sell.go | 14 ++--- api/estimate_coin_sell_all.go | 12 ++-- api/estimate_tx_commission.go | 2 +- api/maxgas.go | 2 +- api/missed_blocks.go | 4 +- api/v2/service/address.go | 4 +- api/v2/service/addresses.go | 4 +- api/v2/service/candidate.go | 12 ++-- api/v2/service/candidates.go | 6 +- api/v2/service/coin_info.go | 2 +- api/v2/service/estimate_coin_buy.go | 14 ++--- api/v2/service/estimate_coin_sell.go | 14 ++--- api/v2/service/estimate_coin_sell_all.go | 12 ++-- api/v2/service/estimate_tx_commission.go | 2 +- api/v2/service/gas.go | 2 +- api/v2/service/service.go | 2 +- api/v2/v2.go | 26 ++++++++- cli/service/service.go | 2 +- core/minter/minter.go | 12 ++-- core/state/accounts/accounts.go | 2 + core/state/app/app.go | 1 + core/state/candidates/candidates.go | 13 +++++ core/state/checks/checks.go | 1 + core/state/state.go | 16 ++++++ core/state/validators/validators.go | 3 + core/transaction/create_coin.go | 39 +++++++------ core/transaction/create_multisig.go | 32 ++++++----- core/transaction/declare_candidacy.go | 44 ++++++++------- core/transaction/delegate.go | 42 ++++++++------ core/transaction/edit_candidate.go | 36 +++++++----- core/transaction/multisend.go | 40 +++++++------ core/transaction/redeem_check.go | 44 ++++++++------- core/transaction/send.go | 38 +++++++------ core/transaction/switch_candidate_status.go | 62 ++++++++++++--------- core/transaction/unbond.go | 38 +++++++------ go.mod | 1 + 43 files changed, 385 insertions(+), 259 deletions(-) diff --git a/api/address.go b/api/address.go index cf8d281a5..2043f1504 100644 --- a/api/address.go +++ b/api/address.go @@ -20,10 +20,10 @@ func Address(address types.Address, height int) (*AddressResponse, error) { response := AddressResponse{ Balance: make(map[string]string), - TransactionCount: cState.Accounts.GetNonce(address), + TransactionCount: cState.Accounts().GetNonce(address), } - balances := cState.Accounts.GetBalances(address) + balances := cState.Accounts().GetBalances(address) for k, v := range balances { response.Balance[k.String()] = v.String() diff --git a/api/addresses.go b/api/addresses.go index 1f302e9c8..0626041e8 100644 --- a/api/addresses.go +++ b/api/addresses.go @@ -25,10 +25,10 @@ func Addresses(addresses []types.Address, height int) (*[]AddressesResponse, err data := AddressesResponse{ Address: address.String(), Balance: make(map[string]string), - TransactionCount: cState.Accounts.GetNonce(address), + TransactionCount: cState.Accounts().GetNonce(address), } - balances := cState.Accounts.GetBalances(address) + balances := cState.Accounts().GetBalances(address) for k, v := range balances { data.Balance[k.String()] = v.String() } diff --git a/api/api.go b/api/api.go index acb5ab7d7..5f9628cc6 100644 --- a/api/api.go +++ b/api/api.go @@ -138,7 +138,7 @@ type Response struct { Log string `json:"log,omitempty"` } -func GetStateForHeight(height int) (*state.State, error) { +func GetStateForHeight(height int) (*state.CheckState, error) { if height > 0 { cState, err := blockchain.GetStateForHeight(uint64(height)) diff --git a/api/candidate.go b/api/candidate.go index 44b2b6f71..1477de12b 100644 --- a/api/candidate.go +++ b/api/candidate.go @@ -24,18 +24,18 @@ type CandidateResponse struct { Status byte `json:"status"` } -func makeResponseCandidate(state *state.State, c candidates.Candidate, includeStakes bool) CandidateResponse { +func makeResponseCandidate(state *state.CheckState, c candidates.Candidate, includeStakes bool) CandidateResponse { candidate := CandidateResponse{ RewardAddress: c.RewardAddress.String(), OwnerAddress: c.OwnerAddress.String(), - TotalStake: state.Candidates.GetTotalStake(c.PubKey).String(), + TotalStake: state.Candidates().GetTotalStake(c.PubKey).String(), PubKey: c.PubKey.String(), Commission: c.Commission, Status: c.Status, } if includeStakes { - stakes := state.Candidates.GetStakes(c.PubKey) + stakes := state.Candidates().GetStakes(c.PubKey) candidate.Stakes = make([]Stake, len(stakes)) for i, stake := range stakes { candidate.Stakes[i] = Stake{ @@ -58,15 +58,15 @@ func Candidate(pubkey types.Pubkey, height int) (*CandidateResponse, error) { if height != 0 { cState.Lock() - cState.Candidates.LoadCandidates() - cState.Candidates.LoadStakesOfCandidate(pubkey) + cState.Candidates().LoadCandidates() + cState.Candidates().LoadStakesOfCandidate(pubkey) cState.Unlock() } cState.RLock() defer cState.RUnlock() - candidate := cState.Candidates.GetCandidate(pubkey) + candidate := cState.Candidates().GetCandidate(pubkey) if candidate == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Candidate not found"} } diff --git a/api/candidates.go b/api/candidates.go index 3831471ad..50455b552 100644 --- a/api/candidates.go +++ b/api/candidates.go @@ -8,9 +8,9 @@ func Candidates(height int, includeStakes bool) (*[]CandidateResponse, error) { if height != 0 { cState.Lock() - cState.Candidates.LoadCandidates() + cState.Candidates().LoadCandidates() if includeStakes { - cState.Candidates.LoadStakes() + cState.Candidates().LoadStakes() } cState.Unlock() } @@ -18,7 +18,7 @@ func Candidates(height int, includeStakes bool) (*[]CandidateResponse, error) { cState.RLock() defer cState.RUnlock() - candidates := cState.Candidates.GetCandidates() + candidates := cState.Candidates().GetCandidates() result := make([]CandidateResponse, len(candidates)) for i, candidate := range candidates { diff --git a/api/coin_info.go b/api/coin_info.go index 748bc36e2..3a2dff2b4 100644 --- a/api/coin_info.go +++ b/api/coin_info.go @@ -23,7 +23,7 @@ func CoinInfo(coinSymbol string, height int) (*CoinInfoResponse, error) { cState.RLock() defer cState.RUnlock() - coin := cState.Coins.GetCoin(types.StrToCoinSymbol(coinSymbol)) + coin := cState.Coins().GetCoin(types.StrToCoinSymbol(coinSymbol)) if coin == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin not found"} } diff --git a/api/estimate_coin_buy.go b/api/estimate_coin_buy.go index 1cd5681a8..3228f4030 100644 --- a/api/estimate_coin_buy.go +++ b/api/estimate_coin_buy.go @@ -33,11 +33,11 @@ func EstimateCoinBuy(coinToSellString string, coinToBuyString string, valueToBuy return nil, rpctypes.RPCError{Code: 400, Message: "\"From\" coin equals to \"to\" coin"} } - if !cState.Coins.Exists(coinToSell) { + if !cState.Coins().Exists(coinToSell) { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to sell not exists"} } - if !cState.Coins.Exists(coinToBuy) { + if !cState.Coins().Exists(coinToBuy) { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to buy not exists"} } @@ -46,7 +46,7 @@ func EstimateCoinBuy(coinToSellString string, coinToBuyString string, valueToBuy commission := big.NewInt(0).Set(commissionInBaseCoin) if coinToSell != types.GetBaseCoin() { - coin := cState.Coins.GetCoin(coinToSell) + coin := cState.Coins().GetCoin(coinToSell) if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { return nil, rpctypes.RPCError{Code: 400, Message: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", @@ -58,10 +58,10 @@ func EstimateCoinBuy(coinToSellString string, coinToBuyString string, valueToBuy switch { case coinToSell == types.GetBaseCoin(): - coin := cState.Coins.GetCoin(coinToBuy) + coin := cState.Coins().GetCoin(coinToBuy) result = formula.CalculatePurchaseAmount(coin.Volume(), coin.Reserve(), coin.Crr(), valueToBuy) case coinToBuy == types.GetBaseCoin(): - coin := cState.Coins.GetCoin(coinToSell) + coin := cState.Coins().GetCoin(coinToSell) if coin.Reserve().Cmp(valueToBuy) < 0 { return nil, rpctypes.RPCError{Code: 400, Message: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", @@ -70,8 +70,8 @@ func EstimateCoinBuy(coinToSellString string, coinToBuyString string, valueToBuy result = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), valueToBuy) default: - coinFrom := cState.Coins.GetCoin(coinToSell) - coinTo := cState.Coins.GetCoin(coinToBuy) + coinFrom := cState.Coins().GetCoin(coinToSell) + coinTo := cState.Coins().GetCoin(coinToBuy) baseCoinNeeded := formula.CalculatePurchaseAmount(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), valueToBuy) if coinFrom.Reserve().Cmp(baseCoinNeeded) < 0 { diff --git a/api/estimate_coin_sell.go b/api/estimate_coin_sell.go index dabdfdada..64881924e 100644 --- a/api/estimate_coin_sell.go +++ b/api/estimate_coin_sell.go @@ -35,11 +35,11 @@ func EstimateCoinSell( return nil, rpctypes.RPCError{Code: 400, Message: "\"From\" coin equals to \"to\" coin"} } - if !cState.Coins.Exists(coinToSell) { + if !cState.Coins().Exists(coinToSell) { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to sell not exists"} } - if !cState.Coins.Exists(coinToBuy) { + if !cState.Coins().Exists(coinToBuy) { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to buy not exists"} } @@ -48,7 +48,7 @@ func EstimateCoinSell( commission := big.NewInt(0).Set(commissionInBaseCoin) if coinToSell != types.GetBaseCoin() { - coin := cState.Coins.GetCoin(coinToSell) + coin := cState.Coins().GetCoin(coinToSell) if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { return nil, rpctypes.RPCError{Code: 400, Message: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", @@ -65,14 +65,14 @@ func EstimateCoinSell( switch { case coinToSell == types.GetBaseCoin(): - coin := cState.Coins.GetCoin(coinToBuy) + coin := cState.Coins().GetCoin(coinToBuy) result = formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) case coinToBuy == types.GetBaseCoin(): - coin := cState.Coins.GetCoin(coinToSell) + coin := cState.Coins().GetCoin(coinToSell) result = formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) default: - coinFrom := cState.Coins.GetCoin(coinToSell) - coinTo := cState.Coins.GetCoin(coinToBuy) + coinFrom := cState.Coins().GetCoin(coinToSell) + coinTo := cState.Coins().GetCoin(coinToBuy) basecoinValue := formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) result = formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), basecoinValue) } diff --git a/api/estimate_coin_sell_all.go b/api/estimate_coin_sell_all.go index 45d138fb8..65a3e80a7 100644 --- a/api/estimate_coin_sell_all.go +++ b/api/estimate_coin_sell_all.go @@ -37,11 +37,11 @@ func EstimateCoinSellAll( return nil, rpctypes.RPCError{Code: 400, Message: "\"From\" coin equals to \"to\" coin"} } - if !cState.Coins.Exists(coinToSell) { + if !cState.Coins().Exists(coinToSell) { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to sell not exists"} } - if !cState.Coins.Exists(coinToBuy) { + if !cState.Coins().Exists(coinToBuy) { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to buy not exists"} } @@ -51,7 +51,7 @@ func EstimateCoinSellAll( switch { case coinToSell == types.GetBaseCoin(): - coin := cState.Coins.GetCoin(coinToBuy) + coin := cState.Coins().GetCoin(coinToBuy) valueToSell.Sub(valueToSell, commission) if valueToSell.Cmp(big.NewInt(0)) != 1 { @@ -60,7 +60,7 @@ func EstimateCoinSellAll( result = formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) case coinToBuy == types.GetBaseCoin(): - coin := cState.Coins.GetCoin(coinToSell) + coin := cState.Coins().GetCoin(coinToSell) result = formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) result.Sub(result, commission) @@ -68,8 +68,8 @@ func EstimateCoinSellAll( return nil, rpctypes.RPCError{Code: 400, Message: "Not enough coins to pay commission"} } default: - coinFrom := cState.Coins.GetCoin(coinToSell) - coinTo := cState.Coins.GetCoin(coinToBuy) + coinFrom := cState.Coins().GetCoin(coinToSell) + coinTo := cState.Coins().GetCoin(coinToBuy) basecoinValue := formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) basecoinValue.Sub(basecoinValue, commission) diff --git a/api/estimate_tx_commission.go b/api/estimate_tx_commission.go index 701dc4494..01e073c4b 100644 --- a/api/estimate_tx_commission.go +++ b/api/estimate_tx_commission.go @@ -30,7 +30,7 @@ func EstimateTxCommission(tx []byte, height int) (*TxCommissionResponse, error) commission := big.NewInt(0).Set(commissionInBaseCoin) if !decodedTx.GasCoin.IsBaseCoin() { - coin := cState.Coins.GetCoin(decodedTx.GasCoin) + coin := cState.Coins().GetCoin(decodedTx.GasCoin) if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { return nil, rpctypes.RPCError{Code: 400, Message: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", diff --git a/api/maxgas.go b/api/maxgas.go index 2f2cbae4f..3154b5f6d 100644 --- a/api/maxgas.go +++ b/api/maxgas.go @@ -9,6 +9,6 @@ func MaxGas(height int) (*uint64, error) { cState.RLock() defer cState.RUnlock() - maxGas := cState.App.GetMaxGas() + maxGas := cState.App().GetMaxGas() return &maxGas, nil } diff --git a/api/missed_blocks.go b/api/missed_blocks.go index 146094ea1..3f0e7c324 100644 --- a/api/missed_blocks.go +++ b/api/missed_blocks.go @@ -18,14 +18,14 @@ func MissedBlocks(pubkey types.Pubkey, height int) (*MissedBlocksResponse, error if height != 0 { cState.Lock() - cState.Validators.LoadValidators() + cState.Validators().LoadValidators() cState.Unlock() } cState.RLock() defer cState.RUnlock() - vals := cState.Validators.GetValidators() + vals := cState.Validators().GetValidators() if vals == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Validators not found"} } diff --git a/api/v2/service/address.go b/api/v2/service/address.go index 4b0a54938..d2a2fc3d1 100644 --- a/api/v2/service/address.go +++ b/api/v2/service/address.go @@ -31,10 +31,10 @@ func (s *Service) Address(_ context.Context, req *pb.AddressRequest) (*pb.Addres address := types.BytesToAddress(decodeString) response := &pb.AddressResponse{ Balance: make(map[string]string), - TransactionsCount: fmt.Sprintf("%d", cState.Accounts.GetNonce(address)), + TransactionsCount: fmt.Sprintf("%d", cState.Accounts().GetNonce(address)), } - balances := cState.Accounts.GetBalances(address) + balances := cState.Accounts().GetBalances(address) for k, v := range balances { response.Balance[k.String()] = v.String() diff --git a/api/v2/service/addresses.go b/api/v2/service/addresses.go index b54f2428d..d3678e12d 100644 --- a/api/v2/service/addresses.go +++ b/api/v2/service/addresses.go @@ -36,10 +36,10 @@ func (s *Service) Addresses(_ context.Context, req *pb.AddressesRequest) (*pb.Ad data := &pb.AddressesResponse_Result{ Address: address, Balance: make(map[string]string), - TransactionsCount: fmt.Sprintf("%d", cState.Accounts.GetNonce(addr)), + TransactionsCount: fmt.Sprintf("%d", cState.Accounts().GetNonce(addr)), } - balances := cState.Accounts.GetBalances(addr) + balances := cState.Accounts().GetBalances(addr) for k, v := range balances { data.Balance[k.String()] = v.String() } diff --git a/api/v2/service/candidate.go b/api/v2/service/candidate.go index 1255796a5..04ca8622e 100644 --- a/api/v2/service/candidate.go +++ b/api/v2/service/candidate.go @@ -30,15 +30,15 @@ func (s *Service) Candidate(_ context.Context, req *pb.CandidateRequest) (*pb.Ca if req.Height != 0 { cState.Lock() - cState.Candidates.LoadCandidates() - cState.Candidates.LoadStakesOfCandidate(pubkey) + cState.Candidates().LoadCandidates() + cState.Candidates().LoadStakesOfCandidate(pubkey) cState.Unlock() } cState.RLock() defer cState.RUnlock() - candidate := cState.Candidates.GetCandidate(pubkey) + candidate := cState.Candidates().GetCandidate(pubkey) if candidate == nil { return new(pb.CandidateResponse), status.Error(codes.NotFound, "Candidate not found") } @@ -47,17 +47,17 @@ func (s *Service) Candidate(_ context.Context, req *pb.CandidateRequest) (*pb.Ca return result, nil } -func makeResponseCandidate(state *state.State, c candidates.Candidate, includeStakes bool) *pb.CandidateResponse { +func makeResponseCandidate(state *state.CheckState, c candidates.Candidate, includeStakes bool) *pb.CandidateResponse { candidate := &pb.CandidateResponse{ RewardAddress: c.RewardAddress.String(), - TotalStake: state.Candidates.GetTotalStake(c.PubKey).String(), + TotalStake: state.Candidates().GetTotalStake(c.PubKey).String(), PublicKey: c.PubKey.String(), Commission: fmt.Sprintf("%d", c.Commission), Status: fmt.Sprintf("%d", c.Status), } if includeStakes { - stakes := state.Candidates.GetStakes(c.PubKey) + stakes := state.Candidates().GetStakes(c.PubKey) candidate.Stakes = make([]*pb.CandidateResponse_Stake, 0, len(stakes)) for _, stake := range stakes { candidate.Stakes = append(candidate.Stakes, &pb.CandidateResponse_Stake{ diff --git a/api/v2/service/candidates.go b/api/v2/service/candidates.go index 05a68526d..ae95e2c55 100644 --- a/api/v2/service/candidates.go +++ b/api/v2/service/candidates.go @@ -15,9 +15,9 @@ func (s *Service) Candidates(_ context.Context, req *pb.CandidatesRequest) (*pb. if req.Height != 0 { cState.Lock() - cState.Candidates.LoadCandidates() + cState.Candidates().LoadCandidates() if req.IncludeStakes { - cState.Candidates.LoadStakes() + cState.Candidates().LoadStakes() } cState.Unlock() } @@ -25,7 +25,7 @@ func (s *Service) Candidates(_ context.Context, req *pb.CandidatesRequest) (*pb. cState.RLock() defer cState.RUnlock() - candidates := cState.Candidates.GetCandidates() + candidates := cState.Candidates().GetCandidates() result := &pb.CandidatesResponse{ Candidates: make([]*pb.CandidateResponse, 0, len(candidates)), diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index 25ab45575..466714d5b 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -18,7 +18,7 @@ func (s *Service) CoinInfo(_ context.Context, req *pb.CoinInfoRequest) (*pb.Coin cState.RLock() defer cState.RUnlock() - coin := cState.Coins.GetCoin(types.StrToCoinSymbol(req.Symbol)) + coin := cState.Coins().GetCoin(types.StrToCoinSymbol(req.Symbol)) if coin == nil { return new(pb.CoinInfoResponse), status.Error(codes.FailedPrecondition, "Coin not found") } diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index 8d2e45ec1..721dfe09b 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -31,11 +31,11 @@ func (s *Service) EstimateCoinBuy(_ context.Context, req *pb.EstimateCoinBuyRequ return new(pb.EstimateCoinBuyResponse), status.Error(codes.FailedPrecondition, "\"From\" coin equals to \"to\" coin") } - if !cState.Coins.Exists(coinToSell) { + if !cState.Coins().Exists(coinToSell) { return new(pb.EstimateCoinBuyResponse), status.Error(codes.FailedPrecondition, "Coin to sell not exists") } - if !cState.Coins.Exists(coinToBuy) { + if !cState.Coins().Exists(coinToBuy) { return new(pb.EstimateCoinBuyResponse), status.Error(codes.FailedPrecondition, "Coin to buy not exists") } @@ -44,7 +44,7 @@ func (s *Service) EstimateCoinBuy(_ context.Context, req *pb.EstimateCoinBuyRequ commission := big.NewInt(0).Set(commissionInBaseCoin) if coinToSell != types.GetBaseCoin() { - coin := cState.Coins.GetCoin(coinToSell) + coin := cState.Coins().GetCoin(coinToSell) if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", @@ -64,10 +64,10 @@ func (s *Service) EstimateCoinBuy(_ context.Context, req *pb.EstimateCoinBuyRequ switch { case coinToSell == types.GetBaseCoin(): - coin := cState.Coins.GetCoin(coinToBuy) + coin := cState.Coins().GetCoin(coinToBuy) result = formula.CalculatePurchaseAmount(coin.Volume(), coin.Reserve(), coin.Crr(), valueToBuy) case coinToBuy == types.GetBaseCoin(): - coin := cState.Coins.GetCoin(coinToSell) + coin := cState.Coins().GetCoin(coinToSell) if coin.Reserve().Cmp(valueToBuy) < 0 { return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", @@ -79,8 +79,8 @@ func (s *Service) EstimateCoinBuy(_ context.Context, req *pb.EstimateCoinBuyRequ result = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), valueToBuy) default: - coinFrom := cState.Coins.GetCoin(coinToSell) - coinTo := cState.Coins.GetCoin(coinToBuy) + coinFrom := cState.Coins().GetCoin(coinToSell) + coinTo := cState.Coins().GetCoin(coinToBuy) baseCoinNeeded := formula.CalculatePurchaseAmount(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), valueToBuy) if coinFrom.Reserve().Cmp(baseCoinNeeded) < 0 { diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index 6b9f290f7..df7afc549 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -32,13 +32,13 @@ func (s *Service) EstimateCoinSell(_ context.Context, req *pb.EstimateCoinSellRe })) } - if !cState.Coins.Exists(coinToSell) { + if !cState.Coins().Exists(coinToSell) { return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ "coin_to_sell": coinToSell.String(), })) } - if !cState.Coins.Exists(coinToBuy) { + if !cState.Coins().Exists(coinToBuy) { return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ "coin_to_buy": coinToSell.String(), })) @@ -54,7 +54,7 @@ func (s *Service) EstimateCoinSell(_ context.Context, req *pb.EstimateCoinSellRe } if coinToSell != types.GetBaseCoin() { - coin := cState.Coins.GetCoin(coinToSell) + coin := cState.Coins().GetCoin(coinToSell) if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", @@ -78,14 +78,14 @@ func (s *Service) EstimateCoinSell(_ context.Context, req *pb.EstimateCoinSellRe var result = big.NewInt(0) switch { case coinToSell == types.GetBaseCoin(): - coin := cState.Coins.GetCoin(coinToBuy) + coin := cState.Coins().GetCoin(coinToBuy) result.Set(formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell)) case coinToBuy == types.GetBaseCoin(): - coin := cState.Coins.GetCoin(coinToSell) + coin := cState.Coins().GetCoin(coinToSell) result.Set(formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell)) default: - coinFrom := cState.Coins.GetCoin(coinToSell) - coinTo := cState.Coins.GetCoin(coinToBuy) + coinFrom := cState.Coins().GetCoin(coinToSell) + coinTo := cState.Coins().GetCoin(coinToBuy) basecoinValue := formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) result.Set(formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), basecoinValue)) } diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index a30895acf..e663e6e0e 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -43,13 +43,13 @@ func (s *Service) EstimateCoinSellAll(_ context.Context, req *pb.EstimateCoinSel })) } - if !cState.Coins.Exists(coinToSell) { + if !cState.Coins().Exists(coinToSell) { return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.InvalidArgument, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ "coin_to_sell": coinToSell.String(), })) } - if !cState.Coins.Exists(coinToBuy) { + if !cState.Coins().Exists(coinToBuy) { return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.InvalidArgument, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ "coin_to_buy": coinToBuy.String(), })) @@ -61,7 +61,7 @@ func (s *Service) EstimateCoinSellAll(_ context.Context, req *pb.EstimateCoinSel switch { case coinToSell == types.GetBaseCoin(): - coin := cState.Coins.GetCoin(coinToBuy) + coin := cState.Coins().GetCoin(coinToBuy) valueToSell.Sub(valueToSell, commission) if valueToSell.Cmp(big.NewInt(0)) != 1 { @@ -74,7 +74,7 @@ func (s *Service) EstimateCoinSellAll(_ context.Context, req *pb.EstimateCoinSel result = formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) case coinToBuy == types.GetBaseCoin(): - coin := cState.Coins.GetCoin(coinToSell) + coin := cState.Coins().GetCoin(coinToSell) result = formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) result.Sub(result, commission) @@ -89,8 +89,8 @@ func (s *Service) EstimateCoinSellAll(_ context.Context, req *pb.EstimateCoinSel })) } default: - coinFrom := cState.Coins.GetCoin(coinToSell) - coinTo := cState.Coins.GetCoin(coinToBuy) + coinFrom := cState.Coins().GetCoin(coinToSell) + coinTo := cState.Coins().GetCoin(coinToBuy) basecoinValue := formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) basecoinValue.Sub(basecoinValue, commission) diff --git a/api/v2/service/estimate_tx_commission.go b/api/v2/service/estimate_tx_commission.go index b1d78040d..8dd983d36 100644 --- a/api/v2/service/estimate_tx_commission.go +++ b/api/v2/service/estimate_tx_commission.go @@ -39,7 +39,7 @@ func (s *Service) EstimateTxCommission(_ context.Context, req *pb.EstimateTxComm commission := big.NewInt(0).Set(commissionInBaseCoin) if !decodedTx.GasCoin.IsBaseCoin() { - coin := cState.Coins.GetCoin(decodedTx.GasCoin) + coin := cState.Coins().GetCoin(decodedTx.GasCoin) if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { return new(pb.EstimateTxCommissionResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", diff --git a/api/v2/service/gas.go b/api/v2/service/gas.go index a64c575fc..7fde75c2d 100644 --- a/api/v2/service/gas.go +++ b/api/v2/service/gas.go @@ -22,6 +22,6 @@ func (s *Service) MaxGas(_ context.Context, req *pb.MaxGasRequest) (*pb.MaxGasRe } return &pb.MaxGasResponse{ - MaxGas: fmt.Sprintf("%d", cState.App.GetMaxGas()), + MaxGas: fmt.Sprintf("%d", cState.App().GetMaxGas()), }, nil } diff --git a/api/v2/service/service.go b/api/v2/service/service.go index 360f408b4..697743359 100644 --- a/api/v2/service/service.go +++ b/api/v2/service/service.go @@ -26,7 +26,7 @@ func NewService(cdc *amino.Codec, blockchain *minter.Blockchain, client *rpc.Loc return &Service{cdc: cdc, blockchain: blockchain, client: client, minterCfg: minterCfg, version: version, tmNode: node} } -func (s *Service) getStateForHeight(height int32) (*state.State, error) { +func (s *Service) getStateForHeight(height int32) (*state.CheckState, error) { if height > 0 { cState, err := s.blockchain.GetStateForHeight(uint64(height)) if err != nil { diff --git a/api/v2/v2.go b/api/v2/v2.go index a2667aeb1..54f57fa89 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -4,6 +4,7 @@ import ( "context" "github.com/MinterTeam/minter-go-node/api/v2/service" gw "github.com/MinterTeam/node-grpc-gateway/api_pb" + "github.com/golang/glog" grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/tmc/grpc-websocket-proxy/wsproxy" @@ -11,6 +12,7 @@ import ( "google.golang.org/grpc" "net" "net/http" + "strings" ) func Run(srv *service.Service, addrGRPC, addrApi string) error { @@ -40,7 +42,7 @@ func Run(srv *service.Service, addrGRPC, addrApi string) error { grpc.WithInsecure(), grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(50000000)), } - + allowCORS(mux) group.Go(func() error { return gw.RegisterApiServiceHandlerFromEndpoint(ctx, mux, addrGRPC, opts) }) @@ -53,3 +55,25 @@ func Run(srv *service.Service, addrGRPC, addrApi string) error { return group.Wait() } + +func allowCORS(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if origin := r.Header.Get("Origin"); origin != "" { + w.Header().Set("Access-Control-Allow-Origin", origin) + if r.Method == "OPTIONS" && r.Header.Get("Access-Control-Request-Method") != "" { + preflightHandler(w, r) + return + } + } + h.ServeHTTP(w, r) + }) +} + +func preflightHandler(w http.ResponseWriter, r *http.Request) { + headers := []string{"Content-Type", "Accept"} + w.Header().Set("Access-Control-Allow-Headers", strings.Join(headers, ",")) + methods := []string{"GET", "HEAD", "POST", "PUT", "DELETE"} + w.Header().Set("Access-Control-Allow-Methods", strings.Join(methods, ",")) + glog.Infof("preflight request for %s", r.URL.Path) + return +} diff --git a/cli/service/service.go b/cli/service/service.go index ac7d986b9..ba7385560 100644 --- a/cli/service/service.go +++ b/cli/service/service.go @@ -63,7 +63,7 @@ func (m *Manager) Dashboard(_ *empty.Empty, stream pb.ManagerService_DashboardSe var address types.TmAddress copy(address[:], resultStatus.ValidatorInfo.Address) - validator := state.Validators.GetByTmAddress(address) + validator := state.Validators().GetByTmAddress(address) validatorStatus := m.blockchain.GetValidatorStatus(address) var pbValidatorStatus pb.DashboardResponse_ValidatorStatus diff --git a/core/minter/minter.go b/core/minter/minter.go index ddceeefc8..085a55db3 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -495,15 +495,15 @@ func (app *Blockchain) Stop() { } // Get immutable state of Minter Blockchain -func (app *Blockchain) CurrentState() *state.State { +func (app *Blockchain) CurrentState() *state.CheckState { app.lock.RLock() defer app.lock.RUnlock() - return state.NewCheckState(app.stateCheck) + return app.stateCheck } // Get immutable state of Minter Blockchain for given height -func (app *Blockchain) GetStateForHeight(height uint64) (*state.State, error) { +func (app *Blockchain) GetStateForHeight(height uint64) (*state.CheckState, error) { app.lock.RLock() defer app.lock.RUnlock() @@ -529,14 +529,14 @@ func (app *Blockchain) MissedBlocks(pubKey string, height uint64) (missedBlocks if height != 0 { cState.Lock() - cState.Validators.LoadValidators() + cState.Validators().LoadValidators() cState.Unlock() } cState.RLock() defer cState.RUnlock() - val := cState.Validators.GetByPublicKey(types.HexToPubkey(pubKey)) + val := cState.Validators().GetByPublicKey(types.HexToPubkey(pubKey)) if val == nil { return "", 0, status.Error(codes.NotFound, "Validator not found") } @@ -630,7 +630,7 @@ func (app *Blockchain) calcMaxGas(height uint64) uint64 { } // get current max gas - newMaxGas := app.stateCheck.App.GetMaxGas() + newMaxGas := app.stateCheck.App().GetMaxGas() // check if blocks are created in time if delta, _ := app.GetBlocksTimeDelta(height, blockDelta); delta > targetTime*blockDelta { diff --git a/core/state/accounts/accounts.go b/core/state/accounts/accounts.go index fca9b01d0..6a84ba51b 100644 --- a/core/state/accounts/accounts.go +++ b/core/state/accounts/accounts.go @@ -23,6 +23,8 @@ type RAccounts interface { GetAccount(address types.Address) *Model GetNonce(address types.Address) uint64 GetBalance(address types.Address, coin types.CoinSymbol) *big.Int + GetBalances(address types.Address) map[types.CoinSymbol]*big.Int + ExistsMultisig(msigAddress types.Address) bool } type Accounts struct { diff --git a/core/state/app/app.go b/core/state/app/app.go index 7668abf5b..fe8a68c07 100644 --- a/core/state/app/app.go +++ b/core/state/app/app.go @@ -13,6 +13,7 @@ const mainPrefix = 'd' type RApp interface { Export(state *types.AppState, height uint64) + GetMaxGas() uint64 } func (v *App) Tree() tree.ITree { diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 08cf3d5fa..23c634c3f 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -31,6 +31,19 @@ const ( type RCandidates interface { Export(state *types.AppState) + Exists(pubkey types.Pubkey) bool + Count() int + IsNewCandidateStakeSufficient(coin types.CoinSymbol, stake *big.Int, limit int) bool + IsDelegatorStakeSufficient(address types.Address, pubkey types.Pubkey, coin types.CoinSymbol, amount *big.Int) bool + GetStakeValueOfAddress(pubkey types.Pubkey, address types.Address, coin types.CoinSymbol) *big.Int + GetCandidateOwner(pubkey types.Pubkey) types.Address + GetTotalStake(pubkey types.Pubkey) *big.Int + LoadCandidates() + LoadStakesOfCandidate(pubkey types.Pubkey) + GetCandidate(pubkey types.Pubkey) *Candidate + LoadStakes() + GetCandidates() []*Candidate + GetStakes(pubkey types.Pubkey) []*Stake } type Candidates struct { diff --git a/core/state/checks/checks.go b/core/state/checks/checks.go index 2962fbab4..6c1843717 100644 --- a/core/state/checks/checks.go +++ b/core/state/checks/checks.go @@ -14,6 +14,7 @@ const mainPrefix = byte('t') type RChecks interface { Export(state *types.AppState) + IsCheckUsed(check *check.Check) bool } type Checks struct { diff --git a/core/state/state.go b/core/state/state.go index bd434edf5..1435b8cc5 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -36,6 +36,22 @@ func NewCheckState(state *State) *CheckState { func (cs *CheckState) isValue_State() {} +func (cs *CheckState) Lock() { + cs.state.lock.Lock() +} + +func (cs *CheckState) Unlock() { + cs.state.lock.Unlock() +} + +func (cs *CheckState) RLock() { + cs.state.lock.RLock() +} + +func (cs *CheckState) RUnlock() { + cs.state.lock.RUnlock() +} + func (cs *CheckState) Validators() validators.RValidators { return cs.state.Validators } diff --git a/core/state/validators/validators.go b/core/state/validators/validators.go index 8ccdf74ce..e61c37e76 100644 --- a/core/state/validators/validators.go +++ b/core/state/validators/validators.go @@ -36,6 +36,9 @@ type Validators struct { type RValidators interface { GetValidators() []*Validator Export(state *types.AppState) + GetByPublicKey(pubKey types.Pubkey) *Validator + LoadValidators() + GetByTmAddress(address types.TmAddress) *Validator } func NewReadValidators(bus *bus.Bus, iavl tree.MTree) (RValidators, error) { diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index 629a2e6a8..7c256326b 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -51,11 +51,11 @@ func (data CreateCoinData) MarshalJSON() ([]byte, error) { }) } -func (data CreateCoinData) TotalSpend(tx *Transaction, context *state.State) (TotalSpends, []Conversion, *big.Int, *Response) { +func (data CreateCoinData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { panic("implement me") } -func (data CreateCoinData) BasicCheck(tx *Transaction, context *state.State) *Response { +func (data CreateCoinData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if data.InitialReserve == nil || data.InitialAmount == nil || data.MaxSupply == nil { return &Response{ Code: code.DecodeError, @@ -74,7 +74,7 @@ func (data CreateCoinData) BasicCheck(tx *Transaction, context *state.State) *Re Log: fmt.Sprintf("Invalid coin symbol. Should be %s", allowedCoinSymbols)} } - if context.Coins.Exists(data.Symbol) { + if context.Coins().Exists(data.Symbol) { return &Response{ Code: code.CoinAlreadyExists, Log: fmt.Sprintf("Coin already exists")} @@ -127,10 +127,15 @@ func (data CreateCoinData) Gas() int64 { return 100000 // 100 bips } -func (data CreateCoinData) Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response { +func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { sender, _ := tx.Sender() - response := data.BasicCheck(tx, context) + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + response := data.BasicCheck(tx, checkState) if response != nil { return *response } @@ -139,7 +144,7 @@ func (data CreateCoinData) Run(tx *Transaction, context *state.State, isCheck bo commission := big.NewInt(0).Set(commissionInBaseCoin) if tx.GasCoin != types.GetBaseCoin() { - coin := context.Coins.GetCoin(tx.GasCoin) + coin := checkState.Coins().GetCoin(tx.GasCoin) errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) if errResp != nil { @@ -161,7 +166,7 @@ func (data CreateCoinData) Run(tx *Transaction, context *state.State, isCheck bo commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) } - if context.Accounts.GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), tx.GasCoin), @@ -173,7 +178,7 @@ func (data CreateCoinData) Run(tx *Transaction, context *state.State, isCheck bo } } - if context.Accounts.GetBalance(sender, types.GetBaseCoin()).Cmp(data.InitialReserve) < 0 { + if checkState.Accounts().GetBalance(sender, types.GetBaseCoin()).Cmp(data.InitialReserve) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), data.InitialReserve.String(), types.GetBaseCoin()), @@ -190,7 +195,7 @@ func (data CreateCoinData) Run(tx *Transaction, context *state.State, isCheck bo totalTxCost.Add(totalTxCost, data.InitialReserve) totalTxCost.Add(totalTxCost, commission) - if context.Accounts.GetBalance(sender, types.GetBaseCoin()).Cmp(totalTxCost) < 0 { + if checkState.Accounts().GetBalance(sender, types.GetBaseCoin()).Cmp(totalTxCost) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), tx.GasCoin), @@ -203,17 +208,17 @@ func (data CreateCoinData) Run(tx *Transaction, context *state.State, isCheck bo } } - if !isCheck { + if deliveryState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - context.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - context.Coins.SubVolume(tx.GasCoin, commission) + deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliveryState.Coins.SubVolume(tx.GasCoin, commission) - context.Accounts.SubBalance(sender, types.GetBaseCoin(), data.InitialReserve) - context.Accounts.SubBalance(sender, tx.GasCoin, commission) - context.Coins.Create(data.Symbol, data.Name, data.InitialAmount, data.ConstantReserveRatio, data.InitialReserve, data.MaxSupply) - context.Accounts.AddBalance(sender, data.Symbol, data.InitialAmount) - context.Accounts.SetNonce(sender, tx.Nonce) + deliveryState.Accounts.SubBalance(sender, types.GetBaseCoin(), data.InitialReserve) + deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliveryState.Coins.Create(data.Symbol, data.Name, data.InitialAmount, data.ConstantReserveRatio, data.InitialReserve, data.MaxSupply) + deliveryState.Accounts.AddBalance(sender, data.Symbol, data.InitialAmount) + deliveryState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index ef6d08668..fecf43587 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -38,11 +38,11 @@ func (data CreateMultisigData) MarshalJSON() ([]byte, error) { }) } -func (data CreateMultisigData) TotalSpend(tx *Transaction, context *state.State) (TotalSpends, []Conversion, *big.Int, *Response) { +func (data CreateMultisigData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { panic("implement me") } -func (data CreateMultisigData) BasicCheck(tx *Transaction, context *state.State) *Response { +func (data CreateMultisigData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { lenWeights := len(data.Weights) if lenWeights > 32 { return &Response{ @@ -92,10 +92,16 @@ func (data CreateMultisigData) Gas() int64 { return commissions.CreateMultisig } -func (data CreateMultisigData) Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response { +func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { sender, _ := tx.Sender() - response := data.BasicCheck(tx, context) + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + response := data.BasicCheck(tx, checkState) if response != nil { return *response } @@ -104,7 +110,7 @@ func (data CreateMultisigData) Run(tx *Transaction, context *state.State, isChec commission := big.NewInt(0).Set(commissionInBaseCoin) if !tx.GasCoin.IsBaseCoin() { - coin := context.Coins.GetCoin(tx.GasCoin) + coin := checkState.Coins().GetCoin(tx.GasCoin) errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) if errResp != nil { @@ -126,7 +132,7 @@ func (data CreateMultisigData) Run(tx *Transaction, context *state.State, isChec commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) } - if context.Accounts.GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, tx.GasCoin), @@ -144,7 +150,7 @@ func (data CreateMultisigData) Run(tx *Transaction, context *state.State, isChec Addresses: data.Addresses, }).Address() - if context.Accounts.ExistsMultisig(msigAddress) { + if checkState.Accounts().ExistsMultisig(msigAddress) { return Response{ Code: code.MultisigExists, Log: fmt.Sprintf("Multisig %s already exists", msigAddress.String()), @@ -154,16 +160,16 @@ func (data CreateMultisigData) Run(tx *Transaction, context *state.State, isChec } } - if !isCheck { + if deliveryState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - context.Coins.SubVolume(tx.GasCoin, commission) - context.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliveryState.Coins.SubVolume(tx.GasCoin, commission) + deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - context.Accounts.SubBalance(sender, tx.GasCoin, commission) - context.Accounts.SetNonce(sender, tx.Nonce) + deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliveryState.Accounts.SetNonce(sender, tx.Nonce) - context.Accounts.CreateMultisig(data.Weights, data.Addresses, data.Threshold, currentBlock) + deliveryState.Accounts.CreateMultisig(data.Weights, data.Addresses, data.Threshold, currentBlock) } tags := kv.Pairs{ diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index a77efa5c6..14ce6b9f7 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -42,18 +42,18 @@ func (data DeclareCandidacyData) MarshalJSON() ([]byte, error) { }) } -func (data DeclareCandidacyData) TotalSpend(tx *Transaction, context *state.State) (TotalSpends, []Conversion, *big.Int, *Response) { +func (data DeclareCandidacyData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { panic("implement me") } -func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.State) *Response { +func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if data.Stake == nil { return &Response{ Code: code.DecodeError, Log: "Incorrect tx data"} } - if !context.Coins.Exists(data.Coin) { + if !context.Coins().Exists(data.Coin) { return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Coin), @@ -63,7 +63,7 @@ func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.Stat } } - if context.Candidates.Exists(data.PubKey) { + if context.Candidates().Exists(data.PubKey) { return &Response{ Code: code.CandidateExists, Log: fmt.Sprintf("Candidate with such public key (%s) already exists", data.PubKey.String()), @@ -95,17 +95,23 @@ func (data DeclareCandidacyData) Gas() int64 { return commissions.DeclareCandidacyTx } -func (data DeclareCandidacyData) Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response { +func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { sender, _ := tx.Sender() - response := data.BasicCheck(tx, context) + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + response := data.BasicCheck(tx, checkState) if response != nil { return *response } maxCandidatesCount := validators.GetCandidatesCountForBlock(currentBlock) - if context.Candidates.Count() >= maxCandidatesCount && !context.Candidates.IsNewCandidateStakeSufficient(data.Coin, data.Stake, maxCandidatesCount) { + if checkState.Candidates().Count() >= maxCandidatesCount && !checkState.Candidates().IsNewCandidateStakeSufficient(data.Coin, data.Stake, maxCandidatesCount) { return Response{ Code: code.TooLowStake, Log: fmt.Sprintf("Given stake is too low")} @@ -116,7 +122,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context *state.State, isCh commission := big.NewInt(0).Set(commissionInBaseCoin) if !tx.GasCoin.IsBaseCoin() { - coin := context.Coins.GetCoin(tx.GasCoin) + coin := checkState.Coins().GetCoin(tx.GasCoin) errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) if errResp != nil { @@ -138,7 +144,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context *state.State, isCh commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) } - if context.Accounts.GetBalance(sender, data.Coin).Cmp(data.Stake) < 0 { + if checkState.Accounts().GetBalance(sender, data.Coin).Cmp(data.Stake) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), data.Stake, data.Coin), @@ -150,7 +156,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context *state.State, isCh } } - if context.Accounts.GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, tx.GasCoin), @@ -167,7 +173,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context *state.State, isCh totalTxCost.Add(totalTxCost, data.Stake) totalTxCost.Add(totalTxCost, commission) - if context.Accounts.GetBalance(sender, tx.GasCoin).Cmp(totalTxCost) < 0 { + if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(totalTxCost) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), tx.GasCoin), @@ -180,17 +186,17 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context *state.State, isCh } } - if !isCheck { + if deliveryState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - context.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - context.Coins.SubVolume(tx.GasCoin, commission) + deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliveryState.Coins.SubVolume(tx.GasCoin, commission) - context.Accounts.SubBalance(sender, data.Coin, data.Stake) - context.Accounts.SubBalance(sender, tx.GasCoin, commission) - context.Candidates.Create(data.Address, sender, data.PubKey, data.Commission) - context.Candidates.Delegate(sender, data.PubKey, data.Coin, data.Stake, big.NewInt(0)) - context.Accounts.SetNonce(sender, tx.Nonce) + deliveryState.Accounts.SubBalance(sender, data.Coin, data.Stake) + deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliveryState.Candidates.Create(data.Address, sender, data.PubKey, data.Commission) + deliveryState.Candidates.Delegate(sender, data.PubKey, data.Coin, data.Stake, big.NewInt(0)) + deliveryState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index 5e4c2a551..7e3e2f51c 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -32,18 +32,18 @@ func (data DelegateData) MarshalJSON() ([]byte, error) { }) } -func (data DelegateData) TotalSpend(tx *Transaction, context *state.State) (TotalSpends, []Conversion, *big.Int, *Response) { +func (data DelegateData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { panic("implement me") } -func (data DelegateData) BasicCheck(tx *Transaction, context *state.State) *Response { +func (data DelegateData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if data.Value == nil { return &Response{ Code: code.DecodeError, Log: "Incorrect tx data"} } - if !context.Coins.Exists(tx.GasCoin) { + if !context.Coins().Exists(tx.GasCoin) { return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", tx.GasCoin)} @@ -55,7 +55,7 @@ func (data DelegateData) BasicCheck(tx *Transaction, context *state.State) *Resp Log: fmt.Sprintf("Stake should be positive")} } - if !context.Candidates.Exists(data.PubKey) { + if !context.Candidates().Exists(data.PubKey) { return &Response{ Code: code.CandidateNotFound, Log: fmt.Sprintf("Candidate with such public key not found"), @@ -66,7 +66,7 @@ func (data DelegateData) BasicCheck(tx *Transaction, context *state.State) *Resp } sender, _ := tx.Sender() - if !context.Candidates.IsDelegatorStakeSufficient(sender, data.PubKey, data.Coin, data.Value) { + if !context.Candidates().IsDelegatorStakeSufficient(sender, data.PubKey, data.Coin, data.Value) { return &Response{ Code: code.TooLowStake, Log: fmt.Sprintf("Stake is too low")} @@ -84,10 +84,16 @@ func (data DelegateData) Gas() int64 { return commissions.DelegateTx } -func (data DelegateData) Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response { +func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { sender, _ := tx.Sender() - response := data.BasicCheck(tx, context) + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + response := data.BasicCheck(tx, checkState) if response != nil { return *response } @@ -96,7 +102,7 @@ func (data DelegateData) Run(tx *Transaction, context *state.State, isCheck bool commission := big.NewInt(0).Set(commissionInBaseCoin) if !tx.GasCoin.IsBaseCoin() { - coin := context.Coins.GetCoin(tx.GasCoin) + coin := checkState.Coins().GetCoin(tx.GasCoin) errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) if errResp != nil { @@ -118,7 +124,7 @@ func (data DelegateData) Run(tx *Transaction, context *state.State, isCheck bool commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) } - if context.Accounts.GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, tx.GasCoin), @@ -130,7 +136,7 @@ func (data DelegateData) Run(tx *Transaction, context *state.State, isCheck bool } } - if context.Accounts.GetBalance(sender, data.Coin).Cmp(data.Value) < 0 { + if checkState.Accounts().GetBalance(sender, data.Coin).Cmp(data.Value) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), data.Value, data.Coin), @@ -147,7 +153,7 @@ func (data DelegateData) Run(tx *Transaction, context *state.State, isCheck bool totalTxCost.Add(totalTxCost, data.Value) totalTxCost.Add(totalTxCost, commission) - if context.Accounts.GetBalance(sender, tx.GasCoin).Cmp(totalTxCost) < 0 { + if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(totalTxCost) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), tx.GasCoin), @@ -160,16 +166,16 @@ func (data DelegateData) Run(tx *Transaction, context *state.State, isCheck bool } } - if !isCheck { + if deliveryState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - context.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - context.Coins.SubVolume(tx.GasCoin, commission) + deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliveryState.Coins.SubVolume(tx.GasCoin, commission) - context.Accounts.SubBalance(sender, tx.GasCoin, commission) - context.Accounts.SubBalance(sender, data.Coin, data.Value) - context.Candidates.Delegate(sender, data.PubKey, data.Coin, data.Value, big.NewInt(0)) - context.Accounts.SetNonce(sender, tx.Nonce) + deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliveryState.Accounts.SubBalance(sender, data.Coin, data.Value) + deliveryState.Candidates.Delegate(sender, data.PubKey, data.Coin, data.Value, big.NewInt(0)) + deliveryState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index 84bbad50f..80ebd78a6 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -39,11 +39,11 @@ func (data EditCandidateData) GetPubKey() types.Pubkey { return data.PubKey } -func (data EditCandidateData) TotalSpend(tx *Transaction, context *state.State) (TotalSpends, []Conversion, *big.Int, *Response) { +func (data EditCandidateData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { panic("implement me") } -func (data EditCandidateData) BasicCheck(tx *Transaction, context *state.State) *Response { +func (data EditCandidateData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { return checkCandidateOwnership(data, tx, context) } @@ -56,10 +56,16 @@ func (data EditCandidateData) Gas() int64 { return commissions.EditCandidate } -func (data EditCandidateData) Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response { +func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { sender, _ := tx.Sender() - response := data.BasicCheck(tx, context) + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + response := data.BasicCheck(tx, checkState) if response != nil { return *response } @@ -68,7 +74,7 @@ func (data EditCandidateData) Run(tx *Transaction, context *state.State, isCheck commission := big.NewInt(0).Set(commissionInBaseCoin) if !tx.GasCoin.IsBaseCoin() { - coin := context.Coins.GetCoin(tx.GasCoin) + coin := checkState.Coins().GetCoin(tx.GasCoin) errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) if errResp != nil { @@ -90,7 +96,7 @@ func (data EditCandidateData) Run(tx *Transaction, context *state.State, isCheck commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) } - if context.Accounts.GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), tx.GasCoin), @@ -102,15 +108,15 @@ func (data EditCandidateData) Run(tx *Transaction, context *state.State, isCheck } } - if !isCheck { + if deliveryState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - context.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - context.Coins.SubVolume(tx.GasCoin, commission) + deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliveryState.Coins.SubVolume(tx.GasCoin, commission) - context.Accounts.SubBalance(sender, tx.GasCoin, commission) - context.Candidates.Edit(data.PubKey, data.RewardAddress, data.OwnerAddress) - context.Accounts.SetNonce(sender, tx.Nonce) + deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliveryState.Candidates.Edit(data.PubKey, data.RewardAddress, data.OwnerAddress) + deliveryState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ @@ -126,8 +132,8 @@ func (data EditCandidateData) Run(tx *Transaction, context *state.State, isCheck } } -func checkCandidateOwnership(data CandidateTx, tx *Transaction, context *state.State) *Response { - if !context.Candidates.Exists(data.GetPubKey()) { +func checkCandidateOwnership(data CandidateTx, tx *Transaction, context *state.CheckState) *Response { + if !context.Candidates().Exists(data.GetPubKey()) { return &Response{ Code: code.CandidateNotFound, Log: fmt.Sprintf("Candidate with such public key (%s) not found", data.GetPubKey().String()), @@ -137,7 +143,7 @@ func checkCandidateOwnership(data CandidateTx, tx *Transaction, context *state.S } } - owner := context.Candidates.GetCandidateOwner(data.GetPubKey()) + owner := context.Candidates().GetCandidateOwner(data.GetPubKey()) sender, _ := tx.Sender() if owner != sender { return &Response{ diff --git a/core/transaction/multisend.go b/core/transaction/multisend.go index a32800838..ec97661e5 100644 --- a/core/transaction/multisend.go +++ b/core/transaction/multisend.go @@ -19,11 +19,11 @@ type MultisendData struct { List []MultisendDataItem `json:"list"` } -func (data MultisendData) TotalSpend(tx *Transaction, context *state.State) (TotalSpends, []Conversion, *big.Int, *Response) { +func (data MultisendData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { panic("implement me") } -func (data MultisendData) BasicCheck(tx *Transaction, context *state.State) *Response { +func (data MultisendData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { quantity := len(data.List) if quantity < 1 || quantity > 100 { return &Response{ @@ -71,10 +71,16 @@ func (data MultisendData) Gas() int64 { return commissions.SendTx + ((int64(len(data.List)) - 1) * commissions.MultisendDelta) } -func (data MultisendData) Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response { +func (data MultisendData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { sender, _ := tx.Sender() - response := data.BasicCheck(tx, context) + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + response := data.BasicCheck(tx, checkState) if response != nil { return *response } @@ -83,7 +89,7 @@ func (data MultisendData) Run(tx *Transaction, context *state.State, isCheck boo commission := big.NewInt(0).Set(commissionInBaseCoin) if !tx.GasCoin.IsBaseCoin() { - coin := context.Coins.GetCoin(tx.GasCoin) + coin := checkState.Coins().GetCoin(tx.GasCoin) errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) if errResp != nil { @@ -105,22 +111,22 @@ func (data MultisendData) Run(tx *Transaction, context *state.State, isCheck boo commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) } - if errResp := checkBalances(context, sender, data.List, commission, tx.GasCoin); errResp != nil { + if errResp := checkBalances(checkState, sender, data.List, commission, tx.GasCoin); errResp != nil { return *errResp } - if !isCheck { + if deliveryState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - context.Coins.SubVolume(tx.GasCoin, commission) - context.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliveryState.Coins.SubVolume(tx.GasCoin, commission) + deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - context.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) for _, item := range data.List { - context.Accounts.SubBalance(sender, item.Coin, item.Value) - context.Accounts.AddBalance(item.To, item.Coin, item.Value) + deliveryState.Accounts.SubBalance(sender, item.Coin, item.Value) + deliveryState.Accounts.AddBalance(item.To, item.Coin, item.Value) } - context.Accounts.SetNonce(sender, tx.Nonce) + deliveryState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ @@ -137,7 +143,7 @@ func (data MultisendData) Run(tx *Transaction, context *state.State, isCheck boo } } -func checkBalances(context *state.State, sender types.Address, items []MultisendDataItem, commission *big.Int, gasCoin types.CoinSymbol) *Response { +func checkBalances(context *state.CheckState, sender types.Address, items []MultisendDataItem, commission *big.Int, gasCoin types.CoinSymbol) *Response { total := map[types.CoinSymbol]*big.Int{} total[gasCoin] = big.NewInt(0).Set(commission) @@ -160,7 +166,7 @@ func checkBalances(context *state.State, sender types.Address, items []Multisend for _, coin := range coins { value := total[coin] - if context.Accounts.GetBalance(sender, coin).Cmp(value) < 0 { + if context.Accounts().GetBalance(sender, coin).Cmp(value) < 0 { return &Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), value, coin), @@ -176,9 +182,9 @@ func checkBalances(context *state.State, sender types.Address, items []Multisend return nil } -func checkCoins(context *state.State, items []MultisendDataItem) *Response { +func checkCoins(context *state.CheckState, items []MultisendDataItem) *Response { for _, item := range items { - if !context.Coins.Exists(item.Coin) { + if !context.Coins().Exists(item.Coin) { return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", item.Coin), diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index 4d17b184c..193528cc7 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -34,7 +34,7 @@ func (data RedeemCheckData) MarshalJSON() ([]byte, error) { }) } -func (data RedeemCheckData) TotalSpend(tx *Transaction, context *state.State) (TotalSpends, []Conversion, *big.Int, *Response) { +func (data RedeemCheckData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { panic("implement me") } @@ -42,7 +42,7 @@ func (data RedeemCheckData) CommissionInBaseCoin(tx *Transaction) *big.Int { panic("implement me") } -func (data RedeemCheckData) BasicCheck(tx *Transaction, context *state.State) *Response { +func (data RedeemCheckData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if data.RawCheck == nil { return &Response{ Code: code.DecodeError, @@ -67,10 +67,16 @@ func (data RedeemCheckData) Gas() int64 { return commissions.RedeemCheckTx } -func (data RedeemCheckData) Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response { +func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { sender, _ := tx.Sender() - response := data.BasicCheck(tx, context) + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + response := data.BasicCheck(tx, checkState) if response != nil { return *response } @@ -109,7 +115,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context *state.State, isCheck b Log: err.Error()} } - if !context.Coins.Exists(decodedCheck.Coin) { + if !checkState.Coins().Exists(decodedCheck.Coin) { return Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin not exists"), @@ -119,7 +125,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context *state.State, isCheck b } } - if !context.Coins.Exists(decodedCheck.GasCoin) { + if !checkState.Coins().Exists(decodedCheck.GasCoin) { return Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Gas coin not exists"), @@ -150,7 +156,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context *state.State, isCheck b } } - if context.Checks.IsCheckUsed(decodedCheck) { + if checkState.Checks().IsCheckUsed(decodedCheck) { return Response{ Code: code.CheckUsed, Log: fmt.Sprintf("Check already redeemed")} @@ -193,7 +199,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context *state.State, isCheck b commission := big.NewInt(0).Set(commissionInBaseCoin) if !decodedCheck.GasCoin.IsBaseCoin() { - coin := context.Coins.GetCoin(decodedCheck.GasCoin) + coin := checkState.Coins().GetCoin(decodedCheck.GasCoin) errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) if errResp != nil { return *errResp @@ -203,7 +209,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context *state.State, isCheck b if decodedCheck.Coin == decodedCheck.GasCoin { totalTxCost := big.NewInt(0).Add(decodedCheck.Value, commission) - if context.Accounts.GetBalance(checkSender, decodedCheck.Coin).Cmp(totalTxCost) < 0 { + if checkState.Accounts().GetBalance(checkSender, decodedCheck.Coin).Cmp(totalTxCost) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", decodedCheck.Coin, checkSender.String(), totalTxCost.String(), decodedCheck.Coin), @@ -215,7 +221,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context *state.State, isCheck b } } } else { - if context.Accounts.GetBalance(checkSender, decodedCheck.Coin).Cmp(decodedCheck.Value) < 0 { + if checkState.Accounts().GetBalance(checkSender, decodedCheck.Coin).Cmp(decodedCheck.Value) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", checkSender.String(), decodedCheck.Coin, decodedCheck.Value.String(), decodedCheck.Coin), @@ -227,7 +233,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context *state.State, isCheck b } } - if context.Accounts.GetBalance(checkSender, decodedCheck.GasCoin).Cmp(commission) < 0 { + if checkState.Accounts().GetBalance(checkSender, decodedCheck.GasCoin).Cmp(commission) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", checkSender.String(), decodedCheck.GasCoin, commission.String(), decodedCheck.GasCoin), @@ -240,17 +246,17 @@ func (data RedeemCheckData) Run(tx *Transaction, context *state.State, isCheck b } } - if !isCheck { - context.Checks.UseCheck(decodedCheck) + if deliveryState, ok := context.(*state.State); ok { + deliveryState.Checks.UseCheck(decodedCheck) rewardPool.Add(rewardPool, commissionInBaseCoin) - context.Coins.SubVolume(decodedCheck.GasCoin, commission) - context.Coins.SubReserve(decodedCheck.GasCoin, commissionInBaseCoin) + deliveryState.Coins.SubVolume(decodedCheck.GasCoin, commission) + deliveryState.Coins.SubReserve(decodedCheck.GasCoin, commissionInBaseCoin) - context.Accounts.SubBalance(checkSender, decodedCheck.GasCoin, commission) - context.Accounts.SubBalance(checkSender, decodedCheck.Coin, decodedCheck.Value) - context.Accounts.AddBalance(sender, decodedCheck.Coin, decodedCheck.Value) - context.Accounts.SetNonce(sender, tx.Nonce) + deliveryState.Accounts.SubBalance(checkSender, decodedCheck.GasCoin, commission) + deliveryState.Accounts.SubBalance(checkSender, decodedCheck.Coin, decodedCheck.Value) + deliveryState.Accounts.AddBalance(sender, decodedCheck.Coin, decodedCheck.Value) + deliveryState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/send.go b/core/transaction/send.go index 3fb7c0842..a485e352d 100644 --- a/core/transaction/send.go +++ b/core/transaction/send.go @@ -31,7 +31,7 @@ func (data SendData) MarshalJSON() ([]byte, error) { }) } -func (data SendData) TotalSpend(tx *Transaction, context *state.State) (TotalSpends, []Conversion, *big.Int, *Response) { +func (data SendData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { total := TotalSpends{} var conversions []Conversion @@ -39,7 +39,7 @@ func (data SendData) TotalSpend(tx *Transaction, context *state.State) (TotalSpe commission := big.NewInt(0).Set(commissionInBaseCoin) if !tx.GasCoin.IsBaseCoin() { - coin := context.Coins.GetCoin(tx.GasCoin) + coin := context.Coins().GetCoin(tx.GasCoin) errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) if errResp != nil { @@ -74,14 +74,14 @@ func (data SendData) TotalSpend(tx *Transaction, context *state.State) (TotalSpe return total, conversions, nil, nil } -func (data SendData) BasicCheck(tx *Transaction, context *state.State) *Response { +func (data SendData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if data.Value == nil { return &Response{ Code: code.DecodeError, Log: "Incorrect tx data"} } - if !context.Coins.Exists(data.Coin) { + if !context.Coins().Exists(data.Coin) { return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Coin), @@ -103,21 +103,27 @@ func (data SendData) Gas() int64 { return commissions.SendTx } -func (data SendData) Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response { +func (data SendData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { sender, _ := tx.Sender() - response := data.BasicCheck(tx, context) + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + response := data.BasicCheck(tx, checkState) if response != nil { return *response } - totalSpends, conversions, _, response := data.TotalSpend(tx, context) + totalSpends, conversions, _, response := data.TotalSpend(tx, checkState) if response != nil { return *response } for _, ts := range totalSpends { - if context.Accounts.GetBalance(sender, ts.Coin).Cmp(ts.Value) < 0 { + if checkState.Accounts().GetBalance(sender, ts.Coin).Cmp(ts.Value) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s.", @@ -133,22 +139,22 @@ func (data SendData) Run(tx *Transaction, context *state.State, isCheck bool, re } } - if !isCheck { + if deliveryState, ok := context.(*state.State); ok { for _, ts := range totalSpends { - context.Accounts.SubBalance(sender, ts.Coin, ts.Value) + deliveryState.Accounts.SubBalance(sender, ts.Coin, ts.Value) } for _, conversion := range conversions { - context.Coins.SubVolume(conversion.FromCoin, conversion.FromAmount) - context.Coins.SubReserve(conversion.FromCoin, conversion.FromReserve) + deliveryState.Coins.SubVolume(conversion.FromCoin, conversion.FromAmount) + deliveryState.Coins.SubReserve(conversion.FromCoin, conversion.FromReserve) - context.Coins.AddVolume(conversion.ToCoin, conversion.ToAmount) - context.Coins.AddReserve(conversion.ToCoin, conversion.ToReserve) + deliveryState.Coins.AddVolume(conversion.ToCoin, conversion.ToAmount) + deliveryState.Coins.AddReserve(conversion.ToCoin, conversion.ToReserve) } rewardPool.Add(rewardPool, tx.CommissionInBaseCoin()) - context.Accounts.AddBalance(data.To, data.Coin, data.Value) - context.Accounts.SetNonce(sender, tx.Nonce) + deliveryState.Accounts.AddBalance(data.To, data.Coin, data.Value) + deliveryState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index bd70c9bf3..8bc2f2ba2 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -29,11 +29,11 @@ func (data SetCandidateOnData) GetPubKey() types.Pubkey { return data.PubKey } -func (data SetCandidateOnData) TotalSpend(tx *Transaction, context *state.State) (TotalSpends, []Conversion, *big.Int, *Response) { +func (data SetCandidateOnData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { panic("implement me") } -func (data SetCandidateOnData) BasicCheck(tx *Transaction, context *state.State) *Response { +func (data SetCandidateOnData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { return checkCandidateOwnership(data, tx, context) } @@ -46,10 +46,16 @@ func (data SetCandidateOnData) Gas() int64 { return commissions.ToggleCandidateStatus } -func (data SetCandidateOnData) Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response { +func (data SetCandidateOnData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { sender, _ := tx.Sender() - response := data.BasicCheck(tx, context) + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + response := data.BasicCheck(tx, checkState) if response != nil { return *response } @@ -58,7 +64,7 @@ func (data SetCandidateOnData) Run(tx *Transaction, context *state.State, isChec commission := big.NewInt(0).Set(commissionInBaseCoin) if !tx.GasCoin.IsBaseCoin() { - coin := context.Coins.GetCoin(tx.GasCoin) + coin := checkState.Coins().GetCoin(tx.GasCoin) errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) if errResp != nil { @@ -80,7 +86,7 @@ func (data SetCandidateOnData) Run(tx *Transaction, context *state.State, isChec commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) } - if context.Accounts.GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, tx.GasCoin), @@ -92,15 +98,15 @@ func (data SetCandidateOnData) Run(tx *Transaction, context *state.State, isChec } } - if !isCheck { + if deliveryState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - context.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - context.Coins.SubVolume(tx.GasCoin, commission) + deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliveryState.Coins.SubVolume(tx.GasCoin, commission) - context.Accounts.SubBalance(sender, tx.GasCoin, commission) - context.Candidates.SetOnline(data.PubKey) - context.Accounts.SetNonce(sender, tx.Nonce) + deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliveryState.Candidates.SetOnline(data.PubKey) + deliveryState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ @@ -132,11 +138,11 @@ func (data SetCandidateOffData) GetPubKey() types.Pubkey { return data.PubKey } -func (data SetCandidateOffData) TotalSpend(tx *Transaction, context *state.State) (TotalSpends, []Conversion, *big.Int, *Response) { +func (data SetCandidateOffData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { panic("implement me") } -func (data SetCandidateOffData) BasicCheck(tx *Transaction, context *state.State) *Response { +func (data SetCandidateOffData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { return checkCandidateOwnership(data, tx, context) } @@ -149,10 +155,16 @@ func (data SetCandidateOffData) Gas() int64 { return commissions.ToggleCandidateStatus } -func (data SetCandidateOffData) Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response { +func (data SetCandidateOffData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { sender, _ := tx.Sender() - response := data.BasicCheck(tx, context) + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + response := data.BasicCheck(tx, checkState) if response != nil { return *response } @@ -161,7 +173,7 @@ func (data SetCandidateOffData) Run(tx *Transaction, context *state.State, isChe commission := big.NewInt(0).Set(commissionInBaseCoin) if !tx.GasCoin.IsBaseCoin() { - coin := context.Coins.GetCoin(tx.GasCoin) + coin := checkState.Coins().GetCoin(tx.GasCoin) if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { return Response{ @@ -178,7 +190,7 @@ func (data SetCandidateOffData) Run(tx *Transaction, context *state.State, isChe commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) } - if context.Accounts.GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, tx.GasCoin), @@ -190,16 +202,16 @@ func (data SetCandidateOffData) Run(tx *Transaction, context *state.State, isChe } } - if !isCheck { + if deliveryState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - context.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - context.Coins.SubVolume(tx.GasCoin, commission) + deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliveryState.Coins.SubVolume(tx.GasCoin, commission) - context.Accounts.SubBalance(sender, tx.GasCoin, commission) - context.Candidates.SetOffline(data.PubKey) - context.Validators.SetToDrop(data.PubKey) - context.Accounts.SetNonce(sender, tx.Nonce) + deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliveryState.Candidates.SetOffline(data.PubKey) + deliveryState.Validators.SetToDrop(data.PubKey) + deliveryState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 322d9228d..85fc6d4ea 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -34,18 +34,18 @@ func (data UnbondData) MarshalJSON() ([]byte, error) { }) } -func (data UnbondData) TotalSpend(tx *Transaction, context *state.State) (TotalSpends, []Conversion, *big.Int, *Response) { +func (data UnbondData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { panic("implement me") } -func (data UnbondData) BasicCheck(tx *Transaction, context *state.State) *Response { +func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if data.Value == nil { return &Response{ Code: code.DecodeError, Log: "Incorrect tx data"} } - if !context.Coins.Exists(data.Coin) { + if !context.Coins().Exists(data.Coin) { return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Coin), @@ -55,7 +55,7 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.State) *Respon } } - if !context.Candidates.Exists(data.PubKey) { + if !context.Candidates().Exists(data.PubKey) { return &Response{ Code: code.CandidateNotFound, Log: fmt.Sprintf("Candidate with such public key not found"), @@ -66,7 +66,7 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.State) *Respon } sender, _ := tx.Sender() - stake := context.Candidates.GetStakeValueOfAddress(data.PubKey, sender, data.Coin) + stake := context.Candidates().GetStakeValueOfAddress(data.PubKey, sender, data.Coin) if stake == nil { return &Response{ @@ -95,10 +95,16 @@ func (data UnbondData) Gas() int64 { return commissions.UnbondTx } -func (data UnbondData) Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response { +func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { sender, _ := tx.Sender() - response := data.BasicCheck(tx, context) + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + response := data.BasicCheck(tx, checkState) if response != nil { return *response } @@ -107,7 +113,7 @@ func (data UnbondData) Run(tx *Transaction, context *state.State, isCheck bool, commission := big.NewInt(0).Set(commissionInBaseCoin) if !tx.GasCoin.IsBaseCoin() { - coin := context.Coins.GetCoin(tx.GasCoin) + coin := checkState.Coins().GetCoin(tx.GasCoin) errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) if errResp != nil { @@ -129,7 +135,7 @@ func (data UnbondData) Run(tx *Transaction, context *state.State, isCheck bool, commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) } - if context.Accounts.GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, tx.GasCoin), @@ -141,19 +147,19 @@ func (data UnbondData) Run(tx *Transaction, context *state.State, isCheck bool, } } - if !isCheck { + if deliveryState, ok := context.(*state.State); ok { // now + 30 days unbondAtBlock := currentBlock + unbondPeriod rewardPool.Add(rewardPool, commissionInBaseCoin) - context.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - context.Coins.SubVolume(tx.GasCoin, commission) + deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliveryState.Coins.SubVolume(tx.GasCoin, commission) - context.Accounts.SubBalance(sender, tx.GasCoin, commission) - context.Candidates.SubStake(sender, data.PubKey, data.Coin, data.Value) - context.FrozenFunds.AddFund(unbondAtBlock, sender, data.PubKey, data.Coin, data.Value) - context.Accounts.SetNonce(sender, tx.Nonce) + deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliveryState.Candidates.SubStake(sender, data.PubKey, data.Coin, data.Value) + deliveryState.FrozenFunds.AddFund(unbondAtBlock, sender, data.PubKey, data.Coin, data.Value) + deliveryState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/go.mod b/go.mod index ad4929638..788553288 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 + github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b github.com/golang/protobuf v1.3.4 github.com/google/uuid v1.1.1 github.com/gorilla/websocket v1.4.1 From 365425c92ec1e076239559b7b4ecd9d5fd6473fc Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 27 Apr 2020 14:30:45 +0300 Subject: [PATCH 022/426] KeepLastStates --- api/v2/service/status.go | 1 + cli/service/service.go | 1 + core/state/app/app.go | 2 +- core/state/state.go | 2 +- tree/tree.go | 38 +++++++++++++++++++++----------------- 5 files changed, 25 insertions(+), 19 deletions(-) diff --git a/api/v2/service/status.go b/api/v2/service/status.go index 72157e32a..1b2ad70a4 100644 --- a/api/v2/service/status.go +++ b/api/v2/service/status.go @@ -22,6 +22,7 @@ func (s *Service) Status(context.Context, *empty.Empty) (*pb.StatusResponse, err LatestAppHash: fmt.Sprintf("%X", result.SyncInfo.LatestAppHash), LatestBlockHeight: fmt.Sprintf("%d", result.SyncInfo.LatestBlockHeight), LatestBlockTime: result.SyncInfo.LatestBlockTime.Format(time.RFC3339Nano), + KeepLastStates: fmt.Sprintf("%d", s.blockchain.CurrentState().Tree().KeepLastHeight()), CatchingUp: result.SyncInfo.CatchingUp, PublicKey: fmt.Sprintf("Mp%x", result.ValidatorInfo.PubKey.Bytes()[5:]), NodeId: string(result.NodeInfo.ID()), diff --git a/cli/service/service.go b/cli/service/service.go index ba7385560..593a30487 100644 --- a/cli/service/service.go +++ b/cli/service/service.go @@ -117,6 +117,7 @@ func (m *Manager) Status(context.Context, *empty.Empty) (*pb.StatusResponse, err Version: version.Version, LatestBlockHash: fmt.Sprintf("%X", resultStatus.SyncInfo.LatestBlockHash), LatestAppHash: fmt.Sprintf("%X", resultStatus.SyncInfo.LatestAppHash), + KeepLastStates: int64(m.blockchain.CurrentState().Tree().KeepLastHeight()), LatestBlockHeight: resultStatus.SyncInfo.LatestBlockHeight, LatestBlockTime: resultStatus.SyncInfo.LatestBlockTime.Format(time.RFC3339), TmStatus: &pb.StatusResponse_TmStatus{ diff --git a/core/state/app/app.go b/core/state/app/app.go index fe8a68c07..5c1215967 100644 --- a/core/state/app/app.go +++ b/core/state/app/app.go @@ -16,7 +16,7 @@ type RApp interface { GetMaxGas() uint64 } -func (v *App) Tree() tree.ITree { +func (v *App) Tree() tree.ReadOnlyTree { return v.iavl } diff --git a/core/state/state.go b/core/state/state.go index 1435b8cc5..b4e71d972 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -73,7 +73,7 @@ func (cs *CheckState) Coins() coins.RCoins { func (cs *CheckState) Checks() checks.RChecks { return cs.state.Checks } -func (cs *CheckState) Tree() tree.ITree { +func (cs *CheckState) Tree() tree.ReadOnlyTree { return cs.state.Tree() } diff --git a/tree/tree.go b/tree/tree.go index ee8ce2497..10fb38bdb 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -6,23 +6,24 @@ import ( "sync" ) -type ITree interface { +type ReadOnlyTree interface { Get(key []byte) (index int64, value []byte) Version() int64 Hash() []byte Iterate(fn func(key []byte, value []byte) bool) (stopped bool) + KeepLastHeight() int } type MTree interface { - ITree + ReadOnlyTree Set(key, value []byte) bool Remove(key []byte) ([]byte, bool) LoadVersion(targetVersion int64) (int64, error) LazyLoadVersion(targetVersion int64) (int64, error) SaveVersion() ([]byte, int64, error) DeleteVersion(version int64) error - GetImmutable() ITree - GetImmutableAtHeight(version int64) (ITree, error) + GetImmutable() *ImmutableTree + GetImmutableAtHeight(version int64) (*ImmutableTree, error) } func NewMutableTree(db dbm.DB, cacheSize int, keepEvery, keepRecent int64) MTree { @@ -42,7 +43,7 @@ type mutableTree struct { lock sync.RWMutex } -func (t *mutableTree) GetImmutableAtHeight(version int64) (ITree, error) { +func (t *mutableTree) GetImmutableAtHeight(version int64) (*ImmutableTree, error) { tree, err := t.tree.GetImmutable(version) if err != nil { return nil, err @@ -71,7 +72,7 @@ func (t *mutableTree) Version() int64 { return t.tree.Version() } -func (t *mutableTree) GetImmutable() ITree { +func (t *mutableTree) GetImmutable() *ImmutableTree { t.lock.RLock() defer t.lock.RUnlock() @@ -129,17 +130,20 @@ func (t *mutableTree) DeleteVersion(version int64) error { return t.tree.DeleteVersion(version) } -//todo -//func (t *mutableTree) KeepLastHeight() string { -// t.lock.Lock() -// defer t.lock.Unlock() -// -// versions := t.tree.AvailableVersions() -// //for _, version := range versions { -// // t.tree.LazyLoadVersion() -// //} -// return fmt.Sprint(versions) -//} +func (t *mutableTree) KeepLastHeight() int { + t.lock.Lock() + defer t.lock.Unlock() + + versions := t.tree.AvailableVersions() + prev := 1 + for _, version := range versions { + if version-prev == 1 { + break + } + prev = version + } + return prev +} func NewImmutableTree(db dbm.DB) *ImmutableTree { return &ImmutableTree{ From 47f83c4d02a5ce83f066a54a090b3e114d4d57ec Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 27 Apr 2020 23:47:18 +0300 Subject: [PATCH 023/426] hot-fix --- core/minter/minter.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index a5c0deb27..25d18ef12 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -462,8 +462,10 @@ func (app *Blockchain) Commit() abciTypes.ResponseCommit { _ = app.eventsDB.CommitEvents() // Persist application hash and height - app.appDB.SetLastBlockHash(hash) - app.appDB.SetLastHeight(app.height) + if app.height%uint64(app.cfg.StateKeepEver) == 0 { + app.appDB.SetLastBlockHash(hash) + app.appDB.SetLastHeight(app.height) + } // Resetting check state to be consistent with current height app.resetCheckState() From 735fd77597a950092bdbe4db90fc1522417afd6a Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 8 May 2020 17:35:06 +0300 Subject: [PATCH 024/426] clean up transaction data interface --- core/transaction/transaction.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index f2f2f3fd3..b70aaf6ae 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -106,8 +106,6 @@ type Conversion struct { type Data interface { String() string Gas() int64 - TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) - BasicCheck(tx *Transaction, context *state.CheckState) *Response Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response } From 6a05dd14ad2c8adce0ee48ea6a18e8aad6b8f837 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 21 May 2020 18:51:44 +0300 Subject: [PATCH 025/426] refactor api v2 --- api/v2/service/send_transaction.go | 6 +++++- api/v2/service/ws.go | 2 +- api/v2/v2.go | 30 ++++++++++++++++++++++-------- cmd/minter/cmd/node.go | 4 +++- go.mod | 2 ++ go.sum | 3 +++ 6 files changed, 36 insertions(+), 11 deletions(-) diff --git a/api/v2/service/send_transaction.go b/api/v2/service/send_transaction.go index f7d64995e..aa7b835ec 100644 --- a/api/v2/service/send_transaction.go +++ b/api/v2/service/send_transaction.go @@ -18,7 +18,11 @@ func (s *Service) SendPostTransaction(ctx context.Context, req *pb.SendTransacti return s.SendGetTransaction(ctx, req) } -func (s *Service) SendGetTransaction(_ context.Context, req *pb.SendTransactionRequest) (*pb.SendTransactionResponse, error) { +func (s *Service) SendGetTransaction(ctx context.Context, req *pb.SendTransactionRequest) (*pb.SendTransactionResponse, error) { + return s.SendTransaction(ctx, req) +} + +func (s *Service) SendTransaction(_ context.Context, req *pb.SendTransactionRequest) (*pb.SendTransactionResponse, error) { if len(req.Tx) < 3 { return new(pb.SendTransactionResponse), status.Error(codes.InvalidArgument, "invalid tx") } diff --git a/api/v2/service/ws.go b/api/v2/service/ws.go index 4387f134f..fde7a4a1e 100644 --- a/api/v2/service/ws.go +++ b/api/v2/service/ws.go @@ -35,7 +35,7 @@ func (s *Service) Subscribe(request *pb.SubscribeRequest, stream pb.ApiService_S return status.Error(codes.Internal, err.Error()) } defer func() { - if err := s.client.UnsubscribeAll(stream.Context(), subscriber); err != nil { + if err := s.client.UnsubscribeAll(context.Background(), subscriber); err != nil { s.client.Logger.Error(err.Error()) } }() diff --git a/api/v2/v2.go b/api/v2/v2.go index a2667aeb1..c163db571 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -4,6 +4,9 @@ import ( "context" "github.com/MinterTeam/minter-go-node/api/v2/service" gw "github.com/MinterTeam/node-grpc-gateway/api_pb" + "github.com/gorilla/handlers" + "github.com/grpc-ecosystem/go-grpc-middleware" + grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/tmc/grpc-websocket-proxy/wsproxy" @@ -11,17 +14,24 @@ import ( "google.golang.org/grpc" "net" "net/http" + "os" ) -func Run(srv *service.Service, addrGRPC, addrApi string) error { +func Run(srv *service.Service, addrGRPC, addrApi string, traceLog bool) error { lis, err := net.Listen("tcp", addrGRPC) if err != nil { return err } grpcServer := grpc.NewServer( - grpc.StreamInterceptor(grpc_prometheus.StreamServerInterceptor), - grpc.UnaryInterceptor(grpc_prometheus.UnaryServerInterceptor), + grpc_middleware.WithStreamServerChain( + grpc_prometheus.StreamServerInterceptor, + grpc_recovery.StreamServerInterceptor(), + ), + grpc_middleware.WithUnaryServerChain( + grpc_prometheus.UnaryServerInterceptor, + grpc_recovery.UnaryServerInterceptor(), + ), ) gw.RegisterApiServiceServer(grpcServer, srv) grpc_prometheus.Register(grpcServer) @@ -35,21 +45,25 @@ func Run(srv *service.Service, addrGRPC, addrApi string) error { ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() - mux := runtime.NewServeMux(runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{OrigName: true, EmitDefaults: true})) + gwmux := runtime.NewServeMux(runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{OrigName: true, EmitDefaults: true})) opts := []grpc.DialOption{ grpc.WithInsecure(), grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(50000000)), } group.Go(func() error { - return gw.RegisterApiServiceHandlerFromEndpoint(ctx, mux, addrGRPC, opts) + return gw.RegisterApiServiceHandlerFromEndpoint(ctx, gwmux, addrGRPC, opts) }) + mux := http.NewServeMux() + handler := wsproxy.WebsocketProxy(gwmux) + + if traceLog { //todo + handler = handlers.CombinedLoggingHandler(os.Stdout, handler) + } + mux.Handle("/", handler) group.Go(func() error { return http.ListenAndServe(addrApi, mux) }) - group.Go(func() error { - return http.ListenAndServe(addrApi, wsproxy.WebsocketProxy(mux)) - }) return group.Wait() } diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index bfa87bf51..9367924d9 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -121,7 +121,9 @@ func runNode(cmd *cobra.Command) error { if err != nil { logger.Error("Failed to parse API v2 address", err) } - logger.Error("Failed to start Api V2 in both gRPC and RESTful", api_v2.Run(srv, grpcUrl.Host, apiV2url.Host)) + traceLog := os.Getenv("API_V2_LOG_LEVEL") == "trace" + logger.Error("Failed to start Api V2 in both gRPC and RESTful", + api_v2.Run(srv, grpcUrl.Host, apiV2url.Host, traceLog)) }(service_api.NewService(amino.NewCodec(), app, client, node, cfg, version.Version)) go api_v1.RunAPI(app, client, cfg, logger) diff --git a/go.mod b/go.mod index ad4929638..74f36d732 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,9 @@ require ( github.com/go-kit/kit v0.10.0 github.com/golang/protobuf v1.3.4 github.com/google/uuid v1.1.1 + github.com/gorilla/handlers v1.4.2 github.com/gorilla/websocket v1.4.1 + github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/grpc-gateway v1.12.0 github.com/marcusolsson/tui-go v0.4.0 diff --git a/go.sum b/go.sum index ab0108620..dd9a4739b 100644 --- a/go.sum +++ b/go.sum @@ -187,6 +187,8 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg= +github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= @@ -195,6 +197,7 @@ github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= From d244ce0349dd7780a64b1957f0644b6ce97f97db Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 22 May 2020 17:22:40 +0300 Subject: [PATCH 026/426] update api gateway 1.1.2 --- api/v2/service/address.go | 7 ++++--- api/v2/service/addresses.go | 2 +- api/v2/service/block.go | 11 ++++++----- api/v2/service/candidate.go | 2 +- api/v2/service/candidates.go | 2 +- api/v2/service/coin_info.go | 2 +- api/v2/service/estimate_coin_buy.go | 2 +- api/v2/service/estimate_coin_sell.go | 2 +- api/v2/service/estimate_coin_sell_all.go | 2 +- api/v2/service/estimate_tx_commission.go | 2 +- api/v2/service/events.go | 3 ++- api/v2/service/gas.go | 2 +- api/v2/service/halts.go | 13 +++++++++++++ api/v2/service/service.go | 13 ------------- api/v2/service/validators.go | 2 +- api/v2/v2.go | 24 +++++++++++++++++++++--- cmd/minter/cmd/node.go | 4 ---- core/minter/minter.go | 11 +++++------ core/state/state.go | 7 +++++-- go.mod | 8 ++++---- go.sum | 15 +++++++++++---- tree/tree.go | 8 ++++++++ 22 files changed, 89 insertions(+), 55 deletions(-) create mode 100644 api/v2/service/halts.go diff --git a/api/v2/service/address.go b/api/v2/service/address.go index d2a2fc3d1..8def826d9 100644 --- a/api/v2/service/address.go +++ b/api/v2/service/address.go @@ -8,19 +8,20 @@ import ( pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "strings" ) func (s *Service) Address(_ context.Context, req *pb.AddressRequest) (*pb.AddressResponse, error) { - if len(req.Address) < 3 { + if !strings.HasPrefix(strings.Title(req.Address), "Mx") { return new(pb.AddressResponse), status.Error(codes.InvalidArgument, "invalid address") } decodeString, err := hex.DecodeString(req.Address[2:]) if err != nil { - return new(pb.AddressResponse), status.Error(codes.InvalidArgument, err.Error()) + return new(pb.AddressResponse), status.Error(codes.InvalidArgument, "invalid address") } - cState, err := s.getStateForHeight(req.Height) + cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.AddressResponse), status.Error(codes.NotFound, err.Error()) } diff --git a/api/v2/service/addresses.go b/api/v2/service/addresses.go index d3678e12d..614cdc3e2 100644 --- a/api/v2/service/addresses.go +++ b/api/v2/service/addresses.go @@ -11,7 +11,7 @@ import ( ) func (s *Service) Addresses(_ context.Context, req *pb.AddressesRequest) (*pb.AddressesResponse, error) { - cState, err := s.getStateForHeight(req.Height) + cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.AddressesResponse), status.Error(codes.NotFound, err.Error()) } diff --git a/api/v2/service/block.go b/api/v2/service/block.go index a443e24cd..845a27d5e 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -17,17 +17,18 @@ import ( ) func (s *Service) Block(_ context.Context, req *pb.BlockRequest) (*pb.BlockResponse, error) { - block, err := s.client.Block(&req.Height) + height := int64(req.Height) + block, err := s.client.Block(&height) if err != nil { return new(pb.BlockResponse), status.Error(codes.NotFound, "Block not found") } - blockResults, err := s.client.BlockResults(&req.Height) + blockResults, err := s.client.BlockResults(&height) if err != nil { return new(pb.BlockResponse), status.Error(codes.NotFound, "Block results not found") } - valHeight := req.Height - 1 + valHeight := height - 1 if valHeight < 1 { valHeight = 1 } @@ -76,7 +77,7 @@ func (s *Service) Block(_ context.Context, req *pb.BlockRequest) (*pb.BlockRespo var validators []*pb.BlockResponse_Validator var proposer string - if req.Height > 1 { + if height > 1 { p, err := getBlockProposer(block, totalValidators) if err != nil { return new(pb.BlockResponse), status.Error(codes.FailedPrecondition, err.Error()) @@ -119,7 +120,7 @@ func (s *Service) Block(_ context.Context, req *pb.BlockRequest) (*pb.BlockRespo Time: block.Block.Time.Format(time.RFC3339Nano), TransactionsCount: fmt.Sprintf("%d", len(block.Block.Txs)), Transactions: txs, - BlockReward: rewards.GetRewardForBlock(uint64(req.Height)).String(), + BlockReward: rewards.GetRewardForBlock(uint64(height)).String(), Size: fmt.Sprintf("%d", len(s.cdc.MustMarshalBinaryLengthPrefixed(block))), Proposer: proposer, Validators: validators, diff --git a/api/v2/service/candidate.go b/api/v2/service/candidate.go index 04ca8622e..146e5fb93 100644 --- a/api/v2/service/candidate.go +++ b/api/v2/service/candidate.go @@ -23,7 +23,7 @@ func (s *Service) Candidate(_ context.Context, req *pb.CandidateRequest) (*pb.Ca pubkey := types.BytesToPubkey(decodeString) - cState, err := s.getStateForHeight(req.Height) + cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.CandidateResponse), status.Error(codes.NotFound, err.Error()) } diff --git a/api/v2/service/candidates.go b/api/v2/service/candidates.go index ae95e2c55..bfbcc1cd5 100644 --- a/api/v2/service/candidates.go +++ b/api/v2/service/candidates.go @@ -8,7 +8,7 @@ import ( ) func (s *Service) Candidates(_ context.Context, req *pb.CandidatesRequest) (*pb.CandidatesResponse, error) { - cState, err := s.getStateForHeight(req.Height) + cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.CandidatesResponse), status.Error(codes.NotFound, err.Error()) } diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index 466714d5b..e5e2c45f3 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -10,7 +10,7 @@ import ( ) func (s *Service) CoinInfo(_ context.Context, req *pb.CoinInfoRequest) (*pb.CoinInfoResponse, error) { - cState, err := s.getStateForHeight(req.Height) + cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.CoinInfoResponse), status.Error(codes.NotFound, err.Error()) } diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index 721dfe09b..748a87d9c 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -14,7 +14,7 @@ import ( ) func (s *Service) EstimateCoinBuy(_ context.Context, req *pb.EstimateCoinBuyRequest) (*pb.EstimateCoinBuyResponse, error) { - cState, err := s.getStateForHeight(req.Height) + cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.EstimateCoinBuyResponse), status.Error(codes.NotFound, err.Error()) } diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index df7afc549..47041685d 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -14,7 +14,7 @@ import ( ) func (s *Service) EstimateCoinSell(_ context.Context, req *pb.EstimateCoinSellRequest) (*pb.EstimateCoinSellResponse, error) { - cState, err := s.getStateForHeight(req.Height) + cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.EstimateCoinSellResponse), status.Error(codes.NotFound, err.Error()) } diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index e663e6e0e..9a657aec7 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -14,7 +14,7 @@ import ( ) func (s *Service) EstimateCoinSellAll(_ context.Context, req *pb.EstimateCoinSellAllRequest) (*pb.EstimateCoinSellAllResponse, error) { - cState, err := s.getStateForHeight(req.Height) + cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.EstimateCoinSellAllResponse), status.Error(codes.NotFound, err.Error()) } diff --git a/api/v2/service/estimate_tx_commission.go b/api/v2/service/estimate_tx_commission.go index 8dd983d36..dae5884d2 100644 --- a/api/v2/service/estimate_tx_commission.go +++ b/api/v2/service/estimate_tx_commission.go @@ -13,7 +13,7 @@ import ( ) func (s *Service) EstimateTxCommission(_ context.Context, req *pb.EstimateTxCommissionRequest) (*pb.EstimateTxCommissionResponse, error) { - cState, err := s.getStateForHeight(req.Height) + cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.EstimateTxCommissionResponse), status.Error(codes.NotFound, err.Error()) } diff --git a/api/v2/service/events.go b/api/v2/service/events.go index eccce3bf2..88151587f 100644 --- a/api/v2/service/events.go +++ b/api/v2/service/events.go @@ -11,7 +11,8 @@ import ( ) func (s *Service) Events(_ context.Context, req *pb.EventsRequest) (*pb.EventsResponse, error) { - events := s.blockchain.GetEventsDB().LoadEvents(req.Height) + height := uint32(req.Height) + events := s.blockchain.GetEventsDB().LoadEvents(height) resultEvents := make([]*pb.EventsResponse_Event, 0, len(events)) for _, event := range events { byteData, err := json.Marshal(event) diff --git a/api/v2/service/gas.go b/api/v2/service/gas.go index 7fde75c2d..0ab52d12d 100644 --- a/api/v2/service/gas.go +++ b/api/v2/service/gas.go @@ -16,7 +16,7 @@ func (s *Service) MinGasPrice(context.Context, *empty.Empty) (*pb.MinGasPriceRes } func (s *Service) MaxGas(_ context.Context, req *pb.MaxGasRequest) (*pb.MaxGasResponse, error) { - cState, err := s.getStateForHeight(req.Height) + cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.MaxGasResponse), status.Error(codes.NotFound, err.Error()) } diff --git a/api/v2/service/halts.go b/api/v2/service/halts.go new file mode 100644 index 000000000..3b7bc6023 --- /dev/null +++ b/api/v2/service/halts.go @@ -0,0 +1,13 @@ +package service + +import ( + "context" + "fmt" + pb "github.com/MinterTeam/node-grpc-gateway/api_pb" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (s *Service) Halts(_ context.Context, _ *pb.HaltsRequest) (*pb.HaltsResponse, error) { + return &pb.HaltsResponse{}, status.Error(codes.Unimplemented, fmt.Sprintf("method Halts not implemented in version %s", s.version)) +} diff --git a/api/v2/service/service.go b/api/v2/service/service.go index 697743359..996378e37 100644 --- a/api/v2/service/service.go +++ b/api/v2/service/service.go @@ -4,7 +4,6 @@ import ( "bytes" "github.com/MinterTeam/minter-go-node/config" "github.com/MinterTeam/minter-go-node/core/minter" - "github.com/MinterTeam/minter-go-node/core/state" "github.com/golang/protobuf/jsonpb" _struct "github.com/golang/protobuf/ptypes/struct" "github.com/tendermint/go-amino" @@ -26,18 +25,6 @@ func NewService(cdc *amino.Codec, blockchain *minter.Blockchain, client *rpc.Loc return &Service{cdc: cdc, blockchain: blockchain, client: client, minterCfg: minterCfg, version: version, tmNode: node} } -func (s *Service) getStateForHeight(height int32) (*state.CheckState, error) { - if height > 0 { - cState, err := s.blockchain.GetStateForHeight(uint64(height)) - if err != nil { - return nil, err - } - return cState, nil - } - - return s.blockchain.CurrentState(), nil -} - func (s *Service) createError(statusErr *status.Status, data string) error { if len(data) == 0 { return statusErr.Err() diff --git a/api/v2/service/validators.go b/api/v2/service/validators.go index 57bbbfbcd..d0d75e19c 100644 --- a/api/v2/service/validators.go +++ b/api/v2/service/validators.go @@ -10,7 +10,7 @@ import ( ) func (s *Service) Validators(_ context.Context, req *pb.ValidatorsRequest) (*pb.ValidatorsResponse, error) { - height := req.Height + height := int64(req.Height) if height == 0 { height = int64(s.blockchain.Height()) } diff --git a/api/v2/v2.go b/api/v2/v2.go index 62266d7f4..6294594ae 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -4,14 +4,17 @@ import ( "context" "github.com/MinterTeam/minter-go-node/api/v2/service" gw "github.com/MinterTeam/node-grpc-gateway/api_pb" + _ "github.com/MinterTeam/node-grpc-gateway/statik" "github.com/gorilla/handlers" "github.com/grpc-ecosystem/go-grpc-middleware" grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/rakyll/statik/fs" "github.com/tmc/grpc-websocket-proxy/wsproxy" "golang.org/x/sync/errgroup" "google.golang.org/grpc" + "mime" "net" "net/http" "os" @@ -57,13 +60,13 @@ func Run(srv *service.Service, addrGRPC, addrApi string, traceLog bool) error { mux := http.NewServeMux() handler := wsproxy.WebsocketProxy(gwmux) - if traceLog { //todo + if traceLog { handler = handlers.CombinedLoggingHandler(os.Stdout, handler) } mux.Handle("/", handler) - allowCORS(mux) + serveOpenAPI(mux) group.Go(func() error { - return http.ListenAndServe(addrApi, mux) + return http.ListenAndServe(addrApi, allowCORS(mux)) }) return group.Wait() @@ -89,3 +92,18 @@ func preflightHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Methods", strings.Join(methods, ",")) return } + +func serveOpenAPI(mux *http.ServeMux) error { + mime.AddExtensionType(".svg", "image/svg+xml") + + statikFS, err := fs.New() + if err != nil { + return err + } + + // Expose files in static on /openapi-ui + fileServer := http.FileServer(statikFS) + prefix := "/openapi-ui/" + mux.Handle(prefix, http.StripPrefix(prefix, fileServer)) + return nil +} diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index 7b96a8a24..2d9270830 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -95,10 +95,6 @@ func runNode(cmd *cobra.Command) error { return err } - if cfg.StateKeepEver < 1 { - panic("state_keep_ever field should be greater than 0") - } - app := minter.NewMinterBlockchain(cfg) // update BlocksTimeDelta in case it was corrupted diff --git a/core/minter/minter.go b/core/minter/minter.go index 9fa210033..73d5ad294 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -2,6 +2,7 @@ package minter import ( "bytes" + "errors" "fmt" eventsdb "github.com/MinterTeam/events-db" "github.com/MinterTeam/minter-go-node/cmd/utils" @@ -25,7 +26,6 @@ import ( cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" "github.com/tendermint/tendermint/evidence" tmNode "github.com/tendermint/tendermint/node" - rpctypes "github.com/tendermint/tendermint/rpc/lib/types" types2 "github.com/tendermint/tendermint/types" "github.com/tendermint/tm-db" "google.golang.org/grpc/codes" @@ -506,13 +506,12 @@ func (app *Blockchain) CurrentState() *state.CheckState { // Get immutable state of Minter Blockchain for given height func (app *Blockchain) GetStateForHeight(height uint64) (*state.CheckState, error) { - app.lock.RLock() - defer app.lock.RUnlock() - - if height != 0 { + if height > 0 { + app.lock.RLock() + defer app.lock.RUnlock() s, err := state.NewCheckStateAtHeight(height, app.stateDB) if err != nil { - return nil, rpctypes.RPCError{Code: 404, Message: "State at given height not found", Data: err.Error()} + return nil, errors.New("state at given height not found") } return s, nil } diff --git a/core/state/state.go b/core/state/state.go index b4e71d972..47eb09da4 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -196,8 +196,11 @@ func (s *State) Commit() ([]byte, error) { hash, version, err := s.tree.SaveVersion() - if s.keepLastStates < version-1 { - _ = s.tree.DeleteVersion(version - s.keepLastStates) + versions := s.tree.AvailableVersions() + for _, v := range versions { + if v < int(version-s.keepLastStates) { + _ = s.tree.DeleteVersion(int64(v)) + } } return hash, err diff --git a/go.mod b/go.mod index 45d1b108d..ef02b08af 100644 --- a/go.mod +++ b/go.mod @@ -4,21 +4,21 @@ go 1.13 require ( github.com/MinterTeam/events-db v0.1.6 - github.com/MinterTeam/node-grpc-gateway v1.0.0 + github.com/MinterTeam/node-grpc-gateway v1.1.2 github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 - github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b - github.com/golang/protobuf v1.3.4 + github.com/golang/protobuf v1.3.5 github.com/google/uuid v1.1.1 github.com/gorilla/handlers v1.4.2 github.com/gorilla/websocket v1.4.1 github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 - github.com/grpc-ecosystem/grpc-gateway v1.12.0 + github.com/grpc-ecosystem/grpc-gateway v1.14.3 github.com/marcusolsson/tui-go v0.4.0 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.5.1 + github.com/rakyll/statik v0.1.7 github.com/rs/cors v1.7.0 github.com/spf13/cobra v0.0.6 github.com/spf13/viper v1.6.2 diff --git a/go.sum b/go.sum index dd9a4739b..d7763fc2c 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,8 @@ github.com/MinterTeam/minter-go-node v1.0.5-0.20191113110340-a46b8ef88084/go.mod github.com/MinterTeam/minter-go-node v1.1.0-beta5/go.mod h1:MeO8y1SPL2uk/znxFPauMB4karv/xQeI1O1SPeEycrU= github.com/MinterTeam/minter-node-cli v0.0.0-20191202172005-309e9d40a5a3 h1:2ndNow11LzKNggx2JNh2Fhb0NKEQ2kVt+HL9jdEBLOg= github.com/MinterTeam/minter-node-cli v0.0.0-20191202172005-309e9d40a5a3/go.mod h1:6iFtZjWsvR9ZaXaogfDkIYVSrQAHQBk/tU1L5yKS5/8= -github.com/MinterTeam/node-grpc-gateway v1.0.0 h1:E2Vn3wC0kv/zgzA1biC84+M2Y4h0k2etLXzTM6jJyeI= -github.com/MinterTeam/node-grpc-gateway v1.0.0/go.mod h1:LJJNHzYkAbWsoWZw3VMgs+NQTnJ3f0YawF2UZxevTOE= +github.com/MinterTeam/node-grpc-gateway v1.1.2 h1:kHwlqPlKXFZX+SjUjqGp4c7pmONhM438EzUyJV8hKyg= +github.com/MinterTeam/node-grpc-gateway v1.1.2/go.mod h1:tfJiYOCloZD+Q8nSplqVQFQNs3ggFgBBVQa0hOVCsjg= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= @@ -163,6 +163,8 @@ github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -204,8 +206,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0 h1:bM6ZAFZmc/wPFaRDi0d5L7hGEZEx/2u+Tmr2evNHDiI= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.12.0 h1:SFRyYOyhgiU1kJG/PmbkWP/iSlizvDJEz531dq5kneg= -github.com/grpc-ecosystem/grpc-gateway v1.12.0/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= +github.com/grpc-ecosystem/grpc-gateway v1.14.3 h1:OCJlWkOUoTnl0neNGlf4fUm3TmbEtguw7vR+nGtnDjY= +github.com/grpc-ecosystem/grpc-gateway v1.14.3/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f h1:8N8XWLZelZNibkhM1FuF+3Ad3YIbgirjdMiVA0eUkaM= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= @@ -391,6 +393,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= +github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165 h1:nkcn14uNmFEuGCb2mBZbBb24RdNRL08b/wb+xBOYpuk= github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ= @@ -630,6 +634,8 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2El google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c h1:hrpEMCZ2O7DR5gC1n2AJGVhrwiEjOi35+jxtIuZpTMo= google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940 h1:MRHtG0U6SnaUb+s+LhNE1qt1FQ1wlhqr5E4usBKC0uA= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/grpc v1.13.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -647,6 +653,7 @@ google.golang.org/grpc v1.25.0/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= diff --git a/tree/tree.go b/tree/tree.go index 10fb38bdb..00c7ff308 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -12,6 +12,7 @@ type ReadOnlyTree interface { Hash() []byte Iterate(fn func(key []byte, value []byte) bool) (stopped bool) KeepLastHeight() int + AvailableVersions() []int } type MTree interface { @@ -144,6 +145,13 @@ func (t *mutableTree) KeepLastHeight() int { } return prev } +func (t *mutableTree) AvailableVersions() []int { + t.lock.Lock() + defer t.lock.Unlock() + + return t.tree.AvailableVersions() + +} func NewImmutableTree(db dbm.DB) *ImmutableTree { return &ImmutableTree{ From b817cb50cb3299f77b511983f647e35f6b8c1375 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 22 May 2020 19:55:01 +0300 Subject: [PATCH 027/426] fix state versions --- core/minter/minter.go | 2 +- core/state/state.go | 13 +++++-------- core/state/state_test.go | 2 +- tree/tree.go | 7 ++++++- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index 8a95a0f67..68b81b771 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -453,7 +453,7 @@ func (app *Blockchain) Commit() abciTypes.ResponseCommit { } // Committing Minter Blockchain state - hash, err := app.stateDeliver.Commit() + hash, err := app.stateDeliver.Commit(app.height) if err != nil { panic(err) } diff --git a/core/state/state.go b/core/state/state.go index 47eb09da4..43905edda 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -99,11 +99,7 @@ type State struct { func (s *State) isValue_State() {} func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, keepEvery, keepRecent int64) (*State, error) { - iavlTree := tree.NewMutableTree(db, cacheSize, keepEvery, keepRecent) - _, err := iavlTree.LoadVersion(int64(height)) - if err != nil { - return nil, err - } + iavlTree := tree.NewMutableTree(height, db, cacheSize, keepEvery, keepRecent) state, err := newStateForTree(iavlTree, events, db, keepRecent) if err != nil { @@ -118,7 +114,7 @@ func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, } func NewCheckStateAtHeight(height uint64, db db.DB) (*CheckState, error) { - iavlTree := tree.NewMutableTree(db, 1024, 1, 0) + iavlTree := tree.NewMutableTree(0, db, 1024, 1, 0) _, err := iavlTree.LazyLoadVersion(int64(height)) if err != nil { return nil, err @@ -163,7 +159,7 @@ func (s *State) Check() error { return nil } -func (s *State) Commit() ([]byte, error) { +func (s *State) Commit(height uint64) ([]byte, error) { s.Checker.Reset() if err := s.Accounts.Commit(); err != nil { @@ -194,9 +190,10 @@ func (s *State) Commit() ([]byte, error) { return nil, err } + versions := s.tree.AvailableVersions() + hash, version, err := s.tree.SaveVersion() - versions := s.tree.AvailableVersions() for _, v := range versions { if v < int(version-s.keepLastStates) { _ = s.tree.DeleteVersion(int64(v)) diff --git a/core/state/state_test.go b/core/state/state_test.go index 6e79377f4..fb70cbefb 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -81,7 +81,7 @@ func TestStateExport(t *testing.T) { state.Checks.UseCheck(newCheck) - _, err = state.Commit() + _, err = state.Commit(height) if err != nil { log.Panicf("Cannot commit state: %s", err) } diff --git a/tree/tree.go b/tree/tree.go index 00c7ff308..2f592d708 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -27,12 +27,17 @@ type MTree interface { GetImmutableAtHeight(version int64) (*ImmutableTree, error) } -func NewMutableTree(db dbm.DB, cacheSize int, keepEvery, keepRecent int64) MTree { +func NewMutableTree(height uint64, db dbm.DB, cacheSize int, keepEvery, keepRecent int64) MTree { tree, err := iavl.NewMutableTreeWithOpts(db, dbm.NewMemDB(), cacheSize, iavl.PruningOptions(keepEvery, keepRecent)) if err != nil { panic(err) } + _, err = tree.LoadVersionForOverwriting(int64(height)) + if err != nil { + panic(err) + } + return &mutableTree{ tree: tree, } From 882777c495f4f41d5d39aa607446d9d7c800bb7c Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 22 May 2020 20:00:35 +0300 Subject: [PATCH 028/426] clean up --- core/minter/minter.go | 2 +- core/state/state.go | 2 +- core/state/state_test.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index 68b81b771..8a95a0f67 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -453,7 +453,7 @@ func (app *Blockchain) Commit() abciTypes.ResponseCommit { } // Committing Minter Blockchain state - hash, err := app.stateDeliver.Commit(app.height) + hash, err := app.stateDeliver.Commit() if err != nil { panic(err) } diff --git a/core/state/state.go b/core/state/state.go index 43905edda..34fef337a 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -159,7 +159,7 @@ func (s *State) Check() error { return nil } -func (s *State) Commit(height uint64) ([]byte, error) { +func (s *State) Commit() ([]byte, error) { s.Checker.Reset() if err := s.Accounts.Commit(); err != nil { diff --git a/core/state/state_test.go b/core/state/state_test.go index fb70cbefb..6e79377f4 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -81,7 +81,7 @@ func TestStateExport(t *testing.T) { state.Checks.UseCheck(newCheck) - _, err = state.Commit(height) + _, err = state.Commit() if err != nil { log.Panicf("Cannot commit state: %s", err) } From 582cdff9757811e4525932a027250de530f71ec9 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 9 Jun 2020 14:25:28 +0300 Subject: [PATCH 029/426] Add cli command for prune blocks. Update tendermint modules --- api/api.go | 4 +-- api/v2/service/service.go | 2 +- cli/service/service.go | 11 +++++-- cmd/minter/cmd/node.go | 8 +++-- cmd/minter/cmd/show_validator.go | 6 +++- core/minter/minter.go | 28 +++++++++++++++++ core/state/state.go | 13 +++----- core/statistics/statistics.go | 2 +- go.mod | 24 +++++++-------- go.sum | 53 +++++++++++++++++++++++++++++--- rpc/lib/rpc_test.go | 28 ++++++++--------- tree/tree.go | 9 +++--- 12 files changed, 134 insertions(+), 54 deletions(-) diff --git a/api/api.go b/api/api.go index 5f9628cc6..80e7c86e6 100644 --- a/api/api.go +++ b/api/api.go @@ -15,7 +15,7 @@ import ( "github.com/tendermint/tendermint/crypto/secp256k1" "github.com/tendermint/tendermint/evidence" "github.com/tendermint/tendermint/libs/log" - rpc "github.com/tendermint/tendermint/rpc/client" + rpc "github.com/tendermint/tendermint/rpc/client/local" "github.com/tendermint/tendermint/types" "net/http" "net/url" @@ -27,7 +27,6 @@ var ( cdc = amino.NewCodec() blockchain *minter.Blockchain client *rpc.Local - minterCfg *config.Config ) var Routes = map[string]*rpcserver.RPCFunc{ @@ -66,7 +65,6 @@ func responseTime(b *minter.Blockchain) func(f func(http.ResponseWriter, *http.R } func RunAPI(b *minter.Blockchain, tmRPC *rpc.Local, cfg *config.Config, logger log.Logger) { - minterCfg = cfg RegisterCryptoAmino(cdc) eventsdb.RegisterAminoEvents(cdc) RegisterEvidenceMessages(cdc) diff --git a/api/v2/service/service.go b/api/v2/service/service.go index 996378e37..a34e83ff6 100644 --- a/api/v2/service/service.go +++ b/api/v2/service/service.go @@ -8,7 +8,7 @@ import ( _struct "github.com/golang/protobuf/ptypes/struct" "github.com/tendermint/go-amino" tmNode "github.com/tendermint/tendermint/node" - rpc "github.com/tendermint/tendermint/rpc/client" + rpc "github.com/tendermint/tendermint/rpc/client/local" "google.golang.org/grpc/status" ) diff --git a/cli/service/service.go b/cli/service/service.go index 593a30487..0fe8305f3 100644 --- a/cli/service/service.go +++ b/cli/service/service.go @@ -10,7 +10,7 @@ import ( "github.com/MinterTeam/minter-go-node/version" "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/empty" - rpc "github.com/tendermint/tendermint/rpc/client" + rpc "github.com/tendermint/tendermint/rpc/client/local" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "runtime" @@ -117,7 +117,7 @@ func (m *Manager) Status(context.Context, *empty.Empty) (*pb.StatusResponse, err Version: version.Version, LatestBlockHash: fmt.Sprintf("%X", resultStatus.SyncInfo.LatestBlockHash), LatestAppHash: fmt.Sprintf("%X", resultStatus.SyncInfo.LatestAppHash), - KeepLastStates: int64(m.blockchain.CurrentState().Tree().KeepLastHeight()), + KeepLastStates: m.blockchain.CurrentState().Tree().KeepLastHeight(), LatestBlockHeight: resultStatus.SyncInfo.LatestBlockHeight, LatestBlockTime: resultStatus.SyncInfo.LatestBlockTime.Format(time.RFC3339), TmStatus: &pb.StatusResponse_TmStatus{ @@ -245,7 +245,12 @@ func (m *Manager) NetInfo(context.Context, *empty.Empty) (*pb.NetInfoResponse, e } func (m *Manager) PruneBlocks(ctx context.Context, req *pb.PruneBlocksRequest) (*empty.Empty, error) { - return new(empty.Empty), status.Error(codes.Unimplemented, "todo") + res := new(empty.Empty) + err := m.blockchain.PruneBlocks(req.FromHeight, req.ToHeight) + if err != nil { + return res, status.Error(codes.FailedPrecondition, err.Error()) + } + return res, nil } func (m *Manager) DealPeer(ctx context.Context, req *pb.DealPeerRequest) (*empty.Empty, error) { diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index 2d9270830..a6b404cfd 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -22,7 +22,7 @@ import ( "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/privval" "github.com/tendermint/tendermint/proxy" - rpc "github.com/tendermint/tendermint/rpc/client" + rpc "github.com/tendermint/tendermint/rpc/client/local" "github.com/tendermint/tendermint/store" tmTypes "github.com/tendermint/tendermint/types" "io" @@ -95,6 +95,10 @@ func runNode(cmd *cobra.Command) error { return err } + if cfg.StateKeepEver < 1 { + logger.Error("state_keep_ever field should be greater than 0. All state will be stored in memory. Data will not be saved to disk.") + } + app := minter.NewMinterBlockchain(cfg) // update BlocksTimeDelta in case it was corrupted @@ -103,7 +107,7 @@ func runNode(cmd *cobra.Command) error { // start TM node node := startTendermintNode(app, tmConfig, logger) - client := rpc.NewLocal(node) + client := rpc.New(node) app.SetTmNode(node) diff --git a/cmd/minter/cmd/show_validator.go b/cmd/minter/cmd/show_validator.go index ada67b4bc..0b2c4e3d8 100644 --- a/cmd/minter/cmd/show_validator.go +++ b/cmd/minter/cmd/show_validator.go @@ -29,6 +29,10 @@ func showValidator(cmd *cobra.Command, args []string) error { } pv := privval.LoadFilePV(keyFilePath, cfg.PrivValidatorStateFile()) - fmt.Printf("Mp%x\n", pv.GetPubKey().Bytes()[5:]) + key, err := pv.GetPubKey() + if err != nil { + panic(err) + } + fmt.Printf("Mp%x\n", key.Bytes()[5:]) return nil } diff --git a/core/minter/minter.go b/core/minter/minter.go index 8a95a0f67..30a042cb8 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -671,6 +671,7 @@ func (app *Blockchain) GetValidatorStatus(address types.TmAddress) int8 { defer app.lock.RUnlock() return app.validatorsStatuses[address] } + func (app *Blockchain) MaxPeerHeight() int64 { var max int64 for _, peer := range app.tmNode.Switch().Peers().List() { @@ -682,6 +683,33 @@ func (app *Blockchain) MaxPeerHeight() int64 { return max } +func (app *Blockchain) PruneBlocks(from int64, to int64) error { + app.stateDeliver.Lock() + defer app.stateDeliver.Unlock() + + versions := app.stateDeliver.Tree().AvailableVersions() + + lastSnapshotVersion := app.appDB.GetLastHeight() + if uint64(to) >= lastSnapshotVersion { + return fmt.Errorf("cannot delete last version saved in disk (%d)", lastSnapshotVersion) + } + + for _, v := range versions { + v := int64(v) + if v < from { + continue + } + if v >= to { + break + } + if err := app.stateDeliver.Tree().DeleteVersion(v); err != nil { + return err + } + } + + return nil +} + func getDbOpts(memLimit int) *opt.Options { if memLimit < 1024 { panic(fmt.Sprintf("Not enough memory given to StateDB. Expected >1024M, given %d", memLimit)) diff --git a/core/state/state.go b/core/state/state.go index 34fef337a..3f7924b89 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -190,17 +190,12 @@ func (s *State) Commit() ([]byte, error) { return nil, err } - versions := s.tree.AvailableVersions() - - hash, version, err := s.tree.SaveVersion() - - for _, v := range versions { - if v < int(version-s.keepLastStates) { - _ = s.tree.DeleteVersion(int64(v)) - } + hash, _, err := s.tree.SaveVersion() + if err != nil { + return hash, err } - return hash, err + return hash, nil } func (s *State) Import(state types.AppState) error { diff --git a/core/statistics/statistics.go b/core/statistics/statistics.go index c7f254158..050d554b3 100644 --- a/core/statistics/statistics.go +++ b/core/statistics/statistics.go @@ -4,7 +4,7 @@ import ( "context" "github.com/prometheus/client_golang/prometheus" "github.com/tendermint/tendermint/rpc/core" - rpctypes "github.com/tendermint/tendermint/rpc/lib/types" + rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types" "net" "net/url" "runtime" diff --git a/go.mod b/go.mod index ef02b08af..0933fcb33 100644 --- a/go.mod +++ b/go.mod @@ -5,13 +5,13 @@ go 1.13 require ( github.com/MinterTeam/events-db v0.1.6 github.com/MinterTeam/node-grpc-gateway v1.1.2 - github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d + github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 - github.com/golang/protobuf v1.3.5 + github.com/golang/protobuf v1.4.0 github.com/google/uuid v1.1.1 github.com/gorilla/handlers v1.4.2 - github.com/gorilla/websocket v1.4.1 + github.com/gorilla/websocket v1.4.2 github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/grpc-gateway v1.14.3 @@ -20,20 +20,20 @@ require ( github.com/prometheus/client_golang v1.5.1 github.com/rakyll/statik v0.1.7 github.com/rs/cors v1.7.0 - github.com/spf13/cobra v0.0.6 - github.com/spf13/viper v1.6.2 + github.com/spf13/cobra v1.0.0 + github.com/spf13/viper v1.6.3 github.com/stretchr/testify v1.5.1 github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d github.com/tendermint/go-amino v0.15.1 - github.com/tendermint/iavl v0.13.2 - github.com/tendermint/tendermint v0.33.3 - github.com/tendermint/tm-db v0.5.0 + github.com/tendermint/iavl v0.13.3 + github.com/tendermint/tendermint v0.33.5 + github.com/tendermint/tm-db v0.5.1 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 github.com/urfave/cli/v2 v2.0.0 - golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 - golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 + golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 + golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e - golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 - google.golang.org/grpc v1.28.0 + golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd + google.golang.org/grpc v1.28.1 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 ) diff --git a/go.sum b/go.sum index d7763fc2c..14d21f297 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/ChainSafe/go-schnorrkel v0.0.0-20200102211924-4bcbc698314f h1:4O1om+UVU+Hfcihr1timk8YNXHxzZWgCo7ofnrZRApw= github.com/ChainSafe/go-schnorrkel v0.0.0-20200102211924-4bcbc698314f/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= +github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= +github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/MinterTeam/events-db v0.1.0/go.mod h1:ZnKNYUSFUgVTTB359LvKQbroYqBiriXmbnyaMsULU2o= github.com/MinterTeam/events-db v0.1.1-0.20191113155258-73206cb9a3ea/go.mod h1:INfo4gbiX8/EGfjHmRvvW2+5YuOcTy7Tob69yUhAqU4= @@ -25,6 +27,7 @@ github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMx github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= +github.com/Workiva/go-datastructures v1.0.52 h1:PLSK6pwn8mYdaoaCZEMsXBpBotr4HHn9abU0yMQt0NI= github.com/Workiva/go-datastructures v1.0.52/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= @@ -51,9 +54,14 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d h1:xG8Pj6Y6J760xwETNmMzmlt38QSwz0BLp1cZ09g27uw= github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0= +github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a h1:RQMUrEILyYJEoAT34XS/kLu40vC0+po/UfxrBBA4qZE= github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= @@ -75,6 +83,7 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= @@ -165,6 +174,12 @@ github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -198,6 +213,8 @@ github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -210,6 +227,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.14.3 h1:OCJlWkOUoTnl0neNGlf4fUm3TmbEtg github.com/grpc-ecosystem/grpc-gateway v1.14.3/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f h1:8N8XWLZelZNibkhM1FuF+3Ad3YIbgirjdMiVA0eUkaM= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= +github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= @@ -298,6 +317,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= +github.com/minio/highwayhash v1.0.0 h1:iMSDhgUILCr0TNm8LWlSjF8N0ZIj2qbO8WHp6Q/J2BA= +github.com/minio/highwayhash v1.0.0/go.mod h1:xQboMTeM9nY9v/LlAOxFctujiv5+Aq2hR5dxBpaMbdc= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -399,6 +420,8 @@ github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165 h1:nkcn14uNmFE github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= +github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -434,6 +457,8 @@ github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.6 h1:breEStsVwemnKh2/s6gMvSdMEkwW0sK8vGStnlVBMCs= github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -445,6 +470,8 @@ github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/y github.com/spf13/viper v1.5.0/go.mod h1:AkYRkVJF8TkSG/xet6PzXX+l39KhhXa2pdqVSxnTcn4= github.com/spf13/viper v1.6.2 h1:7aKfF+e8/k68gda3LOjo5RxiUqddoFxVq4BKBPrxk5E= github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= +github.com/spf13/viper v1.6.3 h1:pDDu1OyEDTKzpJwdq4TiuLyMsUgRa/BT5cn5O62NoHs= +github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -473,8 +500,8 @@ github.com/tendermint/go-amino v0.15.1 h1:D2uk35eT4iTsvJd9jWIetzthE5C0/k2QmMFkCN github.com/tendermint/go-amino v0.15.1/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= github.com/tendermint/iavl v0.12.4 h1:hd1woxUGISKkfUWBA4mmmTwOua6PQZTJM/F0FDrmMV8= github.com/tendermint/iavl v0.12.4/go.mod h1:8LHakzt8/0G3/I8FUU0ReNx98S/EP6eyPJkAUvEXT/o= -github.com/tendermint/iavl v0.13.2 h1:O1m08/Ciy53l9IYmf75uIRVvrNsfjEbre8u/yCu/oqk= -github.com/tendermint/iavl v0.13.2/go.mod h1:vE1u0XAGXYjHykd4BLp8p/yivrw2PF1TuoljBcsQoGA= +github.com/tendermint/iavl v0.13.3 h1:expgBDY1MX+6/3sqrIxGChbTNf9N9aTJ67SH4bPchCs= +github.com/tendermint/iavl v0.13.3/go.mod h1:2lE7GiWdSvc7kvT78ncIKmkOjCnp6JEnSb2O7B9htLw= github.com/tendermint/tendermint v0.32.1/go.mod h1:jmPDAKuNkev9793/ivn/fTBnfpA9mGBww8MPRNPNxnU= github.com/tendermint/tendermint v0.32.6 h1:HozXi0USWvKrWuEh5ratnJV10ykkTy4nwXUi0UvPVzg= github.com/tendermint/tendermint v0.32.6/go.mod h1:D2+A3pNjY+Po72X0mTfaXorFhiVI8dh/Zg640FGyGtE= @@ -483,6 +510,8 @@ github.com/tendermint/tendermint v0.33.2 h1:NzvRMTuXJxqSsFed2J7uHmMU5N1CVzSpfi3n github.com/tendermint/tendermint v0.33.2/go.mod h1:25DqB7YvV1tN3tHsjWoc2vFtlwICfrub9XO6UBO+4xk= github.com/tendermint/tendermint v0.33.3 h1:6lMqjEoCGejCzAghbvfQgmw87snGSqEhDTo/jw+W8CI= github.com/tendermint/tendermint v0.33.3/go.mod h1:25DqB7YvV1tN3tHsjWoc2vFtlwICfrub9XO6UBO+4xk= +github.com/tendermint/tendermint v0.33.5 h1:jYgRd9ImkzA9iOyhpmgreYsqSB6tpDa6/rXYPb8HKE8= +github.com/tendermint/tendermint v0.33.5/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM= github.com/tendermint/tm-db v0.1.1/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw= github.com/tendermint/tm-db v0.2.0 h1:rJxgdqn6fIiVJZy4zLpY1qVlyD0TU6vhkT4kEf71TQQ= github.com/tendermint/tm-db v0.2.0/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw= @@ -490,8 +519,8 @@ github.com/tendermint/tm-db v0.4.0 h1:iPbCcLbf4nwDFhS39Zo1lpdS1X/cT9CkTlUx17FHQg github.com/tendermint/tm-db v0.4.0/go.mod h1:+Cwhgowrf7NBGXmsqFMbwEtbo80XmyrlY5Jsk95JubQ= github.com/tendermint/tm-db v0.4.1 h1:TvX7JWjJOVZ+N3y+I86wddrGttOdMmmBxXcu0/Y7ZJ0= github.com/tendermint/tm-db v0.4.1/go.mod h1:JsJ6qzYkCGiGwm5GHl/H5GLI9XLb6qZX7PRe425dHAY= -github.com/tendermint/tm-db v0.5.0 h1:qtM5UTr1dlRnHtDY6y7MZO5Di8XAE2j3lc/pCnKJ5hQ= -github.com/tendermint/tm-db v0.5.0/go.mod h1:lSq7q5WRR/njf1LnhiZ/lIJHk2S8Y1Zyq5oP/3o9C2U= +github.com/tendermint/tm-db v0.5.1 h1:H9HDq8UEA7Eeg13kdYckkgwwkQLBnJGgX4PgLJRhieY= +github.com/tendermint/tm-db v0.5.1/go.mod h1:g92zWjHpCYlEvQXvy9M168Su8V1IBEeawpXVVBaK4f4= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -530,6 +559,9 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 h1:DOmugCavvUtnUD114C1Wh+UgTgQZ4pMLzXxi1pSt+/Y= +golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -561,6 +593,8 @@ golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 h1:2mqDk8w/o6UmeUCu5Qiq2y7iMf6anbx+YA8d1JFoFrs= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -579,6 +613,7 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -594,6 +629,8 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgmDSfjglYZ3vStQ/gSCU= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= @@ -658,6 +695,14 @@ google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k= +google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 h1:FVCohIoYO7IJoDDVpV2pdq7SgrMH6wHnuTyrdrxJNoY= gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtWgA5THM5lhBAw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= diff --git a/rpc/lib/rpc_test.go b/rpc/lib/rpc_test.go index 7b1cfbf94..d95f22094 100644 --- a/rpc/lib/rpc_test.go +++ b/rpc/lib/rpc_test.go @@ -18,12 +18,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - amino "github.com/tendermint/go-amino" + "github.com/tendermint/go-amino" "github.com/tendermint/tendermint/libs/log" - client "github.com/tendermint/tendermint/rpc/lib/client" - server "github.com/tendermint/tendermint/rpc/lib/server" - types "github.com/tendermint/tendermint/rpc/lib/types" + "github.com/tendermint/tendermint/rpc/jsonrpc/client" + "github.com/tendermint/tendermint/rpc/jsonrpc/server" + "github.com/tendermint/tendermint/rpc/jsonrpc/types" ) // Client and Server should work over tcp or unix sockets @@ -127,7 +127,7 @@ func setup() { if err != nil { panic(err) } - go server.StartHTTPServer(listener1, mux, tcpLogger, config) + go server.Serve(listener1, mux, tcpLogger, config) unixLogger := logger.With("socket", "unix") mux2 := http.NewServeMux() @@ -139,7 +139,7 @@ func setup() { if err != nil { panic(err) } - go server.StartHTTPServer(listener2, mux2, unixLogger, config) + go server.Serve(listener2, mux2, unixLogger, config) // wait for servers to start time.Sleep(time.Second * 2) @@ -272,15 +272,15 @@ func testWithWSClient(t *testing.T, cl *client.WSClient) { func TestServersAndClientsBasic(t *testing.T) { serverAddrs := [...]string{tcpAddr, unixAddr} for _, addr := range serverAddrs { - cl1, _ := client.NewURIClient(addr) + cl1, _ := client.NewURI(addr) fmt.Printf("=== testing server on %s using URI client", addr) testWithHTTPClient(t, cl1) - cl2, _ := client.NewJSONRPCClient(addr) + cl2, _ := client.New(addr) fmt.Printf("=== testing server on %s using JSONRPC client", addr) testWithHTTPClient(t, cl2) - cl3, _ := client.NewWSClient(addr, websocketEndpoint) + cl3, _ := client.NewWS(addr, websocketEndpoint) cl3.SetLogger(log.TestingLogger()) err := cl3.Start() require.Nil(t, err) @@ -291,7 +291,7 @@ func TestServersAndClientsBasic(t *testing.T) { } func TestHexStringArg(t *testing.T) { - cl, _ := client.NewURIClient(tcpAddr) + cl, _ := client.NewURI(tcpAddr) // should NOT be handled as hex val := "0xabc" got, err := echoViaHTTP(cl, val) @@ -300,7 +300,7 @@ func TestHexStringArg(t *testing.T) { } func TestQuotedStringArg(t *testing.T) { - cl, _ := client.NewURIClient(tcpAddr) + cl, _ := client.NewURI(tcpAddr) // should NOT be unquoted val := "\"abc\"" got, err := echoViaHTTP(cl, val) @@ -309,7 +309,7 @@ func TestQuotedStringArg(t *testing.T) { } func TestWSNewWSRPCFunc(t *testing.T) { - cl, _ := client.NewWSClient(tcpAddr, websocketEndpoint) + cl, _ := client.NewWS(tcpAddr, websocketEndpoint) cl.SetLogger(log.TestingLogger()) err := cl.Start() require.Nil(t, err) @@ -334,7 +334,7 @@ func TestWSNewWSRPCFunc(t *testing.T) { } func TestWSHandlesArrayParams(t *testing.T) { - cl, _ := client.NewWSClient(tcpAddr, websocketEndpoint) + cl, _ := client.NewWS(tcpAddr, websocketEndpoint) cl.SetLogger(log.TestingLogger()) err := cl.Start() require.Nil(t, err) @@ -359,7 +359,7 @@ func TestWSHandlesArrayParams(t *testing.T) { // TestWSClientPingPong checks that a client & server exchange pings // & pongs so connection stays alive. func TestWSClientPingPong(t *testing.T) { - cl, _ := client.NewWSClient(tcpAddr, websocketEndpoint) + cl, _ := client.NewWS(tcpAddr, websocketEndpoint) cl.SetLogger(log.TestingLogger()) err := cl.Start() require.Nil(t, err) diff --git a/tree/tree.go b/tree/tree.go index 2f592d708..430e1c270 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -11,7 +11,7 @@ type ReadOnlyTree interface { Version() int64 Hash() []byte Iterate(fn func(key []byte, value []byte) bool) (stopped bool) - KeepLastHeight() int + KeepLastHeight() int64 AvailableVersions() []int } @@ -45,7 +45,6 @@ func NewMutableTree(height uint64, db dbm.DB, cacheSize int, keepEvery, keepRece type mutableTree struct { tree *iavl.MutableTree - lock sync.RWMutex } @@ -136,7 +135,7 @@ func (t *mutableTree) DeleteVersion(version int64) error { return t.tree.DeleteVersion(version) } -func (t *mutableTree) KeepLastHeight() int { +func (t *mutableTree) KeepLastHeight() int64 { t.lock.Lock() defer t.lock.Unlock() @@ -148,8 +147,10 @@ func (t *mutableTree) KeepLastHeight() int { } prev = version } - return prev + + return int64(prev) } + func (t *mutableTree) AvailableVersions() []int { t.lock.Lock() defer t.lock.Unlock() From eaa2377fa359619b33e84067322d958d1270dcb1 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 9 Jun 2020 14:53:31 +0300 Subject: [PATCH 030/426] move events-db inside --- api/api.go | 2 +- api/events.go | 2 +- api/v2/service/events.go | 8 +- core/events/store.go | 261 +++++++++++++++++++++++++ core/events/store_test.go | 64 ++++++ core/events/types.go | 159 +++++++++++++++ core/minter/minter.go | 2 +- core/minter/upgrade3.go | 2 +- core/minter/upgrade3_test.go | 2 +- core/state/bus/bus.go | 2 +- core/state/candidates/candidates.go | 2 +- core/state/candidates_test.go | 2 +- core/state/frozenfunds/frozen_funds.go | 2 +- core/state/state.go | 2 +- core/state/validators/validators.go | 2 +- go.mod | 3 +- go.sum | 61 ------ rpc/test/helpers.go | 4 +- 18 files changed, 503 insertions(+), 79 deletions(-) create mode 100644 core/events/store.go create mode 100644 core/events/store_test.go create mode 100644 core/events/types.go diff --git a/api/api.go b/api/api.go index 80e7c86e6..baa2560c2 100644 --- a/api/api.go +++ b/api/api.go @@ -2,8 +2,8 @@ package api import ( "fmt" - eventsdb "github.com/MinterTeam/events-db" "github.com/MinterTeam/minter-go-node/config" + eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/minter" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/rpc/lib/server" diff --git a/api/events.go b/api/events.go index b926debff..5de924b5f 100644 --- a/api/events.go +++ b/api/events.go @@ -1,7 +1,7 @@ package api import ( - eventsdb "github.com/MinterTeam/events-db" + eventsdb "github.com/MinterTeam/minter-go-node/core/events" ) type EventsResponse struct { diff --git a/api/v2/service/events.go b/api/v2/service/events.go index 88151587f..8122e94fa 100644 --- a/api/v2/service/events.go +++ b/api/v2/service/events.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "encoding/json" - compact_db "github.com/MinterTeam/events-db" + eventsdb "github.com/MinterTeam/minter-go-node/core/events" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "github.com/golang/protobuf/jsonpb" _struct "github.com/golang/protobuf/ptypes/struct" @@ -29,11 +29,11 @@ func (s *Service) Events(_ context.Context, req *pb.EventsRequest) (*pb.EventsRe var t string switch event.(type) { - case *compact_db.RewardEvent: + case *eventsdb.RewardEvent: t = "minter/RewardEvent" - case *compact_db.SlashEvent: + case *eventsdb.SlashEvent: t = "minter/SlashEvent" - case *compact_db.UnbondEvent: + case *eventsdb.UnbondEvent: t = "minter/UnbondEvent" default: t = "Undefined Type" diff --git a/core/events/store.go b/core/events/store.go new file mode 100644 index 000000000..2f3e10949 --- /dev/null +++ b/core/events/store.go @@ -0,0 +1,261 @@ +package events + +import ( + "encoding/binary" + "github.com/tendermint/go-amino" + db "github.com/tendermint/tm-db" + "sync" +) + +type IEventsDB interface { + AddEvent(height uint32, event Event) + LoadEvents(height uint32) Events + CommitEvents() error +} + +type eventsStore struct { + cdc *amino.Codec + sync.RWMutex + db db.DB + pending pendingEvents + idPubKey map[uint16]string + pubKeyID map[string]uint16 + idAddress map[uint32][20]byte + addressID map[[20]byte]uint32 +} + +type pendingEvents struct { + sync.Mutex + height uint32 + items Events +} + +func NewEventsStore(db db.DB) IEventsDB { + codec := amino.NewCodec() + codec.RegisterInterface((*interface{})(nil), nil) + codec.RegisterConcrete(reward{}, "reward", nil) + codec.RegisterConcrete(slash{}, "slash", nil) + codec.RegisterConcrete(unbond{}, "unbond", nil) + + return &eventsStore{ + cdc: codec, + RWMutex: sync.RWMutex{}, + db: db, + pending: pendingEvents{}, + idPubKey: make(map[uint16]string), + pubKeyID: make(map[string]uint16), + idAddress: make(map[uint32][20]byte), + addressID: make(map[[20]byte]uint32), + } +} + +func (store *eventsStore) cachePubKey(id uint16, key string) { + store.idPubKey[id] = key + store.pubKeyID[key] = id +} + +func (store *eventsStore) cacheAddress(id uint32, address [20]byte) { + store.idAddress[id] = address + store.addressID[address] = id +} + +func (store *eventsStore) AddEvent(height uint32, event Event) { + store.pending.Lock() + defer store.pending.Unlock() + if store.pending.height != height { + store.pending.items = Events{} + } + store.pending.items = append(store.pending.items, event) + store.pending.height = height +} + +func (store *eventsStore) LoadEvents(height uint32) Events { + store.loadCache() + + bytes, err := store.db.Get(uint32ToBytes(height)) + if err != nil { + panic(err) + } + if len(bytes) == 0 { + return Events{} + } + + var items []interface{} + if err := store.cdc.UnmarshalBinaryBare(bytes, &items); err != nil { + panic(err) + } + + resultEvents := make(Events, 0, len(items)) + for _, event := range items { + resultEvents = append(resultEvents, store.compile(event)) + } + + return resultEvents +} + +func (store *eventsStore) CommitEvents() error { + store.loadCache() + + store.pending.Lock() + defer store.pending.Unlock() + var data []interface{} + for _, item := range store.pending.items { + data = append(data, store.convert(item)) + } + + bytes, err := store.cdc.MarshalBinaryBare(data) + if err != nil { + return err + } + + store.Lock() + defer store.Unlock() + if err := store.db.Set(uint32ToBytes(store.pending.height), bytes); err != nil { + panic(err) + } + return nil +} + +func (store *eventsStore) loadCache() { + store.Lock() + if len(store.idPubKey) == 0 { + store.loadPubKeys() + store.loadAddresses() + } + store.Unlock() +} + +func (store *eventsStore) convert(event Event) interface{} { + var res interface{} + switch event.(type) { + case RewardEvent: + res = store.convertReward(event.(RewardEvent)) + case UnbondEvent: + res = store.convertUnbound(event.(UnbondEvent)) + case SlashEvent: + res = store.convertSlash(event.(SlashEvent)) + default: + res = event + } + return res +} + +func (store *eventsStore) convertReward(rewardEvent RewardEvent) interface{} { + return rewardConvert(&rewardEvent, store.savePubKey(rewardEvent.ValidatorPubKey), store.saveAddress(rewardEvent.Address)) +} + +func (store *eventsStore) convertUnbound(unbondEvent UnbondEvent) interface{} { + return convertUnbound(&unbondEvent, store.savePubKey(unbondEvent.ValidatorPubKey), store.saveAddress(unbondEvent.Address)) +} + +func (store *eventsStore) convertSlash(slashEvent SlashEvent) interface{} { + return convertSlash(&slashEvent, store.savePubKey(slashEvent.ValidatorPubKey), store.saveAddress(slashEvent.Address)) +} + +const pubKeyPrefix = "pubKey" +const addressPrefix = "address" +const pubKeysCountKey = "pubKeys" +const addressesCountKey = "addresses" + +func (store *eventsStore) saveAddress(address [20]byte) uint32 { + + if id, ok := store.addressID[address]; ok { + return id + } + + id := uint32(len(store.addressID)) + store.cacheAddress(id, address) + + if err := store.db.Set(append([]byte(addressPrefix), uint32ToBytes(id)...), address[:]); err != nil { + panic(err) + } + if err := store.db.Set([]byte(addressesCountKey), uint32ToBytes(uint32(len(store.addressID)))); err != nil { + panic(err) + } + return id +} + +func (store *eventsStore) savePubKey(validatorPubKey [32]byte) uint16 { + + key := string(validatorPubKey[:]) + if id, ok := store.pubKeyID[key]; ok { + return id + } + + id := uint16(len(store.idPubKey)) + store.cachePubKey(id, key) + + if err := store.db.Set(append([]byte(pubKeyPrefix), uint16ToBytes(id)...), validatorPubKey[:]); err != nil { + panic(err) + } + if err := store.db.Set([]byte(pubKeysCountKey), uint16ToBytes(uint16(len(store.idPubKey)))); err != nil { + panic(err) + } + return id +} + +func (store *eventsStore) loadPubKeys() { + if count, _ := store.db.Get([]byte(pubKeysCountKey)); len(count) > 0 { + for id := uint16(0); id < binary.BigEndian.Uint16(count); id++ { + pubKey, err := store.db.Get(append([]byte(pubKeyPrefix), uint16ToBytes(id)...)) + if err != nil { + panic(err) + } + store.cachePubKey(id, string(pubKey)) + } + } +} + +func (store *eventsStore) loadAddresses() { + count, err := store.db.Get([]byte(addressesCountKey)) + if err != nil { + panic(err) + } + if len(count) > 0 { + for id := uint32(0); id < binary.BigEndian.Uint32(count); id++ { + address, _ := store.db.Get(append([]byte(addressPrefix), uint32ToBytes(id)...)) + var key [20]byte + copy(key[:], address) + store.cacheAddress(id, key) + } + } +} + +func (store *eventsStore) compile(event interface{}) Event { + var res interface{} + switch event.(type) { + case reward: + res = store.compileReward(event.(reward)) + case unbond: + res = store.compileUnbond(event.(unbond)) + case slash: + res = store.compileSlash(event.(slash)) + default: + res = event + } + return res +} + +func (store *eventsStore) compileReward(item reward) interface{} { + return compileReward(&item, store.idPubKey[item.PubKeyID], store.idAddress[item.AddressID]) +} + +func (store *eventsStore) compileSlash(item slash) interface{} { + return compileSlash(&item, store.idPubKey[item.PubKeyID], store.idAddress[item.AddressID]) +} + +func (store *eventsStore) compileUnbond(item unbond) interface{} { + return compileUnbond(&item, store.idPubKey[item.PubKeyID], store.idAddress[item.AddressID]) +} + +func uint32ToBytes(height uint32) []byte { + var h = make([]byte, 4) + binary.BigEndian.PutUint32(h, height) + return h +} + +func uint16ToBytes(height uint16) []byte { + var h = make([]byte, 2) + binary.BigEndian.PutUint16(h, height) + return h +} diff --git a/core/events/store_test.go b/core/events/store_test.go new file mode 100644 index 000000000..bab3edd4f --- /dev/null +++ b/core/events/store_test.go @@ -0,0 +1,64 @@ +package events + +import ( + "encoding/hex" + db "github.com/tendermint/tm-db" + "math/big" + "testing" +) + +func TestIEventsDB(t *testing.T) { + store := NewEventsStore(db.NewMemDB()) + + { + amount, _ := big.NewInt(0).SetString("111497225000000000000", 10) + event := RewardEvent{ + Role: RoleDevelopers.String(), + Address: [20]byte{}, + Amount: amount.String(), + ValidatorPubKey: [32]byte{}, + } + bytesAddress, err := hex.DecodeString("Mx04bea23efb744dc93b4fda4c20bf4a21c6e195f1"[2:]) + if err != nil { + t.Fatal(err) + } + copy(event.Address[:], bytesAddress) + hexPubKey, err := hex.DecodeString("Mp9e13f2f5468dd782b316444fbd66595e13dba7d7bd3efa1becd50b42045f58c6"[2:]) + if err != nil { + t.Fatal(err) + } + copy(event.ValidatorPubKey[:], hexPubKey) + store.AddEvent(12, event) + } + { + amount, _ := big.NewInt(0).SetString("891977800000000000000", 10) + event := RewardEvent{ + Role: RoleValidator.String(), + Address: [20]byte{}, + Amount: amount.String(), + ValidatorPubKey: [32]byte{}, + } + bytesAddress, err := hex.DecodeString("Mx18467bbb64a8edf890201d526c35957d82be3d95"[2:]) + if err != nil { + t.Fatal(err) + } + copy(event.Address[:], bytesAddress) + hexPubKey, err := hex.DecodeString("Mp738da41ba6a7b7d69b7294afa158b89c5a1b410cbf0c2443c85c5fe24ad1dd1c"[2:]) + if err != nil { + t.Fatal(err) + } + copy(event.ValidatorPubKey[:], hexPubKey) + store.AddEvent(12, event) + } + err := store.CommitEvents() + if err != nil { + t.Fatal(err) + } + + loadEvents := store.LoadEvents(12) + for _, v := range loadEvents { + t.Logf("%+v", v) + t.Logf("%+v", v.(*RewardEvent).Amount) + t.Logf("%+v", v.(*RewardEvent).Address.String()) + } +} diff --git a/core/events/types.go b/core/events/types.go new file mode 100644 index 000000000..f2eb26cfa --- /dev/null +++ b/core/events/types.go @@ -0,0 +1,159 @@ +package events + +import ( + "fmt" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/tendermint/go-amino" + "math/big" +) + +func RegisterAminoEvents(codec *amino.Codec) { + codec.RegisterInterface((*Event)(nil), nil) + codec.RegisterConcrete(RewardEvent{}, + "minter/RewardEvent", nil) + codec.RegisterConcrete(SlashEvent{}, + "minter/SlashEvent", nil) + codec.RegisterConcrete(UnbondEvent{}, + "minter/UnbondEvent", nil) +} + +type Event interface{} +type Events []Event + +type Role byte + +const ( + RoleValidator Role = iota + RoleDelegator + RoleDAO + RoleDevelopers +) + +func (r Role) String() string { + switch r { + case RoleValidator: + return "Validator" + case RoleDelegator: + return "Delegator" + case RoleDAO: + return "DAO" + case RoleDevelopers: + return "Developers" + } + + panic(fmt.Sprintf("undefined role: %d", r)) +} + +func NewRole(r string) Role { + switch r { + case "Validator": + return RoleValidator + case "Delegator": + return RoleDelegator + case "DAO": + return RoleDAO + case "Developers": + return RoleDevelopers + } + + panic("undefined role: " + r) +} + +type reward struct { + Role Role + AddressID uint32 + Amount []byte + PubKeyID uint16 +} + +type RewardEvent struct { + Role string `json:"role"` + Address types.Address `json:"address"` + Amount string `json:"amount"` + ValidatorPubKey types.Pubkey `json:"validator_pub_key"` +} + +func rewardConvert(event *RewardEvent, pubKeyID uint16, addressID uint32) interface{} { + result := new(reward) + result.AddressID = addressID + result.Role = NewRole(event.Role) + bi, _ := big.NewInt(0).SetString(event.Amount, 10) + result.Amount = bi.Bytes() + result.PubKeyID = pubKeyID + return result +} + +func compileReward(item *reward, pubKey string, address [20]byte) interface{} { + event := new(RewardEvent) + copy(event.ValidatorPubKey[:], pubKey) + copy(event.Address[:], address[:]) + event.Role = item.Role.String() + event.Amount = big.NewInt(0).SetBytes(item.Amount).String() + return event +} + +type slash struct { + AddressID uint32 + Amount []byte + Coin [10]byte + PubKeyID uint16 +} + +type SlashEvent struct { + Address types.Address `json:"address"` + Amount string `json:"amount"` + Coin types.CoinSymbol `json:"coin"` + ValidatorPubKey types.Pubkey `json:"validator_pub_key"` +} + +func convertSlash(event *SlashEvent, pubKeyID uint16, addressID uint32) interface{} { + result := new(slash) + result.AddressID = addressID + copy(result.Coin[:], event.Coin[:]) + bi, _ := big.NewInt(0).SetString(event.Amount, 10) + result.Amount = bi.Bytes() + result.PubKeyID = pubKeyID + return result +} + +func compileSlash(item *slash, pubKey string, address [20]byte) interface{} { + event := new(SlashEvent) + copy(event.ValidatorPubKey[:], pubKey) + copy(event.Address[:], address[:]) + copy(event.Coin[:], item.Coin[:]) + event.Amount = big.NewInt(0).SetBytes(item.Amount).String() + return event +} + +type unbond struct { + AddressID uint32 + Amount []byte + Coin [10]byte + PubKeyID uint16 +} + +type UnbondEvent struct { + Address types.Address `json:"address"` + Amount string `json:"amount"` + Coin types.CoinSymbol `json:"coin"` + ValidatorPubKey types.Pubkey `json:"validator_pub_key"` +} + +func convertUnbound(event *UnbondEvent, pubKeyID uint16, addressID uint32) interface{} { + result := new(unbond) + result.AddressID = addressID + copy(result.Coin[:], event.Coin[:]) + bi, _ := big.NewInt(0).SetString(event.Amount, 10) + result.Amount = bi.Bytes() + result.PubKeyID = pubKeyID + return result +} + +func compileUnbond(item *unbond, pubKey string, address [20]byte) interface{} { + event := new(UnbondEvent) + copy(event.ValidatorPubKey[:], pubKey) + copy(event.Address[:], address[:]) + copy(event.Coin[:], item.Coin[:]) + event.Amount = big.NewInt(0).SetBytes(item.Amount).String() + return event +} diff --git a/core/minter/minter.go b/core/minter/minter.go index 30a042cb8..15b73c519 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -4,10 +4,10 @@ import ( "bytes" "errors" "fmt" - eventsdb "github.com/MinterTeam/events-db" "github.com/MinterTeam/minter-go-node/cmd/utils" "github.com/MinterTeam/minter-go-node/config" "github.com/MinterTeam/minter-go-node/core/appdb" + eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/rewards" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/state/candidates" diff --git a/core/minter/upgrade3.go b/core/minter/upgrade3.go index 379428102..a95b69def 100644 --- a/core/minter/upgrade3.go +++ b/core/minter/upgrade3.go @@ -1,7 +1,7 @@ package minter import ( - eventsdb "github.com/MinterTeam/events-db" + eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/helpers" diff --git a/core/minter/upgrade3_test.go b/core/minter/upgrade3_test.go index fda286e01..9d1be7d9a 100644 --- a/core/minter/upgrade3_test.go +++ b/core/minter/upgrade3_test.go @@ -1,7 +1,7 @@ package minter import ( - eventsdb "github.com/MinterTeam/events-db" + eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/helpers" diff --git a/core/state/bus/bus.go b/core/state/bus/bus.go index 699d011bd..bd9051c89 100644 --- a/core/state/bus/bus.go +++ b/core/state/bus/bus.go @@ -1,6 +1,6 @@ package bus -import eventsdb "github.com/MinterTeam/events-db" +import eventsdb "github.com/MinterTeam/minter-go-node/core/events" type Bus struct { coins Coins diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 23c634c3f..8e88eb739 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -3,7 +3,7 @@ package candidates import ( "bytes" "fmt" - eventsdb "github.com/MinterTeam/events-db" + eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/state/bus" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index 91222ee37..e475d7414 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -3,7 +3,7 @@ package state import ( "crypto/rand" "encoding/binary" - eventsdb "github.com/MinterTeam/events-db" + eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/state/candidates" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/upgrades" diff --git a/core/state/frozenfunds/frozen_funds.go b/core/state/frozenfunds/frozen_funds.go index d1d1cc529..c979cfccb 100644 --- a/core/state/frozenfunds/frozen_funds.go +++ b/core/state/frozenfunds/frozen_funds.go @@ -3,7 +3,7 @@ package frozenfunds import ( "encoding/binary" "fmt" - eventsdb "github.com/MinterTeam/events-db" + eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/state/bus" "github.com/MinterTeam/minter-go-node/core/state/candidates" "github.com/MinterTeam/minter-go-node/core/types" diff --git a/core/state/state.go b/core/state/state.go index 3f7924b89..4c89558ea 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -3,7 +3,7 @@ package state import ( "encoding/hex" "fmt" - eventsdb "github.com/MinterTeam/events-db" + eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/state/accounts" "github.com/MinterTeam/minter-go-node/core/state/app" "github.com/MinterTeam/minter-go-node/core/state/bus" diff --git a/core/state/validators/validators.go b/core/state/validators/validators.go index e61c37e76..8dc1a10a9 100644 --- a/core/state/validators/validators.go +++ b/core/state/validators/validators.go @@ -2,9 +2,9 @@ package validators import ( "fmt" - eventsdb "github.com/MinterTeam/events-db" "github.com/MinterTeam/minter-go-node/core/dao" "github.com/MinterTeam/minter-go-node/core/developers" + eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/state/bus" "github.com/MinterTeam/minter-go-node/core/state/candidates" "github.com/MinterTeam/minter-go-node/core/types" diff --git a/go.mod b/go.mod index 0933fcb33..8fbd567c2 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/events-db v0.1.6 github.com/MinterTeam/node-grpc-gateway v1.1.2 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 @@ -16,7 +15,9 @@ require ( github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/grpc-gateway v1.14.3 github.com/marcusolsson/tui-go v0.4.0 + github.com/mattn/go-tty v0.0.3 // indirect github.com/pkg/errors v0.9.1 + github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942 // indirect github.com/prometheus/client_golang v1.5.1 github.com/rakyll/statik v0.1.7 github.com/rs/cors v1.7.0 diff --git a/go.sum b/go.sum index 14d21f297..883256dea 100644 --- a/go.sum +++ b/go.sum @@ -7,18 +7,6 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200102211924-4bcbc698314f/go.mod h1: github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/events-db v0.1.0/go.mod h1:ZnKNYUSFUgVTTB359LvKQbroYqBiriXmbnyaMsULU2o= -github.com/MinterTeam/events-db v0.1.1-0.20191113155258-73206cb9a3ea/go.mod h1:INfo4gbiX8/EGfjHmRvvW2+5YuOcTy7Tob69yUhAqU4= -github.com/MinterTeam/events-db v0.1.6 h1:kxUPuzmbwSTva7jHOlydsvBFhGAIgkpsXT8xAnQG8yA= -github.com/MinterTeam/events-db v0.1.6/go.mod h1:niLCQF2EmB3G27zHj94jUO3p359sXEvTcdZrt8dS2AQ= -github.com/MinterTeam/go-amino v0.14.1/go.mod h1:2sqs1fcf3DcQpvIJarkzVCjALWc11WDwc5oFHCrG5R4= -github.com/MinterTeam/go-amino v0.14.2-0.20191113110031-d5499d43f453 h1:uHtg6ZR5wVNJhwVI0Gw1RPPip6sj6Mo2SqoAh8scGp0= -github.com/MinterTeam/go-amino v0.14.2-0.20191113110031-d5499d43f453/go.mod h1:o4p3WDNrrIOapHOfM5pKJNZ1exPI+c6ZvbemrNapJxc= -github.com/MinterTeam/minter-go-node v1.0.4/go.mod h1:juaQ5woUKkGknh4Fj57+uv0AgMAzSv/aChNQT04K+uQ= -github.com/MinterTeam/minter-go-node v1.0.5-0.20191113110340-a46b8ef88084/go.mod h1:ihc9SIXO0ZSnnS6AB2kT+UD9iIHap0TH47BvL6A2fQg= -github.com/MinterTeam/minter-go-node v1.1.0-beta5/go.mod h1:MeO8y1SPL2uk/znxFPauMB4karv/xQeI1O1SPeEycrU= -github.com/MinterTeam/minter-node-cli v0.0.0-20191202172005-309e9d40a5a3 h1:2ndNow11LzKNggx2JNh2Fhb0NKEQ2kVt+HL9jdEBLOg= -github.com/MinterTeam/minter-node-cli v0.0.0-20191202172005-309e9d40a5a3/go.mod h1:6iFtZjWsvR9ZaXaogfDkIYVSrQAHQBk/tU1L5yKS5/8= github.com/MinterTeam/node-grpc-gateway v1.1.2 h1:kHwlqPlKXFZX+SjUjqGp4c7pmONhM438EzUyJV8hKyg= github.com/MinterTeam/node-grpc-gateway v1.1.2/go.mod h1:tfJiYOCloZD+Q8nSplqVQFQNs3ggFgBBVQa0hOVCsjg= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -26,7 +14,6 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= github.com/Workiva/go-datastructures v1.0.52 h1:PLSK6pwn8mYdaoaCZEMsXBpBotr4HHn9abU0yMQt0NI= github.com/Workiva/go-datastructures v1.0.52/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -112,7 +99,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/etcd-io/bbolt v1.3.2/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/etcd-io/bbolt v1.3.3 h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= @@ -122,7 +108,6 @@ github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqL github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y= github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= @@ -134,7 +119,6 @@ github.com/gdamore/encoding v0.0.0-20151215212835-b23993cbb635/go.mod h1:yrQYJKK github.com/gdamore/tcell v1.1.0 h1:RbQgl7jukmdqROeNcKps7R2YfDCQbWkOd1BwdXrxfr4= github.com/gdamore/tcell v1.1.0/go.mod h1:tqyG50u7+Ctv1w5VX67kLzKcj9YXR/JSBZQq/+mLl1A= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-kit/kit v0.6.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -148,13 +132,10 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gobuffalo/packr v1.11.1 h1:L44og8g+xWusakqZ5N52ujRSopFNtXextBGJgn69D28= -github.com/gobuffalo/packr v1.11.1/go.mod h1:rYwMLC6NXbAbkKb+9j3NTKbxSswkKLlelZYccr4HYVw= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= @@ -162,7 +143,6 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= @@ -209,7 +189,6 @@ github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -397,7 +376,6 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= @@ -416,8 +394,6 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= -github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165 h1:nkcn14uNmFEuGCb2mBZbBb24RdNRL08b/wb+xBOYpuk= -github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= @@ -425,7 +401,6 @@ github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqn github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= @@ -452,7 +427,6 @@ github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.6 h1:breEStsVwemnKh2/s6gMvSdMEkwW0sK8vGStnlVBMCs= @@ -464,10 +438,8 @@ github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb6 github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.5.0/go.mod h1:AkYRkVJF8TkSG/xet6PzXX+l39KhhXa2pdqVSxnTcn4= github.com/spf13/viper v1.6.2 h1:7aKfF+e8/k68gda3LOjo5RxiUqddoFxVq4BKBPrxk5E= github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= github.com/spf13/viper v1.6.3 h1:pDDu1OyEDTKzpJwdq4TiuLyMsUgRa/BT5cn5O62NoHs= @@ -483,40 +455,21 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stumble/gorocksdb v0.0.3 h1:9UU+QA1pqFYJuf9+5p7z1IqdE5k0mma4UAeu2wmX8kA= -github.com/stumble/gorocksdb v0.0.3/go.mod h1:v6IHdFBXk5DJ1K4FZ0xi+eY737quiiBxYtSWXadLybY= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965 h1:1oFLiOyVl+W7bnBzGhf7BbIv9loSFQcieWWYIjLqcAw= -github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d h1:gZZadD8H+fF+n9CmNhYL1Y0dJB+kLOmKd7FbPJLeGHs= github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= -github.com/tecbot/gorocksdb v0.0.0-20191017175515-d217d93fd4c5 h1:gVwAW5OwaZlDB5/CfqcGFM9p9C+KxvQKyNOltQ8orj0= -github.com/tecbot/gorocksdb v0.0.0-20191017175515-d217d93fd4c5/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso= github.com/tendermint/go-amino v0.15.1 h1:D2uk35eT4iTsvJd9jWIetzthE5C0/k2QmMFkCN+4JgQ= github.com/tendermint/go-amino v0.15.1/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/tendermint/iavl v0.12.4 h1:hd1woxUGISKkfUWBA4mmmTwOua6PQZTJM/F0FDrmMV8= -github.com/tendermint/iavl v0.12.4/go.mod h1:8LHakzt8/0G3/I8FUU0ReNx98S/EP6eyPJkAUvEXT/o= github.com/tendermint/iavl v0.13.3 h1:expgBDY1MX+6/3sqrIxGChbTNf9N9aTJ67SH4bPchCs= github.com/tendermint/iavl v0.13.3/go.mod h1:2lE7GiWdSvc7kvT78ncIKmkOjCnp6JEnSb2O7B9htLw= -github.com/tendermint/tendermint v0.32.1/go.mod h1:jmPDAKuNkev9793/ivn/fTBnfpA9mGBww8MPRNPNxnU= -github.com/tendermint/tendermint v0.32.6 h1:HozXi0USWvKrWuEh5ratnJV10ykkTy4nwXUi0UvPVzg= -github.com/tendermint/tendermint v0.32.6/go.mod h1:D2+A3pNjY+Po72X0mTfaXorFhiVI8dh/Zg640FGyGtE= -github.com/tendermint/tendermint v0.32.8/go.mod h1:5/B1XZjNYtVBso8o1l/Eg4A0Mhu42lDcmftoQl95j/E= github.com/tendermint/tendermint v0.33.2 h1:NzvRMTuXJxqSsFed2J7uHmMU5N1CVzSpfi3nCc882KY= github.com/tendermint/tendermint v0.33.2/go.mod h1:25DqB7YvV1tN3tHsjWoc2vFtlwICfrub9XO6UBO+4xk= -github.com/tendermint/tendermint v0.33.3 h1:6lMqjEoCGejCzAghbvfQgmw87snGSqEhDTo/jw+W8CI= -github.com/tendermint/tendermint v0.33.3/go.mod h1:25DqB7YvV1tN3tHsjWoc2vFtlwICfrub9XO6UBO+4xk= github.com/tendermint/tendermint v0.33.5 h1:jYgRd9ImkzA9iOyhpmgreYsqSB6tpDa6/rXYPb8HKE8= github.com/tendermint/tendermint v0.33.5/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM= -github.com/tendermint/tm-db v0.1.1/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw= -github.com/tendermint/tm-db v0.2.0 h1:rJxgdqn6fIiVJZy4zLpY1qVlyD0TU6vhkT4kEf71TQQ= -github.com/tendermint/tm-db v0.2.0/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw= -github.com/tendermint/tm-db v0.4.0 h1:iPbCcLbf4nwDFhS39Zo1lpdS1X/cT9CkTlUx17FHQgA= -github.com/tendermint/tm-db v0.4.0/go.mod h1:+Cwhgowrf7NBGXmsqFMbwEtbo80XmyrlY5Jsk95JubQ= github.com/tendermint/tm-db v0.4.1 h1:TvX7JWjJOVZ+N3y+I86wddrGttOdMmmBxXcu0/Y7ZJ0= github.com/tendermint/tm-db v0.4.1/go.mod h1:JsJ6qzYkCGiGwm5GHl/H5GLI9XLb6qZX7PRe425dHAY= github.com/tendermint/tm-db v0.5.1 h1:H9HDq8UEA7Eeg13kdYckkgwwkQLBnJGgX4PgLJRhieY= @@ -550,10 +503,7 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a h1:YX8ljsm6wXlHZO+aRz9Exqr0evNhKRNe5K/gi+zKh4U= -golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -563,7 +513,6 @@ golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 h1:DOmugCavvUtnUD114C1Wh+UgTgQZ4pMLzXxi1pSt+/Y= golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -575,7 +524,6 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -620,10 +568,8 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191020212454-3e7259c5e7c2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -662,8 +608,6 @@ google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181109154231-b5d43981345b/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= @@ -673,20 +617,15 @@ google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c h1:hrpEMCZ2O7DR5gC google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940 h1:MRHtG0U6SnaUb+s+LhNE1qt1FQ1wlhqr5E4usBKC0uA= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/grpc v1.13.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= -google.golang.org/grpc v1.25.0 h1:ItERT+UbGdX+s4u+nQNlVM/Q7cbmf7icKfvzbWqVtq0= -google.golang.org/grpc v1.25.0/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= diff --git a/rpc/test/helpers.go b/rpc/test/helpers.go index bc6492238..40896e0a2 100644 --- a/rpc/test/helpers.go +++ b/rpc/test/helpers.go @@ -20,14 +20,14 @@ import ( "github.com/tendermint/tendermint/proxy" ctypes "github.com/tendermint/tendermint/rpc/core/types" core_grpc "github.com/tendermint/tendermint/rpc/grpc" - rpcclient "github.com/tendermint/tendermint/rpc/lib/client" + rpcclient "github.com/tendermint/tendermint/rpc/jsonrpc/client" ) var globalConfig *cfg.Config func waitForRPC() { laddr := GetConfig().RPC.ListenAddress - client, _ := rpcclient.NewJSONRPCClient(laddr) + client, _ := rpcclient.New(laddr) ctypes.RegisterAmino(client.Codec()) result := new(ctypes.ResultStatus) for { From a4c5149a3444b66dd08ecf0e153b2b45b2b93527 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 16 Jun 2020 15:09:56 +0300 Subject: [PATCH 031/426] update events-db --- core/events/store.go | 76 ++---------- core/events/store_test.go | 4 +- core/events/types.go | 159 +++++++++++++++++++------ core/minter/minter.go | 2 +- core/minter/upgrade3.go | 2 +- core/state/candidates/candidates.go | 16 +-- core/state/frozenfunds/frozen_funds.go | 2 +- core/state/validators/validators.go | 8 +- 8 files changed, 152 insertions(+), 117 deletions(-) diff --git a/core/events/store.go b/core/events/store.go index 2f3e10949..6d6949547 100644 --- a/core/events/store.go +++ b/core/events/store.go @@ -32,10 +32,11 @@ type pendingEvents struct { func NewEventsStore(db db.DB) IEventsDB { codec := amino.NewCodec() - codec.RegisterInterface((*interface{})(nil), nil) - codec.RegisterConcrete(reward{}, "reward", nil) - codec.RegisterConcrete(slash{}, "slash", nil) - codec.RegisterConcrete(unbond{}, "unbond", nil) + codec.RegisterInterface((*Event)(nil), nil) + codec.RegisterInterface((*compactEvent)(nil), nil) + codec.RegisterConcrete(&reward{}, "reward", nil) + codec.RegisterConcrete(&slash{}, "slash", nil) + codec.RegisterConcrete(&unbond{}, "unbond", nil) return &eventsStore{ cdc: codec, @@ -80,14 +81,15 @@ func (store *eventsStore) LoadEvents(height uint32) Events { return Events{} } - var items []interface{} + var items []compactEvent if err := store.cdc.UnmarshalBinaryBare(bytes, &items); err != nil { panic(err) } resultEvents := make(Events, 0, len(items)) - for _, event := range items { - resultEvents = append(resultEvents, store.compile(event)) + for _, compactEvent := range items { + event := compactEvent.compile(store.idPubKey[compactEvent.pubKeyID()], store.idAddress[compactEvent.addressID()]) + resultEvents = append(resultEvents, event) } return resultEvents @@ -98,9 +100,11 @@ func (store *eventsStore) CommitEvents() error { store.pending.Lock() defer store.pending.Unlock() - var data []interface{} + var data []compactEvent for _, item := range store.pending.items { - data = append(data, store.convert(item)) + pubKey := store.savePubKey(item.validatorPubKey()) + address := store.saveAddress(item.address()) + data = append(data, item.convert(pubKey, address)) } bytes, err := store.cdc.MarshalBinaryBare(data) @@ -125,33 +129,6 @@ func (store *eventsStore) loadCache() { store.Unlock() } -func (store *eventsStore) convert(event Event) interface{} { - var res interface{} - switch event.(type) { - case RewardEvent: - res = store.convertReward(event.(RewardEvent)) - case UnbondEvent: - res = store.convertUnbound(event.(UnbondEvent)) - case SlashEvent: - res = store.convertSlash(event.(SlashEvent)) - default: - res = event - } - return res -} - -func (store *eventsStore) convertReward(rewardEvent RewardEvent) interface{} { - return rewardConvert(&rewardEvent, store.savePubKey(rewardEvent.ValidatorPubKey), store.saveAddress(rewardEvent.Address)) -} - -func (store *eventsStore) convertUnbound(unbondEvent UnbondEvent) interface{} { - return convertUnbound(&unbondEvent, store.savePubKey(unbondEvent.ValidatorPubKey), store.saveAddress(unbondEvent.Address)) -} - -func (store *eventsStore) convertSlash(slashEvent SlashEvent) interface{} { - return convertSlash(&slashEvent, store.savePubKey(slashEvent.ValidatorPubKey), store.saveAddress(slashEvent.Address)) -} - const pubKeyPrefix = "pubKey" const addressPrefix = "address" const pubKeysCountKey = "pubKeys" @@ -221,33 +198,6 @@ func (store *eventsStore) loadAddresses() { } } -func (store *eventsStore) compile(event interface{}) Event { - var res interface{} - switch event.(type) { - case reward: - res = store.compileReward(event.(reward)) - case unbond: - res = store.compileUnbond(event.(unbond)) - case slash: - res = store.compileSlash(event.(slash)) - default: - res = event - } - return res -} - -func (store *eventsStore) compileReward(item reward) interface{} { - return compileReward(&item, store.idPubKey[item.PubKeyID], store.idAddress[item.AddressID]) -} - -func (store *eventsStore) compileSlash(item slash) interface{} { - return compileSlash(&item, store.idPubKey[item.PubKeyID], store.idAddress[item.AddressID]) -} - -func (store *eventsStore) compileUnbond(item unbond) interface{} { - return compileUnbond(&item, store.idPubKey[item.PubKeyID], store.idAddress[item.AddressID]) -} - func uint32ToBytes(height uint32) []byte { var h = make([]byte, 4) binary.BigEndian.PutUint32(h, height) diff --git a/core/events/store_test.go b/core/events/store_test.go index bab3edd4f..049a0368c 100644 --- a/core/events/store_test.go +++ b/core/events/store_test.go @@ -12,7 +12,7 @@ func TestIEventsDB(t *testing.T) { { amount, _ := big.NewInt(0).SetString("111497225000000000000", 10) - event := RewardEvent{ + event := &RewardEvent{ Role: RoleDevelopers.String(), Address: [20]byte{}, Amount: amount.String(), @@ -32,7 +32,7 @@ func TestIEventsDB(t *testing.T) { } { amount, _ := big.NewInt(0).SetString("891977800000000000000", 10) - event := RewardEvent{ + event := &RewardEvent{ Role: RoleValidator.String(), Address: [20]byte{}, Amount: amount.String(), diff --git a/core/events/types.go b/core/events/types.go index f2eb26cfa..660a712bc 100644 --- a/core/events/types.go +++ b/core/events/types.go @@ -17,7 +17,20 @@ func RegisterAminoEvents(codec *amino.Codec) { "minter/UnbondEvent", nil) } -type Event interface{} +type Event interface { + address() types.Address + validatorPubKey() types.Pubkey + AddressString() string + ValidatorPubKeyString() string + convert(pubKeyID uint16, addressID uint32) compactEvent +} + +type compactEvent interface { + compile(pubKey string, address [20]byte) Event + addressID() uint32 + pubKeyID() uint16 +} + type Events []Event type Role byte @@ -66,6 +79,23 @@ type reward struct { PubKeyID uint16 } +func (r *reward) compile(pubKey string, address [20]byte) Event { + event := new(RewardEvent) + copy(event.ValidatorPubKey[:], pubKey) + copy(event.Address[:], address[:]) + event.Role = r.Role.String() + event.Amount = big.NewInt(0).SetBytes(r.Amount).String() + return event +} + +func (r *reward) addressID() uint32 { + return r.AddressID +} + +func (r *reward) pubKeyID() uint16 { + return r.PubKeyID +} + type RewardEvent struct { Role string `json:"role"` Address types.Address `json:"address"` @@ -73,25 +103,32 @@ type RewardEvent struct { ValidatorPubKey types.Pubkey `json:"validator_pub_key"` } -func rewardConvert(event *RewardEvent, pubKeyID uint16, addressID uint32) interface{} { +func (re *RewardEvent) AddressString() string { + return re.Address.String() +} + +func (re *RewardEvent) address() types.Address { + return re.Address +} + +func (re *RewardEvent) ValidatorPubKeyString() string { + return re.ValidatorPubKey.String() +} + +func (re *RewardEvent) validatorPubKey() types.Pubkey { + return re.ValidatorPubKey +} + +func (re *RewardEvent) convert(pubKeyID uint16, addressID uint32) compactEvent { result := new(reward) result.AddressID = addressID - result.Role = NewRole(event.Role) - bi, _ := big.NewInt(0).SetString(event.Amount, 10) + result.Role = NewRole(re.Role) + bi, _ := big.NewInt(0).SetString(re.Amount, 10) result.Amount = bi.Bytes() result.PubKeyID = pubKeyID return result } -func compileReward(item *reward, pubKey string, address [20]byte) interface{} { - event := new(RewardEvent) - copy(event.ValidatorPubKey[:], pubKey) - copy(event.Address[:], address[:]) - event.Role = item.Role.String() - event.Amount = big.NewInt(0).SetBytes(item.Amount).String() - return event -} - type slash struct { AddressID uint32 Amount []byte @@ -99,6 +136,23 @@ type slash struct { PubKeyID uint16 } +func (s *slash) compile(pubKey string, address [20]byte) Event { + event := new(SlashEvent) + copy(event.ValidatorPubKey[:], pubKey) + copy(event.Address[:], address[:]) + copy(event.Coin[:], s.Coin[:]) + event.Amount = big.NewInt(0).SetBytes(s.Amount).String() + return event +} + +func (s *slash) addressID() uint32 { + return s.AddressID +} + +func (s *slash) pubKeyID() uint16 { + return s.PubKeyID +} + type SlashEvent struct { Address types.Address `json:"address"` Amount string `json:"amount"` @@ -106,25 +160,32 @@ type SlashEvent struct { ValidatorPubKey types.Pubkey `json:"validator_pub_key"` } -func convertSlash(event *SlashEvent, pubKeyID uint16, addressID uint32) interface{} { +func (se *SlashEvent) AddressString() string { + return se.Address.String() +} + +func (se *SlashEvent) address() types.Address { + return se.Address +} + +func (se *SlashEvent) ValidatorPubKeyString() string { + return se.ValidatorPubKey.String() +} + +func (se *SlashEvent) validatorPubKey() types.Pubkey { + return se.ValidatorPubKey +} + +func (se *SlashEvent) convert(pubKeyID uint16, addressID uint32) compactEvent { result := new(slash) result.AddressID = addressID - copy(result.Coin[:], event.Coin[:]) - bi, _ := big.NewInt(0).SetString(event.Amount, 10) + copy(result.Coin[:], se.Coin[:]) + bi, _ := big.NewInt(0).SetString(se.Amount, 10) result.Amount = bi.Bytes() result.PubKeyID = pubKeyID return result } -func compileSlash(item *slash, pubKey string, address [20]byte) interface{} { - event := new(SlashEvent) - copy(event.ValidatorPubKey[:], pubKey) - copy(event.Address[:], address[:]) - copy(event.Coin[:], item.Coin[:]) - event.Amount = big.NewInt(0).SetBytes(item.Amount).String() - return event -} - type unbond struct { AddressID uint32 Amount []byte @@ -132,6 +193,23 @@ type unbond struct { PubKeyID uint16 } +func (u *unbond) compile(pubKey string, address [20]byte) Event { + event := new(UnbondEvent) + copy(event.ValidatorPubKey[:], pubKey) + copy(event.Address[:], address[:]) + copy(event.Coin[:], u.Coin[:]) + event.Amount = big.NewInt(0).SetBytes(u.Amount).String() + return event +} + +func (u *unbond) addressID() uint32 { + return u.AddressID +} + +func (u *unbond) pubKeyID() uint16 { + return u.PubKeyID +} + type UnbondEvent struct { Address types.Address `json:"address"` Amount string `json:"amount"` @@ -139,21 +217,28 @@ type UnbondEvent struct { ValidatorPubKey types.Pubkey `json:"validator_pub_key"` } -func convertUnbound(event *UnbondEvent, pubKeyID uint16, addressID uint32) interface{} { +func (ue *UnbondEvent) AddressString() string { + return ue.Address.String() +} + +func (ue *UnbondEvent) address() types.Address { + return ue.Address +} + +func (ue *UnbondEvent) ValidatorPubKeyString() string { + return ue.ValidatorPubKey.String() +} + +func (ue *UnbondEvent) validatorPubKey() types.Pubkey { + return ue.ValidatorPubKey +} + +func (ue *UnbondEvent) convert(pubKeyID uint16, addressID uint32) compactEvent { result := new(unbond) result.AddressID = addressID - copy(result.Coin[:], event.Coin[:]) - bi, _ := big.NewInt(0).SetString(event.Amount, 10) + copy(result.Coin[:], ue.Coin[:]) + bi, _ := big.NewInt(0).SetString(ue.Amount, 10) result.Amount = bi.Bytes() result.PubKeyID = pubKeyID return result } - -func compileUnbond(item *unbond, pubKey string, address [20]byte) interface{} { - event := new(UnbondEvent) - copy(event.ValidatorPubKey[:], pubKey) - copy(event.Address[:], address[:]) - copy(event.Coin[:], item.Coin[:]) - event.Amount = big.NewInt(0).SetBytes(item.Amount).String() - return event -} diff --git a/core/minter/minter.go b/core/minter/minter.go index 15b73c519..30bb79ff7 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -233,7 +233,7 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res frozenFunds := app.stateDeliver.FrozenFunds.GetFrozenFunds(uint64(req.Header.Height)) if frozenFunds != nil { for _, item := range frozenFunds.List { - app.eventsDB.AddEvent(uint32(req.Header.Height), eventsdb.UnbondEvent{ + app.eventsDB.AddEvent(uint32(req.Header.Height), &eventsdb.UnbondEvent{ Address: item.Address, Amount: item.Value.String(), Coin: item.Coin, diff --git a/core/minter/upgrade3.go b/core/minter/upgrade3.go index a95b69def..1e3bc44c8 100644 --- a/core/minter/upgrade3.go +++ b/core/minter/upgrade3.go @@ -434,7 +434,7 @@ func ApplyUpgrade3(state *state.State, events eventsdb.IEventsDB) { value := helpers.StringToBigInt(data[3]) coin := types.StrToCoinSymbol(data[4]) - events.AddEvent(upgrades.UpgradeBlock3, eventsdb.UnbondEvent{ + events.AddEvent(upgrades.UpgradeBlock3, &eventsdb.UnbondEvent{ Address: owner, Amount: value.String(), Coin: coin, diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 8e88eb739..f9238716f 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -213,7 +213,7 @@ func (c *Candidates) PunishByzantineCandidate(height uint64, tmAddress types.TmA c.bus.Checker().AddCoin(stake.Coin, big.NewInt(0).Neg(slashed)) } - c.bus.Events().AddEvent(uint32(height), eventsdb.SlashEvent{ + c.bus.Events().AddEvent(uint32(height), &eventsdb.SlashEvent{ Address: stake.Owner, Amount: slashed.String(), Coin: stake.Coin, @@ -298,7 +298,7 @@ func (c *Candidates) recalculateStakesOld1(height uint64) { } if index == -1 || smallestStake.Cmp(update.BipValue) == 1 { - c.bus.Events().AddEvent(uint32(height), eventsdb.UnbondEvent{ + c.bus.Events().AddEvent(uint32(height), &eventsdb.UnbondEvent{ Address: update.Owner, Amount: update.Value.String(), Coin: update.Coin, @@ -311,7 +311,7 @@ func (c *Candidates) recalculateStakesOld1(height uint64) { } if stakes[index] != nil { - c.bus.Events().AddEvent(uint32(height), eventsdb.UnbondEvent{ + c.bus.Events().AddEvent(uint32(height), &eventsdb.UnbondEvent{ Address: stakes[index].Owner, Amount: stakes[index].Value.String(), Coin: stakes[index].Coin, @@ -404,7 +404,7 @@ func (c *Candidates) recalculateStakesOld2(height uint64) { } if index == -1 || smallestStake.Cmp(update.BipValue) == 1 { - c.bus.Events().AddEvent(uint32(height), eventsdb.UnbondEvent{ + c.bus.Events().AddEvent(uint32(height), &eventsdb.UnbondEvent{ Address: update.Owner, Amount: update.Value.String(), Coin: update.Coin, @@ -417,7 +417,7 @@ func (c *Candidates) recalculateStakesOld2(height uint64) { } if len(stakes) > index && stakes[index] != nil { - c.bus.Events().AddEvent(uint32(height), eventsdb.UnbondEvent{ + c.bus.Events().AddEvent(uint32(height), &eventsdb.UnbondEvent{ Address: stakes[index].Owner, Amount: stakes[index].Value.String(), Coin: stakes[index].Coin, @@ -493,7 +493,7 @@ func (c *Candidates) recalculateStakesNew(height uint64) { } if smallestStake.Cmp(update.BipValue) == 1 { - c.bus.Events().AddEvent(uint32(height), eventsdb.UnbondEvent{ + c.bus.Events().AddEvent(uint32(height), &eventsdb.UnbondEvent{ Address: update.Owner, Amount: update.Value.String(), Coin: update.Coin, @@ -506,7 +506,7 @@ func (c *Candidates) recalculateStakesNew(height uint64) { } if stakes[index] != nil { - c.bus.Events().AddEvent(uint32(height), eventsdb.UnbondEvent{ + c.bus.Events().AddEvent(uint32(height), &eventsdb.UnbondEvent{ Address: stakes[index].Owner, Amount: stakes[index].Value.String(), Coin: stakes[index].Coin, @@ -811,7 +811,7 @@ func (c *Candidates) Punish(height uint64, address types.TmAddress) *big.Int { c.bus.Checker().AddCoin(stake.Coin, big.NewInt(0).Neg(slashed)) } - c.bus.Events().AddEvent(uint32(height), eventsdb.SlashEvent{ + c.bus.Events().AddEvent(uint32(height), &eventsdb.SlashEvent{ Address: stake.Owner, Amount: slashed.String(), Coin: stake.Coin, diff --git a/core/state/frozenfunds/frozen_funds.go b/core/state/frozenfunds/frozen_funds.go index c979cfccb..6d2243f56 100644 --- a/core/state/frozenfunds/frozen_funds.go +++ b/core/state/frozenfunds/frozen_funds.go @@ -99,7 +99,7 @@ func (f *FrozenFunds) PunishFrozenFundsWithAddress(fromHeight uint64, toHeight u f.bus.Checker().AddCoin(item.Coin, slashed) - f.bus.Events().AddEvent(uint32(fromHeight), eventsdb.SlashEvent{ + f.bus.Events().AddEvent(uint32(fromHeight), &eventsdb.SlashEvent{ Address: item.Address, Amount: slashed.String(), Coin: item.Coin, diff --git a/core/state/validators/validators.go b/core/state/validators/validators.go index 8dc1a10a9..f5f3faca3 100644 --- a/core/state/validators/validators.go +++ b/core/state/validators/validators.go @@ -193,7 +193,7 @@ func (v *Validators) PayRewards(height uint64) { DAOReward.Div(DAOReward, big.NewInt(100)) v.bus.Accounts().AddBalance(dao.Address, types.GetBaseCoin(), DAOReward) remainder.Sub(remainder, DAOReward) - v.bus.Events().AddEvent(uint32(height), eventsdb.RewardEvent{ + v.bus.Events().AddEvent(uint32(height), &eventsdb.RewardEvent{ Role: eventsdb.RoleDAO.String(), Address: dao.Address, Amount: DAOReward.String(), @@ -206,7 +206,7 @@ func (v *Validators) PayRewards(height uint64) { DevelopersReward.Div(DevelopersReward, big.NewInt(100)) v.bus.Accounts().AddBalance(developers.Address, types.GetBaseCoin(), DevelopersReward) remainder.Sub(remainder, DevelopersReward) - v.bus.Events().AddEvent(uint32(height), eventsdb.RewardEvent{ + v.bus.Events().AddEvent(uint32(height), &eventsdb.RewardEvent{ Role: eventsdb.RoleDevelopers.String(), Address: developers.Address, Amount: DevelopersReward.String(), @@ -223,7 +223,7 @@ func (v *Validators) PayRewards(height uint64) { totalReward.Sub(totalReward, validatorReward) v.bus.Accounts().AddBalance(candidate.RewardAddress, types.GetBaseCoin(), validatorReward) remainder.Sub(remainder, validatorReward) - v.bus.Events().AddEvent(uint32(height), eventsdb.RewardEvent{ + v.bus.Events().AddEvent(uint32(height), &eventsdb.RewardEvent{ Role: eventsdb.RoleValidator.String(), Address: candidate.RewardAddress, Amount: validatorReward.String(), @@ -247,7 +247,7 @@ func (v *Validators) PayRewards(height uint64) { v.bus.Accounts().AddBalance(stake.Owner, types.GetBaseCoin(), reward) remainder.Sub(remainder, reward) - v.bus.Events().AddEvent(uint32(height), eventsdb.RewardEvent{ + v.bus.Events().AddEvent(uint32(height), &eventsdb.RewardEvent{ Role: eventsdb.RoleDelegator.String(), Address: stake.Owner, Amount: reward.String(), From ec06d26bd8104736158d5cc222a4ef3c6dfac3ae Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 16 Jun 2020 16:44:17 +0300 Subject: [PATCH 032/426] expand api --- api/addresses_full_balances.go | 159 +++++++++++++++++++++++++++++++++ api/api.go | 13 +++ api/calc_comission.go | 103 +++++++++++++++++++++ api/candidates_alt.go | 119 ++++++++++++++++++++++++ api/find_events.go | 24 +++++ api/frozzen.go | 69 ++++++++++++++ api/get_stakes.go | 84 +++++++++++++++++ api/grouped_events.go | 82 +++++++++++++++++ api/heigt_by_time.go | 73 +++++++++++++++ api/nosign.go | 62 +++++++++++++ api/slashed.go | 18 ++++ api/tx_from_block.go | 63 +++++++++++++ core/state/app/app.go | 1 + 13 files changed, 870 insertions(+) create mode 100644 api/addresses_full_balances.go create mode 100644 api/calc_comission.go create mode 100644 api/candidates_alt.go create mode 100644 api/find_events.go create mode 100644 api/frozzen.go create mode 100644 api/get_stakes.go create mode 100644 api/grouped_events.go create mode 100644 api/heigt_by_time.go create mode 100644 api/nosign.go create mode 100644 api/slashed.go create mode 100644 api/tx_from_block.go diff --git a/api/addresses_full_balances.go b/api/addresses_full_balances.go new file mode 100644 index 000000000..24d5b74d0 --- /dev/null +++ b/api/addresses_full_balances.go @@ -0,0 +1,159 @@ +package api + +import ( + "github.com/MinterTeam/minter-go-node/core/state" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/formula" + "math/big" +) + +type CoinBalance struct { + Coin string `json:"coin"` + Value string `json:"value"` + BipValue string `json:"bip_value"` + DelegateBipValue string `json:"delegate_bip_value,omitempty"` +} + +type AddressBalanceResponse struct { + Freecoins []*CoinBalance `json:"freecoins"` + Delegated []*CoinBalance `json:"delegated"` + Total []*CoinBalance `json:"total"` + TransactionCount uint64 `json:"transaction_count"` + Bipvalue string `json:"bipvalue"` +} + +type AddressesBalancesResponse struct { + Address types.Address `json:"address"` + Balance *AddressBalanceResponse `json:"balance"` +} + +type UserStake struct { + Value *big.Int + BipValue *big.Int +} + +func CustomCoinBipBalance(coinToSell types.CoinSymbol, valueToSell *big.Int, cState *state.CheckState) *big.Int { + coinToBuy := types.StrToCoinSymbol("BIP") + + if coinToSell == coinToBuy { + return valueToSell + } + + if coinToSell == types.GetBaseCoin() { + coin := cState.Coins().GetCoin(coinToBuy) + return formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) + } + + if coinToBuy == types.GetBaseCoin() { + coin := cState.Coins().GetCoin(coinToSell) + return formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) + } + + coinFrom := cState.Coins().GetCoin(coinToSell) + coinTo := cState.Coins().GetCoin(coinToBuy) + basecoinValue := formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) + return formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), basecoinValue) + +} + +func MakeAddressBalance(address types.Address, height int) (*AddressBalanceResponse, error) { + cState, err := GetStateForHeight(height) + if err != nil { + return nil, err + } + + if height != 0 { + cState.Lock() + cState.Candidates().LoadCandidates() + cState.Candidates().LoadStakes() + cState.Unlock() + } + + cState.RLock() + defer cState.RUnlock() + + balances := cState.Accounts().GetBalances(address) + var response AddressBalanceResponse + + totalStakesGroupByCoin := map[types.CoinSymbol]*big.Int{} + + response.Freecoins = make([]*CoinBalance, 0, len(balances)) + for coin, value := range balances { + totalStakesGroupByCoin[coin] = value + response.Freecoins = append(response.Freecoins, &CoinBalance{ + Coin: coin.String(), + Value: value.String(), + BipValue: CustomCoinBipBalance(coin, value, cState).String(), + }) + } + + var userDelegatedStakesGroupByCoin = map[types.CoinSymbol]*UserStake{} + allCandidates := cState.Candidates().GetCandidates() + for _, candidate := range allCandidates { + userStakes := UserStakes(candidate.PubKey, address, cState) + for coin, userStake := range userStakes { + stake, ok := userDelegatedStakesGroupByCoin[coin] + if !ok { + stake = &UserStake{ + Value: big.NewInt(0), + BipValue: big.NewInt(0), + } + } + stake.Value.Add(stake.Value, userStake.Value) + stake.BipValue.Add(stake.BipValue, userStake.BipValue) + userDelegatedStakesGroupByCoin[coin] = stake + } + } + + response.Delegated = make([]*CoinBalance, 0, len(userDelegatedStakesGroupByCoin)) + for coin, delegatedStake := range userDelegatedStakesGroupByCoin { + response.Delegated = append(response.Delegated, &CoinBalance{ + Coin: coin.String(), + Value: delegatedStake.Value.String(), + DelegateBipValue: delegatedStake.BipValue.String(), + BipValue: CustomCoinBipBalance(coin, delegatedStake.Value, cState).String(), + }) + + totalStake, ok := totalStakesGroupByCoin[coin] + if !ok { + totalStake = big.NewInt(0) + totalStakesGroupByCoin[coin] = totalStake + } + totalStake.Add(totalStake, delegatedStake.Value) + } + + coinsBipValue := big.NewInt(0) + response.Total = make([]*CoinBalance, 0, len(totalStakesGroupByCoin)) + for coin, stake := range totalStakesGroupByCoin { + balance := CustomCoinBipBalance(coin, stake, cState) + response.Total = append(response.Total, &CoinBalance{ + Coin: coin.String(), + Value: stake.String(), + BipValue: balance.String(), + }) + coinsBipValue.Add(coinsBipValue, balance) + } + + response.TransactionCount = cState.Accounts().GetNonce(address) + response.Bipvalue = coinsBipValue.String() + + return &response, nil +} + +func UserStakes(c types.Pubkey, address types.Address, state *state.CheckState) map[types.CoinSymbol]*UserStake { + var userStakes = map[types.CoinSymbol]*UserStake{} + + stakes := state.Candidates().GetStakes(c) + + for _, stake := range stakes { + if stake.Owner != address { + continue + } + userStakes[stake.Coin] = &UserStake{ + Value: stake.Value, + BipValue: stake.BipValue, + } + } + + return userStakes +} diff --git a/api/api.go b/api/api.go index baa2560c2..4324f8995 100644 --- a/api/api.go +++ b/api/api.go @@ -52,6 +52,19 @@ var Routes = map[string]*rpcserver.RPCFunc{ "min_gas_price": rpcserver.NewRPCFunc(MinGasPrice, ""), "genesis": rpcserver.NewRPCFunc(Genesis, ""), "missed_blocks": rpcserver.NewRPCFunc(MissedBlocks, "pub_key,height"), + "get_stakes": rpcserver.NewRPCFunc(GetStakes, "pub_key,coin,address,height"), + "total_slashed": rpcserver.NewRPCFunc(TotalSlashed, "height"), + "height_by_time": rpcserver.NewRPCFunc(HeightByTime, "query,height"), + "frozzed": rpcserver.NewRPCFunc(FrozzedFunds, "address,coin"), + "calc_tx_commission": rpcserver.NewRPCFunc(CalcTxCommission, "gascoin,txtype,payload,mtxs,height"), + "calc_tx_free_coin": rpcserver.NewRPCFunc(CalcFreeCoinForTx, "gascoin,gascoinamount,txtype,payload,mtxs,height"), + "address_balance": rpcserver.NewRPCFunc(MakeAddressBalance, "address,height"), + "txs_from_block": rpcserver.NewRPCFunc(TxsFromBlock, "height"), + "candidate_info": rpcserver.NewRPCFunc(CandidateAlt, "pub_key,height"), + "candidates_info": rpcserver.NewRPCFunc(CandidatesAlt, "status,height"), + "nosign": rpcserver.NewRPCFunc(NoSign, "height"), + "find_events": rpcserver.NewRPCFunc(FindEvents, "search,height"), + //"grouped_events": rpcserver.NewRPCFunc(GroupedEvents, "height"), } func responseTime(b *minter.Blockchain) func(f func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) { diff --git a/api/calc_comission.go b/api/calc_comission.go new file mode 100644 index 000000000..6cbd707e2 --- /dev/null +++ b/api/calc_comission.go @@ -0,0 +1,103 @@ +package api + +import ( + "fmt" + "github.com/MinterTeam/minter-go-node/core/commissions" + "github.com/MinterTeam/minter-go-node/core/transaction" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/formula" + "github.com/MinterTeam/minter-go-node/rpc/lib/types" + "math/big" +) + +type UseMaxResponse struct { + GasCoin string `json:"gascoin"` + StartValue string `json:"startvalue"` + TXComissionValue string `json:"txvalue"` + EndValue string `json:"endvalue"` +} + +func CalcTxCommission(gasCoin string, height int, txType string, payload []byte, mtxs int64) (string, error) { + var commissionInBaseCoin *big.Int + switch txType { + case "SendTx": + commissionInBaseCoin = big.NewInt(commissions.SendTx) + case "ConvertTx": + commissionInBaseCoin = big.NewInt(commissions.ConvertTx) + case "DeclareCandidacyTx": + commissionInBaseCoin = big.NewInt(commissions.DeclareCandidacyTx) + case "DelegateTx": + commissionInBaseCoin = big.NewInt(commissions.DelegateTx) + case "UnbondTx": + commissionInBaseCoin = big.NewInt(commissions.UnbondTx) + case "ToggleCandidateStatus": + commissionInBaseCoin = big.NewInt(commissions.ToggleCandidateStatus) + case "EditCandidate": + commissionInBaseCoin = big.NewInt(commissions.EditCandidate) + case "RedeemCheckTx": + commissionInBaseCoin = big.NewInt(commissions.RedeemCheckTx) + case "CreateMultisig": + commissionInBaseCoin = big.NewInt(commissions.CreateMultisig) + case "MultiSend": + if mtxs <= 0 { + return "", rpctypes.RPCError{Code: 400, Message: "Set number of txs for multisend (mtxs)"} + } + commissionInBaseCoin = big.NewInt(commissions.MultisendDelta*(mtxs-1) + 10) + default: + return "", rpctypes.RPCError{Code: 401, Message: "Set correct txtype for tx"} + } + + if len(payload) > 1024 { + return "", rpctypes.RPCError{Code: 401, Message: fmt.Sprintf("TX payload length is over %d bytes", 1024)} + } + + totalCommissionInBaseCoin := new(big.Int).Mul(big.NewInt(0).Add(commissionInBaseCoin, big.NewInt(int64(len(payload)))), transaction.CommissionMultiplier) + + cState, err := GetStateForHeight(height) + if err != nil { + return "", err + } + + cState.RLock() + defer cState.RUnlock() + + if gasCoin == "BIP" { + return totalCommissionInBaseCoin.String(), nil + } + + coin := cState.Coins().GetCoin(types.StrToCoinSymbol(gasCoin)) + + if coin == nil { + return "", rpctypes.RPCError{Code: 404, Message: "Gas Coin not found"} + } + + if totalCommissionInBaseCoin.Cmp(coin.Reserve()) == 1 { + return "", rpctypes.RPCError{Code: 400, Message: "Not enough coin reserve for pay comission"} + } + + return formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), totalCommissionInBaseCoin).String(), nil + +} + +func CalcFreeCoinForTx(gasCoin string, gasCoinAmount string, height int, txType string, payload []byte, mtxs int64) (*UseMaxResponse, error) { + + commission, err := CalcTxCommission(gasCoin, height, txType, payload, mtxs) + + if err != nil { + return new(UseMaxResponse), err + } + + commissionBig, _ := big.NewInt(0).SetString(commission, 10) + gasCoinAmountBig, _ := big.NewInt(0).SetString(gasCoinAmount, 10) + + if gasCoinAmountBig.Cmp(commissionBig) == -1 { + return new(UseMaxResponse), rpctypes.RPCError{Code: 400, Message: "Not enough coin bipValue for pay commission"} + } + + return &UseMaxResponse{ + GasCoin: gasCoin, + StartValue: gasCoinAmountBig.String(), + TXComissionValue: commission, + EndValue: big.NewInt(0).Sub(gasCoinAmountBig, commissionBig).String(), + }, nil +} diff --git a/api/candidates_alt.go b/api/candidates_alt.go new file mode 100644 index 000000000..1eaaaee3a --- /dev/null +++ b/api/candidates_alt.go @@ -0,0 +1,119 @@ +package api + +import ( + "github.com/MinterTeam/minter-go-node/core/state" + "github.com/MinterTeam/minter-go-node/core/state/candidates" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/rpc/lib/types" + "math/big" +) + +type CandidateResponseAlt struct { + PubKey string `json:"pub_key"` + TotalStake string `json:"total_stake"` + Commission uint `json:"commission"` + UsedSlots int `json:"used_slots"` + UniqUsers int `json:"uniq_users"` + MinStake string `json:"minstake"` + Status byte `json:"status"` +} + +const ( + // CandidateOff = 0x01 + // CandidateOn = 0x02 + ValidatorOn = 0x03 + ValidatorsMaxSlots = 1000 +) + +func ResponseCandidateAlt(c *candidates.Candidate, state *state.CheckState) *CandidateResponseAlt { + stakes := state.Candidates().GetStakes(c.PubKey) + candidate := &CandidateResponseAlt{ + TotalStake: state.Candidates().GetTotalStake(c.PubKey).String(), + PubKey: c.PubKey.String(), + Commission: c.Commission, + Status: c.Status, + UsedSlots: len(stakes), + } + + addresses := map[types.Address]struct{}{} + + for _, validator := range state.Validators().GetValidators() { + if validator.PubKey != c.PubKey { + continue + } + candidate.Status = ValidatorOn + break + } + + minStake := big.NewInt(0) + for i, stake := range stakes { + addresses[stake.Owner] = struct{}{} + if candidate.UsedSlots >= ValidatorsMaxSlots { + if i != 0 && minStake.Cmp(stake.BipValue) != 1 { + continue + } + minStake = stake.BipValue + } + } + + candidate.UniqUsers = len(addresses) + candidate.MinStake = minStake.String() + + return candidate +} + +func CandidateAlt(pubkey types.Pubkey, height int) (*CandidateResponseAlt, error) { + cState, err := GetStateForHeight(height) + if err != nil { + return nil, err + } + + if height != 0 { + cState.Lock() + cState.Candidates().LoadCandidates() + cState.Candidates().LoadStakes() + cState.Validators().LoadValidators() + cState.Unlock() + } + + cState.RLock() + defer cState.RUnlock() + + candidate := cState.Candidates().GetCandidate(pubkey) + if candidate == nil { + return nil, rpctypes.RPCError{Code: 404, Message: "Candidate not found"} + } + + return ResponseCandidateAlt(candidate, cState), nil +} + +func CandidatesAlt(height int, status int) ([]*CandidateResponseAlt, error) { + cState, err := GetStateForHeight(height) + if err != nil { + return nil, err + } + + if height != 0 { + cState.Lock() + cState.Candidates().LoadCandidates() + cState.Validators().LoadValidators() + cState.Candidates().LoadStakes() + cState.Unlock() + } + + cState.RLock() + defer cState.RUnlock() + + var result []*CandidateResponseAlt + + allCandidates := cState.Candidates().GetCandidates() + for _, candidate := range allCandidates { + candidateInfo := ResponseCandidateAlt(candidate, cState) + if status != 0 && candidateInfo.Status != byte(status) { + continue + } + result = append(result, candidateInfo) + } + + return result, nil +} diff --git a/api/find_events.go b/api/find_events.go new file mode 100644 index 000000000..6242d43e2 --- /dev/null +++ b/api/find_events.go @@ -0,0 +1,24 @@ +package api + +import ( + eventsdb "github.com/MinterTeam/minter-go-node/core/events" +) + +type FindEventsResponse struct { + Events eventsdb.Events `json:"events"` +} + +func FindEvents(search []string, height uint64) (*FindEventsResponse, error) { + var result FindEventsResponse + events := blockchain.GetEventsDB().LoadEvents(uint32(height)) + + for _, event := range events { + for _, addr := range search { + if event.AddressString() == addr || event.ValidatorPubKeyString() == addr { + result.Events = append(result.Events, event) + } + } + } + + return &result, nil +} diff --git a/api/frozzen.go b/api/frozzen.go new file mode 100644 index 000000000..6b5860f08 --- /dev/null +++ b/api/frozzen.go @@ -0,0 +1,69 @@ +package api + +import ( + "github.com/MinterTeam/minter-go-node/core/types" +) + +type FrozInfo struct { + Height int `json:"height"` + Address types.Address `json:"address"` + CandidateKey *types.Pubkey `json:"candidateKey"` + Coin types.CoinSymbol `json:"coin"` + Value string `json:"value"` +} + +func FrozzedFunds(address types.Address, coin string) ([]*FrozInfo, error) { + cState := blockchain.CurrentState() + cState.RLock() + defer cState.RUnlock() + + var frozes []*FrozInfo + + appState := new(types.AppState) + cState.FrozenFunds().Export(appState, blockchain.Height()) + + var emptyAddress types.Address + + if coin == "" && address == emptyAddress { + for _, fund := range appState.FrozenFunds { + frozes = append(frozes, &FrozInfo{ + Height: int(fund.Height), + Address: fund.Address, + CandidateKey: fund.CandidateKey, + Coin: fund.Coin, + Value: fund.Value, + }) + } + return frozes, nil + } + + if coin != "" && address != emptyAddress { + for _, fund := range appState.FrozenFunds { + if fund.Coin.String() != coin || fund.Address != address { + continue + } + frozes = append(frozes, &FrozInfo{ + Height: int(fund.Height), + Address: fund.Address, + CandidateKey: fund.CandidateKey, + Coin: fund.Coin, + Value: fund.Value, + }) + } + return frozes, nil + } + + for _, fund := range appState.FrozenFunds { + if fund.Coin.String() != coin && fund.Address != address { + continue + } + frozes = append(frozes, &FrozInfo{ + Height: int(fund.Height), + Address: fund.Address, + CandidateKey: fund.CandidateKey, + Coin: fund.Coin, + Value: fund.Value, + }) + } + return frozes, nil +} diff --git a/api/get_stakes.go b/api/get_stakes.go new file mode 100644 index 000000000..322d9efe8 --- /dev/null +++ b/api/get_stakes.go @@ -0,0 +1,84 @@ +package api + +import ( + "github.com/MinterTeam/minter-go-node/core/state" + "github.com/MinterTeam/minter-go-node/core/state/candidates" + "github.com/MinterTeam/minter-go-node/core/types" +) + +type CStake struct { + Address string `json:"address"` + PubKey string `json:"pub_key"` + Coin string `json:"coin"` + Value string `json:"value"` + BipValue string `json:"bip_value"` +} + +func ResponseStakes(state *state.CheckState, c *candidates.Candidate, coin string, address types.Address) []*CStake { + var coinStakes []*CStake + + var multi bool + var allPubkeyStakes bool + + var emptyAddress types.Address + + if coin != "" && address != emptyAddress { + multi = true + } + if coin == "" && address == emptyAddress { + allPubkeyStakes = true + } + + stakes := state.Candidates().GetStakes(c.PubKey) + for _, stake := range stakes { + if !((multi && stake.Coin.String() == coin && stake.Owner == address) || (!multi && (stake.Coin.String() == coin || stake.Owner == address || allPubkeyStakes))) { + continue + } + coinStakes = append(coinStakes, &CStake{ + Address: stake.Owner.String(), + PubKey: c.PubKey.String(), + Coin: stake.Coin.String(), + Value: stake.Value.String(), + BipValue: stake.BipValue.String(), + }) + } + + return coinStakes +} + +func GetStakes(pubkey types.Pubkey, height int, coin string, address types.Address) ([]*CStake, error) { + var coinStakes []*CStake + + cState, err := GetStateForHeight(height) + if err != nil { + return nil, err + } + + if height != 0 { + cState.Lock() + cState.Candidates().LoadCandidates() + cState.Candidates().LoadStakes() + cState.Unlock() + } + + cState.RLock() + defer cState.RUnlock() + + var emptyPyb types.Pubkey + + var allCandidates []*candidates.Candidate + if pubkey == emptyPyb { + allCandidates = cState.Candidates().GetCandidates() + } else { + allCandidates = []*candidates.Candidate{cState.Candidates().GetCandidate(pubkey)} + } + + for _, candidate := range allCandidates { + tmresponse := ResponseStakes(cState, candidate, coin, address) + for _, coinStake := range tmresponse { + coinStakes = append(coinStakes, coinStake) + } + } + + return coinStakes, nil +} diff --git a/api/grouped_events.go b/api/grouped_events.go new file mode 100644 index 000000000..d8e3187d3 --- /dev/null +++ b/api/grouped_events.go @@ -0,0 +1,82 @@ +package api + +import ( + compact_db "github.com/MinterTeam/minter-go-node/core/events" + "github.com/MinterTeam/minter-go-node/core/types" + "math/big" +) + +type EventsResponseValidator struct { + Pubkey string `json:"pub_key"` + DaoRole string `json:"dao"` + DeveloperRole string `json:"developers"` + ValidatorRole string `json:"validator"` + DelegatorRole string `json:"delegator"` +} + +func GroupedEvents(height int64) ([]*EventsResponseValidator, error) { + + recipients := map[string]struct{}{"Validator": {}, "Delegator": {}, "DAO": {}, "Developers": {}} + + if height == 0 { + height = int64(blockchain.Height()) + } + + tmVals, err := client.Validators(&height, 1, 100) + if err != nil { + return nil, err + } + + mapPubkeyEvents := map[types.Pubkey][]*compact_db.RewardEvent{} + events := blockchain.GetEventsDB().LoadEvents(uint32(height)) + for _, event := range events { + e, ok := event.(*compact_db.RewardEvent) + if !ok { + continue + } + if _, ok := recipients[e.Role]; !ok { + continue + } + mapPubkeyEvents[e.ValidatorPubKey] = append(mapPubkeyEvents[e.ValidatorPubKey], e) + } + + var responseValidators []*EventsResponseValidator + for _, val := range tmVals.Validators { + pubKey := types.BytesToPubkey(val.PubKey.Bytes()[5:]) + events, ok := mapPubkeyEvents[pubKey] + if !ok { + continue + } + + validator := &EventsResponseValidator{ + Pubkey: pubKey.String(), + } + + delegatorRoleValue := big.NewInt(0) + for _, event := range events { + eventDelegatorAmount := big.NewInt(0) + switch event.Role { + case "Validator": + validator.ValidatorRole = event.Role + case "Delegator": + eventDelegatorAmount.SetString(event.Amount, 10) + case "DAO": + validator.DaoRole = event.Role + case "Developers": + validator.DeveloperRole = event.Role + default: + continue + } + delegatorRoleValue.Add(delegatorRoleValue, eventDelegatorAmount) + } + if validator.DaoRole == "" { + continue + } + + validator.DelegatorRole = delegatorRoleValue.String() + + responseValidators = append(responseValidators, validator) + } + + return responseValidators, nil +} diff --git a/api/heigt_by_time.go b/api/heigt_by_time.go new file mode 100644 index 000000000..2d861eb56 --- /dev/null +++ b/api/heigt_by_time.go @@ -0,0 +1,73 @@ +package api + +import ( + "github.com/MinterTeam/minter-go-node/rpc/lib/types" + "time" +) + +func DurationTime(height int64, count int64) time.Duration { + if count < 2 { + count = 120 + } + block1, _ := client.Block(&height) + time1 := block1.Block.Time + + height2 := height - count + block2, _ := client.Block(&height2) + duration := time1.Sub(block2.Block.Time) + + return time.Duration(duration.Nanoseconds() / count) +} + +func HeightByTime(query string, height int64) (int64, error) { + + h := int64(blockchain.Height()) + if height > h { + return 0, rpctypes.RPCError{Code: 404, Message: "Inputed block higher actual block"} + } + if height == 0 { + height = h + } + + duration := DurationTime(height, 120) + + block, err := client.Block(&height) + if err != nil { + return 0, err + } + + var sub time.Duration + switch query { + case "day": + sub = time.Hour * 24 + case "week": + sub = time.Hour * 24 * 7 + case "": + return height, nil + default: + target, err := time.Parse(time.RFC3339, query) + if err != nil { + return 0, rpctypes.RPCError{Code: 404, Message: "Incorrect query time", Data: err.Error()} + } + sub = block.Block.Time.Sub(target) + } + + difference := -float64(sub / duration) + targetTime := block.Block.Time.Add(-sub) + + for { + height += int64(difference) + block2, err := client.Block(&height) + if err != nil { + return 0, err + } + result := targetTime.Sub(block2.Block.Time) + difference = float64(result) / float64(DurationTime(height, 2)) + if int(difference) == 0 { + if difference > 0 { + return height, nil + } + return height - 1, nil + } + } +} diff --git a/api/nosign.go b/api/nosign.go new file mode 100644 index 000000000..a8a5e83ed --- /dev/null +++ b/api/nosign.go @@ -0,0 +1,62 @@ +package api + +import ( + "fmt" + "github.com/MinterTeam/minter-go-node/rpc/lib/types" +) + +type MissBlock struct { + Height int64 `json:"height"` + Proposer string `json:"proposer,omitempty"` + Pubkey string `json:"pub_key"` +} + +func NoSign(height int64) ([]*MissBlock, error) { + block, err := client.Block(&height) + if err != nil { + return nil, rpctypes.RPCError{Code: 404, Message: "Block not found", Data: err.Error()} + } + + valHeight := height - 1 + if valHeight < 1 { + valHeight = 1 + } + + var mbs []*MissBlock + + totalValidators, err := client.Validators(&valHeight, 1, 100) + if err != nil { + return nil, rpctypes.RPCError{Code: 500, Message: err.Error()} + } + var proposer string + if height <= 1 { + return mbs, nil + } + p, err := getBlockProposer(block, totalValidators.Validators) + if err != nil { + return nil, err + } + if p != nil { + proposer = p.String() + } + + sign := map[string]struct{}{} + for _, vote := range block.Block.LastCommit.Signatures { + sign[vote.ValidatorAddress.String()] = struct{}{} + } + + for _, tmval := range totalValidators.Validators { + if _, ok := sign[tmval.Address.String()]; ok { + continue + } + mb := &MissBlock{ + Height: height, + Proposer: proposer, + Pubkey: fmt.Sprintf("Mp%x", tmval.PubKey.Bytes()[5:]), + } + mbs = append(mbs, mb) + break + } + + return mbs, nil +} diff --git a/api/slashed.go b/api/slashed.go new file mode 100644 index 000000000..785aaa07d --- /dev/null +++ b/api/slashed.go @@ -0,0 +1,18 @@ +package api + +import ( + "math/big" +) + +func TotalSlashed(height int) (*big.Int, error) { + cState, err := GetStateForHeight(height) + if err != nil { + return nil, err + } + + cState.RLock() + defer cState.RUnlock() + + totalslashed := cState.App().GetTotalSlashed() + return totalslashed, nil +} diff --git a/api/tx_from_block.go b/api/tx_from_block.go new file mode 100644 index 000000000..2d0ba1723 --- /dev/null +++ b/api/tx_from_block.go @@ -0,0 +1,63 @@ +package api + +import ( + "encoding/json" + "fmt" + "github.com/MinterTeam/minter-go-node/core/transaction" + "time" +) + +type TransactionsResponse struct { + Height int64 `json:"height"` + Time time.Time `json:"time"` + Hash string `json:"hash"` + Type uint8 `json:"type"` + From string `json:"from"` + Nonce uint64 `json:"nonce"` + Data json.RawMessage `json:"data"` + Payload []byte `json:"payload"` + ServiceData []byte `json:"service_data"` + Gas int64 `json:"gas"` + GasCoin string `json:"gas_coin"` + Code uint32 `json:"code,omitempty"` + Log string `json:"log,omitempty"` +} + +func TxsFromBlock(height int64) ([]*TransactionsResponse, error) { + block, _ := client.Block(&height) + blockResults, _ := client.BlockResults(&height) + + countTx := len(block.Block.Data.Txs) + trs := make([]*TransactionsResponse, 0, countTx) + + if len(blockResults.TxsResults) != countTx { + return trs, nil + } + + for i, rawTx := range block.Block.Data.Txs { + tx, _ := transaction.TxDecoder.DecodeFromBytes(rawTx) + + sender, _ := tx.Sender() + data, _ := encodeTxData(tx) + + tr := &TransactionsResponse{ + Height: block.Block.Height, + Time: block.Block.Time, + Hash: fmt.Sprintf("Mt%x", rawTx.Hash()), + Type: uint8(tx.Type), + From: sender.String(), + Nonce: tx.Nonce, + Data: data, + Payload: tx.Payload, + ServiceData: tx.ServiceData, + Gas: tx.Gas(), + GasCoin: tx.GasCoin.String(), + Code: blockResults.TxsResults[i].Code, + Log: blockResults.TxsResults[i].Log, + } + + trs = append(trs, tr) + } + + return trs, nil +} diff --git a/core/state/app/app.go b/core/state/app/app.go index 5c1215967..12d3cfa51 100644 --- a/core/state/app/app.go +++ b/core/state/app/app.go @@ -14,6 +14,7 @@ const mainPrefix = 'd' type RApp interface { Export(state *types.AppState, height uint64) GetMaxGas() uint64 + GetTotalSlashed() *big.Int } func (v *App) Tree() tree.ReadOnlyTree { From 186bebfcb32e9f86f17ecc5036fde2aa2e84256a Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 17 Jun 2020 13:23:10 +0300 Subject: [PATCH 033/426] If KeepLastStates is 0, then the KeepEver and KeepRecent strategies are used. --- cmd/minter/cmd/export.go | 2 +- config/config.go | 3 +++ config/toml.go | 7 +++++-- core/minter/minter.go | 4 ++-- core/minter/upgrade3_test.go | 2 +- core/state/candidates_test.go | 2 +- core/state/state.go | 29 ++++++++++++++++++++++++----- core/state/state_test.go | 2 +- core/transaction/buy_coin_test.go | 2 +- tree/tree.go | 4 ++-- 10 files changed, 41 insertions(+), 16 deletions(-) diff --git a/cmd/minter/cmd/export.go b/cmd/minter/cmd/export.go index b05105a9a..dffbe078b 100644 --- a/cmd/minter/cmd/export.go +++ b/cmd/minter/cmd/export.go @@ -58,7 +58,7 @@ func export(cmd *cobra.Command, args []string) error { log.Panicf("Cannot load db: %s", err) } - currentState, err := state.NewState(height, ldb, nil, 1, 1, 0) + currentState, err := state.NewState(height, ldb, nil, 1, 1, 0, 1) if err != nil { log.Panicf("Cannot new state at given height: %s", err) } diff --git a/config/config.go b/config/config.go index 8a2fd8ea5..925da74e4 100644 --- a/config/config.go +++ b/config/config.go @@ -235,6 +235,8 @@ type BaseConfig struct { ValidatorMode bool `mapstructure:"validator_mode"` + KeepLastStates int64 `mapstructure:"keep_last_states"` + APISimultaneousRequests int `mapstructure:"api_simultaneous_requests"` LogPath string `mapstructure:"log_path"` @@ -268,6 +270,7 @@ func DefaultBaseConfig() BaseConfig { GRPCListenAddress: "tcp://0.0.0.0:8842", APIv2ListenAddress: "tcp://0.0.0.0:8843", ValidatorMode: false, + KeepLastStates: 120, StateCacheSize: 1000000, StateKeepEver: 120, StateKeepRecent: 1200, diff --git a/config/toml.go b/config/toml.go index b73471fea..4c3ad775e 100644 --- a/config/toml.go +++ b/config/toml.go @@ -78,13 +78,16 @@ api_v2_listen_addr = "{{ .BaseConfig.APIv2ListenAddress }}" # Sets node to be in validator mode. Disables API, events, history of blocks, indexes, etc. validator_mode = {{ .BaseConfig.ValidatorMode }} +# Sets number of last stated to be saved on disk. If the value is 0, then the KeepEver and KeepRecent strategies are used. +keep_last_states = {{ .BaseConfig.KeepLastStates }} + # State cache size state_cache_size = {{ .BaseConfig.StateCacheSize }} -# State keep ever +# Sets periodicity to save state on disk state_keep_ever = {{ .BaseConfig.StateKeepEver }} -# State keep recent +# Sets the number of stores the last state in the memory state_keep_recent = {{ .BaseConfig.StateKeepRecent }} # State memory in MB diff --git a/core/minter/minter.go b/core/minter/minter.go index 30bb79ff7..0e966cb40 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -107,7 +107,7 @@ func NewMinterBlockchain(cfg *config.Config) *Blockchain { } // Set stateDeliver and stateCheck - blockchain.stateDeliver, err = state.NewState(blockchain.height, blockchain.stateDB, blockchain.eventsDB, cfg.StateCacheSize, cfg.StateKeepEver, cfg.StateKeepRecent) + blockchain.stateDeliver, err = state.NewState(blockchain.height, blockchain.stateDB, blockchain.eventsDB, cfg.StateCacheSize, cfg.StateKeepEver, cfg.StateKeepRecent, cfg.KeepLastStates) if err != nil { panic(err) } @@ -177,7 +177,7 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res if upgrades.IsUpgradeBlock(height) { var err error - app.stateDeliver, err = state.NewState(app.height, app.stateDB, app.eventsDB, app.cfg.StateCacheSize, app.cfg.StateKeepEver, app.cfg.StateKeepRecent) + app.stateDeliver, err = state.NewState(app.height, app.stateDB, app.eventsDB, app.cfg.StateCacheSize, app.cfg.StateKeepEver, app.cfg.StateKeepRecent, app.cfg.KeepLastStates) if err != nil { panic(err) } diff --git a/core/minter/upgrade3_test.go b/core/minter/upgrade3_test.go index 9d1be7d9a..ea7ebebe2 100644 --- a/core/minter/upgrade3_test.go +++ b/core/minter/upgrade3_test.go @@ -38,7 +38,7 @@ func TestApplyUpgrade3(t *testing.T) { } func getState() *state.State { - s, err := state.NewState(0, db.NewMemDB(), emptyEvents{}, 1, 1, 0) + s, err := state.NewState(0, db.NewMemDB(), emptyEvents{}, 1, 1, 0, 1) if err != nil { panic(err) diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index e475d7414..88ff753d4 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -390,7 +390,7 @@ func TestDelegationAfterUnbond(t *testing.T) { } func getState() *State { - s, err := NewState(0, db.NewMemDB(), emptyEvents{}, 1, 1, 0) + s, err := NewState(0, db.NewMemDB(), emptyEvents{}, 1, 1, 0, 1) if err != nil { panic(err) diff --git a/core/state/state.go b/core/state/state.go index 4c89558ea..074e0bfad 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -16,6 +16,7 @@ import ( "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/tree" + "github.com/tendermint/iavl" db "github.com/tendermint/tm-db" "log" "math/big" @@ -98,10 +99,15 @@ type State struct { func (s *State) isValue_State() {} -func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, keepEvery, keepRecent int64) (*State, error) { - iavlTree := tree.NewMutableTree(height, db, cacheSize, keepEvery, keepRecent) +func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, keepEvery, keepRecent, keepLastStates int64) (*State, error) { + options := iavl.DefaultOptions() + if keepLastStates == 0 { + options = iavl.PruningOptions(keepEvery, keepRecent) + } + + iavlTree := tree.NewMutableTree(height, db, cacheSize, options) - state, err := newStateForTree(iavlTree, events, db, keepRecent) + state, err := newStateForTree(iavlTree, events, db, keepLastStates) if err != nil { return nil, err } @@ -114,7 +120,7 @@ func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, } func NewCheckStateAtHeight(height uint64, db db.DB) (*CheckState, error) { - iavlTree := tree.NewMutableTree(0, db, 1024, 1, 0) + iavlTree := tree.NewMutableTree(0, db, 1024, nil) _, err := iavlTree.LazyLoadVersion(int64(height)) if err != nil { return nil, err @@ -190,11 +196,24 @@ func (s *State) Commit() ([]byte, error) { return nil, err } - hash, _, err := s.tree.SaveVersion() + hash, version, err := s.tree.SaveVersion() if err != nil { return hash, err } + if s.keepLastStates == 0 { + return hash, nil + } + + versions := s.tree.AvailableVersions() + for _, v := range versions { + if v < int(version-s.keepLastStates) { + if err := s.tree.DeleteVersion(int64(v)); err != nil { + return hash, err + } + } + } + return hash, nil } diff --git a/core/state/state_test.go b/core/state/state_test.go index 6e79377f4..75f394140 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -15,7 +15,7 @@ import ( func TestStateExport(t *testing.T) { height := uint64(0) - state, err := NewState(height, db.NewMemDB(), emptyEvents{}, 1, 1, 0) + state, err := NewState(height, db.NewMemDB(), emptyEvents{}, 1, 1, 0, 1) if err != nil { log.Panic("Cannot create state") } diff --git a/core/transaction/buy_coin_test.go b/core/transaction/buy_coin_test.go index b03e75064..21c627056 100644 --- a/core/transaction/buy_coin_test.go +++ b/core/transaction/buy_coin_test.go @@ -27,7 +27,7 @@ var ( ) func getState() *state.State { - s, err := state.NewState(0, db.NewMemDB(), nil, 1, 1, 0) + s, err := state.NewState(0, db.NewMemDB(), nil, 1, 1, 0, 1) if err != nil { panic(err) diff --git a/tree/tree.go b/tree/tree.go index 430e1c270..0913fc798 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -27,8 +27,8 @@ type MTree interface { GetImmutableAtHeight(version int64) (*ImmutableTree, error) } -func NewMutableTree(height uint64, db dbm.DB, cacheSize int, keepEvery, keepRecent int64) MTree { - tree, err := iavl.NewMutableTreeWithOpts(db, dbm.NewMemDB(), cacheSize, iavl.PruningOptions(keepEvery, keepRecent)) +func NewMutableTree(height uint64, db dbm.DB, cacheSize int, options *iavl.Options) MTree { + tree, err := iavl.NewMutableTreeWithOpts(db, dbm.NewMemDB(), cacheSize, options) if err != nil { panic(err) } From 41b78c35a1d9d939e2838d7f738d6e0106d79506 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 17 Jun 2020 16:35:55 +0300 Subject: [PATCH 034/426] KeepLastStates default 0 --- config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.go b/config/config.go index 925da74e4..ef2535cc1 100644 --- a/config/config.go +++ b/config/config.go @@ -270,7 +270,7 @@ func DefaultBaseConfig() BaseConfig { GRPCListenAddress: "tcp://0.0.0.0:8842", APIv2ListenAddress: "tcp://0.0.0.0:8843", ValidatorMode: false, - KeepLastStates: 120, + KeepLastStates: 0, StateCacheSize: 1000000, StateKeepEver: 120, StateKeepRecent: 1200, From a43e0b9d7c318ed5ddfdde34eb5039ed9d6ced19 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 17 Jun 2020 21:29:23 +0300 Subject: [PATCH 035/426] fixes --- api/api.go | 4 ++-- api/calc_comission.go | 6 +++--- api/candidates_alt.go | 2 +- api/estimate_coin_sell.go | 4 +--- api/get_stakes.go | 2 +- cli/service/service.go | 2 +- core/minter/minter.go | 20 ++++++++++++-------- tree/tree.go | 7 ------- 8 files changed, 21 insertions(+), 26 deletions(-) diff --git a/api/api.go b/api/api.go index 4324f8995..3d00160e0 100644 --- a/api/api.go +++ b/api/api.go @@ -56,8 +56,8 @@ var Routes = map[string]*rpcserver.RPCFunc{ "total_slashed": rpcserver.NewRPCFunc(TotalSlashed, "height"), "height_by_time": rpcserver.NewRPCFunc(HeightByTime, "query,height"), "frozzed": rpcserver.NewRPCFunc(FrozzedFunds, "address,coin"), - "calc_tx_commission": rpcserver.NewRPCFunc(CalcTxCommission, "gascoin,txtype,payload,mtxs,height"), - "calc_tx_free_coin": rpcserver.NewRPCFunc(CalcFreeCoinForTx, "gascoin,gascoinamount,txtype,payload,mtxs,height"), + "calc_tx_commission": rpcserver.NewRPCFunc(CalcTxCommission, "gas_coin,tx_type,payload,mtxs,height"), + "calc_tx_free_coin": rpcserver.NewRPCFunc(CalcFreeCoinForTx, "gas_coin,gas_coin_amount,tx_type,payload,mtxs,height"), "address_balance": rpcserver.NewRPCFunc(MakeAddressBalance, "address,height"), "txs_from_block": rpcserver.NewRPCFunc(TxsFromBlock, "height"), "candidate_info": rpcserver.NewRPCFunc(CandidateAlt, "pub_key,height"), diff --git a/api/calc_comission.go b/api/calc_comission.go index 6cbd707e2..967167846 100644 --- a/api/calc_comission.go +++ b/api/calc_comission.go @@ -17,7 +17,7 @@ type UseMaxResponse struct { EndValue string `json:"endvalue"` } -func CalcTxCommission(gasCoin string, height int, txType string, payload []byte, mtxs int64) (string, error) { +func CalcTxCommission(gasCoin string, txType string, payload []byte, mtxs int64, height int) (string, error) { var commissionInBaseCoin *big.Int switch txType { case "SendTx": @@ -79,9 +79,9 @@ func CalcTxCommission(gasCoin string, height int, txType string, payload []byte, } -func CalcFreeCoinForTx(gasCoin string, gasCoinAmount string, height int, txType string, payload []byte, mtxs int64) (*UseMaxResponse, error) { +func CalcFreeCoinForTx(gasCoin string, gasCoinAmount string, txType string, payload []byte, mtxs int64, height int) (*UseMaxResponse, error) { - commission, err := CalcTxCommission(gasCoin, height, txType, payload, mtxs) + commission, err := CalcTxCommission(gasCoin, txType, payload, mtxs, height) if err != nil { return new(UseMaxResponse), err diff --git a/api/candidates_alt.go b/api/candidates_alt.go index 1eaaaee3a..985ced57b 100644 --- a/api/candidates_alt.go +++ b/api/candidates_alt.go @@ -87,7 +87,7 @@ func CandidateAlt(pubkey types.Pubkey, height int) (*CandidateResponseAlt, error return ResponseCandidateAlt(candidate, cState), nil } -func CandidatesAlt(height int, status int) ([]*CandidateResponseAlt, error) { +func CandidatesAlt(status int, height int) ([]*CandidateResponseAlt, error) { cState, err := GetStateForHeight(height) if err != nil { return nil, err diff --git a/api/estimate_coin_sell.go b/api/estimate_coin_sell.go index 64881924e..37e2cef13 100644 --- a/api/estimate_coin_sell.go +++ b/api/estimate_coin_sell.go @@ -15,9 +15,7 @@ type EstimateCoinSellResponse struct { Commission string `json:"commission"` } -func EstimateCoinSell( - coinToSellString string, coinToBuyString string, valueToSell *big.Int, height int) (*EstimateCoinSellResponse, - error) { +func EstimateCoinSell(coinToSellString string, coinToBuyString string, valueToSell *big.Int, height int) (*EstimateCoinSellResponse, error) { cState, err := GetStateForHeight(height) if err != nil { return nil, err diff --git a/api/get_stakes.go b/api/get_stakes.go index 322d9efe8..656eb5410 100644 --- a/api/get_stakes.go +++ b/api/get_stakes.go @@ -46,7 +46,7 @@ func ResponseStakes(state *state.CheckState, c *candidates.Candidate, coin strin return coinStakes } -func GetStakes(pubkey types.Pubkey, height int, coin string, address types.Address) ([]*CStake, error) { +func GetStakes(pubkey types.Pubkey, coin string, address types.Address, height int) ([]*CStake, error) { var coinStakes []*CStake cState, err := GetStateForHeight(height) diff --git a/cli/service/service.go b/cli/service/service.go index 0fe8305f3..00385f263 100644 --- a/cli/service/service.go +++ b/cli/service/service.go @@ -246,7 +246,7 @@ func (m *Manager) NetInfo(context.Context, *empty.Empty) (*pb.NetInfoResponse, e func (m *Manager) PruneBlocks(ctx context.Context, req *pb.PruneBlocksRequest) (*empty.Empty, error) { res := new(empty.Empty) - err := m.blockchain.PruneBlocks(req.FromHeight, req.ToHeight) + err := m.blockchain.PruneBlocks(ctx, req.FromHeight, req.ToHeight) if err != nil { return res, status.Error(codes.FailedPrecondition, err.Error()) } diff --git a/core/minter/minter.go b/core/minter/minter.go index 0e966cb40..160b9ad21 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -2,6 +2,7 @@ package minter import ( "bytes" + "context" "errors" "fmt" "github.com/MinterTeam/minter-go-node/cmd/utils" @@ -31,6 +32,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "math/big" + "runtime" "sort" "strings" "sync" @@ -507,8 +509,6 @@ func (app *Blockchain) CurrentState() *state.CheckState { // Get immutable state of Minter Blockchain for given height func (app *Blockchain) GetStateForHeight(height uint64) (*state.CheckState, error) { if height > 0 { - app.lock.RLock() - defer app.lock.RUnlock() s, err := state.NewCheckStateAtHeight(height, app.stateDB) if err != nil { return nil, errors.New("state at given height not found") @@ -683,17 +683,13 @@ func (app *Blockchain) MaxPeerHeight() int64 { return max } -func (app *Blockchain) PruneBlocks(from int64, to int64) error { - app.stateDeliver.Lock() - defer app.stateDeliver.Unlock() - - versions := app.stateDeliver.Tree().AvailableVersions() - +func (app *Blockchain) PruneBlocks(ctx context.Context, from int64, to int64) error { lastSnapshotVersion := app.appDB.GetLastHeight() if uint64(to) >= lastSnapshotVersion { return fmt.Errorf("cannot delete last version saved in disk (%d)", lastSnapshotVersion) } + versions := app.stateDeliver.Tree().AvailableVersions() for _, v := range versions { v := int64(v) if v < from { @@ -702,9 +698,17 @@ func (app *Blockchain) PruneBlocks(from int64, to int64) error { if v >= to { break } + if err := app.stateDeliver.Tree().DeleteVersion(v); err != nil { return err } + + select { + case <-ctx.Done(): + return ctx.Err() + default: + runtime.Gosched() + } } return nil diff --git a/tree/tree.go b/tree/tree.go index 0913fc798..44d1798fb 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -156,13 +156,6 @@ func (t *mutableTree) AvailableVersions() []int { defer t.lock.Unlock() return t.tree.AvailableVersions() - -} - -func NewImmutableTree(db dbm.DB) *ImmutableTree { - return &ImmutableTree{ - tree: iavl.NewImmutableTree(db, 1024), - } } type ImmutableTree struct { From 0d4e04a5b430052c10a5eea86d360b44f36d72c1 Mon Sep 17 00:00:00 2001 From: klim0v Date: Sun, 21 Jun 2020 00:05:06 +0300 Subject: [PATCH 036/426] check min reserve and max supply --- api/v2/service/estimate_coin_buy.go | 55 +++++++-------------- api/v2/service/estimate_coin_sell.go | 57 +++++++++++---------- api/v2/service/estimate_coin_sell_all.go | 63 ++++++------------------ 3 files changed, 62 insertions(+), 113 deletions(-) diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index 748a87d9c..fa8ac9b2e 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -25,8 +25,6 @@ func (s *Service) EstimateCoinBuy(_ context.Context, req *pb.EstimateCoinBuyRequ coinToSell := types.StrToCoinSymbol(req.CoinToSell) coinToBuy := types.StrToCoinSymbol(req.CoinToBuy) - var result *big.Int - if coinToSell == coinToBuy { return new(pb.EstimateCoinBuyResponse), status.Error(codes.FailedPrecondition, "\"From\" coin equals to \"to\" coin") } @@ -43,18 +41,19 @@ func (s *Service) EstimateCoinBuy(_ context.Context, req *pb.EstimateCoinBuyRequ commissionInBaseCoin.Mul(commissionInBaseCoin, transaction.CommissionMultiplier) commission := big.NewInt(0).Set(commissionInBaseCoin) - if coinToSell != types.GetBaseCoin() { - coin := cState.Coins().GetCoin(coinToSell) + coinFrom := cState.Coins().GetCoin(coinToSell) + coinTo := cState.Coins().GetCoin(coinToBuy) - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { + if coinToSell != types.GetBaseCoin() { + if coinFrom.Reserve().Cmp(commissionInBaseCoin) < 0 { return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", - coin.Reserve().String(), commissionInBaseCoin.String())), transaction.EncodeError(map[string]string{ - "has": coin.Reserve().String(), + coinFrom.Reserve().String(), commissionInBaseCoin.String())), transaction.EncodeError(map[string]string{ + "has": coinFrom.Reserve().String(), "required": commissionInBaseCoin.String(), })) } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + commission = formula.CalculateSaleAmount(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), commissionInBaseCoin) } valueToBuy, ok := big.NewInt(0).SetString(req.ValueToBuy, 10) @@ -62,41 +61,23 @@ func (s *Service) EstimateCoinBuy(_ context.Context, req *pb.EstimateCoinBuyRequ return new(pb.EstimateCoinBuyResponse), status.Error(codes.InvalidArgument, "Value to buy not specified") } - switch { - case coinToSell == types.GetBaseCoin(): - coin := cState.Coins().GetCoin(coinToBuy) - result = formula.CalculatePurchaseAmount(coin.Volume(), coin.Reserve(), coin.Crr(), valueToBuy) - case coinToBuy == types.GetBaseCoin(): - coin := cState.Coins().GetCoin(coinToSell) - - if coin.Reserve().Cmp(valueToBuy) < 0 { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", - coin.Reserve().String(), valueToBuy.String())), transaction.EncodeError(map[string]string{ - "has": coin.Reserve().String(), - "required": valueToBuy.String(), - })) + value := valueToBuy + if coinToSell != types.GetBaseCoin() { + value = formula.CalculatePurchaseAmount(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToBuy) + if errResp := transaction.CheckReserveUnderflow(coinFrom, value); errResp != nil { + return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } + } - result = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), valueToBuy) - default: - coinFrom := cState.Coins().GetCoin(coinToSell) - coinTo := cState.Coins().GetCoin(coinToBuy) - baseCoinNeeded := formula.CalculatePurchaseAmount(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), valueToBuy) - - if coinFrom.Reserve().Cmp(baseCoinNeeded) < 0 { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", - coinFrom.Reserve().String(), baseCoinNeeded.String())), transaction.EncodeError(map[string]string{ - "has": coinFrom.Reserve().String(), - "required": baseCoinNeeded.String(), - })) - + if coinToBuy != types.GetBaseCoin() { + if errResp := transaction.CheckForCoinSupplyOverflow(coinTo.Volume(), value, coinTo.MaxSupply()); errResp != nil { + return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } - - result = formula.CalculateSaleAmount(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), baseCoinNeeded) + value = formula.CalculateSaleAmount(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), value) } return &pb.EstimateCoinBuyResponse{ - WillPay: result.String(), + WillPay: value.String(), Commission: commission.String(), }, nil } diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index 47041685d..b275340b2 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -53,45 +53,48 @@ func (s *Service) EstimateCoinSell(_ context.Context, req *pb.EstimateCoinSellRe return new(pb.EstimateCoinSellResponse), status.Error(codes.InvalidArgument, "Value to sell not specified") } + coinFrom := cState.Coins().GetCoin(coinToSell) + coinTo := cState.Coins().GetCoin(coinToBuy) + if coinToSell != types.GetBaseCoin() { - coin := cState.Coins().GetCoin(coinToSell) - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", - coin.Reserve().String(), commissionInBaseCoin.String())), transaction.EncodeError(map[string]string{ - "has": coin.Reserve().String(), - "required": commissionInBaseCoin.String(), + if coinFrom.Volume().Cmp(valueToSell) < 0 { + return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin volume balance is not sufficient for transaction. Has: %s, required %s", + coinFrom.Volume().String(), valueToSell.String())), transaction.EncodeError(map[string]string{ + "volume_has": coinFrom.Volume().String(), + "volume_required": valueToSell.String(), })) } - if coin.Volume().Cmp(valueToSell) < 0 { + if coinFrom.Reserve().Cmp(commissionInBaseCoin) < 0 { return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", - coin.Reserve().String(), valueToSell.String())), transaction.EncodeError(map[string]string{ - "has": coin.Reserve().String(), - "required": valueToSell.String(), + coinFrom.Reserve().String(), commissionInBaseCoin.String())), transaction.EncodeError(map[string]string{ + "reserve_has": coinFrom.Reserve().String(), + "reserve_required": commissionInBaseCoin.String(), })) } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + commission = formula.CalculateSaleAmount(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), commissionInBaseCoin) + } + + value := valueToSell + if coinToSell != types.GetBaseCoin() { + value = formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) + if errResp := transaction.CheckReserveUnderflow(coinFrom, value); errResp != nil { + return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) + } } - var result = big.NewInt(0) - switch { - case coinToSell == types.GetBaseCoin(): - coin := cState.Coins().GetCoin(coinToBuy) - result.Set(formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell)) - case coinToBuy == types.GetBaseCoin(): - coin := cState.Coins().GetCoin(coinToSell) - result.Set(formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell)) - default: - coinFrom := cState.Coins().GetCoin(coinToSell) - coinTo := cState.Coins().GetCoin(coinToBuy) - basecoinValue := formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) - result.Set(formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), basecoinValue)) + if coinToBuy != types.GetBaseCoin() { + if errResp := transaction.CheckForCoinSupplyOverflow(coinTo.Volume(), value, coinTo.MaxSupply()); errResp != nil { + return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) + } + value = formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), value) } - return &pb.EstimateCoinSellResponse{ - WillGet: result.String(), + res := &pb.EstimateCoinSellResponse{ + WillGet: value.String(), Commission: commission.String(), - }, nil + } + return res, nil } diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index 9a657aec7..a80c5c2b9 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -2,7 +2,6 @@ package service import ( "context" - "fmt" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/core/types" @@ -29,13 +28,11 @@ func (s *Service) EstimateCoinSellAll(_ context.Context, req *pb.EstimateCoinSel coinToSell := types.StrToCoinSymbol(req.CoinToSell) coinToBuy := types.StrToCoinSymbol(req.CoinToBuy) - valueToSell, ok := big.NewInt(0).SetString(req.ValueToSell, 10) + valueToSell, ok := big.NewInt(0).SetString(req.ValueToSell, 10) //todo: mb delete? if !ok { return new(pb.EstimateCoinSellAllResponse), status.Error(codes.InvalidArgument, "Value to sell not specified") } - var result *big.Int - if coinToSell == coinToBuy { return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), transaction.EncodeError(map[string]string{ "coin_to_sell": coinToSell.String(), @@ -57,58 +54,26 @@ func (s *Service) EstimateCoinSellAll(_ context.Context, req *pb.EstimateCoinSel commissionInBaseCoin := big.NewInt(commissions.ConvertTx) commissionInBaseCoin.Mul(commissionInBaseCoin, transaction.CommissionMultiplier) - commission := big.NewInt(0).Set(commissionInBaseCoin) - - switch { - case coinToSell == types.GetBaseCoin(): - coin := cState.Coins().GetCoin(coinToBuy) - - valueToSell.Sub(valueToSell, commission) - if valueToSell.Cmp(big.NewInt(0)) != 1 { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.InvalidArgument, "Not enough coins to pay commission"), transaction.EncodeError(map[string]string{ - "value_to_sell": valueToSell.String(), - "coin_to_sell": coinToSell.String(), - "commission": commission.String(), - })) - } - result = formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) - case coinToBuy == types.GetBaseCoin(): - coin := cState.Coins().GetCoin(coinToSell) - result = formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) + coinFrom := cState.Coins().GetCoin(coinToSell) + coinTo := cState.Coins().GetCoin(coinToBuy) - result.Sub(result, commission) - if result.Cmp(big.NewInt(0)) != 1 { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.InvalidArgument, "Not enough coins to pay commission"), transaction.EncodeError(map[string]string{ - "value_to_sell": valueToSell.String(), - "coin_to_sell": coinToSell.String(), - "coin_reserve_to_sell": coin.Reserve().String(), - "coin_crr_to_sell": fmt.Sprintf("%d", coin.Crr()), - "result": result.String(), - "commission": commission.String(), - })) + value := valueToSell + if coinToSell != types.GetBaseCoin() { + value = formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) + if errResp := transaction.CheckReserveUnderflow(coinFrom, value); errResp != nil { + return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } - default: - coinFrom := cState.Coins().GetCoin(coinToSell) - coinTo := cState.Coins().GetCoin(coinToBuy) - basecoinValue := formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) + } - basecoinValue.Sub(basecoinValue, commission) - if basecoinValue.Cmp(big.NewInt(0)) != 1 { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.FailedPrecondition, "Not enough coins to pay commission"), transaction.EncodeError(map[string]string{ - "coin_to_sell": coinToSell.String(), - "coin_to_buy": coinToBuy.String(), - "coin_to_sell_crr": fmt.Sprintf("%d", coinFrom.Crr()), - "coin_to_sell_reserve": coinFrom.Reserve().String(), - "result": basecoinValue.String(), - "commission": commission.String(), - })) + if coinToBuy != types.GetBaseCoin() { + if errResp := transaction.CheckForCoinSupplyOverflow(coinTo.Volume(), value, coinTo.MaxSupply()); errResp != nil { + return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } - - result = formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), basecoinValue) + value = formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), value) } return &pb.EstimateCoinSellAllResponse{ - WillGet: result.String(), + WillGet: value.String(), }, nil } From 77ca89ddb17acfcff77ba43e98ef5997df0dd573 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 23 Jun 2020 00:11:50 +0300 Subject: [PATCH 037/426] optimize CLI prune_blocks --- cli/{pb => cli_pb}/generate.sh | 0 cli/cli_pb/manager.pb.go | 1895 ++++++++++++++++++++++++++++++ cli/{pb => cli_pb}/manager.proto | 52 +- cli/pb/manager.pb.go | 1583 ------------------------- cli/service/client.go | 84 +- cli/service/server.go | 2 +- cli/service/server_test.go | 2 +- cli/service/service.go | 85 +- go.mod | 1 + 9 files changed, 2028 insertions(+), 1676 deletions(-) rename cli/{pb => cli_pb}/generate.sh (100%) create mode 100644 cli/cli_pb/manager.pb.go rename cli/{pb => cli_pb}/manager.proto (76%) delete mode 100644 cli/pb/manager.pb.go diff --git a/cli/pb/generate.sh b/cli/cli_pb/generate.sh similarity index 100% rename from cli/pb/generate.sh rename to cli/cli_pb/generate.sh diff --git a/cli/cli_pb/manager.pb.go b/cli/cli_pb/manager.pb.go new file mode 100644 index 000000000..01b2f22a6 --- /dev/null +++ b/cli/cli_pb/manager.pb.go @@ -0,0 +1,1895 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.24.0 +// protoc v3.12.1 +// source: manager.proto + +package cli_pb + +import ( + context "context" + proto "github.com/golang/protobuf/proto" + empty "github.com/golang/protobuf/ptypes/empty" + timestamp "github.com/golang/protobuf/ptypes/timestamp" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type DashboardResponse_ValidatorStatus int32 + +const ( + DashboardResponse_Validating DashboardResponse_ValidatorStatus = 0 + DashboardResponse_Challenger DashboardResponse_ValidatorStatus = 1 + DashboardResponse_Offline DashboardResponse_ValidatorStatus = 2 + DashboardResponse_NotDeclared DashboardResponse_ValidatorStatus = 3 +) + +// Enum value maps for DashboardResponse_ValidatorStatus. +var ( + DashboardResponse_ValidatorStatus_name = map[int32]string{ + 0: "Validating", + 1: "Challenger", + 2: "Offline", + 3: "NotDeclared", + } + DashboardResponse_ValidatorStatus_value = map[string]int32{ + "Validating": 0, + "Challenger": 1, + "Offline": 2, + "NotDeclared": 3, + } +) + +func (x DashboardResponse_ValidatorStatus) Enum() *DashboardResponse_ValidatorStatus { + p := new(DashboardResponse_ValidatorStatus) + *p = x + return p +} + +func (x DashboardResponse_ValidatorStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DashboardResponse_ValidatorStatus) Descriptor() protoreflect.EnumDescriptor { + return file_manager_proto_enumTypes[0].Descriptor() +} + +func (DashboardResponse_ValidatorStatus) Type() protoreflect.EnumType { + return &file_manager_proto_enumTypes[0] +} + +func (x DashboardResponse_ValidatorStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DashboardResponse_ValidatorStatus.Descriptor instead. +func (DashboardResponse_ValidatorStatus) EnumDescriptor() ([]byte, []int) { + return file_manager_proto_rawDescGZIP(), []int{5, 0} +} + +type NodeInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ProtocolVersion *NodeInfo_ProtocolVersion `protobuf:"bytes,8,opt,name=protocol_version,json=protocolVersion,proto3" json:"protocol_version,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + ListenAddr string `protobuf:"bytes,2,opt,name=listen_addr,json=listenAddr,proto3" json:"listen_addr,omitempty"` + Network string `protobuf:"bytes,3,opt,name=network,proto3" json:"network,omitempty"` + Version string `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` + Channels string `protobuf:"bytes,5,opt,name=channels,proto3" json:"channels,omitempty"` + Moniker string `protobuf:"bytes,6,opt,name=moniker,proto3" json:"moniker,omitempty"` + Other *NodeInfo_Other `protobuf:"bytes,7,opt,name=other,proto3" json:"other,omitempty"` +} + +func (x *NodeInfo) Reset() { + *x = NodeInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_manager_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeInfo) ProtoMessage() {} + +func (x *NodeInfo) ProtoReflect() protoreflect.Message { + mi := &file_manager_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeInfo.ProtoReflect.Descriptor instead. +func (*NodeInfo) Descriptor() ([]byte, []int) { + return file_manager_proto_rawDescGZIP(), []int{0} +} + +func (x *NodeInfo) GetProtocolVersion() *NodeInfo_ProtocolVersion { + if x != nil { + return x.ProtocolVersion + } + return nil +} + +func (x *NodeInfo) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *NodeInfo) GetListenAddr() string { + if x != nil { + return x.ListenAddr + } + return "" +} + +func (x *NodeInfo) GetNetwork() string { + if x != nil { + return x.Network + } + return "" +} + +func (x *NodeInfo) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *NodeInfo) GetChannels() string { + if x != nil { + return x.Channels + } + return "" +} + +func (x *NodeInfo) GetMoniker() string { + if x != nil { + return x.Moniker + } + return "" +} + +func (x *NodeInfo) GetOther() *NodeInfo_Other { + if x != nil { + return x.Other + } + return nil +} + +type NetInfoResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Listening bool `protobuf:"varint,4,opt,name=listening,proto3" json:"listening,omitempty"` + Listeners []string `protobuf:"bytes,1,rep,name=listeners,proto3" json:"listeners,omitempty"` + NPeers int64 `protobuf:"varint,2,opt,name=n_peers,json=nPeers,proto3" json:"n_peers,omitempty"` + Peers []*NetInfoResponse_Peer `protobuf:"bytes,3,rep,name=peers,proto3" json:"peers,omitempty"` +} + +func (x *NetInfoResponse) Reset() { + *x = NetInfoResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_manager_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetInfoResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetInfoResponse) ProtoMessage() {} + +func (x *NetInfoResponse) ProtoReflect() protoreflect.Message { + mi := &file_manager_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetInfoResponse.ProtoReflect.Descriptor instead. +func (*NetInfoResponse) Descriptor() ([]byte, []int) { + return file_manager_proto_rawDescGZIP(), []int{1} +} + +func (x *NetInfoResponse) GetListening() bool { + if x != nil { + return x.Listening + } + return false +} + +func (x *NetInfoResponse) GetListeners() []string { + if x != nil { + return x.Listeners + } + return nil +} + +func (x *NetInfoResponse) GetNPeers() int64 { + if x != nil { + return x.NPeers + } + return 0 +} + +func (x *NetInfoResponse) GetPeers() []*NetInfoResponse_Peer { + if x != nil { + return x.Peers + } + return nil +} + +type StatusResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Version string `protobuf:"bytes,8,opt,name=version,proto3" json:"version,omitempty"` + LatestBlockHash string `protobuf:"bytes,1,opt,name=latest_block_hash,json=latestBlockHash,proto3" json:"latest_block_hash,omitempty"` + LatestAppHash string `protobuf:"bytes,2,opt,name=latest_app_hash,json=latestAppHash,proto3" json:"latest_app_hash,omitempty"` + LatestBlockHeight string `protobuf:"bytes,3,opt,name=latest_block_height,json=latestBlockHeight,proto3" json:"latest_block_height,omitempty"` + LatestBlockTime string `protobuf:"bytes,4,opt,name=latest_block_time,json=latestBlockTime,proto3" json:"latest_block_time,omitempty"` + KeepLastStates string `protobuf:"bytes,5,opt,name=keep_last_states,json=keepLastStates,proto3" json:"keep_last_states,omitempty"` + CatchingUp bool `protobuf:"varint,6,opt,name=catching_up,json=catchingUp,proto3" json:"catching_up,omitempty"` + PublicKey string `protobuf:"bytes,7,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` + NodeId string `protobuf:"bytes,9,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` +} + +func (x *StatusResponse) Reset() { + *x = StatusResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_manager_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StatusResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StatusResponse) ProtoMessage() {} + +func (x *StatusResponse) ProtoReflect() protoreflect.Message { + mi := &file_manager_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StatusResponse.ProtoReflect.Descriptor instead. +func (*StatusResponse) Descriptor() ([]byte, []int) { + return file_manager_proto_rawDescGZIP(), []int{2} +} + +func (x *StatusResponse) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *StatusResponse) GetLatestBlockHash() string { + if x != nil { + return x.LatestBlockHash + } + return "" +} + +func (x *StatusResponse) GetLatestAppHash() string { + if x != nil { + return x.LatestAppHash + } + return "" +} + +func (x *StatusResponse) GetLatestBlockHeight() string { + if x != nil { + return x.LatestBlockHeight + } + return "" +} + +func (x *StatusResponse) GetLatestBlockTime() string { + if x != nil { + return x.LatestBlockTime + } + return "" +} + +func (x *StatusResponse) GetKeepLastStates() string { + if x != nil { + return x.KeepLastStates + } + return "" +} + +func (x *StatusResponse) GetCatchingUp() bool { + if x != nil { + return x.CatchingUp + } + return false +} + +func (x *StatusResponse) GetPublicKey() string { + if x != nil { + return x.PublicKey + } + return "" +} + +func (x *StatusResponse) GetNodeId() string { + if x != nil { + return x.NodeId + } + return "" +} + +type PruneBlocksRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FromHeight int64 `protobuf:"varint,1,opt,name=from_height,json=fromHeight,proto3" json:"from_height,omitempty"` + ToHeight int64 `protobuf:"varint,2,opt,name=to_height,json=toHeight,proto3" json:"to_height,omitempty"` +} + +func (x *PruneBlocksRequest) Reset() { + *x = PruneBlocksRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_manager_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PruneBlocksRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PruneBlocksRequest) ProtoMessage() {} + +func (x *PruneBlocksRequest) ProtoReflect() protoreflect.Message { + mi := &file_manager_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PruneBlocksRequest.ProtoReflect.Descriptor instead. +func (*PruneBlocksRequest) Descriptor() ([]byte, []int) { + return file_manager_proto_rawDescGZIP(), []int{3} +} + +func (x *PruneBlocksRequest) GetFromHeight() int64 { + if x != nil { + return x.FromHeight + } + return 0 +} + +func (x *PruneBlocksRequest) GetToHeight() int64 { + if x != nil { + return x.ToHeight + } + return 0 +} + +type DealPeerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Persistent bool `protobuf:"varint,2,opt,name=persistent,proto3" json:"persistent,omitempty"` +} + +func (x *DealPeerRequest) Reset() { + *x = DealPeerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_manager_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DealPeerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DealPeerRequest) ProtoMessage() {} + +func (x *DealPeerRequest) ProtoReflect() protoreflect.Message { + mi := &file_manager_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DealPeerRequest.ProtoReflect.Descriptor instead. +func (*DealPeerRequest) Descriptor() ([]byte, []int) { + return file_manager_proto_rawDescGZIP(), []int{4} +} + +func (x *DealPeerRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *DealPeerRequest) GetPersistent() bool { + if x != nil { + return x.Persistent + } + return false +} + +type DashboardResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LatestHeight int64 `protobuf:"varint,1,opt,name=latest_height,json=latestHeight,proto3" json:"latest_height,omitempty"` + Timestamp *timestamp.Timestamp `protobuf:"bytes,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Duration int64 `protobuf:"varint,3,opt,name=duration,proto3" json:"duration,omitempty"` + MemoryUsage uint64 `protobuf:"varint,4,opt,name=memory_usage,json=memoryUsage,proto3" json:"memory_usage,omitempty"` + ValidatorPubKey string `protobuf:"bytes,5,opt,name=validator_pub_key,json=validatorPubKey,proto3" json:"validator_pub_key,omitempty"` + MaxPeerHeight int64 `protobuf:"varint,6,opt,name=max_peer_height,json=maxPeerHeight,proto3" json:"max_peer_height,omitempty"` + PeersCount int32 `protobuf:"varint,7,opt,name=peers_count,json=peersCount,proto3" json:"peers_count,omitempty"` + AvgBlockProcessingTime int64 `protobuf:"varint,8,opt,name=avg_block_processing_time,json=avgBlockProcessingTime,proto3" json:"avg_block_processing_time,omitempty"` + TimePerBlock int64 `protobuf:"varint,9,opt,name=time_per_block,json=timePerBlock,proto3" json:"time_per_block,omitempty"` + MissedBlocks string `protobuf:"bytes,10,opt,name=missed_blocks,json=missedBlocks,proto3" json:"missed_blocks,omitempty"` + VotingPower int64 `protobuf:"varint,11,opt,name=voting_power,json=votingPower,proto3" json:"voting_power,omitempty"` + Stake string `protobuf:"bytes,12,opt,name=stake,proto3" json:"stake,omitempty"` + ValidatorStatus DashboardResponse_ValidatorStatus `protobuf:"varint,13,opt,name=validator_status,json=validatorStatus,proto3,enum=cli_pb.DashboardResponse_ValidatorStatus" json:"validator_status,omitempty"` +} + +func (x *DashboardResponse) Reset() { + *x = DashboardResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_manager_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DashboardResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DashboardResponse) ProtoMessage() {} + +func (x *DashboardResponse) ProtoReflect() protoreflect.Message { + mi := &file_manager_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DashboardResponse.ProtoReflect.Descriptor instead. +func (*DashboardResponse) Descriptor() ([]byte, []int) { + return file_manager_proto_rawDescGZIP(), []int{5} +} + +func (x *DashboardResponse) GetLatestHeight() int64 { + if x != nil { + return x.LatestHeight + } + return 0 +} + +func (x *DashboardResponse) GetTimestamp() *timestamp.Timestamp { + if x != nil { + return x.Timestamp + } + return nil +} + +func (x *DashboardResponse) GetDuration() int64 { + if x != nil { + return x.Duration + } + return 0 +} + +func (x *DashboardResponse) GetMemoryUsage() uint64 { + if x != nil { + return x.MemoryUsage + } + return 0 +} + +func (x *DashboardResponse) GetValidatorPubKey() string { + if x != nil { + return x.ValidatorPubKey + } + return "" +} + +func (x *DashboardResponse) GetMaxPeerHeight() int64 { + if x != nil { + return x.MaxPeerHeight + } + return 0 +} + +func (x *DashboardResponse) GetPeersCount() int32 { + if x != nil { + return x.PeersCount + } + return 0 +} + +func (x *DashboardResponse) GetAvgBlockProcessingTime() int64 { + if x != nil { + return x.AvgBlockProcessingTime + } + return 0 +} + +func (x *DashboardResponse) GetTimePerBlock() int64 { + if x != nil { + return x.TimePerBlock + } + return 0 +} + +func (x *DashboardResponse) GetMissedBlocks() string { + if x != nil { + return x.MissedBlocks + } + return "" +} + +func (x *DashboardResponse) GetVotingPower() int64 { + if x != nil { + return x.VotingPower + } + return 0 +} + +func (x *DashboardResponse) GetStake() string { + if x != nil { + return x.Stake + } + return "" +} + +func (x *DashboardResponse) GetValidatorStatus() DashboardResponse_ValidatorStatus { + if x != nil { + return x.ValidatorStatus + } + return DashboardResponse_Validating +} + +type PruneBlocksResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Total int64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` + Current int64 `protobuf:"varint,2,opt,name=current,proto3" json:"current,omitempty"` +} + +func (x *PruneBlocksResponse) Reset() { + *x = PruneBlocksResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_manager_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PruneBlocksResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PruneBlocksResponse) ProtoMessage() {} + +func (x *PruneBlocksResponse) ProtoReflect() protoreflect.Message { + mi := &file_manager_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PruneBlocksResponse.ProtoReflect.Descriptor instead. +func (*PruneBlocksResponse) Descriptor() ([]byte, []int) { + return file_manager_proto_rawDescGZIP(), []int{6} +} + +func (x *PruneBlocksResponse) GetTotal() int64 { + if x != nil { + return x.Total + } + return 0 +} + +func (x *PruneBlocksResponse) GetCurrent() int64 { + if x != nil { + return x.Current + } + return 0 +} + +type NodeInfo_ProtocolVersion struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + P2P uint64 `protobuf:"varint,3,opt,name=p2p,proto3" json:"p2p,omitempty"` + Block uint64 `protobuf:"varint,1,opt,name=block,proto3" json:"block,omitempty"` + App uint64 `protobuf:"varint,2,opt,name=app,proto3" json:"app,omitempty"` +} + +func (x *NodeInfo_ProtocolVersion) Reset() { + *x = NodeInfo_ProtocolVersion{} + if protoimpl.UnsafeEnabled { + mi := &file_manager_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeInfo_ProtocolVersion) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeInfo_ProtocolVersion) ProtoMessage() {} + +func (x *NodeInfo_ProtocolVersion) ProtoReflect() protoreflect.Message { + mi := &file_manager_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeInfo_ProtocolVersion.ProtoReflect.Descriptor instead. +func (*NodeInfo_ProtocolVersion) Descriptor() ([]byte, []int) { + return file_manager_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *NodeInfo_ProtocolVersion) GetP2P() uint64 { + if x != nil { + return x.P2P + } + return 0 +} + +func (x *NodeInfo_ProtocolVersion) GetBlock() uint64 { + if x != nil { + return x.Block + } + return 0 +} + +func (x *NodeInfo_ProtocolVersion) GetApp() uint64 { + if x != nil { + return x.App + } + return 0 +} + +type NodeInfo_Other struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TxIndex string `protobuf:"bytes,2,opt,name=tx_index,json=txIndex,proto3" json:"tx_index,omitempty"` + RpcAddress string `protobuf:"bytes,1,opt,name=rpc_address,json=rpcAddress,proto3" json:"rpc_address,omitempty"` +} + +func (x *NodeInfo_Other) Reset() { + *x = NodeInfo_Other{} + if protoimpl.UnsafeEnabled { + mi := &file_manager_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeInfo_Other) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeInfo_Other) ProtoMessage() {} + +func (x *NodeInfo_Other) ProtoReflect() protoreflect.Message { + mi := &file_manager_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeInfo_Other.ProtoReflect.Descriptor instead. +func (*NodeInfo_Other) Descriptor() ([]byte, []int) { + return file_manager_proto_rawDescGZIP(), []int{0, 1} +} + +func (x *NodeInfo_Other) GetTxIndex() string { + if x != nil { + return x.TxIndex + } + return "" +} + +func (x *NodeInfo_Other) GetRpcAddress() string { + if x != nil { + return x.RpcAddress + } + return "" +} + +type NetInfoResponse_Peer struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeInfo *NodeInfo `protobuf:"bytes,4,opt,name=node_info,json=nodeInfo,proto3" json:"node_info,omitempty"` + IsOutbound bool `protobuf:"varint,1,opt,name=is_outbound,json=isOutbound,proto3" json:"is_outbound,omitempty"` + ConnectionStatus *NetInfoResponse_Peer_ConnectionStatus `protobuf:"bytes,2,opt,name=connection_status,json=connectionStatus,proto3" json:"connection_status,omitempty"` + RemoteIp string `protobuf:"bytes,3,opt,name=remote_ip,json=remoteIp,proto3" json:"remote_ip,omitempty"` +} + +func (x *NetInfoResponse_Peer) Reset() { + *x = NetInfoResponse_Peer{} + if protoimpl.UnsafeEnabled { + mi := &file_manager_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetInfoResponse_Peer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetInfoResponse_Peer) ProtoMessage() {} + +func (x *NetInfoResponse_Peer) ProtoReflect() protoreflect.Message { + mi := &file_manager_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetInfoResponse_Peer.ProtoReflect.Descriptor instead. +func (*NetInfoResponse_Peer) Descriptor() ([]byte, []int) { + return file_manager_proto_rawDescGZIP(), []int{1, 0} +} + +func (x *NetInfoResponse_Peer) GetNodeInfo() *NodeInfo { + if x != nil { + return x.NodeInfo + } + return nil +} + +func (x *NetInfoResponse_Peer) GetIsOutbound() bool { + if x != nil { + return x.IsOutbound + } + return false +} + +func (x *NetInfoResponse_Peer) GetConnectionStatus() *NetInfoResponse_Peer_ConnectionStatus { + if x != nil { + return x.ConnectionStatus + } + return nil +} + +func (x *NetInfoResponse_Peer) GetRemoteIp() string { + if x != nil { + return x.RemoteIp + } + return "" +} + +type NetInfoResponse_Peer_ConnectionStatus struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Duration int64 `protobuf:"varint,4,opt,name=Duration,proto3" json:"Duration,omitempty"` + SendMonitor *NetInfoResponse_Peer_ConnectionStatus_Monitor `protobuf:"bytes,1,opt,name=SendMonitor,proto3" json:"SendMonitor,omitempty"` + RecvMonitor *NetInfoResponse_Peer_ConnectionStatus_Monitor `protobuf:"bytes,2,opt,name=RecvMonitor,proto3" json:"RecvMonitor,omitempty"` + Channels []*NetInfoResponse_Peer_ConnectionStatus_Channel `protobuf:"bytes,3,rep,name=Channels,proto3" json:"Channels,omitempty"` +} + +func (x *NetInfoResponse_Peer_ConnectionStatus) Reset() { + *x = NetInfoResponse_Peer_ConnectionStatus{} + if protoimpl.UnsafeEnabled { + mi := &file_manager_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetInfoResponse_Peer_ConnectionStatus) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetInfoResponse_Peer_ConnectionStatus) ProtoMessage() {} + +func (x *NetInfoResponse_Peer_ConnectionStatus) ProtoReflect() protoreflect.Message { + mi := &file_manager_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetInfoResponse_Peer_ConnectionStatus.ProtoReflect.Descriptor instead. +func (*NetInfoResponse_Peer_ConnectionStatus) Descriptor() ([]byte, []int) { + return file_manager_proto_rawDescGZIP(), []int{1, 0, 0} +} + +func (x *NetInfoResponse_Peer_ConnectionStatus) GetDuration() int64 { + if x != nil { + return x.Duration + } + return 0 +} + +func (x *NetInfoResponse_Peer_ConnectionStatus) GetSendMonitor() *NetInfoResponse_Peer_ConnectionStatus_Monitor { + if x != nil { + return x.SendMonitor + } + return nil +} + +func (x *NetInfoResponse_Peer_ConnectionStatus) GetRecvMonitor() *NetInfoResponse_Peer_ConnectionStatus_Monitor { + if x != nil { + return x.RecvMonitor + } + return nil +} + +func (x *NetInfoResponse_Peer_ConnectionStatus) GetChannels() []*NetInfoResponse_Peer_ConnectionStatus_Channel { + if x != nil { + return x.Channels + } + return nil +} + +type NetInfoResponse_Peer_ConnectionStatus_Monitor struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Active bool `protobuf:"varint,13,opt,name=Active,proto3" json:"Active,omitempty"` + Start string `protobuf:"bytes,1,opt,name=Start,proto3" json:"Start,omitempty"` + Duration int64 `protobuf:"varint,2,opt,name=Duration,proto3" json:"Duration,omitempty"` + Idle int64 `protobuf:"varint,3,opt,name=Idle,proto3" json:"Idle,omitempty"` + Bytes int64 `protobuf:"varint,4,opt,name=Bytes,proto3" json:"Bytes,omitempty"` + Samples int64 `protobuf:"varint,5,opt,name=Samples,proto3" json:"Samples,omitempty"` + InstRate int64 `protobuf:"varint,6,opt,name=InstRate,proto3" json:"InstRate,omitempty"` + CurRate int64 `protobuf:"varint,7,opt,name=CurRate,proto3" json:"CurRate,omitempty"` + AvgRate int64 `protobuf:"varint,8,opt,name=AvgRate,proto3" json:"AvgRate,omitempty"` + PeakRate int64 `protobuf:"varint,9,opt,name=PeakRate,proto3" json:"PeakRate,omitempty"` + BytesRem int64 `protobuf:"varint,10,opt,name=BytesRem,proto3" json:"BytesRem,omitempty"` + TimeRem int64 `protobuf:"varint,11,opt,name=TimeRem,proto3" json:"TimeRem,omitempty"` + Progress uint32 `protobuf:"varint,12,opt,name=Progress,proto3" json:"Progress,omitempty"` +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Monitor) Reset() { + *x = NetInfoResponse_Peer_ConnectionStatus_Monitor{} + if protoimpl.UnsafeEnabled { + mi := &file_manager_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Monitor) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetInfoResponse_Peer_ConnectionStatus_Monitor) ProtoMessage() {} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Monitor) ProtoReflect() protoreflect.Message { + mi := &file_manager_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetInfoResponse_Peer_ConnectionStatus_Monitor.ProtoReflect.Descriptor instead. +func (*NetInfoResponse_Peer_ConnectionStatus_Monitor) Descriptor() ([]byte, []int) { + return file_manager_proto_rawDescGZIP(), []int{1, 0, 0, 0} +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetActive() bool { + if x != nil { + return x.Active + } + return false +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetStart() string { + if x != nil { + return x.Start + } + return "" +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetDuration() int64 { + if x != nil { + return x.Duration + } + return 0 +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetIdle() int64 { + if x != nil { + return x.Idle + } + return 0 +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetBytes() int64 { + if x != nil { + return x.Bytes + } + return 0 +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetSamples() int64 { + if x != nil { + return x.Samples + } + return 0 +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetInstRate() int64 { + if x != nil { + return x.InstRate + } + return 0 +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetCurRate() int64 { + if x != nil { + return x.CurRate + } + return 0 +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetAvgRate() int64 { + if x != nil { + return x.AvgRate + } + return 0 +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetPeakRate() int64 { + if x != nil { + return x.PeakRate + } + return 0 +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetBytesRem() int64 { + if x != nil { + return x.BytesRem + } + return 0 +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetTimeRem() int64 { + if x != nil { + return x.TimeRem + } + return 0 +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetProgress() uint32 { + if x != nil { + return x.Progress + } + return 0 +} + +type NetInfoResponse_Peer_ConnectionStatus_Channel struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ID int32 `protobuf:"varint,5,opt,name=ID,proto3" json:"ID,omitempty"` + SendQueueCapacity int64 `protobuf:"varint,1,opt,name=SendQueueCapacity,proto3" json:"SendQueueCapacity,omitempty"` + SendQueueSize int64 `protobuf:"varint,2,opt,name=SendQueueSize,proto3" json:"SendQueueSize,omitempty"` + Priority int64 `protobuf:"varint,3,opt,name=Priority,proto3" json:"Priority,omitempty"` + RecentlySent int64 `protobuf:"varint,4,opt,name=RecentlySent,proto3" json:"RecentlySent,omitempty"` +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Channel) Reset() { + *x = NetInfoResponse_Peer_ConnectionStatus_Channel{} + if protoimpl.UnsafeEnabled { + mi := &file_manager_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Channel) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetInfoResponse_Peer_ConnectionStatus_Channel) ProtoMessage() {} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Channel) ProtoReflect() protoreflect.Message { + mi := &file_manager_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetInfoResponse_Peer_ConnectionStatus_Channel.ProtoReflect.Descriptor instead. +func (*NetInfoResponse_Peer_ConnectionStatus_Channel) Descriptor() ([]byte, []int) { + return file_manager_proto_rawDescGZIP(), []int{1, 0, 0, 1} +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Channel) GetID() int32 { + if x != nil { + return x.ID + } + return 0 +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Channel) GetSendQueueCapacity() int64 { + if x != nil { + return x.SendQueueCapacity + } + return 0 +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Channel) GetSendQueueSize() int64 { + if x != nil { + return x.SendQueueSize + } + return 0 +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Channel) GetPriority() int64 { + if x != nil { + return x.Priority + } + return 0 +} + +func (x *NetInfoResponse_Peer_ConnectionStatus_Channel) GetRecentlySent() int64 { + if x != nil { + return x.RecentlySent + } + return 0 +} + +var File_manager_proto protoreflect.FileDescriptor + +var file_manager_proto_rawDesc = []byte{ + 0x0a, 0x0d, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x06, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb2, 0x03, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x4b, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, + 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x1f, 0x0a, 0x0b, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x41, 0x64, 0x64, 0x72, + 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, + 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x6e, 0x69, 0x6b, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6d, 0x6f, 0x6e, 0x69, 0x6b, 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x05, 0x6f, 0x74, + 0x68, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x6c, 0x69, 0x5f, + 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4f, 0x74, 0x68, 0x65, + 0x72, 0x52, 0x05, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x1a, 0x4b, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x70, + 0x32, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x70, 0x32, 0x70, 0x12, 0x14, 0x0a, + 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x70, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x03, 0x61, 0x70, 0x70, 0x1a, 0x43, 0x0a, 0x05, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x12, 0x19, + 0x0a, 0x08, 0x74, 0x78, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x74, 0x78, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x70, 0x63, + 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x72, 0x70, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xaa, 0x09, 0x0a, 0x0f, 0x4e, + 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, + 0x0a, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x1c, 0x0a, 0x09, + 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x5f, + 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x50, 0x65, + 0x65, 0x72, 0x73, 0x12, 0x32, 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, + 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x1a, 0x8d, 0x08, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, + 0x12, 0x2d, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, + 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x12, 0x5a, 0x0a, 0x11, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6c, + 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x09, + 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x49, 0x70, 0x1a, 0xbb, 0x06, 0x0a, 0x10, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, + 0x0a, 0x08, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x08, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x57, 0x0a, 0x0b, 0x53, 0x65, + 0x6e, 0x64, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x35, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x2e, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x4d, + 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x6f, 0x6e, 0x69, + 0x74, 0x6f, 0x72, 0x12, 0x57, 0x0a, 0x0b, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x6f, 0x6e, 0x69, 0x74, + 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, + 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, + 0x0b, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x12, 0x51, 0x0a, 0x08, + 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, + 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x43, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x08, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x1a, + 0xd5, 0x02, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x41, + 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x41, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x44, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x44, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x49, 0x64, 0x6c, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x04, 0x49, 0x64, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x42, 0x79, 0x74, + 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, + 0x18, 0x0a, 0x07, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x07, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x49, 0x6e, 0x73, + 0x74, 0x52, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x49, 0x6e, 0x73, + 0x74, 0x52, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x43, 0x75, 0x72, 0x52, 0x61, 0x74, 0x65, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x43, 0x75, 0x72, 0x52, 0x61, 0x74, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x41, 0x76, 0x67, 0x52, 0x61, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x07, 0x41, 0x76, 0x67, 0x52, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x65, 0x61, + 0x6b, 0x52, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x50, 0x65, 0x61, + 0x6b, 0x52, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x42, 0x79, 0x74, 0x65, 0x73, 0x52, 0x65, + 0x6d, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x42, 0x79, 0x74, 0x65, 0x73, 0x52, 0x65, + 0x6d, 0x12, 0x18, 0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x65, 0x6d, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x65, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x50, + 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x50, + 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x1a, 0xad, 0x01, 0x0a, 0x07, 0x43, 0x68, 0x61, 0x6e, + 0x6e, 0x65, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x02, 0x49, 0x44, 0x12, 0x2c, 0x0a, 0x11, 0x53, 0x65, 0x6e, 0x64, 0x51, 0x75, 0x65, 0x75, 0x65, + 0x43, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, + 0x53, 0x65, 0x6e, 0x64, 0x51, 0x75, 0x65, 0x75, 0x65, 0x43, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, + 0x79, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x6e, 0x64, 0x51, 0x75, 0x65, 0x75, 0x65, 0x53, 0x69, + 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x53, 0x65, 0x6e, 0x64, 0x51, 0x75, + 0x65, 0x75, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x69, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x50, 0x72, 0x69, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x12, 0x22, 0x0a, 0x0c, 0x52, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x53, + 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x52, 0x65, 0x63, 0x65, 0x6e, + 0x74, 0x6c, 0x79, 0x53, 0x65, 0x6e, 0x74, 0x22, 0xdd, 0x02, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, + 0x12, 0x26, 0x0a, 0x0f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x70, 0x70, 0x5f, 0x68, + 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x61, 0x74, 0x65, 0x73, + 0x74, 0x41, 0x70, 0x70, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2e, 0x0a, 0x13, 0x6c, 0x61, 0x74, 0x65, + 0x73, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x74, 0x65, + 0x73, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x54, 0x69, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x6c, 0x61, 0x73, + 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x6b, 0x65, 0x65, 0x70, 0x4c, 0x61, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1f, + 0x0a, 0x0b, 0x63, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x70, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0a, 0x63, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x12, + 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x17, + 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x22, 0x52, 0x0a, 0x12, 0x50, 0x72, 0x75, 0x6e, 0x65, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, + 0x0b, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0a, 0x66, 0x72, 0x6f, 0x6d, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1b, + 0x0a, 0x09, 0x74, 0x6f, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x08, 0x74, 0x6f, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x4b, 0x0a, 0x0f, 0x44, + 0x65, 0x61, 0x6c, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, + 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x65, 0x72, 0x73, + 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x70, 0x65, + 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x8c, 0x05, 0x0a, 0x11, 0x44, 0x61, 0x73, + 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, + 0x0a, 0x0d, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x48, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1a, 0x0a, + 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x65, 0x6d, + 0x6f, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0b, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x11, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, + 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, + 0x70, 0x65, 0x65, 0x72, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x50, 0x65, 0x65, 0x72, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x65, 0x65, 0x72, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x39, 0x0a, 0x19, 0x61, 0x76, 0x67, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x61, 0x76, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x50, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, + 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x50, 0x65, 0x72, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x69, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x69, 0x73, 0x73, 0x65, + 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x6f, 0x74, 0x69, 0x6e, + 0x67, 0x5f, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x76, + 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, + 0x61, 0x6b, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x6b, 0x65, + 0x12, 0x54, 0x0a, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x63, 0x6c, 0x69, + 0x5f, 0x70, 0x62, 0x2e, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x4f, 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0e, 0x0a, 0x0a, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x68, 0x61, + 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x72, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x66, 0x66, + 0x6c, 0x69, 0x6e, 0x65, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x4e, 0x6f, 0x74, 0x44, 0x65, 0x63, + 0x6c, 0x61, 0x72, 0x65, 0x64, 0x10, 0x03, 0x22, 0x45, 0x0a, 0x13, 0x50, 0x72, 0x75, 0x6e, 0x65, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, + 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x32, 0xcf, + 0x02, 0x0a, 0x0e, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x38, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x4e, + 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x17, + 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x50, 0x72, 0x75, 0x6e, 0x65, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, + 0x50, 0x72, 0x75, 0x6e, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x50, 0x72, 0x75, 0x6e, + 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, + 0x01, 0x12, 0x3b, 0x0a, 0x08, 0x44, 0x65, 0x61, 0x6c, 0x50, 0x65, 0x65, 0x72, 0x12, 0x17, 0x2e, + 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x61, 0x6c, 0x50, 0x65, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x40, + 0x0a, 0x09, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x44, 0x61, 0x73, + 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, + 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x3b, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_manager_proto_rawDescOnce sync.Once + file_manager_proto_rawDescData = file_manager_proto_rawDesc +) + +func file_manager_proto_rawDescGZIP() []byte { + file_manager_proto_rawDescOnce.Do(func() { + file_manager_proto_rawDescData = protoimpl.X.CompressGZIP(file_manager_proto_rawDescData) + }) + return file_manager_proto_rawDescData +} + +var file_manager_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_manager_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_manager_proto_goTypes = []interface{}{ + (DashboardResponse_ValidatorStatus)(0), // 0: cli_pb.DashboardResponse.ValidatorStatus + (*NodeInfo)(nil), // 1: cli_pb.NodeInfo + (*NetInfoResponse)(nil), // 2: cli_pb.NetInfoResponse + (*StatusResponse)(nil), // 3: cli_pb.StatusResponse + (*PruneBlocksRequest)(nil), // 4: cli_pb.PruneBlocksRequest + (*DealPeerRequest)(nil), // 5: cli_pb.DealPeerRequest + (*DashboardResponse)(nil), // 6: cli_pb.DashboardResponse + (*PruneBlocksResponse)(nil), // 7: cli_pb.PruneBlocksResponse + (*NodeInfo_ProtocolVersion)(nil), // 8: cli_pb.NodeInfo.ProtocolVersion + (*NodeInfo_Other)(nil), // 9: cli_pb.NodeInfo.Other + (*NetInfoResponse_Peer)(nil), // 10: cli_pb.NetInfoResponse.Peer + (*NetInfoResponse_Peer_ConnectionStatus)(nil), // 11: cli_pb.NetInfoResponse.Peer.ConnectionStatus + (*NetInfoResponse_Peer_ConnectionStatus_Monitor)(nil), // 12: cli_pb.NetInfoResponse.Peer.ConnectionStatus.Monitor + (*NetInfoResponse_Peer_ConnectionStatus_Channel)(nil), // 13: cli_pb.NetInfoResponse.Peer.ConnectionStatus.Channel + (*timestamp.Timestamp)(nil), // 14: google.protobuf.Timestamp + (*empty.Empty)(nil), // 15: google.protobuf.Empty +} +var file_manager_proto_depIdxs = []int32{ + 8, // 0: cli_pb.NodeInfo.protocol_version:type_name -> cli_pb.NodeInfo.ProtocolVersion + 9, // 1: cli_pb.NodeInfo.other:type_name -> cli_pb.NodeInfo.Other + 10, // 2: cli_pb.NetInfoResponse.peers:type_name -> cli_pb.NetInfoResponse.Peer + 14, // 3: cli_pb.DashboardResponse.timestamp:type_name -> google.protobuf.Timestamp + 0, // 4: cli_pb.DashboardResponse.validator_status:type_name -> cli_pb.DashboardResponse.ValidatorStatus + 1, // 5: cli_pb.NetInfoResponse.Peer.node_info:type_name -> cli_pb.NodeInfo + 11, // 6: cli_pb.NetInfoResponse.Peer.connection_status:type_name -> cli_pb.NetInfoResponse.Peer.ConnectionStatus + 12, // 7: cli_pb.NetInfoResponse.Peer.ConnectionStatus.SendMonitor:type_name -> cli_pb.NetInfoResponse.Peer.ConnectionStatus.Monitor + 12, // 8: cli_pb.NetInfoResponse.Peer.ConnectionStatus.RecvMonitor:type_name -> cli_pb.NetInfoResponse.Peer.ConnectionStatus.Monitor + 13, // 9: cli_pb.NetInfoResponse.Peer.ConnectionStatus.Channels:type_name -> cli_pb.NetInfoResponse.Peer.ConnectionStatus.Channel + 15, // 10: cli_pb.ManagerService.Status:input_type -> google.protobuf.Empty + 15, // 11: cli_pb.ManagerService.NetInfo:input_type -> google.protobuf.Empty + 4, // 12: cli_pb.ManagerService.PruneBlocks:input_type -> cli_pb.PruneBlocksRequest + 5, // 13: cli_pb.ManagerService.DealPeer:input_type -> cli_pb.DealPeerRequest + 15, // 14: cli_pb.ManagerService.Dashboard:input_type -> google.protobuf.Empty + 3, // 15: cli_pb.ManagerService.Status:output_type -> cli_pb.StatusResponse + 2, // 16: cli_pb.ManagerService.NetInfo:output_type -> cli_pb.NetInfoResponse + 7, // 17: cli_pb.ManagerService.PruneBlocks:output_type -> cli_pb.PruneBlocksResponse + 15, // 18: cli_pb.ManagerService.DealPeer:output_type -> google.protobuf.Empty + 6, // 19: cli_pb.ManagerService.Dashboard:output_type -> cli_pb.DashboardResponse + 15, // [15:20] is the sub-list for method output_type + 10, // [10:15] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name +} + +func init() { file_manager_proto_init() } +func file_manager_proto_init() { + if File_manager_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_manager_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_manager_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetInfoResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_manager_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StatusResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_manager_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PruneBlocksRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_manager_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DealPeerRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_manager_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DashboardResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_manager_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PruneBlocksResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_manager_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeInfo_ProtocolVersion); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_manager_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeInfo_Other); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_manager_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetInfoResponse_Peer); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_manager_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetInfoResponse_Peer_ConnectionStatus); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_manager_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetInfoResponse_Peer_ConnectionStatus_Monitor); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_manager_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetInfoResponse_Peer_ConnectionStatus_Channel); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_manager_proto_rawDesc, + NumEnums: 1, + NumMessages: 13, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_manager_proto_goTypes, + DependencyIndexes: file_manager_proto_depIdxs, + EnumInfos: file_manager_proto_enumTypes, + MessageInfos: file_manager_proto_msgTypes, + }.Build() + File_manager_proto = out.File + file_manager_proto_rawDesc = nil + file_manager_proto_goTypes = nil + file_manager_proto_depIdxs = nil +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConnInterface + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion6 + +// ManagerServiceClient is the client API for ManagerService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type ManagerServiceClient interface { + Status(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*StatusResponse, error) + NetInfo(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*NetInfoResponse, error) + PruneBlocks(ctx context.Context, in *PruneBlocksRequest, opts ...grpc.CallOption) (ManagerService_PruneBlocksClient, error) + DealPeer(ctx context.Context, in *DealPeerRequest, opts ...grpc.CallOption) (*empty.Empty, error) + Dashboard(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (ManagerService_DashboardClient, error) +} + +type managerServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewManagerServiceClient(cc grpc.ClientConnInterface) ManagerServiceClient { + return &managerServiceClient{cc} +} + +func (c *managerServiceClient) Status(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*StatusResponse, error) { + out := new(StatusResponse) + err := c.cc.Invoke(ctx, "/cli_pb.ManagerService/Status", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *managerServiceClient) NetInfo(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*NetInfoResponse, error) { + out := new(NetInfoResponse) + err := c.cc.Invoke(ctx, "/cli_pb.ManagerService/NetInfo", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *managerServiceClient) PruneBlocks(ctx context.Context, in *PruneBlocksRequest, opts ...grpc.CallOption) (ManagerService_PruneBlocksClient, error) { + stream, err := c.cc.NewStream(ctx, &_ManagerService_serviceDesc.Streams[0], "/cli_pb.ManagerService/PruneBlocks", opts...) + if err != nil { + return nil, err + } + x := &managerServicePruneBlocksClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type ManagerService_PruneBlocksClient interface { + Recv() (*PruneBlocksResponse, error) + grpc.ClientStream +} + +type managerServicePruneBlocksClient struct { + grpc.ClientStream +} + +func (x *managerServicePruneBlocksClient) Recv() (*PruneBlocksResponse, error) { + m := new(PruneBlocksResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *managerServiceClient) DealPeer(ctx context.Context, in *DealPeerRequest, opts ...grpc.CallOption) (*empty.Empty, error) { + out := new(empty.Empty) + err := c.cc.Invoke(ctx, "/cli_pb.ManagerService/DealPeer", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *managerServiceClient) Dashboard(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (ManagerService_DashboardClient, error) { + stream, err := c.cc.NewStream(ctx, &_ManagerService_serviceDesc.Streams[1], "/cli_pb.ManagerService/Dashboard", opts...) + if err != nil { + return nil, err + } + x := &managerServiceDashboardClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type ManagerService_DashboardClient interface { + Recv() (*DashboardResponse, error) + grpc.ClientStream +} + +type managerServiceDashboardClient struct { + grpc.ClientStream +} + +func (x *managerServiceDashboardClient) Recv() (*DashboardResponse, error) { + m := new(DashboardResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// ManagerServiceServer is the server API for ManagerService service. +type ManagerServiceServer interface { + Status(context.Context, *empty.Empty) (*StatusResponse, error) + NetInfo(context.Context, *empty.Empty) (*NetInfoResponse, error) + PruneBlocks(*PruneBlocksRequest, ManagerService_PruneBlocksServer) error + DealPeer(context.Context, *DealPeerRequest) (*empty.Empty, error) + Dashboard(*empty.Empty, ManagerService_DashboardServer) error +} + +// UnimplementedManagerServiceServer can be embedded to have forward compatible implementations. +type UnimplementedManagerServiceServer struct { +} + +func (*UnimplementedManagerServiceServer) Status(context.Context, *empty.Empty) (*StatusResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Status not implemented") +} +func (*UnimplementedManagerServiceServer) NetInfo(context.Context, *empty.Empty) (*NetInfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method NetInfo not implemented") +} +func (*UnimplementedManagerServiceServer) PruneBlocks(*PruneBlocksRequest, ManagerService_PruneBlocksServer) error { + return status.Errorf(codes.Unimplemented, "method PruneBlocks not implemented") +} +func (*UnimplementedManagerServiceServer) DealPeer(context.Context, *DealPeerRequest) (*empty.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DealPeer not implemented") +} +func (*UnimplementedManagerServiceServer) Dashboard(*empty.Empty, ManagerService_DashboardServer) error { + return status.Errorf(codes.Unimplemented, "method Dashboard not implemented") +} + +func RegisterManagerServiceServer(s *grpc.Server, srv ManagerServiceServer) { + s.RegisterService(&_ManagerService_serviceDesc, srv) +} + +func _ManagerService_Status_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(empty.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ManagerServiceServer).Status(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cli_pb.ManagerService/Status", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ManagerServiceServer).Status(ctx, req.(*empty.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ManagerService_NetInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(empty.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ManagerServiceServer).NetInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cli_pb.ManagerService/NetInfo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ManagerServiceServer).NetInfo(ctx, req.(*empty.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _ManagerService_PruneBlocks_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(PruneBlocksRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(ManagerServiceServer).PruneBlocks(m, &managerServicePruneBlocksServer{stream}) +} + +type ManagerService_PruneBlocksServer interface { + Send(*PruneBlocksResponse) error + grpc.ServerStream +} + +type managerServicePruneBlocksServer struct { + grpc.ServerStream +} + +func (x *managerServicePruneBlocksServer) Send(m *PruneBlocksResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _ManagerService_DealPeer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DealPeerRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ManagerServiceServer).DealPeer(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cli_pb.ManagerService/DealPeer", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ManagerServiceServer).DealPeer(ctx, req.(*DealPeerRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ManagerService_Dashboard_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(empty.Empty) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(ManagerServiceServer).Dashboard(m, &managerServiceDashboardServer{stream}) +} + +type ManagerService_DashboardServer interface { + Send(*DashboardResponse) error + grpc.ServerStream +} + +type managerServiceDashboardServer struct { + grpc.ServerStream +} + +func (x *managerServiceDashboardServer) Send(m *DashboardResponse) error { + return x.ServerStream.SendMsg(m) +} + +var _ManagerService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cli_pb.ManagerService", + HandlerType: (*ManagerServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Status", + Handler: _ManagerService_Status_Handler, + }, + { + MethodName: "NetInfo", + Handler: _ManagerService_NetInfo_Handler, + }, + { + MethodName: "DealPeer", + Handler: _ManagerService_DealPeer_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "PruneBlocks", + Handler: _ManagerService_PruneBlocks_Handler, + ServerStreams: true, + }, + { + StreamName: "Dashboard", + Handler: _ManagerService_Dashboard_Handler, + ServerStreams: true, + }, + }, + Metadata: "manager.proto", +} diff --git a/cli/pb/manager.proto b/cli/cli_pb/manager.proto similarity index 76% rename from cli/pb/manager.proto rename to cli/cli_pb/manager.proto index e60f45852..6c74ecd86 100644 --- a/cli/pb/manager.proto +++ b/cli/cli_pb/manager.proto @@ -1,8 +1,7 @@ syntax = "proto3"; -// protoc --go_out=plugins=grpc:. *.proto -package pb; - +package cli_pb; +option go_package = ".;cli_pb"; import "google/protobuf/empty.proto"; import "google/protobuf/timestamp.proto"; @@ -83,43 +82,15 @@ message NetInfoResponse { } message StatusResponse { - string version = 7; + string version = 8; string latest_block_hash = 1; string latest_app_hash = 2; - int64 latest_block_height = 3; + string latest_block_height = 3; string latest_block_time = 4; - int64 keep_last_states = 5; - - message TmStatus { - - NodeInfo node_info = 3; - - message SyncInfo { - string latest_block_hash = 5; - string latest_app_hash = 1; - int64 latest_block_height = 2; - string latest_block_time = 3; - bool catching_up = 4; - } - - SyncInfo sync_info = 1; - - message ValidatorInfo { - string address = 3; - - message PubKey { - string type = 2; - string value = 1; - } - - PubKey pub_key = 1; - int64 voting_power = 2; - } - - ValidatorInfo validator_info = 2; - } - - TmStatus tm_status = 6; + string keep_last_states = 5; + bool catching_up = 6; + string public_key = 7; + string node_id = 9; } message PruneBlocksRequest { @@ -154,10 +125,15 @@ message DashboardResponse { ValidatorStatus validator_status = 13; } +message PruneBlocksResponse { + int64 total = 1; + int64 current = 2; +} + service ManagerService { rpc Status (google.protobuf.Empty) returns (StatusResponse); rpc NetInfo (google.protobuf.Empty) returns (NetInfoResponse); - rpc PruneBlocks (PruneBlocksRequest) returns (google.protobuf.Empty); + rpc PruneBlocks (PruneBlocksRequest) returns (stream PruneBlocksResponse); rpc DealPeer (DealPeerRequest) returns (google.protobuf.Empty); rpc Dashboard (google.protobuf.Empty) returns (stream DashboardResponse); } diff --git a/cli/pb/manager.pb.go b/cli/pb/manager.pb.go deleted file mode 100644 index fa0c750f4..000000000 --- a/cli/pb/manager.pb.go +++ /dev/null @@ -1,1583 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: manager.proto - -// protoc --go_out=plugins=grpc:. *.proto - -package pb - -import ( - context "context" - fmt "fmt" - proto "github.com/golang/protobuf/proto" - empty "github.com/golang/protobuf/ptypes/empty" - timestamp "github.com/golang/protobuf/ptypes/timestamp" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" - math "math" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package - -type DashboardResponse_ValidatorStatus int32 - -const ( - DashboardResponse_Validating DashboardResponse_ValidatorStatus = 0 - DashboardResponse_Challenger DashboardResponse_ValidatorStatus = 1 - DashboardResponse_Offline DashboardResponse_ValidatorStatus = 2 - DashboardResponse_NotDeclared DashboardResponse_ValidatorStatus = 3 -) - -var DashboardResponse_ValidatorStatus_name = map[int32]string{ - 0: "Validating", - 1: "Challenger", - 2: "Offline", - 3: "NotDeclared", -} - -var DashboardResponse_ValidatorStatus_value = map[string]int32{ - "Validating": 0, - "Challenger": 1, - "Offline": 2, - "NotDeclared": 3, -} - -func (x DashboardResponse_ValidatorStatus) String() string { - return proto.EnumName(DashboardResponse_ValidatorStatus_name, int32(x)) -} - -func (DashboardResponse_ValidatorStatus) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_cde9ec64f0d2c859, []int{5, 0} -} - -type NodeInfo struct { - ProtocolVersion *NodeInfo_ProtocolVersion `protobuf:"bytes,8,opt,name=protocol_version,json=protocolVersion,proto3" json:"protocol_version,omitempty"` - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - ListenAddr string `protobuf:"bytes,2,opt,name=listen_addr,json=listenAddr,proto3" json:"listen_addr,omitempty"` - Network string `protobuf:"bytes,3,opt,name=network,proto3" json:"network,omitempty"` - Version string `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` - Channels string `protobuf:"bytes,5,opt,name=channels,proto3" json:"channels,omitempty"` - Moniker string `protobuf:"bytes,6,opt,name=moniker,proto3" json:"moniker,omitempty"` - Other *NodeInfo_Other `protobuf:"bytes,7,opt,name=other,proto3" json:"other,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *NodeInfo) Reset() { *m = NodeInfo{} } -func (m *NodeInfo) String() string { return proto.CompactTextString(m) } -func (*NodeInfo) ProtoMessage() {} -func (*NodeInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_cde9ec64f0d2c859, []int{0} -} - -func (m *NodeInfo) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_NodeInfo.Unmarshal(m, b) -} -func (m *NodeInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_NodeInfo.Marshal(b, m, deterministic) -} -func (m *NodeInfo) XXX_Merge(src proto.Message) { - xxx_messageInfo_NodeInfo.Merge(m, src) -} -func (m *NodeInfo) XXX_Size() int { - return xxx_messageInfo_NodeInfo.Size(m) -} -func (m *NodeInfo) XXX_DiscardUnknown() { - xxx_messageInfo_NodeInfo.DiscardUnknown(m) -} - -var xxx_messageInfo_NodeInfo proto.InternalMessageInfo - -func (m *NodeInfo) GetProtocolVersion() *NodeInfo_ProtocolVersion { - if m != nil { - return m.ProtocolVersion - } - return nil -} - -func (m *NodeInfo) GetId() string { - if m != nil { - return m.Id - } - return "" -} - -func (m *NodeInfo) GetListenAddr() string { - if m != nil { - return m.ListenAddr - } - return "" -} - -func (m *NodeInfo) GetNetwork() string { - if m != nil { - return m.Network - } - return "" -} - -func (m *NodeInfo) GetVersion() string { - if m != nil { - return m.Version - } - return "" -} - -func (m *NodeInfo) GetChannels() string { - if m != nil { - return m.Channels - } - return "" -} - -func (m *NodeInfo) GetMoniker() string { - if m != nil { - return m.Moniker - } - return "" -} - -func (m *NodeInfo) GetOther() *NodeInfo_Other { - if m != nil { - return m.Other - } - return nil -} - -type NodeInfo_ProtocolVersion struct { - P2P uint64 `protobuf:"varint,3,opt,name=p2p,proto3" json:"p2p,omitempty"` - Block uint64 `protobuf:"varint,1,opt,name=block,proto3" json:"block,omitempty"` - App uint64 `protobuf:"varint,2,opt,name=app,proto3" json:"app,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *NodeInfo_ProtocolVersion) Reset() { *m = NodeInfo_ProtocolVersion{} } -func (m *NodeInfo_ProtocolVersion) String() string { return proto.CompactTextString(m) } -func (*NodeInfo_ProtocolVersion) ProtoMessage() {} -func (*NodeInfo_ProtocolVersion) Descriptor() ([]byte, []int) { - return fileDescriptor_cde9ec64f0d2c859, []int{0, 0} -} - -func (m *NodeInfo_ProtocolVersion) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_NodeInfo_ProtocolVersion.Unmarshal(m, b) -} -func (m *NodeInfo_ProtocolVersion) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_NodeInfo_ProtocolVersion.Marshal(b, m, deterministic) -} -func (m *NodeInfo_ProtocolVersion) XXX_Merge(src proto.Message) { - xxx_messageInfo_NodeInfo_ProtocolVersion.Merge(m, src) -} -func (m *NodeInfo_ProtocolVersion) XXX_Size() int { - return xxx_messageInfo_NodeInfo_ProtocolVersion.Size(m) -} -func (m *NodeInfo_ProtocolVersion) XXX_DiscardUnknown() { - xxx_messageInfo_NodeInfo_ProtocolVersion.DiscardUnknown(m) -} - -var xxx_messageInfo_NodeInfo_ProtocolVersion proto.InternalMessageInfo - -func (m *NodeInfo_ProtocolVersion) GetP2P() uint64 { - if m != nil { - return m.P2P - } - return 0 -} - -func (m *NodeInfo_ProtocolVersion) GetBlock() uint64 { - if m != nil { - return m.Block - } - return 0 -} - -func (m *NodeInfo_ProtocolVersion) GetApp() uint64 { - if m != nil { - return m.App - } - return 0 -} - -type NodeInfo_Other struct { - TxIndex string `protobuf:"bytes,2,opt,name=tx_index,json=txIndex,proto3" json:"tx_index,omitempty"` - RpcAddress string `protobuf:"bytes,1,opt,name=rpc_address,json=rpcAddress,proto3" json:"rpc_address,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *NodeInfo_Other) Reset() { *m = NodeInfo_Other{} } -func (m *NodeInfo_Other) String() string { return proto.CompactTextString(m) } -func (*NodeInfo_Other) ProtoMessage() {} -func (*NodeInfo_Other) Descriptor() ([]byte, []int) { - return fileDescriptor_cde9ec64f0d2c859, []int{0, 1} -} - -func (m *NodeInfo_Other) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_NodeInfo_Other.Unmarshal(m, b) -} -func (m *NodeInfo_Other) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_NodeInfo_Other.Marshal(b, m, deterministic) -} -func (m *NodeInfo_Other) XXX_Merge(src proto.Message) { - xxx_messageInfo_NodeInfo_Other.Merge(m, src) -} -func (m *NodeInfo_Other) XXX_Size() int { - return xxx_messageInfo_NodeInfo_Other.Size(m) -} -func (m *NodeInfo_Other) XXX_DiscardUnknown() { - xxx_messageInfo_NodeInfo_Other.DiscardUnknown(m) -} - -var xxx_messageInfo_NodeInfo_Other proto.InternalMessageInfo - -func (m *NodeInfo_Other) GetTxIndex() string { - if m != nil { - return m.TxIndex - } - return "" -} - -func (m *NodeInfo_Other) GetRpcAddress() string { - if m != nil { - return m.RpcAddress - } - return "" -} - -type NetInfoResponse struct { - Listening bool `protobuf:"varint,4,opt,name=listening,proto3" json:"listening,omitempty"` - Listeners []string `protobuf:"bytes,1,rep,name=listeners,proto3" json:"listeners,omitempty"` - NPeers int64 `protobuf:"varint,2,opt,name=n_peers,json=nPeers,proto3" json:"n_peers,omitempty"` - Peers []*NetInfoResponse_Peer `protobuf:"bytes,3,rep,name=peers,proto3" json:"peers,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *NetInfoResponse) Reset() { *m = NetInfoResponse{} } -func (m *NetInfoResponse) String() string { return proto.CompactTextString(m) } -func (*NetInfoResponse) ProtoMessage() {} -func (*NetInfoResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_cde9ec64f0d2c859, []int{1} -} - -func (m *NetInfoResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_NetInfoResponse.Unmarshal(m, b) -} -func (m *NetInfoResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_NetInfoResponse.Marshal(b, m, deterministic) -} -func (m *NetInfoResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_NetInfoResponse.Merge(m, src) -} -func (m *NetInfoResponse) XXX_Size() int { - return xxx_messageInfo_NetInfoResponse.Size(m) -} -func (m *NetInfoResponse) XXX_DiscardUnknown() { - xxx_messageInfo_NetInfoResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_NetInfoResponse proto.InternalMessageInfo - -func (m *NetInfoResponse) GetListening() bool { - if m != nil { - return m.Listening - } - return false -} - -func (m *NetInfoResponse) GetListeners() []string { - if m != nil { - return m.Listeners - } - return nil -} - -func (m *NetInfoResponse) GetNPeers() int64 { - if m != nil { - return m.NPeers - } - return 0 -} - -func (m *NetInfoResponse) GetPeers() []*NetInfoResponse_Peer { - if m != nil { - return m.Peers - } - return nil -} - -type NetInfoResponse_Peer struct { - NodeInfo *NodeInfo `protobuf:"bytes,4,opt,name=node_info,json=nodeInfo,proto3" json:"node_info,omitempty"` - IsOutbound bool `protobuf:"varint,1,opt,name=is_outbound,json=isOutbound,proto3" json:"is_outbound,omitempty"` - ConnectionStatus *NetInfoResponse_Peer_ConnectionStatus `protobuf:"bytes,2,opt,name=connection_status,json=connectionStatus,proto3" json:"connection_status,omitempty"` - RemoteIp string `protobuf:"bytes,3,opt,name=remote_ip,json=remoteIp,proto3" json:"remote_ip,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *NetInfoResponse_Peer) Reset() { *m = NetInfoResponse_Peer{} } -func (m *NetInfoResponse_Peer) String() string { return proto.CompactTextString(m) } -func (*NetInfoResponse_Peer) ProtoMessage() {} -func (*NetInfoResponse_Peer) Descriptor() ([]byte, []int) { - return fileDescriptor_cde9ec64f0d2c859, []int{1, 0} -} - -func (m *NetInfoResponse_Peer) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_NetInfoResponse_Peer.Unmarshal(m, b) -} -func (m *NetInfoResponse_Peer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_NetInfoResponse_Peer.Marshal(b, m, deterministic) -} -func (m *NetInfoResponse_Peer) XXX_Merge(src proto.Message) { - xxx_messageInfo_NetInfoResponse_Peer.Merge(m, src) -} -func (m *NetInfoResponse_Peer) XXX_Size() int { - return xxx_messageInfo_NetInfoResponse_Peer.Size(m) -} -func (m *NetInfoResponse_Peer) XXX_DiscardUnknown() { - xxx_messageInfo_NetInfoResponse_Peer.DiscardUnknown(m) -} - -var xxx_messageInfo_NetInfoResponse_Peer proto.InternalMessageInfo - -func (m *NetInfoResponse_Peer) GetNodeInfo() *NodeInfo { - if m != nil { - return m.NodeInfo - } - return nil -} - -func (m *NetInfoResponse_Peer) GetIsOutbound() bool { - if m != nil { - return m.IsOutbound - } - return false -} - -func (m *NetInfoResponse_Peer) GetConnectionStatus() *NetInfoResponse_Peer_ConnectionStatus { - if m != nil { - return m.ConnectionStatus - } - return nil -} - -func (m *NetInfoResponse_Peer) GetRemoteIp() string { - if m != nil { - return m.RemoteIp - } - return "" -} - -type NetInfoResponse_Peer_ConnectionStatus struct { - Duration int64 `protobuf:"varint,4,opt,name=Duration,proto3" json:"Duration,omitempty"` - SendMonitor *NetInfoResponse_Peer_ConnectionStatus_Monitor `protobuf:"bytes,1,opt,name=SendMonitor,proto3" json:"SendMonitor,omitempty"` - RecvMonitor *NetInfoResponse_Peer_ConnectionStatus_Monitor `protobuf:"bytes,2,opt,name=RecvMonitor,proto3" json:"RecvMonitor,omitempty"` - Channels []*NetInfoResponse_Peer_ConnectionStatus_Channel `protobuf:"bytes,3,rep,name=Channels,proto3" json:"Channels,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *NetInfoResponse_Peer_ConnectionStatus) Reset() { *m = NetInfoResponse_Peer_ConnectionStatus{} } -func (m *NetInfoResponse_Peer_ConnectionStatus) String() string { return proto.CompactTextString(m) } -func (*NetInfoResponse_Peer_ConnectionStatus) ProtoMessage() {} -func (*NetInfoResponse_Peer_ConnectionStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_cde9ec64f0d2c859, []int{1, 0, 0} -} - -func (m *NetInfoResponse_Peer_ConnectionStatus) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus.Unmarshal(m, b) -} -func (m *NetInfoResponse_Peer_ConnectionStatus) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus.Marshal(b, m, deterministic) -} -func (m *NetInfoResponse_Peer_ConnectionStatus) XXX_Merge(src proto.Message) { - xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus.Merge(m, src) -} -func (m *NetInfoResponse_Peer_ConnectionStatus) XXX_Size() int { - return xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus.Size(m) -} -func (m *NetInfoResponse_Peer_ConnectionStatus) XXX_DiscardUnknown() { - xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus.DiscardUnknown(m) -} - -var xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus proto.InternalMessageInfo - -func (m *NetInfoResponse_Peer_ConnectionStatus) GetDuration() int64 { - if m != nil { - return m.Duration - } - return 0 -} - -func (m *NetInfoResponse_Peer_ConnectionStatus) GetSendMonitor() *NetInfoResponse_Peer_ConnectionStatus_Monitor { - if m != nil { - return m.SendMonitor - } - return nil -} - -func (m *NetInfoResponse_Peer_ConnectionStatus) GetRecvMonitor() *NetInfoResponse_Peer_ConnectionStatus_Monitor { - if m != nil { - return m.RecvMonitor - } - return nil -} - -func (m *NetInfoResponse_Peer_ConnectionStatus) GetChannels() []*NetInfoResponse_Peer_ConnectionStatus_Channel { - if m != nil { - return m.Channels - } - return nil -} - -type NetInfoResponse_Peer_ConnectionStatus_Monitor struct { - Active bool `protobuf:"varint,13,opt,name=Active,proto3" json:"Active,omitempty"` - Start string `protobuf:"bytes,1,opt,name=Start,proto3" json:"Start,omitempty"` - Duration int64 `protobuf:"varint,2,opt,name=Duration,proto3" json:"Duration,omitempty"` - Idle int64 `protobuf:"varint,3,opt,name=Idle,proto3" json:"Idle,omitempty"` - Bytes int64 `protobuf:"varint,4,opt,name=Bytes,proto3" json:"Bytes,omitempty"` - Samples int64 `protobuf:"varint,5,opt,name=Samples,proto3" json:"Samples,omitempty"` - InstRate int64 `protobuf:"varint,6,opt,name=InstRate,proto3" json:"InstRate,omitempty"` - CurRate int64 `protobuf:"varint,7,opt,name=CurRate,proto3" json:"CurRate,omitempty"` - AvgRate int64 `protobuf:"varint,8,opt,name=AvgRate,proto3" json:"AvgRate,omitempty"` - PeakRate int64 `protobuf:"varint,9,opt,name=PeakRate,proto3" json:"PeakRate,omitempty"` - BytesRem int64 `protobuf:"varint,10,opt,name=BytesRem,proto3" json:"BytesRem,omitempty"` - TimeRem int64 `protobuf:"varint,11,opt,name=TimeRem,proto3" json:"TimeRem,omitempty"` - Progress uint32 `protobuf:"varint,12,opt,name=Progress,proto3" json:"Progress,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) Reset() { - *m = NetInfoResponse_Peer_ConnectionStatus_Monitor{} -} -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) String() string { - return proto.CompactTextString(m) -} -func (*NetInfoResponse_Peer_ConnectionStatus_Monitor) ProtoMessage() {} -func (*NetInfoResponse_Peer_ConnectionStatus_Monitor) Descriptor() ([]byte, []int) { - return fileDescriptor_cde9ec64f0d2c859, []int{1, 0, 0, 0} -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus_Monitor.Unmarshal(m, b) -} -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus_Monitor.Marshal(b, m, deterministic) -} -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) XXX_Merge(src proto.Message) { - xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus_Monitor.Merge(m, src) -} -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) XXX_Size() int { - return xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus_Monitor.Size(m) -} -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) XXX_DiscardUnknown() { - xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus_Monitor.DiscardUnknown(m) -} - -var xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus_Monitor proto.InternalMessageInfo - -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetActive() bool { - if m != nil { - return m.Active - } - return false -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetStart() string { - if m != nil { - return m.Start - } - return "" -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetDuration() int64 { - if m != nil { - return m.Duration - } - return 0 -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetIdle() int64 { - if m != nil { - return m.Idle - } - return 0 -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetBytes() int64 { - if m != nil { - return m.Bytes - } - return 0 -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetSamples() int64 { - if m != nil { - return m.Samples - } - return 0 -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetInstRate() int64 { - if m != nil { - return m.InstRate - } - return 0 -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetCurRate() int64 { - if m != nil { - return m.CurRate - } - return 0 -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetAvgRate() int64 { - if m != nil { - return m.AvgRate - } - return 0 -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetPeakRate() int64 { - if m != nil { - return m.PeakRate - } - return 0 -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetBytesRem() int64 { - if m != nil { - return m.BytesRem - } - return 0 -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetTimeRem() int64 { - if m != nil { - return m.TimeRem - } - return 0 -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Monitor) GetProgress() uint32 { - if m != nil { - return m.Progress - } - return 0 -} - -type NetInfoResponse_Peer_ConnectionStatus_Channel struct { - ID int32 `protobuf:"varint,5,opt,name=ID,proto3" json:"ID,omitempty"` - SendQueueCapacity int64 `protobuf:"varint,1,opt,name=SendQueueCapacity,proto3" json:"SendQueueCapacity,omitempty"` - SendQueueSize int64 `protobuf:"varint,2,opt,name=SendQueueSize,proto3" json:"SendQueueSize,omitempty"` - Priority int64 `protobuf:"varint,3,opt,name=Priority,proto3" json:"Priority,omitempty"` - RecentlySent int64 `protobuf:"varint,4,opt,name=RecentlySent,proto3" json:"RecentlySent,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Channel) Reset() { - *m = NetInfoResponse_Peer_ConnectionStatus_Channel{} -} -func (m *NetInfoResponse_Peer_ConnectionStatus_Channel) String() string { - return proto.CompactTextString(m) -} -func (*NetInfoResponse_Peer_ConnectionStatus_Channel) ProtoMessage() {} -func (*NetInfoResponse_Peer_ConnectionStatus_Channel) Descriptor() ([]byte, []int) { - return fileDescriptor_cde9ec64f0d2c859, []int{1, 0, 0, 1} -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Channel) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus_Channel.Unmarshal(m, b) -} -func (m *NetInfoResponse_Peer_ConnectionStatus_Channel) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus_Channel.Marshal(b, m, deterministic) -} -func (m *NetInfoResponse_Peer_ConnectionStatus_Channel) XXX_Merge(src proto.Message) { - xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus_Channel.Merge(m, src) -} -func (m *NetInfoResponse_Peer_ConnectionStatus_Channel) XXX_Size() int { - return xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus_Channel.Size(m) -} -func (m *NetInfoResponse_Peer_ConnectionStatus_Channel) XXX_DiscardUnknown() { - xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus_Channel.DiscardUnknown(m) -} - -var xxx_messageInfo_NetInfoResponse_Peer_ConnectionStatus_Channel proto.InternalMessageInfo - -func (m *NetInfoResponse_Peer_ConnectionStatus_Channel) GetID() int32 { - if m != nil { - return m.ID - } - return 0 -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Channel) GetSendQueueCapacity() int64 { - if m != nil { - return m.SendQueueCapacity - } - return 0 -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Channel) GetSendQueueSize() int64 { - if m != nil { - return m.SendQueueSize - } - return 0 -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Channel) GetPriority() int64 { - if m != nil { - return m.Priority - } - return 0 -} - -func (m *NetInfoResponse_Peer_ConnectionStatus_Channel) GetRecentlySent() int64 { - if m != nil { - return m.RecentlySent - } - return 0 -} - -type StatusResponse struct { - Version string `protobuf:"bytes,7,opt,name=version,proto3" json:"version,omitempty"` - LatestBlockHash string `protobuf:"bytes,1,opt,name=latest_block_hash,json=latestBlockHash,proto3" json:"latest_block_hash,omitempty"` - LatestAppHash string `protobuf:"bytes,2,opt,name=latest_app_hash,json=latestAppHash,proto3" json:"latest_app_hash,omitempty"` - LatestBlockHeight int64 `protobuf:"varint,3,opt,name=latest_block_height,json=latestBlockHeight,proto3" json:"latest_block_height,omitempty"` - LatestBlockTime string `protobuf:"bytes,4,opt,name=latest_block_time,json=latestBlockTime,proto3" json:"latest_block_time,omitempty"` - KeepLastStates int64 `protobuf:"varint,5,opt,name=keep_last_states,json=keepLastStates,proto3" json:"keep_last_states,omitempty"` - TmStatus *StatusResponse_TmStatus `protobuf:"bytes,6,opt,name=tm_status,json=tmStatus,proto3" json:"tm_status,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *StatusResponse) Reset() { *m = StatusResponse{} } -func (m *StatusResponse) String() string { return proto.CompactTextString(m) } -func (*StatusResponse) ProtoMessage() {} -func (*StatusResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_cde9ec64f0d2c859, []int{2} -} - -func (m *StatusResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_StatusResponse.Unmarshal(m, b) -} -func (m *StatusResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_StatusResponse.Marshal(b, m, deterministic) -} -func (m *StatusResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_StatusResponse.Merge(m, src) -} -func (m *StatusResponse) XXX_Size() int { - return xxx_messageInfo_StatusResponse.Size(m) -} -func (m *StatusResponse) XXX_DiscardUnknown() { - xxx_messageInfo_StatusResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_StatusResponse proto.InternalMessageInfo - -func (m *StatusResponse) GetVersion() string { - if m != nil { - return m.Version - } - return "" -} - -func (m *StatusResponse) GetLatestBlockHash() string { - if m != nil { - return m.LatestBlockHash - } - return "" -} - -func (m *StatusResponse) GetLatestAppHash() string { - if m != nil { - return m.LatestAppHash - } - return "" -} - -func (m *StatusResponse) GetLatestBlockHeight() int64 { - if m != nil { - return m.LatestBlockHeight - } - return 0 -} - -func (m *StatusResponse) GetLatestBlockTime() string { - if m != nil { - return m.LatestBlockTime - } - return "" -} - -func (m *StatusResponse) GetKeepLastStates() int64 { - if m != nil { - return m.KeepLastStates - } - return 0 -} - -func (m *StatusResponse) GetTmStatus() *StatusResponse_TmStatus { - if m != nil { - return m.TmStatus - } - return nil -} - -type StatusResponse_TmStatus struct { - NodeInfo *NodeInfo `protobuf:"bytes,3,opt,name=node_info,json=nodeInfo,proto3" json:"node_info,omitempty"` - SyncInfo *StatusResponse_TmStatus_SyncInfo `protobuf:"bytes,1,opt,name=sync_info,json=syncInfo,proto3" json:"sync_info,omitempty"` - ValidatorInfo *StatusResponse_TmStatus_ValidatorInfo `protobuf:"bytes,2,opt,name=validator_info,json=validatorInfo,proto3" json:"validator_info,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *StatusResponse_TmStatus) Reset() { *m = StatusResponse_TmStatus{} } -func (m *StatusResponse_TmStatus) String() string { return proto.CompactTextString(m) } -func (*StatusResponse_TmStatus) ProtoMessage() {} -func (*StatusResponse_TmStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_cde9ec64f0d2c859, []int{2, 0} -} - -func (m *StatusResponse_TmStatus) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_StatusResponse_TmStatus.Unmarshal(m, b) -} -func (m *StatusResponse_TmStatus) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_StatusResponse_TmStatus.Marshal(b, m, deterministic) -} -func (m *StatusResponse_TmStatus) XXX_Merge(src proto.Message) { - xxx_messageInfo_StatusResponse_TmStatus.Merge(m, src) -} -func (m *StatusResponse_TmStatus) XXX_Size() int { - return xxx_messageInfo_StatusResponse_TmStatus.Size(m) -} -func (m *StatusResponse_TmStatus) XXX_DiscardUnknown() { - xxx_messageInfo_StatusResponse_TmStatus.DiscardUnknown(m) -} - -var xxx_messageInfo_StatusResponse_TmStatus proto.InternalMessageInfo - -func (m *StatusResponse_TmStatus) GetNodeInfo() *NodeInfo { - if m != nil { - return m.NodeInfo - } - return nil -} - -func (m *StatusResponse_TmStatus) GetSyncInfo() *StatusResponse_TmStatus_SyncInfo { - if m != nil { - return m.SyncInfo - } - return nil -} - -func (m *StatusResponse_TmStatus) GetValidatorInfo() *StatusResponse_TmStatus_ValidatorInfo { - if m != nil { - return m.ValidatorInfo - } - return nil -} - -type StatusResponse_TmStatus_SyncInfo struct { - LatestBlockHash string `protobuf:"bytes,5,opt,name=latest_block_hash,json=latestBlockHash,proto3" json:"latest_block_hash,omitempty"` - LatestAppHash string `protobuf:"bytes,1,opt,name=latest_app_hash,json=latestAppHash,proto3" json:"latest_app_hash,omitempty"` - LatestBlockHeight int64 `protobuf:"varint,2,opt,name=latest_block_height,json=latestBlockHeight,proto3" json:"latest_block_height,omitempty"` - LatestBlockTime string `protobuf:"bytes,3,opt,name=latest_block_time,json=latestBlockTime,proto3" json:"latest_block_time,omitempty"` - CatchingUp bool `protobuf:"varint,4,opt,name=catching_up,json=catchingUp,proto3" json:"catching_up,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *StatusResponse_TmStatus_SyncInfo) Reset() { *m = StatusResponse_TmStatus_SyncInfo{} } -func (m *StatusResponse_TmStatus_SyncInfo) String() string { return proto.CompactTextString(m) } -func (*StatusResponse_TmStatus_SyncInfo) ProtoMessage() {} -func (*StatusResponse_TmStatus_SyncInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_cde9ec64f0d2c859, []int{2, 0, 0} -} - -func (m *StatusResponse_TmStatus_SyncInfo) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_StatusResponse_TmStatus_SyncInfo.Unmarshal(m, b) -} -func (m *StatusResponse_TmStatus_SyncInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_StatusResponse_TmStatus_SyncInfo.Marshal(b, m, deterministic) -} -func (m *StatusResponse_TmStatus_SyncInfo) XXX_Merge(src proto.Message) { - xxx_messageInfo_StatusResponse_TmStatus_SyncInfo.Merge(m, src) -} -func (m *StatusResponse_TmStatus_SyncInfo) XXX_Size() int { - return xxx_messageInfo_StatusResponse_TmStatus_SyncInfo.Size(m) -} -func (m *StatusResponse_TmStatus_SyncInfo) XXX_DiscardUnknown() { - xxx_messageInfo_StatusResponse_TmStatus_SyncInfo.DiscardUnknown(m) -} - -var xxx_messageInfo_StatusResponse_TmStatus_SyncInfo proto.InternalMessageInfo - -func (m *StatusResponse_TmStatus_SyncInfo) GetLatestBlockHash() string { - if m != nil { - return m.LatestBlockHash - } - return "" -} - -func (m *StatusResponse_TmStatus_SyncInfo) GetLatestAppHash() string { - if m != nil { - return m.LatestAppHash - } - return "" -} - -func (m *StatusResponse_TmStatus_SyncInfo) GetLatestBlockHeight() int64 { - if m != nil { - return m.LatestBlockHeight - } - return 0 -} - -func (m *StatusResponse_TmStatus_SyncInfo) GetLatestBlockTime() string { - if m != nil { - return m.LatestBlockTime - } - return "" -} - -func (m *StatusResponse_TmStatus_SyncInfo) GetCatchingUp() bool { - if m != nil { - return m.CatchingUp - } - return false -} - -type StatusResponse_TmStatus_ValidatorInfo struct { - Address string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"` - PubKey *StatusResponse_TmStatus_ValidatorInfo_PubKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key,omitempty"` - VotingPower int64 `protobuf:"varint,2,opt,name=voting_power,json=votingPower,proto3" json:"voting_power,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *StatusResponse_TmStatus_ValidatorInfo) Reset() { *m = StatusResponse_TmStatus_ValidatorInfo{} } -func (m *StatusResponse_TmStatus_ValidatorInfo) String() string { return proto.CompactTextString(m) } -func (*StatusResponse_TmStatus_ValidatorInfo) ProtoMessage() {} -func (*StatusResponse_TmStatus_ValidatorInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_cde9ec64f0d2c859, []int{2, 0, 1} -} - -func (m *StatusResponse_TmStatus_ValidatorInfo) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_StatusResponse_TmStatus_ValidatorInfo.Unmarshal(m, b) -} -func (m *StatusResponse_TmStatus_ValidatorInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_StatusResponse_TmStatus_ValidatorInfo.Marshal(b, m, deterministic) -} -func (m *StatusResponse_TmStatus_ValidatorInfo) XXX_Merge(src proto.Message) { - xxx_messageInfo_StatusResponse_TmStatus_ValidatorInfo.Merge(m, src) -} -func (m *StatusResponse_TmStatus_ValidatorInfo) XXX_Size() int { - return xxx_messageInfo_StatusResponse_TmStatus_ValidatorInfo.Size(m) -} -func (m *StatusResponse_TmStatus_ValidatorInfo) XXX_DiscardUnknown() { - xxx_messageInfo_StatusResponse_TmStatus_ValidatorInfo.DiscardUnknown(m) -} - -var xxx_messageInfo_StatusResponse_TmStatus_ValidatorInfo proto.InternalMessageInfo - -func (m *StatusResponse_TmStatus_ValidatorInfo) GetAddress() string { - if m != nil { - return m.Address - } - return "" -} - -func (m *StatusResponse_TmStatus_ValidatorInfo) GetPubKey() *StatusResponse_TmStatus_ValidatorInfo_PubKey { - if m != nil { - return m.PubKey - } - return nil -} - -func (m *StatusResponse_TmStatus_ValidatorInfo) GetVotingPower() int64 { - if m != nil { - return m.VotingPower - } - return 0 -} - -type StatusResponse_TmStatus_ValidatorInfo_PubKey struct { - Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` - Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *StatusResponse_TmStatus_ValidatorInfo_PubKey) Reset() { - *m = StatusResponse_TmStatus_ValidatorInfo_PubKey{} -} -func (m *StatusResponse_TmStatus_ValidatorInfo_PubKey) String() string { - return proto.CompactTextString(m) -} -func (*StatusResponse_TmStatus_ValidatorInfo_PubKey) ProtoMessage() {} -func (*StatusResponse_TmStatus_ValidatorInfo_PubKey) Descriptor() ([]byte, []int) { - return fileDescriptor_cde9ec64f0d2c859, []int{2, 0, 1, 0} -} - -func (m *StatusResponse_TmStatus_ValidatorInfo_PubKey) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_StatusResponse_TmStatus_ValidatorInfo_PubKey.Unmarshal(m, b) -} -func (m *StatusResponse_TmStatus_ValidatorInfo_PubKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_StatusResponse_TmStatus_ValidatorInfo_PubKey.Marshal(b, m, deterministic) -} -func (m *StatusResponse_TmStatus_ValidatorInfo_PubKey) XXX_Merge(src proto.Message) { - xxx_messageInfo_StatusResponse_TmStatus_ValidatorInfo_PubKey.Merge(m, src) -} -func (m *StatusResponse_TmStatus_ValidatorInfo_PubKey) XXX_Size() int { - return xxx_messageInfo_StatusResponse_TmStatus_ValidatorInfo_PubKey.Size(m) -} -func (m *StatusResponse_TmStatus_ValidatorInfo_PubKey) XXX_DiscardUnknown() { - xxx_messageInfo_StatusResponse_TmStatus_ValidatorInfo_PubKey.DiscardUnknown(m) -} - -var xxx_messageInfo_StatusResponse_TmStatus_ValidatorInfo_PubKey proto.InternalMessageInfo - -func (m *StatusResponse_TmStatus_ValidatorInfo_PubKey) GetType() string { - if m != nil { - return m.Type - } - return "" -} - -func (m *StatusResponse_TmStatus_ValidatorInfo_PubKey) GetValue() string { - if m != nil { - return m.Value - } - return "" -} - -type PruneBlocksRequest struct { - FromHeight int64 `protobuf:"varint,1,opt,name=from_height,json=fromHeight,proto3" json:"from_height,omitempty"` - ToHeight int64 `protobuf:"varint,2,opt,name=to_height,json=toHeight,proto3" json:"to_height,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PruneBlocksRequest) Reset() { *m = PruneBlocksRequest{} } -func (m *PruneBlocksRequest) String() string { return proto.CompactTextString(m) } -func (*PruneBlocksRequest) ProtoMessage() {} -func (*PruneBlocksRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_cde9ec64f0d2c859, []int{3} -} - -func (m *PruneBlocksRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PruneBlocksRequest.Unmarshal(m, b) -} -func (m *PruneBlocksRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PruneBlocksRequest.Marshal(b, m, deterministic) -} -func (m *PruneBlocksRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_PruneBlocksRequest.Merge(m, src) -} -func (m *PruneBlocksRequest) XXX_Size() int { - return xxx_messageInfo_PruneBlocksRequest.Size(m) -} -func (m *PruneBlocksRequest) XXX_DiscardUnknown() { - xxx_messageInfo_PruneBlocksRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_PruneBlocksRequest proto.InternalMessageInfo - -func (m *PruneBlocksRequest) GetFromHeight() int64 { - if m != nil { - return m.FromHeight - } - return 0 -} - -func (m *PruneBlocksRequest) GetToHeight() int64 { - if m != nil { - return m.ToHeight - } - return 0 -} - -type DealPeerRequest struct { - Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` - Persistent bool `protobuf:"varint,2,opt,name=persistent,proto3" json:"persistent,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *DealPeerRequest) Reset() { *m = DealPeerRequest{} } -func (m *DealPeerRequest) String() string { return proto.CompactTextString(m) } -func (*DealPeerRequest) ProtoMessage() {} -func (*DealPeerRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_cde9ec64f0d2c859, []int{4} -} - -func (m *DealPeerRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_DealPeerRequest.Unmarshal(m, b) -} -func (m *DealPeerRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_DealPeerRequest.Marshal(b, m, deterministic) -} -func (m *DealPeerRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_DealPeerRequest.Merge(m, src) -} -func (m *DealPeerRequest) XXX_Size() int { - return xxx_messageInfo_DealPeerRequest.Size(m) -} -func (m *DealPeerRequest) XXX_DiscardUnknown() { - xxx_messageInfo_DealPeerRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_DealPeerRequest proto.InternalMessageInfo - -func (m *DealPeerRequest) GetAddress() string { - if m != nil { - return m.Address - } - return "" -} - -func (m *DealPeerRequest) GetPersistent() bool { - if m != nil { - return m.Persistent - } - return false -} - -type DashboardResponse struct { - LatestHeight int64 `protobuf:"varint,1,opt,name=latest_height,json=latestHeight,proto3" json:"latest_height,omitempty"` - Timestamp *timestamp.Timestamp `protobuf:"bytes,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Duration int64 `protobuf:"varint,3,opt,name=duration,proto3" json:"duration,omitempty"` - MemoryUsage uint64 `protobuf:"varint,4,opt,name=memory_usage,json=memoryUsage,proto3" json:"memory_usage,omitempty"` - ValidatorPubKey string `protobuf:"bytes,5,opt,name=validator_pub_key,json=validatorPubKey,proto3" json:"validator_pub_key,omitempty"` - MaxPeerHeight int64 `protobuf:"varint,6,opt,name=max_peer_height,json=maxPeerHeight,proto3" json:"max_peer_height,omitempty"` - PeersCount int32 `protobuf:"varint,7,opt,name=peers_count,json=peersCount,proto3" json:"peers_count,omitempty"` - AvgBlockProcessingTime int64 `protobuf:"varint,8,opt,name=avg_block_processing_time,json=avgBlockProcessingTime,proto3" json:"avg_block_processing_time,omitempty"` - TimePerBlock int64 `protobuf:"varint,9,opt,name=time_per_block,json=timePerBlock,proto3" json:"time_per_block,omitempty"` - MissedBlocks string `protobuf:"bytes,10,opt,name=missed_blocks,json=missedBlocks,proto3" json:"missed_blocks,omitempty"` - VotingPower int64 `protobuf:"varint,11,opt,name=voting_power,json=votingPower,proto3" json:"voting_power,omitempty"` - Stake string `protobuf:"bytes,12,opt,name=stake,proto3" json:"stake,omitempty"` - ValidatorStatus DashboardResponse_ValidatorStatus `protobuf:"varint,13,opt,name=validator_status,json=validatorStatus,proto3,enum=pb.DashboardResponse_ValidatorStatus" json:"validator_status,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *DashboardResponse) Reset() { *m = DashboardResponse{} } -func (m *DashboardResponse) String() string { return proto.CompactTextString(m) } -func (*DashboardResponse) ProtoMessage() {} -func (*DashboardResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_cde9ec64f0d2c859, []int{5} -} - -func (m *DashboardResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_DashboardResponse.Unmarshal(m, b) -} -func (m *DashboardResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_DashboardResponse.Marshal(b, m, deterministic) -} -func (m *DashboardResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_DashboardResponse.Merge(m, src) -} -func (m *DashboardResponse) XXX_Size() int { - return xxx_messageInfo_DashboardResponse.Size(m) -} -func (m *DashboardResponse) XXX_DiscardUnknown() { - xxx_messageInfo_DashboardResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_DashboardResponse proto.InternalMessageInfo - -func (m *DashboardResponse) GetLatestHeight() int64 { - if m != nil { - return m.LatestHeight - } - return 0 -} - -func (m *DashboardResponse) GetTimestamp() *timestamp.Timestamp { - if m != nil { - return m.Timestamp - } - return nil -} - -func (m *DashboardResponse) GetDuration() int64 { - if m != nil { - return m.Duration - } - return 0 -} - -func (m *DashboardResponse) GetMemoryUsage() uint64 { - if m != nil { - return m.MemoryUsage - } - return 0 -} - -func (m *DashboardResponse) GetValidatorPubKey() string { - if m != nil { - return m.ValidatorPubKey - } - return "" -} - -func (m *DashboardResponse) GetMaxPeerHeight() int64 { - if m != nil { - return m.MaxPeerHeight - } - return 0 -} - -func (m *DashboardResponse) GetPeersCount() int32 { - if m != nil { - return m.PeersCount - } - return 0 -} - -func (m *DashboardResponse) GetAvgBlockProcessingTime() int64 { - if m != nil { - return m.AvgBlockProcessingTime - } - return 0 -} - -func (m *DashboardResponse) GetTimePerBlock() int64 { - if m != nil { - return m.TimePerBlock - } - return 0 -} - -func (m *DashboardResponse) GetMissedBlocks() string { - if m != nil { - return m.MissedBlocks - } - return "" -} - -func (m *DashboardResponse) GetVotingPower() int64 { - if m != nil { - return m.VotingPower - } - return 0 -} - -func (m *DashboardResponse) GetStake() string { - if m != nil { - return m.Stake - } - return "" -} - -func (m *DashboardResponse) GetValidatorStatus() DashboardResponse_ValidatorStatus { - if m != nil { - return m.ValidatorStatus - } - return DashboardResponse_Validating -} - -func init() { - proto.RegisterEnum("pb.DashboardResponse_ValidatorStatus", DashboardResponse_ValidatorStatus_name, DashboardResponse_ValidatorStatus_value) - proto.RegisterType((*NodeInfo)(nil), "pb.NodeInfo") - proto.RegisterType((*NodeInfo_ProtocolVersion)(nil), "pb.NodeInfo.ProtocolVersion") - proto.RegisterType((*NodeInfo_Other)(nil), "pb.NodeInfo.Other") - proto.RegisterType((*NetInfoResponse)(nil), "pb.NetInfoResponse") - proto.RegisterType((*NetInfoResponse_Peer)(nil), "pb.NetInfoResponse.Peer") - proto.RegisterType((*NetInfoResponse_Peer_ConnectionStatus)(nil), "pb.NetInfoResponse.Peer.ConnectionStatus") - proto.RegisterType((*NetInfoResponse_Peer_ConnectionStatus_Monitor)(nil), "pb.NetInfoResponse.Peer.ConnectionStatus.Monitor") - proto.RegisterType((*NetInfoResponse_Peer_ConnectionStatus_Channel)(nil), "pb.NetInfoResponse.Peer.ConnectionStatus.Channel") - proto.RegisterType((*StatusResponse)(nil), "pb.StatusResponse") - proto.RegisterType((*StatusResponse_TmStatus)(nil), "pb.StatusResponse.TmStatus") - proto.RegisterType((*StatusResponse_TmStatus_SyncInfo)(nil), "pb.StatusResponse.TmStatus.SyncInfo") - proto.RegisterType((*StatusResponse_TmStatus_ValidatorInfo)(nil), "pb.StatusResponse.TmStatus.ValidatorInfo") - proto.RegisterType((*StatusResponse_TmStatus_ValidatorInfo_PubKey)(nil), "pb.StatusResponse.TmStatus.ValidatorInfo.PubKey") - proto.RegisterType((*PruneBlocksRequest)(nil), "pb.PruneBlocksRequest") - proto.RegisterType((*DealPeerRequest)(nil), "pb.DealPeerRequest") - proto.RegisterType((*DashboardResponse)(nil), "pb.DashboardResponse") -} - -func init() { proto.RegisterFile("manager.proto", fileDescriptor_cde9ec64f0d2c859) } - -var fileDescriptor_cde9ec64f0d2c859 = []byte{ - // 1543 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0xdd, 0x6e, 0x23, 0x49, - 0x15, 0xc6, 0xee, 0xd8, 0x6e, 0x9f, 0x4e, 0x62, 0xa7, 0x16, 0x06, 0x6f, 0xcf, 0x8a, 0x0c, 0x66, - 0x58, 0x65, 0x11, 0xf2, 0x2e, 0x06, 0xf1, 0x23, 0xc1, 0x45, 0x36, 0x41, 0x60, 0x0d, 0x33, 0x63, - 0xca, 0xb3, 0x73, 0xdb, 0x2a, 0x77, 0x9f, 0xd8, 0xad, 0x74, 0x57, 0x15, 0xdd, 0xd5, 0xde, 0x98, - 0x27, 0xe0, 0x9a, 0xc7, 0x40, 0x42, 0xdc, 0x20, 0xf1, 0x10, 0x5c, 0x73, 0xc5, 0x7b, 0x20, 0x71, - 0x87, 0xea, 0xa7, 0xfd, 0x13, 0x27, 0xa3, 0x19, 0xae, 0xd2, 0xe7, 0x3b, 0xa7, 0x3e, 0x9f, 0xfa, - 0xea, 0x9c, 0x53, 0x15, 0x38, 0xc9, 0x19, 0x67, 0x0b, 0x2c, 0x46, 0xb2, 0x10, 0x4a, 0x90, 0xa6, - 0x9c, 0x87, 0x4f, 0x17, 0x42, 0x2c, 0x32, 0xfc, 0xdc, 0x20, 0xf3, 0xea, 0xe6, 0x73, 0xcc, 0xa5, - 0x5a, 0xdb, 0x80, 0xf0, 0xfc, 0xbe, 0x53, 0xa5, 0x39, 0x96, 0x8a, 0xe5, 0xd2, 0x06, 0x0c, 0xff, - 0xe2, 0x81, 0xff, 0x4a, 0x24, 0x38, 0xe1, 0x37, 0x82, 0xfc, 0x06, 0xfa, 0x06, 0x8d, 0x45, 0x16, - 0xad, 0xb0, 0x28, 0x53, 0xc1, 0x07, 0xfe, 0xb3, 0xc6, 0x45, 0x30, 0xfe, 0x64, 0x24, 0xe7, 0xa3, - 0x3a, 0x6e, 0x34, 0x75, 0x41, 0x6f, 0x6d, 0x0c, 0xed, 0xc9, 0x7d, 0x80, 0x9c, 0x42, 0x33, 0x4d, - 0x06, 0x8d, 0x67, 0x8d, 0x8b, 0x2e, 0x6d, 0xa6, 0x09, 0x39, 0x87, 0x20, 0x4b, 0x4b, 0x85, 0x3c, - 0x62, 0x49, 0x52, 0x0c, 0x9a, 0xc6, 0x01, 0x16, 0xba, 0x4c, 0x92, 0x82, 0x0c, 0xa0, 0xc3, 0x51, - 0x7d, 0x2d, 0x8a, 0xdb, 0x81, 0x67, 0x9c, 0xb5, 0xa9, 0x3d, 0x75, 0x2a, 0x47, 0xd6, 0xe3, 0x4c, - 0x12, 0x82, 0x1f, 0x2f, 0x19, 0xe7, 0x98, 0x95, 0x83, 0x96, 0x71, 0x6d, 0x6c, 0xbd, 0x2a, 0x17, - 0x3c, 0xbd, 0xc5, 0x62, 0xd0, 0xb6, 0xab, 0x9c, 0x49, 0x2e, 0xa0, 0x25, 0xd4, 0x12, 0x8b, 0x41, - 0xc7, 0x6c, 0x8c, 0xec, 0x6d, 0xec, 0xb5, 0xf6, 0x50, 0x1b, 0x10, 0xbe, 0x80, 0xde, 0xbd, 0x8d, - 0x92, 0x3e, 0x78, 0x72, 0x2c, 0x4d, 0x8a, 0x47, 0x54, 0x7f, 0x92, 0x6f, 0x42, 0x6b, 0x9e, 0x89, - 0xf8, 0xd6, 0x6c, 0xf6, 0x88, 0x5a, 0x43, 0xc7, 0x31, 0x29, 0xcd, 0x3e, 0x8f, 0xa8, 0xfe, 0x0c, - 0xaf, 0xa0, 0x65, 0xc8, 0xc9, 0xc7, 0xe0, 0xab, 0xbb, 0x28, 0xe5, 0x09, 0xde, 0x39, 0x1d, 0x3a, - 0xea, 0x6e, 0xa2, 0x4d, 0xad, 0x52, 0x21, 0x63, 0x23, 0x11, 0x96, 0xa5, 0x93, 0x0f, 0x0a, 0x19, - 0x5f, 0x5a, 0x64, 0xf8, 0xe7, 0x2e, 0xf4, 0x5e, 0xa1, 0xd2, 0xa9, 0x52, 0x2c, 0xa5, 0xe0, 0x25, - 0x92, 0x4f, 0xa0, 0x6b, 0x75, 0x4c, 0xf9, 0xc2, 0x28, 0xe4, 0xd3, 0x2d, 0xb0, 0xf5, 0x62, 0xa1, - 0x09, 0xbd, 0x8b, 0x2e, 0xdd, 0x02, 0xe4, 0xdb, 0xd0, 0xe1, 0x91, 0x44, 0xed, 0xd3, 0xa9, 0x78, - 0xb4, 0xcd, 0xa7, 0xda, 0x22, 0x23, 0x68, 0x59, 0xd8, 0x7b, 0xe6, 0x5d, 0x04, 0xe3, 0x81, 0x11, - 0x69, 0xff, 0x87, 0x47, 0x3a, 0x92, 0xda, 0xb0, 0xf0, 0xbf, 0x1d, 0x38, 0xd2, 0x36, 0xf9, 0x0c, - 0xba, 0x5c, 0x24, 0x18, 0xa5, 0xfc, 0x46, 0x98, 0x6c, 0x82, 0xf1, 0xf1, 0xae, 0xc2, 0xd4, 0xe7, - 0x75, 0xb1, 0x9d, 0x43, 0x90, 0x96, 0x91, 0xa8, 0xd4, 0x5c, 0x54, 0xdc, 0x16, 0x8b, 0x4f, 0x21, - 0x2d, 0x5f, 0x3b, 0x84, 0xbc, 0x85, 0xb3, 0x58, 0x70, 0x8e, 0xb1, 0x4a, 0x05, 0x8f, 0x4a, 0xc5, - 0x54, 0x65, 0xf3, 0x0c, 0xc6, 0x9f, 0x3d, 0x96, 0xd0, 0xe8, 0x6a, 0xb3, 0x62, 0x66, 0x16, 0xd0, - 0x7e, 0x7c, 0x0f, 0x21, 0x4f, 0xa1, 0x5b, 0x60, 0x2e, 0x14, 0x46, 0xa9, 0x74, 0xd5, 0xe6, 0x5b, - 0x60, 0x22, 0xc3, 0xbf, 0xb5, 0xa1, 0x7f, 0x9f, 0x43, 0x57, 0xda, 0x75, 0x55, 0x30, 0x55, 0x17, - 0xa1, 0x47, 0x37, 0x36, 0x99, 0x41, 0x30, 0x43, 0x9e, 0xbc, 0x14, 0x3c, 0x55, 0xa2, 0x30, 0xdb, - 0x08, 0xc6, 0x3f, 0x7a, 0xef, 0xfc, 0x46, 0x6e, 0x21, 0xdd, 0x65, 0xd1, 0xa4, 0x14, 0xe3, 0x55, - 0x4d, 0xda, 0xfc, 0xbf, 0x49, 0x77, 0x58, 0xc8, 0x4b, 0xf0, 0xaf, 0xea, 0x7e, 0xb1, 0xe7, 0xfa, - 0x01, 0x8c, 0x6e, 0x25, 0xdd, 0x50, 0x84, 0xff, 0x6a, 0x42, 0xa7, 0xa6, 0x7e, 0x02, 0xed, 0xcb, - 0x58, 0xa5, 0x2b, 0x1c, 0x9c, 0x98, 0x63, 0x74, 0x96, 0xee, 0x8e, 0x99, 0x62, 0x85, 0x72, 0xb5, - 0x6c, 0x8d, 0x3d, 0x39, 0x9b, 0xf7, 0xe4, 0x24, 0x70, 0x34, 0x49, 0x32, 0x34, 0xe7, 0xe2, 0x51, - 0xf3, 0xad, 0x59, 0xbe, 0x5c, 0x2b, 0x2c, 0x9d, 0xf6, 0xd6, 0xd0, 0x2d, 0x3e, 0x63, 0xb9, 0xcc, - 0xd0, 0x76, 0xbf, 0x47, 0x6b, 0x53, 0xf3, 0x4f, 0x78, 0xa9, 0x28, 0x53, 0x68, 0xba, 0xdf, 0xa3, - 0x1b, 0x5b, 0xaf, 0xba, 0xaa, 0x0a, 0xe3, 0xea, 0xd8, 0x55, 0xce, 0xd4, 0x9e, 0xcb, 0xd5, 0xc2, - 0x78, 0x7c, 0xeb, 0x71, 0xa6, 0xe6, 0x9b, 0x22, 0xbb, 0x35, 0xae, 0xae, 0xe5, 0xab, 0x6d, 0xed, - 0x33, 0xe9, 0x50, 0xcc, 0x07, 0x60, 0x7d, 0xb5, 0xad, 0x19, 0xdf, 0xa4, 0x39, 0x6a, 0x57, 0x60, - 0x19, 0x9d, 0x69, 0x18, 0x0b, 0xb1, 0x30, 0x6d, 0x7e, 0xfc, 0xac, 0x71, 0x71, 0x42, 0x37, 0x76, - 0xf8, 0xd7, 0x06, 0x74, 0x9c, 0xc8, 0x7a, 0x8e, 0x4e, 0xae, 0xcd, 0xf6, 0x5a, 0xb4, 0x39, 0xb9, - 0x26, 0x3f, 0x84, 0x33, 0x5d, 0x26, 0xbf, 0xaf, 0xb0, 0xc2, 0x2b, 0x26, 0x59, 0x9c, 0xaa, 0xb5, - 0xd1, 0xd6, 0xa3, 0x87, 0x0e, 0xf2, 0x1c, 0x4e, 0x36, 0xe0, 0x2c, 0xfd, 0x23, 0x3a, 0xb1, 0xf7, - 0x41, 0x9b, 0x4b, 0x2a, 0x0a, 0x4d, 0xe5, 0xb9, 0xdd, 0x39, 0x9b, 0x0c, 0xe1, 0x98, 0x62, 0x8c, - 0x5c, 0x65, 0xeb, 0x19, 0x72, 0xe5, 0x0e, 0x60, 0x0f, 0x1b, 0xfe, 0xa3, 0x03, 0xa7, 0xae, 0xd7, - 0xea, 0x99, 0xb4, 0x33, 0xb3, 0x3b, 0xfb, 0x33, 0xfb, 0x07, 0x70, 0x96, 0x31, 0x85, 0xa5, 0x8a, - 0xcc, 0xa0, 0x8c, 0x96, 0xac, 0x5c, 0xba, 0xe2, 0xe8, 0x59, 0xc7, 0x97, 0x1a, 0xff, 0x2d, 0x2b, - 0x97, 0xe4, 0x53, 0x70, 0x50, 0xc4, 0xa4, 0xb4, 0x91, 0x76, 0x60, 0x9e, 0x58, 0xf8, 0x52, 0x4a, - 0x13, 0x37, 0x82, 0x8f, 0xf6, 0x39, 0x31, 0x5d, 0x2c, 0x95, 0xdb, 0xcb, 0xd9, 0x2e, 0xab, 0x71, - 0x1c, 0xe4, 0xa0, 0xaf, 0x44, 0x77, 0xb7, 0xec, 0xe6, 0xa0, 0xcf, 0x8a, 0x5c, 0x40, 0xff, 0x16, - 0x51, 0x46, 0x19, 0x2b, 0x95, 0x19, 0x41, 0x9b, 0x6a, 0x3b, 0xd5, 0xf8, 0xef, 0x58, 0xa9, 0x66, - 0x06, 0x25, 0x3f, 0x87, 0xae, 0xca, 0xeb, 0x29, 0xd5, 0x36, 0x0d, 0xfb, 0x54, 0xb7, 0xd7, 0xbe, - 0x34, 0xa3, 0x37, 0xb9, 0x03, 0x7c, 0xe5, 0xbe, 0xc2, 0xff, 0x1c, 0x81, 0x5f, 0xc3, 0xfb, 0x03, - 0xd4, 0x7b, 0xe7, 0x00, 0xbd, 0x84, 0x6e, 0xb9, 0xe6, 0xb1, 0x0d, 0xb5, 0x73, 0xe7, 0xf9, 0x3b, - 0x7e, 0x71, 0x34, 0x5b, 0xf3, 0xd8, 0x52, 0x94, 0xee, 0x8b, 0x4c, 0xe1, 0x74, 0xc5, 0xb2, 0x34, - 0x61, 0x4a, 0x14, 0x96, 0x67, 0x67, 0xbe, 0x3e, 0xc6, 0xf3, 0xb6, 0x5e, 0x61, 0xc8, 0x4e, 0x56, - 0xbb, 0x66, 0xf8, 0xef, 0x06, 0xf8, 0xf5, 0x0f, 0x3d, 0x7c, 0xda, 0xad, 0xf7, 0x3e, 0xed, 0xc6, - 0x07, 0x9c, 0x76, 0xf3, 0x83, 0x4e, 0xdb, 0x7b, 0xf8, 0xb4, 0xcf, 0x21, 0x88, 0x99, 0x8a, 0x97, - 0x29, 0x5f, 0x44, 0x95, 0x74, 0xb7, 0x29, 0xd4, 0xd0, 0x57, 0x32, 0xfc, 0x67, 0x03, 0x4e, 0xf6, - 0xb6, 0xaf, 0x4b, 0xbd, 0xbe, 0xaf, 0xdd, 0xc3, 0xc5, 0x99, 0x64, 0x02, 0x1d, 0x59, 0xcd, 0xa3, - 0x5b, 0x5c, 0xbb, 0xc3, 0xf9, 0xe2, 0xbd, 0x45, 0x1d, 0x4d, 0xab, 0xf9, 0x0b, 0x5c, 0xd3, 0xb6, - 0x34, 0x7f, 0xc9, 0x77, 0xe1, 0x78, 0x25, 0x94, 0xce, 0x4a, 0x8a, 0xaf, 0xb1, 0x70, 0x9b, 0x0d, - 0x2c, 0x36, 0xd5, 0x50, 0x38, 0x86, 0xb6, 0x5d, 0xa4, 0x27, 0xa8, 0x5a, 0x4b, 0x74, 0xbd, 0x62, - 0xbe, 0xf5, 0x04, 0x5d, 0xb1, 0xac, 0xc2, 0x7a, 0x0e, 0x1b, 0x63, 0x48, 0x81, 0x4c, 0x8b, 0x8a, - 0xa3, 0x11, 0xa0, 0xa4, 0xf8, 0x87, 0x0a, 0x4b, 0xa5, 0x45, 0xb8, 0x29, 0x44, 0x5e, 0x0b, 0x6b, - 0xa7, 0x0b, 0x68, 0xc8, 0x29, 0xfa, 0x14, 0xba, 0x4a, 0xec, 0xeb, 0xee, 0x2b, 0x61, 0x9d, 0xc3, - 0x17, 0xd0, 0xbb, 0x46, 0x96, 0x99, 0xc7, 0x81, 0x23, 0xdc, 0x91, 0xa8, 0xb1, 0x2f, 0xd1, 0x77, - 0x00, 0xa4, 0x1e, 0x0c, 0xfa, 0x3d, 0x62, 0xa9, 0x7c, 0xba, 0x83, 0x0c, 0xff, 0xd4, 0x82, 0xb3, - 0x6b, 0x56, 0x2e, 0xe7, 0x82, 0x15, 0xc9, 0x66, 0xba, 0x7c, 0x0f, 0x5c, 0x49, 0xec, 0xa7, 0x78, - 0x6c, 0x41, 0x97, 0xa4, 0x6e, 0xc7, 0xfa, 0xa9, 0xeb, 0x8a, 0x3a, 0x1c, 0xd9, 0xc7, 0xf0, 0xa8, - 0x7e, 0x0c, 0x8f, 0xde, 0xd4, 0x11, 0x74, 0x1b, 0xac, 0xe7, 0x61, 0x52, 0xdf, 0x4e, 0x6e, 0x1e, - 0xd6, 0xb6, 0x3e, 0x88, 0x1c, 0x73, 0x51, 0xac, 0xa3, 0xaa, 0x64, 0x0b, 0x3b, 0x35, 0x8e, 0x68, - 0x60, 0xb1, 0xaf, 0x34, 0xa4, 0xeb, 0x6d, 0xdb, 0x52, 0x75, 0x01, 0xb8, 0x9a, 0xdf, 0x38, 0xdc, - 0x51, 0x7d, 0x0a, 0xbd, 0x9c, 0xdd, 0x99, 0x17, 0x58, 0xbd, 0x17, 0x7b, 0x5f, 0x9d, 0xe4, 0xec, - 0x4e, 0x4b, 0xe8, 0x36, 0x73, 0x0e, 0x81, 0x79, 0x67, 0x45, 0xb1, 0xa8, 0xb8, 0x32, 0x33, 0xb5, - 0xa5, 0x85, 0xc2, 0xa2, 0xbc, 0xd2, 0x08, 0xf9, 0x05, 0x7c, 0xcc, 0x56, 0x0b, 0x57, 0xe1, 0xb2, - 0x10, 0x31, 0x96, 0xa5, 0x2e, 0x17, 0x53, 0xec, 0xf6, 0x36, 0x7b, 0xc2, 0x56, 0x0b, 0x73, 0xd0, - 0xd3, 0x8d, 0xdb, 0xd4, 0xfc, 0x73, 0x38, 0xd5, 0x51, 0x91, 0xc4, 0xc2, 0xae, 0x77, 0x57, 0xdc, - 0xb1, 0x46, 0xa7, 0x58, 0x98, 0x35, 0x5a, 0xf3, 0x3c, 0x2d, 0x4b, 0x4c, 0x6c, 0x4c, 0x69, 0xee, - 0xba, 0x2e, 0x3d, 0xb6, 0xa0, 0x2d, 0xa0, 0x83, 0x32, 0x0d, 0x0e, 0xca, 0x54, 0x17, 0x62, 0xa9, - 0xd8, 0x2d, 0x9a, 0x5b, 0xaf, 0x4b, 0xad, 0x41, 0xa6, 0xd0, 0xdf, 0x6a, 0xe6, 0x46, 0xa8, 0x7e, - 0x48, 0x9c, 0x8e, 0xbf, 0xaf, 0x7b, 0xe6, 0xa0, 0x04, 0xb6, 0xdd, 0xe2, 0xda, 0x69, 0xab, 0xac, - 0x05, 0x86, 0xaf, 0xa1, 0x77, 0x2f, 0x86, 0x9c, 0x02, 0x38, 0x28, 0xe5, 0x8b, 0xfe, 0x37, 0xb4, - 0x7d, 0xb5, 0x64, 0x59, 0x86, 0x7c, 0x81, 0x45, 0xbf, 0x41, 0x02, 0xe8, 0xbc, 0xbe, 0xb9, 0xc9, - 0x52, 0x8e, 0xfd, 0x26, 0xe9, 0x41, 0xf0, 0x4a, 0xa8, 0x6b, 0x8c, 0x33, 0x56, 0x60, 0xd2, 0xf7, - 0xc6, 0x7f, 0x6f, 0xc2, 0xe9, 0x4b, 0xfb, 0xbf, 0xd7, 0x0c, 0x8b, 0x55, 0x1a, 0x23, 0xf9, 0x09, - 0xb4, 0x1d, 0xf5, 0x93, 0x83, 0xca, 0xfa, 0xb5, 0xfe, 0x1f, 0x2c, 0x24, 0x87, 0x1d, 0x4f, 0x7e, - 0x0a, 0x1d, 0xf7, 0xe2, 0x7a, 0x74, 0xd9, 0x47, 0x0f, 0x3c, 0xcb, 0xc8, 0xaf, 0x20, 0xd8, 0x69, - 0x56, 0xf2, 0x44, 0xc7, 0x1c, 0x76, 0x6f, 0xf8, 0x08, 0x27, 0xf9, 0x19, 0xf8, 0x75, 0x5f, 0x12, - 0xc3, 0x7f, 0xaf, 0x4b, 0x1f, 0x5d, 0xf8, 0x4b, 0xe8, 0x6e, 0xf4, 0x7f, 0x34, 0xe3, 0x6f, 0x3d, - 0x78, 0x4c, 0x5f, 0x34, 0xe6, 0x6d, 0x13, 0xf8, 0xe3, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xd5, - 0x86, 0xa6, 0x3b, 0xb8, 0x0e, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// ManagerServiceClient is the client API for ManagerService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type ManagerServiceClient interface { - Status(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*StatusResponse, error) - NetInfo(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*NetInfoResponse, error) - PruneBlocks(ctx context.Context, in *PruneBlocksRequest, opts ...grpc.CallOption) (*empty.Empty, error) - DealPeer(ctx context.Context, in *DealPeerRequest, opts ...grpc.CallOption) (*empty.Empty, error) - Dashboard(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (ManagerService_DashboardClient, error) -} - -type managerServiceClient struct { - cc *grpc.ClientConn -} - -func NewManagerServiceClient(cc *grpc.ClientConn) ManagerServiceClient { - return &managerServiceClient{cc} -} - -func (c *managerServiceClient) Status(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*StatusResponse, error) { - out := new(StatusResponse) - err := c.cc.Invoke(ctx, "/pb.ManagerService/Status", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *managerServiceClient) NetInfo(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*NetInfoResponse, error) { - out := new(NetInfoResponse) - err := c.cc.Invoke(ctx, "/pb.ManagerService/NetInfo", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *managerServiceClient) PruneBlocks(ctx context.Context, in *PruneBlocksRequest, opts ...grpc.CallOption) (*empty.Empty, error) { - out := new(empty.Empty) - err := c.cc.Invoke(ctx, "/pb.ManagerService/PruneBlocks", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *managerServiceClient) DealPeer(ctx context.Context, in *DealPeerRequest, opts ...grpc.CallOption) (*empty.Empty, error) { - out := new(empty.Empty) - err := c.cc.Invoke(ctx, "/pb.ManagerService/DealPeer", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *managerServiceClient) Dashboard(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (ManagerService_DashboardClient, error) { - stream, err := c.cc.NewStream(ctx, &_ManagerService_serviceDesc.Streams[0], "/pb.ManagerService/Dashboard", opts...) - if err != nil { - return nil, err - } - x := &managerServiceDashboardClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type ManagerService_DashboardClient interface { - Recv() (*DashboardResponse, error) - grpc.ClientStream -} - -type managerServiceDashboardClient struct { - grpc.ClientStream -} - -func (x *managerServiceDashboardClient) Recv() (*DashboardResponse, error) { - m := new(DashboardResponse) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -// ManagerServiceServer is the server API for ManagerService service. -type ManagerServiceServer interface { - Status(context.Context, *empty.Empty) (*StatusResponse, error) - NetInfo(context.Context, *empty.Empty) (*NetInfoResponse, error) - PruneBlocks(context.Context, *PruneBlocksRequest) (*empty.Empty, error) - DealPeer(context.Context, *DealPeerRequest) (*empty.Empty, error) - Dashboard(*empty.Empty, ManagerService_DashboardServer) error -} - -// UnimplementedManagerServiceServer can be embedded to have forward compatible implementations. -type UnimplementedManagerServiceServer struct { -} - -func (*UnimplementedManagerServiceServer) Status(ctx context.Context, req *empty.Empty) (*StatusResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Status not implemented") -} -func (*UnimplementedManagerServiceServer) NetInfo(ctx context.Context, req *empty.Empty) (*NetInfoResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method NetInfo not implemented") -} -func (*UnimplementedManagerServiceServer) PruneBlocks(ctx context.Context, req *PruneBlocksRequest) (*empty.Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method PruneBlocks not implemented") -} -func (*UnimplementedManagerServiceServer) DealPeer(ctx context.Context, req *DealPeerRequest) (*empty.Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method DealPeer not implemented") -} -func (*UnimplementedManagerServiceServer) Dashboard(req *empty.Empty, srv ManagerService_DashboardServer) error { - return status.Errorf(codes.Unimplemented, "method Dashboard not implemented") -} - -func RegisterManagerServiceServer(s *grpc.Server, srv ManagerServiceServer) { - s.RegisterService(&_ManagerService_serviceDesc, srv) -} - -func _ManagerService_Status_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(empty.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ManagerServiceServer).Status(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.ManagerService/Status", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ManagerServiceServer).Status(ctx, req.(*empty.Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _ManagerService_NetInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(empty.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ManagerServiceServer).NetInfo(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.ManagerService/NetInfo", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ManagerServiceServer).NetInfo(ctx, req.(*empty.Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _ManagerService_PruneBlocks_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(PruneBlocksRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ManagerServiceServer).PruneBlocks(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.ManagerService/PruneBlocks", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ManagerServiceServer).PruneBlocks(ctx, req.(*PruneBlocksRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _ManagerService_DealPeer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(DealPeerRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ManagerServiceServer).DealPeer(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.ManagerService/DealPeer", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ManagerServiceServer).DealPeer(ctx, req.(*DealPeerRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _ManagerService_Dashboard_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(empty.Empty) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(ManagerServiceServer).Dashboard(m, &managerServiceDashboardServer{stream}) -} - -type ManagerService_DashboardServer interface { - Send(*DashboardResponse) error - grpc.ServerStream -} - -type managerServiceDashboardServer struct { - grpc.ServerStream -} - -func (x *managerServiceDashboardServer) Send(m *DashboardResponse) error { - return x.ServerStream.SendMsg(m) -} - -var _ManagerService_serviceDesc = grpc.ServiceDesc{ - ServiceName: "pb.ManagerService", - HandlerType: (*ManagerServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Status", - Handler: _ManagerService_Status_Handler, - }, - { - MethodName: "NetInfo", - Handler: _ManagerService_NetInfo_Handler, - }, - { - MethodName: "PruneBlocks", - Handler: _ManagerService_PruneBlocks_Handler, - }, - { - MethodName: "DealPeer", - Handler: _ManagerService_DealPeer_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "Dashboard", - Handler: _ManagerService_Dashboard_Handler, - ServerStreams: true, - }, - }, - Metadata: "manager.proto", -} diff --git a/cli/service/client.go b/cli/service/client.go index c81d1da29..9750f9f76 100644 --- a/cli/service/client.go +++ b/cli/service/client.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "fmt" - "github.com/MinterTeam/minter-go-node/cli/pb" + pb "github.com/MinterTeam/minter-go-node/cli/cli_pb" "github.com/c-bata/go-prompt" "github.com/golang/protobuf/jsonpb" "github.com/golang/protobuf/proto" @@ -190,13 +190,13 @@ func exitCMD(_ *cli.Context) error { func dashboardCMD(client pb.ManagerServiceClient) func(c *cli.Context) error { return func(c *cli.Context) error { ctx, cancel := context.WithCancel(c.Context) + defer cancel() + response, err := client.Dashboard(ctx, &empty.Empty{}) if err != nil { return err } - defer cancel() - box := tui.NewVBox() ui, err := tui.New(tui.NewHBox(box, tui.NewSpacer())) if err != nil { @@ -372,15 +372,87 @@ func statusCMD(client pb.ManagerServiceClient) func(c *cli.Context) error { func pruneBlocksCMD(client pb.ManagerServiceClient) func(c *cli.Context) error { return func(c *cli.Context) error { - _, err := client.PruneBlocks(c.Context, &pb.PruneBlocksRequest{ + ctx, cancel := context.WithCancel(c.Context) + defer cancel() + + stream, err := client.PruneBlocks(ctx, &pb.PruneBlocksRequest{ FromHeight: c.Int64("from"), ToHeight: c.Int64("to"), }) if err != nil { return err } - fmt.Println("OK") - return nil + + box := tui.NewVBox() + progress := tui.NewProgress(100) + text := tui.NewLabel(fmt.Sprintf("%d, %d of %d")) + progressBox := tui.NewHBox(progress, text, tui.NewSpacer()) + box.Append(progressBox) + ui, err := tui.New(tui.NewHBox(box, tui.NewSpacer())) + if err != nil { + return err + } + ui.SetKeybinding("Esc", func() { ui.Quit() }) + ui.SetKeybinding("Ctrl+C", func() { ui.Quit() }) + ui.SetKeybinding("q", func() { ui.Quit() }) + + errCh := make(chan error) + quitUI := make(chan error) + recvCh := make(chan *pb.PruneBlocksResponse) + + next := make(chan struct{}) + go func() { + close(next) + quitUI <- ui.Run() + }() + <-next + + go func() { + for { + select { + case <-ctx.Done(): + return + default: + recv, err := stream.Recv() + if err == io.EOF { + close(errCh) + return + } + if err != nil { + errCh <- err + return + } + recvCh <- recv + time.Sleep(1 * time.Second) + } + } + }() + + for { + select { + case <-c.Done(): + ui.Quit() + return c.Err() + case err := <-quitUI: + close(errCh) + return err + case err, more := <-errCh: + ui.Quit() + _ = stream.CloseSend() + if more { + close(errCh) + return err + } + fmt.Println(text.Text()) + fmt.Println("OK") + return nil + case recv := <-recvCh: + progress.SetMax(int(recv.Total)) + progress.SetCurrent(int(recv.Current)) + text.SetText(fmt.Sprintf("%d%%, %d of %d", recv.Total/recv.Current, recv.Current, recv.Total)) + ui.Repaint() + } + } } } diff --git a/cli/service/server.go b/cli/service/server.go index 7103875bc..a46da701f 100644 --- a/cli/service/server.go +++ b/cli/service/server.go @@ -2,7 +2,7 @@ package service import ( "context" - "github.com/MinterTeam/minter-go-node/cli/pb" + pb "github.com/MinterTeam/minter-go-node/cli/cli_pb" "google.golang.org/grpc" "net" "os" diff --git a/cli/service/server_test.go b/cli/service/server_test.go index 42f0b7536..03eae00de 100644 --- a/cli/service/server_test.go +++ b/cli/service/server_test.go @@ -4,7 +4,7 @@ import ( "context" "github.com/MinterTeam/minter-go-node/config" "github.com/MinterTeam/minter-go-node/core/minter" - rpc "github.com/tendermint/tendermint/rpc/client" + rpc "github.com/tendermint/tendermint/rpc/client/local" "io/ioutil" "path/filepath" "testing" diff --git a/cli/service/service.go b/cli/service/service.go index 00385f263..672b59792 100644 --- a/cli/service/service.go +++ b/cli/service/service.go @@ -3,7 +3,7 @@ package service import ( "context" "fmt" - "github.com/MinterTeam/minter-go-node/cli/pb" + pb "github.com/MinterTeam/minter-go-node/cli/cli_pb" "github.com/MinterTeam/minter-go-node/config" "github.com/MinterTeam/minter-go-node/core/minter" "github.com/MinterTeam/minter-go-node/core/types" @@ -108,52 +108,21 @@ func (m *Manager) Dashboard(_ *empty.Empty, stream pb.ManagerService_DashboardSe } func (m *Manager) Status(context.Context, *empty.Empty) (*pb.StatusResponse, error) { - resultStatus, err := m.tmRPC.Status() + result, err := m.tmRPC.Status() if err != nil { return new(pb.StatusResponse), status.Error(codes.Internal, err.Error()) } response := &pb.StatusResponse{ Version: version.Version, - LatestBlockHash: fmt.Sprintf("%X", resultStatus.SyncInfo.LatestBlockHash), - LatestAppHash: fmt.Sprintf("%X", resultStatus.SyncInfo.LatestAppHash), - KeepLastStates: m.blockchain.CurrentState().Tree().KeepLastHeight(), - LatestBlockHeight: resultStatus.SyncInfo.LatestBlockHeight, - LatestBlockTime: resultStatus.SyncInfo.LatestBlockTime.Format(time.RFC3339), - TmStatus: &pb.StatusResponse_TmStatus{ - NodeInfo: &pb.NodeInfo{ - ProtocolVersion: &pb.NodeInfo_ProtocolVersion{ - P2P: uint64(resultStatus.NodeInfo.ProtocolVersion.P2P), - Block: uint64(resultStatus.NodeInfo.ProtocolVersion.Block), - App: uint64(resultStatus.NodeInfo.ProtocolVersion.App), - }, - Id: fmt.Sprintf("%X", resultStatus.NodeInfo.ID()), - ListenAddr: resultStatus.NodeInfo.ListenAddr, - Network: resultStatus.NodeInfo.Network, - Version: resultStatus.NodeInfo.Version, - Channels: fmt.Sprintf("%X", resultStatus.NodeInfo.Channels), - Moniker: resultStatus.NodeInfo.Moniker, - Other: &pb.NodeInfo_Other{ - TxIndex: resultStatus.NodeInfo.Other.TxIndex, - RpcAddress: resultStatus.NodeInfo.Other.RPCAddress, - }, - }, - SyncInfo: &pb.StatusResponse_TmStatus_SyncInfo{ - LatestBlockHash: fmt.Sprintf("%X", resultStatus.SyncInfo.LatestBlockHash), - LatestAppHash: fmt.Sprintf("%X", resultStatus.SyncInfo.LatestAppHash), - LatestBlockHeight: resultStatus.SyncInfo.LatestBlockHeight, - LatestBlockTime: resultStatus.SyncInfo.LatestBlockTime.Format(time.RFC3339), - CatchingUp: resultStatus.SyncInfo.CatchingUp, - }, - ValidatorInfo: &pb.StatusResponse_TmStatus_ValidatorInfo{ - Address: fmt.Sprintf("%X", resultStatus.ValidatorInfo.Address), - PubKey: &pb.StatusResponse_TmStatus_ValidatorInfo_PubKey{ - Type: "tendermint/PubKeyEd25519", - Value: fmt.Sprintf("%X", resultStatus.ValidatorInfo.PubKey.Bytes()), - }, - VotingPower: resultStatus.ValidatorInfo.VotingPower, - }, - }, + LatestBlockHash: fmt.Sprintf("%X", result.SyncInfo.LatestBlockHash), + LatestAppHash: fmt.Sprintf("%X", result.SyncInfo.LatestAppHash), + LatestBlockHeight: fmt.Sprintf("%d", result.SyncInfo.LatestBlockHeight), + LatestBlockTime: result.SyncInfo.LatestBlockTime.Format(time.RFC3339Nano), + KeepLastStates: fmt.Sprintf("%d", m.blockchain.CurrentState().Tree().KeepLastHeight()), + CatchingUp: result.SyncInfo.CatchingUp, + PublicKey: fmt.Sprintf("Mp%x", result.ValidatorInfo.PubKey.Bytes()[5:]), + NodeId: string(result.NodeInfo.ID()), } return response, nil @@ -244,16 +213,38 @@ func (m *Manager) NetInfo(context.Context, *empty.Empty) (*pb.NetInfoResponse, e return response, nil } -func (m *Manager) PruneBlocks(ctx context.Context, req *pb.PruneBlocksRequest) (*empty.Empty, error) { - res := new(empty.Empty) - err := m.blockchain.PruneBlocks(ctx, req.FromHeight, req.ToHeight) +func (m *Manager) PruneBlocks(req *pb.PruneBlocksRequest, stream pb.ManagerService_PruneBlocksServer) error { + versions, err := m.blockchain.PruneBlocksNumber(req.FromHeight, req.ToHeight) if err != nil { - return res, status.Error(codes.FailedPrecondition, err.Error()) + return status.Error(codes.FailedPrecondition, err.Error()) } - return res, nil + + total := int64(len(versions)) + for i, v := range versions { + if err := m.blockchain.DeleteStateVersion(int64(v)); err != nil { + return err + } + + err := stream.Send(&pb.PruneBlocksResponse{ + Total: total, + Current: int64(i), + }) + if err != nil { + return err + } + + select { + case <-stream.Context().Done(): + return stream.Context().Err() + default: + runtime.Gosched() + } + } + + return nil } -func (m *Manager) DealPeer(ctx context.Context, req *pb.DealPeerRequest) (*empty.Empty, error) { +func (m *Manager) DealPeer(_ context.Context, req *pb.DealPeerRequest) (*empty.Empty, error) { res := new(empty.Empty) _, err := m.tmRPC.DialPeers([]string{req.Address}, req.Persistent) if err != nil { diff --git a/go.mod b/go.mod index 8fbd567c2..c6912e47e 100644 --- a/go.mod +++ b/go.mod @@ -36,5 +36,6 @@ require ( golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd google.golang.org/grpc v1.28.1 + google.golang.org/protobuf v1.21.0 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 ) From 722db7e72087d7e0c660268009ac0650a07e29fc Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 23 Jun 2020 00:12:34 +0300 Subject: [PATCH 038/426] optimize CLI prune_blocks --- core/minter/minter.go | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index 160b9ad21..d43de855e 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -2,7 +2,6 @@ package minter import ( "bytes" - "context" "errors" "fmt" "github.com/MinterTeam/minter-go-node/cmd/utils" @@ -32,7 +31,6 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "math/big" - "runtime" "sort" "strings" "sync" @@ -464,7 +462,7 @@ func (app *Blockchain) Commit() abciTypes.ResponseCommit { _ = app.eventsDB.CommitEvents() // Persist application hash and height - if app.height%uint64(app.cfg.StateKeepEver) == 0 { + if app.cfg.KeepLastStates != 0 || app.height%uint64(app.cfg.StateKeepEver) == 0 { app.appDB.SetLastBlockHash(hash) app.appDB.SetLastHeight(app.height) } @@ -683,35 +681,29 @@ func (app *Blockchain) MaxPeerHeight() int64 { return max } -func (app *Blockchain) PruneBlocks(ctx context.Context, from int64, to int64) error { +func (app *Blockchain) PruneBlocksNumber(from, to int64) ([]int, error) { lastSnapshotVersion := app.appDB.GetLastHeight() - if uint64(to) >= lastSnapshotVersion { - return fmt.Errorf("cannot delete last version saved in disk (%d)", lastSnapshotVersion) + if to >= int64(lastSnapshotVersion) { + return nil, fmt.Errorf("cannot delete last version saved in disk (%d)", lastSnapshotVersion) } - versions := app.stateDeliver.Tree().AvailableVersions() - for _, v := range versions { - v := int64(v) - if v < from { + + var indexFrom, indexTo int + for i, v := range versions { + if int64(v) < from { + indexFrom = i continue } - if v >= to { + if int64(v) >= to { + indexTo = i break } - - if err := app.stateDeliver.Tree().DeleteVersion(v); err != nil { - return err - } - - select { - case <-ctx.Done(): - return ctx.Err() - default: - runtime.Gosched() - } } + return versions[indexFrom:indexTo], nil +} - return nil +func (app *Blockchain) DeleteStateVersion(v int64) error { + return app.stateDeliver.Tree().DeleteVersion(v) } func getDbOpts(memLimit int) *opt.Options { From dfae102a43230ebe38ba767e358f924a1f99666e Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 23 Jun 2020 10:36:27 +0300 Subject: [PATCH 039/426] fix --- core/minter/minter.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index d43de855e..07e1d52a3 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -690,11 +690,11 @@ func (app *Blockchain) PruneBlocksNumber(from, to int64) ([]int, error) { var indexFrom, indexTo int for i, v := range versions { - if int64(v) < from { + if int64(v) <= from { indexFrom = i continue } - if int64(v) >= to { + if int64(v) > to { indexTo = i break } From f1dd15b65966400f685e98433d57f6b66214bc2d Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 23 Jun 2020 14:43:06 +0300 Subject: [PATCH 040/426] rework cli ui prune_blocks --- cli/service/client.go | 34 ++++++++++++++-------------------- go.mod | 3 ++- go.sum | 27 +++++++++++++++++++++++---- 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/cli/service/client.go b/cli/service/client.go index 9750f9f76..1fa35a731 100644 --- a/cli/service/client.go +++ b/cli/service/client.go @@ -12,6 +12,7 @@ import ( "github.com/golang/protobuf/ptypes/empty" "github.com/marcusolsson/tui-go" "github.com/urfave/cli/v2" + "gitlab.com/tslocum/cview" "google.golang.org/grpc" "io" "os" @@ -383,18 +384,8 @@ func pruneBlocksCMD(client pb.ManagerServiceClient) func(c *cli.Context) error { return err } - box := tui.NewVBox() - progress := tui.NewProgress(100) - text := tui.NewLabel(fmt.Sprintf("%d, %d of %d")) - progressBox := tui.NewHBox(progress, text, tui.NewSpacer()) - box.Append(progressBox) - ui, err := tui.New(tui.NewHBox(box, tui.NewSpacer())) - if err != nil { - return err - } - ui.SetKeybinding("Esc", func() { ui.Quit() }) - ui.SetKeybinding("Ctrl+C", func() { ui.Quit() }) - ui.SetKeybinding("q", func() { ui.Quit() }) + progress := cview.NewProgressBar() + app := cview.NewApplication().SetRoot(progress, true) errCh := make(chan error) quitUI := make(chan error) @@ -403,7 +394,7 @@ func pruneBlocksCMD(client pb.ManagerServiceClient) func(c *cli.Context) error { next := make(chan struct{}) go func() { close(next) - quitUI <- ui.Run() + quitUI <- app.Run() }() <-next @@ -431,26 +422,29 @@ func pruneBlocksCMD(client pb.ManagerServiceClient) func(c *cli.Context) error { for { select { case <-c.Done(): - ui.Quit() + app.Stop() return c.Err() case err := <-quitUI: - close(errCh) + fmt.Println(progress.GetTitle()) return err case err, more := <-errCh: - ui.Quit() + app.Stop() _ = stream.CloseSend() if more { close(errCh) return err } - fmt.Println(text.Text()) fmt.Println("OK") return nil case recv := <-recvCh: progress.SetMax(int(recv.Total)) - progress.SetCurrent(int(recv.Current)) - text.SetText(fmt.Sprintf("%d%%, %d of %d", recv.Total/recv.Current, recv.Current, recv.Total)) - ui.Repaint() + progress.SetProgress(int(recv.Current)) + total := int64(0) + if recv.Total != 0 { + total = recv.Current * 100 / recv.Total + } + progress.SetTitle(fmt.Sprintf("Compleated %d%%, %d of %d", total, recv.Current, recv.Total)) + app.QueueUpdateDraw(func() {}) } } } diff --git a/go.mod b/go.mod index c6912e47e..20ce2211a 100644 --- a/go.mod +++ b/go.mod @@ -31,10 +31,11 @@ require ( github.com/tendermint/tm-db v0.5.1 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 github.com/urfave/cli/v2 v2.0.0 + gitlab.com/tslocum/cview v1.4.7 golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e - golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd + golang.org/x/sys v0.0.0-20200523222454-059865788121 google.golang.org/grpc v1.28.1 google.golang.org/protobuf v1.21.0 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 diff --git a/go.sum b/go.sum index 883256dea..c3b7e7e91 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,7 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200102211924-4bcbc698314f h1:4O1om+U github.com/ChainSafe/go-schnorrkel v0.0.0-20200102211924-4bcbc698314f/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= +github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/MinterTeam/node-grpc-gateway v1.1.2 h1:kHwlqPlKXFZX+SjUjqGp4c7pmONhM438EzUyJV8hKyg= github.com/MinterTeam/node-grpc-gateway v1.1.2/go.mod h1:tfJiYOCloZD+Q8nSplqVQFQNs3ggFgBBVQa0hOVCsjg= @@ -114,10 +115,12 @@ github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVB github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/gdamore/encoding v0.0.0-20151215212835-b23993cbb635 h1:hheUEMzaOie/wKeIc1WPa7CDVuIO5hqQxjS+dwTQEnI= github.com/gdamore/encoding v0.0.0-20151215212835-b23993cbb635/go.mod h1:yrQYJKKDTrHmbYxI7CYi+/hbdiDT2m4Hj+t0ikCjsrQ= -github.com/gdamore/tcell v1.1.0 h1:RbQgl7jukmdqROeNcKps7R2YfDCQbWkOd1BwdXrxfr4= +github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= +github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/tcell v1.1.0/go.mod h1:tqyG50u7+Ctv1w5VX67kLzKcj9YXR/JSBZQq/+mLl1A= +github.com/gdamore/tcell v1.3.0 h1:r35w0JBADPZCVQijYebl6YMWWtHRqVEGt7kL2eBADRM= +github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= @@ -269,8 +272,10 @@ github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOS github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/lucasb-eyer/go-colorful v0.0.0-20180709185858-c7842319cf3a h1:B2QfFRl5yGVGGcyEVFzfdXlC1BBvszsIAsCeef2oD0k= github.com/lucasb-eyer/go-colorful v0.0.0-20180709185858-c7842319cf3a/go.mod h1:NXg0ArsFk0Y01623LgUqoqcouGDB+PwCCQlrwrG6xJ4= +github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s= +github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac= +github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= @@ -287,8 +292,13 @@ github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW1 github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.6 h1:V2iyH+aX9C5fsYCpK60U8BYIvmhqxuOL3JZcqc1NB7k= github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.8 h1:3tS41NlGYSmhhe/8fhGRzc+z3AYCw1Fe1WAyLuujKs0= +github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-tty v0.0.3 h1:5OfyWorkyO7xP52Mq7tB36ajHDG5OHrmBGIS/DtakQI= github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= @@ -398,6 +408,8 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhD github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -485,6 +497,10 @@ github.com/urfave/cli/v2 v2.0.0 h1:+HU9SCbu8GnEUFtIBfuUNXN39ofWViIEJIp6SURMpCg= github.com/urfave/cli/v2 v2.0.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +gitlab.com/tslocum/cbind v0.1.1 h1:JXXtxMWHgWLvoF+QkrvcNvOQ59juy7OE1RhT7hZfdt0= +gitlab.com/tslocum/cbind v0.1.1/go.mod h1:rX7vkl0pUSg/yy427MmD1FZAf99S7WwpUlxF/qTpPqk= +gitlab.com/tslocum/cview v1.4.7 h1:8HkA2iwk9008FKDTbi6L0KkHoj2mFbgUW73DHw9iG1U= +gitlab.com/tslocum/cview v1.4.7/go.mod h1:87HOuFUfgmyY0zfg+7qKg6jyN9gI/znsa/KE2ZZHDSs= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -567,6 +583,7 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -575,8 +592,11 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgmDSfjglYZ3vStQ/gSCU= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121 h1:rITEj+UZHYC927n8GT97eC3zrpzXdb/voyeOuVKS46o= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= @@ -642,7 +662,6 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 h1:FVCohIoYO7IJoDDVpV2pdq7SgrMH6wHnuTyrdrxJNoY= gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtWgA5THM5lhBAw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 6179a324097a052c864b1f5654a34eef898a5cb9 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 3 Jul 2020 16:04:40 +0300 Subject: [PATCH 041/426] more changes remove keep ever and resent. move new methods from v1 api to v2. mark v1 as deprecated. fixes. --- api/api.go | 3 + api/status.go | 1 + api/v2/service/address.go | 139 ++++++++++++++-- api/v2/service/addresses.go | 110 +++++++++++-- api/v2/service/block.go | 198 ++++++++++++++++------- api/v2/service/candidate.go | 2 +- api/v2/service/candidates.go | 13 +- api/v2/service/coin_info.go | 2 +- api/v2/service/estimate_coin_buy.go | 2 +- api/v2/service/estimate_coin_sell.go | 2 +- api/v2/service/estimate_coin_sell_all.go | 2 +- api/v2/service/estimate_tx_commission.go | 78 ++++++++- api/v2/service/events.go | 35 ++-- api/v2/service/frozen.go | 83 ++++++++++ api/v2/service/gas.go | 2 +- api/v2/service/genesis.go | 18 ++- api/v2/service/halts.go | 1 + api/v2/service/missed_blocks.go | 4 +- api/v2/service/net_info.go | 7 +- api/v2/service/send_transaction.go | 44 ++--- api/v2/service/service.go | 46 ++++-- api/v2/service/stakes.go | 92 +++++++++++ api/v2/service/status.go | 3 +- api/v2/service/transaction.go | 11 +- api/v2/service/transactions.go | 7 +- api/v2/service/unconfirmed_txs.go | 2 +- api/v2/service/validators.go | 6 +- api/v2/service/ws.go | 11 +- api/v2/v2.go | 24 ++- cli/service/client.go | 7 +- cli/service/server_test.go | 2 +- cli/service/service.go | 26 ++- cmd/minter/cmd/export.go | 2 +- cmd/minter/cmd/manager.go | 4 +- cmd/minter/cmd/node.go | 7 +- config/config.go | 12 +- config/toml.go | 6 - core/minter/minter.go | 33 +--- core/minter/upgrade3_test.go | 2 +- core/state/candidates_test.go | 2 +- core/state/state.go | 25 +-- core/state/state_test.go | 2 +- core/transaction/buy_coin_test.go | 2 +- go.mod | 17 +- go.sum | 68 ++++---- rpc/lib/server/http_server.go | 4 + tree/tree.go | 4 +- 47 files changed, 861 insertions(+), 312 deletions(-) create mode 100644 api/v2/service/frozen.go create mode 100644 api/v2/service/stakes.go diff --git a/api/api.go b/api/api.go index 3d00160e0..bf855385a 100644 --- a/api/api.go +++ b/api/api.go @@ -27,6 +27,7 @@ var ( cdc = amino.NewCodec() blockchain *minter.Blockchain client *rpc.Local + minterCfg *config.Config ) var Routes = map[string]*rpcserver.RPCFunc{ @@ -78,6 +79,8 @@ func responseTime(b *minter.Blockchain) func(f func(http.ResponseWriter, *http.R } func RunAPI(b *minter.Blockchain, tmRPC *rpc.Local, cfg *config.Config, logger log.Logger) { + minterCfg = cfg + RegisterCryptoAmino(cdc) eventsdb.RegisterAminoEvents(cdc) RegisterEvidenceMessages(cdc) diff --git a/api/status.go b/api/status.go index 94d5f2f51..8bc2af607 100644 --- a/api/status.go +++ b/api/status.go @@ -27,6 +27,7 @@ func Status() (*StatusResponse, error) { MinterVersion: version.Version, LatestBlockHash: fmt.Sprintf("%X", result.SyncInfo.LatestBlockHash), LatestAppHash: fmt.Sprintf("%X", result.SyncInfo.LatestAppHash), + KeepLastStates: minterCfg.BaseConfig.KeepLastStates, LatestBlockHeight: result.SyncInfo.LatestBlockHeight, LatestBlockTime: result.SyncInfo.LatestBlockTime, TmStatus: result, diff --git a/api/v2/service/address.go b/api/v2/service/address.go index 8def826d9..b5cb1dc15 100644 --- a/api/v2/service/address.go +++ b/api/v2/service/address.go @@ -4,14 +4,22 @@ import ( "context" "encoding/hex" "fmt" + "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/formula" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "math/big" "strings" ) -func (s *Service) Address(_ context.Context, req *pb.AddressRequest) (*pb.AddressResponse, error) { +type UserStake struct { + Value *big.Int + BipValue *big.Int +} + +func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.AddressResponse, error) { if !strings.HasPrefix(strings.Title(req.Address), "Mx") { return new(pb.AddressResponse), status.Error(codes.InvalidArgument, "invalid address") } @@ -21,6 +29,8 @@ func (s *Service) Address(_ context.Context, req *pb.AddressRequest) (*pb.Addres return new(pb.AddressResponse), status.Error(codes.InvalidArgument, "invalid address") } + address := types.BytesToAddress(decodeString) + cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.AddressResponse), status.Error(codes.NotFound, err.Error()) @@ -29,21 +39,130 @@ func (s *Service) Address(_ context.Context, req *pb.AddressRequest) (*pb.Addres cState.RLock() defer cState.RUnlock() - address := types.BytesToAddress(decodeString) - response := &pb.AddressResponse{ - Balance: make(map[string]string), - TransactionsCount: fmt.Sprintf("%d", cState.Accounts().GetNonce(address)), + if req.Height != 0 && req.Delegated { + cState.Lock() + cState.Candidates().LoadCandidates() + cState.Candidates().LoadStakes() + cState.Unlock() } balances := cState.Accounts().GetBalances(address) + var response pb.AddressResponse + + totalStakesGroupByCoin := map[types.CoinSymbol]*big.Int{} + + response.Balance = make(map[string]*pb.AddressBalance, len(balances)) + for coin, value := range balances { + totalStakesGroupByCoin[coin] = value + response.Balance[coin.String()] = &pb.AddressBalance{ + Value: value.String(), + BipValue: customCoinBipBalance(coin, value, cState).String(), + } + } + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.AddressResponse), timeoutStatus.Err() + } + + if req.Delegated { + var userDelegatedStakesGroupByCoin = map[types.CoinSymbol]*UserStake{} + allCandidates := cState.Candidates().GetCandidates() + for _, candidate := range allCandidates { + userStakes := userStakes(candidate.PubKey, address, cState) + for coin, userStake := range userStakes { + stake, ok := userDelegatedStakesGroupByCoin[coin] + if !ok { + stake = &UserStake{ + Value: big.NewInt(0), + BipValue: big.NewInt(0), + } + } + stake.Value.Add(stake.Value, userStake.Value) + stake.BipValue.Add(stake.BipValue, userStake.BipValue) + userDelegatedStakesGroupByCoin[coin] = stake + } + } + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.AddressResponse), timeoutStatus.Err() + } + + response.Delegated = make(map[string]*pb.AddressDelegatedBalance, len(userDelegatedStakesGroupByCoin)) + for coin, delegatedStake := range userDelegatedStakesGroupByCoin { + response.Delegated[coin.String()] = &pb.AddressDelegatedBalance{ + Value: delegatedStake.Value.String(), + DelegateBipValue: delegatedStake.BipValue.String(), + BipValue: customCoinBipBalance(coin, delegatedStake.Value, cState).String(), + } + + totalStake, ok := totalStakesGroupByCoin[coin] + if !ok { + totalStake = big.NewInt(0) + totalStakesGroupByCoin[coin] = totalStake + } + totalStake.Add(totalStake, delegatedStake.Value) + } + } - for k, v := range balances { - response.Balance[k.String()] = v.String() + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.AddressResponse), timeoutStatus.Err() } - if _, exists := response.Balance[types.GetBaseCoin().String()]; !exists { - response.Balance[types.GetBaseCoin().String()] = "0" + coinsBipValue := big.NewInt(0) + response.Total = make(map[string]*pb.AddressBalance, len(totalStakesGroupByCoin)) + for coin, stake := range totalStakesGroupByCoin { + balance := customCoinBipBalance(coin, stake, cState) + if req.Delegated { + response.Total[coin.String()] = &pb.AddressBalance{ + Value: stake.String(), + BipValue: balance.String(), + } + } + coinsBipValue.Add(coinsBipValue, balance) + } + response.BipValue = coinsBipValue.String() + + response.TransactionsCount = fmt.Sprintf("%d", cState.Accounts().GetNonce(address)) + return &response, nil +} + +func customCoinBipBalance(coinToSell types.CoinSymbol, valueToSell *big.Int, cState *state.CheckState) *big.Int { + coinToBuy := types.StrToCoinSymbol("BIP") + + if coinToSell == coinToBuy { + return valueToSell + } + + if coinToSell == types.GetBaseCoin() { + coin := cState.Coins().GetCoin(coinToBuy) + return formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) + } + + if coinToBuy == types.GetBaseCoin() { + coin := cState.Coins().GetCoin(coinToSell) + return formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) + } + + coinFrom := cState.Coins().GetCoin(coinToSell) + coinTo := cState.Coins().GetCoin(coinToBuy) + basecoinValue := formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) + return formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), basecoinValue) +} + +func userStakes(c types.Pubkey, address types.Address, state *state.CheckState) map[types.CoinSymbol]*UserStake { + var userStakes = map[types.CoinSymbol]*UserStake{} + + stakes := state.Candidates().GetStakes(c) + + for _, stake := range stakes { + if stake.Owner != address { + continue + } + userStakes[stake.Coin] = &UserStake{ + Value: stake.Value, + BipValue: stake.BipValue, + } } - return response, nil + return userStakes } diff --git a/api/v2/service/addresses.go b/api/v2/service/addresses.go index 614cdc3e2..9412a141f 100644 --- a/api/v2/service/addresses.go +++ b/api/v2/service/addresses.go @@ -8,9 +8,10 @@ import ( pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "math/big" ) -func (s *Service) Addresses(_ context.Context, req *pb.AddressesRequest) (*pb.AddressesResponse, error) { +func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb.AddressesResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.AddressesResponse), status.Error(codes.NotFound, err.Error()) @@ -19,36 +20,111 @@ func (s *Service) Addresses(_ context.Context, req *pb.AddressesRequest) (*pb.Ad cState.RLock() defer cState.RUnlock() + if req.Height != 0 && req.Delegated { + cState.Lock() + cState.Candidates().LoadCandidates() + cState.Candidates().LoadStakes() + cState.Unlock() + } + response := &pb.AddressesResponse{ - Addresses: make([]*pb.AddressesResponse_Result, 0, len(req.Addresses)), + Addresses: make(map[string]*pb.AddressesResponse_Result, len(req.Addresses)), } - for _, address := range req.Addresses { - if len(address) < 3 { - return new(pb.AddressesResponse), status.Error(codes.InvalidArgument, fmt.Sprintf("invalid address %s", address)) + for _, addr := range req.Addresses { + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return response, timeoutStatus.Err() + } + + if len(addr) < 3 { + return new(pb.AddressesResponse), status.Error(codes.InvalidArgument, fmt.Sprintf("invalid address %s", addr)) } - decodeString, err := hex.DecodeString(address[2:]) + decodeString, err := hex.DecodeString(addr[2:]) if err != nil { return new(pb.AddressesResponse), status.Error(codes.InvalidArgument, err.Error()) } - addr := types.BytesToAddress(decodeString) - data := &pb.AddressesResponse_Result{ - Address: address, - Balance: make(map[string]string), - TransactionsCount: fmt.Sprintf("%d", cState.Accounts().GetNonce(addr)), + address := types.BytesToAddress(decodeString) + + balances := cState.Accounts().GetBalances(address) + var res pb.AddressesResponse_Result + + totalStakesGroupByCoin := map[types.CoinSymbol]*big.Int{} + + res.Balance = make(map[string]*pb.AddressBalance, len(balances)) + for coin, value := range balances { + totalStakesGroupByCoin[coin] = value + res.Balance[coin.String()] = &pb.AddressBalance{ + Value: value.String(), + BipValue: customCoinBipBalance(coin, value, cState).String(), + } + } + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.AddressesResponse), timeoutStatus.Err() + } + + if req.Delegated { + var userDelegatedStakesGroupByCoin = map[types.CoinSymbol]*UserStake{} + allCandidates := cState.Candidates().GetCandidates() + for _, candidate := range allCandidates { + userStakes := userStakes(candidate.PubKey, address, cState) + for coin, userStake := range userStakes { + stake, ok := userDelegatedStakesGroupByCoin[coin] + if !ok { + stake = &UserStake{ + Value: big.NewInt(0), + BipValue: big.NewInt(0), + } + } + stake.Value.Add(stake.Value, userStake.Value) + stake.BipValue.Add(stake.BipValue, userStake.BipValue) + userDelegatedStakesGroupByCoin[coin] = stake + } + } + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.AddressesResponse), timeoutStatus.Err() + } + + res.Delegated = make(map[string]*pb.AddressDelegatedBalance, len(userDelegatedStakesGroupByCoin)) + for coin, delegatedStake := range userDelegatedStakesGroupByCoin { + res.Delegated[coin.String()] = &pb.AddressDelegatedBalance{ + Value: delegatedStake.Value.String(), + DelegateBipValue: delegatedStake.BipValue.String(), + BipValue: customCoinBipBalance(coin, delegatedStake.Value, cState).String(), + } + + totalStake, ok := totalStakesGroupByCoin[coin] + if !ok { + totalStake = big.NewInt(0) + totalStakesGroupByCoin[coin] = totalStake + } + totalStake.Add(totalStake, delegatedStake.Value) + } } - balances := cState.Accounts().GetBalances(addr) - for k, v := range balances { - data.Balance[k.String()] = v.String() + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return response, timeoutStatus.Err() } - if _, exists := data.Balance[types.GetBaseCoin().String()]; !exists { - data.Balance[types.GetBaseCoin().String()] = "0" + coinsBipValue := big.NewInt(0) + res.Total = make(map[string]*pb.AddressBalance, len(totalStakesGroupByCoin)) + for coin, stake := range totalStakesGroupByCoin { + balance := customCoinBipBalance(coin, stake, cState) + if req.Delegated { + res.Total[coin.String()] = &pb.AddressBalance{ + Value: stake.String(), + BipValue: balance.String(), + } + } + coinsBipValue.Add(coinsBipValue, balance) } + res.BipValue = coinsBipValue.String() + res.TransactionsCount = fmt.Sprintf("%d", cState.Accounts().GetNonce(address)) - response.Addresses = append(response.Addresses, data) + response.Addresses[addr] = &res } return response, nil diff --git a/api/v2/service/block.go b/api/v2/service/block.go index 845a27d5e..b1c5ce29b 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -16,7 +16,7 @@ import ( "time" ) -func (s *Service) Block(_ context.Context, req *pb.BlockRequest) (*pb.BlockResponse, error) { +func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockResponse, error) { height := int64(req.Height) block, err := s.client.Block(&height) if err != nil { @@ -33,15 +33,148 @@ func (s *Service) Block(_ context.Context, req *pb.BlockRequest) (*pb.BlockRespo valHeight = 1 } + response := &pb.BlockResponse{ + Hash: hex.EncodeToString(block.Block.Hash()), + Height: fmt.Sprintf("%d", block.Block.Height), + Time: block.Block.Time.Format(time.RFC3339Nano), + TransactionsCount: fmt.Sprintf("%d", len(block.Block.Txs)), + } + var totalValidators []*tmTypes.Validator - for i := 0; i < (((len(block.Block.LastCommit.Signatures) - 1) / 100) + 1); i++ { - tmValidators, err := s.client.Validators(&valHeight, i+1, 100) + + if len(req.Fields) == 0 { + response.Size = fmt.Sprintf("%d", len(s.cdc.MustMarshalBinaryLengthPrefixed(block))) + response.BlockReward = rewards.GetRewardForBlock(uint64(height)).String() + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.BlockResponse), timeoutStatus.Err() + } + + response.Transactions, err = s.blockTransaction(block, blockResults) + if err != nil { + return new(pb.BlockResponse), err + } + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.BlockResponse), timeoutStatus.Err() + } + + tmValidators, err := s.client.Validators(&valHeight, 1, 100) if err != nil { return new(pb.BlockResponse), status.Error(codes.Internal, err.Error()) } - totalValidators = append(totalValidators, tmValidators.Validators...) + totalValidators = tmValidators.Validators + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.BlockResponse), timeoutStatus.Err() + } + + response.Proposer, err = blockProposer(block, totalValidators) + if err != nil { + return new(pb.BlockResponse), err + } + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.BlockResponse), timeoutStatus.Err() + } + + response.Validators = blockValidators(totalValidators, block) + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.BlockResponse), timeoutStatus.Err() + } + + response.Evidence = blockEvidence(block) + + return response, nil + } + + for _, field := range req.Fields { + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.BlockResponse), timeoutStatus.Err() + } + switch field { + case pb.BlockRequest_size: + response.Size = fmt.Sprintf("%d", len(s.cdc.MustMarshalBinaryLengthPrefixed(block))) + case pb.BlockRequest_block_reward: + response.BlockReward = rewards.GetRewardForBlock(uint64(height)).String() + case pb.BlockRequest_transactions: + response.Transactions, err = s.blockTransaction(block, blockResults) + if err != nil { + return new(pb.BlockResponse), err + } + case pb.BlockRequest_proposer, pb.BlockRequest_validators: + if len(totalValidators) == 0 { + tmValidators, err := s.client.Validators(&valHeight, 1, 100) + if err != nil { + return new(pb.BlockResponse), status.Error(codes.Internal, err.Error()) + } + totalValidators = tmValidators.Validators + } + + if pb.BlockRequest_validators == field { + response.Validators = blockValidators(totalValidators, block) + continue + } + + response.Proposer, err = blockProposer(block, totalValidators) + if err != nil { + return new(pb.BlockResponse), err + } + case pb.BlockRequest_evidence: + response.Evidence = blockEvidence(block) + } + + } + + return response, nil +} + +func blockEvidence(block *core_types.ResultBlock) *pb.BlockResponse_Evidence { + evidences := make([]*pb.BlockResponse_Evidence_Evidence, 0, len(block.Block.Evidence.Evidence)) + for _, evidence := range block.Block.Evidence.Evidence { + evidences = append(evidences, &pb.BlockResponse_Evidence_Evidence{ + Height: fmt.Sprintf("%d", evidence.Height()), + Time: evidence.Time().Format(time.RFC3339Nano), + Address: fmt.Sprintf("%s", evidence.Address()), + Hash: fmt.Sprintf("%s", evidence.Hash()), + }) + } + return &pb.BlockResponse_Evidence{Evidence: evidences} +} + +func blockValidators(totalValidators []*tmTypes.Validator, block *core_types.ResultBlock) []*pb.BlockResponse_Validator { + validators := make([]*pb.BlockResponse_Validator, 0, len(totalValidators)) + for _, tmval := range totalValidators { + signed := false + for _, vote := range block.Block.LastCommit.Signatures { + if bytes.Equal(vote.ValidatorAddress.Bytes(), tmval.Address.Bytes()) { + signed = true + break + } + } + validators = append(validators, &pb.BlockResponse_Validator{ + PublicKey: fmt.Sprintf("Mp%x", tmval.PubKey.Bytes()[5:]), + Signed: signed, + }) + } + + return validators +} + +func blockProposer(block *core_types.ResultBlock, totalValidators []*tmTypes.Validator) (string, error) { + p, err := getBlockProposer(block, totalValidators) + if err != nil { + return "", status.Error(codes.FailedPrecondition, err.Error()) } + if p != nil { + return p.String(), nil + } + return "", nil +} + +func (s *Service) blockTransaction(block *core_types.ResultBlock, blockResults *core_types.ResultBlockResults) ([]*pb.BlockResponse_Transaction, error) { txs := make([]*pb.BlockResponse_Transaction, 0, len(block.Block.Data.Txs)) for i, rawTx := range block.Block.Data.Txs { tx, _ := transaction.TxDecoder.DecodeFromBytes(rawTx) @@ -54,7 +187,7 @@ func (s *Service) Block(_ context.Context, req *pb.BlockRequest) (*pb.BlockRespo dataStruct, err := s.encodeTxData(tx) if err != nil { - return new(pb.BlockResponse), status.Error(codes.InvalidArgument, err.Error()) + return nil, status.Error(codes.InvalidArgument, err.Error()) } txs = append(txs, &pb.BlockResponse_Transaction{ @@ -74,60 +207,7 @@ func (s *Service) Block(_ context.Context, req *pb.BlockRequest) (*pb.BlockRespo Log: blockResults.TxsResults[i].Log, }) } - - var validators []*pb.BlockResponse_Validator - var proposer string - if height > 1 { - p, err := getBlockProposer(block, totalValidators) - if err != nil { - return new(pb.BlockResponse), status.Error(codes.FailedPrecondition, err.Error()) - } - - if p != nil { - str := p.String() - proposer = str - } - - validators = make([]*pb.BlockResponse_Validator, 0, len(totalValidators)) - for _, tmval := range totalValidators { - signed := false - for _, vote := range block.Block.LastCommit.Signatures { - if bytes.Equal(vote.ValidatorAddress.Bytes(), tmval.Address.Bytes()) { - signed = true - break - } - } - - validators = append(validators, &pb.BlockResponse_Validator{ - PublicKey: fmt.Sprintf("Mp%x", tmval.PubKey.Bytes()[5:]), - Signed: signed, - }) - } - } - - evidences := make([]*pb.BlockResponse_Evidence_Evidence, len(block.Block.Evidence.Evidence)) - for _, evidence := range block.Block.Evidence.Evidence { - evidences = append(evidences, &pb.BlockResponse_Evidence_Evidence{ - Height: fmt.Sprintf("%d", evidence.Height()), - Time: evidence.Time().Format(time.RFC3339Nano), - Address: fmt.Sprintf("%s", evidence.Address()), - Hash: fmt.Sprintf("%s", evidence.Hash()), - }) - } - return &pb.BlockResponse{ - Hash: hex.EncodeToString(block.Block.Hash()), - Height: fmt.Sprintf("%d", block.Block.Height), - Time: block.Block.Time.Format(time.RFC3339Nano), - TransactionsCount: fmt.Sprintf("%d", len(block.Block.Txs)), - Transactions: txs, - BlockReward: rewards.GetRewardForBlock(uint64(height)).String(), - Size: fmt.Sprintf("%d", len(s.cdc.MustMarshalBinaryLengthPrefixed(block))), - Proposer: proposer, - Validators: validators, - Evidence: &pb.BlockResponse_Evidence{ - Evidence: evidences, - }, - }, nil + return txs, nil } func getBlockProposer(block *core_types.ResultBlock, vals []*tmTypes.Validator) (*types.Pubkey, error) { diff --git a/api/v2/service/candidate.go b/api/v2/service/candidate.go index 146e5fb93..38643a7ab 100644 --- a/api/v2/service/candidate.go +++ b/api/v2/service/candidate.go @@ -12,7 +12,7 @@ import ( "google.golang.org/grpc/status" ) -func (s *Service) Candidate(_ context.Context, req *pb.CandidateRequest) (*pb.CandidateResponse, error) { +func (s *Service) Candidate(ctx context.Context, req *pb.CandidateRequest) (*pb.CandidateResponse, error) { if len(req.PublicKey) < 3 { return new(pb.CandidateResponse), status.Error(codes.InvalidArgument, "invalid public_key") } diff --git a/api/v2/service/candidates.go b/api/v2/service/candidates.go index bfbcc1cd5..2128cfe52 100644 --- a/api/v2/service/candidates.go +++ b/api/v2/service/candidates.go @@ -7,7 +7,7 @@ import ( "google.golang.org/grpc/status" ) -func (s *Service) Candidates(_ context.Context, req *pb.CandidatesRequest) (*pb.CandidatesResponse, error) { +func (s *Service) Candidates(ctx context.Context, req *pb.CandidatesRequest) (*pb.CandidatesResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.CandidatesResponse), status.Error(codes.NotFound, err.Error()) @@ -27,12 +27,17 @@ func (s *Service) Candidates(_ context.Context, req *pb.CandidatesRequest) (*pb. candidates := cState.Candidates().GetCandidates() - result := &pb.CandidatesResponse{ + response := &pb.CandidatesResponse{ Candidates: make([]*pb.CandidateResponse, 0, len(candidates)), } for _, candidate := range candidates { - result.Candidates = append(result.Candidates, makeResponseCandidate(cState, *candidate, req.IncludeStakes)) + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.CandidatesResponse), timeoutStatus.Err() + } + + response.Candidates = append(response.Candidates, makeResponseCandidate(cState, *candidate, req.IncludeStakes)) } - return result, nil + return response, nil } diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index e5e2c45f3..1ae47d7f7 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -9,7 +9,7 @@ import ( "google.golang.org/grpc/status" ) -func (s *Service) CoinInfo(_ context.Context, req *pb.CoinInfoRequest) (*pb.CoinInfoResponse, error) { +func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.CoinInfoResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.CoinInfoResponse), status.Error(codes.NotFound, err.Error()) diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index fa8ac9b2e..8b62987a5 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -13,7 +13,7 @@ import ( "math/big" ) -func (s *Service) EstimateCoinBuy(_ context.Context, req *pb.EstimateCoinBuyRequest) (*pb.EstimateCoinBuyResponse, error) { +func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRequest) (*pb.EstimateCoinBuyResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.EstimateCoinBuyResponse), status.Error(codes.NotFound, err.Error()) diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index b275340b2..0702c3865 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -13,7 +13,7 @@ import ( "math/big" ) -func (s *Service) EstimateCoinSell(_ context.Context, req *pb.EstimateCoinSellRequest) (*pb.EstimateCoinSellResponse, error) { +func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSellRequest) (*pb.EstimateCoinSellResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.EstimateCoinSellResponse), status.Error(codes.NotFound, err.Error()) diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index a80c5c2b9..b7a0a44d9 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -12,7 +12,7 @@ import ( "math/big" ) -func (s *Service) EstimateCoinSellAll(_ context.Context, req *pb.EstimateCoinSellAllRequest) (*pb.EstimateCoinSellAllResponse, error) { +func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinSellAllRequest) (*pb.EstimateCoinSellAllResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.EstimateCoinSellAllResponse), status.Error(codes.NotFound, err.Error()) diff --git a/api/v2/service/estimate_tx_commission.go b/api/v2/service/estimate_tx_commission.go index dae5884d2..d50585761 100644 --- a/api/v2/service/estimate_tx_commission.go +++ b/api/v2/service/estimate_tx_commission.go @@ -4,7 +4,10 @@ import ( "context" "encoding/hex" "fmt" + "github.com/MinterTeam/minter-go-node/core/commissions" + "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/transaction" + "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" @@ -12,7 +15,7 @@ import ( "math/big" ) -func (s *Service) EstimateTxCommission(_ context.Context, req *pb.EstimateTxCommissionRequest) (*pb.EstimateTxCommissionResponse, error) { +func (s *Service) EstimateTxCommission(ctx context.Context, req *pb.EstimateTxCommissionRequest) (*pb.EstimateTxCommissionResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.EstimateTxCommissionResponse), status.Error(codes.NotFound, err.Error()) @@ -21,11 +24,16 @@ func (s *Service) EstimateTxCommission(_ context.Context, req *pb.EstimateTxComm cState.RLock() defer cState.RUnlock() - if len(req.Tx) < 3 { - return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "invalid tx") + if len(req.GetTx()) < 3 { + data := req.GetData() + if data == nil { + return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "invalid tx and data") + } + + return commissionCoinForData(data, cState) } - decodeString, err := hex.DecodeString(req.Tx[2:]) + decodeString, err := hex.DecodeString(req.GetTx()[2:]) if err != nil { return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, err.Error()) } @@ -57,3 +65,65 @@ func (s *Service) EstimateTxCommission(_ context.Context, req *pb.EstimateTxComm Commission: commission.String(), }, nil } + +func commissionCoinForData(data *pb.EstimateTxCommissionRequest_TransactionData, cState *state.CheckState) (*pb.EstimateTxCommissionResponse, error) { + var commissionInBaseCoin *big.Int + switch data.Type { + case pb.EstimateTxCommissionRequest_TransactionData_Send: + commissionInBaseCoin = big.NewInt(commissions.SendTx) + case pb.EstimateTxCommissionRequest_TransactionData_SellAllCoin, + pb.EstimateTxCommissionRequest_TransactionData_SellCoin, + pb.EstimateTxCommissionRequest_TransactionData_BuyCoin: + commissionInBaseCoin = big.NewInt(commissions.ConvertTx) + case pb.EstimateTxCommissionRequest_TransactionData_DeclareCandidacy: + commissionInBaseCoin = big.NewInt(commissions.DeclareCandidacyTx) + case pb.EstimateTxCommissionRequest_TransactionData_Delegate: + commissionInBaseCoin = big.NewInt(commissions.DelegateTx) + case pb.EstimateTxCommissionRequest_TransactionData_Unbond: + commissionInBaseCoin = big.NewInt(commissions.UnbondTx) + case pb.EstimateTxCommissionRequest_TransactionData_SetCandidateOffline, + pb.EstimateTxCommissionRequest_TransactionData_SetCandidateOnline: + commissionInBaseCoin = big.NewInt(commissions.ToggleCandidateStatus) + case pb.EstimateTxCommissionRequest_TransactionData_EditCandidate: + commissionInBaseCoin = big.NewInt(commissions.EditCandidate) + case pb.EstimateTxCommissionRequest_TransactionData_RedeemCheck: + commissionInBaseCoin = big.NewInt(commissions.RedeemCheckTx) + case pb.EstimateTxCommissionRequest_TransactionData_CreateMultisig: + commissionInBaseCoin = big.NewInt(commissions.CreateMultisig) + case pb.EstimateTxCommissionRequest_TransactionData_Multisend: + if data.Mtxs <= 0 { + return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "Set number of txs for multisend (mtxs)") + } + commissionInBaseCoin = big.NewInt(commissions.MultisendDelta*(data.Mtxs-1) + 10) + default: + return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "Set correct txtype for tx") + } + + lenPayload := len(data.Payload) + if lenPayload > 1024 { + return new(pb.EstimateTxCommissionResponse), status.Errorf(codes.InvalidArgument, "TX payload length is over %d bytes", 1024) + } + + totalCommissionInBaseCoin := new(big.Int).Mul(big.NewInt(0).Add(commissionInBaseCoin, big.NewInt(int64(lenPayload))), transaction.CommissionMultiplier) + + if data.GasCoin == "BIP" { + return &pb.EstimateTxCommissionResponse{ + Commission: totalCommissionInBaseCoin.String(), + }, nil + } + + coin := cState.Coins().GetCoin(types.StrToCoinSymbol(data.GasCoin)) + + if coin == nil { + return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "Gas Coin not found") + } + + if totalCommissionInBaseCoin.Cmp(coin.Reserve()) == 1 { + return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "Not enough coin reserve for pay comission") + } + + return &pb.EstimateTxCommissionResponse{ + Commission: formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), totalCommissionInBaseCoin).String(), + }, nil + +} diff --git a/api/v2/service/events.go b/api/v2/service/events.go index 8122e94fa..52470064f 100644 --- a/api/v2/service/events.go +++ b/api/v2/service/events.go @@ -1,30 +1,45 @@ package service import ( - "bytes" "context" "encoding/json" eventsdb "github.com/MinterTeam/minter-go-node/core/events" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" - "github.com/golang/protobuf/jsonpb" _struct "github.com/golang/protobuf/ptypes/struct" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) -func (s *Service) Events(_ context.Context, req *pb.EventsRequest) (*pb.EventsResponse, error) { +func (s *Service) Events(ctx context.Context, req *pb.EventsRequest) (*pb.EventsResponse, error) { height := uint32(req.Height) events := s.blockchain.GetEventsDB().LoadEvents(height) resultEvents := make([]*pb.EventsResponse_Event, 0, len(events)) for _, event := range events { - byteData, err := json.Marshal(event) + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.EventsResponse), timeoutStatus.Err() + } + + var find = true + for _, s := range req.Search { + if event.AddressString() == s || event.ValidatorPubKeyString() == s { + find = true + break + } + find = false + } + if !find { + continue + } + + b, err := json.Marshal(event) if err != nil { - return nil, err + return new(pb.EventsResponse), status.Error(codes.Internal, err.Error()) } - var bb bytes.Buffer - bb.Write(byteData) - data := &_struct.Struct{Fields: make(map[string]*_struct.Value)} - if err := (&jsonpb.Unmarshaler{}).Unmarshal(&bb, data); err != nil { - return nil, err + data := &_struct.Struct{} + if err := data.UnmarshalJSON(b); err != nil { + return new(pb.EventsResponse), status.Error(codes.Internal, err.Error()) } var t string diff --git a/api/v2/service/frozen.go b/api/v2/service/frozen.go new file mode 100644 index 000000000..263362538 --- /dev/null +++ b/api/v2/service/frozen.go @@ -0,0 +1,83 @@ +package service + +import ( + "context" + "encoding/hex" + "fmt" + "github.com/MinterTeam/minter-go-node/core/types" + pb "github.com/MinterTeam/node-grpc-gateway/api_pb" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "strings" +) + +func (s *Service) Frozen(ctx context.Context, req *pb.FrozenRequest) (*pb.FrozenResponse, error) { + if !strings.HasPrefix(strings.Title(req.Address), "Mx") { + return new(pb.FrozenResponse), status.Error(codes.InvalidArgument, "invalid address") + } + + decodeString, err := hex.DecodeString(req.Address[2:]) + if err != nil { + return new(pb.FrozenResponse), status.Error(codes.InvalidArgument, "invalid address") + } + + address := types.BytesToAddress(decodeString) + + cState := s.blockchain.CurrentState() + cState.RLock() + defer cState.RUnlock() + + var frozen []*pb.FrozenResponse_Frozen + + appState := new(types.AppState) + cState.FrozenFunds().Export(appState, s.blockchain.Height()) + + var emptyAddress types.Address + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.FrozenResponse), timeoutStatus.Err() + } + + if req.Coin == "" && address == emptyAddress { + for _, fund := range appState.FrozenFunds { + frozen = append(frozen, &pb.FrozenResponse_Frozen{ + Height: fmt.Sprintf("%d", fund.Height), + Address: fund.Address.String(), + CandidateKey: fund.CandidateKey.String(), + Coin: fund.Coin.String(), + Value: fund.Value, + }) + } + return &pb.FrozenResponse{Frozen: frozen}, nil + } + + if req.Coin != "" && address != emptyAddress { + for _, fund := range appState.FrozenFunds { + if fund.Coin.String() != req.Coin || fund.Address != address { + continue + } + frozen = append(frozen, &pb.FrozenResponse_Frozen{ + Height: fmt.Sprintf("%d", fund.Height), + Address: fund.Address.String(), + CandidateKey: fund.CandidateKey.String(), + Coin: fund.Coin.String(), + Value: fund.Value, + }) + } + return &pb.FrozenResponse{Frozen: frozen}, nil + } + + for _, fund := range appState.FrozenFunds { + if fund.Coin.String() != req.Coin && fund.Address != address { + continue + } + frozen = append(frozen, &pb.FrozenResponse_Frozen{ + Height: fmt.Sprintf("%d", fund.Height), + Address: fund.Address.String(), + CandidateKey: fund.CandidateKey.String(), + Coin: fund.Coin.String(), + Value: fund.Value, + }) + } + return &pb.FrozenResponse{Frozen: frozen}, nil +} diff --git a/api/v2/service/gas.go b/api/v2/service/gas.go index 0ab52d12d..5af9edc62 100644 --- a/api/v2/service/gas.go +++ b/api/v2/service/gas.go @@ -15,7 +15,7 @@ func (s *Service) MinGasPrice(context.Context, *empty.Empty) (*pb.MinGasPriceRes }, nil } -func (s *Service) MaxGas(_ context.Context, req *pb.MaxGasRequest) (*pb.MaxGasResponse, error) { +func (s *Service) MaxGas(ctx context.Context, req *pb.MaxGasRequest) (*pb.MaxGasResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.MaxGasResponse), status.Error(codes.NotFound, err.Error()) diff --git a/api/v2/service/genesis.go b/api/v2/service/genesis.go index d2184c6df..42b4882dc 100644 --- a/api/v2/service/genesis.go +++ b/api/v2/service/genesis.go @@ -1,11 +1,9 @@ package service import ( - "bytes" "context" "fmt" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" - "github.com/golang/protobuf/jsonpb" "github.com/golang/protobuf/ptypes/empty" _struct "github.com/golang/protobuf/ptypes/struct" "google.golang.org/grpc/codes" @@ -13,21 +11,25 @@ import ( "time" ) -func (s *Service) Genesis(context.Context, *empty.Empty) (*pb.GenesisResponse, error) { +func (s *Service) Genesis(ctx context.Context, _ *empty.Empty) (*pb.GenesisResponse, error) { result, err := s.client.Genesis() if err != nil { return new(pb.GenesisResponse), status.Error(codes.FailedPrecondition, err.Error()) } - var bb bytes.Buffer - if _, err := bb.Write(result.Genesis.AppState); err != nil { - return new(pb.GenesisResponse), status.Error(codes.Internal, err.Error()) + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.GenesisResponse), timeoutStatus.Err() } - appState := &_struct.Struct{Fields: make(map[string]*_struct.Value)} - if err := (&jsonpb.Unmarshaler{}).Unmarshal(&bb, appState); err != nil { + + appState := &_struct.Struct{} + if err := appState.UnmarshalJSON(result.Genesis.AppState); err != nil { return new(pb.GenesisResponse), status.Error(codes.Internal, err.Error()) } + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.GenesisResponse), timeoutStatus.Err() + } + return &pb.GenesisResponse{ GenesisTime: result.Genesis.GenesisTime.Format(time.RFC3339Nano), ChainId: result.Genesis.ChainID, diff --git a/api/v2/service/halts.go b/api/v2/service/halts.go index 3b7bc6023..88960616d 100644 --- a/api/v2/service/halts.go +++ b/api/v2/service/halts.go @@ -9,5 +9,6 @@ import ( ) func (s *Service) Halts(_ context.Context, _ *pb.HaltsRequest) (*pb.HaltsResponse, error) { + //todo return &pb.HaltsResponse{}, status.Error(codes.Unimplemented, fmt.Sprintf("method Halts not implemented in version %s", s.version)) } diff --git a/api/v2/service/missed_blocks.go b/api/v2/service/missed_blocks.go index 835780e0f..b6b7fc64e 100644 --- a/api/v2/service/missed_blocks.go +++ b/api/v2/service/missed_blocks.go @@ -6,8 +6,8 @@ import ( pb "github.com/MinterTeam/node-grpc-gateway/api_pb" ) -func (s *Service) MissedBlocks(_ context.Context, req *pb.MissedBlocksRequest) (*pb.MissedBlocksResponse, error) { - blocks, count, err := s.blockchain.MissedBlocks(req.PublicKey, uint64(req.Height)) +func (s *Service) MissedBlocks(ctx context.Context, req *pb.MissedBlocksRequest) (*pb.MissedBlocksResponse, error) { + blocks, count, err := s.blockchain.MissedBlocks(req.PublicKey, req.Height) if err != nil { return new(pb.MissedBlocksResponse), err } diff --git a/api/v2/service/net_info.go b/api/v2/service/net_info.go index 28ef10402..92372f90f 100644 --- a/api/v2/service/net_info.go +++ b/api/v2/service/net_info.go @@ -10,7 +10,7 @@ import ( "time" ) -func (s *Service) NetInfo(context.Context, *empty.Empty) (*pb.NetInfoResponse, error) { +func (s *Service) NetInfo(ctx context.Context, _ *empty.Empty) (*pb.NetInfoResponse, error) { result, err := s.client.NetInfo() if err != nil { return new(pb.NetInfoResponse), status.Error(codes.FailedPrecondition, err.Error()) @@ -18,6 +18,11 @@ func (s *Service) NetInfo(context.Context, *empty.Empty) (*pb.NetInfoResponse, e var peers []*pb.NetInfoResponse_Peer for _, peer := range result.Peers { + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.NetInfoResponse), timeoutStatus.Err() + } + var channels []*pb.NetInfoResponse_Peer_ConnectionStatus_Channel for _, channel := range peer.ConnectionStatus.Channels { channels = append(channels, &pb.NetInfoResponse_Peer_ConnectionStatus_Channel{ diff --git a/api/v2/service/send_transaction.go b/api/v2/service/send_transaction.go index aa7b835ec..fc93dea95 100644 --- a/api/v2/service/send_transaction.go +++ b/api/v2/service/send_transaction.go @@ -14,15 +14,7 @@ import ( "google.golang.org/grpc/status" ) -func (s *Service) SendPostTransaction(ctx context.Context, req *pb.SendTransactionRequest) (*pb.SendTransactionResponse, error) { - return s.SendGetTransaction(ctx, req) -} - -func (s *Service) SendGetTransaction(ctx context.Context, req *pb.SendTransactionRequest) (*pb.SendTransactionResponse, error) { - return s.SendTransaction(ctx, req) -} - -func (s *Service) SendTransaction(_ context.Context, req *pb.SendTransactionRequest) (*pb.SendTransactionResponse, error) { +func (s *Service) SendTransaction(ctx context.Context, req *pb.SendTransactionRequest) (*pb.SendTransactionResponse, error) { if len(req.Tx) < 3 { return new(pb.SendTransactionResponse), status.Error(codes.InvalidArgument, "invalid tx") } @@ -31,8 +23,11 @@ func (s *Service) SendTransaction(_ context.Context, req *pb.SendTransactionRequ return new(pb.SendTransactionResponse), status.Error(codes.InvalidArgument, err.Error()) } - result, err := s.broadcastTxSync(decodeString) + result, err := s.broadcastTxSync(decodeString, ctx /*timeout*/) if err != nil { + if _, ok := status.FromError(err); ok { + return new(pb.SendTransactionResponse), err + } return new(pb.SendTransactionResponse), status.Error(codes.FailedPrecondition, err.Error()) } @@ -56,7 +51,7 @@ type ResultBroadcastTx struct { Hash bytes.HexBytes `json:"hash"` } -func (s *Service) broadcastTxSync(tx types.Tx) (*ResultBroadcastTx, error) { +func (s *Service) broadcastTxSync(tx types.Tx, ctx context.Context) (*ResultBroadcastTx, error) { resCh := make(chan *abci.Response, 1) err := s.tmNode.Mempool().CheckTx(tx, func(res *abci.Response) { resCh <- res @@ -64,13 +59,22 @@ func (s *Service) broadcastTxSync(tx types.Tx) (*ResultBroadcastTx, error) { if err != nil { return nil, err } - res := <-resCh - r := res.GetCheckTx() - return &ResultBroadcastTx{ - Code: r.Code, - Data: r.Data, - Log: r.Log, - Info: r.Info, - Hash: tx.Hash(), - }, nil + + select { + case res := <-resCh: + r := res.GetCheckTx() + return &ResultBroadcastTx{ + Code: r.Code, + Data: r.Data, + Log: r.Log, + Info: r.Info, + Hash: tx.Hash(), + }, nil + case <-ctx.Done(): + if ctx.Err() != context.DeadlineExceeded { + return nil, status.New(codes.Canceled, ctx.Err().Error()).Err() + } + return nil, status.New(codes.DeadlineExceeded, ctx.Err().Error()).Err() + } + } diff --git a/api/v2/service/service.go b/api/v2/service/service.go index a34e83ff6..860f0ad07 100644 --- a/api/v2/service/service.go +++ b/api/v2/service/service.go @@ -1,15 +1,17 @@ package service import ( - "bytes" + "context" "github.com/MinterTeam/minter-go-node/config" "github.com/MinterTeam/minter-go-node/core/minter" - "github.com/golang/protobuf/jsonpb" _struct "github.com/golang/protobuf/ptypes/struct" + "github.com/prometheus/client_golang/prometheus" "github.com/tendermint/go-amino" tmNode "github.com/tendermint/tendermint/node" rpc "github.com/tendermint/tendermint/rpc/client/local" + "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "time" ) type Service struct { @@ -22,7 +24,18 @@ type Service struct { } func NewService(cdc *amino.Codec, blockchain *minter.Blockchain, client *rpc.Local, node *tmNode.Node, minterCfg *config.Config, version string) *Service { - return &Service{cdc: cdc, blockchain: blockchain, client: client, minterCfg: minterCfg, version: version, tmNode: node} + prometheusTimeoutErrorsTotal := prometheus.NewCounterVec(prometheus.CounterOpts{ + Name: "timeout_errors_total", + Help: "A counter of the occurred timeout errors separated by requests.", + }, []string{"path"}) + prometheus.MustRegister(prometheusTimeoutErrorsTotal) + return &Service{cdc: cdc, + blockchain: blockchain, + client: client, + minterCfg: minterCfg, + version: version, + tmNode: node, + } } func (s *Service) createError(statusErr *status.Status, data string) error { @@ -30,14 +43,8 @@ func (s *Service) createError(statusErr *status.Status, data string) error { return statusErr.Err() } - var bb bytes.Buffer - if _, err := bb.Write([]byte(data)); err != nil { - s.client.Logger.Error(err.Error()) - return statusErr.Err() - } - - detailsMap := &_struct.Struct{Fields: make(map[string]*_struct.Value)} - if err := (&jsonpb.Unmarshaler{}).Unmarshal(&bb, detailsMap); err != nil { + detailsMap := &_struct.Struct{} + if err := detailsMap.UnmarshalJSON([]byte(data)); err != nil { s.client.Logger.Error(err.Error()) return statusErr.Err() } @@ -50,3 +57,20 @@ func (s *Service) createError(statusErr *status.Status, data string) error { return withDetails.Err() } + +func (s *Service) TimeoutDuration() time.Duration { + return time.Duration(s.minterCfg.APIv2TimeoutDuration) +} + +func (s *Service) checkTimeout(ctx context.Context) *status.Status { + select { + case <-ctx.Done(): + if ctx.Err() != context.DeadlineExceeded { + return status.New(codes.Canceled, ctx.Err().Error()) + } + + return status.New(codes.DeadlineExceeded, ctx.Err().Error()) + default: + return nil + } +} diff --git a/api/v2/service/stakes.go b/api/v2/service/stakes.go new file mode 100644 index 000000000..3f7314eaa --- /dev/null +++ b/api/v2/service/stakes.go @@ -0,0 +1,92 @@ +package service + +import ( + "context" + "encoding/hex" + "github.com/MinterTeam/minter-go-node/core/state/candidates" + "github.com/MinterTeam/minter-go-node/core/types" + pb "github.com/MinterTeam/node-grpc-gateway/api_pb" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "strings" +) + +func (s *Service) Stakes(ctx context.Context, req *pb.StakesRequest) (*pb.StakesResponse, error) { + if !strings.HasPrefix(req.PublicKey, "Mp") { + return new(pb.StakesResponse), status.Error(codes.InvalidArgument, "public key don't has prefix 'Mp'") + } + + pubKey := types.HexToPubkey(req.PublicKey[2:]) + + var address types.Address + if req.Address != "" { + if !strings.HasPrefix(strings.Title(req.Address), "Mx") { + return new(pb.StakesResponse), status.Error(codes.InvalidArgument, "invalid address") + } + + decodeAddr, err := hex.DecodeString(req.Address[2:]) + if err != nil { + return new(pb.StakesResponse), status.Error(codes.InvalidArgument, "invalid address") + } + + address = types.BytesToAddress(decodeAddr) + } + + cState, err := s.blockchain.GetStateForHeight(req.Height) + if err != nil { + return nil, err + } + + if req.Height != 0 { + cState.Lock() + cState.Candidates().LoadCandidates() + cState.Candidates().LoadStakes() + cState.Unlock() + } + + cState.RLock() + defer cState.RUnlock() + + var allCandidates []*candidates.Candidate + if req.PublicKey == "" { + allCandidates = cState.Candidates().GetCandidates() + } else { + allCandidates = []*candidates.Candidate{cState.Candidates().GetCandidate(pubKey)} + } + + var result []*pb.StakesResponse_Stake + for _, candidate := range allCandidates { + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.StakesResponse), timeoutStatus.Err() + } + + var multi bool + var allPubkeyStakes bool + + if req.Coin != "" && req.Address != "" { + multi = true + } + if req.Coin == "" && req.Address == "" { + allPubkeyStakes = true + } + + stakes := cState.Candidates().GetStakes(pubKey) + for _, stake := range stakes { + if !((multi && stake.Coin.String() == req.Coin && stake.Owner == address) || (!multi && (stake.Coin.String() == req.Coin || stake.Owner == address || allPubkeyStakes))) { + continue + } + result = append(result, &pb.StakesResponse_Stake{ + Address: stake.Owner.String(), + PubKey: candidate.PubKey.String(), + Coin: stake.Coin.String(), + Value: stake.Value.String(), + BipValue: stake.BipValue.String(), + }) + } + } + + return &pb.StakesResponse{ + Stakes: result, + }, nil +} diff --git a/api/v2/service/status.go b/api/v2/service/status.go index 1b2ad70a4..d8aadcac7 100644 --- a/api/v2/service/status.go +++ b/api/v2/service/status.go @@ -22,7 +22,8 @@ func (s *Service) Status(context.Context, *empty.Empty) (*pb.StatusResponse, err LatestAppHash: fmt.Sprintf("%X", result.SyncInfo.LatestAppHash), LatestBlockHeight: fmt.Sprintf("%d", result.SyncInfo.LatestBlockHeight), LatestBlockTime: result.SyncInfo.LatestBlockTime.Format(time.RFC3339Nano), - KeepLastStates: fmt.Sprintf("%d", s.blockchain.CurrentState().Tree().KeepLastHeight()), + KeepLastStates: fmt.Sprintf("%d", s.minterCfg.BaseConfig.KeepLastStates), + TotalSlashed: s.blockchain.CurrentState().App().GetTotalSlashed().String(), CatchingUp: result.SyncInfo.CatchingUp, PublicKey: fmt.Sprintf("Mp%x", result.ValidatorInfo.PubKey.Bytes()[5:]), NodeId: string(result.NodeInfo.ID()), diff --git a/api/v2/service/transaction.go b/api/v2/service/transaction.go index e55f26c18..f7e41f2df 100644 --- a/api/v2/service/transaction.go +++ b/api/v2/service/transaction.go @@ -1,21 +1,19 @@ package service import ( - "bytes" "context" "encoding/hex" "errors" "fmt" "github.com/MinterTeam/minter-go-node/core/transaction" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" - "github.com/golang/protobuf/jsonpb" _struct "github.com/golang/protobuf/ptypes/struct" tmbytes "github.com/tendermint/tendermint/libs/bytes" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) -func (s *Service) Transaction(_ context.Context, req *pb.TransactionRequest) (*pb.TransactionResponse, error) { +func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) (*pb.TransactionResponse, error) { if len(req.Hash) < 3 { return new(pb.TransactionResponse), status.Error(codes.InvalidArgument, "invalid hash") } @@ -65,7 +63,6 @@ func (s *Service) encodeTxData(decodedTx *transaction.Transaction) (*_struct.Str var ( err error b []byte - bb bytes.Buffer ) switch decodedTx.Type { case transaction.TypeSend: @@ -104,10 +101,8 @@ func (s *Service) encodeTxData(decodedTx *transaction.Transaction) (*_struct.Str return nil, err } - bb.Write(b) - - dataStruct := &_struct.Struct{Fields: make(map[string]*_struct.Value)} - if err := (&jsonpb.Unmarshaler{}).Unmarshal(&bb, dataStruct); err != nil { + dataStruct := &_struct.Struct{} + if err := dataStruct.UnmarshalJSON(b); err != nil { return nil, err } diff --git a/api/v2/service/transactions.go b/api/v2/service/transactions.go index cd7429024..ae6b0d73b 100644 --- a/api/v2/service/transactions.go +++ b/api/v2/service/transactions.go @@ -10,7 +10,7 @@ import ( "google.golang.org/grpc/status" ) -func (s *Service) Transactions(_ context.Context, req *pb.TransactionsRequest) (*pb.TransactionsResponse, error) { +func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) (*pb.TransactionsResponse, error) { page := int(req.Page) if page == 0 { page = 1 @@ -27,6 +27,11 @@ func (s *Service) Transactions(_ context.Context, req *pb.TransactionsRequest) ( result := make([]*pb.TransactionResponse, 0, len(rpcResult.Txs)) for _, tx := range rpcResult.Txs { + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.TransactionsResponse), timeoutStatus.Err() + } + decodedTx, _ := transaction.TxDecoder.DecodeFromBytes(tx.Tx) sender, _ := decodedTx.Sender() diff --git a/api/v2/service/unconfirmed_txs.go b/api/v2/service/unconfirmed_txs.go index 32f7a6688..666430715 100644 --- a/api/v2/service/unconfirmed_txs.go +++ b/api/v2/service/unconfirmed_txs.go @@ -8,7 +8,7 @@ import ( "google.golang.org/grpc/status" ) -func (s *Service) UnconfirmedTxs(_ context.Context, req *pb.UnconfirmedTxsRequest) (*pb.UnconfirmedTxsResponse, error) { +func (s *Service) UnconfirmedTxs(ctx context.Context, req *pb.UnconfirmedTxsRequest) (*pb.UnconfirmedTxsResponse, error) { txs, err := s.client.UnconfirmedTxs(int(req.Limit)) if err != nil { return new(pb.UnconfirmedTxsResponse), status.Error(codes.Internal, err.Error()) diff --git a/api/v2/service/validators.go b/api/v2/service/validators.go index d0d75e19c..1569d1748 100644 --- a/api/v2/service/validators.go +++ b/api/v2/service/validators.go @@ -9,7 +9,7 @@ import ( "google.golang.org/grpc/status" ) -func (s *Service) Validators(_ context.Context, req *pb.ValidatorsRequest) (*pb.ValidatorsResponse, error) { +func (s *Service) Validators(ctx context.Context, req *pb.ValidatorsRequest) (*pb.ValidatorsResponse, error) { height := int64(req.Height) if height == 0 { height = int64(s.blockchain.Height()) @@ -20,6 +20,10 @@ func (s *Service) Validators(_ context.Context, req *pb.ValidatorsRequest) (*pb. return new(pb.ValidatorsResponse), status.Error(codes.FailedPrecondition, err.Error()) } + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.ValidatorsResponse), timeoutStatus.Err() + } + responseValidators := make([]*pb.ValidatorsResponse_Result, 0, len(tmVals.Validators)) for _, val := range tmVals.Validators { var pk types.Pubkey diff --git a/api/v2/service/ws.go b/api/v2/service/ws.go index fde7a4a1e..6fd8bd717 100644 --- a/api/v2/service/ws.go +++ b/api/v2/service/ws.go @@ -1,12 +1,10 @@ package service import ( - "bytes" "context" "encoding/json" "fmt" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" - "github.com/golang/protobuf/jsonpb" _struct "github.com/golang/protobuf/ptypes/struct" "github.com/google/uuid" core_types "github.com/tendermint/tendermint/rpc/core/types" @@ -60,23 +58,22 @@ func (s *Service) Subscribe(request *pb.SubscribeRequest, stream pb.ApiService_S } func subscribeResponse(msg core_types.ResultEvent) (*pb.SubscribeResponse, error) { - var events []*pb.SubscribeResponse_Event + events := make([]*pb.SubscribeResponse_Event, 0, len(msg.Events)) for key, eventSlice := range msg.Events { events = append(events, &pb.SubscribeResponse_Event{ Key: key, Events: eventSlice, }) } + byteData, err := json.Marshal(msg.Data) if err != nil { return nil, err } - var bb bytes.Buffer - bb.Write(byteData) + data := &_struct.Struct{} - data := &_struct.Struct{Fields: make(map[string]*_struct.Value)} - if err := (&jsonpb.Unmarshaler{}).Unmarshal(&bb, data); err != nil { + if err := data.UnmarshalJSON(byteData); err != nil { return nil, err } diff --git a/api/v2/v2.go b/api/v2/v2.go index 6294594ae..fac2ec5a5 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -19,6 +19,7 @@ import ( "net/http" "os" "strings" + "time" ) func Run(srv *service.Service, addrGRPC, addrApi string, traceLog bool) error { @@ -35,8 +36,11 @@ func Run(srv *service.Service, addrGRPC, addrApi string, traceLog bool) error { grpc_middleware.WithUnaryServerChain( grpc_prometheus.UnaryServerInterceptor, grpc_recovery.UnaryServerInterceptor(), + contextWithTimeoutInterceptor(srv.TimeoutDuration()), ), ) + runtime.DefaultContextTimeout = 10 * time.Second + gw.RegisterApiServiceServer(grpcServer, srv) grpc_prometheus.Register(grpcServer) @@ -49,7 +53,9 @@ func Run(srv *service.Service, addrGRPC, addrApi string, traceLog bool) error { ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() - gwmux := runtime.NewServeMux(runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{OrigName: true, EmitDefaults: true})) + gwmux := runtime.NewServeMux( + runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{OrigName: true, EmitDefaults: true}), + ) opts := []grpc.DialOption{ grpc.WithInsecure(), grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(50000000)), @@ -64,7 +70,10 @@ func Run(srv *service.Service, addrGRPC, addrApi string, traceLog bool) error { handler = handlers.CombinedLoggingHandler(os.Stdout, handler) } mux.Handle("/", handler) - serveOpenAPI(mux) + if err := serveOpenAPI(mux); err != nil { + //ignore + } + group.Go(func() error { return http.ListenAndServe(addrApi, allowCORS(mux)) }) @@ -85,7 +94,7 @@ func allowCORS(h http.Handler) http.Handler { }) } -func preflightHandler(w http.ResponseWriter, r *http.Request) { +func preflightHandler(w http.ResponseWriter, _ *http.Request) { headers := []string{"Content-Type", "Accept"} w.Header().Set("Access-Control-Allow-Headers", strings.Join(headers, ",")) methods := []string{"GET", "HEAD", "POST", "PUT", "DELETE"} @@ -94,7 +103,7 @@ func preflightHandler(w http.ResponseWriter, r *http.Request) { } func serveOpenAPI(mux *http.ServeMux) error { - mime.AddExtensionType(".svg", "image/svg+xml") + _ = mime.AddExtensionType(".svg", "image/svg+xml") statikFS, err := fs.New() if err != nil { @@ -107,3 +116,10 @@ func serveOpenAPI(mux *http.ServeMux) error { mux.Handle(prefix, http.StripPrefix(prefix, fileServer)) return nil } + +func contextWithTimeoutInterceptor(timeout time.Duration) func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + withTimeout, _ := context.WithTimeout(ctx, timeout) + return handler(withTimeout, req) + } +} diff --git a/cli/service/client.go b/cli/service/client.go index 1fa35a731..83dd6e203 100644 --- a/cli/service/client.go +++ b/cli/service/client.go @@ -24,7 +24,7 @@ type ManagerConsole struct { cli *cli.App } -func NewManagerConsole(cli *cli.App) *ManagerConsole { +func newManagerConsole(cli *cli.App) *ManagerConsole { return &ManagerConsole{cli: cli} } @@ -107,7 +107,7 @@ func (mc *ManagerConsole) Cli(ctx context.Context) { } } -func ConfigureManagerConsole(socketPath string) (*ManagerConsole, error) { +func NewCLI(socketPath string) (*ManagerConsole, error) { cc, err := grpc.Dial("passthrough:///unix:///"+socketPath, grpc.WithInsecure()) if err != nil { return nil, err @@ -180,7 +180,7 @@ func ConfigureManagerConsole(socketPath string) (*ManagerConsole, error) { } app.Setup() - return NewManagerConsole(app), nil + return newManagerConsole(app), nil } func exitCMD(_ *cli.Context) error { @@ -434,6 +434,7 @@ func pruneBlocksCMD(client pb.ManagerServiceClient) func(c *cli.Context) error { close(errCh) return err } + fmt.Println(progress.GetTitle()) fmt.Println("OK") return nil case recv := <-recvCh: diff --git a/cli/service/server_test.go b/cli/service/server_test.go index 03eae00de..2f4e47999 100644 --- a/cli/service/server_test.go +++ b/cli/service/server_test.go @@ -27,7 +27,7 @@ func TestStartCLIServer(t *testing.T) { } }() time.Sleep(time.Millisecond) - console, err := ConfigureManagerConsole(socketPath) + console, err := NewCLI(socketPath) if err != nil { t.Log(err) } diff --git a/cli/service/service.go b/cli/service/service.go index 672b59792..52b416c19 100644 --- a/cli/service/service.go +++ b/cli/service/service.go @@ -119,7 +119,7 @@ func (m *Manager) Status(context.Context, *empty.Empty) (*pb.StatusResponse, err LatestAppHash: fmt.Sprintf("%X", result.SyncInfo.LatestAppHash), LatestBlockHeight: fmt.Sprintf("%d", result.SyncInfo.LatestBlockHeight), LatestBlockTime: result.SyncInfo.LatestBlockTime.Format(time.RFC3339Nano), - KeepLastStates: fmt.Sprintf("%d", m.blockchain.CurrentState().Tree().KeepLastHeight()), + KeepLastStates: fmt.Sprintf("%d", m.cfg.BaseConfig.KeepLastStates), CatchingUp: result.SyncInfo.CatchingUp, PublicKey: fmt.Sprintf("Mp%x", result.ValidatorInfo.PubKey.Bytes()[5:]), NodeId: string(result.NodeInfo.ID()), @@ -214,28 +214,26 @@ func (m *Manager) NetInfo(context.Context, *empty.Empty) (*pb.NetInfoResponse, e } func (m *Manager) PruneBlocks(req *pb.PruneBlocksRequest, stream pb.ManagerService_PruneBlocksServer) error { - versions, err := m.blockchain.PruneBlocksNumber(req.FromHeight, req.ToHeight) - if err != nil { - return status.Error(codes.FailedPrecondition, err.Error()) + current := m.blockchain.Height() + if req.ToHeight >= int64(current) { + return status.Errorf(codes.FailedPrecondition, "cannot delete latest saved version (%d)", current) } - total := int64(len(versions)) - for i, v := range versions { - if err := m.blockchain.DeleteStateVersion(int64(v)); err != nil { - return err - } + min := req.FromHeight - 1 + total := req.ToHeight - min + for i := req.FromHeight; i <= req.ToHeight; i++ { + _ = m.blockchain.DeleteStateVersion(i) - err := stream.Send(&pb.PruneBlocksResponse{ + if err := stream.Send(&pb.PruneBlocksResponse{ Total: total, - Current: int64(i), - }) - if err != nil { + Current: i - min, + }); err != nil { return err } select { case <-stream.Context().Done(): - return stream.Context().Err() + return status.Error(codes.Canceled, stream.Context().Err().Error()) default: runtime.Gosched() } diff --git a/cmd/minter/cmd/export.go b/cmd/minter/cmd/export.go index dffbe078b..6d239c961 100644 --- a/cmd/minter/cmd/export.go +++ b/cmd/minter/cmd/export.go @@ -58,7 +58,7 @@ func export(cmd *cobra.Command, args []string) error { log.Panicf("Cannot load db: %s", err) } - currentState, err := state.NewState(height, ldb, nil, 1, 1, 0, 1) + currentState, err := state.NewState(height, ldb, nil, 1, 1) if err != nil { log.Panicf("Cannot new state at given height: %s", err) } diff --git a/cmd/minter/cmd/manager.go b/cmd/minter/cmd/manager.go index 246932944..28269d824 100644 --- a/cmd/minter/cmd/manager.go +++ b/cmd/minter/cmd/manager.go @@ -13,7 +13,7 @@ var ManagerCommand = &cobra.Command{ DisableFlagParsing: true, RunE: func(cmd *cobra.Command, args []string) error { newArgs := setParentFlags(cmd, args) - console, err := service.ConfigureManagerConsole(utils.GetMinterHome() + "/manager.sock") + console, err := service.NewCLI(utils.GetMinterHome() + "/manager.sock") if err != nil { return nil } @@ -27,7 +27,7 @@ var ManagerConsole = &cobra.Command{ DisableFlagParsing: true, RunE: func(cmd *cobra.Command, args []string) error { _ = setParentFlags(cmd, args) - console, err := service.ConfigureManagerConsole(utils.GetMinterHome() + "/manager.sock") + console, err := service.NewCLI(utils.GetMinterHome() + "/manager.sock") if err != nil { return nil } diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index a6b404cfd..d1202dc57 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -95,8 +95,8 @@ func runNode(cmd *cobra.Command) error { return err } - if cfg.StateKeepEver < 1 { - logger.Error("state_keep_ever field should be greater than 0. All state will be stored in memory. Data will not be saved to disk.") + if cfg.KeepLastStates < 1 { + panic("keep_last_states field should be greater than 0") } app := minter.NewMinterBlockchain(cfg) @@ -137,8 +137,7 @@ func runNode(cmd *cobra.Command) error { }() if cfg.Instrumentation.Prometheus { - data := statistics.New() - go app.SetStatisticData(data).Statistic(cmd.Context()) + go app.SetStatisticData(statistics.New()).Statistic(cmd.Context()) } <-cmd.Context().Done() diff --git a/config/config.go b/config/config.go index ef2535cc1..179a1e5ff 100644 --- a/config/config.go +++ b/config/config.go @@ -233,6 +233,9 @@ type BaseConfig struct { // Address to listen for API v2 connections APIv2ListenAddress string `mapstructure:"api_v2_listen_addr"` + // API v2 Timeout + APIv2TimeoutDuration int64 `mapstructure:"api_v2_timeout_duration"` + ValidatorMode bool `mapstructure:"validator_mode"` KeepLastStates int64 `mapstructure:"keep_last_states"` @@ -243,10 +246,6 @@ type BaseConfig struct { StateCacheSize int `mapstructure:"state_cache_size"` - StateKeepEver int64 `mapstructure:"state_keep_ever"` - - StateKeepRecent int64 `mapstructure:"state_keep_recent"` - StateMemAvailable int `mapstructure:"state_mem_available"` HaltHeight int `mapstructure:"halt_height"` @@ -269,11 +268,10 @@ func DefaultBaseConfig() BaseConfig { APIListenAddress: "tcp://0.0.0.0:8841", GRPCListenAddress: "tcp://0.0.0.0:8842", APIv2ListenAddress: "tcp://0.0.0.0:8843", + APIv2TimeoutDuration: 10 * time.Second.Nanoseconds(), ValidatorMode: false, - KeepLastStates: 0, + KeepLastStates: 120, StateCacheSize: 1000000, - StateKeepEver: 120, - StateKeepRecent: 1200, StateMemAvailable: 1024, APISimultaneousRequests: 100, LogPath: "stdout", diff --git a/config/toml.go b/config/toml.go index 4c3ad775e..78ec5249a 100644 --- a/config/toml.go +++ b/config/toml.go @@ -84,12 +84,6 @@ keep_last_states = {{ .BaseConfig.KeepLastStates }} # State cache size state_cache_size = {{ .BaseConfig.StateCacheSize }} -# Sets periodicity to save state on disk -state_keep_ever = {{ .BaseConfig.StateKeepEver }} - -# Sets the number of stores the last state in the memory -state_keep_recent = {{ .BaseConfig.StateKeepRecent }} - # State memory in MB state_mem_available = {{ .BaseConfig.StateMemAvailable }} diff --git a/core/minter/minter.go b/core/minter/minter.go index 07e1d52a3..11c5a7ef6 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -107,7 +107,7 @@ func NewMinterBlockchain(cfg *config.Config) *Blockchain { } // Set stateDeliver and stateCheck - blockchain.stateDeliver, err = state.NewState(blockchain.height, blockchain.stateDB, blockchain.eventsDB, cfg.StateCacheSize, cfg.StateKeepEver, cfg.StateKeepRecent, cfg.KeepLastStates) + blockchain.stateDeliver, err = state.NewState(blockchain.height, blockchain.stateDB, blockchain.eventsDB, cfg.StateCacheSize, cfg.KeepLastStates) if err != nil { panic(err) } @@ -177,7 +177,7 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res if upgrades.IsUpgradeBlock(height) { var err error - app.stateDeliver, err = state.NewState(app.height, app.stateDB, app.eventsDB, app.cfg.StateCacheSize, app.cfg.StateKeepEver, app.cfg.StateKeepRecent, app.cfg.KeepLastStates) + app.stateDeliver, err = state.NewState(app.height, app.stateDB, app.eventsDB, app.cfg.StateCacheSize, app.cfg.KeepLastStates) if err != nil { panic(err) } @@ -462,10 +462,8 @@ func (app *Blockchain) Commit() abciTypes.ResponseCommit { _ = app.eventsDB.CommitEvents() // Persist application hash and height - if app.cfg.KeepLastStates != 0 || app.height%uint64(app.cfg.StateKeepEver) == 0 { - app.appDB.SetLastBlockHash(hash) - app.appDB.SetLastHeight(app.height) - } + app.appDB.SetLastBlockHash(hash) + app.appDB.SetLastHeight(app.height) // Resetting check state to be consistent with current height app.resetCheckState() @@ -535,7 +533,7 @@ func (app *Blockchain) MissedBlocks(pubKey string, height uint64) (missedBlocks cState.RLock() defer cState.RUnlock() - val := cState.Validators().GetByPublicKey(types.HexToPubkey(pubKey)) + val := cState.Validators().GetByPublicKey(types.HexToPubkey(pubKey[2:])) if val == nil { return "", 0, status.Error(codes.NotFound, "Validator not found") } @@ -681,27 +679,6 @@ func (app *Blockchain) MaxPeerHeight() int64 { return max } -func (app *Blockchain) PruneBlocksNumber(from, to int64) ([]int, error) { - lastSnapshotVersion := app.appDB.GetLastHeight() - if to >= int64(lastSnapshotVersion) { - return nil, fmt.Errorf("cannot delete last version saved in disk (%d)", lastSnapshotVersion) - } - versions := app.stateDeliver.Tree().AvailableVersions() - - var indexFrom, indexTo int - for i, v := range versions { - if int64(v) <= from { - indexFrom = i - continue - } - if int64(v) > to { - indexTo = i - break - } - } - return versions[indexFrom:indexTo], nil -} - func (app *Blockchain) DeleteStateVersion(v int64) error { return app.stateDeliver.Tree().DeleteVersion(v) } diff --git a/core/minter/upgrade3_test.go b/core/minter/upgrade3_test.go index ea7ebebe2..04b2410d3 100644 --- a/core/minter/upgrade3_test.go +++ b/core/minter/upgrade3_test.go @@ -38,7 +38,7 @@ func TestApplyUpgrade3(t *testing.T) { } func getState() *state.State { - s, err := state.NewState(0, db.NewMemDB(), emptyEvents{}, 1, 1, 0, 1) + s, err := state.NewState(0, db.NewMemDB(), emptyEvents{}, 1, 1) if err != nil { panic(err) diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index 88ff753d4..11074a768 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -390,7 +390,7 @@ func TestDelegationAfterUnbond(t *testing.T) { } func getState() *State { - s, err := NewState(0, db.NewMemDB(), emptyEvents{}, 1, 1, 0, 1) + s, err := NewState(0, db.NewMemDB(), emptyEvents{}, 1, 1) if err != nil { panic(err) diff --git a/core/state/state.go b/core/state/state.go index 074e0bfad..b299955e0 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -16,7 +16,6 @@ import ( "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/tree" - "github.com/tendermint/iavl" db "github.com/tendermint/tm-db" "log" "math/big" @@ -99,13 +98,8 @@ type State struct { func (s *State) isValue_State() {} -func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, keepEvery, keepRecent, keepLastStates int64) (*State, error) { - options := iavl.DefaultOptions() - if keepLastStates == 0 { - options = iavl.PruningOptions(keepEvery, keepRecent) - } - - iavlTree := tree.NewMutableTree(height, db, cacheSize, options) +func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, keepLastStates int64) (*State, error) { + iavlTree := tree.NewMutableTree(height, db, cacheSize) state, err := newStateForTree(iavlTree, events, db, keepLastStates) if err != nil { @@ -120,7 +114,7 @@ func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, } func NewCheckStateAtHeight(height uint64, db db.DB) (*CheckState, error) { - iavlTree := tree.NewMutableTree(0, db, 1024, nil) + iavlTree := tree.NewMutableTree(0, db, 1024) _, err := iavlTree.LazyLoadVersion(int64(height)) if err != nil { return nil, err @@ -201,17 +195,8 @@ func (s *State) Commit() ([]byte, error) { return hash, err } - if s.keepLastStates == 0 { - return hash, nil - } - - versions := s.tree.AvailableVersions() - for _, v := range versions { - if v < int(version-s.keepLastStates) { - if err := s.tree.DeleteVersion(int64(v)); err != nil { - return hash, err - } - } + if s.keepLastStates < version-1 { + _ = s.tree.DeleteVersion(version - s.keepLastStates) } return hash, nil diff --git a/core/state/state_test.go b/core/state/state_test.go index 75f394140..cc3637c46 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -15,7 +15,7 @@ import ( func TestStateExport(t *testing.T) { height := uint64(0) - state, err := NewState(height, db.NewMemDB(), emptyEvents{}, 1, 1, 0, 1) + state, err := NewState(height, db.NewMemDB(), emptyEvents{}, 1, 1) if err != nil { log.Panic("Cannot create state") } diff --git a/core/transaction/buy_coin_test.go b/core/transaction/buy_coin_test.go index 21c627056..6055cef6b 100644 --- a/core/transaction/buy_coin_test.go +++ b/core/transaction/buy_coin_test.go @@ -27,7 +27,7 @@ var ( ) func getState() *state.State { - s, err := state.NewState(0, db.NewMemDB(), nil, 1, 1, 0, 1) + s, err := state.NewState(0, db.NewMemDB(), nil, 1, 1) if err != nil { panic(err) diff --git a/go.mod b/go.mod index 20ce2211a..868aa550d 100644 --- a/go.mod +++ b/go.mod @@ -6,14 +6,15 @@ require ( github.com/MinterTeam/node-grpc-gateway v1.1.2 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 + github.com/gdamore/tcell v1.3.0 github.com/go-kit/kit v0.10.0 - github.com/golang/protobuf v1.4.0 + github.com/golang/protobuf v1.4.2 github.com/google/uuid v1.1.1 github.com/gorilla/handlers v1.4.2 github.com/gorilla/websocket v1.4.2 github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 - github.com/grpc-ecosystem/grpc-gateway v1.14.3 + github.com/grpc-ecosystem/grpc-gateway v1.14.6 github.com/marcusolsson/tui-go v0.4.0 github.com/mattn/go-tty v0.0.3 // indirect github.com/pkg/errors v0.9.1 @@ -23,20 +24,22 @@ require ( github.com/rs/cors v1.7.0 github.com/spf13/cobra v1.0.0 github.com/spf13/viper v1.6.3 - github.com/stretchr/testify v1.5.1 + github.com/stretchr/testify v1.6.1 github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d github.com/tendermint/go-amino v0.15.1 - github.com/tendermint/iavl v0.13.3 + github.com/tendermint/iavl v0.14.0 github.com/tendermint/tendermint v0.33.5 github.com/tendermint/tm-db v0.5.1 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 github.com/urfave/cli/v2 v2.0.0 gitlab.com/tslocum/cview v1.4.7 - golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 + golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e golang.org/x/sys v0.0.0-20200523222454-059865788121 - google.golang.org/grpc v1.28.1 - google.golang.org/protobuf v1.21.0 + google.golang.org/grpc v1.29.1 + google.golang.org/protobuf v1.25.0 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 ) + +replace github.com/MinterTeam/node-grpc-gateway => /Users/klim0v/GolandProjects/node-grpc-gateway diff --git a/go.sum b/go.sum index c3b7e7e91..ecf9b63fa 100644 --- a/go.sum +++ b/go.sum @@ -2,14 +2,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200102211924-4bcbc698314f h1:4O1om+UVU+Hfcihr1timk8YNXHxzZWgCo7ofnrZRApw= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200102211924-4bcbc698314f/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.2 h1:kHwlqPlKXFZX+SjUjqGp4c7pmONhM438EzUyJV8hKyg= -github.com/MinterTeam/node-grpc-gateway v1.1.2/go.mod h1:tfJiYOCloZD+Q8nSplqVQFQNs3ggFgBBVQa0hOVCsjg= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= @@ -23,7 +19,7 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -40,13 +36,9 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d h1:xG8Pj6Y6J760xwETNmMzmlt38QSwz0BLp1cZ09g27uw= -github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0= github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a h1:RQMUrEILyYJEoAT34XS/kLu40vC0+po/UfxrBBA4qZE= -github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= @@ -100,8 +92,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/etcd-io/bbolt v1.3.3 h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM= -github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= @@ -153,16 +143,15 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -175,6 +164,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -193,8 +184,6 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -205,8 +194,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0 h1:bM6ZAFZmc/wPFaRDi0d5L7hGEZEx/2u+Tmr2evNHDiI= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.14.3 h1:OCJlWkOUoTnl0neNGlf4fUm3TmbEtguw7vR+nGtnDjY= -github.com/grpc-ecosystem/grpc-gateway v1.14.3/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0= +github.com/grpc-ecosystem/grpc-gateway v1.14.6 h1:8ERzHx8aj1Sc47mu9n/AksaKCSWrMchFtkdrS4BIj5o= +github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f h1:8N8XWLZelZNibkhM1FuF+3Ad3YIbgirjdMiVA0eUkaM= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= @@ -374,8 +363,6 @@ github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAy github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= -github.com/prometheus/client_golang v1.5.0 h1:Ctq0iGpCmr3jeP77kbF2UxgvRwzWWz+4Bh9/vJTyg1A= -github.com/prometheus/client_golang v1.5.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.5.1 h1:bdHYieyGlH+6OLEk2YQha8THib30KP0/yD0YH9m6xcA= github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -441,8 +428,6 @@ github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.6 h1:breEStsVwemnKh2/s6gMvSdMEkwW0sK8vGStnlVBMCs= -github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= @@ -452,8 +437,6 @@ github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.6.2 h1:7aKfF+e8/k68gda3LOjo5RxiUqddoFxVq4BKBPrxk5E= -github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= github.com/spf13/viper v1.6.3 h1:pDDu1OyEDTKzpJwdq4TiuLyMsUgRa/BT5cn5O62NoHs= github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -467,6 +450,8 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d h1:gZZadD8H+fF+n9CmNhYL1Y0dJB+kLOmKd7FbPJLeGHs= @@ -476,14 +461,10 @@ github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7 github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso= github.com/tendermint/go-amino v0.15.1 h1:D2uk35eT4iTsvJd9jWIetzthE5C0/k2QmMFkCN+4JgQ= github.com/tendermint/go-amino v0.15.1/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/tendermint/iavl v0.13.3 h1:expgBDY1MX+6/3sqrIxGChbTNf9N9aTJ67SH4bPchCs= -github.com/tendermint/iavl v0.13.3/go.mod h1:2lE7GiWdSvc7kvT78ncIKmkOjCnp6JEnSb2O7B9htLw= -github.com/tendermint/tendermint v0.33.2 h1:NzvRMTuXJxqSsFed2J7uHmMU5N1CVzSpfi3nCc882KY= -github.com/tendermint/tendermint v0.33.2/go.mod h1:25DqB7YvV1tN3tHsjWoc2vFtlwICfrub9XO6UBO+4xk= +github.com/tendermint/iavl v0.14.0 h1:Jkff+IFrXxRWtH9Jn/ga/2cxNnzMTv58xEKgCJsKUBg= +github.com/tendermint/iavl v0.14.0/go.mod h1:QmfViflFiXzxKLQE4tAUuWQHq+RSuQFxablW5oJZ6sE= github.com/tendermint/tendermint v0.33.5 h1:jYgRd9ImkzA9iOyhpmgreYsqSB6tpDa6/rXYPb8HKE8= github.com/tendermint/tendermint v0.33.5/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM= -github.com/tendermint/tm-db v0.4.1 h1:TvX7JWjJOVZ+N3y+I86wddrGttOdMmmBxXcu0/Y7ZJ0= -github.com/tendermint/tm-db v0.4.1/go.mod h1:JsJ6qzYkCGiGwm5GHl/H5GLI9XLb6qZX7PRe425dHAY= github.com/tendermint/tm-db v0.5.1 h1:H9HDq8UEA7Eeg13kdYckkgwwkQLBnJGgX4PgLJRhieY= github.com/tendermint/tm-db v0.5.1/go.mod h1:g92zWjHpCYlEvQXvy9M168Su8V1IBEeawpXVVBaK4f4= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -528,6 +509,8 @@ golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 h1:DOmugCavvUtnUD114C1Wh+UgTgQZ4pMLzXxi1pSt+/Y= golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88= +golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -561,6 +544,7 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7 golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -633,10 +617,10 @@ google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c h1:hrpEMCZ2O7DR5gC1n2AJGVhrwiEjOi35+jxtIuZpTMo= -google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940 h1:MRHtG0U6SnaUb+s+LhNE1qt1FQ1wlhqr5E4usBKC0uA= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5 h1:a/Sqq5B3dGnmxhuJZIHFsIxhEkqElErr5TaU6IqBAj0= +google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -645,23 +629,29 @@ google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k= google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtWgA5THM5lhBAw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -689,6 +679,8 @@ gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/rpc/lib/server/http_server.go b/rpc/lib/server/http_server.go index 90a262430..2b9c1c1e4 100644 --- a/rpc/lib/server/http_server.go +++ b/rpc/lib/server/http_server.go @@ -124,6 +124,10 @@ func RecoverAndLogHandler(handler http.Handler, logger log.Logger) http.Handler begin := time.Now() rww.Header().Set("X-Server-Time", fmt.Sprintf("%v", begin.Unix())) + rww.Header().Set("Deprecation", "version=\"v1\"") + // rww.Header().Set("Link", fmt.Sprintf("<%s>; rel=\"successor-version\"","")) + // rww.Header().Set("Link", fmt.Sprintf("<%s>; rel=\"deprecation\"","")) + // rww.Header().Set("Sunset", time.Unix(0,0).Format(time.RFC1123)) defer func() { // Send a 500 error if a panic happens during a handler. diff --git a/tree/tree.go b/tree/tree.go index 44d1798fb..b1337870b 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -27,8 +27,8 @@ type MTree interface { GetImmutableAtHeight(version int64) (*ImmutableTree, error) } -func NewMutableTree(height uint64, db dbm.DB, cacheSize int, options *iavl.Options) MTree { - tree, err := iavl.NewMutableTreeWithOpts(db, dbm.NewMemDB(), cacheSize, options) +func NewMutableTree(height uint64, db dbm.DB, cacheSize int) MTree { + tree, err := iavl.NewMutableTree(db, cacheSize) if err != nil { panic(err) } From a94303e61ac5eb58a784ad81fdd9a21750ebf0f0 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 3 Jul 2020 18:24:13 +0300 Subject: [PATCH 042/426] halts and update gateway --- api/v2/service/halts.go | 2 +- core/minter/minter.go | 55 +++++++++++++++++++++++++++++- core/minter/minter_test.go | 4 +-- core/state/halts/halts.go | 8 +++-- core/state/state.go | 5 ++- core/transaction/set_halt_block.go | 30 +++++++++------- go.mod | 7 ++-- go.sum | 8 +++-- tree/tree.go | 8 +++-- 9 files changed, 98 insertions(+), 29 deletions(-) diff --git a/api/v2/service/halts.go b/api/v2/service/halts.go index 2944b9b9d..91a40a429 100644 --- a/api/v2/service/halts.go +++ b/api/v2/service/halts.go @@ -13,7 +13,7 @@ func (s *Service) Halts(_ context.Context, req *pb.HaltsRequest) (*pb.HaltsRespo return new(pb.HaltsResponse), status.Error(codes.NotFound, err.Error()) } - blocks := cState.Halts.GetHaltBlocks(req.Height) + blocks := cState.Halts().GetHaltBlocks(req.Height) if blocks == nil { return &pb.HaltsResponse{}, nil diff --git a/core/minter/minter.go b/core/minter/minter.go index 11c5a7ef6..52615630a 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -47,6 +47,8 @@ const ( DefaultMaxGas = 100000 MinMaxGas = 5000 + + VotingPowerConsensus = 2. / 3. ) var ( @@ -171,7 +173,7 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res app.StatisticData().PushStartBlock(&statistics.StartRequest{Height: int64(height), Now: time.Now(), HeaderTime: req.Header.Time}) - if app.haltHeight > 0 && height >= app.haltHeight { + if app.isApplicationHalted(height) { panic(fmt.Sprintf("Application halted at height %d", height)) } @@ -246,6 +248,11 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res app.stateDeliver.FrozenFunds.Delete(frozenFunds.Height()) } + if height >= upgrades.UpgradeBlock4 { + // delete halts from db + app.stateDeliver.Halts.Delete(height) + } + return abciTypes.ResponseBeginBlock{} } @@ -694,3 +701,49 @@ func getDbOpts(memLimit int) *opt.Options { Filter: filter.NewBloomFilter(10), } } + +func (app *Blockchain) isApplicationHalted(height uint64) bool { + if app.haltHeight > 0 && height >= app.haltHeight { + return true + } + + if height < upgrades.UpgradeBlock4 { + return false + } + + halts := app.stateDeliver.Halts.GetHaltBlocks(height) + if halts != nil { + // calculate total power of validators + vals := app.stateDeliver.Validators.GetValidators() + totalPower, totalVotingPower := big.NewInt(0), big.NewInt(0) + for _, val := range vals { + // skip if candidate is not present + if val.IsToDrop() || app.validatorsStatuses[val.GetAddress()] != ValidatorPresent { + continue + } + + for _, halt := range halts.List { + if halt.Pubkey == val.PubKey { + totalVotingPower.Add(totalVotingPower, val.GetTotalBipStake()) + } + } + + totalPower.Add(totalPower, val.GetTotalBipStake()) + } + + if totalPower.Cmp(types.Big0) == 0 { + totalPower = big.NewInt(1) + } + + votingResult := new(big.Float).Quo( + new(big.Float).SetInt(totalVotingPower), + new(big.Float).SetInt(totalPower), + ) + + if votingResult.Cmp(big.NewFloat(VotingPowerConsensus)) == 1 { + return true + } + } + + return false +} diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index 4af43627c..979ac409d 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -26,7 +26,7 @@ import ( "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/privval" "github.com/tendermint/tendermint/proxy" - rpc "github.com/tendermint/tendermint/rpc/client" + rpc "github.com/tendermint/tendermint/rpc/client/local" _ "github.com/tendermint/tendermint/types" types2 "github.com/tendermint/tendermint/types" "math/big" @@ -110,7 +110,7 @@ func initNode() { logger.Info("Started node", "nodeInfo", node.Switch().NodeInfo()) app.SetTmNode(node) - tmCli = rpc.NewLocal(node) + tmCli = rpc.New(node) l.Unlock() } diff --git a/core/state/halts/halts.go b/core/state/halts/halts.go index 64bb0f224..fb9ada436 100644 --- a/core/state/halts/halts.go +++ b/core/state/halts/halts.go @@ -13,17 +13,21 @@ import ( const mainPrefix = byte('h') +type RHalts interface { + GetHaltBlocks(height uint64) *Model +} + type HaltBlocks struct { list map[uint64]*Model dirty map[uint64]interface{} bus *bus.Bus - iavl tree.Tree + iavl tree.MTree lock sync.RWMutex } -func NewHalts(stateBus *bus.Bus, iavl tree.Tree) (*HaltBlocks, error) { +func NewHalts(stateBus *bus.Bus, iavl tree.MTree) (*HaltBlocks, error) { halts := &HaltBlocks{ bus: stateBus, iavl: iavl, diff --git a/core/state/state.go b/core/state/state.go index 070e95ba2..07a98f630 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -65,6 +65,9 @@ func (cs *CheckState) Candidates() candidates.RCandidates { func (cs *CheckState) FrozenFunds() frozenfunds.RFrozenFunds { return cs.state.FrozenFunds } +func (cs *CheckState) Halts() halts.RHalts { + return cs.state.Halts +} func (cs *CheckState) Accounts() accounts.RAccounts { return cs.state.Accounts } @@ -116,7 +119,7 @@ func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, } func NewCheckStateAtHeight(height uint64, db db.DB) (*CheckState, error) { - iavlTree := tree.NewMutableTree(0, db, 1024) + iavlTree := tree.NewMutableTree(height, db, 1024) _, err := iavlTree.LazyLoadVersion(int64(height)) if err != nil { return nil, err diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index 6acc89836..1e8bb4ff7 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -39,8 +39,8 @@ func (data SetHaltBlockData) TotalSpend(tx *Transaction, context *state.State) ( panic("implement me") } -func (data SetHaltBlockData) BasicCheck(tx *Transaction, context *state.State) *Response { - if !context.Candidates.Exists(data.PubKey) { +func (data SetHaltBlockData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { + if !context.Candidates().Exists(data.PubKey) { return &Response{ Code: code.CandidateNotFound, Log: fmt.Sprintf("Candidate with such public key not found"), @@ -62,7 +62,7 @@ func (data SetHaltBlockData) Gas() int64 { return commissions.SetHaltBlock } -func (data SetHaltBlockData) Run(tx *Transaction, context *state.State, isCheck bool, rewardPool *big.Int, currentBlock uint64) Response { +func (data SetHaltBlockData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { if currentBlock < upgrades.UpgradeBlock4 { return Response{ Code: code.DecodeError, @@ -72,7 +72,13 @@ func (data SetHaltBlockData) Run(tx *Transaction, context *state.State, isCheck sender, _ := tx.Sender() - response := data.BasicCheck(tx, context) + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + response := data.BasicCheck(tx, checkState) if response != nil { return *response } @@ -91,7 +97,7 @@ func (data SetHaltBlockData) Run(tx *Transaction, context *state.State, isCheck commission := big.NewInt(0).Set(commissionInBaseCoin) if !tx.GasCoin.IsBaseCoin() { - coin := context.Coins.GetCoin(tx.GasCoin) + coin := checkState.Coins().GetCoin(tx.GasCoin) errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) if errResp != nil { @@ -113,7 +119,7 @@ func (data SetHaltBlockData) Run(tx *Transaction, context *state.State, isCheck commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) } - if context.Accounts.GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, tx.GasCoin), @@ -125,15 +131,15 @@ func (data SetHaltBlockData) Run(tx *Transaction, context *state.State, isCheck } } - if !isCheck { + if deliveryState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - context.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - context.Coins.SubVolume(tx.GasCoin, commission) + deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliveryState.Coins.SubVolume(tx.GasCoin, commission) - context.Accounts.SubBalance(sender, tx.GasCoin, commission) - context.Halts.AddHaltBlock(data.Height, data.PubKey) - context.Accounts.SetNonce(sender, tx.Nonce) + deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliveryState.Halts.AddHaltBlock(data.Height, data.PubKey) + deliveryState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/go.mod b/go.mod index 868aa550d..672a4cb1c 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,9 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.2 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200703152116-e7149c5e7eb3 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 - github.com/gdamore/tcell v1.3.0 github.com/go-kit/kit v0.10.0 github.com/golang/protobuf v1.4.2 github.com/google/uuid v1.1.1 @@ -37,9 +36,7 @@ require ( golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e golang.org/x/sys v0.0.0-20200523222454-059865788121 - google.golang.org/grpc v1.29.1 + google.golang.org/grpc v1.30.0 google.golang.org/protobuf v1.25.0 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 ) - -replace github.com/MinterTeam/node-grpc-gateway => /Users/klim0v/GolandProjects/node-grpc-gateway diff --git a/go.sum b/go.sum index ecf9b63fa..9d9bc4e88 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200703152116-e7149c5e7eb3 h1:O1uMi5FUdiOXYmCaAwkH6WNxbWTf6EExI19FYGN2728= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200703152116-e7149c5e7eb3/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= @@ -619,8 +621,8 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2El google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5 h1:a/Sqq5B3dGnmxhuJZIHFsIxhEkqElErr5TaU6IqBAj0= -google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200702021140-07506425bd67 h1:4BC1C1i30F3MZeiIO6y6IIo4DxrtOwITK87bQl3lhFA= +google.golang.org/genproto v0.0.0-20200702021140-07506425bd67/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -639,6 +641,8 @@ google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k= google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/tree/tree.go b/tree/tree.go index b1337870b..6a9ad5593 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -3,6 +3,7 @@ package tree import ( "github.com/tendermint/iavl" dbm "github.com/tendermint/tm-db" + "log" "sync" ) @@ -33,9 +34,10 @@ func NewMutableTree(height uint64, db dbm.DB, cacheSize int) MTree { panic(err) } - _, err = tree.LoadVersionForOverwriting(int64(height)) - if err != nil { - panic(err) + if _, err1 := tree.LoadVersion(int64(height)); err1 != nil { + if _, err2 := tree.LoadVersionForOverwriting(int64(height)); err2 != nil { + log.Panicln(err1, err2) + } } return &mutableTree{ From 12e823a571e08f17bc7b1e4bbac01c4e846dbf16 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 3 Jul 2020 18:44:47 +0300 Subject: [PATCH 043/426] clean up apiV1 --- api/addresses_full_balances.go | 159 --------------------------------- api/api.go | 14 --- api/calc_comission.go | 103 --------------------- api/candidates_alt.go | 119 ------------------------ api/find_events.go | 24 ----- api/frozzen.go | 69 -------------- api/get_stakes.go | 84 ----------------- api/grouped_events.go | 82 ----------------- api/heigt_by_time.go | 73 --------------- api/missed_blocks.go | 43 --------- api/nosign.go | 62 ------------- api/slashed.go | 18 ---- api/tx_from_block.go | 63 ------------- 13 files changed, 913 deletions(-) delete mode 100644 api/addresses_full_balances.go delete mode 100644 api/calc_comission.go delete mode 100644 api/candidates_alt.go delete mode 100644 api/find_events.go delete mode 100644 api/frozzen.go delete mode 100644 api/get_stakes.go delete mode 100644 api/grouped_events.go delete mode 100644 api/heigt_by_time.go delete mode 100644 api/missed_blocks.go delete mode 100644 api/nosign.go delete mode 100644 api/slashed.go delete mode 100644 api/tx_from_block.go diff --git a/api/addresses_full_balances.go b/api/addresses_full_balances.go deleted file mode 100644 index 24d5b74d0..000000000 --- a/api/addresses_full_balances.go +++ /dev/null @@ -1,159 +0,0 @@ -package api - -import ( - "github.com/MinterTeam/minter-go-node/core/state" - "github.com/MinterTeam/minter-go-node/core/types" - "github.com/MinterTeam/minter-go-node/formula" - "math/big" -) - -type CoinBalance struct { - Coin string `json:"coin"` - Value string `json:"value"` - BipValue string `json:"bip_value"` - DelegateBipValue string `json:"delegate_bip_value,omitempty"` -} - -type AddressBalanceResponse struct { - Freecoins []*CoinBalance `json:"freecoins"` - Delegated []*CoinBalance `json:"delegated"` - Total []*CoinBalance `json:"total"` - TransactionCount uint64 `json:"transaction_count"` - Bipvalue string `json:"bipvalue"` -} - -type AddressesBalancesResponse struct { - Address types.Address `json:"address"` - Balance *AddressBalanceResponse `json:"balance"` -} - -type UserStake struct { - Value *big.Int - BipValue *big.Int -} - -func CustomCoinBipBalance(coinToSell types.CoinSymbol, valueToSell *big.Int, cState *state.CheckState) *big.Int { - coinToBuy := types.StrToCoinSymbol("BIP") - - if coinToSell == coinToBuy { - return valueToSell - } - - if coinToSell == types.GetBaseCoin() { - coin := cState.Coins().GetCoin(coinToBuy) - return formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) - } - - if coinToBuy == types.GetBaseCoin() { - coin := cState.Coins().GetCoin(coinToSell) - return formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) - } - - coinFrom := cState.Coins().GetCoin(coinToSell) - coinTo := cState.Coins().GetCoin(coinToBuy) - basecoinValue := formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) - return formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), basecoinValue) - -} - -func MakeAddressBalance(address types.Address, height int) (*AddressBalanceResponse, error) { - cState, err := GetStateForHeight(height) - if err != nil { - return nil, err - } - - if height != 0 { - cState.Lock() - cState.Candidates().LoadCandidates() - cState.Candidates().LoadStakes() - cState.Unlock() - } - - cState.RLock() - defer cState.RUnlock() - - balances := cState.Accounts().GetBalances(address) - var response AddressBalanceResponse - - totalStakesGroupByCoin := map[types.CoinSymbol]*big.Int{} - - response.Freecoins = make([]*CoinBalance, 0, len(balances)) - for coin, value := range balances { - totalStakesGroupByCoin[coin] = value - response.Freecoins = append(response.Freecoins, &CoinBalance{ - Coin: coin.String(), - Value: value.String(), - BipValue: CustomCoinBipBalance(coin, value, cState).String(), - }) - } - - var userDelegatedStakesGroupByCoin = map[types.CoinSymbol]*UserStake{} - allCandidates := cState.Candidates().GetCandidates() - for _, candidate := range allCandidates { - userStakes := UserStakes(candidate.PubKey, address, cState) - for coin, userStake := range userStakes { - stake, ok := userDelegatedStakesGroupByCoin[coin] - if !ok { - stake = &UserStake{ - Value: big.NewInt(0), - BipValue: big.NewInt(0), - } - } - stake.Value.Add(stake.Value, userStake.Value) - stake.BipValue.Add(stake.BipValue, userStake.BipValue) - userDelegatedStakesGroupByCoin[coin] = stake - } - } - - response.Delegated = make([]*CoinBalance, 0, len(userDelegatedStakesGroupByCoin)) - for coin, delegatedStake := range userDelegatedStakesGroupByCoin { - response.Delegated = append(response.Delegated, &CoinBalance{ - Coin: coin.String(), - Value: delegatedStake.Value.String(), - DelegateBipValue: delegatedStake.BipValue.String(), - BipValue: CustomCoinBipBalance(coin, delegatedStake.Value, cState).String(), - }) - - totalStake, ok := totalStakesGroupByCoin[coin] - if !ok { - totalStake = big.NewInt(0) - totalStakesGroupByCoin[coin] = totalStake - } - totalStake.Add(totalStake, delegatedStake.Value) - } - - coinsBipValue := big.NewInt(0) - response.Total = make([]*CoinBalance, 0, len(totalStakesGroupByCoin)) - for coin, stake := range totalStakesGroupByCoin { - balance := CustomCoinBipBalance(coin, stake, cState) - response.Total = append(response.Total, &CoinBalance{ - Coin: coin.String(), - Value: stake.String(), - BipValue: balance.String(), - }) - coinsBipValue.Add(coinsBipValue, balance) - } - - response.TransactionCount = cState.Accounts().GetNonce(address) - response.Bipvalue = coinsBipValue.String() - - return &response, nil -} - -func UserStakes(c types.Pubkey, address types.Address, state *state.CheckState) map[types.CoinSymbol]*UserStake { - var userStakes = map[types.CoinSymbol]*UserStake{} - - stakes := state.Candidates().GetStakes(c) - - for _, stake := range stakes { - if stake.Owner != address { - continue - } - userStakes[stake.Coin] = &UserStake{ - Value: stake.Value, - BipValue: stake.BipValue, - } - } - - return userStakes -} diff --git a/api/api.go b/api/api.go index bf855385a..0bf796a9a 100644 --- a/api/api.go +++ b/api/api.go @@ -52,20 +52,6 @@ var Routes = map[string]*rpcserver.RPCFunc{ "max_gas": rpcserver.NewRPCFunc(MaxGas, "height"), "min_gas_price": rpcserver.NewRPCFunc(MinGasPrice, ""), "genesis": rpcserver.NewRPCFunc(Genesis, ""), - "missed_blocks": rpcserver.NewRPCFunc(MissedBlocks, "pub_key,height"), - "get_stakes": rpcserver.NewRPCFunc(GetStakes, "pub_key,coin,address,height"), - "total_slashed": rpcserver.NewRPCFunc(TotalSlashed, "height"), - "height_by_time": rpcserver.NewRPCFunc(HeightByTime, "query,height"), - "frozzed": rpcserver.NewRPCFunc(FrozzedFunds, "address,coin"), - "calc_tx_commission": rpcserver.NewRPCFunc(CalcTxCommission, "gas_coin,tx_type,payload,mtxs,height"), - "calc_tx_free_coin": rpcserver.NewRPCFunc(CalcFreeCoinForTx, "gas_coin,gas_coin_amount,tx_type,payload,mtxs,height"), - "address_balance": rpcserver.NewRPCFunc(MakeAddressBalance, "address,height"), - "txs_from_block": rpcserver.NewRPCFunc(TxsFromBlock, "height"), - "candidate_info": rpcserver.NewRPCFunc(CandidateAlt, "pub_key,height"), - "candidates_info": rpcserver.NewRPCFunc(CandidatesAlt, "status,height"), - "nosign": rpcserver.NewRPCFunc(NoSign, "height"), - "find_events": rpcserver.NewRPCFunc(FindEvents, "search,height"), - //"grouped_events": rpcserver.NewRPCFunc(GroupedEvents, "height"), } func responseTime(b *minter.Blockchain) func(f func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) { diff --git a/api/calc_comission.go b/api/calc_comission.go deleted file mode 100644 index 967167846..000000000 --- a/api/calc_comission.go +++ /dev/null @@ -1,103 +0,0 @@ -package api - -import ( - "fmt" - "github.com/MinterTeam/minter-go-node/core/commissions" - "github.com/MinterTeam/minter-go-node/core/transaction" - "github.com/MinterTeam/minter-go-node/core/types" - "github.com/MinterTeam/minter-go-node/formula" - "github.com/MinterTeam/minter-go-node/rpc/lib/types" - "math/big" -) - -type UseMaxResponse struct { - GasCoin string `json:"gascoin"` - StartValue string `json:"startvalue"` - TXComissionValue string `json:"txvalue"` - EndValue string `json:"endvalue"` -} - -func CalcTxCommission(gasCoin string, txType string, payload []byte, mtxs int64, height int) (string, error) { - var commissionInBaseCoin *big.Int - switch txType { - case "SendTx": - commissionInBaseCoin = big.NewInt(commissions.SendTx) - case "ConvertTx": - commissionInBaseCoin = big.NewInt(commissions.ConvertTx) - case "DeclareCandidacyTx": - commissionInBaseCoin = big.NewInt(commissions.DeclareCandidacyTx) - case "DelegateTx": - commissionInBaseCoin = big.NewInt(commissions.DelegateTx) - case "UnbondTx": - commissionInBaseCoin = big.NewInt(commissions.UnbondTx) - case "ToggleCandidateStatus": - commissionInBaseCoin = big.NewInt(commissions.ToggleCandidateStatus) - case "EditCandidate": - commissionInBaseCoin = big.NewInt(commissions.EditCandidate) - case "RedeemCheckTx": - commissionInBaseCoin = big.NewInt(commissions.RedeemCheckTx) - case "CreateMultisig": - commissionInBaseCoin = big.NewInt(commissions.CreateMultisig) - case "MultiSend": - if mtxs <= 0 { - return "", rpctypes.RPCError{Code: 400, Message: "Set number of txs for multisend (mtxs)"} - } - commissionInBaseCoin = big.NewInt(commissions.MultisendDelta*(mtxs-1) + 10) - default: - return "", rpctypes.RPCError{Code: 401, Message: "Set correct txtype for tx"} - } - - if len(payload) > 1024 { - return "", rpctypes.RPCError{Code: 401, Message: fmt.Sprintf("TX payload length is over %d bytes", 1024)} - } - - totalCommissionInBaseCoin := new(big.Int).Mul(big.NewInt(0).Add(commissionInBaseCoin, big.NewInt(int64(len(payload)))), transaction.CommissionMultiplier) - - cState, err := GetStateForHeight(height) - if err != nil { - return "", err - } - - cState.RLock() - defer cState.RUnlock() - - if gasCoin == "BIP" { - return totalCommissionInBaseCoin.String(), nil - } - - coin := cState.Coins().GetCoin(types.StrToCoinSymbol(gasCoin)) - - if coin == nil { - return "", rpctypes.RPCError{Code: 404, Message: "Gas Coin not found"} - } - - if totalCommissionInBaseCoin.Cmp(coin.Reserve()) == 1 { - return "", rpctypes.RPCError{Code: 400, Message: "Not enough coin reserve for pay comission"} - } - - return formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), totalCommissionInBaseCoin).String(), nil - -} - -func CalcFreeCoinForTx(gasCoin string, gasCoinAmount string, txType string, payload []byte, mtxs int64, height int) (*UseMaxResponse, error) { - - commission, err := CalcTxCommission(gasCoin, txType, payload, mtxs, height) - - if err != nil { - return new(UseMaxResponse), err - } - - commissionBig, _ := big.NewInt(0).SetString(commission, 10) - gasCoinAmountBig, _ := big.NewInt(0).SetString(gasCoinAmount, 10) - - if gasCoinAmountBig.Cmp(commissionBig) == -1 { - return new(UseMaxResponse), rpctypes.RPCError{Code: 400, Message: "Not enough coin bipValue for pay commission"} - } - - return &UseMaxResponse{ - GasCoin: gasCoin, - StartValue: gasCoinAmountBig.String(), - TXComissionValue: commission, - EndValue: big.NewInt(0).Sub(gasCoinAmountBig, commissionBig).String(), - }, nil -} diff --git a/api/candidates_alt.go b/api/candidates_alt.go deleted file mode 100644 index 985ced57b..000000000 --- a/api/candidates_alt.go +++ /dev/null @@ -1,119 +0,0 @@ -package api - -import ( - "github.com/MinterTeam/minter-go-node/core/state" - "github.com/MinterTeam/minter-go-node/core/state/candidates" - "github.com/MinterTeam/minter-go-node/core/types" - "github.com/MinterTeam/minter-go-node/rpc/lib/types" - "math/big" -) - -type CandidateResponseAlt struct { - PubKey string `json:"pub_key"` - TotalStake string `json:"total_stake"` - Commission uint `json:"commission"` - UsedSlots int `json:"used_slots"` - UniqUsers int `json:"uniq_users"` - MinStake string `json:"minstake"` - Status byte `json:"status"` -} - -const ( - // CandidateOff = 0x01 - // CandidateOn = 0x02 - ValidatorOn = 0x03 - ValidatorsMaxSlots = 1000 -) - -func ResponseCandidateAlt(c *candidates.Candidate, state *state.CheckState) *CandidateResponseAlt { - stakes := state.Candidates().GetStakes(c.PubKey) - candidate := &CandidateResponseAlt{ - TotalStake: state.Candidates().GetTotalStake(c.PubKey).String(), - PubKey: c.PubKey.String(), - Commission: c.Commission, - Status: c.Status, - UsedSlots: len(stakes), - } - - addresses := map[types.Address]struct{}{} - - for _, validator := range state.Validators().GetValidators() { - if validator.PubKey != c.PubKey { - continue - } - candidate.Status = ValidatorOn - break - } - - minStake := big.NewInt(0) - for i, stake := range stakes { - addresses[stake.Owner] = struct{}{} - if candidate.UsedSlots >= ValidatorsMaxSlots { - if i != 0 && minStake.Cmp(stake.BipValue) != 1 { - continue - } - minStake = stake.BipValue - } - } - - candidate.UniqUsers = len(addresses) - candidate.MinStake = minStake.String() - - return candidate -} - -func CandidateAlt(pubkey types.Pubkey, height int) (*CandidateResponseAlt, error) { - cState, err := GetStateForHeight(height) - if err != nil { - return nil, err - } - - if height != 0 { - cState.Lock() - cState.Candidates().LoadCandidates() - cState.Candidates().LoadStakes() - cState.Validators().LoadValidators() - cState.Unlock() - } - - cState.RLock() - defer cState.RUnlock() - - candidate := cState.Candidates().GetCandidate(pubkey) - if candidate == nil { - return nil, rpctypes.RPCError{Code: 404, Message: "Candidate not found"} - } - - return ResponseCandidateAlt(candidate, cState), nil -} - -func CandidatesAlt(status int, height int) ([]*CandidateResponseAlt, error) { - cState, err := GetStateForHeight(height) - if err != nil { - return nil, err - } - - if height != 0 { - cState.Lock() - cState.Candidates().LoadCandidates() - cState.Validators().LoadValidators() - cState.Candidates().LoadStakes() - cState.Unlock() - } - - cState.RLock() - defer cState.RUnlock() - - var result []*CandidateResponseAlt - - allCandidates := cState.Candidates().GetCandidates() - for _, candidate := range allCandidates { - candidateInfo := ResponseCandidateAlt(candidate, cState) - if status != 0 && candidateInfo.Status != byte(status) { - continue - } - result = append(result, candidateInfo) - } - - return result, nil -} diff --git a/api/find_events.go b/api/find_events.go deleted file mode 100644 index 6242d43e2..000000000 --- a/api/find_events.go +++ /dev/null @@ -1,24 +0,0 @@ -package api - -import ( - eventsdb "github.com/MinterTeam/minter-go-node/core/events" -) - -type FindEventsResponse struct { - Events eventsdb.Events `json:"events"` -} - -func FindEvents(search []string, height uint64) (*FindEventsResponse, error) { - var result FindEventsResponse - events := blockchain.GetEventsDB().LoadEvents(uint32(height)) - - for _, event := range events { - for _, addr := range search { - if event.AddressString() == addr || event.ValidatorPubKeyString() == addr { - result.Events = append(result.Events, event) - } - } - } - - return &result, nil -} diff --git a/api/frozzen.go b/api/frozzen.go deleted file mode 100644 index 6b5860f08..000000000 --- a/api/frozzen.go +++ /dev/null @@ -1,69 +0,0 @@ -package api - -import ( - "github.com/MinterTeam/minter-go-node/core/types" -) - -type FrozInfo struct { - Height int `json:"height"` - Address types.Address `json:"address"` - CandidateKey *types.Pubkey `json:"candidateKey"` - Coin types.CoinSymbol `json:"coin"` - Value string `json:"value"` -} - -func FrozzedFunds(address types.Address, coin string) ([]*FrozInfo, error) { - cState := blockchain.CurrentState() - cState.RLock() - defer cState.RUnlock() - - var frozes []*FrozInfo - - appState := new(types.AppState) - cState.FrozenFunds().Export(appState, blockchain.Height()) - - var emptyAddress types.Address - - if coin == "" && address == emptyAddress { - for _, fund := range appState.FrozenFunds { - frozes = append(frozes, &FrozInfo{ - Height: int(fund.Height), - Address: fund.Address, - CandidateKey: fund.CandidateKey, - Coin: fund.Coin, - Value: fund.Value, - }) - } - return frozes, nil - } - - if coin != "" && address != emptyAddress { - for _, fund := range appState.FrozenFunds { - if fund.Coin.String() != coin || fund.Address != address { - continue - } - frozes = append(frozes, &FrozInfo{ - Height: int(fund.Height), - Address: fund.Address, - CandidateKey: fund.CandidateKey, - Coin: fund.Coin, - Value: fund.Value, - }) - } - return frozes, nil - } - - for _, fund := range appState.FrozenFunds { - if fund.Coin.String() != coin && fund.Address != address { - continue - } - frozes = append(frozes, &FrozInfo{ - Height: int(fund.Height), - Address: fund.Address, - CandidateKey: fund.CandidateKey, - Coin: fund.Coin, - Value: fund.Value, - }) - } - return frozes, nil -} diff --git a/api/get_stakes.go b/api/get_stakes.go deleted file mode 100644 index 656eb5410..000000000 --- a/api/get_stakes.go +++ /dev/null @@ -1,84 +0,0 @@ -package api - -import ( - "github.com/MinterTeam/minter-go-node/core/state" - "github.com/MinterTeam/minter-go-node/core/state/candidates" - "github.com/MinterTeam/minter-go-node/core/types" -) - -type CStake struct { - Address string `json:"address"` - PubKey string `json:"pub_key"` - Coin string `json:"coin"` - Value string `json:"value"` - BipValue string `json:"bip_value"` -} - -func ResponseStakes(state *state.CheckState, c *candidates.Candidate, coin string, address types.Address) []*CStake { - var coinStakes []*CStake - - var multi bool - var allPubkeyStakes bool - - var emptyAddress types.Address - - if coin != "" && address != emptyAddress { - multi = true - } - if coin == "" && address == emptyAddress { - allPubkeyStakes = true - } - - stakes := state.Candidates().GetStakes(c.PubKey) - for _, stake := range stakes { - if !((multi && stake.Coin.String() == coin && stake.Owner == address) || (!multi && (stake.Coin.String() == coin || stake.Owner == address || allPubkeyStakes))) { - continue - } - coinStakes = append(coinStakes, &CStake{ - Address: stake.Owner.String(), - PubKey: c.PubKey.String(), - Coin: stake.Coin.String(), - Value: stake.Value.String(), - BipValue: stake.BipValue.String(), - }) - } - - return coinStakes -} - -func GetStakes(pubkey types.Pubkey, coin string, address types.Address, height int) ([]*CStake, error) { - var coinStakes []*CStake - - cState, err := GetStateForHeight(height) - if err != nil { - return nil, err - } - - if height != 0 { - cState.Lock() - cState.Candidates().LoadCandidates() - cState.Candidates().LoadStakes() - cState.Unlock() - } - - cState.RLock() - defer cState.RUnlock() - - var emptyPyb types.Pubkey - - var allCandidates []*candidates.Candidate - if pubkey == emptyPyb { - allCandidates = cState.Candidates().GetCandidates() - } else { - allCandidates = []*candidates.Candidate{cState.Candidates().GetCandidate(pubkey)} - } - - for _, candidate := range allCandidates { - tmresponse := ResponseStakes(cState, candidate, coin, address) - for _, coinStake := range tmresponse { - coinStakes = append(coinStakes, coinStake) - } - } - - return coinStakes, nil -} diff --git a/api/grouped_events.go b/api/grouped_events.go deleted file mode 100644 index d8e3187d3..000000000 --- a/api/grouped_events.go +++ /dev/null @@ -1,82 +0,0 @@ -package api - -import ( - compact_db "github.com/MinterTeam/minter-go-node/core/events" - "github.com/MinterTeam/minter-go-node/core/types" - "math/big" -) - -type EventsResponseValidator struct { - Pubkey string `json:"pub_key"` - DaoRole string `json:"dao"` - DeveloperRole string `json:"developers"` - ValidatorRole string `json:"validator"` - DelegatorRole string `json:"delegator"` -} - -func GroupedEvents(height int64) ([]*EventsResponseValidator, error) { - - recipients := map[string]struct{}{"Validator": {}, "Delegator": {}, "DAO": {}, "Developers": {}} - - if height == 0 { - height = int64(blockchain.Height()) - } - - tmVals, err := client.Validators(&height, 1, 100) - if err != nil { - return nil, err - } - - mapPubkeyEvents := map[types.Pubkey][]*compact_db.RewardEvent{} - events := blockchain.GetEventsDB().LoadEvents(uint32(height)) - for _, event := range events { - e, ok := event.(*compact_db.RewardEvent) - if !ok { - continue - } - if _, ok := recipients[e.Role]; !ok { - continue - } - mapPubkeyEvents[e.ValidatorPubKey] = append(mapPubkeyEvents[e.ValidatorPubKey], e) - } - - var responseValidators []*EventsResponseValidator - for _, val := range tmVals.Validators { - pubKey := types.BytesToPubkey(val.PubKey.Bytes()[5:]) - events, ok := mapPubkeyEvents[pubKey] - if !ok { - continue - } - - validator := &EventsResponseValidator{ - Pubkey: pubKey.String(), - } - - delegatorRoleValue := big.NewInt(0) - for _, event := range events { - eventDelegatorAmount := big.NewInt(0) - switch event.Role { - case "Validator": - validator.ValidatorRole = event.Role - case "Delegator": - eventDelegatorAmount.SetString(event.Amount, 10) - case "DAO": - validator.DaoRole = event.Role - case "Developers": - validator.DeveloperRole = event.Role - default: - continue - } - delegatorRoleValue.Add(delegatorRoleValue, eventDelegatorAmount) - } - if validator.DaoRole == "" { - continue - } - - validator.DelegatorRole = delegatorRoleValue.String() - - responseValidators = append(responseValidators, validator) - } - - return responseValidators, nil -} diff --git a/api/heigt_by_time.go b/api/heigt_by_time.go deleted file mode 100644 index 2d861eb56..000000000 --- a/api/heigt_by_time.go +++ /dev/null @@ -1,73 +0,0 @@ -package api - -import ( - "github.com/MinterTeam/minter-go-node/rpc/lib/types" - "time" -) - -func DurationTime(height int64, count int64) time.Duration { - if count < 2 { - count = 120 - } - block1, _ := client.Block(&height) - time1 := block1.Block.Time - - height2 := height - count - block2, _ := client.Block(&height2) - duration := time1.Sub(block2.Block.Time) - - return time.Duration(duration.Nanoseconds() / count) -} - -func HeightByTime(query string, height int64) (int64, error) { - - h := int64(blockchain.Height()) - if height > h { - return 0, rpctypes.RPCError{Code: 404, Message: "Inputed block higher actual block"} - } - if height == 0 { - height = h - } - - duration := DurationTime(height, 120) - - block, err := client.Block(&height) - if err != nil { - return 0, err - } - - var sub time.Duration - switch query { - case "day": - sub = time.Hour * 24 - case "week": - sub = time.Hour * 24 * 7 - case "": - return height, nil - default: - target, err := time.Parse(time.RFC3339, query) - if err != nil { - return 0, rpctypes.RPCError{Code: 404, Message: "Incorrect query time", Data: err.Error()} - } - sub = block.Block.Time.Sub(target) - } - - difference := -float64(sub / duration) - targetTime := block.Block.Time.Add(-sub) - - for { - height += int64(difference) - block2, err := client.Block(&height) - if err != nil { - return 0, err - } - result := targetTime.Sub(block2.Block.Time) - difference = float64(result) / float64(DurationTime(height, 2)) - if int(difference) == 0 { - if difference > 0 { - return height, nil - } - return height - 1, nil - } - } -} diff --git a/api/missed_blocks.go b/api/missed_blocks.go deleted file mode 100644 index 3f0e7c324..000000000 --- a/api/missed_blocks.go +++ /dev/null @@ -1,43 +0,0 @@ -package api - -import ( - "github.com/MinterTeam/minter-go-node/core/types" - "github.com/MinterTeam/minter-go-node/rpc/lib/types" -) - -type MissedBlocksResponse struct { - MissedBlocks *types.BitArray `json:"missed_blocks"` - MissedBlocksCount int `json:"missed_blocks_count"` -} - -func MissedBlocks(pubkey types.Pubkey, height int) (*MissedBlocksResponse, error) { - cState, err := GetStateForHeight(height) - if err != nil { - return nil, err - } - - if height != 0 { - cState.Lock() - cState.Validators().LoadValidators() - cState.Unlock() - } - - cState.RLock() - defer cState.RUnlock() - - vals := cState.Validators().GetValidators() - if vals == nil { - return nil, rpctypes.RPCError{Code: 404, Message: "Validators not found"} - } - - for _, val := range vals { - if val.PubKey == pubkey { - return &MissedBlocksResponse{ - MissedBlocks: val.AbsentTimes, - MissedBlocksCount: val.CountAbsentTimes(), - }, nil - } - } - - return nil, rpctypes.RPCError{Code: 404, Message: "Validator not found"} -} diff --git a/api/nosign.go b/api/nosign.go deleted file mode 100644 index a8a5e83ed..000000000 --- a/api/nosign.go +++ /dev/null @@ -1,62 +0,0 @@ -package api - -import ( - "fmt" - "github.com/MinterTeam/minter-go-node/rpc/lib/types" -) - -type MissBlock struct { - Height int64 `json:"height"` - Proposer string `json:"proposer,omitempty"` - Pubkey string `json:"pub_key"` -} - -func NoSign(height int64) ([]*MissBlock, error) { - block, err := client.Block(&height) - if err != nil { - return nil, rpctypes.RPCError{Code: 404, Message: "Block not found", Data: err.Error()} - } - - valHeight := height - 1 - if valHeight < 1 { - valHeight = 1 - } - - var mbs []*MissBlock - - totalValidators, err := client.Validators(&valHeight, 1, 100) - if err != nil { - return nil, rpctypes.RPCError{Code: 500, Message: err.Error()} - } - var proposer string - if height <= 1 { - return mbs, nil - } - p, err := getBlockProposer(block, totalValidators.Validators) - if err != nil { - return nil, err - } - if p != nil { - proposer = p.String() - } - - sign := map[string]struct{}{} - for _, vote := range block.Block.LastCommit.Signatures { - sign[vote.ValidatorAddress.String()] = struct{}{} - } - - for _, tmval := range totalValidators.Validators { - if _, ok := sign[tmval.Address.String()]; ok { - continue - } - mb := &MissBlock{ - Height: height, - Proposer: proposer, - Pubkey: fmt.Sprintf("Mp%x", tmval.PubKey.Bytes()[5:]), - } - mbs = append(mbs, mb) - break - } - - return mbs, nil -} diff --git a/api/slashed.go b/api/slashed.go deleted file mode 100644 index 785aaa07d..000000000 --- a/api/slashed.go +++ /dev/null @@ -1,18 +0,0 @@ -package api - -import ( - "math/big" -) - -func TotalSlashed(height int) (*big.Int, error) { - cState, err := GetStateForHeight(height) - if err != nil { - return nil, err - } - - cState.RLock() - defer cState.RUnlock() - - totalslashed := cState.App().GetTotalSlashed() - return totalslashed, nil -} diff --git a/api/tx_from_block.go b/api/tx_from_block.go deleted file mode 100644 index 2d0ba1723..000000000 --- a/api/tx_from_block.go +++ /dev/null @@ -1,63 +0,0 @@ -package api - -import ( - "encoding/json" - "fmt" - "github.com/MinterTeam/minter-go-node/core/transaction" - "time" -) - -type TransactionsResponse struct { - Height int64 `json:"height"` - Time time.Time `json:"time"` - Hash string `json:"hash"` - Type uint8 `json:"type"` - From string `json:"from"` - Nonce uint64 `json:"nonce"` - Data json.RawMessage `json:"data"` - Payload []byte `json:"payload"` - ServiceData []byte `json:"service_data"` - Gas int64 `json:"gas"` - GasCoin string `json:"gas_coin"` - Code uint32 `json:"code,omitempty"` - Log string `json:"log,omitempty"` -} - -func TxsFromBlock(height int64) ([]*TransactionsResponse, error) { - block, _ := client.Block(&height) - blockResults, _ := client.BlockResults(&height) - - countTx := len(block.Block.Data.Txs) - trs := make([]*TransactionsResponse, 0, countTx) - - if len(blockResults.TxsResults) != countTx { - return trs, nil - } - - for i, rawTx := range block.Block.Data.Txs { - tx, _ := transaction.TxDecoder.DecodeFromBytes(rawTx) - - sender, _ := tx.Sender() - data, _ := encodeTxData(tx) - - tr := &TransactionsResponse{ - Height: block.Block.Height, - Time: block.Block.Time, - Hash: fmt.Sprintf("Mt%x", rawTx.Hash()), - Type: uint8(tx.Type), - From: sender.String(), - Nonce: tx.Nonce, - Data: data, - Payload: tx.Payload, - ServiceData: tx.ServiceData, - Gas: tx.Gas(), - GasCoin: tx.GasCoin.String(), - Code: blockResults.TxsResults[i].Code, - Log: blockResults.TxsResults[i].Log, - } - - trs = append(trs, tr) - } - - return trs, nil -} From 5ac33cdc445ddd5d6f298b358447c5909c93fb91 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 6 Jul 2020 11:13:21 +0300 Subject: [PATCH 044/426] wip --- cli/service/client.go | 6 ------ cli/service/service.go | 23 +++++++++++++-------- config/toml.go | 3 +++ core/minter/minter.go | 10 +++++++-- core/state/state.go | 4 +++- go.mod | 2 +- go.sum | 2 ++ tree/tree.go | 47 +++++++++++++++++++++++++++++++++--------- 8 files changed, 68 insertions(+), 29 deletions(-) diff --git a/cli/service/client.go b/cli/service/client.go index 83dd6e203..a833aa057 100644 --- a/cli/service/client.go +++ b/cli/service/client.go @@ -434,17 +434,11 @@ func pruneBlocksCMD(client pb.ManagerServiceClient) func(c *cli.Context) error { close(errCh) return err } - fmt.Println(progress.GetTitle()) fmt.Println("OK") return nil case recv := <-recvCh: progress.SetMax(int(recv.Total)) progress.SetProgress(int(recv.Current)) - total := int64(0) - if recv.Total != 0 { - total = recv.Current * 100 / recv.Total - } - progress.SetTitle(fmt.Sprintf("Compleated %d%%, %d of %d", total, recv.Current, recv.Total)) app.QueueUpdateDraw(func() {}) } } diff --git a/cli/service/service.go b/cli/service/service.go index 52b416c19..cec466399 100644 --- a/cli/service/service.go +++ b/cli/service/service.go @@ -221,21 +221,26 @@ func (m *Manager) PruneBlocks(req *pb.PruneBlocksRequest, stream pb.ManagerServi min := req.FromHeight - 1 total := req.ToHeight - min - for i := req.FromHeight; i <= req.ToHeight; i++ { - _ = m.blockchain.DeleteStateVersion(i) - if err := stream.Send(&pb.PruneBlocksResponse{ - Total: total, - Current: i - min, - }); err != nil { - return err - } + var deleteVersions []int64 + for i := req.FromHeight; i <= req.ToHeight; i++ { + deleteVersions = append(deleteVersions, i) select { case <-stream.Context().Done(): return status.Error(codes.Canceled, stream.Context().Err().Error()) + case <-time.After(time.Second): + _ = m.blockchain.DeleteStateVersions(deleteVersions) + if err := stream.Send(&pb.PruneBlocksResponse{ + Total: total, + Current: i - min, + }); err != nil { + return err + } + + deleteVersions = []int64{} default: - runtime.Gosched() + } } diff --git a/config/toml.go b/config/toml.go index 78ec5249a..205248b16 100644 --- a/config/toml.go +++ b/config/toml.go @@ -75,6 +75,9 @@ grpc_listen_addr = "{{ .BaseConfig.GRPCListenAddress }}" # Address to listen for API V2 connections api_v2_listen_addr = "{{ .BaseConfig.APIv2ListenAddress }}" +# API v2 Timeout +api_v2_timeout_duration = "{{ .BaseConfig.APIv2TimeoutDuration }}" + # Sets node to be in validator mode. Disables API, events, history of blocks, indexes, etc. validator_mode = {{ .BaseConfig.ValidatorMode }} diff --git a/core/minter/minter.go b/core/minter/minter.go index 52615630a..dbd2b831d 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -177,6 +177,7 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res panic(fmt.Sprintf("Application halted at height %d", height)) } + app.lock.Lock() if upgrades.IsUpgradeBlock(height) { var err error app.stateDeliver, err = state.NewState(app.height, app.stateDB, app.eventsDB, app.cfg.StateCacheSize, app.cfg.KeepLastStates) @@ -185,6 +186,7 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res } app.stateCheck = state.NewCheckState(app.stateDeliver) } + app.lock.Unlock() app.stateDeliver.Lock() @@ -672,6 +674,7 @@ func (app *Blockchain) StatisticData() *statistics.Data { func (app *Blockchain) GetValidatorStatus(address types.TmAddress) int8 { app.lock.RLock() defer app.lock.RUnlock() + return app.validatorsStatuses[address] } @@ -686,8 +689,11 @@ func (app *Blockchain) MaxPeerHeight() int64 { return max } -func (app *Blockchain) DeleteStateVersion(v int64) error { - return app.stateDeliver.Tree().DeleteVersion(v) +func (app *Blockchain) DeleteStateVersions(versions []int64) error { + app.lock.RLock() + defer app.lock.Unlock() + + return app.stateDeliver.Tree().DeleteVersions(versions) } func getDbOpts(memLimit int) *opt.Options { diff --git a/core/state/state.go b/core/state/state.go index 07a98f630..b9cf99c70 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -205,7 +205,9 @@ func (s *State) Commit() ([]byte, error) { } if s.keepLastStates < version-1 { - _ = s.tree.DeleteVersion(version - s.keepLastStates) + if err := s.tree.DeleteVersionIfExists(version - s.keepLastStates); err != nil { + return hash, err + } } return hash, nil diff --git a/go.mod b/go.mod index 672a4cb1c..d79ced4cc 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d github.com/tendermint/go-amino v0.15.1 github.com/tendermint/iavl v0.14.0 - github.com/tendermint/tendermint v0.33.5 + github.com/tendermint/tendermint v0.33.6 github.com/tendermint/tm-db v0.5.1 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 github.com/urfave/cli/v2 v2.0.0 diff --git a/go.sum b/go.sum index 9d9bc4e88..76f04d5f9 100644 --- a/go.sum +++ b/go.sum @@ -467,6 +467,8 @@ github.com/tendermint/iavl v0.14.0 h1:Jkff+IFrXxRWtH9Jn/ga/2cxNnzMTv58xEKgCJsKUB github.com/tendermint/iavl v0.14.0/go.mod h1:QmfViflFiXzxKLQE4tAUuWQHq+RSuQFxablW5oJZ6sE= github.com/tendermint/tendermint v0.33.5 h1:jYgRd9ImkzA9iOyhpmgreYsqSB6tpDa6/rXYPb8HKE8= github.com/tendermint/tendermint v0.33.5/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM= +github.com/tendermint/tendermint v0.33.6 h1:W4UOsXY4ROJZ3TLLGVVv71VXD4WK2gJRb3gzeced+mg= +github.com/tendermint/tendermint v0.33.6/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM= github.com/tendermint/tm-db v0.5.1 h1:H9HDq8UEA7Eeg13kdYckkgwwkQLBnJGgX4PgLJRhieY= github.com/tendermint/tm-db v0.5.1/go.mod h1:g92zWjHpCYlEvQXvy9M168Su8V1IBEeawpXVVBaK4f4= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= diff --git a/tree/tree.go b/tree/tree.go index 6a9ad5593..5227f73ff 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -3,7 +3,6 @@ package tree import ( "github.com/tendermint/iavl" dbm "github.com/tendermint/tm-db" - "log" "sync" ) @@ -14,6 +13,7 @@ type ReadOnlyTree interface { Iterate(fn func(key []byte, value []byte) bool) (stopped bool) KeepLastHeight() int64 AvailableVersions() []int + VersionExists(v int64) bool } type MTree interface { @@ -23,7 +23,8 @@ type MTree interface { LoadVersion(targetVersion int64) (int64, error) LazyLoadVersion(targetVersion int64) (int64, error) SaveVersion() ([]byte, int64, error) - DeleteVersion(version int64) error + DeleteVersions(versions []int64) error + DeleteVersionIfExists(version int64) error GetImmutable() *ImmutableTree GetImmutableAtHeight(version int64) (*ImmutableTree, error) } @@ -34,12 +35,16 @@ func NewMutableTree(height uint64, db dbm.DB, cacheSize int) MTree { panic(err) } - if _, err1 := tree.LoadVersion(int64(height)); err1 != nil { - if _, err2 := tree.LoadVersionForOverwriting(int64(height)); err2 != nil { - log.Panicln(err1, err2) + if height == 0 { + return &mutableTree{ + tree: tree, } } + if _, err := tree.LoadVersionForOverwriting(int64(height)); err != nil { + panic(err) + } + return &mutableTree{ tree: tree, } @@ -51,6 +56,9 @@ type mutableTree struct { } func (t *mutableTree) GetImmutableAtHeight(version int64) (*ImmutableTree, error) { + t.lock.RLock() + defer t.lock.RUnlock() + tree, err := t.tree.GetImmutable(version) if err != nil { return nil, err @@ -62,6 +70,9 @@ func (t *mutableTree) GetImmutableAtHeight(version int64) (*ImmutableTree, error } func (t *mutableTree) Iterate(fn func(key []byte, value []byte) bool) (stopped bool) { + t.lock.RLock() + defer t.lock.RUnlock() + return t.tree.Iterate(fn) } @@ -130,16 +141,26 @@ func (t *mutableTree) SaveVersion() ([]byte, int64, error) { return t.tree.SaveVersion() } -func (t *mutableTree) DeleteVersion(version int64) error { +func (t *mutableTree) DeleteVersions(versions []int64) error { t.lock.Lock() defer t.lock.Unlock() - return t.tree.DeleteVersion(version) + return t.tree.DeleteVersions(versions...) } -func (t *mutableTree) KeepLastHeight() int64 { +func (t *mutableTree) DeleteVersionIfExists(version int64) error { t.lock.Lock() defer t.lock.Unlock() + if !t.tree.VersionExists(version) { + return nil + } + + return t.tree.DeleteVersion(version) +} + +func (t *mutableTree) KeepLastHeight() int64 { + t.lock.RLock() + defer t.lock.RUnlock() versions := t.tree.AvailableVersions() prev := 1 @@ -154,12 +175,18 @@ func (t *mutableTree) KeepLastHeight() int64 { } func (t *mutableTree) AvailableVersions() []int { - t.lock.Lock() - defer t.lock.Unlock() + t.lock.RLock() + defer t.lock.RUnlock() return t.tree.AvailableVersions() } +func (t *mutableTree) VersionExists(v int64) bool { + t.lock.RLock() + defer t.lock.RUnlock() + return t.tree.VersionExists(v) +} + type ImmutableTree struct { tree *iavl.ImmutableTree } From 62ad401c7b6f11c4723632719409dcd52c8dd077 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 6 Jul 2020 12:08:54 +0300 Subject: [PATCH 045/426] fix --- core/minter/minter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index dbd2b831d..da7f1844e 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -690,7 +690,7 @@ func (app *Blockchain) MaxPeerHeight() int64 { } func (app *Blockchain) DeleteStateVersions(versions []int64) error { - app.lock.RLock() + app.lock.Lock() defer app.lock.Unlock() return app.stateDeliver.Tree().DeleteVersions(versions) From b124e54e6f76bf8a9411450523f5afb12dda0726 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 6 Jul 2020 12:09:50 +0300 Subject: [PATCH 046/426] fix --- core/minter/minter.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index da7f1844e..dbfd5a6b5 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -690,8 +690,8 @@ func (app *Blockchain) MaxPeerHeight() int64 { } func (app *Blockchain) DeleteStateVersions(versions []int64) error { - app.lock.Lock() - defer app.lock.Unlock() + app.lock.RLock() + defer app.lock.RUnlock() return app.stateDeliver.Tree().DeleteVersions(versions) } From de56e04b8a4cdd512e847a7c5c629c7407726674 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 6 Jul 2020 17:33:16 +0300 Subject: [PATCH 047/426] fix iavl conflict commit/delete --- core/minter/minter.go | 3 +++ core/state/state.go | 3 +++ tree/tree.go | 14 ++++++++++++++ 3 files changed, 20 insertions(+) diff --git a/core/minter/minter.go b/core/minter/minter.go index dbfd5a6b5..4ab780e32 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -693,6 +693,9 @@ func (app *Blockchain) DeleteStateVersions(versions []int64) error { app.lock.RLock() defer app.lock.RUnlock() + app.stateDeliver.Tree().GlobalLock() + defer app.stateDeliver.Tree().GlobalUnlock() + return app.stateDeliver.Tree().DeleteVersions(versions) } diff --git a/core/state/state.go b/core/state/state.go index b9cf99c70..f01df6509 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -167,6 +167,9 @@ func (s *State) Check() error { func (s *State) Commit() ([]byte, error) { s.Checker.Reset() + s.tree.GlobalLock() + defer s.tree.GlobalUnlock() + if err := s.Accounts.Commit(); err != nil { return nil, err } diff --git a/tree/tree.go b/tree/tree.go index 5227f73ff..ec0906e5c 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -27,6 +27,8 @@ type MTree interface { DeleteVersionIfExists(version int64) error GetImmutable() *ImmutableTree GetImmutableAtHeight(version int64) (*ImmutableTree, error) + GlobalLock() + GlobalUnlock() } func NewMutableTree(height uint64, db dbm.DB, cacheSize int) MTree { @@ -53,6 +55,7 @@ func NewMutableTree(height uint64, db dbm.DB, cacheSize int) MTree { type mutableTree struct { tree *iavl.MutableTree lock sync.RWMutex + sync.Mutex } func (t *mutableTree) GetImmutableAtHeight(version int64) (*ImmutableTree, error) { @@ -69,6 +72,14 @@ func (t *mutableTree) GetImmutableAtHeight(version int64) (*ImmutableTree, error }, nil } +func (t *mutableTree) GlobalLock() { + t.Lock() +} + +func (t *mutableTree) GlobalUnlock() { + t.Unlock() +} + func (t *mutableTree) Iterate(fn func(key []byte, value []byte) bool) (stopped bool) { t.lock.RLock() defer t.lock.RUnlock() @@ -134,6 +145,7 @@ func (t *mutableTree) LazyLoadVersion(targetVersion int64) (int64, error) { return t.tree.LazyLoadVersion(targetVersion) } +// Should use GlobalLock() and GlobalUnlock func (t *mutableTree) SaveVersion() ([]byte, int64, error) { t.lock.Lock() defer t.lock.Unlock() @@ -141,6 +153,7 @@ func (t *mutableTree) SaveVersion() ([]byte, int64, error) { return t.tree.SaveVersion() } +//Should use GlobalLock() and GlobalUnlock func (t *mutableTree) DeleteVersions(versions []int64) error { t.lock.Lock() defer t.lock.Unlock() @@ -148,6 +161,7 @@ func (t *mutableTree) DeleteVersions(versions []int64) error { return t.tree.DeleteVersions(versions...) } +//Should use GlobalLock() and GlobalUnlock func (t *mutableTree) DeleteVersionIfExists(version int64) error { t.lock.Lock() defer t.lock.Unlock() From c4db8e071da8e0a3ee5290ebd859ca16cb8f3382 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 7 Jul 2020 18:10:40 +0300 Subject: [PATCH 048/426] fixes --- cli/service/client.go | 1 - cli/service/service.go | 30 ++++++++++++++++++++++-------- core/minter/minter.go | 4 ++-- core/state/state.go | 8 +++++--- tree/tree.go | 20 ++++++++++---------- 5 files changed, 39 insertions(+), 24 deletions(-) diff --git a/cli/service/client.go b/cli/service/client.go index a833aa057..4c9796cc7 100644 --- a/cli/service/client.go +++ b/cli/service/client.go @@ -414,7 +414,6 @@ func pruneBlocksCMD(client pb.ManagerServiceClient) func(c *cli.Context) error { return } recvCh <- recv - time.Sleep(1 * time.Second) } } }() diff --git a/cli/service/service.go b/cli/service/service.go index cec466399..ddcc0aa05 100644 --- a/cli/service/service.go +++ b/cli/service/service.go @@ -213,6 +213,8 @@ func (m *Manager) NetInfo(context.Context, *empty.Empty) (*pb.NetInfoResponse, e return response, nil } +const countBatchBlocksDelete = 250 + func (m *Manager) PruneBlocks(req *pb.PruneBlocksRequest, stream pb.ManagerService_PruneBlocksServer) error { current := m.blockchain.Height() if req.ToHeight >= int64(current) { @@ -222,25 +224,37 @@ func (m *Manager) PruneBlocks(req *pb.PruneBlocksRequest, stream pb.ManagerServi min := req.FromHeight - 1 total := req.ToHeight - min - var deleteVersions []int64 - for i := req.FromHeight; i <= req.ToHeight; i++ { - deleteVersions = append(deleteVersions, i) + from := req.FromHeight + last := make(chan struct{}) + for i := req.FromHeight; i <= req.ToHeight; i++ { + if i == req.ToHeight { + close(last) + } select { case <-stream.Context().Done(): return status.Error(codes.Canceled, stream.Context().Err().Error()) - case <-time.After(time.Second): - _ = m.blockchain.DeleteStateVersions(deleteVersions) + case <-last: + _ = m.blockchain.DeleteStateVersions(from, i) if err := stream.Send(&pb.PruneBlocksResponse{ Total: total, Current: i - min, }); err != nil { return err } - - deleteVersions = []int64{} + return nil default: - + if i-from != countBatchBlocksDelete { + continue + } + _ = m.blockchain.DeleteStateVersions(from, i) + if err := stream.Send(&pb.PruneBlocksResponse{ + Total: total, + Current: i - min, + }); err != nil { + return err + } + from = i } } diff --git a/core/minter/minter.go b/core/minter/minter.go index 4ab780e32..735a61fab 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -689,14 +689,14 @@ func (app *Blockchain) MaxPeerHeight() int64 { return max } -func (app *Blockchain) DeleteStateVersions(versions []int64) error { +func (app *Blockchain) DeleteStateVersions(from, to int64) error { app.lock.RLock() defer app.lock.RUnlock() app.stateDeliver.Tree().GlobalLock() defer app.stateDeliver.Tree().GlobalUnlock() - return app.stateDeliver.Tree().DeleteVersions(versions) + return app.stateDeliver.Tree().DeleteVersionsIfExists(from, to) } func getDbOpts(memLimit int) *opt.Options { diff --git a/core/state/state.go b/core/state/state.go index f01df6509..97775f7db 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -119,7 +119,7 @@ func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, } func NewCheckStateAtHeight(height uint64, db db.DB) (*CheckState, error) { - iavlTree := tree.NewMutableTree(height, db, 1024) + iavlTree := tree.NewMutableTree(0, db, 1024) _, err := iavlTree.LazyLoadVersion(int64(height)) if err != nil { return nil, err @@ -164,6 +164,8 @@ func (s *State) Check() error { return nil } +const countBatchBlocksDelete = 100 + func (s *State) Commit() ([]byte, error) { s.Checker.Reset() @@ -207,8 +209,8 @@ func (s *State) Commit() ([]byte, error) { return hash, err } - if s.keepLastStates < version-1 { - if err := s.tree.DeleteVersionIfExists(version - s.keepLastStates); err != nil { + if version%countBatchBlocksDelete == 0 && version-countBatchBlocksDelete > s.keepLastStates { + if err := s.tree.DeleteVersionsIfExists(version-countBatchBlocksDelete-s.keepLastStates, version-s.keepLastStates); err != nil { return hash, err } } diff --git a/tree/tree.go b/tree/tree.go index ec0906e5c..374b3a29d 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -13,7 +13,6 @@ type ReadOnlyTree interface { Iterate(fn func(key []byte, value []byte) bool) (stopped bool) KeepLastHeight() int64 AvailableVersions() []int - VersionExists(v int64) bool } type MTree interface { @@ -23,7 +22,7 @@ type MTree interface { LoadVersion(targetVersion int64) (int64, error) LazyLoadVersion(targetVersion int64) (int64, error) SaveVersion() ([]byte, int64, error) - DeleteVersions(versions []int64) error + DeleteVersionsIfExists(from, to int64) error DeleteVersionIfExists(version int64) error GetImmutable() *ImmutableTree GetImmutableAtHeight(version int64) (*ImmutableTree, error) @@ -31,6 +30,7 @@ type MTree interface { GlobalUnlock() } +//Should use height = 0 and LazyLoadVersion(version) func NewMutableTree(height uint64, db dbm.DB, cacheSize int) MTree { tree, err := iavl.NewMutableTree(db, cacheSize) if err != nil { @@ -154,11 +154,17 @@ func (t *mutableTree) SaveVersion() ([]byte, int64, error) { } //Should use GlobalLock() and GlobalUnlock -func (t *mutableTree) DeleteVersions(versions []int64) error { +func (t *mutableTree) DeleteVersionsIfExists(from, to int64) error { t.lock.Lock() defer t.lock.Unlock() - return t.tree.DeleteVersions(versions...) + var existsVersions = make([]int64, 0, to-from) + for i := from; i < to; i++ { + if t.tree.VersionExists(i) { + existsVersions = append(existsVersions, i) + } + } + return t.tree.DeleteVersions(existsVersions...) } //Should use GlobalLock() and GlobalUnlock @@ -195,12 +201,6 @@ func (t *mutableTree) AvailableVersions() []int { return t.tree.AvailableVersions() } -func (t *mutableTree) VersionExists(v int64) bool { - t.lock.RLock() - defer t.lock.RUnlock() - return t.tree.VersionExists(v) -} - type ImmutableTree struct { tree *iavl.ImmutableTree } From cdc7c30a827b9910e516b3304edca438ec5c1223 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 7 Jul 2020 18:27:29 +0300 Subject: [PATCH 049/426] add notes for iavl tree --- core/state/state.go | 6 +----- tree/tree.go | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/core/state/state.go b/core/state/state.go index 97775f7db..f6c70343c 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -119,11 +119,7 @@ func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, } func NewCheckStateAtHeight(height uint64, db db.DB) (*CheckState, error) { - iavlTree := tree.NewMutableTree(0, db, 1024) - _, err := iavlTree.LazyLoadVersion(int64(height)) - if err != nil { - return nil, err - } + iavlTree := tree.NewImmutableTree(height, db) return newCheckStateForTree(iavlTree, nil, nil, 0) } diff --git a/tree/tree.go b/tree/tree.go index 374b3a29d..9fd68f5b5 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -11,12 +11,12 @@ type ReadOnlyTree interface { Version() int64 Hash() []byte Iterate(fn func(key []byte, value []byte) bool) (stopped bool) - KeepLastHeight() int64 - AvailableVersions() []int } type MTree interface { ReadOnlyTree + KeepLastHeight() int64 + AvailableVersions() []int Set(key, value []byte) bool Remove(key []byte) ([]byte, bool) LoadVersion(targetVersion int64) (int64, error) @@ -30,7 +30,7 @@ type MTree interface { GlobalUnlock() } -//Should use height = 0 and LazyLoadVersion(version) +// If you want to get read-only state, you should use height = 0 and LazyLoadVersion (version), see NewImmutableTree func NewMutableTree(height uint64, db dbm.DB, cacheSize int) MTree { tree, err := iavl.NewMutableTree(db, cacheSize) if err != nil { @@ -205,6 +205,16 @@ type ImmutableTree struct { tree *iavl.ImmutableTree } +//Warning: returns the MTree interface, but you should only use ReadOnlyTree +func NewImmutableTree(height uint64, db dbm.DB) MTree { + tree := NewMutableTree(0, db, 1024) + _, err := tree.LazyLoadVersion(int64(height)) + if err != nil { + panic(err) + } + return tree +} + func (t *ImmutableTree) Iterate(fn func(key []byte, value []byte) bool) (stopped bool) { return t.tree.Iterate(fn) } From a253936c24370f117c6e3758ee1e2e1383aa1691 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 8 Jul 2020 11:38:25 +0300 Subject: [PATCH 050/426] add notes for iavl tree --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d79ced4cc..4019d0412 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200703152116-e7149c5e7eb3 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200708082254-89679228c4b1 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 76f04d5f9..158564f05 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200703152116-e7149c5e7eb3 h1:O1uMi5FUdiOXYmCaAwkH6WNxbWTf6EExI19FYGN2728= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200703152116-e7149c5e7eb3/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200708082254-89679228c4b1 h1:KzB/n+6r9Ue8IPBNnkpa2lvtF/F0xbb7zJDB4fBRzrE= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200708082254-89679228c4b1/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 05fe8e2b6b81e19b8cdfbd81718e7943a8213e3b Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 8 Jul 2020 11:53:18 +0300 Subject: [PATCH 051/426] Limit the maximum quantity of validators to 64 --- core/minter/minter.go | 2 -- core/validators/validators.go | 15 +-------------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index 735a61fab..797d6c70d 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -118,7 +118,6 @@ func NewMinterBlockchain(cfg *config.Config) *Blockchain { // Set start height for rewards and validators rewards.SetStartHeight(applicationDB.GetStartHeight()) - validators.SetStartHeight(applicationDB.GetStartHeight()) blockchain.haltHeight = uint64(cfg.HaltHeight) @@ -160,7 +159,6 @@ func (app *Blockchain) InitChain(req abciTypes.RequestInitChain) abciTypes.Respo app.appDB.SetStartHeight(genesisState.StartHeight) app.appDB.SaveValidators(vals) rewards.SetStartHeight(genesisState.StartHeight) - validators.SetStartHeight(genesisState.StartHeight) return abciTypes.ResponseInitChain{ Validators: vals, diff --git a/core/validators/validators.go b/core/validators/validators.go index 0df7c426b..13dcd8a43 100644 --- a/core/validators/validators.go +++ b/core/validators/validators.go @@ -1,22 +1,9 @@ package validators -var startHeight uint64 = 0 - func GetValidatorsCountForBlock(block uint64) int { - block += startHeight - count := 16 + (block/518400)*4 - - if count > 256 { - return 256 - } - - return int(count) + return 64 } func GetCandidatesCountForBlock(block uint64) int { return GetValidatorsCountForBlock(block) * 3 } - -func SetStartHeight(sHeight uint64) { - startHeight = sHeight -} From b369f3d211f663c2a69af187a226636674b4da51 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 8 Jul 2020 14:43:49 +0300 Subject: [PATCH 052/426] Control Address for Candidates --- core/state/bus/candidates.go | 11 +++--- core/state/candidates/bus.go | 22 ++++++------ core/state/candidates/candidates.go | 26 ++++++++++----- core/state/candidates/model.go | 16 ++++++--- core/transaction/edit_candidate.go | 35 +++++++++++-------- core/transaction/switch_candidate_status.go | 37 +++++++++++++++------ core/types/appstate.go | 17 +++++----- 7 files changed, 103 insertions(+), 61 deletions(-) diff --git a/core/state/bus/candidates.go b/core/state/bus/candidates.go index c1c90c1f1..7bcc38ee6 100644 --- a/core/state/bus/candidates.go +++ b/core/state/bus/candidates.go @@ -21,9 +21,10 @@ type Stake struct { } type Candidate struct { - PubKey types.Pubkey - RewardAddress types.Address - OwnerAddress types.Address - Commission uint - Status byte + PubKey types.Pubkey + RewardAddress types.Address + OwnerAddress types.Address + ControlAddress types.Address + Commission uint + Status byte } diff --git a/core/state/candidates/bus.go b/core/state/candidates/bus.go index f128d08e6..39396e503 100644 --- a/core/state/candidates/bus.go +++ b/core/state/candidates/bus.go @@ -41,11 +41,12 @@ func (b *Bus) GetCandidate(pubkey types.Pubkey) *bus.Candidate { } return &bus.Candidate{ - PubKey: candidate.PubKey, - RewardAddress: candidate.RewardAddress, - OwnerAddress: candidate.OwnerAddress, - Commission: candidate.Commission, - Status: candidate.Status, + PubKey: candidate.PubKey, + RewardAddress: candidate.RewardAddress, + OwnerAddress: candidate.OwnerAddress, + ControlAddress: candidate.ControlAddress, + Commission: candidate.Commission, + Status: candidate.Status, } } @@ -60,10 +61,11 @@ func (b *Bus) GetCandidateByTendermintAddress(tmAddress types.TmAddress) *bus.Ca } return &bus.Candidate{ - PubKey: candidate.PubKey, - RewardAddress: candidate.RewardAddress, - OwnerAddress: candidate.OwnerAddress, - Commission: candidate.Commission, - Status: candidate.Status, + PubKey: candidate.PubKey, + RewardAddress: candidate.RewardAddress, + OwnerAddress: candidate.OwnerAddress, + ControlAddress: candidate.ControlAddress, + Commission: candidate.Commission, + Status: candidate.Status, } } diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index f9238716f..c58d62344 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -37,6 +37,7 @@ type RCandidates interface { IsDelegatorStakeSufficient(address types.Address, pubkey types.Pubkey, coin types.CoinSymbol, amount *big.Int) bool GetStakeValueOfAddress(pubkey types.Pubkey, address types.Address, coin types.CoinSymbol) *big.Int GetCandidateOwner(pubkey types.Pubkey) types.Address + GetCandidateControl(pubkey types.Pubkey) types.Address GetTotalStake(pubkey types.Pubkey) *big.Int LoadCandidates() LoadStakesOfCandidate(pubkey types.Pubkey) @@ -175,6 +176,7 @@ func (c *Candidates) Create(ownerAddress types.Address, rewardAddress types.Addr PubKey: pubkey, RewardAddress: rewardAddress, OwnerAddress: ownerAddress, + ControlAddress: ownerAddress, Commission: commission, Status: CandidateStatusOffline, totalBipStake: big.NewInt(0), @@ -607,10 +609,11 @@ func (c *Candidates) Delegate(address types.Address, pubkey types.Pubkey, coin t c.bus.Checker().AddCoin(coin, value) } -func (c *Candidates) Edit(pubkey types.Pubkey, rewardAddress types.Address, ownerAddress types.Address) { +func (c *Candidates) Edit(pubkey types.Pubkey, rewardAddress types.Address, ownerAddress types.Address, controlAddress types.Address) { candidate := c.getFromMap(pubkey) candidate.setOwner(ownerAddress) candidate.setReward(rewardAddress) + candidate.setControl(controlAddress) } func (c *Candidates) SetOnline(pubkey types.Pubkey) { @@ -701,6 +704,10 @@ func (c *Candidates) GetCandidateOwner(pubkey types.Pubkey) types.Address { return c.getFromMap(pubkey).OwnerAddress } +func (c *Candidates) GetCandidateControl(pubkey types.Pubkey) types.Address { + return c.getFromMap(pubkey).ControlAddress +} + func (c *Candidates) LoadCandidates() { if c.loaded { return @@ -896,14 +903,15 @@ func (c *Candidates) Export(state *types.AppState) { } state.Candidates = append(state.Candidates, types.Candidate{ - RewardAddress: candidate.RewardAddress, - OwnerAddress: candidate.OwnerAddress, - TotalBipStake: candidate.GetTotalBipStake().String(), - PubKey: candidate.PubKey, - Commission: candidate.Commission, - Status: candidate.Status, - Updates: updates, - Stakes: stakes, + RewardAddress: candidate.RewardAddress, + OwnerAddress: candidate.OwnerAddress, + ControlAddress: candidate.ControlAddress, + TotalBipStake: candidate.GetTotalBipStake().String(), + PubKey: candidate.PubKey, + Commission: candidate.Commission, + Status: candidate.Status, + Updates: updates, + Stakes: stakes, }) } diff --git a/core/state/candidates/model.go b/core/state/candidates/model.go index 6b6830b09..df6397ea8 100644 --- a/core/state/candidates/model.go +++ b/core/state/candidates/model.go @@ -8,11 +8,12 @@ import ( ) type Candidate struct { - PubKey types.Pubkey - RewardAddress types.Address - OwnerAddress types.Address - Commission uint - Status byte + PubKey types.Pubkey + RewardAddress types.Address + OwnerAddress types.Address + ControlAddress types.Address + Commission uint + Status byte totalBipStake *big.Int stakesCount int @@ -41,6 +42,11 @@ func (candidate *Candidate) setReward(address types.Address) { candidate.RewardAddress = address } +func (candidate *Candidate) setControl(address types.Address) { + candidate.isDirty = true + candidate.ControlAddress = address +} + func (candidate *Candidate) addUpdate(stake *Stake) { candidate.isUpdatesDirty = true stake.markDirty = func(i int) { diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index 80ebd78a6..af1021954 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -18,20 +18,31 @@ type CandidateTx interface { } type EditCandidateData struct { - PubKey types.Pubkey - RewardAddress types.Address - OwnerAddress types.Address + PubKey types.Pubkey + NewPubKey *types.Pubkey + RewardAddress types.Address + OwnerAddress types.Address + ControlAddress types.Address } func (data EditCandidateData) MarshalJSON() ([]byte, error) { + newPubKey := data.NewPubKey + newPubKeyStr := "" + if newPubKey != nil { + newPubKeyStr = newPubKey.String() + } return json.Marshal(struct { - PubKey string `json:"pub_key"` - RewardAddress string `json:"reward_address"` - OwnerAddress string `json:"owner_address"` + PubKey string `json:"pub_key"` + NewPubKey string `json:"new_pub_key"` + RewardAddress string `json:"reward_address"` + OwnerAddress string `json:"owner_address"` + ControlAddress string `json:"owner_address"` }{ - PubKey: data.PubKey.String(), - RewardAddress: data.RewardAddress.String(), - OwnerAddress: data.OwnerAddress.String(), + PubKey: data.PubKey.String(), + NewPubKey: newPubKeyStr, + RewardAddress: data.RewardAddress.String(), + OwnerAddress: data.OwnerAddress.String(), + ControlAddress: data.ControlAddress.String(), }) } @@ -39,10 +50,6 @@ func (data EditCandidateData) GetPubKey() types.Pubkey { return data.PubKey } -func (data EditCandidateData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { - panic("implement me") -} - func (data EditCandidateData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { return checkCandidateOwnership(data, tx, context) } @@ -115,7 +122,7 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa deliveryState.Coins.SubVolume(tx.GasCoin, commission) deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) - deliveryState.Candidates.Edit(data.PubKey, data.RewardAddress, data.OwnerAddress) + deliveryState.Candidates.Edit(data.PubKey, data.RewardAddress, data.OwnerAddress, data.ControlAddress) deliveryState.Accounts.SetNonce(sender, tx.Nonce) } diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index 8bc2f2ba2..78f079b13 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -29,12 +29,8 @@ func (data SetCandidateOnData) GetPubKey() types.Pubkey { return data.PubKey } -func (data SetCandidateOnData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { - panic("implement me") -} - func (data SetCandidateOnData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { - return checkCandidateOwnership(data, tx, context) + return checkCandidateControl(data, tx, context) } func (data SetCandidateOnData) String() string { @@ -138,12 +134,8 @@ func (data SetCandidateOffData) GetPubKey() types.Pubkey { return data.PubKey } -func (data SetCandidateOffData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { - panic("implement me") -} - func (data SetCandidateOffData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { - return checkCandidateOwnership(data, tx, context) + return checkCandidateControl(data, tx, context) } func (data SetCandidateOffData) String() string { @@ -226,3 +218,28 @@ func (data SetCandidateOffData) Run(tx *Transaction, context state.Interface, re Tags: tags, } } + +func checkCandidateControl(data CandidateTx, tx *Transaction, context *state.CheckState) *Response { + if !context.Candidates().Exists(data.GetPubKey()) { + return &Response{ + Code: code.CandidateNotFound, + Log: fmt.Sprintf("Candidate with such public key (%s) not found", data.GetPubKey().String()), + Info: EncodeError(map[string]string{ + "public_key": data.GetPubKey().String(), + }), + } + } + + owner := context.Candidates().GetCandidateOwner(data.GetPubKey()) + control := context.Candidates().GetCandidateControl(data.GetPubKey()) + sender, _ := tx.Sender() + switch sender { + case owner, control: + default: + return &Response{ + Code: code.IsNotOwnerOfCandidate, + Log: fmt.Sprintf("Sender is not an owner of a candidate")} + } + + return nil +} diff --git a/core/types/appstate.go b/core/types/appstate.go index 69f86c1b0..1b201fb60 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -209,14 +209,15 @@ type Validator struct { } type Candidate struct { - RewardAddress Address `json:"reward_address"` - OwnerAddress Address `json:"owner_address"` - TotalBipStake string `json:"total_bip_stake"` - PubKey Pubkey `json:"pub_key"` - Commission uint `json:"commission"` - Stakes []Stake `json:"stakes"` - Updates []Stake `json:"updates"` - Status byte `json:"status"` + RewardAddress Address `json:"reward_address"` + OwnerAddress Address `json:"owner_address"` + ControlAddress Address `json:"control_address"` + TotalBipStake string `json:"total_bip_stake"` + PubKey Pubkey `json:"pub_key"` + Commission uint `json:"commission"` + Stakes []Stake `json:"stakes"` + Updates []Stake `json:"updates"` + Status byte `json:"status"` } type Stake struct { From d29340fec78b30a476c532b06e3c7383491d2293 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Fri, 10 Jul 2020 13:36:48 +0300 Subject: [PATCH 053/426] MN-435: replace symbol by id at coins related structures --- api/coin_info.go | 3 +- api/estimate_coin_buy.go | 12 +- api/estimate_coin_sell.go | 12 +- api/estimate_coin_sell_all.go | 11 +- api/v2/service/address.go | 16 +- api/v2/service/addresses.go | 4 +- api/v2/service/coin_info.go | 2 +- cmd/minter/cmd/export.go | 8 +- cmd/minter/cmd/node.go | 31 +- core/check/check.go | 4 +- core/events/types.go | 12 +- core/minter/minter.go | 6 +- core/minter/upgrade3.go | 446 ------------------------- core/minter/upgrade3_test.go | 54 --- core/state/accounts/accounts.go | 50 +-- core/state/accounts/bus.go | 4 +- core/state/accounts/model.go | 20 +- core/state/app/app.go | 12 +- core/state/app/model.go | 13 + core/state/bus/accounts.go | 4 +- core/state/bus/candidates.go | 2 +- core/state/bus/checker.go | 4 +- core/state/bus/coins.go | 7 +- core/state/bus/frozenfunds.go | 2 +- core/state/candidates/candidates.go | 42 +-- core/state/candidates/model.go | 28 +- core/state/checker/checker.go | 20 +- core/state/coins/bus.go | 12 +- core/state/coins/coins.go | 228 +++++++++---- core/state/coins/model.go | 24 +- core/state/frozenfunds/bus.go | 2 +- core/state/frozenfunds/frozen_funds.go | 2 +- core/state/frozenfunds/model.go | 4 +- core/state/legacy/states.go | 3 + core/state/state.go | 12 +- core/state/validators/model.go | 2 +- core/state/validators/validators.go | 8 +- core/transaction/buy_coin.go | 16 +- core/transaction/create_coin.go | 28 +- core/transaction/declare_candidacy.go | 2 +- core/transaction/delegate.go | 2 +- core/transaction/multisend.go | 10 +- core/transaction/sell_all_coin.go | 4 +- core/transaction/sell_coin.go | 14 +- core/transaction/send.go | 4 +- core/transaction/transaction.go | 10 +- core/transaction/unbond.go | 2 +- core/types/appstate.go | 32 +- core/types/constants.go | 4 + core/types/types.go | 33 ++ 50 files changed, 475 insertions(+), 812 deletions(-) delete mode 100644 core/minter/upgrade3.go delete mode 100644 core/minter/upgrade3_test.go create mode 100644 core/state/legacy/states.go diff --git a/api/coin_info.go b/api/coin_info.go index 3a2dff2b4..fb24e3228 100644 --- a/api/coin_info.go +++ b/api/coin_info.go @@ -6,6 +6,7 @@ import ( ) type CoinInfoResponse struct { + ID uint64 `json:"id"` Name string `json:"name"` Symbol string `json:"symbol"` Volume string `json:"volume"` @@ -23,7 +24,7 @@ func CoinInfo(coinSymbol string, height int) (*CoinInfoResponse, error) { cState.RLock() defer cState.RUnlock() - coin := cState.Coins().GetCoin(types.StrToCoinSymbol(coinSymbol)) + coin := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinSymbol)) if coin == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin not found"} } diff --git a/api/estimate_coin_buy.go b/api/estimate_coin_buy.go index 3228f4030..0b19e9888 100644 --- a/api/estimate_coin_buy.go +++ b/api/estimate_coin_buy.go @@ -15,7 +15,7 @@ type EstimateCoinBuyResponse struct { Commission string `json:"commission"` } -func EstimateCoinBuy(coinToSellString string, coinToBuyString string, valueToBuy *big.Int, height int) (*EstimateCoinBuyResponse, error) { +func EstimateCoinBuy(coinIdToSell uint64, coinIdToBuy uint64, valueToBuy *big.Int, height int) (*EstimateCoinBuyResponse, error) { cState, err := GetStateForHeight(height) if err != nil { return nil, err @@ -24,8 +24,8 @@ func EstimateCoinBuy(coinToSellString string, coinToBuyString string, valueToBuy cState.RLock() defer cState.RUnlock() - coinToSell := types.StrToCoinSymbol(coinToSellString) - coinToBuy := types.StrToCoinSymbol(coinToBuyString) + coinToSell := types.CoinID(coinIdToSell) + coinToBuy := types.CoinID(coinIdToBuy) var result *big.Int @@ -45,7 +45,7 @@ func EstimateCoinBuy(coinToSellString string, coinToBuyString string, valueToBuy commissionInBaseCoin.Mul(commissionInBaseCoin, transaction.CommissionMultiplier) commission := big.NewInt(0).Set(commissionInBaseCoin) - if coinToSell != types.GetBaseCoin() { + if coinToSell != types.GetBaseCoinID() { coin := cState.Coins().GetCoin(coinToSell) if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { @@ -57,10 +57,10 @@ func EstimateCoinBuy(coinToSellString string, coinToBuyString string, valueToBuy } switch { - case coinToSell == types.GetBaseCoin(): + case coinToSell == types.GetBaseCoinID(): coin := cState.Coins().GetCoin(coinToBuy) result = formula.CalculatePurchaseAmount(coin.Volume(), coin.Reserve(), coin.Crr(), valueToBuy) - case coinToBuy == types.GetBaseCoin(): + case coinToBuy == types.GetBaseCoinID(): coin := cState.Coins().GetCoin(coinToSell) if coin.Reserve().Cmp(valueToBuy) < 0 { diff --git a/api/estimate_coin_sell.go b/api/estimate_coin_sell.go index 37e2cef13..d622c24a8 100644 --- a/api/estimate_coin_sell.go +++ b/api/estimate_coin_sell.go @@ -15,7 +15,7 @@ type EstimateCoinSellResponse struct { Commission string `json:"commission"` } -func EstimateCoinSell(coinToSellString string, coinToBuyString string, valueToSell *big.Int, height int) (*EstimateCoinSellResponse, error) { +func EstimateCoinSell(coinIdToSell uint64, coinIdToBuy uint64, valueToSell *big.Int, height int) (*EstimateCoinSellResponse, error) { cState, err := GetStateForHeight(height) if err != nil { return nil, err @@ -24,8 +24,8 @@ func EstimateCoinSell(coinToSellString string, coinToBuyString string, valueToSe cState.RLock() defer cState.RUnlock() - coinToSell := types.StrToCoinSymbol(coinToSellString) - coinToBuy := types.StrToCoinSymbol(coinToBuyString) + coinToSell := types.CoinID(coinIdToSell) + coinToBuy := types.CoinID(coinIdToBuy) var result *big.Int @@ -45,7 +45,7 @@ func EstimateCoinSell(coinToSellString string, coinToBuyString string, valueToSe commissionInBaseCoin.Mul(commissionInBaseCoin, transaction.CommissionMultiplier) commission := big.NewInt(0).Set(commissionInBaseCoin) - if coinToSell != types.GetBaseCoin() { + if coinToSell != types.GetBaseCoinID() { coin := cState.Coins().GetCoin(coinToSell) if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { @@ -62,10 +62,10 @@ func EstimateCoinSell(coinToSellString string, coinToBuyString string, valueToSe } switch { - case coinToSell == types.GetBaseCoin(): + case coinToSell == types.GetBaseCoinID(): coin := cState.Coins().GetCoin(coinToBuy) result = formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) - case coinToBuy == types.GetBaseCoin(): + case coinToBuy == types.GetBaseCoinID(): coin := cState.Coins().GetCoin(coinToSell) result = formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) default: diff --git a/api/estimate_coin_sell_all.go b/api/estimate_coin_sell_all.go index 65a3e80a7..9c72d9572 100644 --- a/api/estimate_coin_sell_all.go +++ b/api/estimate_coin_sell_all.go @@ -13,8 +13,7 @@ type EstimateCoinSellAllResponse struct { WillGet string `json:"will_get"` } -func EstimateCoinSellAll( - coinToSellString string, coinToBuyString string, valueToSell *big.Int, gasPrice uint64, height int) (*EstimateCoinSellAllResponse, +func EstimateCoinSellAll(coinIdToSell uint64, coinIdToBuy uint64, valueToSell *big.Int, gasPrice uint64, height int) (*EstimateCoinSellAllResponse, error) { cState, err := GetStateForHeight(height) if err != nil { @@ -28,8 +27,8 @@ func EstimateCoinSellAll( gasPrice = 1 } - coinToSell := types.StrToCoinSymbol(coinToSellString) - coinToBuy := types.StrToCoinSymbol(coinToBuyString) + coinToSell := types.CoinID(coinIdToSell) + coinToBuy := types.CoinID(coinIdToBuy) var result *big.Int @@ -50,7 +49,7 @@ func EstimateCoinSellAll( commission := big.NewInt(0).Set(commissionInBaseCoin) switch { - case coinToSell == types.GetBaseCoin(): + case coinToSell == types.GetBaseCoinID(): coin := cState.Coins().GetCoin(coinToBuy) valueToSell.Sub(valueToSell, commission) @@ -59,7 +58,7 @@ func EstimateCoinSellAll( } result = formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) - case coinToBuy == types.GetBaseCoin(): + case coinToBuy == types.GetBaseCoinID(): coin := cState.Coins().GetCoin(coinToSell) result = formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) diff --git a/api/v2/service/address.go b/api/v2/service/address.go index b5cb1dc15..34ca5010a 100644 --- a/api/v2/service/address.go +++ b/api/v2/service/address.go @@ -49,7 +49,7 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr balances := cState.Accounts().GetBalances(address) var response pb.AddressResponse - totalStakesGroupByCoin := map[types.CoinSymbol]*big.Int{} + totalStakesGroupByCoin := map[types.CoinID]*big.Int{} response.Balance = make(map[string]*pb.AddressBalance, len(balances)) for coin, value := range balances { @@ -65,7 +65,7 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr } if req.Delegated { - var userDelegatedStakesGroupByCoin = map[types.CoinSymbol]*UserStake{} + var userDelegatedStakesGroupByCoin = map[types.CoinID]*UserStake{} allCandidates := cState.Candidates().GetCandidates() for _, candidate := range allCandidates { userStakes := userStakes(candidate.PubKey, address, cState) @@ -126,19 +126,19 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr return &response, nil } -func customCoinBipBalance(coinToSell types.CoinSymbol, valueToSell *big.Int, cState *state.CheckState) *big.Int { - coinToBuy := types.StrToCoinSymbol("BIP") +func customCoinBipBalance(coinToSell types.CoinID, valueToSell *big.Int, cState *state.CheckState) *big.Int { + coinToBuy := types.GetBaseCoinID() if coinToSell == coinToBuy { return valueToSell } - if coinToSell == types.GetBaseCoin() { + if coinToSell == types.GetBaseCoinID() { coin := cState.Coins().GetCoin(coinToBuy) return formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) } - if coinToBuy == types.GetBaseCoin() { + if coinToBuy == types.GetBaseCoinID() { coin := cState.Coins().GetCoin(coinToSell) return formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) } @@ -149,8 +149,8 @@ func customCoinBipBalance(coinToSell types.CoinSymbol, valueToSell *big.Int, cSt return formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), basecoinValue) } -func userStakes(c types.Pubkey, address types.Address, state *state.CheckState) map[types.CoinSymbol]*UserStake { - var userStakes = map[types.CoinSymbol]*UserStake{} +func userStakes(c types.Pubkey, address types.Address, state *state.CheckState) map[types.CoinID]*UserStake { + var userStakes = map[types.CoinID]*UserStake{} stakes := state.Candidates().GetStakes(c) diff --git a/api/v2/service/addresses.go b/api/v2/service/addresses.go index 9412a141f..d00925b34 100644 --- a/api/v2/service/addresses.go +++ b/api/v2/service/addresses.go @@ -50,7 +50,7 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. balances := cState.Accounts().GetBalances(address) var res pb.AddressesResponse_Result - totalStakesGroupByCoin := map[types.CoinSymbol]*big.Int{} + totalStakesGroupByCoin := map[types.CoinID]*big.Int{} res.Balance = make(map[string]*pb.AddressBalance, len(balances)) for coin, value := range balances { @@ -66,7 +66,7 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. } if req.Delegated { - var userDelegatedStakesGroupByCoin = map[types.CoinSymbol]*UserStake{} + var userDelegatedStakesGroupByCoin = map[types.CoinID]*UserStake{} allCandidates := cState.Candidates().GetCandidates() for _, candidate := range allCandidates { userStakes := userStakes(candidate.PubKey, address, cState) diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index 1ae47d7f7..3fd9b6609 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -18,7 +18,7 @@ func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.Co cState.RLock() defer cState.RUnlock() - coin := cState.Coins().GetCoin(types.StrToCoinSymbol(req.Symbol)) + coin := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.Symbol)) if coin == nil { return new(pb.CoinInfoResponse), status.Error(codes.FailedPrecondition, "Coin not found") } diff --git a/cmd/minter/cmd/export.go b/cmd/minter/cmd/export.go index 6d239c961..b74f4554b 100644 --- a/cmd/minter/cmd/export.go +++ b/cmd/minter/cmd/export.go @@ -97,10 +97,10 @@ func export(cmd *cobra.Command, args []string) error { AppState: json.RawMessage(jsonBytes), } - err = genesis.ValidateAndComplete() - if err != nil { - log.Panicf("Failed to validate: %s", err) - } + //err = genesis.ValidateAndComplete() + //if err != nil { + // log.Panicf("Failed to validate: %s", err) + //} if err := genesis.SaveAs(genesisPath); err != nil { log.Panicf("Failed to save genesis file: %s", err) diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index d1202dc57..a06c59c76 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -3,17 +3,13 @@ package cmd import ( "fmt" api_v1 "github.com/MinterTeam/minter-go-node/api" - api_v2 "github.com/MinterTeam/minter-go-node/api/v2" - service_api "github.com/MinterTeam/minter-go-node/api/v2/service" "github.com/MinterTeam/minter-go-node/cli/service" "github.com/MinterTeam/minter-go-node/cmd/utils" "github.com/MinterTeam/minter-go-node/config" "github.com/MinterTeam/minter-go-node/core/minter" "github.com/MinterTeam/minter-go-node/core/statistics" "github.com/MinterTeam/minter-go-node/log" - "github.com/MinterTeam/minter-go-node/version" "github.com/spf13/cobra" - "github.com/tendermint/go-amino" "github.com/tendermint/tendermint/abci/types" tmCfg "github.com/tendermint/tendermint/config" tmlog "github.com/tendermint/tendermint/libs/log" @@ -28,7 +24,6 @@ import ( "io" "net/http" _ "net/http/pprof" - "net/url" "os" "syscall" ) @@ -112,19 +107,19 @@ func runNode(cmd *cobra.Command) error { app.SetTmNode(node) if !cfg.ValidatorMode { - go func(srv *service_api.Service) { - grpcUrl, err := url.Parse(cfg.GRPCListenAddress) - if err != nil { - logger.Error("Failed to parse gRPC address", err) - } - apiV2url, err := url.Parse(cfg.APIv2ListenAddress) - if err != nil { - logger.Error("Failed to parse API v2 address", err) - } - traceLog := os.Getenv("API_V2_LOG_LEVEL") == "trace" - logger.Error("Failed to start Api V2 in both gRPC and RESTful", - api_v2.Run(srv, grpcUrl.Host, apiV2url.Host, traceLog)) - }(service_api.NewService(amino.NewCodec(), app, client, node, cfg, version.Version)) + //go func(srv *service_api.Service) { + // grpcUrl, err := url.Parse(cfg.GRPCListenAddress) + // if err != nil { + // logger.Error("Failed to parse gRPC address", err) + // } + // apiV2url, err := url.Parse(cfg.APIv2ListenAddress) + // if err != nil { + // logger.Error("Failed to parse API v2 address", err) + // } + // traceLog := os.Getenv("API_V2_LOG_LEVEL") == "trace" + // logger.Error("Failed to start Api V2 in both gRPC and RESTful", + // api_v2.Run(srv, grpcUrl.Host, apiV2url.Host, traceLog)) + //}(service_api.NewService(amino.NewCodec(), app, client, node, cfg, version.Version)) go api_v1.RunAPI(app, client, cfg, logger) } diff --git a/core/check/check.go b/core/check/check.go index 45de54814..59d94fcc9 100644 --- a/core/check/check.go +++ b/core/check/check.go @@ -20,9 +20,9 @@ type Check struct { Nonce []byte ChainID types.ChainID DueBlock uint64 - Coin types.CoinSymbol + Coin types.CoinID Value *big.Int - GasCoin types.CoinSymbol + GasCoin types.CoinID Lock *big.Int V *big.Int R *big.Int diff --git a/core/events/types.go b/core/events/types.go index 660a712bc..46c8384be 100644 --- a/core/events/types.go +++ b/core/events/types.go @@ -140,7 +140,7 @@ func (s *slash) compile(pubKey string, address [20]byte) Event { event := new(SlashEvent) copy(event.ValidatorPubKey[:], pubKey) copy(event.Address[:], address[:]) - copy(event.Coin[:], s.Coin[:]) + copy(event.Coin.Bytes(), s.Coin[:]) event.Amount = big.NewInt(0).SetBytes(s.Amount).String() return event } @@ -156,7 +156,7 @@ func (s *slash) pubKeyID() uint16 { type SlashEvent struct { Address types.Address `json:"address"` Amount string `json:"amount"` - Coin types.CoinSymbol `json:"coin"` + Coin types.CoinID `json:"coin"` ValidatorPubKey types.Pubkey `json:"validator_pub_key"` } @@ -179,7 +179,7 @@ func (se *SlashEvent) validatorPubKey() types.Pubkey { func (se *SlashEvent) convert(pubKeyID uint16, addressID uint32) compactEvent { result := new(slash) result.AddressID = addressID - copy(result.Coin[:], se.Coin[:]) + copy(result.Coin[:], se.Coin.Bytes()) bi, _ := big.NewInt(0).SetString(se.Amount, 10) result.Amount = bi.Bytes() result.PubKeyID = pubKeyID @@ -197,7 +197,7 @@ func (u *unbond) compile(pubKey string, address [20]byte) Event { event := new(UnbondEvent) copy(event.ValidatorPubKey[:], pubKey) copy(event.Address[:], address[:]) - copy(event.Coin[:], u.Coin[:]) + copy(event.Coin.Bytes(), u.Coin[:]) event.Amount = big.NewInt(0).SetBytes(u.Amount).String() return event } @@ -213,7 +213,7 @@ func (u *unbond) pubKeyID() uint16 { type UnbondEvent struct { Address types.Address `json:"address"` Amount string `json:"amount"` - Coin types.CoinSymbol `json:"coin"` + Coin types.CoinID `json:"coin"` ValidatorPubKey types.Pubkey `json:"validator_pub_key"` } @@ -236,7 +236,7 @@ func (ue *UnbondEvent) validatorPubKey() types.Pubkey { func (ue *UnbondEvent) convert(pubKeyID uint16, addressID uint32) compactEvent { result := new(unbond) result.AddressID = addressID - copy(result.Coin[:], ue.Coin[:]) + copy(result.Coin[:], ue.Coin.Bytes()) bi, _ := big.NewInt(0).SetString(ue.Amount, 10) result.Amount = bi.Bytes() result.PubKeyID = pubKeyID diff --git a/core/minter/minter.go b/core/minter/minter.go index 735a61fab..0f93fbb3c 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -262,10 +262,6 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res func (app *Blockchain) EndBlock(req abciTypes.RequestEndBlock) abciTypes.ResponseEndBlock { height := uint64(req.Height) - if height == upgrades.UpgradeBlock3 { - ApplyUpgrade3(app.stateDeliver, app.eventsDB) - } - var updates []abciTypes.ValidatorUpdate vals := app.stateDeliver.Validators.GetValidators() @@ -299,7 +295,7 @@ func (app *Blockchain) EndBlock(req abciTypes.RequestEndBlock) abciTypes.Respons // accumulate rewards reward := rewards.GetRewardForBlock(height) - app.stateDeliver.Checker.AddCoinVolume(types.GetBaseCoin(), reward) + app.stateDeliver.Checker.AddCoinVolume(types.GetBaseCoinID(), reward) reward.Add(reward, app.rewards) // compute remainder to keep total emission consist diff --git a/core/minter/upgrade3.go b/core/minter/upgrade3.go deleted file mode 100644 index 1e3bc44c8..000000000 --- a/core/minter/upgrade3.go +++ /dev/null @@ -1,446 +0,0 @@ -package minter - -import ( - eventsdb "github.com/MinterTeam/minter-go-node/core/events" - "github.com/MinterTeam/minter-go-node/core/state" - "github.com/MinterTeam/minter-go-node/core/types" - "github.com/MinterTeam/minter-go-node/helpers" - "github.com/MinterTeam/minter-go-node/upgrades" - "math/big" - "strings" -) - -func ApplyUpgrade3(state *state.State, events eventsdb.IEventsDB) { - list := `720:Mp2cbade2b08501047bb9d2a08abeee21e276cb0e027e84e3a526ede85c4cbd442:Mxdd611a177d523bcb3f7faef70dbccc7c78b89e93:10000000000000000000000:FRANKLIN -960:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxa69b27ddca35b3438a9f5abfd170cc79d167f99d:50949508056216228178:KARAT -1320:Mp2cbade2b08501047bb9d2a08abeee21e276cb0e027e84e3a526ede85c4cbd442:Mx96bba42ec0eecf784fe3b3bb4fab0ffeb5e6c560:200000000000000000:LOVECOIN -1800:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx8f16fe070b065b958fa6865bd549193827abc0f8:5000000000000000000000:FUFELL14 -1920:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mx065f5324316c467103ad8e8c721b9b7f2b26836c:8612440583210883172:BIP -2040:Mpc6df0dd44cae3cb49ee0ef8bd78750b961e64e231e6dfdc22fbd8e0c476d66d2:Mxdb7c5253e849e1116465b616cb3b69154478681f:315000000000000000000:BTT -2280:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxf7ae7dd3c97b2734ffc8e5ad54eadb7e1b1308a9:97696679897506760254:BIP -2760:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxc128ec9acd82a2a92f483426d06db9de80ee82fa:2350000000000000000000:FRANKLIN -2760:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx2daa18881dc75f27d9debacc46fda99a5445d94a:115000000000000000000:FACK10K -2760:Mp2cbade2b08501047bb9d2a08abeee21e276cb0e027e84e3a526ede85c4cbd442:Mx19db40809286d0d8f287d403024f5a8ae834b304:1000000000000000000000:ROCKNROLL -2760:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mx24315150d9877b61d53993e4d007de9f0b8cdec2:1000000000000000000000:BIP -3120:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mx3c2e19acf5bab7ca39382cb73cf7fb544ac67236:10075395600411873912:ALPHA -3198:Mp2cbade2b08501047bb9d2a08abeee21e276cb0e027e84e3a526ede85c4cbd442:Mx3a87af3eb515803ff10bbaa5784ccd66e9b60c58:150000000000000000000:FACK10K -3373:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx8f16fe070b065b958fa6865bd549193827abc0f8:85000000000000000000000:VEXILIFERR -3480:Mpc6df0dd44cae3cb49ee0ef8bd78750b961e64e231e6dfdc22fbd8e0c476d66d2:Mxe8381cd918aee5942bd70bafcca0d935da703054:345000000000000000000:MNST -3960:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx2f3b77e109ce73f61f929d0415a42ae4808f6988:7288642318836932269539:VECTRUM -3994:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mxcfa7c5d4ef6d5efe025152e8b7cd5307cfab4ffc:266059072503155167552:ALPHA -4223:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx64690ff5480819e37e88456c855ba36682d4e822:79000000000000000000:BIP -4245:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx6baf0b01879662b1979967e1a01d64cd6646a52b:90000000000000000000:BIP -4276:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mxd41794f2d58651c44135fc8dc447f6464d24a8bb:90000000000000000000:BIP -4383:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxddf836602a86301d7e00e5b21f7c7bb69a2d7fbf:2000000000000000000000:FRANKLIN -4662:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxf4fcf5a27ff92087129bd69051d81366629edf65:82500000000000000000:KARAT -4662:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxd77163004f5ce2ac3f99677c9a11dc329cb13269:5000000000000000000000:GENESIS -5160:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx30a344ffc322514d809f8da32a7f97c33f18f894:90000000000000000000:BIP -5160:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx876274fda7683706639f96f453699866f763c99c:51830000000000000000:MPRO -5160:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mx2daa18881dc75f27d9debacc46fda99a5445d94a:115000000000000000000:FACK10K -5280:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxa0dab5810bf5f667c7fa5ed1433006fba87fbe32:728253397094429504794:BIP -5640:Mp92d05e745464f4d17a12440f48d73dddf8135e45cf91a7e3c4bcacdb2cc1c99f:Mxbde0012c075024e87fb66ab3ad014b6b81db8c3d:3003574960395749645337:ROCKNROLL -5640:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx57c2ae9be768965f98ab4df0c7fda86042b2b756:223889670732786458:CHAINIK -5760:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx541db3945ca1a02562682e1ca8132cd74063a2ce:2000000000000000000000:FRANKLIN -5760:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx64690ff5480819e37e88456c855ba36682d4e822:90000000000000000000:BIP -5880:Mp4926c68cec9b85d743810c801c35c33bd3d1e74ae0a801e4e08998e656835727:Mx87950dd945b86ffa42198651577e49ae18e1de6f:63000000000000000000:BIP -6000:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx5e66b44e1eec6529752c49bfc8c708310035f32e:1600000000000000000000:BIP -6120:Mpf2e3975489fbb0c3df8116e7de239d2f5ee72da156983f974a7b6a55f223d3c8:Mx43fd592a69fad43c8c882cd280e4b464b2a7583c:88100000000000000000000:AFFILATE -6360:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mxf9fc891309605917b4127ac151eb31a9e44637e6:2944000000000000000000:BIP -6360:Mpf2e3975489fbb0c3df8116e7de239d2f5ee72da156983f974a7b6a55f223d3c8:Mx943212f3e5428a29d11c1c6c22739f689b9a79fd:101000000000000000000:AFFILATE -6480:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx3e547ce1dda747b1de1abd5c3c6d48dcfb88b88b:122488046690011534568:BIP -6600:Mpf2e3975489fbb0c3df8116e7de239d2f5ee72da156983f974a7b6a55f223d3c8:Mx5d4396eb0169976da59f7e6e0a95e53b97ae00bb:526820000000000000000:AFFILATE -6960:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx0825e377f259dbf7cd06f5e3a7bf0a642c33edfb:800000000000000000:BIP -6960:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mxfafcdfb4f5a4307328f19f6b776db8cd7ee2bcf8:1481645300000000000000:BIP -7080:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mxecc5f8214ea59adce6503affd19bda1b16a05770:19321316782411115110:BIP -7200:Mp4926c68cec9b85d743810c801c35c33bd3d1e74ae0a801e4e08998e656835727:Mxf0b478262f2f931652fe5d3d0e6d71566c891220:10000000000000000000:MRBLACK -7680:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx7f50e4fa2eef1bb3faca1dbfdfe43491d3ef4ee3:73994814771892150786:BIP -7800:Mp3ff4490148c0cf42a9780dbb24a08e012d30d6f371021d28f8e4d3a8e2d6d9cf:Mxb0024e09c92e3c578c7706140ac4582ba7dafa12:3941465748785008068:GAMEZZ -8040:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx4a7ba405fab3c15ceaec716eb9a3ac82adcae9ca:20000000000000000000000:BIP -8160:Mpa70d12c096cb459e7c191be0dffb1a7dbe4a9587bfa7174c654959e5e9da7203:Mxe8fc28f7558ce5a89119dd76a7f5053fdb4ad242:147800000000000000000:BIP -8280:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mxa020f3fead6c0a862bd7bcb899e667eee44fd577:3119861290830091897617:BIRUZA -8400:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx44fdcecd97b88f5b3bccdf2266dbd8e2507bf257:95144868569374506624:BIP -8640:Mpd7a9eae76d3e98145b6b897c00c407b42ae8c42f937527ebdcd0239a4d88c0a5:Mxb58810523c95a54fb6fda7e0adb09acdffd4cd30:159250200000000000000:BIP -8880:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx0576ef7b02c95b55061c7e49af08b07daea6f23b:17739564141443223755:BIP -9000:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mxbdb97854a89798d03583bbaa974e9283ec0c26fe:1000000000000000000:BIP -9120:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx4bb3ff4c53e3078f5268247ae4d24f02285667f3:1095887843938452267791:DESIGN -9120:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxf8d2a6af093385b5ef4b04dc3ba2ab963867caf0:97070960022638037159:TIME -9720:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx3406e85e5dc6cbbfe52a16725969fcf7cf61da58:800000000000000000035:BIPBONUS -9840:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxc7839fdb4a5b4fc2f6d3559f0a458bb1d5fd2f8d:40000000000000000000:GALAXY1 -10080:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx31e8a6caa0a2aeadcb1ad3c4db715af238205476:390000000000000000:PLAKAT -10080:Mp5e3e1da62c7eabd9d8d168a36a92727fc1970a54ec61eadd285d4199c41191d7:Mx21a8d6ac8f592c94f01bfb5b12bdb98cb3575882:1983413301941081789861:CAPITAL -10440:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx7e640862d0f4135143729f76dd7ad071f89249eb:5000000000000000000:PLAKAT -10560:Mpd7a9eae76d3e98145b6b897c00c407b42ae8c42f937527ebdcd0239a4d88c0a5:Mxb550c550bf538858e95fa594291c85c004601c41:292000000000000000000:CHIP -10680:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx070cd0650784690994e02fee48e57e2eafe17d51:2999845540976787160135:BIRUZA -10680:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxe4f197512e393faed559f40730f0238c5c066666:100000000000000000000:LITTLEBIG -11280:Mp2cbade2b08501047bb9d2a08abeee21e276cb0e027e84e3a526ede85c4cbd442:Mx59466e1ecb5f22583957377cb8f32a1d9f05ac7a:4735830081657526113:BIP -11760:Mp65758496f8a5d626cac77f5a38894beae0050fdef862da201964cd2fd8111111:Mxb6cf27afb1d43f0c1a54239946eba656ddf7b719:63574911304593469:BIP -12360:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx7e640862d0f4135143729f76dd7ad071f89249eb:20548180455237193660846:STILBON -12360:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx7b62c49a589001d818d695a741fd45feb7677fc2:35763296409768599488:WORLDCOIN -12480:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx8059198fdd5110b167f9174d8a4fcf5636932aed:43111692098939098488:CASH -12480:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx8059198fdd5110b167f9174d8a4fcf5636932aed:26803379835019366643:DOBRO -12480:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx8059198fdd5110b167f9174d8a4fcf5636932aed:258137574566281399720:WORLDCOIN -12480:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx8059198fdd5110b167f9174d8a4fcf5636932aed:2588040721837738868382:LIGMARGAME -12960:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx8059198fdd5110b167f9174d8a4fcf5636932aed:4013866585422192175:REWARD -14160:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxa713cacee41e221416b0e4185d2711c6a637d565:36000000000000000000:ENERGY -15240:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx3c2e19acf5bab7ca39382cb73cf7fb544ac67236:2236402216980526145220:BIP -15480:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxbe6b206df4c74bee59e4dd6bd464a7ba51a741bc:1000000000000000000000:FRANKLIN -15840:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx71ca18b482baa95714e556d20255aa12f8d6e8ea:10000000000000000000000:KEEPTHEBIP -16080:Mpd7a9eae76d3e98145b6b897c00c407b42ae8c42f937527ebdcd0239a4d88c0a5:Mx845e872ba7400162402df881514b70eb777697ae:3000000000000000000000:BIP -16200:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mx7c7c564724e80aaa1d47553c5390008b6f4a89ab:1000000000000000000000:ALPHA -16440:Mp2cbade2b08501047bb9d2a08abeee21e276cb0e027e84e3a526ede85c4cbd442:Mxb9d13133cda57fe61fc5c0e66e0ef7b8eb9dddb8:1815907510832552134161:HEALTH -16560:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx5ba0e3efa1ac05a9bbbbb59000b800169040b2c7:932209771174254658822:WILDBIT -16680:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx5f80627a82f79c657045b36cba35abce2dc7a548:500000000000000000000:BIP -16680:Mpf2e3975489fbb0c3df8116e7de239d2f5ee72da156983f974a7b6a55f223d3c8:Mx943212f3e5428a29d11c1c6c22739f689b9a79fd:445420000000000000000:AFFILATE -17040:Mpc6df0dd44cae3cb49ee0ef8bd78750b961e64e231e6dfdc22fbd8e0c476d66d2:Mx50e9c7195feda1f2a8f62eb7acf8facfb8210a08:20191790000000000000000:BIP -17160:Mpf2e3975489fbb0c3df8116e7de239d2f5ee72da156983f974a7b6a55f223d3c8:Mx6a18282d5579349f10ac901171bddd5e62d652c7:55514943631444791426829:AFFILATE -17160:Mp5e3e1da62c7eabd9d8d168a36a92727fc1970a54ec61eadd285d4199c41191d7:Mxabc09e696e571599ed2649ccd7b90222f7a37b3f:1558413327355746185849:ROCKNROLL -17280:Mpf2e3975489fbb0c3df8116e7de239d2f5ee72da156983f974a7b6a55f223d3c8:Mx14bdb62cea3e57e8e2bae574ecb1c9a9ecb32c4c:2511000000000000000000:AFFILATE -17640:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxcac16cd32911a23127caba14c42065241e97e34f:1000000000000000000:MSCAN -17760:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mxd6429ea394ad9e10b4e61f3eb305bc16eeee8239:913792800000000000000:BIP -17880:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mxf6f80dcc3551b97753adc2d37de401ae0288f3e4:132000000000000000000:BIP -18000:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx28a36ef48e7538af8f0fe0e528347c0c0db4230d:35000000000000000000:ZERO -18240:Mp92d05e745464f4d17a12440f48d73dddf8135e45cf91a7e3c4bcacdb2cc1c99f:Mxc7839fdb4a5b4fc2f6d3559f0a458bb1d5fd2f8d:10000000000000000000:GALAXY1 -18240:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx90d178e077b0bacec19556cb9f5b1120670b1197:1228665027914854590162:FRANKLIN -18240:Mp3ff4490148c0cf42a9780dbb24a08e012d30d6f371021d28f8e4d3a8e2d6d9cf:Mxf4fcf5a27ff92087129bd69051d81366629edf65:772428699776254913:BIP -18240:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mx845e872ba7400162402df881514b70eb777697ae:3000000000000000000000:BIP -18240:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mx7d3a7d965bf8ee95ff7999c8c2af7683cba39be1:22538812514902170853:BIP -18360:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:AMERICAN -18360:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx8059198fdd5110b167f9174d8a4fcf5636932aed:20358137596845703:LOBSTER -18360:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:IMAGINARY -18360:Mp5e3e1da62c7eabd9d8d168a36a92727fc1970a54ec61eadd285d4199c41191d7:Mxfda2f0143fbc896c6dac4fa50714661f93187b44:262906496442186187200:SNAPSHOT -18360:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:70800000000000000000:BIPBANKER -18360:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:AEROFLOT -18480:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxffa76830d38834898ba8ffb61b9a630a431b4981:70000000000000000000:BURGERKING -18480:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:GENERAL -18480:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:MARLBORO -18480:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx8a2f6b28e78bcfc43a47d3a454422fb681445b5d:263818192813925416100:FREEDOM -18480:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx940361f744b427749406d9dfc80bf6c00474291a:1055000000000000000000:BIP -18480:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:76000000000000000000:IBANKER -18480:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:70000000000000000000:BITTEAM -18600:Mpf2e3975489fbb0c3df8116e7de239d2f5ee72da156983f974a7b6a55f223d3c8:Mx6a18282d5579349f10ac901171bddd5e62d652c7:47035711653037566887284:AFFILATE -18600:Mpa70d12c096cb459e7c191be0dffb1a7dbe4a9587bfa7174c654959e5e9da7203:Mx206d38cf4edcda8919ecb930367020a5c17b7fbc:4999000000000000000000:BIP -18600:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxffa76830d38834898ba8ffb61b9a630a431b4981:75000000000000000000:MCDONALDS -18600:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:FREEPORT -18600:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxffa76830d38834898ba8ffb61b9a630a431b4981:75000000000000000000:MCDONALD -18600:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:RAIFFEISEN -18600:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx41c8876db5af0e5668bd6461e0edcf9fccc6bdcb:955734957695297206392:BIP -18600:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:70000000000000000000:GENESISLAB -18600:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:MEADOW -18600:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:KRAFTFOODS -18600:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:BUTTERFLY -18720:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxffa76830d38834898ba8ffb61b9a630a431b4981:63000000000000000000:MASTERCARD -18720:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:MIRACLE -18720:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxffa76830d38834898ba8ffb61b9a630a431b4981:63000000000000000000:VISACARD -18720:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxffa76830d38834898ba8ffb61b9a630a431b4981:75000000000000000000:SILVERCOIN -18720:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxffa76830d38834898ba8ffb61b9a630a431b4981:70000000000000000000:PROFICOIN -18720:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxffa76830d38834898ba8ffb61b9a630a431b4981:70000000000000000000:ROADMAP -18720:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:ROSNEFT -18720:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:62000000000000000000:SBERBANK -18720:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:70000000000000000000:CANDYNODE -18840:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:CAPPUCCINO -18840:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:UMBRELLA -18840:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:GAZPROM -18840:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:COCACOLA -18840:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:DIAMONDS -18840:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:PALADIN -18840:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:WESTERN -18840:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:REFLECTION -18960:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mxf3ae262a23c30f6aa3be1ddab2a10dfb5e251c15:36000000000000000000:BIP -19080:Mpf2e3975489fbb0c3df8116e7de239d2f5ee72da156983f974a7b6a55f223d3c8:Mx7fd23f9b9e1151e559107aae0b1ac118816bf25b:10294967177126885463234:AFFILATE -19320:Mpc6df0dd44cae3cb49ee0ef8bd78750b961e64e231e6dfdc22fbd8e0c476d66d2:Mx0784c166c6f33649deeb6d3e030d5d378e4744a0:1851072601610888:BEHEALTHY -19320:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:WALMART -19680:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mx8504b25a26939f48a3f8877ff1646b9b5d33129c:100000000000000000000:BIP -20160:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxa7795090ded80ae1122d8ece8bdc17cdcaa72a84:215204566204493842877:KARAT -20280:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx7117eb5f6d0b86822dcbad650d848dcce0a12ebd:365295881133658263065:BIP -20280:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mxb1a18a1f888752e27bcd7d60064ebb5af673c503:4314680000000000000000:BIP -20400:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mx8ec3f0f9ea5e57140d4931aff99c85af85da33e8:1010000000000000000000:BIP -20520:Mp2cbade2b08501047bb9d2a08abeee21e276cb0e027e84e3a526ede85c4cbd442:Mx96bba42ec0eecf784fe3b3bb4fab0ffeb5e6c560:100000000000000000:LOVECOIN -20520:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mx0108df50a1e72b03908d697bebdfadf0516e087a:10000000000000000000:ALPHA -20520:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mx063c561965c1363caef0050d9c6b5c517cf6e5d1:3964295060573553972686:EGGCOIN -20640:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxffa76830d38834898ba8ffb61b9a630a431b4981:72000000000000000000:COINPRO -20640:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx92f1475a7c4269ab1b9949609b406fffc67076e9:150000000000000000000:FRANKLIN -20760:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mxbdb97854a89798d03583bbaa974e9283ec0c26fe:1000000000000000000:BIP -20760:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxb97ecd5fe8f09a00a65801e7d70e61e74f13600c:100000000000000000:100COINS -21000:Mpd7a9eae76d3e98145b6b897c00c407b42ae8c42f937527ebdcd0239a4d88c0a5:Mxd2194b32f679232fb3bce747bf35750c2e3f18a3:10404119730572297000:BIP -21240:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx4f390f612b7e5f0d6a075720f836e614368d0dbf:7777000000000000000000:FRANKLIN -21240:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx504c113c65f8abadfebf0e72f579fcffdda6f23f:5960192988979158464:BIP -21600:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxa4ca13d5831e095aaedc08f172977805e215d34c:137040108084953075701:BIP -21600:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mxdd7585be32f4669b92acee3928e59afe832a6afc:2543906195560268140:BIP -21840:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx912dc60742724905ee1434c096464ea82559a5da:960807343727548430024:ELECTRO -22080:Mp4926c68cec9b85d743810c801c35c33bd3d1e74ae0a801e4e08998e656835727:Mxef57005e8f085f23ee9fae84c3cc467ca7a0e79f:500000000000000000000:EP1CPWR -22080:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxc5fed5dbb6c48b99a683ec98540605de14bc078c:284374018093303695804:BIP -22320:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx9436047660fbf1c04df3cfae457975733bfc66d0:831636722950215583812738:WILDBIT -22320:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx57c2ae9be768965f98ab4df0c7fda86042b2b756:7209808638667525923731:ONLY1 -22320:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxd4835b5acf6e87271071dd99d55b8bdd6c651589:1750000000000000000000:PIZZA -22320:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx3eac9a8c2063d7b0e140e6349fc7207c3cd2f3d1:1500000000000000000000:PIZZA -22320:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx5340146e93ae3f5e811b0573b7c8780a3f060ced:7246170777851714543:KARAT -22440:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx09606fbeaee7d6d6926c654294690b09e07773f4:2500000000000000000000:PIZZA -22440:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mx063c561965c1363caef0050d9c6b5c517cf6e5d1:5000000000000000000:MSCAN -22440:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:SYMANTEC -22560:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxddf836602a86301d7e00e5b21f7c7bb69a2d7fbf:50000000000000000000:FRANKLIN -22560:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx57c2ae9be768965f98ab4df0c7fda86042b2b756:13553602876624029726:KARAT -23040:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx5340146e93ae3f5e811b0573b7c8780a3f060ced:690000000000000000000:KARAT -23040:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxa4b8bf84fa6a5a47bf3a7f5a0674ee6b1fe3491f:120000000000000000000:BIP -23160:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxbe6b206df4c74bee59e4dd6bd464a7ba51a741bc:490000000000000000000:FRANKLIN -23280:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx8147ec52768d0eb9a101eb3e15b7187f183f6636:1500000000000000000000:PIZZA -23400:Mp02ff680cbea3fb95f547bddde69c9150b3b7ab8d1c5c2a1bf94ccb70bf073b2c:Mx1ddf11baaf6e169949a903cb199487a104cdf167:1500000000000000000:INFLOW -23760:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx08adb0251013bda4f09effa744ec1cf192717c48:101600015918981066963:BIP -23880:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mx062446125fadd8f424891ae16dae0a11b69442d3:278000000000000000000:BIP -24000:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx0c9c587dd552f949c356bbda67c4ad3dd61e2db0:30000000000000000000000:LUCKYLIFE -24000:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mxb0b7a8193b02ce8610815ca9138fb168ac0d9f44:377239475575567506534:BIP -24120:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxc2836035e7d25658cfa229646d77f4a1a07e6cca:615643141483183660722:KARAT -24120:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx57c2ae9be768965f98ab4df0c7fda86042b2b756:7879488610183692704:KARAT -24120:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx9822d4fb9d3f212975af1b1fd8324ffd177eab53:54747704448640294147:MPRO -24240:Mpd7a9eae76d3e98145b6b897c00c407b42ae8c42f937527ebdcd0239a4d88c0a5:Mx791a6d843077efa0a83b80e84ca598f5fcacf118:10000000000000000000000:GRAMIUM -24240:Mp2cbade2b08501047bb9d2a08abeee21e276cb0e027e84e3a526ede85c4cbd442:Mx3861de6d792caed96fc84d629a9edd2a54d2ec74:2010028019254643306632:STILBON -24600:Mpa70d12c096cb459e7c191be0dffb1a7dbe4a9587bfa7174c654959e5e9da7203:Mxd8a267e01afa4624699ee9fc2a2067d59eebdb10:1331000000000000000000:BIP -24600:Mp92d05e745464f4d17a12440f48d73dddf8135e45cf91a7e3c4bcacdb2cc1c99f:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:CARNIVAL -24600:Mp5e3e1da62c7eabd9d8d168a36a92727fc1970a54ec61eadd285d4199c41191d7:Mxabc09e696e571599ed2649ccd7b90222f7a37b3f:1500000000000000000000:ROCKNROLL -24600:Mp4926c68cec9b85d743810c801c35c33bd3d1e74ae0a801e4e08998e656835727:Mx01cb3d112b53e4c0968bf87bbd73a1323ad6b732:500000000000000000000:BIP -24600:Mp02ff680cbea3fb95f547bddde69c9150b3b7ab8d1c5c2a1bf94ccb70bf073b2c:Mxe2214434df155bb122c42fe87925eeee5c1788ed:40000000000000000000:BIP -24840:Mp4926c68cec9b85d743810c801c35c33bd3d1e74ae0a801e4e08998e656835727:Mx36c6db1a37e9fe1b51df5dedcd60d8339c696111:1000000000000000000000:GANGSTER -24840:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mx7ccfd00ab7689a12aa283eb3d00683cf5348fcec:1068000000000000000000:FRANKLIN -24960:Mp7b4174732a169c467c9ee791576fc5860ca99bc7a49d8cfb041a91f9202178cc:Mxf2202fdf698ad4138dc4d446f72b1c53317ffcd8:400000000000000000:BANANA -24960:Mp2cbade2b08501047bb9d2a08abeee21e276cb0e027e84e3a526ede85c4cbd442:Mx96bba42ec0eecf784fe3b3bb4fab0ffeb5e6c560:200000000000000000:LOVECOIN -25080:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx88a711cad28d0df19ef4a7f9461dd8855c478a95:3132137331393384066392:BIP -25080:Mp2cbade2b08501047bb9d2a08abeee21e276cb0e027e84e3a526ede85c4cbd442:Mx27513ee8e47f457b5561e83c25864b65f2f8db0c:1584689887496928605628:QUANTIUM -25200:Mpa70d12c096cb459e7c191be0dffb1a7dbe4a9587bfa7174c654959e5e9da7203:Mx36c6db1a37e9fe1b51df5dedcd60d8339c696111:1000000000000000000000:GAMES -25320:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx25eb0e6020c0a951200081fd465210f09ab3e56b:10000000000000000000000:VIOLEUM -25320:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxda4819ae2e0edb48f080ed755df902bc1b1c3917:1500000000000000000000000:LIFEMONEY -25320:Mp02ff680cbea3fb95f547bddde69c9150b3b7ab8d1c5c2a1bf94ccb70bf073b2c:Mxface92230fc9d9ccf9646924d8a49863d7b9a649:153937522729283569570:TRADERS -25440:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx876274fda7683706639f96f453699866f763c99c:1149871218781843188:BIP -25560:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx69fc61d2ee91d6b50dd34a528bb7171fb4d8f849:500000000000000000000:BIP -25560:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxe9fd1e557a4851fe1ba76def2967da15defa4e4d:39454494455115615902423:BIP -25800:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx24315150d9877b61d53993e4d007de9f0b8cdec2:1200000000000000000000:BIP -26040:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mxefaf094072e11f20936c05b8ca5140c45e2e8bf6:1005781048961943237615:AFFILATE -26040:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx66d50e4634b0f62185a2a666bedc9f05e322cce2:162800000000000000000:BIP -26160:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx10306021211dd5190bcd17b9082c4977c457eedd:89763513419195623473:BIPSTORE -26160:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mx7ccfd00ab7689a12aa283eb3d00683cf5348fcec:100000000000000000000:FRANKLIN -26280:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mxc7a14ba1921de49c37016ce0fea8e4be5bf931de:65766723383130982226:ALPHA -26520:Mp5e3e1da62c7eabd9d8d168a36a92727fc1970a54ec61eadd285d4199c41191d7:Mx36c6db1a37e9fe1b51df5dedcd60d8339c696111:217513450893878287618:CAPITAL -26640:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx4d6e737bc043de4cc6f5ffdb0383eb01ccca3457:100000000000000000000:ONLY1 -26640:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx36c6db1a37e9fe1b51df5dedcd60d8339c696111:547846135000000000000:KARAT -26760:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx30123adc5f91eae372195a1bec0096e545ab1048:1263554828942720300:BIP -26880:Mp3ff4490148c0cf42a9780dbb24a08e012d30d6f371021d28f8e4d3a8e2d6d9cf:Mx227206dd8559b81a292a3dbd529a7193278051b2:86000000000000000000:BIP -27000:Mp2cbade2b08501047bb9d2a08abeee21e276cb0e027e84e3a526ede85c4cbd442:Mx0c9c587dd552f949c356bbda67c4ad3dd61e2db0:10000000000000000000000:LUCKYLIFE -27360:Mp92d05e745464f4d17a12440f48d73dddf8135e45cf91a7e3c4bcacdb2cc1c99f:Mx36c6db1a37e9fe1b51df5dedcd60d8339c696111:1000000000000000000000:GAMES -27720:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mx183c39990c3cf13cf16f89bd5672f2a04f8b4de4:1300000000000000000000:BIP -28080:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx30123adc5f91eae372195a1bec0096e545ab1048:131470000000000000035:BIPBONUS -28200:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx0576ef7b02c95b55061c7e49af08b07daea6f23b:61903195366876440360:BIP -28200:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxd77507ae481352e48615728dad3307d82b6e6895:4502290995554099058424:PIZZA -28200:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxcdbdcf4ce903a9ae2d3b97e8f8b982d1f01cd820:1178652242047212253914179:BIP -28440:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxbc0fbb4be660dd846399bd639c88a68ff1613ca0:1018711880563948791473:KARAT -28680:Mp4926c68cec9b85d743810c801c35c33bd3d1e74ae0a801e4e08998e656835727:Mxb97ecd5fe8f09a00a65801e7d70e61e74f13600c:100000000000000000:100COINS -28920:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx12ae36bee529fa1d78158634380ad2a1654afe79:4000000000000000000000:KARAT -29280:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxb098961f76be4d533509bca197d97b067cdc43e7:12472051126987485441:WILDBIT -29280:Mp5e3e1da62c7eabd9d8d168a36a92727fc1970a54ec61eadd285d4199c41191d7:Mxcebda1b2a6834db97b3d05f386729d2561060960:21993360586919369:BIP -30240:Mpc6df0dd44cae3cb49ee0ef8bd78750b961e64e231e6dfdc22fbd8e0c476d66d2:Mx9c984bc154f86f2aa37760d8465c416cc139769a:700000000000000000000:BIP -30840:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx04b3719d601e1204666e525367918f152f336ed3:854106370937750564071:WILDBIT -31200:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxc2836035e7d25658cfa229646d77f4a1a07e6cca:10739930341080808280:KARAT -31560:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx10306021211dd5190bcd17b9082c4977c457eedd:455559739904428660949:SOUNDCOIN -32520:Mp2cbade2b08501047bb9d2a08abeee21e276cb0e027e84e3a526ede85c4cbd442:Mx53fe2bfa554f59addd4abae8c6fd5f6a5bc921e9:7250277603262780739:FRANKLIN -32760:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxb32244a93589ceca6d46406b9d74328c771914d9:1890248514428746718521:BIP -33240:Mp65758496f8a5d626cac77f5a38894beae0050fdef862da201964cd2fd8111111:Mx78469e0cf2ac0eb9f4b84b7d27ee8866de402e3e:890659673011110054735:BIP -33480:Mpc6df0dd44cae3cb49ee0ef8bd78750b961e64e231e6dfdc22fbd8e0c476d66d2:Mx4f6ba53e3f6072e426d2c4da56439064ee756659:99800000000000000000:BIP -33480:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxef90c0384cdc70ccd30713f2c268bf55b2d1ae3b:70000000000000000000:BIP -33840:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxc2836035e7d25658cfa229646d77f4a1a07e6cca:9416146514332110069:KARAT -34080:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mxb34b4313aa28e48288cad7ceb3d21204797375ee:1429000000000000000000:BIP -34560:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mx1bf6b2e8daba57fc5fb58727f516013bac43b7c2:595605589000000000000:BIP -34800:Mp5e3e1da62c7eabd9d8d168a36a92727fc1970a54ec61eadd285d4199c41191d7:Mxa8b8992366c8d9bc9c329163c1a12714dac0ffee:1100538662221569875034:FUSION -35040:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx35f1b5e75dcaaa25ed15d1b3912d650fea61f823:2683577574444981732:BIP -35160:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxb5c1f6748132bbf7b6baa5e942f392aaece5e283:328351226967225342052:MINTERIUM -35280:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx61992c381a9b065a0c412d67d6ea048bf4d0e699:925197134998364980252:COINOPTIK -35400:Mpd7a9eae76d3e98145b6b897c00c407b42ae8c42f937527ebdcd0239a4d88c0a5:Mx9452faa8b6eb2447ebb8e1e1f9e008ed35bcaf89:140000000000000000000:BIP -35520:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mxecfe4212667f632ea240e5567cd24cae240054ef:1500000000000000000000:BIP -35520:Mpc6df0dd44cae3cb49ee0ef8bd78750b961e64e231e6dfdc22fbd8e0c476d66d2:Mx601422af0ec48feb62976c4952a6a4baf5583e90:100700000000000000000:BIP -35760:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx0a58d2d5de600efec190893c7f45ac4387051836:5096679502130353679:BIP -35760:Mp92d05e745464f4d17a12440f48d73dddf8135e45cf91a7e3c4bcacdb2cc1c99f:Mxffa76830d38834898ba8ffb61b9a630a431b4981:71000000000000000000:ROSTELECOM -36360:Mpd7a9eae76d3e98145b6b897c00c407b42ae8c42f937527ebdcd0239a4d88c0a5:Mx711f7a704d12e9e2f9cc928aee2b061522407ec8:25000000000000000000:BIP -36360:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxa8ed545a414a1d8fb95b9a3e9d56a46ae46f9c9f:36000830957111522865:KARAT -36480:Mp4926c68cec9b85d743810c801c35c33bd3d1e74ae0a801e4e08998e656835727:Mxbe5faf1f03fd032b1ea66681ea6f706a2033d8a4:10000000000000000000:UNB200K -36600:Mp4926c68cec9b85d743810c801c35c33bd3d1e74ae0a801e4e08998e656835727:Mxef57005e8f085f23ee9fae84c3cc467ca7a0e79f:100000000000000000:EP1CPWR -36720:Mp92d05e745464f4d17a12440f48d73dddf8135e45cf91a7e3c4bcacdb2cc1c99f:Mxc9dcb31dcf9b75ff6b9c7e4fae556147012a3d61:125405174118902032:BIP -36720:Mp4926c68cec9b85d743810c801c35c33bd3d1e74ae0a801e4e08998e656835727:Mx22c127fdb84e9f4f71a1a1a7be20d6a0ac17cdcd:871298343849:MATRIX -36720:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx2440baf2479851aab6f07f4bd61731b9515c5edf:70000000000000000000:BIP -37200:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mxd2da6a788b4fda271abcff2f9fd2de16cd79c527:8001562270222961429:BIP -37560:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx8546f047947fa126f49d005adee1c5809ec60270:1100000000000000000000:BIP -37560:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx33d6a20dc01827e6abb452a66d788fd0d2444537:122000000000000000000:BIP -37680:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxbe7dab5a2a7d472a36446541eabb9f0b5b134070:3550730308362633244908:BIP -37680:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mx10306021211dd5190bcd17b9082c4977c457eedd:686564852132370232979:SCIENCE -37800:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx936529c5bd5f68c2e9404372f5b2ca9033c8d0d2:3423477563596483015601:KARAT -38040:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx720b19989e78ee78bcdb78b1977cda51a6ad6d07:250000000000000000000:BIP -38400:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx91826fc03077294b332eb71ac3425b604be32ea1:665100073133074720:PLAKAT -38521:Mpa70d12c096cb459e7c191be0dffb1a7dbe4a9587bfa7174c654959e5e9da7203:Mx039569fdddc1148a83eb251ce731c40c26eb305d:808062273896046504725:BIP -38521:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxc65f0168a26dfbeb6128e2d14fd6e2239c1ec3b1:1000200000000:MINTDROPS -38640:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxc38c2b191e1797437ede99e2a7c70d289f81e33c:150000000000000000000:BIP -38760:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx9c213b6970ebf78e1ddff2ac7efa1ee4bbe6acde:2999845838979324071822:BIRUZA -38880:Mp5e3e1da62c7eabd9d8d168a36a92727fc1970a54ec61eadd285d4199c41191d7:Mx6c63799ef4408f4fd93ff5d7e228e3ccfd548df2:181738200000000000000:BIP -38880:Mp5e3e1da62c7eabd9d8d168a36a92727fc1970a54ec61eadd285d4199c41191d7:Mxabf98d720d1df5e3a639648507b7e87fb2204370:2810997878757988652:MATRIX -38880:Mp5e3e1da62c7eabd9d8d168a36a92727fc1970a54ec61eadd285d4199c41191d7:Mx111e470b470d418503a78c4e6bbb0816213c8fa2:1268851996838230149:MATRIX -38880:Mp5e3e1da62c7eabd9d8d168a36a92727fc1970a54ec61eadd285d4199c41191d7:Mx0d516c3cf0fa4cae2c25bc85d756d338be798bc3:1180657293357886440:MATRIX -38880:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxae3772f9ff4954cb2f4fe9796f0478696d36dd4c:187650981834753687554:DESIGN -38880:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxc4583af399dbb5d04f1a4dd6cf3f2c4e50aba470:100000000000000000000:BALANCE -38880:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxc4583af399dbb5d04f1a4dd6cf3f2c4e50aba470:110000000000000000000:DISBALANCE -38880:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mx95b842754ebd588773fa8550e2262d0ad1032c98:115567639629593700373:ALPHA -39360:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx0a58d2d5de600efec190893c7f45ac4387051836:891497838090304335767:BIP -39720:Mp92d05e745464f4d17a12440f48d73dddf8135e45cf91a7e3c4bcacdb2cc1c99f:Mxbde0012c075024e87fb66ab3ad014b6b81db8c3d:1000000000000000000000:ROCKNROLL -39840:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx44d51edf682330bec6c627abaed107c028e4b5c5:10000000000000000000:BIP -40080:Mp02ff680cbea3fb95f547bddde69c9150b3b7ab8d1c5c2a1bf94ccb70bf073b2c:Mx3f82f301b0fdcdaf7d0eb4a45e60a9e7d8be4f39:1000000000000000000000:FRANKLIN -40200:Mp5e3e1da62c7eabd9d8d168a36a92727fc1970a54ec61eadd285d4199c41191d7:Mx1ba993008a62d7be98b33f92bd85ba1c6a3fdb84:1177692511207742548:MATRIX -40200:Mp5e3e1da62c7eabd9d8d168a36a92727fc1970a54ec61eadd285d4199c41191d7:Mxc57f77767f20954b306c6e098d1a06fe893f65ce:14886686039859121538:MATRIX -40320:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxc4583af399dbb5d04f1a4dd6cf3f2c4e50aba470:477000000000000000000:BIOMETRY -40320:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mxcaa5a3742b9dc54c5cbd160ed3fa0785798ded13:900000000000000000000:BIP -40680:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx5217595c799f12c9c586b6a7496144a3cbab3446:1000000000000000000000:BIP -40680:Mp7b4174732a169c467c9ee791576fc5860ca99bc7a49d8cfb041a91f9202178cc:Mx66025ad100fbc18c5f51595d6f3effc162d2dcb0:10000000000000000000:CANDY -40920:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx684a6dc651293214a2942d6e5bc5dc6d6b3ec7d2:15341742910846751966:BIP -41040:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx26ad1e4ff99bfd8b72887d9253d88a7922847575:50650000000000000000:MPRO -41160:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mxd7cf0bab4624c31fe980ea3faed8cb81b05fa82d:7500000000000000000000:BIP -41160:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx63bfae01a963ae3bd78b03b50de723084a1e2dd8:49770000000000000000:MPRO -41400:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxc2836035e7d25658cfa229646d77f4a1a07e6cca:14495626589077689275:KARAT -41400:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx33d6a20dc01827e6abb452a66d788fd0d2444537:97517549311670217153:BIP -41520:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mxe7ab556dcd6474911aa995c0a2d07795ac096d3c:482680462789406289:ALPHA -41880:Mp5e3e1da62c7eabd9d8d168a36a92727fc1970a54ec61eadd285d4199c41191d7:Mxc57f77767f20954b306c6e098d1a06fe893f65ce:3672128237793956594:DOMAIN -41880:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxd568ff3f3b2681bb748b271589e7cdec648c75af:12300000000000000000:BIP -42120:Mp2cbade2b08501047bb9d2a08abeee21e276cb0e027e84e3a526ede85c4cbd442:Mx9436047660fbf1c04df3cfae457975733bfc66d0:4094870901300156750:HOSTING -42240:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx9884ade1269f36a84ecfc4d0244c1e93e5a9fe10:4144000000000000000000:BIP -42360:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx6e832344418a9bad70f4ffc95924781993eb33bd:1293497002068770219794:ZERO -42720:Mp1ada5ac409b965623bf6a4320260190038ae27230abfb5ebc9158280cdffffff:Mx69fc61d2ee91d6b50dd34a528bb7171fb4d8f849:1348798631654926474563:BIP -42840:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mxdd7585be32f4669b92acee3928e59afe832a6afc:7474421589711159660:BIP -43200:Mpa70d12c096cb459e7c191be0dffb1a7dbe4a9587bfa7174c654959e5e9da7203:Mxf2f738929e1989e6b89d2d2638b5cf9e71332880:67564233678576238125:BIP -43200:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx72730b5c2b659fc57ab2af06461192a23f6354f9:192280765883511575657:KARAT -43320:Mpc6df0dd44cae3cb49ee0ef8bd78750b961e64e231e6dfdc22fbd8e0c476d66d2:Mx7e17de669bd586e9ef22d515eb68675edbdf1b48:6000000000000000000:MNST -43320:Mpc6df0dd44cae3cb49ee0ef8bd78750b961e64e231e6dfdc22fbd8e0c476d66d2:Mx183c6d4e55f4a0b1c0ae22f99ee1c0e0211dfce0:21000000000000000000:ROBINCOIN -43320:Mpc6df0dd44cae3cb49ee0ef8bd78750b961e64e231e6dfdc22fbd8e0c476d66d2:Mx183c6d4e55f4a0b1c0ae22f99ee1c0e0211dfce0:200000000000000000000:GANGSTER -43440:Mp999d3789d40ff0c699f861758bcafde15d3b4828c7518bc94810837688888888:Mx1293bf099d359dffedf6f317fe9742179ce42241:1000000000000000000000:EGGCOIN -43440:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxbe6b206df4c74bee59e4dd6bd464a7ba51a741bc:1000000000000000000:BIP -43800:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mx6b32d1a0cff21de94fc6c519eaf85f264f016431:3000000000000000000:BTT -44040:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx566367694688785876927b5d57e25b6487b6f679:1000000000000000000:PRIVILEGE -44160:Mp7779ec1c6492e7c71a36f4009d7ee5a43fed2fe4048882b8a099e748869f0777:Mx36c6db1a37e9fe1b51df5dedcd60d8339c696111:465698355349903514000:WORLDCOIN -44400:Mp02bc3c3f77d5ab9732ef9fc3801a6d72dc18f88328c14dc735648abfe551f50f:Mxe4f197512e393faed559f40730f0238c5c066666:100000000000000000000:LITTLEBIG -44640:Mp7779ec1c6492e7c71a36f4009d7ee5a43fed2fe4048882b8a099e748869f0777:Mx84bef90cfda16a45d7a357e5c6e4833d99cfc741:1001100000000000000:4DREAM -45120:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx438c163efa201012690295a8ab4cdc0ae75edd7b:1190503776321856753636:MINTIUM -45720:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxcebda1b2a6834db97b3d05f386729d2561060960:2091749961963592741:BIP -45960:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxbde0012c075024e87fb66ab3ad014b6b81db8c3d:102583546473431954520:KARAT -47640:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxbd2c0c8cc16931b0fbe08dd173fd7c953dcaad58:1000000000000000000:IAMIMPROV -47640:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxf559a0609425bb8a41c5a275d6b7e65607de9321:13013100000000000000:LOVECOIN -48240:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxc2836035e7d25658cfa229646d77f4a1a07e6cca:11797753320201586028:KARAT -48600:Mp4926c68cec9b85d743810c801c35c33bd3d1e74ae0a801e4e08998e656835727:Mxef57005e8f085f23ee9fae84c3cc467ca7a0e79f:500100000000000000000:EP1CPWR -48600:Mp1ada5ac409b965623bf6a4320260190038ae27230abfb5ebc9158280cdffffff:Mxc0be46f30934181370ee02b716935805ef073ee7:100000000000000000000:BIP -49800:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx72effc233e0957d12288635f54c0fcada4cd1184:60402513926457125311:LASHIN -50280:Mp999d3789d40ff0c699f861758bcafde15d3b4828c7518bc94810837688888888:Mx4b966dce44f9a7c1786ab9ae92c5a94626d76842:110516998724015148:ENLIGHTEN -51000:Mp1ada5ac409b965623bf6a4320260190038ae27230abfb5ebc9158280cdffffff:Mx8031f68b35b0d77139b96ff7afd1ef11e3e41e25:4000000000000000000:BIP -51120:Mpd7a9eae76d3e98145b6b897c00c407b42ae8c42f937527ebdcd0239a4d88c0a5:Mx6cef43e6a00a1fbe6b162b946dd13245b4efe2e1:50000000000000000000:WHIPPING -51120:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxdf8a3187318cc77688a844ad6956e20d04cf2732:3029893000000000000000:BIP -51480:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx655a9fb0543d41121ae2855bdf673e5e9e688d04:90000000000000000000:BIP -51600:Mp3ff4490148c0cf42a9780dbb24a08e012d30d6f371021d28f8e4d3a8e2d6d9cf:Mx6d93344a3bd5483e927bb324e38f7d76e8c4c33e:1441593984980926645516:FRANKLIN -51720:Mp02ff680cbea3fb95f547bddde69c9150b3b7ab8d1c5c2a1bf94ccb70bf073b2c:Mx5a21fb54e94ab855c9092cc25955cdccb296044c:52241668071302600354:BIPMEX -51720:Mp02bc3c3f77d5ab9732ef9fc3801a6d72dc18f88328c14dc735648abfe551f50f:Mx8036617bf70954c9139f7156866c9975e4ccbb08:2000000000000000000:FREEDOM -52080:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx9d0d1c894c06bd96718558d5a22ce0ecbc7e3830:283544800000000000000:TRACKCOIN -52080:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx99ddb4f50c3183718e4af1f255435270a8cd3605:7719401443998266633:MPRO -52200:Mp02bc3c3f77d5ab9732ef9fc3801a6d72dc18f88328c14dc735648abfe551f50f:Mx06acaf371bf50fd4cf82c2952bf8f5dbb131a449:1010000000000000000000:BIP -52320:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx41f93b51f87b1c4b4d4230b5f2d3dd1188d3fa5e:101000000000000000000:BIP -52440:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mxc37ee66efbf36025d6b481e661b55d3a52ef817e:101847756969931054261:BIP -52440:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mxf8ff98415480e1972fddc80ddf8e3bd2be5ecbed:103799165465886561765:BIP -52680:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxf6b4e7245ab3ce3d76bf522490322aa270653b84:5148709312628042447928:BIP -52680:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx51ffc60c86c29e2250f30e2b19169a526b65edaf:1000000000000000000:4DREAM -52680:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxd79b89e6f0e8ef45ffc8da70810e7fb74b68b6d3:1000000000000000000:4DREAM -52680:Mp02bc3c3f77d5ab9732ef9fc3801a6d72dc18f88328c14dc735648abfe551f50f:Mx41f93b51f87b1c4b4d4230b5f2d3dd1188d3fa5e:1001000000000000000000:BIP -52920:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx7d47a4a24588088f1af565e4e383877733a335d9:1000000000000000000:4DREAM -52920:Mp02bc3c3f77d5ab9732ef9fc3801a6d72dc18f88328c14dc735648abfe551f50f:Mx8036617bf70954c9139f7156866c9975e4ccbb08:4000000000000000000000:FREEDOM -53040:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mxd1399b428b1f6f855bebe2bf2a57f77ccf233df2:114785367435876917650:BIP -53520:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx0a58d2d5de600efec190893c7f45ac4387051836:5267062284092328550:BIP -53520:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxf559a0609425bb8a41c5a275d6b7e65607de9321:390161883257509598932:WILDBIT -53520:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx57b20f1004438a2539c851d02704081944d76016:75000000000000000000:TRADERS -53520:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx8383a7c2057dc71c2f7328f3c0bfc6fc82533c6c:20000000000000000000:BIP -53640:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx4bc5be896635ac43c8b7cb61f2772cff4d606b17:37071089542645362610:MPRO -53880:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx705ede3cf7d49f664b31db5c0ce795d8afd0addf:1127526700871423569720:FRANKLIN -53880:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mxe7ab556dcd6474911aa995c0a2d07795ac096d3c:254999854671847786623911:ALPHA -54120:Mp4926c68cec9b85d743810c801c35c33bd3d1e74ae0a801e4e08998e656835727:Mx8036617bf70954c9139f7156866c9975e4ccbb08:2000953169641907344853:FREEDOM -54360:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx047f300ee314b9b3498657b8d73ac85aa7144032:1000000000000000000000:BIP -54360:Mp5e3e1da62c7eabd9d8d168a36a92727fc1970a54ec61eadd285d4199c41191d7:Mxfda2f0143fbc896c6dac4fa50714661f93187b44:1420729236340788392766:FREEDOM -54480:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx047f300ee314b9b3498657b8d73ac85aa7144032:640000000000000000000:BIP -54600:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxc2836035e7d25658cfa229646d77f4a1a07e6cca:16239040671383714957:KARAT -54817:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx57b20f1004438a2539c851d02704081944d76016:419729584279382637:BIPNET -54817:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxd7e9ed48a659c0cd0f7faf48e5502057ccdd6942:50000000000000000000:BIP -54943:Mp7779ec1c6492e7c71a36f4009d7ee5a43fed2fe4048882b8a099e748869f0777:Mx161522eacb8ace354d3dbce39d7ed60b7d601477:70329055830012847302:BIP -55080:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx49ee05172a871d69ed20540015103fa5fa901917:80000000000000000000:ROCKNROLL -55080:Mp92d05e745464f4d17a12440f48d73dddf8135e45cf91a7e3c4bcacdb2cc1c99f:Mxbde0012c075024e87fb66ab3ad014b6b81db8c3d:31000000000000000000:BIZXBOX -55200:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mxab0659c1f6b8b535712376278ef11b62397669de:6768841063763402356493:FREEDOM -55320:Mpa70d12c096cb459e7c191be0dffb1a7dbe4a9587bfa7174c654959e5e9da7203:Mxf533360a79da177f834a9667596a523402beae8b:3000000000000000000:CASHXCASH -55320:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mxb098961f76be4d533509bca197d97b067cdc43e7:55705920774912805403:WILDBIT -55680:Mpeee9614b63a7ed6370ccd1fa227222fa30d6106770145c55bd4b482b88888888:Mx629e48e818797596f3e75929eccb7bdbd25e892e:10287900000000000000:BIP -55680:Mp02bc3c3f77d5ab9732ef9fc3801a6d72dc18f88328c14dc735648abfe551f50f:Mx63b524c1136ce92e235e2ad1ac32f39949fae345:334800859985912571117368:BIGCOIN -55800:Mp02bc3c3f77d5ab9732ef9fc3801a6d72dc18f88328c14dc735648abfe551f50f:Mxee3c4bf8265b8cbedb361fc46b209aa8a0fd997e:10000000000000000000:BIP -55920:Mpeee9614b63a7ed6370ccd1fa227222fa30d6106770145c55bd4b482b88888888:Mxd09a11b45aa8f52813a14a56f841e466f0e44266:66270553501143815:POPE -56160:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx51926e5d89e582433881c9bda6d82df0dc7bb166:3010000000000000000000:FRANKLIN -56280:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx8504b25a26939f48a3f8877ff1646b9b5d33129c:100000000000000000000:BIP -56280:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx381588dddb6736e1596b76da5d1e86e9fc5bf3bb:59800000000000000000:BIP -56280:Mpeee9614b63a7ed6370ccd1fa227222fa30d6106770145c55bd4b482b88888888:Mx629e48e818797596f3e75929eccb7bdbd25e892e:10000000000000000000:BIP -56400:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx938d9bf3857843d976c2f2e1b11a3179aa4b69e8:1000000000000000000000:BIP -56400:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mx89b2c0f1d6b056aa5e069b92867d414083484e66:102503403763750610145:ALPHA -56400:Mp02bc3c3f77d5ab9732ef9fc3801a6d72dc18f88328c14dc735648abfe551f50f:Mx39cdacf9776c00f13cf10a80e85f1cd967ea08c2:101224672885746066656:BIP -56760:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx55cb82d7085da20abc2bd6cf26447b40521014c0:1000000000000000000:4DREAM -56880:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxa69b27ddca35b3438a9f5abfd170cc79d167f99d:10333522528525841120:KARAT -57000:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx05362cfc04795b81ca94d6fa1ad3919fa26b5d79:2091248449997812476909:NUT -57000:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mx00fc7bf5dfb882794bbc36b44fb0bdfdfd29aed7:1500000000000000000000000:ETERNITY -57360:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx381588dddb6736e1596b76da5d1e86e9fc5bf3bb:545000000000000000000:BIP -57720:Mp1ada5ac409b965623bf6a4320260190038ae27230abfb5ebc9158280cdffffff:Mxf8a9843e73585548d982d2858d3697ca0c6158b5:399800000000000000000:BIP -57720:Mp1ada5ac409b965623bf6a4320260190038ae27230abfb5ebc9158280cdffffff:Mx87cb13fbb3607282e91ab27c01a436c9a9390535:44355983558951213109:FRANKLIN -57720:Mp1ada5ac409b965623bf6a4320260190038ae27230abfb5ebc9158280cdffffff:Mx87cb13fbb3607282e91ab27c01a436c9a9390535:15162853093488807771:KARAT -57960:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mx49ee05172a871d69ed20540015103fa5fa901917:600000000000000000000:BIP -58200:Mp2cbade2b08501047bb9d2a08abeee21e276cb0e027e84e3a526ede85c4cbd442:Mxf277a5dd1fc8dc70b1aef6b81e8fcdabee463494:10700000000000000000:LOVECOIN -58200:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mx938d9bf3857843d976c2f2e1b11a3179aa4b69e8:200000000000000000000:BIP -58320:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mx11a013438124097b2baf17bcd8737c8c177ef8de:1000000000000000000:BIP -58440:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx938d9bf3857843d976c2f2e1b11a3179aa4b69e8:290000000000000000000:BIP -58560:Mpeee9614b63a7ed6370ccd1fa227222fa30d6106770145c55bd4b482b88888888:Mxa50ae74607930530430c61ca246120fefeab8d0c:1300000000000000000000:BIP -58680:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx6cc4c2b7e2aab57350c697f48048b3a0a6a6055d:600000000000000000000:BIP -58680:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mxf9fc891309605917b4127ac151eb31a9e44637e6:2008000000000000000000:ALPHA -58680:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxb0bdfa9aa7512a87da4dcbc44b2391cca5f89e8b:734541154582255964606:BIP -58920:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mxb9b20e085a581d42f74101399b8d65c7753643dc:60000000000000000000:MPRO -59280:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mxb8229efbccbfede7d668b48e5f30f0744e961408:480000000000000000000:BIP -59400:Mp120c15e48aed0ac866a1a918bd367cfa31909a6b09f328a18bd18f32edef2be8:Mxfc59af550e6360a90d71ab7b55f50f2f8cfdaa89:350000000000000000000:GENESIS -59520:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxa4ca13d5831e095aaedc08f172977805e215d34c:235754514054095950301:BIP -59520:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mx065f5324316c467103ad8e8c721b9b7f2b26836c:19739348224325625487:BIP -59640:Mp2c827f0365d6592b5377b771d36cb6b1006ca13243122476800febab59b4a2e9:Mx81855472acef3c71d30b880830b350f36742dec8:87591097527093558566:ALPHA -60120:Mp7779ec1c6492e7c71a36f4009d7ee5a43fed2fe4048882b8a099e748869f0777:Mxe6e7502505db2fd77d827a3466ad4341396a99d2:1000000000000000000000:ROCKNROLL -60240:Mp1ada5ac409b965623bf6a4320260190038ae27230abfb5ebc9158280cdffffff:Mx87cb13fbb3607282e91ab27c01a436c9a9390535:56218416172736415259:TRADERS -60600:Mp02ff680cbea3fb95f547bddde69c9150b3b7ab8d1c5c2a1bf94ccb70bf073b2c:Mx1ddf11baaf6e169949a903cb199487a104cdf167:20000000000000000000:2RICH -60600:Mp00454817134295dc6d39517672b2467ee8301a836216ace04bf0cf3910000000:Mx3d0f5efad5ee44bbf9a9327c67b5f85f85ab6e69:1000000000000000000:LOVECOIN -60600:Mp00454817134295dc6d39517672b2467ee8301a836216ace04bf0cf3910000000:Mx390f3d312f1b5999217ec5fddd1ec32d0188dbbc:20045000000000000000000:WILDBIT -60840:Mpfe176f944623a8ca9f409a62f0ea3ca75c1cf8d89970adf9384fc9ae8d77fa0b:Mx03f0a3dfc3f933f01ad73011a04ec782f04c1088:31000800000000000000000:BIP -60840:Mpc6df0dd44cae3cb49ee0ef8bd78750b961e64e231e6dfdc22fbd8e0c476d66d2:Mx183c6d4e55f4a0b1c0ae22f99ee1c0e0211dfce0:10000000000000000000:ROCKNROLL -60840:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxa3cee87f82b9c796e902caf2ac9410e909b072a9:212153044468361763535:SAFECOIN -60960:Mpeee9614b63a7ed6370ccd1fa227222fa30d6106770145c55bd4b482b88888888:Mxdd587dad689a72b1be371932f52b6dc8cbfc584a:3254768990000000000000000:EMPIRE -60960:Mp00454817134295dc6d39517672b2467ee8301a836216ace04bf0cf3910000000:Mx2bd36881a63611e07cdeb073fb601e7021eb668b:24286522037138846422704:WILDBIT -61200:Mp4926c68cec9b85d743810c801c35c33bd3d1e74ae0a801e4e08998e656835727:Mx22c127fdb84e9f4f71a1a1a7be20d6a0ac17cdcd:1004158037577:MATRIX -61320:Mpd7a9eae76d3e98145b6b897c00c407b42ae8c42f937527ebdcd0239a4d88c0a5:Mxbee8d34f238e3561cd52710f726ef575834cbebe:10625060778296898000:BIP -61560:Mp02ff680cbea3fb95f547bddde69c9150b3b7ab8d1c5c2a1bf94ccb70bf073b2c:Mxe2214434df155bb122c42fe87925eeee5c1788ed:14770000000000000000:BIP -61680:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx916ba692019f1bec85aa1b19be91f12e2b7b66f4:50000000000000000000000:KRFCOIN -61800:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx13f2b88bf48e6ff16af3718069a31b0f7bdd604a:400693287485955378433:PIZZA -61800:Mp88883bcd4e9a4eeb7f5a7b7d1f4c02ac0fadc268824694fcccc84e39f4e08888:Mx6abef0c4e2b50f2438971e36fc8a27a4e5ff10af:2000000000000000000:LOVECOIN -61920:Mp03478aae43a1a660573fab0763ae44492cdaf8deffc3fcbcc844acd67dfb2db6:Mxc4e4e5ca42b20e25fa167f0229197806c9d76fa3:800000000000000000000:BIP -62040:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mx832fe661435e61aa7b00e6ee5481d9dfa459406a:138356434058965219962:ZENNOROBOT -62160:Mp1ada5ac409b965623bf6a4320260190038ae27230abfb5ebc9158280cdffffff:Mx94fa414f99831784b29f7763dbde610b2f60e5ef:299960185501040069045258:BIP -63960:Mpd7a9eae76d3e98145b6b897c00c407b42ae8c42f937527ebdcd0239a4d88c0a5:Mxb550c550bf538858e95fa594291c85c004601c41:570000000000000000000:BIP -69840:Mp4881ad167ca5fb5886322841f992d68aed894ffcb58abc080e8ad3b156f1045b:Mxf5755f152ca461796ea64d311bfeac9c1113433b:1110772217949376359725:BIP -76920:Mpd7a9eae76d3e98145b6b897c00c407b42ae8c42f937527ebdcd0239a4d88c0a5:Mxb4d201fb7a03686f13277c566db323aea6aa0631:10426743932470850000:BIP -88560:Mp00454817134295dc6d39517672b2467ee8301a836216ace04bf0cf3910000000:Mx8017588598dad6323c1d4c7814aa99bc972b20c3:8452723075253212652730:WILDBIT` - - lines := strings.Split(list, "\n") - for _, line := range lines { - data := strings.Split(line, ":") - pubkey := types.HexToPubkey(data[1]) - owner := types.HexToAddress(data[2]) - value := helpers.StringToBigInt(data[3]) - coin := types.StrToCoinSymbol(data[4]) - - events.AddEvent(upgrades.UpgradeBlock3, &eventsdb.UnbondEvent{ - Address: owner, - Amount: value.String(), - Coin: coin, - ValidatorPubKey: pubkey, - }) - state.Accounts.AddBalance(owner, coin, value) - state.Checker.AddCoin(coin, big.NewInt(0).Neg(value)) - } -} diff --git a/core/minter/upgrade3_test.go b/core/minter/upgrade3_test.go deleted file mode 100644 index 04b2410d3..000000000 --- a/core/minter/upgrade3_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package minter - -import ( - eventsdb "github.com/MinterTeam/minter-go-node/core/events" - "github.com/MinterTeam/minter-go-node/core/state" - "github.com/MinterTeam/minter-go-node/core/types" - "github.com/MinterTeam/minter-go-node/helpers" - db "github.com/tendermint/tm-db" - "testing" -) - -func TestApplyUpgrade3(t *testing.T) { - cState := getState() - - ApplyUpgrade3(cState, emptyEvents{}) - - address := types.HexToAddress("Mx8f16fe070b065b958fa6865bd549193827abc0f8") - - { - targetBalance := helpers.StringToBigInt("5000000000000000000000") - balance := cState.Accounts.GetBalance(address, types.StrToCoinSymbol("FUFELL14")) - if balance.Cmp(targetBalance) != 0 { - t.Fatalf("Balance of %s is not correct", address) - } - } - - { - targetBalance := helpers.StringToBigInt("85000000000000000000000") - balance := cState.Accounts.GetBalance(address, types.StrToCoinSymbol("VEXILIFERR")) - if balance.Cmp(targetBalance) != 0 { - t.Fatalf("Balance of %s is not correct", address) - } - } - - if err := cState.Check(); err != nil { - t.Fatal(err) - } -} - -func getState() *state.State { - s, err := state.NewState(0, db.NewMemDB(), emptyEvents{}, 1, 1) - - if err != nil { - panic(err) - } - - return s -} - -type emptyEvents struct{} - -func (e emptyEvents) AddEvent(height uint32, event eventsdb.Event) {} -func (e emptyEvents) LoadEvents(height uint32) eventsdb.Events { return eventsdb.Events{} } -func (e emptyEvents) CommitEvents() error { return nil } diff --git a/core/state/accounts/accounts.go b/core/state/accounts/accounts.go index 6a84ba51b..f7ad97f4a 100644 --- a/core/state/accounts/accounts.go +++ b/core/state/accounts/accounts.go @@ -22,8 +22,8 @@ type RAccounts interface { Export(state *types.AppState) GetAccount(address types.Address) *Model GetNonce(address types.Address) uint64 - GetBalance(address types.Address, coin types.CoinSymbol) *big.Int - GetBalances(address types.Address) map[types.CoinSymbol]*big.Int + GetBalance(address types.Address, coin types.CoinID) *big.Int + GetBalances(address types.Address) map[types.CoinID]*big.Int ExistsMultisig(msigAddress types.Address) bool } @@ -91,7 +91,7 @@ func (a *Accounts) Commit() error { path := []byte{mainPrefix} path = append(path, address[:]...) path = append(path, balancePrefix) - path = append(path, coin[:]...) + path = append(path, coin.Bytes()...) balance := account.getBalance(coin) if balance.Cmp(big.NewInt(0)) == 0 { @@ -101,7 +101,7 @@ func (a *Accounts) Commit() error { } } - account.dirtyBalances = map[types.CoinSymbol]struct{}{} + account.dirtyBalances = map[types.CoinID]struct{}{} } } @@ -121,12 +121,12 @@ func (a *Accounts) getOrderedDirtyAccounts() []types.Address { return keys } -func (a *Accounts) AddBalance(address types.Address, coin types.CoinSymbol, amount *big.Int) { +func (a *Accounts) AddBalance(address types.Address, coin types.CoinID, amount *big.Int) { balance := a.GetBalance(address, coin) a.SetBalance(address, coin, big.NewInt(0).Add(balance, amount)) } -func (a *Accounts) GetBalance(address types.Address, coin types.CoinSymbol) *big.Int { +func (a *Accounts) GetBalance(address types.Address, coin types.CoinID) *big.Int { account := a.getOrNew(address) if !account.hasCoin(coin) { return big.NewInt(0) @@ -138,7 +138,7 @@ func (a *Accounts) GetBalance(address types.Address, coin types.CoinSymbol) *big path := []byte{mainPrefix} path = append(path, address[:]...) path = append(path, balancePrefix) - path = append(path, coin[:]...) + path = append(path, coin.Bytes()...) _, enc := a.iavl.Get(path) if len(enc) != 0 { @@ -151,12 +151,12 @@ func (a *Accounts) GetBalance(address types.Address, coin types.CoinSymbol) *big return big.NewInt(0).Set(account.balances[coin]) } -func (a *Accounts) SubBalance(address types.Address, coin types.CoinSymbol, amount *big.Int) { +func (a *Accounts) SubBalance(address types.Address, coin types.CoinID, amount *big.Int) { balance := big.NewInt(0).Sub(a.GetBalance(address, coin), amount) a.SetBalance(address, coin, balance) } -func (a *Accounts) SetBalance(address types.Address, coin types.CoinSymbol, amount *big.Int) { +func (a *Accounts) SetBalance(address types.Address, coin types.CoinID, amount *big.Int) { account := a.getOrNew(address) oldBalance := a.GetBalance(address, coin) a.bus.Checker().AddCoin(coin, big.NewInt(0).Sub(amount, oldBalance)) @@ -201,10 +201,10 @@ func (a *Accounts) CreateMultisig(weights []uint, addresses []types.Address, thr Nonce: 0, MultisigData: msig, address: address, - coins: []types.CoinSymbol{}, - balances: map[types.CoinSymbol]*big.Int{}, + coins: []types.CoinID{}, + balances: map[types.CoinID]*big.Int{}, markDirty: a.markDirty, - dirtyBalances: map[types.CoinSymbol]struct{}{}, + dirtyBalances: map[types.CoinID]struct{}{}, } } @@ -238,9 +238,9 @@ func (a *Accounts) get(address types.Address) *Model { } account.address = address - account.balances = map[types.CoinSymbol]*big.Int{} + account.balances = map[types.CoinID]*big.Int{} account.markDirty = a.markDirty - account.dirtyBalances = map[types.CoinSymbol]struct{}{} + account.dirtyBalances = map[types.CoinID]struct{}{} // load coins path = []byte{mainPrefix} @@ -248,7 +248,7 @@ func (a *Accounts) get(address types.Address) *Model { path = append(path, coinsPrefix) _, enc = a.iavl.Get(path) if len(enc) != 0 { - var coins []types.CoinSymbol + var coins []types.CoinID if err := rlp.DecodeBytes(enc, &coins); err != nil { panic(fmt.Sprintf("failed to decode coins list at address %s: %s", address.String(), err)) } @@ -266,10 +266,10 @@ func (a *Accounts) getOrNew(address types.Address) *Model { account = &Model{ Nonce: 0, address: address, - coins: []types.CoinSymbol{}, - balances: map[types.CoinSymbol]*big.Int{}, + coins: []types.CoinID{}, + balances: map[types.CoinID]*big.Int{}, markDirty: a.markDirty, - dirtyBalances: map[types.CoinSymbol]struct{}{}, + dirtyBalances: map[types.CoinID]struct{}{}, isNew: true, } a.setToMap(address, account) @@ -284,10 +284,10 @@ func (a *Accounts) GetNonce(address types.Address) uint64 { return account.Nonce } -func (a *Accounts) GetBalances(address types.Address) map[types.CoinSymbol]*big.Int { +func (a *Accounts) GetBalances(address types.Address) map[types.CoinID]*big.Int { account := a.getOrNew(address) - balances := make(map[types.CoinSymbol]*big.Int, len(account.coins)) + balances := make(map[types.CoinID]*big.Int, len(account.coins)) for _, coin := range account.coins { balances[coin] = a.GetBalance(address, coin) } @@ -295,14 +295,14 @@ func (a *Accounts) GetBalances(address types.Address) map[types.CoinSymbol]*big. return balances } -func (a *Accounts) DeleteCoin(address types.Address, symbol types.CoinSymbol) { - balance := a.GetBalance(address, symbol) - coin := a.bus.Coins().GetCoin(symbol) +func (a *Accounts) DeleteCoin(address types.Address, id types.CoinID) { + balance := a.GetBalance(address, id) + coin := a.bus.Coins().GetCoin(id) ret := formula.CalculateSaleReturn(coin.Volume, coin.Reserve, 100, balance) - a.AddBalance(address, types.GetBaseCoin(), ret) - a.SetBalance(address, symbol, big.NewInt(0)) + a.AddBalance(address, types.GetBaseCoinID(), ret) + a.SetBalance(address, id, big.NewInt(0)) } func (a *Accounts) markDirty(addr types.Address) { diff --git a/core/state/accounts/bus.go b/core/state/accounts/bus.go index 9bbcbc08c..1062bf201 100644 --- a/core/state/accounts/bus.go +++ b/core/state/accounts/bus.go @@ -13,10 +13,10 @@ func NewBus(accounts *Accounts) *Bus { return &Bus{accounts: accounts} } -func (b *Bus) DeleteCoin(address types.Address, coin types.CoinSymbol) { +func (b *Bus) DeleteCoin(address types.Address, coin types.CoinID) { b.accounts.DeleteCoin(address, coin) } -func (b *Bus) AddBalance(address types.Address, coin types.CoinSymbol, value *big.Int) { +func (b *Bus) AddBalance(address types.Address, coin types.CoinID, value *big.Int) { b.accounts.AddBalance(address, coin, value) } diff --git a/core/state/accounts/model.go b/core/state/accounts/model.go index 307773997..38f80205d 100644 --- a/core/state/accounts/model.go +++ b/core/state/accounts/model.go @@ -14,11 +14,11 @@ type Model struct { MultisigData Multisig address types.Address - coins []types.CoinSymbol - balances map[types.CoinSymbol]*big.Int + coins []types.CoinID + balances map[types.CoinID]*big.Int hasDirtyCoins bool - dirtyBalances map[types.CoinSymbol]struct{} + dirtyBalances map[types.CoinID]struct{} isDirty bool // nonce or multisig data isNew bool @@ -60,7 +60,7 @@ func (model *Model) setNonce(nonce uint64) { model.markDirty(model.address) } -func (model *Model) getBalance(coin types.CoinSymbol) *big.Int { +func (model *Model) getBalance(coin types.CoinID) *big.Int { return model.balances[coin] } @@ -68,13 +68,13 @@ func (model *Model) hasDirtyBalances() bool { return len(model.dirtyBalances) > 0 } -func (model *Model) isBalanceDirty(coin types.CoinSymbol) bool { +func (model *Model) isBalanceDirty(coin types.CoinID) bool { _, exists := model.dirtyBalances[coin] return exists } -func (model *Model) getOrderedCoins() []types.CoinSymbol { - keys := make([]types.CoinSymbol, 0, len(model.balances)) +func (model *Model) getOrderedCoins() []types.CoinID { + keys := make([]types.CoinID, 0, len(model.balances)) for k := range model.balances { keys = append(keys, k) } @@ -86,13 +86,13 @@ func (model *Model) getOrderedCoins() []types.CoinSymbol { return keys } -func (model *Model) setBalance(coin types.CoinSymbol, amount *big.Int) { +func (model *Model) setBalance(coin types.CoinID, amount *big.Int) { if amount.Cmp(big.NewInt(0)) == 0 { if !model.hasCoin(coin) { return } - var newCoins []types.CoinSymbol + var newCoins []types.CoinID for _, c := range model.coins { if coin == c { continue @@ -119,7 +119,7 @@ func (model *Model) setBalance(coin types.CoinSymbol, amount *big.Int) { model.balances[coin] = amount } -func (model *Model) hasCoin(coin types.CoinSymbol) bool { +func (model *Model) hasCoin(coin types.CoinID) bool { for _, c := range model.coins { if c == coin { return true diff --git a/core/state/app/app.go b/core/state/app/app.go index 12d3cfa51..2f26a9e4b 100644 --- a/core/state/app/app.go +++ b/core/state/app/app.go @@ -15,6 +15,7 @@ type RApp interface { Export(state *types.AppState, height uint64) GetMaxGas() uint64 GetTotalSlashed() *big.Int + GetCoinsCount() uint64 } func (v *App) Tree() tree.ReadOnlyTree { @@ -78,7 +79,7 @@ func (v *App) AddTotalSlashed(amount *big.Int) { model := v.getOrNew() model.setTotalSlashed(big.NewInt(0).Add(model.getTotalSlashed(), amount)) - v.bus.Checker().AddCoin(types.GetBaseCoin(), amount) + v.bus.Checker().AddCoin(types.GetBaseCoinID(), amount) } func (v *App) get() *Model { @@ -107,6 +108,7 @@ func (v *App) getOrNew() *Model { if model == nil { model = &Model{ TotalSlashed: big.NewInt(0), + CoinsCount: 0, MaxGas: 0, markDirty: v.markDirty, } @@ -124,6 +126,14 @@ func (v *App) SetTotalSlashed(amount *big.Int) { v.getOrNew().setTotalSlashed(amount) } +func (v *App) GetCoinsCount() uint64 { + return v.getOrNew().getCoinsCount() +} + +func (v *App) SetCoinsCount(count uint64) { + v.getOrNew().setCoinsCount(count) +} + func (v *App) Export(state *types.AppState, height uint64) { state.MaxGas = v.GetMaxGas() state.TotalSlashed = v.GetTotalSlashed().String() diff --git a/core/state/app/model.go b/core/state/app/model.go index d502226f7..53374413c 100644 --- a/core/state/app/model.go +++ b/core/state/app/model.go @@ -4,6 +4,7 @@ import "math/big" type Model struct { TotalSlashed *big.Int + CoinsCount uint64 MaxGas uint64 markDirty func() @@ -34,3 +35,15 @@ func (model *Model) setTotalSlashed(totalSlashed *big.Int) { } model.TotalSlashed = totalSlashed } + +func (model *Model) getCoinsCount() uint64 { + return model.CoinsCount +} + +func (model *Model) setCoinsCount(count uint64) { + if model.CoinsCount != count { + model.markDirty() + } + + model.CoinsCount = count +} diff --git a/core/state/bus/accounts.go b/core/state/bus/accounts.go index 888f55bc6..5fd807a45 100644 --- a/core/state/bus/accounts.go +++ b/core/state/bus/accounts.go @@ -6,6 +6,6 @@ import ( ) type Accounts interface { - DeleteCoin(types.Address, types.CoinSymbol) - AddBalance(types.Address, types.CoinSymbol, *big.Int) + DeleteCoin(types.Address, types.CoinID) + AddBalance(types.Address, types.CoinID, *big.Int) } diff --git a/core/state/bus/candidates.go b/core/state/bus/candidates.go index c1c90c1f1..5717e2226 100644 --- a/core/state/bus/candidates.go +++ b/core/state/bus/candidates.go @@ -16,7 +16,7 @@ type Candidates interface { type Stake struct { Owner types.Address Value *big.Int - Coin types.CoinSymbol + Coin types.CoinID BipValue *big.Int } diff --git a/core/state/bus/checker.go b/core/state/bus/checker.go index 5c4390be3..b110cc7c5 100644 --- a/core/state/bus/checker.go +++ b/core/state/bus/checker.go @@ -6,6 +6,6 @@ import ( ) type Checker interface { - AddCoin(types.CoinSymbol, *big.Int, ...string) - AddCoinVolume(types.CoinSymbol, *big.Int) + AddCoin(types.CoinID, *big.Int, ...string) + AddCoinVolume(types.CoinID, *big.Int) } diff --git a/core/state/bus/coins.go b/core/state/bus/coins.go index 0a25a10cf..750c83bf4 100644 --- a/core/state/bus/coins.go +++ b/core/state/bus/coins.go @@ -6,12 +6,13 @@ import ( ) type Coins interface { - GetCoin(types.CoinSymbol) *Coin - SubCoinVolume(types.CoinSymbol, *big.Int) - SubCoinReserve(types.CoinSymbol, *big.Int) + GetCoin(types.CoinID) *Coin + SubCoinVolume(types.CoinID, *big.Int) + SubCoinReserve(types.CoinID, *big.Int) } type Coin struct { + ID types.CoinID Name string Crr uint Symbol types.CoinSymbol diff --git a/core/state/bus/frozenfunds.go b/core/state/bus/frozenfunds.go index 2ec11f946..ec3a1d1fa 100644 --- a/core/state/bus/frozenfunds.go +++ b/core/state/bus/frozenfunds.go @@ -6,5 +6,5 @@ import ( ) type FrozenFunds interface { - AddFrozenFund(uint64, types.Address, types.Pubkey, types.CoinSymbol, *big.Int) + AddFrozenFund(uint64, types.Address, types.Pubkey, types.CoinID, *big.Int) } diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index f9238716f..9091fe519 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -33,9 +33,9 @@ type RCandidates interface { Export(state *types.AppState) Exists(pubkey types.Pubkey) bool Count() int - IsNewCandidateStakeSufficient(coin types.CoinSymbol, stake *big.Int, limit int) bool - IsDelegatorStakeSufficient(address types.Address, pubkey types.Pubkey, coin types.CoinSymbol, amount *big.Int) bool - GetStakeValueOfAddress(pubkey types.Pubkey, address types.Address, coin types.CoinSymbol) *big.Int + IsNewCandidateStakeSufficient(coin types.CoinID, stake *big.Int, limit int) bool + IsDelegatorStakeSufficient(address types.Address, pubkey types.Pubkey, coin types.CoinID, amount *big.Int) bool + GetStakeValueOfAddress(pubkey types.Pubkey, address types.Address, coin types.CoinID) *big.Int GetCandidateOwner(pubkey types.Pubkey) types.Address GetTotalStake(pubkey types.Pubkey) *big.Int LoadCandidates() @@ -203,8 +203,8 @@ func (c *Candidates) PunishByzantineCandidate(height uint64, tmAddress types.TmA coin := c.bus.Coins().GetCoin(stake.Coin) ret := formula.CalculateSaleReturn(coin.Volume, coin.Reserve, coin.Crr, slashed) - c.bus.Coins().SubCoinVolume(coin.Symbol, slashed) - c.bus.Coins().SubCoinReserve(coin.Symbol, ret) + c.bus.Coins().SubCoinVolume(coin.ID, slashed) + c.bus.Coins().SubCoinReserve(coin.ID, ret) c.bus.App().AddTotalSlashed(ret) c.bus.Checker().AddCoin(stake.Coin, big.NewInt(0).Neg(ret)) @@ -549,7 +549,7 @@ func (c *Candidates) Count() int { return len(c.list) } -func (c *Candidates) IsNewCandidateStakeSufficient(coin types.CoinSymbol, stake *big.Int, limit int) bool { +func (c *Candidates) IsNewCandidateStakeSufficient(coin types.CoinID, stake *big.Int, limit int) bool { c.lock.RLock() defer c.lock.RUnlock() @@ -577,7 +577,7 @@ func (c *Candidates) GetCandidate(pubkey types.Pubkey) *Candidate { return c.getFromMap(pubkey) } -func (c *Candidates) IsDelegatorStakeSufficient(address types.Address, pubkey types.Pubkey, coin types.CoinSymbol, amount *big.Int) bool { +func (c *Candidates) IsDelegatorStakeSufficient(address types.Address, pubkey types.Pubkey, coin types.CoinID, amount *big.Int) bool { stakes := c.GetStakes(pubkey) if len(stakes) < MaxDelegatorsPerCandidate { return true @@ -593,7 +593,7 @@ func (c *Candidates) IsDelegatorStakeSufficient(address types.Address, pubkey ty return false } -func (c *Candidates) Delegate(address types.Address, pubkey types.Pubkey, coin types.CoinSymbol, value *big.Int, bipValue *big.Int) { +func (c *Candidates) Delegate(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int, bipValue *big.Int) { stake := &Stake{ Owner: address, Coin: coin, @@ -621,7 +621,7 @@ func (c *Candidates) SetOffline(pubkey types.Pubkey) { c.getFromMap(pubkey).setStatus(CandidateStatusOffline) } -func (c *Candidates) SubStake(address types.Address, pubkey types.Pubkey, coin types.CoinSymbol, value *big.Int) { +func (c *Candidates) SubStake(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { stake := c.GetStakeOfAddress(pubkey, address, coin) stake.subValue(value) c.bus.Checker().AddCoin(coin, big.NewInt(0).Neg(value)) @@ -673,7 +673,7 @@ func (c *Candidates) StakesCount(pubkey types.Pubkey) int { return c.GetCandidate(pubkey).stakesCount } -func (c *Candidates) GetStakeOfAddress(pubkey types.Pubkey, address types.Address, coin types.CoinSymbol) *Stake { +func (c *Candidates) GetStakeOfAddress(pubkey types.Pubkey, address types.Address, coin types.CoinID) *Stake { candidate := c.GetCandidate(pubkey) for _, stake := range candidate.stakes { if stake == nil { @@ -688,7 +688,7 @@ func (c *Candidates) GetStakeOfAddress(pubkey types.Pubkey, address types.Addres return nil } -func (c *Candidates) GetStakeValueOfAddress(pubkey types.Pubkey, address types.Address, coin types.CoinSymbol) *big.Int { +func (c *Candidates) GetStakeValueOfAddress(pubkey types.Pubkey, address types.Address, coin types.CoinID) *big.Int { stake := c.GetStakeOfAddress(pubkey, address, coin) if stake == nil { return nil @@ -742,8 +742,8 @@ func (c *Candidates) LoadStakes() { } } -func (c *Candidates) calculateBipValue(coinSymbol types.CoinSymbol, amount *big.Int, includeSelf, includeUpdates bool, coinsCache *coinsCache) *big.Int { - if coinSymbol.IsBaseCoin() { +func (c *Candidates) calculateBipValue(CoinID types.CoinID, amount *big.Int, includeSelf, includeUpdates bool, coinsCache *coinsCache) *big.Int { + if CoinID.IsBaseCoin() { return big.NewInt(0).Set(amount) } @@ -754,30 +754,30 @@ func (c *Candidates) calculateBipValue(coinSymbol types.CoinSymbol, amount *big. var totalPower *big.Int - if coinsCache.Exists(coinSymbol) { - totalPower, totalAmount = coinsCache.Get(coinSymbol) + if coinsCache.Exists(CoinID) { + totalPower, totalAmount = coinsCache.Get(CoinID) } else { candidates := c.GetCandidates() for _, candidate := range candidates { for _, stake := range candidate.stakes { - if stake != nil && stake.Coin == coinSymbol { + if stake != nil && stake.Coin == CoinID { totalAmount.Add(totalAmount, stake.Value) } } if includeUpdates { for _, update := range candidate.updates { - if update.Coin == coinSymbol { + if update.Coin == CoinID { totalAmount.Add(totalAmount, update.Value) } } } } - coin := c.bus.Coins().GetCoin(coinSymbol) + coin := c.bus.Coins().GetCoin(CoinID) totalPower = formula.CalculateSaleReturn(coin.Volume, coin.Reserve, coin.Crr, totalAmount) - coinsCache.Set(coinSymbol, totalPower, totalAmount) + coinsCache.Set(CoinID, totalPower, totalAmount) } return big.NewInt(0).Div(big.NewInt(0).Mul(totalPower, amount), totalAmount) @@ -801,8 +801,8 @@ func (c *Candidates) Punish(height uint64, address types.TmAddress) *big.Int { coin := c.bus.Coins().GetCoin(stake.Coin) ret := formula.CalculateSaleReturn(coin.Volume, coin.Reserve, coin.Crr, slashed) - c.bus.Coins().SubCoinVolume(coin.Symbol, slashed) - c.bus.Coins().SubCoinReserve(coin.Symbol, ret) + c.bus.Coins().SubCoinVolume(coin.ID, slashed) + c.bus.Coins().SubCoinReserve(coin.ID, ret) c.bus.App().AddTotalSlashed(ret) c.bus.Checker().AddCoin(stake.Coin, big.NewInt(0).Neg(ret)) diff --git a/core/state/candidates/model.go b/core/state/candidates/model.go index 6b6830b09..eb94fbe3b 100644 --- a/core/state/candidates/model.go +++ b/core/state/candidates/model.go @@ -166,7 +166,7 @@ func (candidate *Candidate) SetStakeAtIndex(index int, stake *Stake, isDirty boo type Stake struct { Owner types.Address - Coin types.CoinSymbol + Coin types.CoinID Value *big.Int BipValue *big.Int @@ -192,7 +192,7 @@ func (stake *Stake) setBipValue(value *big.Int) { stake.BipValue.Set(value) } -func (stake *Stake) setNewOwner(coin types.CoinSymbol, owner types.Address) { +func (stake *Stake) setNewOwner(coin types.CoinID, owner types.Address) { stake.Coin = coin stake.Owner = owner stake.BipValue = big.NewInt(0) @@ -205,17 +205,17 @@ func (stake *Stake) setValue(ret *big.Int) { stake.Value.Set(ret) } -func (stake *Stake) setCoin(coin types.CoinSymbol) { +func (stake *Stake) setCoin(coin types.CoinID) { stake.markDirty(stake.index) stake.Coin = coin } type coinsCache struct { - list map[types.CoinSymbol]*coinsCacheItem + list map[types.CoinID]*coinsCacheItem } func newCoinsCache() *coinsCache { - return &coinsCache{list: map[types.CoinSymbol]*coinsCacheItem{}} + return &coinsCache{list: map[types.CoinID]*coinsCacheItem{}} } type coinsCacheItem struct { @@ -223,29 +223,29 @@ type coinsCacheItem struct { totalAmount *big.Int } -func (c *coinsCache) Exists(symbol types.CoinSymbol) bool { +func (c *coinsCache) Exists(id types.CoinID) bool { if c == nil { return false } - _, exists := c.list[symbol] + _, exists := c.list[id] return exists } -func (c *coinsCache) Get(symbol types.CoinSymbol) (totalPower *big.Int, totalAmount *big.Int) { - return c.list[symbol].totalPower, c.list[symbol].totalAmount +func (c *coinsCache) Get(id types.CoinID) (totalPower *big.Int, totalAmount *big.Int) { + return c.list[id].totalPower, c.list[id].totalAmount } -func (c *coinsCache) Set(symbol types.CoinSymbol, totalPower *big.Int, totalAmount *big.Int) { +func (c *coinsCache) Set(id types.CoinID, totalPower *big.Int, totalAmount *big.Int) { if c == nil { return } - if c.list[symbol] == nil { - c.list[symbol] = &coinsCacheItem{} + if c.list[id] == nil { + c.list[id] = &coinsCacheItem{} } - c.list[symbol].totalAmount = totalAmount - c.list[symbol].totalPower = totalPower + c.list[id].totalAmount = totalAmount + c.list[id].totalPower = totalPower } diff --git a/core/state/checker/checker.go b/core/state/checker/checker.go index d4a953699..8dcd7e327 100644 --- a/core/state/checker/checker.go +++ b/core/state/checker/checker.go @@ -7,21 +7,21 @@ import ( ) type Checker struct { - delta map[types.CoinSymbol]*big.Int - volumeDelta map[types.CoinSymbol]*big.Int + delta map[types.CoinID]*big.Int + volumeDelta map[types.CoinID]*big.Int } func NewChecker(bus *bus.Bus) *Checker { checker := &Checker{ - delta: map[types.CoinSymbol]*big.Int{}, - volumeDelta: map[types.CoinSymbol]*big.Int{}, + delta: map[types.CoinID]*big.Int{}, + volumeDelta: map[types.CoinID]*big.Int{}, } bus.SetChecker(checker) return checker } -func (c *Checker) AddCoin(coin types.CoinSymbol, value *big.Int, msg ...string) { +func (c *Checker) AddCoin(coin types.CoinID, value *big.Int, msg ...string) { cValue, exists := c.delta[coin] if !exists { @@ -32,7 +32,7 @@ func (c *Checker) AddCoin(coin types.CoinSymbol, value *big.Int, msg ...string) cValue.Add(cValue, value) } -func (c *Checker) AddCoinVolume(coin types.CoinSymbol, value *big.Int) { +func (c *Checker) AddCoinVolume(coin types.CoinID, value *big.Int) { cValue, exists := c.volumeDelta[coin] if !exists { @@ -44,14 +44,14 @@ func (c *Checker) AddCoinVolume(coin types.CoinSymbol, value *big.Int) { } func (c *Checker) Reset() { - c.delta = map[types.CoinSymbol]*big.Int{} - c.volumeDelta = map[types.CoinSymbol]*big.Int{} + c.delta = map[types.CoinID]*big.Int{} + c.volumeDelta = map[types.CoinID]*big.Int{} } -func (c *Checker) Deltas() map[types.CoinSymbol]*big.Int { +func (c *Checker) Deltas() map[types.CoinID]*big.Int { return c.delta } -func (c *Checker) VolumeDeltas() map[types.CoinSymbol]*big.Int { +func (c *Checker) VolumeDeltas() map[types.CoinID]*big.Int { return c.volumeDelta } diff --git a/core/state/coins/bus.go b/core/state/coins/bus.go index cd9dd2d56..44242414b 100644 --- a/core/state/coins/bus.go +++ b/core/state/coins/bus.go @@ -14,8 +14,8 @@ func NewBus(coins *Coins) *Bus { return &Bus{coins: coins} } -func (b *Bus) GetCoin(symbol types.CoinSymbol) *bus.Coin { - coin := b.coins.GetCoin(symbol) +func (b *Bus) GetCoin(id types.CoinID) *bus.Coin { + coin := b.coins.GetCoin(id) if coin == nil { return nil } @@ -29,10 +29,10 @@ func (b *Bus) GetCoin(symbol types.CoinSymbol) *bus.Coin { } } -func (b *Bus) SubCoinVolume(symbol types.CoinSymbol, amount *big.Int) { - b.coins.SubVolume(symbol, amount) +func (b *Bus) SubCoinVolume(id types.CoinID, amount *big.Int) { + b.coins.SubVolume(id, amount) } -func (b *Bus) SubCoinReserve(symbol types.CoinSymbol, amount *big.Int) { - b.coins.SubReserve(symbol, amount) +func (b *Bus) SubCoinReserve(id types.CoinID, amount *big.Int) { + b.coins.SubReserve(id, amount) } diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index 4b033bb7e..b4f89012a 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -1,10 +1,11 @@ package coins import ( - "bytes" + "encoding/binary" "fmt" "github.com/MinterTeam/minter-go-node/core/state/bus" "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/rlp" "github.com/MinterTeam/minter-go-node/tree" "math/big" @@ -13,20 +14,22 @@ import ( ) const ( - mainPrefix = byte('q') - infoPrefix = byte('i') + mainPrefix = byte('q') + infoPrefix = byte('i') ) type RCoins interface { Export(state *types.AppState) - Exists(symbol types.CoinSymbol) bool - SubReserve(symbol types.CoinSymbol, amount *big.Int) - GetCoin(symbol types.CoinSymbol) *Model + Exists(id types.CoinID) bool + ExistsBySymbol(symbol types.CoinSymbol) bool + SubReserve(symbol types.CoinID, amount *big.Int) + GetCoin(id types.CoinID) *Model + GetCoinBySymbol(symbol types.CoinSymbol) *Model } type Coins struct { - list map[types.CoinSymbol]*Model - dirty map[types.CoinSymbol]struct{} + list map[types.CoinID]*Model + dirty map[types.CoinID]struct{} bus *bus.Bus iavl tree.MTree @@ -35,7 +38,7 @@ type Coins struct { } func NewCoins(stateBus *bus.Bus, iavl tree.MTree) (*Coins, error) { - coins := &Coins{bus: stateBus, iavl: iavl, list: map[types.CoinSymbol]*Model{}, dirty: map[types.CoinSymbol]struct{}{}} + coins := &Coins{bus: stateBus, iavl: iavl, list: map[types.CoinID]*Model{}, dirty: map[types.CoinID]struct{}{}} coins.bus.SetCoins(NewBus(coins)) return coins, nil @@ -43,34 +46,29 @@ func NewCoins(stateBus *bus.Bus, iavl tree.MTree) (*Coins, error) { func (c *Coins) Commit() error { coins := c.getOrderedDirtyCoins() - for _, symbol := range coins { - coin := c.getFromMap(symbol) + for _, id := range coins { + coin := c.getFromMap(id) c.lock.Lock() - delete(c.dirty, symbol) + delete(c.dirty, id) c.lock.Unlock() if coin.IsDirty() { data, err := rlp.EncodeToBytes(coin) if err != nil { - return fmt.Errorf("can't encode object at %x: %v", symbol[:], err) + return fmt.Errorf("can't encode object at %d: %v", id, err) } - path := []byte{mainPrefix} - path = append(path, symbol[:]...) - c.iavl.Set(path, data) + c.iavl.Set(getCoinPath(id), data) coin.isDirty = false } if coin.IsInfoDirty() { data, err := rlp.EncodeToBytes(coin.info) if err != nil { - return fmt.Errorf("can't encode object at %x: %v", symbol[:], err) + return fmt.Errorf("can't encode object at %d: %v", id, err) } - path := []byte{mainPrefix} - path = append(path, symbol[:]...) - path = append(path, infoPrefix) - c.iavl.Set(path, data) + c.iavl.Set(getCoinInfoPath(id), data) coin.info.isDirty = false } } @@ -78,55 +76,84 @@ func (c *Coins) Commit() error { return nil } -func (c *Coins) GetCoin(symbol types.CoinSymbol) *Model { - return c.get(symbol) +func (c *Coins) GetCoin(id types.CoinID) *Model { + return c.get(id) } -func (c *Coins) Exists(symbol types.CoinSymbol) bool { - if symbol.IsBaseCoin() { +func (c *Coins) Exists(id types.CoinID) bool { + if id.IsBaseCoin() { return true } - return c.get(symbol) != nil + return c.get(id) != nil } -func (c *Coins) SubVolume(symbol types.CoinSymbol, amount *big.Int) { +func (c *Coins) ExistsBySymbol(symbol types.CoinSymbol) bool { if symbol.IsBaseCoin() { + return true + } + + return c.getBySymbol(symbol) != nil +} + +func (c *Coins) GetCoinBySymbol(symbol types.CoinSymbol) *Model { + coins := c.getBySymbol(symbol.GetBaseSymbol()) + if coins == nil { + return nil + } + + for _, c := range *coins { + if c.Version() == symbol.GetVersion() { + return &c + } + } + + return nil +} + +func (c *Coins) SubVolume(id types.CoinID, amount *big.Int) { + if id.IsBaseCoin() { return } - c.get(symbol).SubVolume(amount) - c.bus.Checker().AddCoinVolume(symbol, big.NewInt(0).Neg(amount)) + + c.get(id).SubVolume(amount) + c.bus.Checker().AddCoinVolume(id, big.NewInt(0).Neg(amount)) } -func (c *Coins) AddVolume(symbol types.CoinSymbol, amount *big.Int) { - if symbol.IsBaseCoin() { +func (c *Coins) AddVolume(id types.CoinID, amount *big.Int) { + if id.IsBaseCoin() { return } - c.get(symbol).AddVolume(amount) - c.bus.Checker().AddCoinVolume(symbol, amount) + + c.get(id).AddVolume(amount) + c.bus.Checker().AddCoinVolume(id, amount) } -func (c *Coins) SubReserve(symbol types.CoinSymbol, amount *big.Int) { - if symbol.IsBaseCoin() { +func (c *Coins) SubReserve(id types.CoinID, amount *big.Int) { + if id.IsBaseCoin() { return } - c.get(symbol).SubReserve(amount) - c.bus.Checker().AddCoin(types.GetBaseCoin(), big.NewInt(0).Neg(amount)) + + c.get(id).SubReserve(amount) + c.bus.Checker().AddCoin(types.GetBaseCoinID(), big.NewInt(0).Neg(amount)) } -func (c *Coins) AddReserve(symbol types.CoinSymbol, amount *big.Int) { - if symbol.IsBaseCoin() { +func (c *Coins) AddReserve(id types.CoinID, amount *big.Int) { + if id.IsBaseCoin() { return } - c.get(symbol).AddReserve(amount) - c.bus.Checker().AddCoin(types.GetBaseCoin(), amount) + + c.get(id).AddReserve(amount) + c.bus.Checker().AddCoin(types.GetBaseCoinID(), amount) } -func (c *Coins) Create(symbol types.CoinSymbol, name string, volume *big.Int, crr uint, reserve *big.Int, maxSupply *big.Int) { +func (c *Coins) Create(id types.CoinID, symbol types.CoinSymbol, name string, + volume *big.Int, crr uint, reserve *big.Int, maxSupply *big.Int) { coin := &Model{ CName: name, CCrr: crr, CMaxSupply: maxSupply, + id: id, symbol: symbol, markDirty: c.markDirty, isDirty: true, @@ -137,107 +164,162 @@ func (c *Coins) Create(symbol types.CoinSymbol, name string, volume *big.Int, cr }, } - c.setToMap(coin.symbol, coin) + c.setToMap(coin.id, coin) coin.SetReserve(reserve) coin.SetVolume(volume) - c.markDirty(symbol) + c.markDirty(coin.id) - c.bus.Checker().AddCoin(types.GetBaseCoin(), reserve) - c.bus.Checker().AddCoinVolume(symbol, volume) + c.bus.Checker().AddCoin(types.GetBaseCoinID(), reserve) + c.bus.Checker().AddCoinVolume(coin.id, volume) } -func (c *Coins) get(symbol types.CoinSymbol) *Model { - if coin := c.getFromMap(symbol); coin != nil { +func (c *Coins) get(id types.CoinID) *Model { + if coin := c.getFromMap(id); coin != nil { return coin } - path := []byte{mainPrefix} - path = append(path, symbol[:]...) - _, enc := c.iavl.Get(path) + _, enc := c.iavl.Get(getCoinPath(id)) if len(enc) == 0 { return nil } coin := &Model{} if err := rlp.DecodeBytes(enc, coin); err != nil { - panic(fmt.Sprintf("failed to decode coin at %s: %s", symbol.String(), err)) + panic(fmt.Sprintf("failed to decode coin at %d: %s", id, err)) } - coin.symbol = symbol + coin.id = id coin.markDirty = c.markDirty // load info - path = []byte{mainPrefix} - path = append(path, symbol[:]...) - path = append(path, infoPrefix) - _, enc = c.iavl.Get(path) + _, enc = c.iavl.Get(getCoinInfoPath(id)) if len(enc) != 0 { var info Info if err := rlp.DecodeBytes(enc, &info); err != nil { - panic(fmt.Sprintf("failed to decode coin info %s: %s", symbol.String(), err)) + panic(fmt.Sprintf("failed to decode coin info %d: %s", id, err)) } coin.info = &info } - c.setToMap(symbol, coin) + c.setToMap(id, coin) return coin } -func (c *Coins) markDirty(symbol types.CoinSymbol) { - c.dirty[symbol] = struct{}{} +func (c *Coins) getBySymbol(symbol types.CoinSymbol) *[]Model { + coins := &[]Model{} + + path := []byte{mainPrefix} + path = append(path, symbol.Bytes()...) + _, enc := c.iavl.Get(path) + if len(enc) == 0 { + return nil + } + + if err := rlp.DecodeBytes(enc, coins); err != nil { + panic(fmt.Sprintf("failed to decode coins by symbol %s: %s", symbol, err)) + } + + return coins } -func (c *Coins) getOrderedDirtyCoins() []types.CoinSymbol { - keys := make([]types.CoinSymbol, 0, len(c.dirty)) +func (c *Coins) markDirty(id types.CoinID) { + c.dirty[id] = struct{}{} +} + +func (c *Coins) getOrderedDirtyCoins() []types.CoinID { + keys := make([]types.CoinID, 0, len(c.dirty)) for k := range c.dirty { keys = append(keys, k) } sort.SliceStable(keys, func(i, j int) bool { - return bytes.Compare(keys[i].Bytes(), keys[j].Bytes()) == 1 + return keys[i] > keys[j] }) return keys } func (c *Coins) Export(state *types.AppState) { - // todo: iterate range? + var coins []types.Coin + isSortingRequired := true + c.iavl.Iterate(func(key []byte, value []byte) bool { if key[0] == mainPrefix { if len(key[1:]) > types.CoinSymbolLength { return false } - coinSymbol := types.StrToCoinSymbol(string(key[1:])) - coin := c.GetCoin(coinSymbol) + coinID := types.CoinID(binary.LittleEndian.Uint32(key[1:])) + coin := c.GetCoin(coinID) - state.Coins = append(state.Coins, types.Coin{ + coinModel := types.Coin{ + ID: coinID, Name: coin.Name(), Symbol: coin.Symbol(), Volume: coin.Volume().String(), Crr: coin.Crr(), Reserve: coin.Reserve().String(), MaxSupply: coin.MaxSupply().String(), - }) + } + + if coin.ID() != 0 { + isSortingRequired = false + } + + if isSortingRequired { + for _, account := range state.Accounts { + for _, balance := range account.Balance { + if balance.Coin.String() == coin.Symbol().String() && balance.Value == coin.Volume().String() { + coinModel.OwnerAddress = &account.Address + } + } + } + } + + coins = append(coins, coinModel) } return false }) + + if isSortingRequired { + sort.Slice(coins[:], func(i, j int) bool { + return helpers.StringToBigInt(coins[i].Reserve).Cmp(helpers.StringToBigInt(coins[j].Reserve)) == 1 + }) + + for i, _ := range coins { + coins[i].ID = types.CoinID(i + 1) + } + } + + state.Coins = coins } -func (c *Coins) getFromMap(symbol types.CoinSymbol) *Model { +func (c *Coins) getFromMap(id types.CoinID) *Model { c.lock.RLock() defer c.lock.RUnlock() - return c.list[symbol] + return c.list[id] } -func (c *Coins) setToMap(symbol types.CoinSymbol, model *Model) { +func (c *Coins) setToMap(id types.CoinID, model *Model) { c.lock.Lock() defer c.lock.Unlock() - c.list[symbol] = model + c.list[id] = model +} + +func getCoinPath(id types.CoinID) []byte { + path := []byte{mainPrefix} + return append(path, id.Bytes()...) } + +func getCoinInfoPath(id types.CoinID) []byte { + path := getCoinInfoPath(id) + path = append(path, infoPrefix) + path = append(path, id.Bytes()...) + return path +} \ No newline at end of file diff --git a/core/state/coins/model.go b/core/state/coins/model.go index 262fc1146..2351cf32d 100644 --- a/core/state/coins/model.go +++ b/core/state/coins/model.go @@ -14,9 +14,11 @@ type Model struct { CCrr uint CMaxSupply *big.Int + id types.CoinID symbol types.CoinSymbol + version uint16 info *Info - markDirty func(symbol types.CoinSymbol) + markDirty func(symbol types.CoinID) isDirty bool } @@ -28,6 +30,10 @@ func (m Model) Symbol() types.CoinSymbol { return m.symbol } +func (m Model) ID() types.CoinID { + return m.id +} + func (m Model) Crr() uint { return m.CCrr } @@ -40,39 +46,43 @@ func (m Model) Reserve() *big.Int { return big.NewInt(0).Set(m.info.Reserve) } +func (m Model) Version() uint16 { + return m.version +} + func (m *Model) SubVolume(amount *big.Int) { m.info.Volume.Sub(m.info.Volume, amount) - m.markDirty(m.symbol) + m.markDirty(m.id) m.info.isDirty = true } func (m *Model) AddVolume(amount *big.Int) { m.info.Volume.Add(m.info.Volume, amount) - m.markDirty(m.symbol) + m.markDirty(m.id) m.info.isDirty = true } func (m *Model) SubReserve(amount *big.Int) { m.info.Reserve.Sub(m.info.Reserve, amount) - m.markDirty(m.symbol) + m.markDirty(m.id) m.info.isDirty = true } func (m *Model) AddReserve(amount *big.Int) { m.info.Reserve.Add(m.info.Reserve, amount) - m.markDirty(m.symbol) + m.markDirty(m.id) m.info.isDirty = true } func (m *Model) SetReserve(reserve *big.Int) { m.info.Reserve.Set(reserve) - m.markDirty(m.symbol) + m.markDirty(m.id) m.info.isDirty = true } func (m *Model) SetVolume(volume *big.Int) { m.info.Volume.Set(volume) - m.markDirty(m.symbol) + m.markDirty(m.id) m.info.isDirty = true } diff --git a/core/state/frozenfunds/bus.go b/core/state/frozenfunds/bus.go index 80f8fe93f..aabe77314 100644 --- a/core/state/frozenfunds/bus.go +++ b/core/state/frozenfunds/bus.go @@ -9,7 +9,7 @@ type Bus struct { frozenfunds *FrozenFunds } -func (b *Bus) AddFrozenFund(height uint64, address types.Address, pubkey types.Pubkey, coin types.CoinSymbol, value *big.Int) { +func (b *Bus) AddFrozenFund(height uint64, address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { b.frozenfunds.AddFund(height, address, pubkey, coin, value) } diff --git a/core/state/frozenfunds/frozen_funds.go b/core/state/frozenfunds/frozen_funds.go index 6d2243f56..1eb5641a8 100644 --- a/core/state/frozenfunds/frozen_funds.go +++ b/core/state/frozenfunds/frozen_funds.go @@ -171,7 +171,7 @@ func (f *FrozenFunds) getOrderedDirty() []uint64 { return keys } -func (f *FrozenFunds) AddFund(height uint64, address types.Address, pubkey types.Pubkey, coin types.CoinSymbol, value *big.Int) { +func (f *FrozenFunds) AddFund(height uint64, address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { f.GetOrNew(height).addFund(address, pubkey, coin, value) f.bus.Checker().AddCoin(coin, value) } diff --git a/core/state/frozenfunds/model.go b/core/state/frozenfunds/model.go index 826effb1a..a4e4a459e 100644 --- a/core/state/frozenfunds/model.go +++ b/core/state/frozenfunds/model.go @@ -8,7 +8,7 @@ import ( type Item struct { Address types.Address CandidateKey *types.Pubkey - Coin types.CoinSymbol + Coin types.CoinID Value *big.Int } @@ -25,7 +25,7 @@ func (m *Model) delete() { m.markDirty(m.height) } -func (m *Model) addFund(address types.Address, pubkey types.Pubkey, coin types.CoinSymbol, value *big.Int) { +func (m *Model) addFund(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { m.List = append(m.List, Item{ Address: address, CandidateKey: &pubkey, diff --git a/core/state/legacy/states.go b/core/state/legacy/states.go new file mode 100644 index 000000000..97c7d05f7 --- /dev/null +++ b/core/state/legacy/states.go @@ -0,0 +1,3 @@ +package legacy + + diff --git a/core/state/state.go b/core/state/state.go index f6c70343c..a0e5a35b0 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -231,7 +231,7 @@ func (s *State) Import(state types.AppState) error { } for _, c := range state.Coins { - s.Coins.Create(c.Symbol, c.Name, helpers.StringToBigInt(c.Volume), c.Crr, helpers.StringToBigInt(c.Reserve), helpers.StringToBigInt(c.MaxSupply)) + s.Coins.Create(c.ID, c.Symbol, c.Name, helpers.StringToBigInt(c.Volume), c.Crr, helpers.StringToBigInt(c.Reserve), helpers.StringToBigInt(c.MaxSupply)) } var vals []*validators.Validator @@ -280,12 +280,12 @@ func (s *State) Export(height uint64) types.AppState { appState := new(types.AppState) state.App().Export(appState, height) - state.Validators().Export(appState) - state.Candidates().Export(appState) - state.FrozenFunds().Export(appState, height) - state.Accounts().Export(appState) + //state.Validators().Export(appState) + //state.Candidates().Export(appState) + //state.FrozenFunds().Export(appState, height) + //state.Accounts().Export(appState) state.Coins().Export(appState) - state.Checks().Export(appState) + //state.Checks().Export(appState) return *appState } diff --git a/core/state/validators/model.go b/core/state/validators/model.go index fa869d579..abaa5723e 100644 --- a/core/state/validators/model.go +++ b/core/state/validators/model.go @@ -47,7 +47,7 @@ func (v *Validator) SetAccumReward(value *big.Int) { if v.accumReward.Cmp(value) != 0 { v.isAccumRewardDirty = true } - v.bus.Checker().AddCoin(types.GetBaseCoin(), big.NewInt(0).Sub(value, v.accumReward), "reward") + v.bus.Checker().AddCoin(types.GetBaseCoinID(), big.NewInt(0).Sub(value, v.accumReward), "reward") v.accumReward = big.NewInt(0).Set(value) } diff --git a/core/state/validators/validators.go b/core/state/validators/validators.go index f5f3faca3..9d4d62d0e 100644 --- a/core/state/validators/validators.go +++ b/core/state/validators/validators.go @@ -191,7 +191,7 @@ func (v *Validators) PayRewards(height uint64) { DAOReward := big.NewInt(0).Set(totalReward) DAOReward.Mul(DAOReward, big.NewInt(int64(dao.Commission))) DAOReward.Div(DAOReward, big.NewInt(100)) - v.bus.Accounts().AddBalance(dao.Address, types.GetBaseCoin(), DAOReward) + v.bus.Accounts().AddBalance(dao.Address, types.GetBaseCoinID(), DAOReward) remainder.Sub(remainder, DAOReward) v.bus.Events().AddEvent(uint32(height), &eventsdb.RewardEvent{ Role: eventsdb.RoleDAO.String(), @@ -204,7 +204,7 @@ func (v *Validators) PayRewards(height uint64) { DevelopersReward := big.NewInt(0).Set(totalReward) DevelopersReward.Mul(DevelopersReward, big.NewInt(int64(developers.Commission))) DevelopersReward.Div(DevelopersReward, big.NewInt(100)) - v.bus.Accounts().AddBalance(developers.Address, types.GetBaseCoin(), DevelopersReward) + v.bus.Accounts().AddBalance(developers.Address, types.GetBaseCoinID(), DevelopersReward) remainder.Sub(remainder, DevelopersReward) v.bus.Events().AddEvent(uint32(height), &eventsdb.RewardEvent{ Role: eventsdb.RoleDevelopers.String(), @@ -221,7 +221,7 @@ func (v *Validators) PayRewards(height uint64) { validatorReward.Mul(validatorReward, big.NewInt(int64(candidate.Commission))) validatorReward.Div(validatorReward, big.NewInt(100)) totalReward.Sub(totalReward, validatorReward) - v.bus.Accounts().AddBalance(candidate.RewardAddress, types.GetBaseCoin(), validatorReward) + v.bus.Accounts().AddBalance(candidate.RewardAddress, types.GetBaseCoinID(), validatorReward) remainder.Sub(remainder, validatorReward) v.bus.Events().AddEvent(uint32(height), &eventsdb.RewardEvent{ Role: eventsdb.RoleValidator.String(), @@ -244,7 +244,7 @@ func (v *Validators) PayRewards(height uint64) { continue } - v.bus.Accounts().AddBalance(stake.Owner, types.GetBaseCoin(), reward) + v.bus.Accounts().AddBalance(stake.Owner, types.GetBaseCoinID(), reward) remainder.Sub(remainder, reward) v.bus.Events().AddEvent(uint32(height), &eventsdb.RewardEvent{ diff --git a/core/transaction/buy_coin.go b/core/transaction/buy_coin.go index eeb1e22d2..5c90726d4 100644 --- a/core/transaction/buy_coin.go +++ b/core/transaction/buy_coin.go @@ -14,9 +14,9 @@ import ( ) type BuyCoinData struct { - CoinToBuy types.CoinSymbol + CoinToBuy types.CoinID ValueToBuy *big.Int - CoinToSell types.CoinSymbol + CoinToSell types.CoinID MaximumValueToSell *big.Int } @@ -111,7 +111,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( FromCoin: tx.GasCoin, FromAmount: commission, FromReserve: commissionInBaseCoin, - ToCoin: types.GetBaseCoin(), + ToCoin: types.GetBaseCoinID(), }) } @@ -208,7 +208,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( FromCoin: tx.GasCoin, FromAmount: commission, FromReserve: commissionInBaseCoin, - ToCoin: types.GetBaseCoin(), + ToCoin: types.GetBaseCoinID(), }) } @@ -258,7 +258,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( FromCoin: tx.GasCoin, FromAmount: commission, FromReserve: commissionInBaseCoin, - ToCoin: types.GetBaseCoin(), + ToCoin: types.GetBaseCoinID(), }) totalValue := big.NewInt(0).Add(value, commission) @@ -312,7 +312,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( FromCoin: tx.GasCoin, FromAmount: commission, FromReserve: commissionInBaseCoin, - ToCoin: types.GetBaseCoin(), + ToCoin: types.GetBaseCoinID(), }) } @@ -434,8 +434,8 @@ func (data BuyCoinData) Run(tx *Transaction, context state.Interface, rewardPool } func checkConversionsReserveUnderflow(conversions []Conversion, context *state.CheckState) *Response { - var totalReserveCoins []types.CoinSymbol - totalReserveSub := make(map[types.CoinSymbol]*big.Int) + var totalReserveCoins []types.CoinID + totalReserveSub := make(map[types.CoinID]*big.Int) for _, conversion := range conversions { if conversion.FromCoin.IsBaseCoin() { continue diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index 7c256326b..2f19d0b9b 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -74,7 +74,7 @@ func (data CreateCoinData) BasicCheck(tx *Transaction, context *state.CheckState Log: fmt.Sprintf("Invalid coin symbol. Should be %s", allowedCoinSymbols)} } - if context.Coins().Exists(data.Symbol) { + if context.Coins().ExistsBySymbol(data.Symbol) { return &Response{ Code: code.CoinAlreadyExists, Log: fmt.Sprintf("Coin already exists")} @@ -143,7 +143,7 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP commissionInBaseCoin := tx.CommissionInBaseCoin() commission := big.NewInt(0).Set(commissionInBaseCoin) - if tx.GasCoin != types.GetBaseCoin() { + if tx.GasCoin != types.GetBaseCoinID() { coin := checkState.Coins().GetCoin(tx.GasCoin) errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) @@ -178,7 +178,7 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP } } - if checkState.Accounts().GetBalance(sender, types.GetBaseCoin()).Cmp(data.InitialReserve) < 0 { + if checkState.Accounts().GetBalance(sender, types.GetBaseCoinID()).Cmp(data.InitialReserve) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), data.InitialReserve.String(), types.GetBaseCoin()), @@ -195,7 +195,7 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP totalTxCost.Add(totalTxCost, data.InitialReserve) totalTxCost.Add(totalTxCost, commission) - if checkState.Accounts().GetBalance(sender, types.GetBaseCoin()).Cmp(totalTxCost) < 0 { + if checkState.Accounts().GetBalance(sender, types.GetBaseCoinID()).Cmp(totalTxCost) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), tx.GasCoin), @@ -214,10 +214,24 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) deliveryState.Coins.SubVolume(tx.GasCoin, commission) - deliveryState.Accounts.SubBalance(sender, types.GetBaseCoin(), data.InitialReserve) + deliveryState.App.GetCoinsCount() + + deliveryState.Accounts.SubBalance(sender, types.GetBaseCoinID(), data.InitialReserve) deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) - deliveryState.Coins.Create(data.Symbol, data.Name, data.InitialAmount, data.ConstantReserveRatio, data.InitialReserve, data.MaxSupply) - deliveryState.Accounts.AddBalance(sender, data.Symbol, data.InitialAmount) + + coinID := deliveryState.App.GetCoinsCount() + 1 + deliveryState.Coins.Create( + types.CoinID(coinID), + data.Symbol, + data.Name, + data.InitialAmount, + data.ConstantReserveRatio, + data.InitialReserve, + data.MaxSupply, + ) + + deliveryState.App.SetCoinsCount(coinID) + deliveryState.Accounts.AddBalance(sender, types.CoinID(coinID), data.InitialAmount) deliveryState.Accounts.SetNonce(sender, tx.Nonce) } diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index 14ce6b9f7..bd9891dd4 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -22,7 +22,7 @@ type DeclareCandidacyData struct { Address types.Address PubKey types.Pubkey Commission uint - Coin types.CoinSymbol + Coin types.CoinID Stake *big.Int } diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index 7e3e2f51c..55a859ddb 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -16,7 +16,7 @@ import ( type DelegateData struct { PubKey types.Pubkey - Coin types.CoinSymbol + Coin types.CoinID Value *big.Int } diff --git a/core/transaction/multisend.go b/core/transaction/multisend.go index ec97661e5..a6819b4f8 100644 --- a/core/transaction/multisend.go +++ b/core/transaction/multisend.go @@ -46,7 +46,7 @@ func (data MultisendData) BasicCheck(tx *Transaction, context *state.CheckState) } type MultisendDataItem struct { - Coin types.CoinSymbol + Coin types.CoinID To types.Address Value *big.Int } @@ -143,8 +143,8 @@ func (data MultisendData) Run(tx *Transaction, context state.Interface, rewardPo } } -func checkBalances(context *state.CheckState, sender types.Address, items []MultisendDataItem, commission *big.Int, gasCoin types.CoinSymbol) *Response { - total := map[types.CoinSymbol]*big.Int{} +func checkBalances(context *state.CheckState, sender types.Address, items []MultisendDataItem, commission *big.Int, gasCoin types.CoinID) *Response { + total := map[types.CoinID]*big.Int{} total[gasCoin] = big.NewInt(0).Set(commission) for _, item := range items { @@ -155,13 +155,13 @@ func checkBalances(context *state.CheckState, sender types.Address, items []Mult total[item.Coin].Add(total[item.Coin], item.Value) } - coins := make([]types.CoinSymbol, 0, len(total)) + coins := make([]types.CoinID, 0, len(total)) for k := range total { coins = append(coins, k) } sort.SliceStable(coins, func(i, j int) bool { - return coins[i].Compare(coins[j]) == 1 + return coins[i] > coins[j] }) for _, coin := range coins { diff --git a/core/transaction/sell_all_coin.go b/core/transaction/sell_all_coin.go index 04acb7621..ca8e41d97 100644 --- a/core/transaction/sell_all_coin.go +++ b/core/transaction/sell_all_coin.go @@ -14,8 +14,8 @@ import ( ) type SellAllCoinData struct { - CoinToSell types.CoinSymbol - CoinToBuy types.CoinSymbol + CoinToSell types.CoinID + CoinToBuy types.CoinID MinimumValueToBuy *big.Int } diff --git a/core/transaction/sell_coin.go b/core/transaction/sell_coin.go index b2b548a62..022d35727 100644 --- a/core/transaction/sell_coin.go +++ b/core/transaction/sell_coin.go @@ -14,9 +14,9 @@ import ( ) type SellCoinData struct { - CoinToSell types.CoinSymbol + CoinToSell types.CoinID ValueToSell *big.Int - CoinToBuy types.CoinSymbol + CoinToBuy types.CoinID MinimumValueToBuy *big.Int } @@ -70,7 +70,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) FromCoin: tx.GasCoin, FromAmount: commission, FromReserve: commissionInBaseCoin, - ToCoin: types.GetBaseCoin(), + ToCoin: types.GetBaseCoinID(), }) } @@ -135,7 +135,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) FromCoin: tx.GasCoin, FromAmount: c, FromReserve: commissionInBaseCoin, - ToCoin: types.GetBaseCoin(), + ToCoin: types.GetBaseCoinID(), }) } @@ -186,7 +186,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) FromCoin: tx.GasCoin, FromAmount: c, FromReserve: commissionInBaseCoin, - ToCoin: types.GetBaseCoin(), + ToCoin: types.GetBaseCoinID(), }) } @@ -219,7 +219,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) FromCoin: tx.GasCoin, FromAmount: commission, FromReserve: commissionInBaseCoin, - ToCoin: types.GetBaseCoin(), + ToCoin: types.GetBaseCoinID(), }) } @@ -266,7 +266,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) FromCoin: tx.GasCoin, FromAmount: commission, FromReserve: commissionInBaseCoin, - ToCoin: types.GetBaseCoin(), + ToCoin: types.GetBaseCoinID(), }) } diff --git a/core/transaction/send.go b/core/transaction/send.go index a485e352d..db30a7e62 100644 --- a/core/transaction/send.go +++ b/core/transaction/send.go @@ -14,7 +14,7 @@ import ( ) type SendData struct { - Coin types.CoinSymbol + Coin types.CoinID To types.Address Value *big.Int } @@ -64,7 +64,7 @@ func (data SendData) TotalSpend(tx *Transaction, context *state.CheckState) (Tot FromCoin: tx.GasCoin, FromAmount: commission, FromReserve: commissionInBaseCoin, - ToCoin: types.GetBaseCoin(), + ToCoin: types.GetBaseCoinID(), }) } diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index 2db5460ca..b15658371 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -47,7 +47,7 @@ type Transaction struct { Nonce uint64 ChainID types.ChainID GasPrice uint32 - GasCoin types.CoinSymbol + GasCoin types.CoinID Type TxType Data RawData Payload []byte @@ -76,7 +76,7 @@ type RawData []byte type TotalSpends []TotalSpend -func (tss *TotalSpends) Add(coin types.CoinSymbol, value *big.Int) { +func (tss *TotalSpends) Add(coin types.CoinID, value *big.Int) { for i, t := range *tss { if t.Coin == coin { (*tss)[i].Value.Add((*tss)[i].Value, big.NewInt(0).Set(value)) @@ -91,15 +91,15 @@ func (tss *TotalSpends) Add(coin types.CoinSymbol, value *big.Int) { } type TotalSpend struct { - Coin types.CoinSymbol + Coin types.CoinID Value *big.Int } type Conversion struct { - FromCoin types.CoinSymbol + FromCoin types.CoinID FromAmount *big.Int FromReserve *big.Int - ToCoin types.CoinSymbol + ToCoin types.CoinID ToAmount *big.Int ToReserve *big.Int } diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 85fc6d4ea..1e2de7aed 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -18,7 +18,7 @@ const unbondPeriod = 518400 type UnbondData struct { PubKey types.Pubkey - Coin types.CoinSymbol + Coin types.CoinID Value *big.Int } diff --git a/core/types/appstate.go b/core/types/appstate.go index 69f86c1b0..3e18de728 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -84,7 +84,7 @@ func (s *AppState) Verify() error { // check not existing coins foundCoin := false for _, coin := range s.Coins { - if coin.Symbol == bal.Coin { + if coin.ID == bal.Coin { foundCoin = true break } @@ -111,7 +111,7 @@ func (s *AppState) Verify() error { if !stake.Coin.IsBaseCoin() { foundCoin := false for _, coin := range s.Coins { - if coin.Symbol == stake.Coin { + if coin.ID == stake.Coin { foundCoin = true break } @@ -139,14 +139,14 @@ func (s *AppState) Verify() error { // check coins' volume volume := big.NewInt(0) for _, ff := range s.FrozenFunds { - if ff.Coin == coin.Symbol { + if ff.Coin == coin.ID { volume.Add(volume, helpers.StringToBigInt(ff.Value)) } } for _, candidate := range s.Candidates { for _, stake := range candidate.Stakes { - if stake.Coin == coin.Symbol { + if stake.Coin == coin.ID { volume.Add(volume, helpers.StringToBigInt(stake.Value)) } } @@ -154,7 +154,7 @@ func (s *AppState) Verify() error { for _, account := range s.Accounts { for _, bal := range account.Balance { - if bal.Coin == coin.Symbol { + if bal.Coin == coin.ID { volume.Add(volume, helpers.StringToBigInt(bal.Value)) } } @@ -174,7 +174,7 @@ func (s *AppState) Verify() error { if !ff.Coin.IsBaseCoin() { foundCoin := false for _, coin := range s.Coins { - if coin.Symbol == ff.Coin { + if coin.ID == ff.Coin { foundCoin = true break } @@ -221,25 +221,27 @@ type Candidate struct { type Stake struct { Owner Address `json:"owner"` - Coin CoinSymbol `json:"coin"` + Coin CoinID `json:"coin"` Value string `json:"value"` BipValue string `json:"bip_value"` } type Coin struct { - Name string `json:"name"` - Symbol CoinSymbol `json:"symbol"` - Volume string `json:"volume"` - Crr uint `json:"crr"` - Reserve string `json:"reserve"` - MaxSupply string `json:"max_supply"` + ID CoinID `json:"id"` + Name string `json:"name"` + Symbol CoinSymbol `json:"symbol"` + Volume string `json:"volume"` + Crr uint `json:"crr"` + Reserve string `json:"reserve"` + MaxSupply string `json:"max_supply"` + OwnerAddress *Address `json:"owner_address"` } type FrozenFund struct { Height uint64 `json:"height"` Address Address `json:"address"` CandidateKey *Pubkey `json:"candidate_key,omitempty"` - Coin CoinSymbol `json:"coin"` + Coin CoinID `json:"coin"` Value string `json:"value"` } @@ -253,7 +255,7 @@ type Account struct { } type Balance struct { - Coin CoinSymbol `json:"coin"` + Coin CoinID `json:"coin"` Value string `json:"value"` } diff --git a/core/types/constants.go b/core/types/constants.go index d40591857..b1f1767d4 100644 --- a/core/types/constants.go +++ b/core/types/constants.go @@ -18,6 +18,10 @@ func GetBaseCoin() CoinSymbol { return getBaseCoin(CurrentChainID) } +func GetBaseCoinID() CoinID { + return BasecoinID +} + func getBaseCoin(chainID ChainID) CoinSymbol { switch chainID { case ChainMainnet: diff --git a/core/types/types.go b/core/types/types.go index 848f71f73..fb25428da 100644 --- a/core/types/types.go +++ b/core/types/types.go @@ -2,12 +2,15 @@ package types import ( "bytes" + "encoding/binary" "encoding/hex" "fmt" "github.com/MinterTeam/minter-go-node/hexutil" "math/big" "math/rand" "reflect" + "strconv" + "strings" ) const ( @@ -15,6 +18,7 @@ const ( AddressLength = 20 PubKeyLength = 32 CoinSymbolLength = 10 + BasecoinID = 0 ) var ( @@ -147,12 +151,41 @@ func (c CoinSymbol) IsBaseCoin() bool { return c.Compare(GetBaseCoin()) == 0 } +func (c CoinSymbol) GetBaseSymbol() CoinSymbol { + return StrToCoinSymbol(strings.Split(c.String(), "-")[0]) +} + +func (c CoinSymbol) GetVersion() uint16 { + parts := strings.Split(c.String(), "-") + if len(parts) == 1 { + return 0 + } + + return 1 +} + func StrToCoinSymbol(s string) CoinSymbol { var symbol CoinSymbol copy(symbol[:], []byte(s)) return symbol } +type CoinID uint32 + +func (c CoinID) IsBaseCoin() bool { + return c == GetBaseCoinID() +} + +func (c CoinID) String() string { + return strconv.Itoa(int(c)) +} + +func (c CoinID) Bytes() []byte { + var b []byte + binary.LittleEndian.PutUint32(b, uint32(c)) + return b +} + /////////// Address type Address [AddressLength]byte From 9f52af96ae8d8dccc793daad6ee080a0f89f4f5d Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 10 Jul 2020 15:55:09 +0300 Subject: [PATCH 054/426] Update validators Public Key and Export --- cmd/minter/cmd/export.go | 2 +- core/code/code.go | 1 + core/state/bus/candidates.go | 1 + core/state/candidates/bus.go | 2 + core/state/candidates/candidates.go | 181 ++++++++++++++++++++-- core/state/candidates/export_v11_old.go | 198 ++++++++++++++++++++++++ core/state/candidates/model.go | 6 + core/state/state.go | 18 +++ core/state/validators/validators.go | 1 + core/transaction/declare_candidacy.go | 10 ++ core/transaction/edit_candidate.go | 13 ++ core/types/appstate.go | 1 + 12 files changed, 424 insertions(+), 10 deletions(-) create mode 100644 core/state/candidates/export_v11_old.go diff --git a/cmd/minter/cmd/export.go b/cmd/minter/cmd/export.go index 6d239c961..195af26f3 100644 --- a/cmd/minter/cmd/export.go +++ b/cmd/minter/cmd/export.go @@ -63,7 +63,7 @@ func export(cmd *cobra.Command, args []string) error { log.Panicf("Cannot new state at given height: %s", err) } - exportTimeStart, newState := time.Now(), currentState.Export(height) + exportTimeStart, newState := time.Now(), currentState.Export11To12(height) fmt.Printf("State has been exported. Took %s", time.Since(exportTimeStart)) jsonBytes, err := amino.NewCodec().MarshalJSONIndent(newState, "", " ") diff --git a/core/code/code.go b/core/code/code.go index 12b283a8e..8e154a0a2 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -41,6 +41,7 @@ const ( IncorrectPubKey uint32 = 407 StakeShouldBePositive uint32 = 408 TooLowStake uint32 = 409 + PublicKeyInBlockList uint32 = 410 // check CheckInvalidLock uint32 = 501 diff --git a/core/state/bus/candidates.go b/core/state/bus/candidates.go index 7bcc38ee6..4e6bbf5f6 100644 --- a/core/state/bus/candidates.go +++ b/core/state/bus/candidates.go @@ -21,6 +21,7 @@ type Stake struct { } type Candidate struct { + ID uint PubKey types.Pubkey RewardAddress types.Address OwnerAddress types.Address diff --git a/core/state/candidates/bus.go b/core/state/candidates/bus.go index 39396e503..362a95195 100644 --- a/core/state/candidates/bus.go +++ b/core/state/candidates/bus.go @@ -41,6 +41,7 @@ func (b *Bus) GetCandidate(pubkey types.Pubkey) *bus.Candidate { } return &bus.Candidate{ + ID: candidate.ID, PubKey: candidate.PubKey, RewardAddress: candidate.RewardAddress, OwnerAddress: candidate.OwnerAddress, @@ -61,6 +62,7 @@ func (b *Bus) GetCandidateByTendermintAddress(tmAddress types.TmAddress) *bus.Ca } return &bus.Candidate{ + ID: candidate.ID, PubKey: candidate.PubKey, RewardAddress: candidate.RewardAddress, OwnerAddress: candidate.OwnerAddress, diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index c58d62344..88f21d055 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -24,14 +24,18 @@ const ( MaxDelegatorsPerCandidate = 1000 mainPrefix = 'c' + pubKeyIDPrefix = 'i' + blockListPrefix = 'b' stakesPrefix = 's' totalStakePrefix = 't' updatesPrefix = 'u' ) type RCandidates interface { + Export11To12(state *types.AppState) //todo: delete after start Node v1.1 Export(state *types.AppState) Exists(pubkey types.Pubkey) bool + IsBlockPubKey(pubkey *types.Pubkey) bool Count() int IsNewCandidateStakeSufficient(coin types.CoinSymbol, stake *big.Int, limit int) bool IsDelegatorStakeSufficient(address types.Address, pubkey types.Pubkey, coin types.CoinSymbol, amount *big.Int) bool @@ -48,7 +52,9 @@ type RCandidates interface { } type Candidates struct { - list map[types.Pubkey]*Candidate + list map[uint]*Candidate + blockList map[types.Pubkey]struct{} + pubKeyIDs map[types.Pubkey]uint iavl tree.MTree bus *bus.Bus @@ -89,6 +95,16 @@ func (c *Candidates) Commit() error { c.iavl.Set(path, data) } + var blockList []types.Pubkey + for pubKey := range c.blockList { + blockList = append(blockList, pubKey) + } + blockListData, err := rlp.EncodeToBytes(blockList) + if err != nil { + return fmt.Errorf("can't encode block list of candidates: %v", err) + } + c.iavl.Set([]byte{blockListPrefix}, blockListData) + for _, pubkey := range keys { candidate := c.getFromMap(pubkey) candidate.isDirty = false @@ -539,8 +555,30 @@ func (c *Candidates) Exists(pubkey types.Pubkey) bool { c.lock.RLock() defer c.lock.RUnlock() - _, exists := c.list[pubkey] + return c.existPubKey(pubkey) +} + +func (c *Candidates) existPubKey(pubKey types.Pubkey) bool { + if c.pubKeyIDs == nil { + return false + } + _, exists := c.pubKeyIDs[pubKey] + return exists +} + +func (c *Candidates) IsBlockPubKey(pubkey *types.Pubkey) bool { + if pubkey == nil { + return false + } + + c.lock.RLock() + defer c.lock.RUnlock() + + return c.isBlock(*pubkey) +} +func (c *Candidates) isBlock(pubKey types.Pubkey) bool { + _, exists := c.blockList[pubKey] return exists } @@ -709,15 +747,31 @@ func (c *Candidates) GetCandidateControl(pubkey types.Pubkey) types.Address { } func (c *Candidates) LoadCandidates() { - if c.loaded { + if c.checkAndSetLoaded() { + return + } + + _, pubIDenc := c.iavl.Get([]byte{pubKeyIDPrefix}) + if len(pubIDenc) == 0 { + c.pubKeyIDs = map[types.Pubkey]uint{} return } - c.loaded = true + + var pubIDs []*pubkeyID + if err := rlp.DecodeBytes(pubIDenc, &pubIDs); err != nil { + panic(fmt.Sprintf("failed to decode candidates: %s", err)) + } + + pubKeyIDs := map[types.Pubkey]uint{} + for _, v := range pubIDs { + pubKeyIDs[v.PubKey] = v.ID + } + c.setPubKeyIDs(pubKeyIDs) path := []byte{mainPrefix} _, enc := c.iavl.Get(path) if len(enc) == 0 { - c.list = map[types.Pubkey]*Candidate{} + c.list = map[uint]*Candidate{} return } @@ -726,7 +780,6 @@ func (c *Candidates) LoadCandidates() { panic(fmt.Sprintf("failed to decode candidates: %s", err)) } - c.list = map[types.Pubkey]*Candidate{} for _, candidate := range candidates { // load total stake path = append([]byte{mainPrefix}, candidate.PubKey.Bytes()...) @@ -741,10 +794,40 @@ func (c *Candidates) LoadCandidates() { candidate.setTmAddress() c.setToMap(candidate.PubKey, candidate) } + + _, blockListEnc := c.iavl.Get([]byte{blockListPrefix}) + if len(blockListEnc) == 0 { + c.blockList = map[types.Pubkey]struct{}{} + return + } + + var blockList []types.Pubkey + if err := rlp.DecodeBytes(enc, &blockList); err != nil { + panic(fmt.Sprintf("failed to decode candidates block list: %s", err)) + } + + blockListMap := map[types.Pubkey]struct{}{} + for _, pubkey := range blockList { + blockListMap[pubkey] = struct{}{} + } + c.setBlockList(blockListMap) +} + +func (c *Candidates) checkAndSetLoaded() bool { + c.lock.RLock() + if c.loaded { + c.lock.RLock() + return true + } + c.lock.RUnlock() + c.lock.Lock() + c.loaded = true + c.lock.Unlock() + return false } func (c *Candidates) LoadStakes() { - for pubkey := range c.list { + for pubkey := range c.pubKeyIDs { c.LoadStakesOfCandidate(pubkey) } } @@ -880,6 +963,7 @@ func (c *Candidates) Export(state *types.AppState) { c.LoadStakes() candidates := c.GetCandidates() + state.Candidates = make([]types.Candidate, 0, len(candidates)) for _, candidate := range candidates { candidateStakes := c.GetStakes(candidate.PubKey) stakes := make([]types.Stake, len(candidateStakes)) @@ -903,6 +987,7 @@ func (c *Candidates) Export(state *types.AppState) { } state.Candidates = append(state.Candidates, types.Candidate{ + ID: candidate.ID, RewardAddress: candidate.RewardAddress, OwnerAddress: candidate.OwnerAddress, ControlAddress: candidate.ControlAddress, @@ -937,14 +1022,38 @@ func (c *Candidates) getFromMap(pubkey types.Pubkey) *Candidate { c.lock.RLock() defer c.lock.RUnlock() - return c.list[pubkey] + return c.list[c.id(pubkey)] } func (c *Candidates) setToMap(pubkey types.Pubkey, model *Candidate) { + id := model.ID + if id == 0 { + id = c.getOrNewID(pubkey) + + c.lock.Lock() + defer c.lock.Unlock() + + model.ID = id + } + + if c.list == nil { + c.list = map[uint]*Candidate{} + } + c.list[id] = model +} + +func (c *Candidates) setBlockList(blockList map[types.Pubkey]struct{}) { + c.lock.Lock() + defer c.lock.Unlock() + + c.blockList = blockList +} + +func (c *Candidates) setPubKeyIDs(list map[types.Pubkey]uint) { c.lock.Lock() defer c.lock.Unlock() - c.list[pubkey] = model + c.pubKeyIDs = list } func (c *Candidates) SetTotalStake(pubkey types.Pubkey, stake *big.Int) { @@ -1016,3 +1125,57 @@ func (c *Candidates) LoadStakesOfCandidate(pubkey types.Pubkey) { candidate.setTmAddress() c.setToMap(candidate.PubKey, candidate) } + +func (c *Candidates) ChangePubKey(old types.Pubkey, new types.Pubkey) { + c.getFromMap(old).PubKey = new + c.lock.Lock() + defer c.lock.Unlock() + + if c.isBlock(new) { + panic("Candidate with such public key (" + new.String() + ") exists in block list") + } + c.setBlockPybKey(old) + c.setPubKeyID(new, c.pubKeyIDs[old]) + delete(c.pubKeyIDs, old) +} + +func (c *Candidates) getOrNewID(pubKey types.Pubkey) uint { + c.lock.RLock() + id := c.id(pubKey) + c.lock.RUnlock() + if id != 0 { + return id + } + + c.lock.Lock() + defer c.lock.Unlock() + + id = uint(len(c.list)) + 1 + c.setPubKeyID(pubKey, id) + return id +} + +func (c *Candidates) id(pubKey types.Pubkey) uint { + return c.pubKeyIDs[pubKey] +} + +func (c *Candidates) ID(pubKey types.Pubkey) uint { + c.lock.RLock() + defer c.lock.RUnlock() + + return c.pubKeyIDs[pubKey] +} + +func (c *Candidates) setPubKeyID(pubkey types.Pubkey, u uint) { + if c.pubKeyIDs == nil { + c.pubKeyIDs = map[types.Pubkey]uint{} + } + c.pubKeyIDs[pubkey] = u +} + +func (c *Candidates) setBlockPybKey(p types.Pubkey) { + if c.blockList == nil { + c.blockList = map[types.Pubkey]struct{}{} + } + c.blockList[p] = struct{}{} +} diff --git a/core/state/candidates/export_v11_old.go b/core/state/candidates/export_v11_old.go new file mode 100644 index 000000000..f521c676a --- /dev/null +++ b/core/state/candidates/export_v11_old.go @@ -0,0 +1,198 @@ +package candidates + +import ( + "fmt" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/rlp" + "github.com/tendermint/tendermint/crypto/ed25519" + "math/big" +) + +type Candidate11 struct { + PubKey types.Pubkey + RewardAddress types.Address + OwnerAddress types.Address + Commission uint + Status byte + + totalBipStake *big.Int + stakesCount int + stakes [MaxDelegatorsPerCandidate]*Stake + updates []*Stake + tmAddress *types.TmAddress + + isDirty bool + isTotalStakeDirty bool + isUpdatesDirty bool + dirtyStakes [MaxDelegatorsPerCandidate]bool +} + +func (candidate *Candidate11) setTmAddress() { + // set tm address + var pubkey ed25519.PubKeyEd25519 + copy(pubkey[:], candidate.PubKey[:]) + + var address types.TmAddress + copy(address[:], pubkey.Address().Bytes()) + + candidate.tmAddress = &address +} + +func (c *Candidates) Export11To12(state *types.AppState) { + c.LoadCandidates11() + c.LoadStakes11() + + candidates := c.GetCandidates() + for _, candidate := range candidates { + candidateStakes := c.GetStakes(candidate.PubKey) + stakes := make([]types.Stake, len(candidateStakes)) + for i, s := range candidateStakes { + stakes[i] = types.Stake{ + Owner: s.Owner, + Coin: s.Coin, + Value: s.Value.String(), + BipValue: s.BipValue.String(), + } + } + + updates := make([]types.Stake, len(candidate.updates)) + for i, u := range candidate.updates { + updates[i] = types.Stake{ + Owner: u.Owner, + Coin: u.Coin, + Value: u.Value.String(), + BipValue: u.BipValue.String(), + } + } + + state.Candidates = append(state.Candidates, types.Candidate{ + ID: c.getOrNewID(candidate.PubKey), + RewardAddress: candidate.RewardAddress, + OwnerAddress: candidate.OwnerAddress, + ControlAddress: candidate.ControlAddress, + TotalBipStake: candidate.GetTotalBipStake().String(), + PubKey: candidate.PubKey, + Commission: candidate.Commission, + Status: candidate.Status, + Updates: updates, + Stakes: stakes, + }) + } + + return +} + +func (c *Candidates) LoadCandidates11() { + if c.loaded { + return + } + c.loaded = true + + path := []byte{mainPrefix} + _, enc := c.iavl.Get(path) + if len(enc) == 0 { + c.list = map[uint]*Candidate{} + return + } + + var candidates []*Candidate11 + if err := rlp.DecodeBytes(enc, &candidates); err != nil { + panic(fmt.Sprintf("failed to decode candidates: %s", err)) + } + + c.list = map[uint]*Candidate{} + for _, candidate := range candidates { + // load total stake + path = append([]byte{mainPrefix}, candidate.PubKey.Bytes()...) + path = append(path, totalStakePrefix) + _, enc = c.iavl.Get(path) + if len(enc) == 0 { + candidate.totalBipStake = big.NewInt(0) + } else { + candidate.totalBipStake = big.NewInt(0).SetBytes(enc) + } + + candidate.setTmAddress() + c.setToMap(candidate.PubKey, &Candidate{ + PubKey: candidate.PubKey, + RewardAddress: candidate.RewardAddress, + OwnerAddress: candidate.OwnerAddress, + ControlAddress: types.HexToAddress("Mxf8a88c0ed668e995639cb8a08ffb38541bcc9045"), + Commission: candidate.Commission, + Status: candidate.Status, + ID: c.getOrNewID(candidate.PubKey), + }) + } +} + +func (c *Candidates) LoadStakes11() { + for _, candidate := range c.list { + c.LoadStakesOfCandidate11(candidate.PubKey) + } +} + +func (c *Candidates) LoadStakesOfCandidate11(pubkey types.Pubkey) { + candidate := c.GetCandidate(pubkey) + + // load stakes + stakesCount := 0 + for index := 0; index < MaxDelegatorsPerCandidate; index++ { + path := []byte{mainPrefix} + path = append(path, candidate.PubKey.Bytes()...) + path = append(path, stakesPrefix) + path = append(path, []byte(fmt.Sprintf("%d", index))...) + _, enc := c.iavl.Get(path) + if len(enc) == 0 { + candidate.stakes[index] = nil + continue + } + + stake := &Stake{} + if err := rlp.DecodeBytes(enc, stake); err != nil { + panic(fmt.Sprintf("failed to decode stake: %s", err)) + } + + candidate.SetStakeAtIndex(index, stake, false) + + stakesCount++ + } + + candidate.stakesCount = stakesCount + + // load updates + path := []byte{mainPrefix} + path = append(path, candidate.PubKey.Bytes()...) + path = append(path, updatesPrefix) + _, enc := c.iavl.Get(path) + if len(enc) == 0 { + candidate.updates = nil + } else { + var updates []*Stake + if err := rlp.DecodeBytes(enc, &updates); err != nil { + panic(fmt.Sprintf("failed to decode updated: %s", err)) + } + + for _, update := range updates { + update.markDirty = (func(candidate *Candidate) func(int) { + return func(i int) { + candidate.isUpdatesDirty = true + } + })(candidate) + } + + candidate.updates = updates + } + + // load total stake + path = append([]byte{mainPrefix}, candidate.PubKey.Bytes()...) + path = append(path, totalStakePrefix) + _, enc = c.iavl.Get(path) + if len(enc) == 0 { + candidate.totalBipStake = big.NewInt(0) + } else { + candidate.totalBipStake = big.NewInt(0).SetBytes(enc) + } + + candidate.setTmAddress() + c.setToMap(candidate.PubKey, candidate) +} diff --git a/core/state/candidates/model.go b/core/state/candidates/model.go index df6397ea8..07791ed08 100644 --- a/core/state/candidates/model.go +++ b/core/state/candidates/model.go @@ -7,6 +7,11 @@ import ( "sort" ) +type pubkeyID struct { + PubKey types.Pubkey + ID uint +} + type Candidate struct { PubKey types.Pubkey RewardAddress types.Address @@ -14,6 +19,7 @@ type Candidate struct { ControlAddress types.Address Commission uint Status byte + ID uint totalBipStake *big.Int stakesCount int diff --git a/core/state/state.go b/core/state/state.go index f6c70343c..42e340611 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -290,6 +290,24 @@ func (s *State) Export(height uint64) types.AppState { return *appState } +func (s *State) Export11To12(height uint64) types.AppState { + state, err := NewCheckStateAtHeight(height, s.db) + if err != nil { + log.Panicf("Create new state at height %d failed: %s", height, err) + } + + appState := new(types.AppState) + state.App().Export(appState, height) + state.Validators().Export(appState) + state.Candidates().Export11To12(appState) + state.FrozenFunds().Export(appState, height) + state.Accounts().Export(appState) + state.Coins().Export(appState) + state.Checks().Export(appState) + + return *appState +} + func newCheckStateForTree(iavlTree tree.MTree, events eventsdb.IEventsDB, db db.DB, keepLastStates int64) (*CheckState, error) { stateForTree, err := newStateForTree(iavlTree, events, db, keepLastStates) if err != nil { diff --git a/core/state/validators/validators.go b/core/state/validators/validators.go index f5f3faca3..100214174 100644 --- a/core/state/validators/validators.go +++ b/core/state/validators/validators.go @@ -141,6 +141,7 @@ func (v *Validators) SetNewValidators(candidates []candidates.Candidate) { } newVals = append(newVals, &Validator{ + PubKey: candidate.PubKey, AbsentTimes: absentTimes, totalStake: candidate.GetTotalBipStake(), diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index 14ce6b9f7..e30dbed7f 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -73,6 +73,16 @@ func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.Chec } } + if context.Candidates().IsBlockPubKey(&data.PubKey) { + return &Response{ + Code: code.PublicKeyInBlockList, + Log: fmt.Sprintf("Candidate with such public key (%s) exists in block list", data.PubKey.String()), + Info: EncodeError(map[string]string{ + "public_key": data.PubKey.String(), + }), + } + } + if data.Commission < minCommission || data.Commission > maxCommission { return &Response{ Code: code.WrongCommission, diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index af1021954..b6cf77ece 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -115,6 +115,16 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa } } + if checkState.Candidates().IsBlockPubKey(data.NewPubKey) { + return Response{ + Code: code.PublicKeyInBlockList, + Log: fmt.Sprintf("Candidate with such public key (%s) exists in block list", data.PubKey.String()), + Info: EncodeError(map[string]string{ + "public_key": data.PubKey.String(), + }), + } + } + if deliveryState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) @@ -122,6 +132,9 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa deliveryState.Coins.SubVolume(tx.GasCoin, commission) deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) + if data.NewPubKey != nil { + deliveryState.Candidates.ChangePubKey(data.PubKey, *data.NewPubKey) + } deliveryState.Candidates.Edit(data.PubKey, data.RewardAddress, data.OwnerAddress, data.ControlAddress) deliveryState.Accounts.SetNonce(sender, tx.Nonce) } diff --git a/core/types/appstate.go b/core/types/appstate.go index 1b201fb60..ff5e056d3 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -209,6 +209,7 @@ type Validator struct { } type Candidate struct { + ID uint `json:"id"` RewardAddress Address `json:"reward_address"` OwnerAddress Address `json:"owner_address"` ControlAddress Address `json:"control_address"` From 3b3d78d8c54720e956bc76111423eb9fb12c04a4 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Fri, 10 Jul 2020 17:03:56 +0300 Subject: [PATCH 055/426] MN-435: export legacy state from 1.1 to 1.2 --- cmd/minter/cmd/export.go | 2 +- core/state/app/app.go | 4 +- core/state/coins/coins.go | 105 +++-- core/state/legacy/accounts/accounts.go | 212 ++++++++++ core/state/legacy/accounts/model.go | 138 +++++++ core/state/legacy/app/app.go | 106 +++++ core/state/legacy/app/model.go | 36 ++ core/state/legacy/candidates/candidates.go | 379 ++++++++++++++++++ core/state/legacy/candidates/model.go | 251 ++++++++++++ core/state/legacy/coins/coins.go | 155 +++++++ core/state/legacy/coins/model.go | 107 +++++ core/state/legacy/frozenfunds/frozen_funds.go | 119 ++++++ core/state/legacy/frozenfunds/model.go | 40 ++ core/state/legacy/states.go | 3 - core/state/state.go | 65 ++- core/types/appstate.go | 1 + 16 files changed, 1657 insertions(+), 66 deletions(-) create mode 100644 core/state/legacy/accounts/accounts.go create mode 100644 core/state/legacy/accounts/model.go create mode 100644 core/state/legacy/app/app.go create mode 100644 core/state/legacy/app/model.go create mode 100644 core/state/legacy/candidates/candidates.go create mode 100644 core/state/legacy/candidates/model.go create mode 100644 core/state/legacy/coins/coins.go create mode 100644 core/state/legacy/coins/model.go create mode 100644 core/state/legacy/frozenfunds/frozen_funds.go create mode 100644 core/state/legacy/frozenfunds/model.go delete mode 100644 core/state/legacy/states.go diff --git a/cmd/minter/cmd/export.go b/cmd/minter/cmd/export.go index b74f4554b..06de22993 100644 --- a/cmd/minter/cmd/export.go +++ b/cmd/minter/cmd/export.go @@ -63,7 +63,7 @@ func export(cmd *cobra.Command, args []string) error { log.Panicf("Cannot new state at given height: %s", err) } - exportTimeStart, newState := time.Now(), currentState.Export(height) + exportTimeStart, newState := time.Now(), currentState.Export11To12(height) fmt.Printf("State has been exported. Took %s", time.Since(exportTimeStart)) jsonBytes, err := amino.NewCodec().MarshalJSONIndent(newState, "", " ") diff --git a/core/state/app/app.go b/core/state/app/app.go index 2f26a9e4b..91edbf4ad 100644 --- a/core/state/app/app.go +++ b/core/state/app/app.go @@ -46,7 +46,7 @@ func (v *App) Commit() error { data, err := rlp.EncodeToBytes(v.model) if err != nil { - return fmt.Errorf("can't encode app model: %s", err) + return fmt.Errorf("can't encode legacyApp model: %s", err) } path := []byte{mainPrefix} @@ -95,7 +95,7 @@ func (v *App) get() *Model { model := &Model{} if err := rlp.DecodeBytes(enc, model); err != nil { - panic(fmt.Sprintf("failed to decode app model at: %s", err)) + panic(fmt.Sprintf("failed to decode legacyApp model at: %s", err)) } v.model = model diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index b4f89012a..265fea0b2 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -1,11 +1,9 @@ package coins import ( - "encoding/binary" "fmt" "github.com/MinterTeam/minter-go-node/core/state/bus" "github.com/MinterTeam/minter-go-node/core/types" - "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/rlp" "github.com/MinterTeam/minter-go-node/tree" "math/big" @@ -243,59 +241,56 @@ func (c *Coins) getOrderedDirtyCoins() []types.CoinID { } func (c *Coins) Export(state *types.AppState) { - var coins []types.Coin - isSortingRequired := true - - c.iavl.Iterate(func(key []byte, value []byte) bool { - if key[0] == mainPrefix { - if len(key[1:]) > types.CoinSymbolLength { - return false - } - - coinID := types.CoinID(binary.LittleEndian.Uint32(key[1:])) - coin := c.GetCoin(coinID) - - coinModel := types.Coin{ - ID: coinID, - Name: coin.Name(), - Symbol: coin.Symbol(), - Volume: coin.Volume().String(), - Crr: coin.Crr(), - Reserve: coin.Reserve().String(), - MaxSupply: coin.MaxSupply().String(), - } - - if coin.ID() != 0 { - isSortingRequired = false - } - - if isSortingRequired { - for _, account := range state.Accounts { - for _, balance := range account.Balance { - if balance.Coin.String() == coin.Symbol().String() && balance.Value == coin.Volume().String() { - coinModel.OwnerAddress = &account.Address - } - } - } - } - - coins = append(coins, coinModel) - } - - return false - }) - - if isSortingRequired { - sort.Slice(coins[:], func(i, j int) bool { - return helpers.StringToBigInt(coins[i].Reserve).Cmp(helpers.StringToBigInt(coins[j].Reserve)) == 1 - }) - - for i, _ := range coins { - coins[i].ID = types.CoinID(i + 1) - } - } - - state.Coins = coins + //c.iavl.Iterate(func(key []byte, value []byte) bool { + // if key[0] == mainPrefix { + // if len(key[1:]) > types.CoinSymbolLength { + // return false + // } + // + // coinID := types.CoinID(binary.LittleEndian.Uint32(key[1:])) + // coin := c.GetCoin(coinID) + // + // coinModel := types.Coin{ + // ID: coinID, + // Name: coin.Name(), + // Symbol: coin.Symbol(), + // Volume: coin.Volume().String(), + // Crr: coin.Crr(), + // Reserve: coin.Reserve().String(), + // MaxSupply: coin.MaxSupply().String(), + // } + // + // if coin.ID() != 0 { + // isSortingRequired = false + // } + // + // if isSortingRequired { + // for _, account := range state.Accounts { + // for _, balance := range account.Balance { + // if balance.Coin.String() == coin.Symbol().String() && balance.Value == coin.Volume().String() { + // coinModel.OwnerAddress = &account.Address + // } + // } + // } + // } + // + // coins = append(coins, coinModel) + // } + // + // return false + //}) + // + //if isSortingRequired { + // sort.Slice(coins[:], func(i, j int) bool { + // return helpers.StringToBigInt(coins[i].Reserve).Cmp(helpers.StringToBigInt(coins[j].Reserve)) == 1 + // }) + // + // for i, _ := range coins { + // coins[i].ID = types.CoinID(i + 1) + // } + //} + // + //state.Coins = coins } func (c *Coins) getFromMap(id types.CoinID) *Model { diff --git a/core/state/legacy/accounts/accounts.go b/core/state/legacy/accounts/accounts.go new file mode 100644 index 000000000..f5054a3e7 --- /dev/null +++ b/core/state/legacy/accounts/accounts.go @@ -0,0 +1,212 @@ +package accounts + +import ( + "fmt" + "github.com/MinterTeam/minter-go-node/core/state/bus" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/rlp" + "github.com/MinterTeam/minter-go-node/tree" + "math/big" + "sort" + "sync" +) + +const mainPrefix = byte('a') +const coinsPrefix = byte('c') +const balancePrefix = byte('b') + +type Accounts struct { + list map[types.Address]*Model + dirty map[types.Address]struct{} + + iavl tree.MTree + bus *bus.Bus + + lock sync.RWMutex +} + +func NewAccounts(stateBus *bus.Bus, iavl tree.MTree) (*Accounts, error) { + accounts := &Accounts{iavl: iavl, bus: stateBus, list: map[types.Address]*Model{}, dirty: map[types.Address]struct{}{}} + return accounts, nil +} + +func (a *Accounts) GetBalance(address types.Address, coin types.CoinSymbol) *big.Int { + account := a.getOrNew(address) + if !account.hasCoin(coin) { + return big.NewInt(0) + } + + if _, ok := account.balances[coin]; !ok { + balance := big.NewInt(0) + + path := []byte{mainPrefix} + path = append(path, address[:]...) + path = append(path, balancePrefix) + path = append(path, coin[:]...) + + _, enc := a.iavl.Get(path) + if len(enc) != 0 { + balance = big.NewInt(0).SetBytes(enc) + } + + account.balances[coin] = balance + } + + return big.NewInt(0).Set(account.balances[coin]) +} + +func (a *Accounts) get(address types.Address) *Model { + if account := a.getFromMap(address); account != nil { + return account + } + + path := []byte{mainPrefix} + path = append(path, address[:]...) + _, enc := a.iavl.Get(path) + if len(enc) == 0 { + return nil + } + + account := &Model{} + if err := rlp.DecodeBytes(enc, account); err != nil { + panic(fmt.Sprintf("failed to decode account at address %s: %s", address.String(), err)) + } + + account.address = address + account.balances = map[types.CoinSymbol]*big.Int{} + account.markDirty = a.markDirty + account.dirtyBalances = map[types.CoinSymbol]struct{}{} + + // load coins + path = []byte{mainPrefix} + path = append(path, address[:]...) + path = append(path, coinsPrefix) + _, enc = a.iavl.Get(path) + if len(enc) != 0 { + var coins []types.CoinSymbol + if err := rlp.DecodeBytes(enc, &coins); err != nil { + panic(fmt.Sprintf("failed to decode coins list at address %s: %s", address.String(), err)) + } + + account.coins = coins + } + + a.setToMap(address, account) + return account +} + +func (a *Accounts) getOrNew(address types.Address) *Model { + account := a.get(address) + if account == nil { + account = &Model{ + Nonce: 0, + address: address, + coins: []types.CoinSymbol{}, + balances: map[types.CoinSymbol]*big.Int{}, + markDirty: a.markDirty, + dirtyBalances: map[types.CoinSymbol]struct{}{}, + isNew: true, + } + a.setToMap(address, account) + } + + return account +} + +func (a *Accounts) GetNonce(address types.Address) uint64 { + account := a.getOrNew(address) + + return account.Nonce +} + +func (a *Accounts) GetBalances(address types.Address) map[types.CoinSymbol]*big.Int { + account := a.getOrNew(address) + + balances := make(map[types.CoinSymbol]*big.Int, len(account.coins)) + for _, coin := range account.coins { + balances[coin] = a.GetBalance(address, coin) + } + + return balances +} + +func (a *Accounts) markDirty(addr types.Address) { + a.dirty[addr] = struct{}{} +} + +func (a *Accounts) Export(state *types.AppState) { + // todo: iterate range? + a.iavl.Iterate(func(key []byte, value []byte) bool { + if key[0] == mainPrefix { + addressPath := key[1:] + if len(addressPath) > types.AddressLength { + return false + } + + address := types.BytesToAddress(addressPath) + account := a.get(address) + + var balance []types.Balance + for coin, value := range a.GetBalances(account.address) { + id := types.GetBaseCoinID() + for key, c := range state.Coins { + if c.Symbol == coin { + id = c.ID + + // save owner address for coin + // accounts are not available during coins export + if c.Volume == value.String() { + state.Coins[key].OwnerAddress = &account.address + } + } + } + + balance = append(balance, types.Balance{ + Coin: id, + Value: value.String(), + }) + } + + // sort balances by coin symbol + sort.SliceStable(balance, func(i, j int) bool { + return balance[i].Coin > balance[j].Coin + }) + + acc := types.Account{ + Address: account.address, + Balance: balance, + Nonce: account.Nonce, + } + + if account.IsMultisig() { + acc.MultisigData = &types.Multisig{ + Weights: account.MultisigData.Weights, + Threshold: account.MultisigData.Threshold, + Addresses: account.MultisigData.Addresses, + } + } + + state.Accounts = append(state.Accounts, acc) + } + + return false + }) +} + +func (a *Accounts) GetAccount(address types.Address) *Model { + return a.getOrNew(address) +} + +func (a *Accounts) getFromMap(address types.Address) *Model { + a.lock.RLock() + defer a.lock.RUnlock() + + return a.list[address] +} + +func (a *Accounts) setToMap(address types.Address, model *Model) { + a.lock.Lock() + defer a.lock.Unlock() + + a.list[address] = model +} \ No newline at end of file diff --git a/core/state/legacy/accounts/model.go b/core/state/legacy/accounts/model.go new file mode 100644 index 000000000..7e80e1c3f --- /dev/null +++ b/core/state/legacy/accounts/model.go @@ -0,0 +1,138 @@ +package accounts + +import ( + "bytes" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/crypto" + "github.com/MinterTeam/minter-go-node/rlp" + "math/big" + "sort" +) + +type Model struct { + Nonce uint64 + MultisigData Multisig + + address types.Address + coins []types.CoinSymbol + balances map[types.CoinSymbol]*big.Int + + hasDirtyCoins bool + dirtyBalances map[types.CoinSymbol]struct{} + isDirty bool // nonce or multisig data + + isNew bool + + markDirty func(types.Address) +} + +type Multisig struct { + Threshold uint + Weights []uint + Addresses []types.Address +} + +func (m *Multisig) Address() types.Address { + b, err := rlp.EncodeToBytes(m) + if err != nil { + panic(err) + } + + var addr types.Address + copy(addr[:], crypto.Keccak256(b)[12:]) + + return addr +} + +func (m *Multisig) GetWeight(address types.Address) uint { + for i, addr := range m.Addresses { + if addr == address { + return m.Weights[i] + } + } + + return 0 +} + +func (model *Model) setNonce(nonce uint64) { + model.Nonce = nonce + model.isDirty = true + model.markDirty(model.address) +} + +func (model *Model) getBalance(coin types.CoinSymbol) *big.Int { + return model.balances[coin] +} + +func (model *Model) hasDirtyBalances() bool { + return len(model.dirtyBalances) > 0 +} + +func (model *Model) isBalanceDirty(coin types.CoinSymbol) bool { + _, exists := model.dirtyBalances[coin] + return exists +} + +func (model *Model) getOrderedCoins() []types.CoinSymbol { + keys := make([]types.CoinSymbol, 0, len(model.balances)) + for k := range model.balances { + keys = append(keys, k) + } + + sort.SliceStable(keys, func(i, j int) bool { + return bytes.Compare(keys[i].Bytes(), keys[j].Bytes()) == 1 + }) + + return keys +} + +func (model *Model) setBalance(coin types.CoinSymbol, amount *big.Int) { + if amount.Cmp(big.NewInt(0)) == 0 { + if !model.hasCoin(coin) { + return + } + + var newCoins []types.CoinSymbol + for _, c := range model.coins { + if coin == c { + continue + } + + newCoins = append(newCoins, c) + } + + model.hasDirtyCoins = true + model.coins = newCoins + model.balances[coin] = amount + model.dirtyBalances[coin] = struct{}{} + model.markDirty(model.address) + + return + } + + if !model.hasCoin(coin) { + model.hasDirtyCoins = true + model.coins = append(model.coins, coin) + } + model.dirtyBalances[coin] = struct{}{} + model.markDirty(model.address) + model.balances[coin] = amount +} + +func (model *Model) hasCoin(coin types.CoinSymbol) bool { + for _, c := range model.coins { + if c == coin { + return true + } + } + + return false +} + +func (model *Model) IsMultisig() bool { + return len(model.MultisigData.Weights) > 0 +} + +func (model *Model) Multisig() Multisig { + return model.MultisigData +} \ No newline at end of file diff --git a/core/state/legacy/app/app.go b/core/state/legacy/app/app.go new file mode 100644 index 000000000..ac38ca66d --- /dev/null +++ b/core/state/legacy/app/app.go @@ -0,0 +1,106 @@ +package app + +import ( + "fmt" + "github.com/MinterTeam/minter-go-node/core/state/bus" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/rlp" + "github.com/MinterTeam/minter-go-node/tree" + "math/big" +) + +const mainPrefix = 'd' + +func (v *App) Tree() tree.ReadOnlyTree { + return v.iavl +} + +type App struct { + model *Model + isDirty bool + + bus *bus.Bus + iavl tree.MTree +} + +func NewApp(stateBus *bus.Bus, iavl tree.MTree) (*App, error) { + app := &App{bus: stateBus, iavl: iavl} + + return app, nil +} + +func (v *App) GetMaxGas() uint64 { + model := v.getOrNew() + + return model.getMaxGas() +} + +func (v *App) SetMaxGas(gas uint64) { + model := v.getOrNew() + model.setMaxGas(gas) +} + +func (v *App) GetTotalSlashed() *big.Int { + model := v.getOrNew() + + return model.getTotalSlashed() +} + +func (v *App) AddTotalSlashed(amount *big.Int) { + if amount.Cmp(big.NewInt(0)) == 0 { + return + } + + model := v.getOrNew() + model.setTotalSlashed(big.NewInt(0).Add(model.getTotalSlashed(), amount)) + v.bus.Checker().AddCoin(types.GetBaseCoinID(), amount) +} + +func (v *App) get() *Model { + if v.model != nil { + return v.model + } + + path := []byte{mainPrefix} + _, enc := v.iavl.Get(path) + if len(enc) == 0 { + return nil + } + + model := &Model{} + if err := rlp.DecodeBytes(enc, model); err != nil { + panic(fmt.Sprintf("failed to decode app model at: %s", err)) + } + + v.model = model + v.model.markDirty = v.markDirty + return v.model +} + +func (v *App) getOrNew() *Model { + model := v.get() + if model == nil { + model = &Model{ + TotalSlashed: big.NewInt(0), + MaxGas: 0, + markDirty: v.markDirty, + } + v.model = model + } + + return model +} + +func (v *App) markDirty() { + v.isDirty = true +} + +func (v *App) SetTotalSlashed(amount *big.Int) { + v.getOrNew().setTotalSlashed(amount) +} + +func (v *App) Export(state *types.AppState, height uint64) { + state.MaxGas = v.GetMaxGas() + state.TotalSlashed = v.GetTotalSlashed().String() + state.StartHeight = height +} diff --git a/core/state/legacy/app/model.go b/core/state/legacy/app/model.go new file mode 100644 index 000000000..d502226f7 --- /dev/null +++ b/core/state/legacy/app/model.go @@ -0,0 +1,36 @@ +package app + +import "math/big" + +type Model struct { + TotalSlashed *big.Int + MaxGas uint64 + + markDirty func() +} + +func (model *Model) getMaxGas() uint64 { + return model.MaxGas +} + +func (model *Model) setMaxGas(maxGas uint64) { + if model.MaxGas != maxGas { + model.markDirty() + } + model.MaxGas = maxGas +} + +func (model *Model) getTotalSlashed() *big.Int { + if model.TotalSlashed == nil { + return big.NewInt(0) + } + + return model.TotalSlashed +} + +func (model *Model) setTotalSlashed(totalSlashed *big.Int) { + if model.TotalSlashed.Cmp(totalSlashed) != 0 { + model.markDirty() + } + model.TotalSlashed = totalSlashed +} diff --git a/core/state/legacy/candidates/candidates.go b/core/state/legacy/candidates/candidates.go new file mode 100644 index 000000000..97d7eb317 --- /dev/null +++ b/core/state/legacy/candidates/candidates.go @@ -0,0 +1,379 @@ + +package candidates + +import ( + "bytes" + "fmt" + "github.com/MinterTeam/minter-go-node/core/state/bus" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/rlp" + "github.com/MinterTeam/minter-go-node/tree" + "math/big" + "sort" + "sync" +) + +const ( + CandidateStatusOffline = 0x01 + CandidateStatusOnline = 0x02 + + UnbondPeriod = 518400 + MaxDelegatorsPerCandidate = 1000 + + mainPrefix = 'c' + stakesPrefix = 's' + totalStakePrefix = 't' + updatesPrefix = 'u' +) + +type Candidates struct { + list map[types.Pubkey]*Candidate + + iavl tree.MTree + bus *bus.Bus + + lock sync.RWMutex + loaded bool +} + +func NewCandidates(bus *bus.Bus, iavl tree.MTree) (*Candidates, error) { + candidates := &Candidates{iavl: iavl, bus: bus} + + return candidates, nil +} + +func (c *Candidates) GetNewCandidates(valCount int) []Candidate { + var result []Candidate + + candidates := c.GetCandidates() + for _, candidate := range candidates { + if candidate.Status == CandidateStatusOffline { + continue + } + + if candidate.totalBipStake.Cmp(big.NewInt(0)) == 0 { + continue + } + + result = append(result, *candidate) + } + + sort.Slice(result, func(i, j int) bool { + return result[i].totalBipStake.Cmp(result[j].totalBipStake) == 1 + }) + + if len(result) > valCount { + result = result[:valCount] + } + + return result +} + +func (c *Candidates) Create(ownerAddress types.Address, rewardAddress types.Address, pubkey types.Pubkey, commission uint) { + candidate := &Candidate{ + PubKey: pubkey, + RewardAddress: rewardAddress, + OwnerAddress: ownerAddress, + Commission: commission, + Status: CandidateStatusOffline, + totalBipStake: big.NewInt(0), + stakes: [MaxDelegatorsPerCandidate]*Stake{}, + isDirty: true, + isTotalStakeDirty: true, + } + + candidate.setTmAddress() + c.setToMap(pubkey, candidate) +} + +func (c *Candidates) GetCandidateByTendermintAddress(address types.TmAddress) *Candidate { + candidates := c.GetCandidates() + for _, candidate := range candidates { + if candidate.GetTmAddress() == address { + return candidate + } + } + + return nil +} + +func (c *Candidates) Exists(pubkey types.Pubkey) bool { + c.lock.RLock() + defer c.lock.RUnlock() + + _, exists := c.list[pubkey] + + return exists +} + +func (c *Candidates) Count() int { + c.lock.RLock() + defer c.lock.RUnlock() + + return len(c.list) +} + +func (c *Candidates) GetCandidate(pubkey types.Pubkey) *Candidate { + return c.getFromMap(pubkey) +} + +func (c *Candidates) GetCandidates() []*Candidate { + var candidates []*Candidate + for _, pubkey := range c.getOrderedCandidates() { + candidates = append(candidates, c.getFromMap(pubkey)) + } + + return candidates +} + +func (c *Candidates) GetTotalStake(pubkey types.Pubkey) *big.Int { + candidate := c.getFromMap(pubkey) + if candidate.totalBipStake == nil { + path := []byte{mainPrefix} + path = append(path, pubkey[:]...) + path = append(path, totalStakePrefix) + _, enc := c.iavl.Get(path) + if len(enc) == 0 { + candidate.totalBipStake = big.NewInt(0) + return big.NewInt(0) + } + + candidate.totalBipStake = big.NewInt(0).SetBytes(enc) + } + + return candidate.totalBipStake +} + +func (c *Candidates) GetStakes(pubkey types.Pubkey) []*Stake { + candidate := c.GetCandidate(pubkey) + + var stakes []*Stake + for i := 0; i < MaxDelegatorsPerCandidate; i++ { + stake := candidate.stakes[i] + if stake == nil { + continue + } + stakes = append(stakes, stake) + } + + return stakes +} + +func (c *Candidates) StakesCount(pubkey types.Pubkey) int { + return c.GetCandidate(pubkey).stakesCount +} + +func (c *Candidates) GetStakeOfAddress(pubkey types.Pubkey, address types.Address, coin types.CoinSymbol) *Stake { + candidate := c.GetCandidate(pubkey) + for _, stake := range candidate.stakes { + if stake == nil { + continue + } + + if stake.Owner == address && stake.Coin == coin { + return stake + } + } + + return nil +} + +func (c *Candidates) GetStakeValueOfAddress(pubkey types.Pubkey, address types.Address, coin types.CoinSymbol) *big.Int { + stake := c.GetStakeOfAddress(pubkey, address, coin) + if stake == nil { + return nil + } + + return stake.Value +} + +func (c *Candidates) GetCandidateOwner(pubkey types.Pubkey) types.Address { + return c.getFromMap(pubkey).OwnerAddress +} + +func (c *Candidates) LoadCandidates() { + if c.loaded { + return + } + c.loaded = true + + path := []byte{mainPrefix} + _, enc := c.iavl.Get(path) + if len(enc) == 0 { + c.list = map[types.Pubkey]*Candidate{} + return + } + + var candidates []*Candidate + if err := rlp.DecodeBytes(enc, &candidates); err != nil { + panic(fmt.Sprintf("failed to decode candidates: %s", err)) + } + + c.list = map[types.Pubkey]*Candidate{} + for _, candidate := range candidates { + // load total stake + path = append([]byte{mainPrefix}, candidate.PubKey.Bytes()...) + path = append(path, totalStakePrefix) + _, enc = c.iavl.Get(path) + if len(enc) == 0 { + candidate.totalBipStake = big.NewInt(0) + } else { + candidate.totalBipStake = big.NewInt(0).SetBytes(enc) + } + + candidate.setTmAddress() + c.setToMap(candidate.PubKey, candidate) + } +} + +func (c *Candidates) LoadStakes() { + for pubkey := range c.list { + c.LoadStakesOfCandidate(pubkey) + } +} + +func (c *Candidates) Export(state *types.AppState) { + c.LoadCandidates() + c.LoadStakes() + + coinsSymbolToID := make(map[types.CoinSymbol]types.CoinID, len(state.Coins)) + for _, c := range state.Coins { + coinsSymbolToID[c.Symbol] = c.ID + } + + candidates := c.GetCandidates() + for _, candidate := range candidates { + candidateStakes := c.GetStakes(candidate.PubKey) + stakes := make([]types.Stake, len(candidateStakes)) + for i, s := range candidateStakes { + stakes[i] = types.Stake{ + Owner: s.Owner, + Coin: coinsSymbolToID[s.Coin], + Value: s.Value.String(), + BipValue: s.BipValue.String(), + } + } + + updates := make([]types.Stake, len(candidate.updates)) + for i, u := range candidate.updates { + updates[i] = types.Stake{ + Owner: u.Owner, + Coin: coinsSymbolToID[u.Coin], + Value: u.Value.String(), + BipValue: u.BipValue.String(), + } + } + + state.Candidates = append(state.Candidates, types.Candidate{ + RewardAddress: candidate.RewardAddress, + OwnerAddress: candidate.OwnerAddress, + TotalBipStake: candidate.GetTotalBipStake().String(), + PubKey: candidate.PubKey, + Commission: candidate.Commission, + Status: candidate.Status, + Updates: updates, + Stakes: stakes, + }) + } + +} + +func (c *Candidates) getOrderedCandidates() []types.Pubkey { + c.lock.RLock() + defer c.lock.RUnlock() + + var keys []types.Pubkey + for _, candidate := range c.list { + keys = append(keys, candidate.PubKey) + } + + sort.SliceStable(keys, func(i, j int) bool { + return bytes.Compare(keys[i].Bytes(), keys[j].Bytes()) == 1 + }) + + return keys +} + +func (c *Candidates) getFromMap(pubkey types.Pubkey) *Candidate { + c.lock.RLock() + defer c.lock.RUnlock() + + return c.list[pubkey] +} + +func (c *Candidates) setToMap(pubkey types.Pubkey, model *Candidate) { + c.lock.Lock() + defer c.lock.Unlock() + + c.list[pubkey] = model +} + +func (c *Candidates) SetTotalStake(pubkey types.Pubkey, stake *big.Int) { + c.GetCandidate(pubkey).setTotalBipStake(stake) +} + +func (c *Candidates) LoadStakesOfCandidate(pubkey types.Pubkey) { + candidate := c.GetCandidate(pubkey) + + // load stakes + stakesCount := 0 + for index := 0; index < MaxDelegatorsPerCandidate; index++ { + path := []byte{mainPrefix} + path = append(path, candidate.PubKey.Bytes()...) + path = append(path, stakesPrefix) + path = append(path, []byte(fmt.Sprintf("%d", index))...) + _, enc := c.iavl.Get(path) + if len(enc) == 0 { + candidate.stakes[index] = nil + continue + } + + stake := &Stake{} + if err := rlp.DecodeBytes(enc, stake); err != nil { + panic(fmt.Sprintf("failed to decode stake: %s", err)) + } + + candidate.SetStakeAtIndex(index, stake, false) + + stakesCount++ + } + + candidate.stakesCount = stakesCount + + // load updates + path := []byte{mainPrefix} + path = append(path, candidate.PubKey.Bytes()...) + path = append(path, updatesPrefix) + _, enc := c.iavl.Get(path) + if len(enc) == 0 { + candidate.updates = nil + } else { + var updates []*Stake + if err := rlp.DecodeBytes(enc, &updates); err != nil { + panic(fmt.Sprintf("failed to decode updated: %s", err)) + } + + for _, update := range updates { + update.markDirty = (func(candidate *Candidate) func(int) { + return func(i int) { + candidate.isUpdatesDirty = true + } + })(candidate) + } + + candidate.updates = updates + } + + // load total stake + path = append([]byte{mainPrefix}, candidate.PubKey.Bytes()...) + path = append(path, totalStakePrefix) + _, enc = c.iavl.Get(path) + if len(enc) == 0 { + candidate.totalBipStake = big.NewInt(0) + } else { + candidate.totalBipStake = big.NewInt(0).SetBytes(enc) + } + + candidate.setTmAddress() + c.setToMap(candidate.PubKey, candidate) +} \ No newline at end of file diff --git a/core/state/legacy/candidates/model.go b/core/state/legacy/candidates/model.go new file mode 100644 index 000000000..93a40d1d6 --- /dev/null +++ b/core/state/legacy/candidates/model.go @@ -0,0 +1,251 @@ +package candidates + +import ( + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/tendermint/tendermint/crypto/ed25519" + "math/big" + "sort" +) + +type Candidate struct { + PubKey types.Pubkey + RewardAddress types.Address + OwnerAddress types.Address + Commission uint + Status byte + + totalBipStake *big.Int + stakesCount int + stakes [MaxDelegatorsPerCandidate]*Stake + updates []*Stake + tmAddress *types.TmAddress + + isDirty bool + isTotalStakeDirty bool + isUpdatesDirty bool + dirtyStakes [MaxDelegatorsPerCandidate]bool +} + +func (candidate *Candidate) setStatus(status byte) { + candidate.isDirty = true + candidate.Status = status +} + +func (candidate *Candidate) setOwner(address types.Address) { + candidate.isDirty = true + candidate.OwnerAddress = address +} + +func (candidate *Candidate) setReward(address types.Address) { + candidate.isDirty = true + candidate.RewardAddress = address +} + +func (candidate *Candidate) addUpdate(stake *Stake) { + candidate.isUpdatesDirty = true + stake.markDirty = func(i int) { + candidate.isUpdatesDirty = true + } + candidate.updates = append(candidate.updates, stake) +} + +func (candidate *Candidate) clearUpdates() { + if len(candidate.updates) != 0 { + candidate.isUpdatesDirty = true + } + + candidate.updates = nil +} + +func (candidate *Candidate) setTotalBipStake(totalBipValue *big.Int) { + if totalBipValue.Cmp(candidate.totalBipStake) != 0 { + candidate.isTotalStakeDirty = true + } + + candidate.totalBipStake.Set(totalBipValue) +} + +func (candidate *Candidate) GetTmAddress() types.TmAddress { + return *candidate.tmAddress +} + +func (candidate *Candidate) setTmAddress() { + // set tm address + var pubkey ed25519.PubKeyEd25519 + copy(pubkey[:], candidate.PubKey[:]) + + var address types.TmAddress + copy(address[:], pubkey.Address().Bytes()) + + candidate.tmAddress = &address +} + +func (candidate *Candidate) GetFilteredUpdates() []*Stake { + var updates []*Stake + for _, update := range candidate.updates { + // skip updates with 0 stakes + if update.Value.Cmp(big.NewInt(0)) != 1 { + continue + } + + // merge updates + merged := false + for _, u := range updates { + if u.Coin == update.Coin && u.Owner == update.Owner { + u.Value.Add(u.Value, update.Value) + merged = true + break + } + } + + if !merged { + updates = append(updates, update) + } + } + + return updates +} + +func (candidate *Candidate) FilterUpdates() { + var updates []*Stake + for _, update := range candidate.updates { + // skip updates with 0 stakes + if update.Value.Cmp(big.NewInt(0)) != 1 { + continue + } + + // merge updates + merged := false + for _, u := range updates { + if u.Coin == update.Coin && u.Owner == update.Owner { + u.Value.Add(u.Value, update.Value) + merged = true + break + } + } + + if !merged { + updates = append(updates, update) + } + } + + sort.SliceStable(updates, func(i, j int) bool { + return updates[i].BipValue.Cmp(updates[j].BipValue) == 1 + }) + + candidate.updates = updates + candidate.isUpdatesDirty = true +} + +func (candidate *Candidate) updateStakesCount() { + count := 0 + for _, stake := range candidate.stakes { + if stake != nil { + count++ + } + } + candidate.stakesCount = count +} + +func (candidate *Candidate) GetTotalBipStake() *big.Int { + return big.NewInt(0).Set(candidate.totalBipStake) +} + +func (candidate *Candidate) SetStakeAtIndex(index int, stake *Stake, isDirty bool) { + stake.markDirty = func(i int) { + candidate.dirtyStakes[i] = true + } + stake.index = index + + candidate.stakes[index] = stake + + if isDirty { + stake.markDirty(index) + } +} + +type Stake struct { + Owner types.Address + Coin types.CoinSymbol + Value *big.Int + BipValue *big.Int + + index int + markDirty func(int) +} + +func (stake *Stake) addValue(value *big.Int) { + stake.markDirty(stake.index) + stake.Value.Add(stake.Value, value) +} + +func (stake *Stake) subValue(value *big.Int) { + stake.markDirty(stake.index) + stake.Value.Sub(stake.Value, value) +} + +func (stake *Stake) setBipValue(value *big.Int) { + if stake.BipValue.Cmp(value) != 0 { + stake.markDirty(stake.index) + } + + stake.BipValue.Set(value) +} + +func (stake *Stake) setNewOwner(coin types.CoinSymbol, owner types.Address) { + stake.Coin = coin + stake.Owner = owner + stake.BipValue = big.NewInt(0) + stake.Value = big.NewInt(0) + stake.markDirty(stake.index) +} + +func (stake *Stake) setValue(ret *big.Int) { + stake.markDirty(stake.index) + stake.Value.Set(ret) +} + +func (stake *Stake) setCoin(coin types.CoinSymbol) { + stake.markDirty(stake.index) + stake.Coin = coin +} + +type coinsCache struct { + list map[types.CoinSymbol]*coinsCacheItem +} + +func newCoinsCache() *coinsCache { + return &coinsCache{list: map[types.CoinSymbol]*coinsCacheItem{}} +} + +type coinsCacheItem struct { + totalPower *big.Int + totalAmount *big.Int +} + +func (c *coinsCache) Exists(symbol types.CoinSymbol) bool { + if c == nil { + return false + } + + _, exists := c.list[symbol] + + return exists +} + +func (c *coinsCache) Get(symbol types.CoinSymbol) (totalPower *big.Int, totalAmount *big.Int) { + return c.list[symbol].totalPower, c.list[symbol].totalAmount +} + +func (c *coinsCache) Set(symbol types.CoinSymbol, totalPower *big.Int, totalAmount *big.Int) { + if c == nil { + return + } + + if c.list[symbol] == nil { + c.list[symbol] = &coinsCacheItem{} + } + + c.list[symbol].totalAmount = totalAmount + c.list[symbol].totalPower = totalPower +} \ No newline at end of file diff --git a/core/state/legacy/coins/coins.go b/core/state/legacy/coins/coins.go new file mode 100644 index 000000000..0cf84fead --- /dev/null +++ b/core/state/legacy/coins/coins.go @@ -0,0 +1,155 @@ +package coins + +import ( + "bytes" + "fmt" + "github.com/MinterTeam/minter-go-node/core/state/bus" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/helpers" + "github.com/MinterTeam/minter-go-node/rlp" + "github.com/MinterTeam/minter-go-node/tree" + "sort" + "sync" +) + +const ( + mainPrefix = byte('q') + infoPrefix = byte('i') +) + +type Coins struct { + list map[types.CoinSymbol]*Model + dirty map[types.CoinSymbol]struct{} + + bus *bus.Bus + iavl tree.MTree + + lock sync.RWMutex +} + +func NewCoins(stateBus *bus.Bus, iavl tree.MTree) (*Coins, error) { + coins := &Coins{bus: stateBus, iavl: iavl, list: map[types.CoinSymbol]*Model{}, dirty: map[types.CoinSymbol]struct{}{}} + + return coins, nil +} + +func (c *Coins) GetCoin(symbol types.CoinSymbol) *Model { + return c.get(symbol) +} + +func (c *Coins) Exists(symbol types.CoinSymbol) bool { + if symbol.IsBaseCoin() { + return true + } + + return c.get(symbol) != nil +} + +func (c *Coins) get(symbol types.CoinSymbol) *Model { + if coin := c.getFromMap(symbol); coin != nil { + return coin + } + + path := []byte{mainPrefix} + path = append(path, symbol[:]...) + _, enc := c.iavl.Get(path) + if len(enc) == 0 { + return nil + } + + coin := &Model{} + if err := rlp.DecodeBytes(enc, coin); err != nil { + panic(fmt.Sprintf("failed to decode coin at %s: %s", symbol.String(), err)) + } + + coin.symbol = symbol + coin.markDirty = c.markDirty + + // load info + path = []byte{mainPrefix} + path = append(path, symbol[:]...) + path = append(path, infoPrefix) + _, enc = c.iavl.Get(path) + if len(enc) != 0 { + var info Info + if err := rlp.DecodeBytes(enc, &info); err != nil { + panic(fmt.Sprintf("failed to decode coin info %s: %s", symbol.String(), err)) + } + + coin.info = &info + } + + c.setToMap(symbol, coin) + + return coin +} + +func (c *Coins) markDirty(symbol types.CoinSymbol) { + c.dirty[symbol] = struct{}{} +} + +func (c *Coins) getOrderedDirtyCoins() []types.CoinSymbol { + keys := make([]types.CoinSymbol, 0, len(c.dirty)) + for k := range c.dirty { + keys = append(keys, k) + } + + sort.SliceStable(keys, func(i, j int) bool { + return bytes.Compare(keys[i].Bytes(), keys[j].Bytes()) == 1 + }) + + return keys +} + +func (c *Coins) Export(state *types.AppState) { + var coins []types.Coin + + c.iavl.Iterate(func(key []byte, value []byte) bool { + if key[0] == mainPrefix { + if len(key[1:]) > types.CoinSymbolLength { + return false + } + + coinSymbol := types.StrToCoinSymbol(string(key[1:])) + coin := c.GetCoin(coinSymbol) + + coinModel := types.Coin{ + Name: coin.Name(), + Symbol: coin.Symbol(), + Volume: coin.Volume().String(), + Crr: coin.Crr(), + Reserve: coin.Reserve().String(), + MaxSupply: coin.MaxSupply().String(), + } + + coins = append(coins, coinModel) + } + + return false + }) + + sort.Slice(coins[:], func(i, j int) bool { + return helpers.StringToBigInt(coins[i].Reserve).Cmp(helpers.StringToBigInt(coins[j].Reserve)) == 1 + }) + + for i, _ := range coins { + coins[i].ID = types.CoinID(i + 1) + } + + state.Coins = coins + state.CoinsCount = uint32(len(state.Coins)) +} + +func (c *Coins) getFromMap(symbol types.CoinSymbol) *Model { + c.lock.RLock() + defer c.lock.RUnlock() + + return c.list[symbol] +} + +func (c *Coins) setToMap(symbol types.CoinSymbol, model *Model) { + c.lock.Lock() + defer c.lock.Unlock() + + c.list[symbol] = model +} \ No newline at end of file diff --git a/core/state/legacy/coins/model.go b/core/state/legacy/coins/model.go new file mode 100644 index 000000000..262fc1146 --- /dev/null +++ b/core/state/legacy/coins/model.go @@ -0,0 +1,107 @@ +package coins + +import ( + "fmt" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/helpers" + "math/big" +) + +var minCoinReserve = helpers.BipToPip(big.NewInt(10000)) + +type Model struct { + CName string + CCrr uint + CMaxSupply *big.Int + + symbol types.CoinSymbol + info *Info + markDirty func(symbol types.CoinSymbol) + isDirty bool +} + +func (m Model) Name() string { + return m.CName +} + +func (m Model) Symbol() types.CoinSymbol { + return m.symbol +} + +func (m Model) Crr() uint { + return m.CCrr +} + +func (m Model) Volume() *big.Int { + return big.NewInt(0).Set(m.info.Volume) +} + +func (m Model) Reserve() *big.Int { + return big.NewInt(0).Set(m.info.Reserve) +} + +func (m *Model) SubVolume(amount *big.Int) { + m.info.Volume.Sub(m.info.Volume, amount) + m.markDirty(m.symbol) + m.info.isDirty = true +} + +func (m *Model) AddVolume(amount *big.Int) { + m.info.Volume.Add(m.info.Volume, amount) + m.markDirty(m.symbol) + m.info.isDirty = true +} + +func (m *Model) SubReserve(amount *big.Int) { + m.info.Reserve.Sub(m.info.Reserve, amount) + m.markDirty(m.symbol) + m.info.isDirty = true +} + +func (m *Model) AddReserve(amount *big.Int) { + m.info.Reserve.Add(m.info.Reserve, amount) + m.markDirty(m.symbol) + m.info.isDirty = true +} + +func (m *Model) SetReserve(reserve *big.Int) { + m.info.Reserve.Set(reserve) + m.markDirty(m.symbol) + m.info.isDirty = true +} + +func (m *Model) SetVolume(volume *big.Int) { + m.info.Volume.Set(volume) + m.markDirty(m.symbol) + m.info.isDirty = true +} + +func (m *Model) CheckReserveUnderflow(delta *big.Int) error { + total := big.NewInt(0).Sub(m.Reserve(), delta) + + if total.Cmp(minCoinReserve) == -1 { + min := big.NewInt(0).Add(minCoinReserve, delta) + return fmt.Errorf("coin %s reserve is too small (%s, required at least %s)", m.symbol.String(), m.Reserve().String(), min.String()) + } + + return nil +} + +func (m Model) IsInfoDirty() bool { + return m.info.isDirty +} + +func (m Model) IsDirty() bool { + return m.isDirty +} + +func (m Model) MaxSupply() *big.Int { + return m.CMaxSupply +} + +type Info struct { + Volume *big.Int + Reserve *big.Int + + isDirty bool +} diff --git a/core/state/legacy/frozenfunds/frozen_funds.go b/core/state/legacy/frozenfunds/frozen_funds.go new file mode 100644 index 000000000..02e96162c --- /dev/null +++ b/core/state/legacy/frozenfunds/frozen_funds.go @@ -0,0 +1,119 @@ +package frozenfunds + +import ( + "encoding/binary" + "fmt" + "github.com/MinterTeam/minter-go-node/core/state/bus" + "github.com/MinterTeam/minter-go-node/core/state/candidates" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/rlp" + "github.com/MinterTeam/minter-go-node/tree" + "sort" + "sync" +) + +const mainPrefix = byte('f') + +type RFrozenFunds interface { + Export(state *types.AppState, height uint64) +} + +type FrozenFunds struct { + list map[uint64]*Model + dirty map[uint64]interface{} + + bus *bus.Bus + iavl tree.MTree + + lock sync.RWMutex +} + +func NewFrozenFunds(stateBus *bus.Bus, iavl tree.MTree) (*FrozenFunds, error) { + frozenfunds := &FrozenFunds{bus: stateBus, iavl: iavl, list: map[uint64]*Model{}, dirty: map[uint64]interface{}{}} + return frozenfunds, nil +} + +func (f *FrozenFunds) get(height uint64) *Model { + if ff := f.getFromMap(height); ff != nil { + return ff + } + + _, enc := f.iavl.Get(getPath(height)) + if len(enc) == 0 { + return nil + } + + ff := &Model{} + if err := rlp.DecodeBytes(enc, ff); err != nil { + panic(fmt.Sprintf("failed to decode frozen funds at height %d: %s", height, err)) + } + + ff.height = height + ff.markDirty = f.markDirty + + f.setToMap(height, ff) + + return ff +} + +func (f *FrozenFunds) markDirty(height uint64) { + f.dirty[height] = struct{}{} +} + +func (f *FrozenFunds) getOrderedDirty() []uint64 { + keys := make([]uint64, 0, len(f.dirty)) + for k := range f.dirty { + keys = append(keys, k) + } + + sort.SliceStable(keys, func(i, j int) bool { + return keys[i] < keys[j] + }) + + return keys +} + +func (f *FrozenFunds) Export(state *types.AppState, height uint64) { + coinsSymbolToID := make(map[types.CoinSymbol]types.CoinID, len(state.Coins)) + for _, c := range state.Coins { + coinsSymbolToID[c.Symbol] = c.ID + } + + for i := height; i <= height+candidates.UnbondPeriod; i++ { + frozenFunds := f.get(i) + if frozenFunds == nil { + continue + } + + for _, frozenFund := range frozenFunds.List { + state.FrozenFunds = append(state.FrozenFunds, types.FrozenFund{ + Height: i, + Address: frozenFund.Address, + CandidateKey: frozenFund.CandidateKey, + Coin: coinsSymbolToID[frozenFund.Coin], + Value: frozenFund.Value.String(), + }) + } + } +} + +func (f *FrozenFunds) getFromMap(height uint64) *Model { + f.lock.RLock() + defer f.lock.RUnlock() + + return f.list[height] +} + +func (f *FrozenFunds) setToMap(height uint64, model *Model) { + f.lock.Lock() + defer f.lock.Unlock() + + f.list[height] = model +} + +func getPath(height uint64) []byte { + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, height) + + return append([]byte{mainPrefix}, b...) +} \ No newline at end of file diff --git a/core/state/legacy/frozenfunds/model.go b/core/state/legacy/frozenfunds/model.go new file mode 100644 index 000000000..44372e3f5 --- /dev/null +++ b/core/state/legacy/frozenfunds/model.go @@ -0,0 +1,40 @@ +package frozenfunds + +import ( + "github.com/MinterTeam/minter-go-node/core/types" + "math/big" +) + +type Item struct { + Address types.Address + CandidateKey *types.Pubkey + Coin types.CoinSymbol + Value *big.Int +} + +type Model struct { + List []Item + + height uint64 + deleted bool + markDirty func(height uint64) +} + +func (m *Model) delete() { + m.deleted = true + m.markDirty(m.height) +} + +func (m *Model) addFund(address types.Address, pubkey types.Pubkey, coin types.CoinSymbol, value *big.Int) { + m.List = append(m.List, Item{ + Address: address, + CandidateKey: &pubkey, + Coin: coin, + Value: value, + }) + m.markDirty(m.height) +} + +func (m *Model) Height() uint64 { + return m.height +} \ No newline at end of file diff --git a/core/state/legacy/states.go b/core/state/legacy/states.go deleted file mode 100644 index 97c7d05f7..000000000 --- a/core/state/legacy/states.go +++ /dev/null @@ -1,3 +0,0 @@ -package legacy - - diff --git a/core/state/state.go b/core/state/state.go index a0e5a35b0..472648d31 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -5,13 +5,18 @@ import ( "fmt" eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/state/accounts" + legacyAccounts "github.com/MinterTeam/minter-go-node/core/state/legacy/accounts" "github.com/MinterTeam/minter-go-node/core/state/app" + legacyApp "github.com/MinterTeam/minter-go-node/core/state/legacy/app" "github.com/MinterTeam/minter-go-node/core/state/bus" "github.com/MinterTeam/minter-go-node/core/state/candidates" + legacyCandidates "github.com/MinterTeam/minter-go-node/core/state/legacy/candidates" "github.com/MinterTeam/minter-go-node/core/state/checker" "github.com/MinterTeam/minter-go-node/core/state/checks" "github.com/MinterTeam/minter-go-node/core/state/coins" + legacyCoins "github.com/MinterTeam/minter-go-node/core/state/legacy/coins" "github.com/MinterTeam/minter-go-node/core/state/frozenfunds" + legacyFrozenfunds "github.com/MinterTeam/minter-go-node/core/state/legacy/frozenfunds" "github.com/MinterTeam/minter-go-node/core/state/halts" "github.com/MinterTeam/minter-go-node/core/state/validators" "github.com/MinterTeam/minter-go-node/core/types" @@ -280,16 +285,66 @@ func (s *State) Export(height uint64) types.AppState { appState := new(types.AppState) state.App().Export(appState, height) - //state.Validators().Export(appState) - //state.Candidates().Export(appState) - //state.FrozenFunds().Export(appState, height) - //state.Accounts().Export(appState) + state.Validators().Export(appState) + state.Candidates().Export(appState) + state.FrozenFunds().Export(appState, height) + state.Accounts().Export(appState) state.Coins().Export(appState) - //state.Checks().Export(appState) + state.Checks().Export(appState) return *appState } +func (s *State) Export11To12(height uint64) types.AppState { + iavlTree := tree.NewImmutableTree(height, s.db) + + candidatesState, err := legacyCandidates.NewCandidates(nil, iavlTree) + if err != nil { + log.Panicf("Create new state at height %d failed: %s", height, err) + } + + validatorsState, err := validators.NewValidators(nil, iavlTree) + if err != nil { + log.Panicf("Create new state at height %d failed: %s", height, err) + } + + appState, err := legacyApp.NewApp(nil, iavlTree) + if err != nil { + log.Panicf("Create new state at height %d failed: %s", height, err) + } + + frozenFundsState, err := legacyFrozenfunds.NewFrozenFunds(nil, iavlTree) + if err != nil { + log.Panicf("Create new state at height %d failed: %s", height, err) + } + + accountsState, err := legacyAccounts.NewAccounts(nil, iavlTree) + if err != nil { + log.Panicf("Create new state at height %d failed: %s", height, err) + } + + coinsState, err := legacyCoins.NewCoins(nil, iavlTree) + if err != nil { + log.Panicf("Create new state at height %d failed: %s", height, err) + } + + checksState, err := checks.NewChecks(iavlTree) + if err != nil { + log.Panicf("Create new state at height %d failed: %s", height, err) + } + + state := new(types.AppState) + appState.Export(state, height) + coinsState.Export(state) + validatorsState.Export(state) + candidatesState.Export(state) + frozenFundsState.Export(state, height) + accountsState.Export(state) + checksState.Export(state) + + return *state +} + func newCheckStateForTree(iavlTree tree.MTree, events eventsdb.IEventsDB, db db.DB, keepLastStates int64) (*CheckState, error) { stateForTree, err := newStateForTree(iavlTree, events, db, keepLastStates) if err != nil { diff --git a/core/types/appstate.go b/core/types/appstate.go index 3e18de728..198f08cbf 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -19,6 +19,7 @@ type AppState struct { UsedChecks []UsedCheck `json:"used_checks,omitempty"` MaxGas uint64 `json:"max_gas"` TotalSlashed string `json:"total_slashed"` + CoinsCount uint32 `json:"coins_count"` } func (s *AppState) Verify() error { From 1a3dd63fbe47e9d97c86d108cc252ed8fbf00e3f Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 10 Jul 2020 20:43:10 +0300 Subject: [PATCH 056/426] edit stakes iavl key --- core/state/candidates/candidates.go | 15 +++++++-------- core/state/candidates/model.go | 7 +++++++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 88f21d055..23f605064 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -111,7 +111,7 @@ func (c *Candidates) Commit() error { if candidate.isTotalStakeDirty { path := []byte{mainPrefix} - path = append(path, pubkey[:]...) + path = append(path, candidate.idBytes()...) path = append(path, totalStakePrefix) c.iavl.Set(path, candidate.totalBipStake.Bytes()) candidate.isTotalStakeDirty = false @@ -125,7 +125,7 @@ func (c *Candidates) Commit() error { candidate.dirtyStakes[index] = false path := []byte{mainPrefix} - path = append(path, pubkey[:]...) + path = append(path, candidate.idBytes()...) path = append(path, stakesPrefix) path = append(path, []byte(fmt.Sprintf("%d", index))...) @@ -150,7 +150,7 @@ func (c *Candidates) Commit() error { } path := []byte{mainPrefix} - path = append(path, pubkey[:]...) + path = append(path, candidate.idBytes()...) path = append(path, updatesPrefix) c.iavl.Set(path, data) candidate.isUpdatesDirty = false @@ -782,7 +782,7 @@ func (c *Candidates) LoadCandidates() { for _, candidate := range candidates { // load total stake - path = append([]byte{mainPrefix}, candidate.PubKey.Bytes()...) + path = append([]byte{mainPrefix}, candidate.idBytes()...) path = append(path, totalStakePrefix) _, enc = c.iavl.Get(path) if len(enc) == 0 { @@ -999,7 +999,6 @@ func (c *Candidates) Export(state *types.AppState) { Stakes: stakes, }) } - } func (c *Candidates) getOrderedCandidates() []types.Pubkey { @@ -1067,7 +1066,7 @@ func (c *Candidates) LoadStakesOfCandidate(pubkey types.Pubkey) { stakesCount := 0 for index := 0; index < MaxDelegatorsPerCandidate; index++ { path := []byte{mainPrefix} - path = append(path, candidate.PubKey.Bytes()...) + path = append(path, candidate.idBytes()...) path = append(path, stakesPrefix) path = append(path, []byte(fmt.Sprintf("%d", index))...) _, enc := c.iavl.Get(path) @@ -1090,7 +1089,7 @@ func (c *Candidates) LoadStakesOfCandidate(pubkey types.Pubkey) { // load updates path := []byte{mainPrefix} - path = append(path, candidate.PubKey.Bytes()...) + path = append(path, candidate.idBytes()...) path = append(path, updatesPrefix) _, enc := c.iavl.Get(path) if len(enc) == 0 { @@ -1113,7 +1112,7 @@ func (c *Candidates) LoadStakesOfCandidate(pubkey types.Pubkey) { } // load total stake - path = append([]byte{mainPrefix}, candidate.PubKey.Bytes()...) + path = append([]byte{mainPrefix}, candidate.idBytes()...) path = append(path, totalStakePrefix) _, enc = c.iavl.Get(path) if len(enc) == 0 { diff --git a/core/state/candidates/model.go b/core/state/candidates/model.go index 07791ed08..cff1bcea0 100644 --- a/core/state/candidates/model.go +++ b/core/state/candidates/model.go @@ -1,6 +1,7 @@ package candidates import ( + "encoding/binary" "github.com/MinterTeam/minter-go-node/core/types" "github.com/tendermint/tendermint/crypto/ed25519" "math/big" @@ -33,6 +34,12 @@ type Candidate struct { dirtyStakes [MaxDelegatorsPerCandidate]bool } +func (candidate *Candidate) idBytes() []byte { + bs := make([]byte, 4) + binary.LittleEndian.PutUint32(bs, uint32(candidate.ID)) + return bs +} + func (candidate *Candidate) setStatus(status byte) { candidate.isDirty = true candidate.Status = status From 4741eb930eebe42829237efa9dd8ebb446864e61 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Mon, 13 Jul 2020 13:25:28 +0300 Subject: [PATCH 057/426] MN-435: coins full symbol --- api/coin_info.go | 5 +- cmd/minter/cmd/export.go | 8 +-- core/events/types.go | 16 +++--- core/state/app/app.go | 6 +-- core/state/app/model.go | 6 +-- core/state/coins/coins.go | 52 ++++++++++++------- core/state/coins/model.go | 25 +++++++-- core/state/legacy/accounts/accounts.go | 2 +- core/state/legacy/accounts/model.go | 2 +- core/state/legacy/candidates/candidates.go | 3 +- core/state/legacy/candidates/model.go | 2 +- core/state/legacy/coins/coins.go | 2 +- core/state/legacy/frozenfunds/frozen_funds.go | 2 +- core/state/legacy/frozenfunds/model.go | 2 +- core/state/state.go | 11 ++-- core/types/appstate.go | 22 ++++---- core/types/types.go | 8 ++- 17 files changed, 105 insertions(+), 69 deletions(-) diff --git a/api/coin_info.go b/api/coin_info.go index fb24e3228..cc79ad176 100644 --- a/api/coin_info.go +++ b/api/coin_info.go @@ -6,7 +6,7 @@ import ( ) type CoinInfoResponse struct { - ID uint64 `json:"id"` + ID uint32 `json:"id"` Name string `json:"name"` Symbol string `json:"symbol"` Volume string `json:"volume"` @@ -30,8 +30,9 @@ func CoinInfo(coinSymbol string, height int) (*CoinInfoResponse, error) { } return &CoinInfoResponse{ + ID: coin.ID().Uint32(), Name: coin.Name(), - Symbol: coin.Symbol().String(), + Symbol: coin.GetFullSymbol(), Volume: coin.Volume().String(), Crr: coin.Crr(), ReserveBalance: coin.Reserve().String(), diff --git a/cmd/minter/cmd/export.go b/cmd/minter/cmd/export.go index 06de22993..195af26f3 100644 --- a/cmd/minter/cmd/export.go +++ b/cmd/minter/cmd/export.go @@ -97,10 +97,10 @@ func export(cmd *cobra.Command, args []string) error { AppState: json.RawMessage(jsonBytes), } - //err = genesis.ValidateAndComplete() - //if err != nil { - // log.Panicf("Failed to validate: %s", err) - //} + err = genesis.ValidateAndComplete() + if err != nil { + log.Panicf("Failed to validate: %s", err) + } if err := genesis.SaveAs(genesisPath); err != nil { log.Panicf("Failed to save genesis file: %s", err) diff --git a/core/events/types.go b/core/events/types.go index 46c8384be..9a46d3f4a 100644 --- a/core/events/types.go +++ b/core/events/types.go @@ -154,10 +154,10 @@ func (s *slash) pubKeyID() uint16 { } type SlashEvent struct { - Address types.Address `json:"address"` - Amount string `json:"amount"` - Coin types.CoinID `json:"coin"` - ValidatorPubKey types.Pubkey `json:"validator_pub_key"` + Address types.Address `json:"address"` + Amount string `json:"amount"` + Coin types.CoinID `json:"coin"` + ValidatorPubKey types.Pubkey `json:"validator_pub_key"` } func (se *SlashEvent) AddressString() string { @@ -211,10 +211,10 @@ func (u *unbond) pubKeyID() uint16 { } type UnbondEvent struct { - Address types.Address `json:"address"` - Amount string `json:"amount"` - Coin types.CoinID `json:"coin"` - ValidatorPubKey types.Pubkey `json:"validator_pub_key"` + Address types.Address `json:"address"` + Amount string `json:"amount"` + Coin types.CoinID `json:"coin"` + ValidatorPubKey types.Pubkey `json:"validator_pub_key"` } func (ue *UnbondEvent) AddressString() string { diff --git a/core/state/app/app.go b/core/state/app/app.go index 91edbf4ad..b23eace64 100644 --- a/core/state/app/app.go +++ b/core/state/app/app.go @@ -15,7 +15,7 @@ type RApp interface { Export(state *types.AppState, height uint64) GetMaxGas() uint64 GetTotalSlashed() *big.Int - GetCoinsCount() uint64 + GetCoinsCount() uint32 } func (v *App) Tree() tree.ReadOnlyTree { @@ -126,11 +126,11 @@ func (v *App) SetTotalSlashed(amount *big.Int) { v.getOrNew().setTotalSlashed(amount) } -func (v *App) GetCoinsCount() uint64 { +func (v *App) GetCoinsCount() uint32 { return v.getOrNew().getCoinsCount() } -func (v *App) SetCoinsCount(count uint64) { +func (v *App) SetCoinsCount(count uint32) { v.getOrNew().setCoinsCount(count) } diff --git a/core/state/app/model.go b/core/state/app/model.go index 53374413c..3ca80ec15 100644 --- a/core/state/app/model.go +++ b/core/state/app/model.go @@ -4,7 +4,7 @@ import "math/big" type Model struct { TotalSlashed *big.Int - CoinsCount uint64 + CoinsCount uint32 MaxGas uint64 markDirty func() @@ -36,11 +36,11 @@ func (model *Model) setTotalSlashed(totalSlashed *big.Int) { model.TotalSlashed = totalSlashed } -func (model *Model) getCoinsCount() uint64 { +func (model *Model) getCoinsCount() uint32 { return model.CoinsCount } -func (model *Model) setCoinsCount(count uint64) { +func (model *Model) setCoinsCount(count uint32) { if model.CoinsCount != count { model.markDirty() } diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index 265fea0b2..861b3f4ad 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -12,8 +12,8 @@ import ( ) const ( - mainPrefix = byte('q') - infoPrefix = byte('i') + mainPrefix = byte('q') + infoPrefix = byte('i') ) type RCoins interface { @@ -50,6 +50,19 @@ func (c *Coins) Commit() error { delete(c.dirty, id) c.lock.Unlock() + if coin.IsCreated() { + ids := c.getBySymbol(coin.Symbol()) + ids = append(ids, coin.ID()) + + data, err := rlp.EncodeToBytes(ids) + if err != nil { + return fmt.Errorf("can't encode object at %d: %v", id, err) + } + + c.iavl.Set(getSymbolCoinsPath(coin.Symbol()), data) + coin.isCreated = false + } + if coin.IsDirty() { data, err := rlp.EncodeToBytes(coin) if err != nil { @@ -96,13 +109,15 @@ func (c *Coins) ExistsBySymbol(symbol types.CoinSymbol) bool { func (c *Coins) GetCoinBySymbol(symbol types.CoinSymbol) *Model { coins := c.getBySymbol(symbol.GetBaseSymbol()) - if coins == nil { + if len(coins) == 0 { return nil } - for _, c := range *coins { - if c.Version() == symbol.GetVersion() { - return &c + for _, coinID := range coins { + coin := c.get(coinID) + if coin.Version() == symbol.GetVersion() { + coin.symbol = symbol + return coin } } @@ -155,6 +170,7 @@ func (c *Coins) Create(id types.CoinID, symbol types.CoinSymbol, name string, symbol: symbol, markDirty: c.markDirty, isDirty: true, + isCreated: true, info: &Info{ Volume: big.NewInt(0), Reserve: big.NewInt(0), @@ -206,17 +222,15 @@ func (c *Coins) get(id types.CoinID) *Model { return coin } -func (c *Coins) getBySymbol(symbol types.CoinSymbol) *[]Model { - coins := &[]Model{} +func (c *Coins) getBySymbol(symbol types.CoinSymbol) []types.CoinID { + var coins []types.CoinID - path := []byte{mainPrefix} - path = append(path, symbol.Bytes()...) - _, enc := c.iavl.Get(path) + _, enc := c.iavl.Get(getSymbolCoinsPath(symbol)) if len(enc) == 0 { - return nil + return coins } - if err := rlp.DecodeBytes(enc, coins); err != nil { + if err := rlp.DecodeBytes(enc, &coins); err != nil { panic(fmt.Sprintf("failed to decode coins by symbol %s: %s", symbol, err)) } @@ -307,14 +321,16 @@ func (c *Coins) setToMap(id types.CoinID, model *Model) { c.list[id] = model } +func getSymbolCoinsPath(symbol types.CoinSymbol) []byte { + return append([]byte{mainPrefix}, symbol.Bytes()...) +} + func getCoinPath(id types.CoinID) []byte { - path := []byte{mainPrefix} - return append(path, id.Bytes()...) + return append([]byte{mainPrefix}, id.Bytes()...) } func getCoinInfoPath(id types.CoinID) []byte { - path := getCoinInfoPath(id) + path := getCoinPath(id) path = append(path, infoPrefix) - path = append(path, id.Bytes()...) return path -} \ No newline at end of file +} diff --git a/core/state/coins/model.go b/core/state/coins/model.go index 2351cf32d..dbb17d2e6 100644 --- a/core/state/coins/model.go +++ b/core/state/coins/model.go @@ -13,13 +13,16 @@ type Model struct { CName string CCrr uint CMaxSupply *big.Int + CVersion uint16 + + id types.CoinID + symbol types.CoinSymbol + info *Info - id types.CoinID - symbol types.CoinSymbol - version uint16 - info *Info markDirty func(symbol types.CoinID) + isDirty bool + isCreated bool } func (m Model) Name() string { @@ -47,7 +50,7 @@ func (m Model) Reserve() *big.Int { } func (m Model) Version() uint16 { - return m.version + return m.CVersion } func (m *Model) SubVolume(amount *big.Int) { @@ -105,10 +108,22 @@ func (m Model) IsDirty() bool { return m.isDirty } +func (m Model) IsCreated() bool { + return m.isCreated +} + func (m Model) MaxSupply() *big.Int { return m.CMaxSupply } +func (m Model) GetFullSymbol() string { + if m.Version() == 0 { + return m.Symbol().String() + } + + return fmt.Sprintf("%s-%d", m.Symbol(), m.Version()) +} + type Info struct { Volume *big.Int Reserve *big.Int diff --git a/core/state/legacy/accounts/accounts.go b/core/state/legacy/accounts/accounts.go index f5054a3e7..3252551fa 100644 --- a/core/state/legacy/accounts/accounts.go +++ b/core/state/legacy/accounts/accounts.go @@ -209,4 +209,4 @@ func (a *Accounts) setToMap(address types.Address, model *Model) { defer a.lock.Unlock() a.list[address] = model -} \ No newline at end of file +} diff --git a/core/state/legacy/accounts/model.go b/core/state/legacy/accounts/model.go index 7e80e1c3f..307773997 100644 --- a/core/state/legacy/accounts/model.go +++ b/core/state/legacy/accounts/model.go @@ -135,4 +135,4 @@ func (model *Model) IsMultisig() bool { func (model *Model) Multisig() Multisig { return model.MultisigData -} \ No newline at end of file +} diff --git a/core/state/legacy/candidates/candidates.go b/core/state/legacy/candidates/candidates.go index 97d7eb317..0748874b3 100644 --- a/core/state/legacy/candidates/candidates.go +++ b/core/state/legacy/candidates/candidates.go @@ -1,4 +1,3 @@ - package candidates import ( @@ -376,4 +375,4 @@ func (c *Candidates) LoadStakesOfCandidate(pubkey types.Pubkey) { candidate.setTmAddress() c.setToMap(candidate.PubKey, candidate) -} \ No newline at end of file +} diff --git a/core/state/legacy/candidates/model.go b/core/state/legacy/candidates/model.go index 93a40d1d6..6b6830b09 100644 --- a/core/state/legacy/candidates/model.go +++ b/core/state/legacy/candidates/model.go @@ -248,4 +248,4 @@ func (c *coinsCache) Set(symbol types.CoinSymbol, totalPower *big.Int, totalAmou c.list[symbol].totalAmount = totalAmount c.list[symbol].totalPower = totalPower -} \ No newline at end of file +} diff --git a/core/state/legacy/coins/coins.go b/core/state/legacy/coins/coins.go index 0cf84fead..85ec67b9a 100644 --- a/core/state/legacy/coins/coins.go +++ b/core/state/legacy/coins/coins.go @@ -152,4 +152,4 @@ func (c *Coins) setToMap(symbol types.CoinSymbol, model *Model) { defer c.lock.Unlock() c.list[symbol] = model -} \ No newline at end of file +} diff --git a/core/state/legacy/frozenfunds/frozen_funds.go b/core/state/legacy/frozenfunds/frozen_funds.go index 02e96162c..77d72f72f 100644 --- a/core/state/legacy/frozenfunds/frozen_funds.go +++ b/core/state/legacy/frozenfunds/frozen_funds.go @@ -116,4 +116,4 @@ func getPath(height uint64) []byte { binary.BigEndian.PutUint64(b, height) return append([]byte{mainPrefix}, b...) -} \ No newline at end of file +} diff --git a/core/state/legacy/frozenfunds/model.go b/core/state/legacy/frozenfunds/model.go index 44372e3f5..826effb1a 100644 --- a/core/state/legacy/frozenfunds/model.go +++ b/core/state/legacy/frozenfunds/model.go @@ -37,4 +37,4 @@ func (m *Model) addFund(address types.Address, pubkey types.Pubkey, coin types.C func (m *Model) Height() uint64 { return m.height -} \ No newline at end of file +} diff --git a/core/state/state.go b/core/state/state.go index 472648d31..d5cdb7cef 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -5,19 +5,19 @@ import ( "fmt" eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/state/accounts" - legacyAccounts "github.com/MinterTeam/minter-go-node/core/state/legacy/accounts" "github.com/MinterTeam/minter-go-node/core/state/app" - legacyApp "github.com/MinterTeam/minter-go-node/core/state/legacy/app" "github.com/MinterTeam/minter-go-node/core/state/bus" "github.com/MinterTeam/minter-go-node/core/state/candidates" - legacyCandidates "github.com/MinterTeam/minter-go-node/core/state/legacy/candidates" "github.com/MinterTeam/minter-go-node/core/state/checker" "github.com/MinterTeam/minter-go-node/core/state/checks" "github.com/MinterTeam/minter-go-node/core/state/coins" - legacyCoins "github.com/MinterTeam/minter-go-node/core/state/legacy/coins" "github.com/MinterTeam/minter-go-node/core/state/frozenfunds" - legacyFrozenfunds "github.com/MinterTeam/minter-go-node/core/state/legacy/frozenfunds" "github.com/MinterTeam/minter-go-node/core/state/halts" + legacyAccounts "github.com/MinterTeam/minter-go-node/core/state/legacy/accounts" + legacyApp "github.com/MinterTeam/minter-go-node/core/state/legacy/app" + legacyCandidates "github.com/MinterTeam/minter-go-node/core/state/legacy/candidates" + legacyCoins "github.com/MinterTeam/minter-go-node/core/state/legacy/coins" + legacyFrozenfunds "github.com/MinterTeam/minter-go-node/core/state/legacy/frozenfunds" "github.com/MinterTeam/minter-go-node/core/state/validators" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/helpers" @@ -222,6 +222,7 @@ func (s *State) Commit() ([]byte, error) { func (s *State) Import(state types.AppState) error { s.App.SetMaxGas(state.MaxGas) s.App.SetTotalSlashed(helpers.StringToBigInt(state.TotalSlashed)) + s.App.SetCoinsCount(state.CoinsCount) for _, a := range state.Accounts { if a.MultisigData != nil { diff --git a/core/types/appstate.go b/core/types/appstate.go index 198f08cbf..7f8bb5dd1 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -221,10 +221,10 @@ type Candidate struct { } type Stake struct { - Owner Address `json:"owner"` - Coin CoinID `json:"coin"` - Value string `json:"value"` - BipValue string `json:"bip_value"` + Owner Address `json:"owner"` + Coin CoinID `json:"coin"` + Value string `json:"value"` + BipValue string `json:"bip_value"` } type Coin struct { @@ -239,11 +239,11 @@ type Coin struct { } type FrozenFund struct { - Height uint64 `json:"height"` - Address Address `json:"address"` - CandidateKey *Pubkey `json:"candidate_key,omitempty"` - Coin CoinID `json:"coin"` - Value string `json:"value"` + Height uint64 `json:"height"` + Address Address `json:"address"` + CandidateKey *Pubkey `json:"candidate_key,omitempty"` + Coin CoinID `json:"coin"` + Value string `json:"value"` } type UsedCheck string @@ -256,8 +256,8 @@ type Account struct { } type Balance struct { - Coin CoinID `json:"coin"` - Value string `json:"value"` + Coin CoinID `json:"coin"` + Value string `json:"value"` } type Multisig struct { diff --git a/core/types/types.go b/core/types/types.go index fb25428da..bc6107dec 100644 --- a/core/types/types.go +++ b/core/types/types.go @@ -181,11 +181,15 @@ func (c CoinID) String() string { } func (c CoinID) Bytes() []byte { - var b []byte - binary.LittleEndian.PutUint32(b, uint32(c)) + b := make([]byte, 4) + binary.BigEndian.PutUint32(b, c.Uint32()) return b } +func (c CoinID) Uint32() uint32 { + return uint32(c) +} + /////////// Address type Address [AddressLength]byte From 1602f8fca76a3886eefb1d51b404a5992086ac11 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 13 Jul 2020 16:58:57 +0300 Subject: [PATCH 058/426] store current max candidate id number --- core/state/candidates/candidates.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 23f605064..8ceffae31 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -2,6 +2,7 @@ package candidates import ( "bytes" + "encoding/binary" "fmt" eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/state/bus" @@ -24,11 +25,12 @@ const ( MaxDelegatorsPerCandidate = 1000 mainPrefix = 'c' - pubKeyIDPrefix = 'i' + pubKeyIDPrefix = 'p' blockListPrefix = 'b' stakesPrefix = 's' totalStakePrefix = 't' updatesPrefix = 'u' + maxIDPrefix = 'i' ) type RCandidates interface { @@ -55,6 +57,7 @@ type Candidates struct { list map[uint]*Candidate blockList map[types.Pubkey]struct{} pubKeyIDs map[types.Pubkey]uint + maxID uint iavl tree.MTree bus *bus.Bus @@ -105,6 +108,8 @@ func (c *Candidates) Commit() error { } c.iavl.Set([]byte{blockListPrefix}, blockListData) + c.iavl.Set([]byte{maxIDPrefix}, c.maxIDBytes()) + for _, pubkey := range keys { candidate := c.getFromMap(pubkey) candidate.isDirty = false @@ -772,7 +777,6 @@ func (c *Candidates) LoadCandidates() { _, enc := c.iavl.Get(path) if len(enc) == 0 { c.list = map[uint]*Candidate{} - return } var candidates []*Candidate @@ -798,7 +802,6 @@ func (c *Candidates) LoadCandidates() { _, blockListEnc := c.iavl.Get([]byte{blockListPrefix}) if len(blockListEnc) == 0 { c.blockList = map[types.Pubkey]struct{}{} - return } var blockList []types.Pubkey @@ -811,6 +814,9 @@ func (c *Candidates) LoadCandidates() { blockListMap[pubkey] = struct{}{} } c.setBlockList(blockListMap) + + _, valueMaxID := c.iavl.Get([]byte{maxIDPrefix}) + c.maxID = uint(binary.LittleEndian.Uint32(valueMaxID)) } func (c *Candidates) checkAndSetLoaded() bool { @@ -1149,7 +1155,8 @@ func (c *Candidates) getOrNewID(pubKey types.Pubkey) uint { c.lock.Lock() defer c.lock.Unlock() - id = uint(len(c.list)) + 1 + c.maxID++ + id = c.maxID c.setPubKeyID(pubKey, id) return id } @@ -1178,3 +1185,9 @@ func (c *Candidates) setBlockPybKey(p types.Pubkey) { } c.blockList[p] = struct{}{} } + +func (c *Candidates) maxIDBytes() []byte { + bs := make([]byte, 4) + binary.LittleEndian.PutUint32(bs, uint32(c.maxID)) + return bs +} From a806850286fee1a40f549a462b847e201d532be8 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 13 Jul 2020 17:01:34 +0300 Subject: [PATCH 059/426] optimize delete block number --- core/state/state.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/state/state.go b/core/state/state.go index f6c70343c..77b175c99 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -160,7 +160,7 @@ func (s *State) Check() error { return nil } -const countBatchBlocksDelete = 100 +const countBatchBlocksDelete = 60 func (s *State) Commit() ([]byte, error) { s.Checker.Reset() @@ -205,7 +205,7 @@ func (s *State) Commit() ([]byte, error) { return hash, err } - if version%countBatchBlocksDelete == 0 && version-countBatchBlocksDelete > s.keepLastStates { + if version%countBatchBlocksDelete == 30 && version-countBatchBlocksDelete > s.keepLastStates { if err := s.tree.DeleteVersionsIfExists(version-countBatchBlocksDelete-s.keepLastStates, version-s.keepLastStates); err != nil { return hash, err } From b372382cdca7a2ac595315f5bbfeec18ff467e9f Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Mon, 13 Jul 2020 18:16:59 +0300 Subject: [PATCH 060/426] MN-435: api resources --- api/address.go | 30 +++++++++++++++++--------- api/addresses.go | 21 +++++++++++------- api/candidate.go | 12 +++++++++-- api/coin_info.go | 21 ++++++++++++------ core/state/accounts/accounts.go | 24 ++++++++++++++------- core/state/bus/coins.go | 23 ++++++++++++++------ core/state/coins/bus.go | 13 ++++++----- core/state/coins/coins.go | 37 +++++++++++++++++++++++--------- core/state/coins/model.go | 23 ++++++++++++-------- core/state/legacy/coins/coins.go | 1 + core/state/state.go | 3 ++- core/transaction/create_coin.go | 1 + core/types/appstate.go | 1 + core/types/types.go | 2 ++ 14 files changed, 146 insertions(+), 66 deletions(-) diff --git a/api/address.go b/api/address.go index 2043f1504..62cc93a67 100644 --- a/api/address.go +++ b/api/address.go @@ -5,8 +5,14 @@ import ( ) type AddressResponse struct { - Balance map[string]string `json:"balance"` - TransactionCount uint64 `json:"transaction_count"` + Balance []BalanceItem `json:"balances"` + TransactionCount uint64 `json:"transaction_count"` +} + +type BalanceItem struct { + CoinID uint32 `json:"coin_id"` + Symbol string `json:"symbol"` + Value string `json:"value"` } func Address(address types.Address, height int) (*AddressResponse, error) { @@ -18,20 +24,24 @@ func Address(address types.Address, height int) (*AddressResponse, error) { cState.RLock() defer cState.RUnlock() + balances := cState.Accounts().GetBalances(address) + response := AddressResponse{ - Balance: make(map[string]string), + Balance: make([]BalanceItem, len(balances)), TransactionCount: cState.Accounts().GetNonce(address), } - balances := cState.Accounts().GetBalances(address) - - for k, v := range balances { - response.Balance[k.String()] = v.String() + for k, b := range balances { + response.Balance[k] = BalanceItem{ + CoinID: b.Coin.ID.Uint32(), + Symbol: b.Coin.GetFullSymbol(), + Value: b.Value.String(), + } } - if _, exists := response.Balance[types.GetBaseCoin().String()]; !exists { - response.Balance[types.GetBaseCoin().String()] = "0" - } + //if _, exists := response.Balance[types.GetBaseCoin().String()]; !exists { + // response.Balance[types.GetBaseCoin().String()] = "0" + //} return &response, nil } diff --git a/api/addresses.go b/api/addresses.go index 0626041e8..12d5e4587 100644 --- a/api/addresses.go +++ b/api/addresses.go @@ -6,7 +6,7 @@ import ( type AddressesResponse struct { Address string `json:"address"` - Balance map[string]string `json:"balance"` + Balance []BalanceItem `json:"balances"` TransactionCount uint64 `json:"transaction_count"` } @@ -22,20 +22,25 @@ func Addresses(addresses []types.Address, height int) (*[]AddressesResponse, err response := make([]AddressesResponse, len(addresses)) for i, address := range addresses { + balances := cState.Accounts().GetBalances(address) + data := AddressesResponse{ Address: address.String(), - Balance: make(map[string]string), + Balance: make([]BalanceItem, len(balances)), TransactionCount: cState.Accounts().GetNonce(address), } - balances := cState.Accounts().GetBalances(address) - for k, v := range balances { - data.Balance[k.String()] = v.String() + for k, b := range balances { + data.Balance[k] = BalanceItem{ + CoinID: b.Coin.ID.Uint32(), + Symbol: b.Coin.GetFullSymbol(), + Value: b.Value.String(), + } } - if _, exists := data.Balance[types.GetBaseCoin().String()]; !exists { - data.Balance[types.GetBaseCoin().String()] = "0" - } + //if _, exists := data.Balance[types.GetBaseCoin().String()]; !exists { + // data.Balance[types.GetBaseCoin().String()] = "0" + //} response[i] = data } diff --git a/api/candidate.go b/api/candidate.go index 1477de12b..bcbf604af 100644 --- a/api/candidate.go +++ b/api/candidate.go @@ -7,9 +7,14 @@ import ( "github.com/MinterTeam/minter-go-node/rpc/lib/types" ) +type Coin struct { + ID uint32 `json:"id"` + Symbol string `json:"symbol"` +} + type Stake struct { Owner string `json:"owner"` - Coin string `json:"coin"` + Coin Coin `json:"coin"` Value string `json:"value"` BipValue string `json:"bip_value"` } @@ -40,7 +45,10 @@ func makeResponseCandidate(state *state.CheckState, c candidates.Candidate, incl for i, stake := range stakes { candidate.Stakes[i] = Stake{ Owner: stake.Owner.String(), - Coin: stake.Coin.String(), + Coin: Coin{ + ID: stake.Coin.Uint32(), + Symbol: state.Coins().GetCoin(stake.Coin).GetFullSymbol(), + }, Value: stake.Value.String(), BipValue: stake.BipValue.String(), } diff --git a/api/coin_info.go b/api/coin_info.go index cc79ad176..6f64fc14b 100644 --- a/api/coin_info.go +++ b/api/coin_info.go @@ -6,13 +6,14 @@ import ( ) type CoinInfoResponse struct { - ID uint32 `json:"id"` - Name string `json:"name"` - Symbol string `json:"symbol"` - Volume string `json:"volume"` - Crr uint `json:"crr"` - ReserveBalance string `json:"reserve_balance"` - MaxSupply string `json:"max_supply"` + ID uint32 `json:"id"` + Name string `json:"name"` + Symbol string `json:"symbol"` + Volume string `json:"volume"` + Crr uint `json:"crr"` + ReserveBalance string `json:"reserve_balance"` + MaxSupply string `json:"max_supply"` + OwnerAddress *string `json:"owner_address"` } func CoinInfo(coinSymbol string, height int) (*CoinInfoResponse, error) { @@ -29,6 +30,11 @@ func CoinInfo(coinSymbol string, height int) (*CoinInfoResponse, error) { return nil, rpctypes.RPCError{Code: 404, Message: "Coin not found"} } + var ownerAddress string + if coin.OwnerAddress() != (types.Address{}) { + ownerAddress = coin.OwnerAddress().String() + } + return &CoinInfoResponse{ ID: coin.ID().Uint32(), Name: coin.Name(), @@ -37,5 +43,6 @@ func CoinInfo(coinSymbol string, height int) (*CoinInfoResponse, error) { Crr: coin.Crr(), ReserveBalance: coin.Reserve().String(), MaxSupply: coin.MaxSupply().String(), + OwnerAddress: &ownerAddress, }, nil } diff --git a/core/state/accounts/accounts.go b/core/state/accounts/accounts.go index f7ad97f4a..f119abcba 100644 --- a/core/state/accounts/accounts.go +++ b/core/state/accounts/accounts.go @@ -23,7 +23,7 @@ type RAccounts interface { GetAccount(address types.Address) *Model GetNonce(address types.Address) uint64 GetBalance(address types.Address, coin types.CoinID) *big.Int - GetBalances(address types.Address) map[types.CoinID]*big.Int + GetBalances(address types.Address) []Balance ExistsMultisig(msigAddress types.Address) bool } @@ -37,6 +37,11 @@ type Accounts struct { lock sync.RWMutex } +type Balance struct { + Coin bus.Coin + Value *big.Int +} + func NewAccounts(stateBus *bus.Bus, iavl tree.MTree) (*Accounts, error) { accounts := &Accounts{iavl: iavl, bus: stateBus, list: map[types.Address]*Model{}, dirty: map[types.Address]struct{}{}} accounts.bus.SetAccounts(NewBus(accounts)) @@ -284,12 +289,15 @@ func (a *Accounts) GetNonce(address types.Address) uint64 { return account.Nonce } -func (a *Accounts) GetBalances(address types.Address) map[types.CoinID]*big.Int { +func (a *Accounts) GetBalances(address types.Address) []Balance { account := a.getOrNew(address) - balances := make(map[types.CoinID]*big.Int, len(account.coins)) - for _, coin := range account.coins { - balances[coin] = a.GetBalance(address, coin) + balances := make([]Balance, len(account.coins)) + for key, id := range account.coins { + balances[key] = Balance{ + Coin: *a.bus.Coins().GetCoin(id), + Value: a.GetBalance(address, id), + } } return balances @@ -322,10 +330,10 @@ func (a *Accounts) Export(state *types.AppState) { account := a.get(address) var balance []types.Balance - for coin, value := range a.GetBalances(account.address) { + for _, b := range a.GetBalances(account.address) { balance = append(balance, types.Balance{ - Coin: coin, - Value: value.String(), + Coin: b.Coin.ID, + Value: b.Value.String(), }) } diff --git a/core/state/bus/coins.go b/core/state/bus/coins.go index 750c83bf4..f85533c5a 100644 --- a/core/state/bus/coins.go +++ b/core/state/bus/coins.go @@ -1,6 +1,7 @@ package bus import ( + "fmt" "github.com/MinterTeam/minter-go-node/core/types" "math/big" ) @@ -12,10 +13,20 @@ type Coins interface { } type Coin struct { - ID types.CoinID - Name string - Crr uint - Symbol types.CoinSymbol - Volume *big.Int - Reserve *big.Int + ID types.CoinID + Name string + Crr uint + Symbol types.CoinSymbol + Version types.CoinVersion + Volume *big.Int + Reserve *big.Int + OwnerAddress types.Address +} + +func (m Coin) GetFullSymbol() string { + if m.Version == 0 { + return m.Symbol.String() + } + + return fmt.Sprintf("%s-%d", m.Symbol, m.Version) } diff --git a/core/state/coins/bus.go b/core/state/coins/bus.go index 44242414b..fd1f7a3b7 100644 --- a/core/state/coins/bus.go +++ b/core/state/coins/bus.go @@ -21,11 +21,14 @@ func (b *Bus) GetCoin(id types.CoinID) *bus.Coin { } return &bus.Coin{ - Name: coin.Name(), - Crr: coin.Crr(), - Symbol: coin.Symbol(), - Volume: coin.Volume(), - Reserve: coin.Reserve(), + ID: coin.id, + Name: coin.Name(), + Crr: coin.Crr(), + Symbol: coin.Symbol(), + Volume: coin.Volume(), + Reserve: coin.Reserve(), + Version: coin.Version(), + OwnerAddress: coin.OwnerAddress(), } } diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index 861b3f4ad..6d5d536c3 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -116,7 +116,6 @@ func (c *Coins) GetCoinBySymbol(symbol types.CoinSymbol) *Model { for _, coinID := range coins { coin := c.get(coinID) if coin.Version() == symbol.GetVersion() { - coin.symbol = symbol return coin } } @@ -161,16 +160,22 @@ func (c *Coins) AddReserve(id types.CoinID, amount *big.Int) { } func (c *Coins) Create(id types.CoinID, symbol types.CoinSymbol, name string, - volume *big.Int, crr uint, reserve *big.Int, maxSupply *big.Int) { + volume *big.Int, crr uint, reserve *big.Int, maxSupply *big.Int, owner *types.Address, +) { + if owner == nil { + owner = &types.Address{} + } + coin := &Model{ - CName: name, - CCrr: crr, - CMaxSupply: maxSupply, - id: id, - symbol: symbol, - markDirty: c.markDirty, - isDirty: true, - isCreated: true, + CName: name, + CCrr: crr, + CMaxSupply: maxSupply, + CSymbol: symbol, + COwnerAddress: *owner, + id: id, + markDirty: c.markDirty, + isDirty: true, + isCreated: true, info: &Info{ Volume: big.NewInt(0), Reserve: big.NewInt(0), @@ -189,6 +194,18 @@ func (c *Coins) Create(id types.CoinID, symbol types.CoinSymbol, name string, } func (c *Coins) get(id types.CoinID) *Model { + if id.IsBaseCoin() { + // TODO: refactor + return &Model{ + id: types.GetBaseCoinID(), + CSymbol: types.GetBaseCoin(), + info: &Info{ + Volume: big.NewInt(0), + Reserve: big.NewInt(0), + }, + } + } + if coin := c.getFromMap(id); coin != nil { return coin } diff --git a/core/state/coins/model.go b/core/state/coins/model.go index dbb17d2e6..2e63dcdea 100644 --- a/core/state/coins/model.go +++ b/core/state/coins/model.go @@ -10,14 +10,15 @@ import ( var minCoinReserve = helpers.BipToPip(big.NewInt(10000)) type Model struct { - CName string - CCrr uint - CMaxSupply *big.Int - CVersion uint16 + CName string + CCrr uint + CMaxSupply *big.Int + CVersion types.CoinVersion + CSymbol types.CoinSymbol + COwnerAddress types.Address - id types.CoinID - symbol types.CoinSymbol - info *Info + id types.CoinID + info *Info markDirty func(symbol types.CoinID) @@ -30,7 +31,7 @@ func (m Model) Name() string { } func (m Model) Symbol() types.CoinSymbol { - return m.symbol + return m.CSymbol } func (m Model) ID() types.CoinID { @@ -53,6 +54,10 @@ func (m Model) Version() uint16 { return m.CVersion } +func (m Model) OwnerAddress() types.Address { + return m.COwnerAddress +} + func (m *Model) SubVolume(amount *big.Int) { m.info.Volume.Sub(m.info.Volume, amount) m.markDirty(m.id) @@ -94,7 +99,7 @@ func (m *Model) CheckReserveUnderflow(delta *big.Int) error { if total.Cmp(minCoinReserve) == -1 { min := big.NewInt(0).Add(minCoinReserve, delta) - return fmt.Errorf("coin %s reserve is too small (%s, required at least %s)", m.symbol.String(), m.Reserve().String(), min.String()) + return fmt.Errorf("coin %s reserve is too small (%s, required at least %s)", m.CSymbol.String(), m.Reserve().String(), min.String()) } return nil diff --git a/core/state/legacy/coins/coins.go b/core/state/legacy/coins/coins.go index 85ec67b9a..8928fccef 100644 --- a/core/state/legacy/coins/coins.go +++ b/core/state/legacy/coins/coins.go @@ -120,6 +120,7 @@ func (c *Coins) Export(state *types.AppState) { Crr: coin.Crr(), Reserve: coin.Reserve().String(), MaxSupply: coin.MaxSupply().String(), + Version: 0, } coins = append(coins, coinModel) diff --git a/core/state/state.go b/core/state/state.go index d5cdb7cef..846614525 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -237,7 +237,8 @@ func (s *State) Import(state types.AppState) error { } for _, c := range state.Coins { - s.Coins.Create(c.ID, c.Symbol, c.Name, helpers.StringToBigInt(c.Volume), c.Crr, helpers.StringToBigInt(c.Reserve), helpers.StringToBigInt(c.MaxSupply)) + s.Coins.Create(c.ID, c.Symbol, c.Name, helpers.StringToBigInt(c.Volume), + c.Crr, helpers.StringToBigInt(c.Reserve), helpers.StringToBigInt(c.MaxSupply), c.OwnerAddress) } var vals []*validators.Validator diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index 2f19d0b9b..ed14346ec 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -228,6 +228,7 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP data.ConstantReserveRatio, data.InitialReserve, data.MaxSupply, + &sender, ) deliveryState.App.SetCoinsCount(coinID) diff --git a/core/types/appstate.go b/core/types/appstate.go index 7f8bb5dd1..460344267 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -235,6 +235,7 @@ type Coin struct { Crr uint `json:"crr"` Reserve string `json:"reserve"` MaxSupply string `json:"max_supply"` + Version CoinVersion `json:"version"` OwnerAddress *Address `json:"owner_address"` } diff --git a/core/types/types.go b/core/types/types.go index bc6107dec..da4a4ae77 100644 --- a/core/types/types.go +++ b/core/types/types.go @@ -190,6 +190,8 @@ func (c CoinID) Uint32() uint32 { return uint32(c) } +type CoinVersion = uint16 + /////////// Address type Address [AddressLength]byte From 06c92cbeb9e0e8ae664603073e71f99f3204d314 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 13 Jul 2020 18:54:35 +0300 Subject: [PATCH 061/426] fix import --- core/state/candidates/candidates.go | 5 +++-- core/state/state.go | 2 +- core/transaction/declare_candidacy.go | 6 +----- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 8ceffae31..f872e6b1b 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -192,12 +192,13 @@ func (c *Candidates) GetNewCandidates(valCount int) []Candidate { return result } -func (c *Candidates) Create(ownerAddress types.Address, rewardAddress types.Address, pubkey types.Pubkey, commission uint) { +func (c *Candidates) Create(ownerAddress, rewardAddress, controlAddress types.Address, pubkey types.Pubkey, commission uint) { candidate := &Candidate{ + ID: c.getOrNewID(pubkey), PubKey: pubkey, RewardAddress: rewardAddress, OwnerAddress: ownerAddress, - ControlAddress: ownerAddress, + ControlAddress: controlAddress, Commission: commission, Status: CandidateStatusOffline, totalBipStake: big.NewInt(0), diff --git a/core/state/state.go b/core/state/state.go index 42e340611..a1202623a 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -249,7 +249,7 @@ func (s *State) Import(state types.AppState) error { s.Validators.SetValidators(vals) for _, c := range state.Candidates { - s.Candidates.Create(c.OwnerAddress, c.RewardAddress, c.PubKey, c.Commission) + s.Candidates.Create(c.OwnerAddress, c.RewardAddress, c.ControlAddress, c.PubKey, c.Commission) if c.Status == candidates.CandidateStatusOnline { s.Candidates.SetOnline(c.PubKey) } diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index e30dbed7f..df28db904 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -42,10 +42,6 @@ func (data DeclareCandidacyData) MarshalJSON() ([]byte, error) { }) } -func (data DeclareCandidacyData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { - panic("implement me") -} - func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if data.Stake == nil { return &Response{ @@ -204,7 +200,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r deliveryState.Accounts.SubBalance(sender, data.Coin, data.Stake) deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) - deliveryState.Candidates.Create(data.Address, sender, data.PubKey, data.Commission) + deliveryState.Candidates.Create(data.Address, sender, sender, data.PubKey, data.Commission) deliveryState.Candidates.Delegate(sender, data.PubKey, data.Coin, data.Stake, big.NewInt(0)) deliveryState.Accounts.SetNonce(sender, tx.Nonce) } From a35243d66ca3db6f8cdfab8d69754fe1fc43fdf1 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 14 Jul 2020 09:59:44 +0300 Subject: [PATCH 062/426] MN-435: return gas coin with id, symbol --- api/transaction.go | 12 +++++- api/transactions.go | 7 +++- core/state/coins/coins.go | 86 ++++++++++++++------------------------- core/transaction/send.go | 12 +++++- core/types/types.go | 4 ++ 5 files changed, 60 insertions(+), 61 deletions(-) diff --git a/api/transaction.go b/api/transaction.go index 216352742..8aa8d3079 100644 --- a/api/transaction.go +++ b/api/transaction.go @@ -26,6 +26,16 @@ func Transaction(hash []byte) (*TransactionResponse, error) { return nil, err } + cState, err := GetStateForHeight(int(tx.Height)) + if err != nil { + return nil, err + } + + gasCoin := Coin{ + ID: decodedTx.GasCoin.Uint32(), + Symbol: cState.Coins().GetCoin(decodedTx.GasCoin).GetFullSymbol(), + } + return &TransactionResponse{ Hash: bytes.HexBytes(tx.Tx.Hash()).String(), RawTx: fmt.Sprintf("%x", []byte(tx.Tx)), @@ -34,7 +44,7 @@ func Transaction(hash []byte) (*TransactionResponse, error) { From: sender.String(), Nonce: decodedTx.Nonce, GasPrice: decodedTx.GasPrice, - GasCoin: decodedTx.GasCoin.String(), + GasCoin: gasCoin, Gas: decodedTx.Gas(), Type: uint8(decodedTx.Type), Data: data, diff --git a/api/transactions.go b/api/transactions.go index 2b79cd8e8..e5fc23571 100644 --- a/api/transactions.go +++ b/api/transactions.go @@ -17,7 +17,7 @@ type TransactionResponse struct { Nonce uint64 `json:"nonce"` Gas int64 `json:"gas"` GasPrice uint32 `json:"gas_price"` - GasCoin string `json:"gas_coin"` + GasCoin Coin `json:"gas_coin"` Type uint8 `json:"type"` Data json.RawMessage `json:"data"` Payload []byte `json:"payload"` @@ -68,7 +68,10 @@ func Transactions(query string, page, perPage int) (*[]TransactionResponse, erro Nonce: decodedTx.Nonce, Gas: decodedTx.Gas(), GasPrice: decodedTx.GasPrice, - GasCoin: decodedTx.GasCoin.String(), + GasCoin: Coin{ + ID: decodedTx.GasCoin.Uint32(), + Symbol: "", + }, Type: uint8(decodedTx.Type), Data: data, Payload: decodedTx.Payload, diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index 6d5d536c3..3610f4c12 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -12,8 +12,9 @@ import ( ) const ( - mainPrefix = byte('q') - infoPrefix = byte('i') + mainPrefix = byte('q') + infoPrefix = byte('i') + symbolPrefix = byte('s') ) type RCoins interface { @@ -272,56 +273,30 @@ func (c *Coins) getOrderedDirtyCoins() []types.CoinID { } func (c *Coins) Export(state *types.AppState) { - //c.iavl.Iterate(func(key []byte, value []byte) bool { - // if key[0] == mainPrefix { - // if len(key[1:]) > types.CoinSymbolLength { - // return false - // } - // - // coinID := types.CoinID(binary.LittleEndian.Uint32(key[1:])) - // coin := c.GetCoin(coinID) - // - // coinModel := types.Coin{ - // ID: coinID, - // Name: coin.Name(), - // Symbol: coin.Symbol(), - // Volume: coin.Volume().String(), - // Crr: coin.Crr(), - // Reserve: coin.Reserve().String(), - // MaxSupply: coin.MaxSupply().String(), - // } - // - // if coin.ID() != 0 { - // isSortingRequired = false - // } - // - // if isSortingRequired { - // for _, account := range state.Accounts { - // for _, balance := range account.Balance { - // if balance.Coin.String() == coin.Symbol().String() && balance.Value == coin.Volume().String() { - // coinModel.OwnerAddress = &account.Address - // } - // } - // } - // } - // - // coins = append(coins, coinModel) - // } - // - // return false - //}) - // - //if isSortingRequired { - // sort.Slice(coins[:], func(i, j int) bool { - // return helpers.StringToBigInt(coins[i].Reserve).Cmp(helpers.StringToBigInt(coins[j].Reserve)) == 1 - // }) - // - // for i, _ := range coins { - // coins[i].ID = types.CoinID(i + 1) - // } - //} - // - //state.Coins = coins + c.iavl.Iterate(func(key []byte, value []byte) bool { + if key[0] == mainPrefix { + if key[1] == symbolPrefix { + return false + } + + coinID := types.BytesToCoinID(key[1:]) + coin := c.GetCoin(coinID) + + state.Coins = append(state.Coins, types.Coin{ + ID: coin.ID(), + Name: coin.Name(), + Symbol: coin.Symbol(), + Volume: coin.Volume().String(), + Crr: coin.Crr(), + Reserve: coin.Reserve().String(), + MaxSupply: coin.MaxSupply().String(), + Version: coin.Version(), + OwnerAddress: &coin.COwnerAddress, + }) + } + + return false + }) } func (c *Coins) getFromMap(id types.CoinID) *Model { @@ -339,7 +314,8 @@ func (c *Coins) setToMap(id types.CoinID, model *Model) { } func getSymbolCoinsPath(symbol types.CoinSymbol) []byte { - return append([]byte{mainPrefix}, symbol.Bytes()...) + path := append([]byte{mainPrefix}, []byte{symbolPrefix}...) + return append(path, symbol.Bytes()...) } func getCoinPath(id types.CoinID) []byte { @@ -347,7 +323,5 @@ func getCoinPath(id types.CoinID) []byte { } func getCoinInfoPath(id types.CoinID) []byte { - path := getCoinPath(id) - path = append(path, infoPrefix) - return path + return append(getCoinPath(id), infoPrefix) } diff --git a/core/transaction/send.go b/core/transaction/send.go index db30a7e62..afceb479f 100644 --- a/core/transaction/send.go +++ b/core/transaction/send.go @@ -19,13 +19,21 @@ type SendData struct { Value *big.Int } +type Coin struct { + ID uint32 `json:"id"` + Symbol string `json:"symbol"` +} + func (data SendData) MarshalJSON() ([]byte, error) { return json.Marshal(struct { - Coin string `json:"coin"` + Coin Coin `json:"coin"` To string `json:"to"` Value string `json:"value"` }{ - Coin: data.Coin.String(), + Coin: Coin{ + ID: data.Coin.Uint32(), + Symbol: "", + }, To: data.To.String(), Value: data.Value.String(), }) diff --git a/core/types/types.go b/core/types/types.go index da4a4ae77..90079f86f 100644 --- a/core/types/types.go +++ b/core/types/types.go @@ -190,6 +190,10 @@ func (c CoinID) Uint32() uint32 { return uint32(c) } +func BytesToCoinID(bytes []byte) CoinID { + return CoinID(binary.BigEndian.Uint32(bytes)) +} + type CoinVersion = uint16 /////////// Address From ad159a4b701d1683d4d3cfc17bd063dfd722f957 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 14 Jul 2020 13:27:08 +0300 Subject: [PATCH 063/426] MN-435: api transaction resources --- api/addresses.go | 6 +- api/block.go | 9 +- api/candidate.go | 4 +- api/transaction.go | 77 +------ api/transactions.go | 41 +--- core/state/accounts/accounts.go | 8 +- core/transaction/encoder/encoder.go | 102 +++++++++ core/transaction/encoder/resources.go | 303 ++++++++++++++++++++++++++ core/transaction/send.go | 2 +- core/types/appstate.go | 16 +- 10 files changed, 445 insertions(+), 123 deletions(-) create mode 100644 core/transaction/encoder/encoder.go create mode 100644 core/transaction/encoder/resources.go diff --git a/api/addresses.go b/api/addresses.go index 12d5e4587..9c1510c83 100644 --- a/api/addresses.go +++ b/api/addresses.go @@ -5,9 +5,9 @@ import ( ) type AddressesResponse struct { - Address string `json:"address"` - Balance []BalanceItem `json:"balances"` - TransactionCount uint64 `json:"transaction_count"` + Address string `json:"address"` + Balance []BalanceItem `json:"balances"` + TransactionCount uint64 `json:"transaction_count"` } func Addresses(addresses []types.Address, height int) (*[]AddressesResponse, error) { diff --git a/api/block.go b/api/block.go index c86855291..22e62a8d7 100644 --- a/api/block.go +++ b/api/block.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/MinterTeam/minter-go-node/core/rewards" "github.com/MinterTeam/minter-go-node/core/transaction" + "github.com/MinterTeam/minter-go-node/core/transaction/encoder" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/rpc/lib/types" core_types "github.com/tendermint/tendermint/rpc/core/types" @@ -88,7 +89,13 @@ func Block(height int64) (*BlockResponse, error) { tags[string(tag.Key)] = string(tag.Value) } - data, err := encodeTxData(tx) + cState, err := GetStateForHeight(int(height)) + if err != nil { + return nil, err + } + + txJsonEncoder := encoder.NewTxEncoderJSON(cState) + data, err := txJsonEncoder.EncodeData(tx) if err != nil { return nil, err } diff --git a/api/candidate.go b/api/candidate.go index bcbf604af..3e215b42f 100644 --- a/api/candidate.go +++ b/api/candidate.go @@ -44,8 +44,8 @@ func makeResponseCandidate(state *state.CheckState, c candidates.Candidate, incl candidate.Stakes = make([]Stake, len(stakes)) for i, stake := range stakes { candidate.Stakes[i] = Stake{ - Owner: stake.Owner.String(), - Coin: Coin{ + Owner: stake.Owner.String(), + Coin: Coin{ ID: stake.Coin.Uint32(), Symbol: state.Coins().GetCoin(stake.Coin).GetFullSymbol(), }, diff --git a/api/transaction.go b/api/transaction.go index 8aa8d3079..4356b6f80 100644 --- a/api/transaction.go +++ b/api/transaction.go @@ -1,93 +1,24 @@ package api import ( - "fmt" "github.com/MinterTeam/minter-go-node/core/transaction" - "github.com/MinterTeam/minter-go-node/rpc/lib/types" - "github.com/tendermint/tendermint/libs/bytes" + "github.com/MinterTeam/minter-go-node/core/transaction/encoder" ) -func Transaction(hash []byte) (*TransactionResponse, error) { +func Transaction(hash []byte) (*encoder.TransactionResponse, error) { tx, err := client.Tx(hash, false) if err != nil { return nil, err } decodedTx, _ := transaction.TxDecoder.DecodeFromBytes(tx.Tx) - sender, _ := decodedTx.Sender() - - tags := make(map[string]string) - for _, tag := range tx.TxResult.Events[0].Attributes { - tags[string(tag.Key)] = string(tag.Value) - } - - data, err := encodeTxData(decodedTx) - if err != nil { - return nil, err - } cState, err := GetStateForHeight(int(tx.Height)) if err != nil { return nil, err } - gasCoin := Coin{ - ID: decodedTx.GasCoin.Uint32(), - Symbol: cState.Coins().GetCoin(decodedTx.GasCoin).GetFullSymbol(), - } - - return &TransactionResponse{ - Hash: bytes.HexBytes(tx.Tx.Hash()).String(), - RawTx: fmt.Sprintf("%x", []byte(tx.Tx)), - Height: tx.Height, - Index: tx.Index, - From: sender.String(), - Nonce: decodedTx.Nonce, - GasPrice: decodedTx.GasPrice, - GasCoin: gasCoin, - Gas: decodedTx.Gas(), - Type: uint8(decodedTx.Type), - Data: data, - Payload: decodedTx.Payload, - Tags: tags, - Code: tx.TxResult.Code, - Log: tx.TxResult.Log, - }, nil -} - -func encodeTxData(decodedTx *transaction.Transaction) ([]byte, error) { - switch decodedTx.Type { - case transaction.TypeSend: - return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.SendData)) - case transaction.TypeRedeemCheck: - return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.RedeemCheckData)) - case transaction.TypeSellCoin: - return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.SellCoinData)) - case transaction.TypeSellAllCoin: - return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.SellAllCoinData)) - case transaction.TypeBuyCoin: - return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.BuyCoinData)) - case transaction.TypeCreateCoin: - return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.CreateCoinData)) - case transaction.TypeDeclareCandidacy: - return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.DeclareCandidacyData)) - case transaction.TypeDelegate: - return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.DelegateData)) - case transaction.TypeSetCandidateOnline: - return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.SetCandidateOnData)) - case transaction.TypeSetCandidateOffline: - return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.SetCandidateOffData)) - case transaction.TypeUnbond: - return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.UnbondData)) - case transaction.TypeMultisend: - return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.MultisendData)) - case transaction.TypeCreateMultisig: - return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.CreateMultisigData)) - case transaction.TypeEditCandidate: - return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.EditCandidateData)) - case transaction.TypeSetHaltBlock: - return cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.SetHaltBlockData)) - } + txJsonEncoder := encoder.NewTxEncoderJSON(cState) - return nil, rpctypes.RPCError{Code: 500, Message: "unknown tx type"} + return txJsonEncoder.Encode(decodedTx, tx) } diff --git a/api/transactions.go b/api/transactions.go index e5fc23571..650a405b4 100644 --- a/api/transactions.go +++ b/api/transactions.go @@ -2,9 +2,8 @@ package api import ( "encoding/json" - "fmt" "github.com/MinterTeam/minter-go-node/core/transaction" - "github.com/tendermint/tendermint/libs/bytes" + "github.com/MinterTeam/minter-go-node/core/transaction/encoder" core_types "github.com/tendermint/tendermint/rpc/core/types" ) @@ -31,7 +30,7 @@ type ResultTxSearch struct { TotalCount int `json:"total_count"` } -func Transactions(query string, page, perPage int) (*[]TransactionResponse, error) { +func Transactions(query string, page, perPage int) (*[]encoder.TransactionResponse, error) { if page == 0 { page = 1 } @@ -44,41 +43,21 @@ func Transactions(query string, page, perPage int) (*[]TransactionResponse, erro return nil, err } - result := make([]TransactionResponse, len(rpcResult.Txs)) + result := make([]encoder.TransactionResponse, len(rpcResult.Txs)) for i, tx := range rpcResult.Txs { - decodedTx, _ := transaction.TxDecoder.DecodeFromBytes(tx.Tx) - sender, _ := decodedTx.Sender() - - tags := make(map[string]string) - for _, tag := range tx.TxResult.Events[0].Attributes { - tags[string(tag.Key)] = string(tag.Value) + cState, err := GetStateForHeight(int(tx.Height)) + if err != nil { + return nil, err } - data, err := encodeTxData(decodedTx) + decodedTx, _ := transaction.TxDecoder.DecodeFromBytes(tx.Tx) + txJsonEncoder := encoder.NewTxEncoderJSON(cState) + response, err := txJsonEncoder.Encode(decodedTx, tx) if err != nil { return nil, err } - result[i] = TransactionResponse{ - Hash: bytes.HexBytes(tx.Tx.Hash()).String(), - RawTx: fmt.Sprintf("%x", []byte(tx.Tx)), - Height: tx.Height, - Index: tx.Index, - From: sender.String(), - Nonce: decodedTx.Nonce, - Gas: decodedTx.Gas(), - GasPrice: decodedTx.GasPrice, - GasCoin: Coin{ - ID: decodedTx.GasCoin.Uint32(), - Symbol: "", - }, - Type: uint8(decodedTx.Type), - Data: data, - Payload: decodedTx.Payload, - Tags: tags, - Code: tx.TxResult.Code, - Log: tx.TxResult.Log, - } + result[i] = *response } return &result, nil diff --git a/core/state/accounts/accounts.go b/core/state/accounts/accounts.go index f119abcba..2c2661df1 100644 --- a/core/state/accounts/accounts.go +++ b/core/state/accounts/accounts.go @@ -38,8 +38,8 @@ type Accounts struct { } type Balance struct { - Coin bus.Coin - Value *big.Int + Coin bus.Coin + Value *big.Int } func NewAccounts(stateBus *bus.Bus, iavl tree.MTree) (*Accounts, error) { @@ -295,8 +295,8 @@ func (a *Accounts) GetBalances(address types.Address) []Balance { balances := make([]Balance, len(account.coins)) for key, id := range account.coins { balances[key] = Balance{ - Coin: *a.bus.Coins().GetCoin(id), - Value: a.GetBalance(address, id), + Coin: *a.bus.Coins().GetCoin(id), + Value: a.GetBalance(address, id), } } diff --git a/core/transaction/encoder/encoder.go b/core/transaction/encoder/encoder.go new file mode 100644 index 000000000..33eab8943 --- /dev/null +++ b/core/transaction/encoder/encoder.go @@ -0,0 +1,102 @@ +package encoder + +import ( + "encoding/json" + "fmt" + "github.com/MinterTeam/minter-go-node/core/state" + "github.com/MinterTeam/minter-go-node/core/transaction" + rpctypes "github.com/MinterTeam/minter-go-node/rpc/lib/types" + "github.com/tendermint/tendermint/libs/bytes" + coretypes "github.com/tendermint/tendermint/rpc/core/types" +) + +type TxEncoderJSON struct { + state *state.CheckState +} + +type TransactionResponse struct { + Hash string `json:"hash"` + RawTx string `json:"raw_tx"` + Height int64 `json:"height"` + Index uint32 `json:"index"` + From string `json:"from"` + Nonce uint64 `json:"nonce"` + Gas int64 `json:"gas"` + GasPrice uint32 `json:"gas_price"` + GasCoin CoinResource `json:"gas_coin"` + Type uint8 `json:"type"` + Data json.RawMessage `json:"data"` + Payload []byte `json:"payload"` + Tags map[string]string `json:"tags"` + Code uint32 `json:"code,omitempty"` + Log string `json:"log,omitempty"` +} + +var resourcesConfig = map[transaction.TxType]TxDataResource{ + transaction.TypeSend: new(SendDataResource), + transaction.TypeSellCoin: new(SellCoinDataResource), + transaction.TypeSellAllCoin: new(SellAllCoinDataResource), + transaction.TypeBuyCoin: new(BuyCoinDataResource), + transaction.TypeCreateCoin: new(CreateCoinDataResource), + transaction.TypeDeclareCandidacy: new(DeclareCandidacyDataResource), + transaction.TypeDelegate: new(DelegateDataResource), + transaction.TypeUnbond: new(UnbondDataResource), + transaction.TypeRedeemCheck: new(RedeemCheckDataResource), + transaction.TypeSetCandidateOnline: new(SetCandidateOnDataResource), + transaction.TypeSetCandidateOffline: new(SetCandidateOffDataResource), + transaction.TypeCreateMultisig: new(CreateMultisigDataResource), + transaction.TypeMultisend: new(MultiSendDataResource), + transaction.TypeEditCandidate: new(EditCandidateDataResource), + transaction.TypeSetHaltBlock: new(SetHaltBlockDataResource), +} + +func NewTxEncoderJSON(state *state.CheckState) *TxEncoderJSON { + return &TxEncoderJSON{state} +} + +func (encoder *TxEncoderJSON) Encode(transaction *transaction.Transaction, tmTx *coretypes.ResultTx) (*TransactionResponse, error) { + sender, _ := transaction.Sender() + + // prepare transaction data resource + data, err := encoder.EncodeData(transaction) + if err != nil { + return nil, err + } + + // prepare transaction tags + tags := make(map[string]string) + for _, tag := range tmTx.TxResult.Events[0].Attributes { + tags[string(tag.Key)] = string(tag.Value) + } + + gasCoin := encoder.state.Coins().GetCoin(transaction.GasCoin) + txGasCoin := CoinResource{gasCoin.ID().Uint32(), gasCoin.GetFullSymbol()} + + return &TransactionResponse{ + Hash: bytes.HexBytes(tmTx.Tx.Hash()).String(), + RawTx: fmt.Sprintf("%x", []byte(tmTx.Tx)), + Height: tmTx.Height, + Index: tmTx.Index, + From: sender.String(), + Nonce: transaction.Nonce, + Gas: transaction.Gas(), + GasPrice: transaction.GasPrice, + GasCoin: txGasCoin, + Type: uint8(transaction.Type), + Data: data, + Payload: transaction.Payload, + Tags: tags, + Code: tmTx.TxResult.Code, + Log: tmTx.TxResult.Log, + }, nil +} + +func (encoder *TxEncoderJSON) EncodeData(decodedTx *transaction.Transaction) ([]byte, error) { + if resource, exists := resourcesConfig[decodedTx.Type]; exists { + return json.Marshal( + resource.Transform(decodedTx.GetDecodedData(), encoder.state), + ) + } + + return nil, rpctypes.RPCError{Code: 500, Message: "unknown tx type"} +} diff --git a/core/transaction/encoder/resources.go b/core/transaction/encoder/resources.go new file mode 100644 index 000000000..3e591c78c --- /dev/null +++ b/core/transaction/encoder/resources.go @@ -0,0 +1,303 @@ +package encoder + +import ( + "encoding/base64" + "github.com/MinterTeam/minter-go-node/core/state" + "github.com/MinterTeam/minter-go-node/core/transaction" + "github.com/MinterTeam/minter-go-node/core/types" + "strconv" +) + +type TxDataResource interface { + Transform(txData interface{}, state *state.CheckState) TxDataResource +} + +type CoinResource struct { + ID uint32 `json:"id"` + Symbol string `json:"symbol"` +} + +// TxType 0x01 + +type SendDataResource struct { + Coin CoinResource `json:"coin"` + To string `json:"to"` + Value string `json:"value"` +} + +func (SendDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { + data := txData.(*transaction.SendData) + coin := state.Coins().GetCoin(data.Coin) + + return SendDataResource{ + To: data.To.String(), + Value: data.Value.String(), + Coin: CoinResource{coin.ID().Uint32(), coin.GetFullSymbol()}, + } +} + +// TxType 0x02 + +type SellCoinDataResource struct { + CoinToSell CoinResource `json:"coin_to_sell"` + ValueToSell string `json:"value_to_sell"` + CoinToBuy CoinResource `json:"coin_to_buy"` + MinimumValueToBuy string `json:"minimum_value_to_buy"` +} + +func (SellCoinDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { + data := txData.(*transaction.SellCoinData) + buyCoin := state.Coins().GetCoin(data.CoinToBuy) + sellCoin := state.Coins().GetCoin(data.CoinToSell) + + return SellCoinDataResource{ + ValueToSell: data.ValueToSell.String(), + MinimumValueToBuy: data.MinimumValueToBuy.String(), + CoinToBuy: CoinResource{buyCoin.ID().Uint32(), buyCoin.GetFullSymbol()}, + CoinToSell: CoinResource{sellCoin.ID().Uint32(), sellCoin.GetFullSymbol()}, + } +} + +// TxType 0x03 + +type SellAllCoinDataResource struct { + CoinToSell CoinResource `json:"coin_to_sell"` + CoinToBuy CoinResource `json:"coin_to_buy"` + MinimumValueToBuy string `json:"minimum_value_to_buy"` +} + +func (SellAllCoinDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { + data := txData.(*transaction.SellAllCoinData) + buyCoin := state.Coins().GetCoin(data.CoinToBuy) + sellCoin := state.Coins().GetCoin(data.CoinToSell) + + return SellAllCoinDataResource{ + MinimumValueToBuy: data.MinimumValueToBuy.String(), + CoinToBuy: CoinResource{buyCoin.ID().Uint32(), buyCoin.GetFullSymbol()}, + CoinToSell: CoinResource{sellCoin.ID().Uint32(), sellCoin.GetFullSymbol()}, + } +} + +// TxType 0x04 + +type BuyCoinDataResource struct { + CoinToBuy CoinResource `json:"coin_to_buy"` + ValueToBuy string `json:"value_to_buy"` + CoinToSell CoinResource `json:"coin_to_sell"` + MaximumValueToSell string `json:"maximum_value_to_sell"` +} + +func (BuyCoinDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { + data := txData.(*transaction.BuyCoinData) + buyCoin := state.Coins().GetCoin(data.CoinToBuy) + sellCoin := state.Coins().GetCoin(data.CoinToSell) + + return BuyCoinDataResource{ + ValueToBuy: data.ValueToBuy.String(), + MaximumValueToSell: data.MaximumValueToSell.String(), + CoinToBuy: CoinResource{buyCoin.ID().Uint32(), buyCoin.GetFullSymbol()}, + CoinToSell: CoinResource{sellCoin.ID().Uint32(), sellCoin.GetFullSymbol()}, + } +} + +// TxType 0x05 + +type CreateCoinDataResource struct { + Name string `json:"name"` + Symbol string `json:"symbol"` + InitialAmount string `json:"initial_amount"` + InitialReserve string `json:"initial_reserve"` + ConstantReserveRatio string `json:"constant_reserve_ratio"` + MaxSupply string `json:"max_supply"` +} + +func (CreateCoinDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { + data := txData.(*transaction.CreateCoinData) + + return CreateCoinDataResource{ + Name: data.Name, + Symbol: data.Symbol.String(), + InitialAmount: data.InitialAmount.String(), + InitialReserve: data.InitialReserve.String(), + ConstantReserveRatio: strconv.Itoa(int(data.ConstantReserveRatio)), + MaxSupply: data.MaxSupply.String(), + } +} + +// TxType 0x06 + +type DeclareCandidacyDataResource struct { + Address string `json:"address"` + PubKey string `json:"pub_key"` + Commission string `json:"commission"` + Coin CoinResource `json:"coin"` + Stake string `json:"stake"` +} + +func (DeclareCandidacyDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { + data := txData.(*transaction.DeclareCandidacyData) + coin := state.Coins().GetCoin(data.Coin) + + return DeclareCandidacyDataResource{ + Address: data.Address.String(), + PubKey: data.PubKey.String(), + Commission: strconv.Itoa(int(data.Commission)), + Stake: data.Stake.String(), + Coin: CoinResource{coin.ID().Uint32(), coin.GetFullSymbol()}, + } +} + +// TxType 0x07 + +type DelegateDataResource struct { + PubKey string `json:"pub_key"` + Coin CoinResource `json:"coin"` + Value string `json:"value"` +} + +func (DelegateDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { + data := txData.(*transaction.DelegateData) + coin := state.Coins().GetCoin(data.Coin) + + return DelegateDataResource{ + PubKey: data.PubKey.String(), + Value: data.Value.String(), + Coin: CoinResource{coin.ID().Uint32(), coin.GetFullSymbol()}, + } +} + +// TxType 0x08 + +type UnbondDataResource struct { + PubKey string `json:"pub_key"` + Coin CoinResource `json:"coin"` + Value string `json:"value"` +} + +func (UnbondDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { + data := txData.(*transaction.UnbondData) + coin := state.Coins().GetCoin(data.Coin) + + return UnbondDataResource{ + PubKey: data.PubKey.String(), + Value: data.Value.String(), + Coin: CoinResource{coin.ID().Uint32(), coin.GetFullSymbol()}, + } +} + +// TxType 0x09 + +type RedeemCheckDataResource struct { + RawCheck string `json:"raw_check"` + Proof string `json:"proof"` +} + +func (RedeemCheckDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { + data := txData.(*transaction.RedeemCheckData) + + return RedeemCheckDataResource{ + RawCheck: base64.StdEncoding.EncodeToString(data.RawCheck), + Proof: base64.StdEncoding.EncodeToString(data.Proof[:]), + } +} + +// TxType 0x0A + +type SetCandidateOnDataResource struct { + PubKey string `json:"pub_key"` +} + +func (SetCandidateOnDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { + data := txData.(*transaction.SetCandidateOnData) + return SetCandidateOnDataResource{data.PubKey.String()} +} + +// TxType 0x0B + +type SetCandidateOffDataResource struct { + PubKey string `json:"pub_key"` +} + +func (SetCandidateOffDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { + data := txData.(*transaction.SetCandidateOffData) + return SetCandidateOffDataResource{data.PubKey.String()} +} + +// TxType 0x0C + +type CreateMultisigDataResource struct { + Threshold string `json:"threshold"` + Weights []string `json:"weights"` + Addresses []types.Address `json:"addresses"` +} + +func (CreateMultisigDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { + data := txData.(*transaction.CreateMultisigData) + + var weights []string + for _, weight := range data.Weights { + weights = append(weights, strconv.Itoa(int(weight))) + } + + return CreateMultisigDataResource{ + Threshold: strconv.Itoa(int(data.Threshold)), + Weights: weights, + Addresses: data.Addresses, + } +} + +// TxType 0x0D + +type MultiSendDataResource struct { + List []SendDataResource `json:"list"` +} + +func (resource MultiSendDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { + data := txData.(*transaction.MultisendData) + + for _, v := range data.List { + coin := state.Coins().GetCoin(v.Coin) + + resource.List = append(resource.List, SendDataResource{ + Coin: CoinResource{coin.ID().Uint32(), coin.GetFullSymbol()}, + To: v.To.String(), + Value: v.Value.String(), + }) + } + + return resource +} + +// TxType 0x0E + +type EditCandidateDataResource struct { + PubKey string `json:"pub_key"` + RewardAddress string `json:"reward_address"` + OwnerAddress string `json:"owner_address"` +} + +func (EditCandidateDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { + data := txData.(*transaction.EditCandidateData) + + return EditCandidateDataResource{ + PubKey: data.PubKey.String(), + RewardAddress: data.RewardAddress.String(), + OwnerAddress: data.OwnerAddress.String(), + } +} + +// TxType 0x0F + +type SetHaltBlockDataResource struct { + PubKey string `json:"pub_key"` + Height string `json:"height"` +} + +func (SetHaltBlockDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { + data := txData.(*transaction.SetHaltBlockData) + + return SetHaltBlockDataResource{ + PubKey: data.PubKey.String(), + Height: strconv.FormatUint(data.Height, 10), + } +} diff --git a/core/transaction/send.go b/core/transaction/send.go index afceb479f..6ed519b2c 100644 --- a/core/transaction/send.go +++ b/core/transaction/send.go @@ -30,7 +30,7 @@ func (data SendData) MarshalJSON() ([]byte, error) { To string `json:"to"` Value string `json:"value"` }{ - Coin: Coin{ + Coin: Coin{ ID: data.Coin.Uint32(), Symbol: "", }, diff --git a/core/types/appstate.go b/core/types/appstate.go index 460344267..d274648da 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -228,15 +228,15 @@ type Stake struct { } type Coin struct { - ID CoinID `json:"id"` - Name string `json:"name"` - Symbol CoinSymbol `json:"symbol"` - Volume string `json:"volume"` - Crr uint `json:"crr"` - Reserve string `json:"reserve"` - MaxSupply string `json:"max_supply"` + ID CoinID `json:"id"` + Name string `json:"name"` + Symbol CoinSymbol `json:"symbol"` + Volume string `json:"volume"` + Crr uint `json:"crr"` + Reserve string `json:"reserve"` + MaxSupply string `json:"max_supply"` Version CoinVersion `json:"version"` - OwnerAddress *Address `json:"owner_address"` + OwnerAddress *Address `json:"owner_address"` } type FrozenFund struct { From c0e52c0381748ad8a43b5192a2da7162af69ef7f Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 14 Jul 2020 15:22:24 +0300 Subject: [PATCH 064/426] more fixes --- api/v2/service/candidate.go | 19 +++++ core/state/candidates/candidates.go | 119 +++++++++++++++++----------- core/state/state.go | 4 + core/transaction/edit_candidate.go | 2 +- core/types/appstate.go | 23 +++--- 5 files changed, 110 insertions(+), 57 deletions(-) diff --git a/api/v2/service/candidate.go b/api/v2/service/candidate.go index 38643a7ab..5c72deaeb 100644 --- a/api/v2/service/candidate.go +++ b/api/v2/service/candidate.go @@ -10,6 +10,7 @@ import ( pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "math/big" ) func (s *Service) Candidate(ctx context.Context, req *pb.CandidateRequest) (*pb.CandidateResponse, error) { @@ -56,6 +57,24 @@ func makeResponseCandidate(state *state.CheckState, c candidates.Candidate, incl Status: fmt.Sprintf("%d", c.Status), } + stakes := state.Candidates().GetStakes(c.PubKey) + usedSlots := len(stakes) + candidate.UsedSlots = fmt.Sprintf("%d", usedSlots) + addresses := map[types.Address]struct{}{} + minStake := big.NewInt(0) + for i, stake := range stakes { + addresses[stake.Owner] = struct{}{} + if usedSlots >= candidates.MaxDelegatorsPerCandidate { + if i != 0 && minStake.Cmp(stake.BipValue) != 1 { + continue + } + minStake = stake.BipValue + } + } + + candidate.UniqUsers = fmt.Sprintf("%d", len(addresses)) + candidate.MinStake = minStake.String() + if includeStakes { stakes := state.Candidates().GetStakes(c.PubKey) candidate.Stakes = make([]*pb.CandidateResponse_Stake, 0, len(stakes)) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index f872e6b1b..e3cecc210 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -98,10 +98,30 @@ func (c *Candidates) Commit() error { c.iavl.Set(path, data) } + var pubIDs []pubkeyID + for pk, v := range c.pubKeyIDs { + pubIDs = append(pubIDs, pubkeyID{ + PubKey: pk, + ID: v, + }) + } + sort.SliceStable(pubIDs, func(i, j int) bool { + return pubIDs[i].ID < pubIDs[j].ID + }) + pubIDenc, err := rlp.EncodeToBytes(pubIDs) + if err != nil { + panic(fmt.Sprintf("failed to encode candidates public key with ID: %s", err)) + } + + c.iavl.Set([]byte{pubKeyIDPrefix}, pubIDenc) + var blockList []types.Pubkey for pubKey := range c.blockList { blockList = append(blockList, pubKey) } + sort.SliceStable(blockList, func(i, j int) bool { + return bytes.Compare(blockList[i].Bytes(), blockList[j].Bytes()) == 1 + }) blockListData, err := rlp.EncodeToBytes(blockList) if err != nil { return fmt.Errorf("can't encode block list of candidates: %v", err) @@ -758,66 +778,61 @@ func (c *Candidates) LoadCandidates() { } _, pubIDenc := c.iavl.Get([]byte{pubKeyIDPrefix}) - if len(pubIDenc) == 0 { - c.pubKeyIDs = map[types.Pubkey]uint{} - return - } - - var pubIDs []*pubkeyID - if err := rlp.DecodeBytes(pubIDenc, &pubIDs); err != nil { - panic(fmt.Sprintf("failed to decode candidates: %s", err)) - } + if len(pubIDenc) != 0 { + var pubIDs []pubkeyID + if err := rlp.DecodeBytes(pubIDenc, &pubIDs); err != nil { + panic(fmt.Sprintf("failed to decode candidates: %s", err)) + } - pubKeyIDs := map[types.Pubkey]uint{} - for _, v := range pubIDs { - pubKeyIDs[v.PubKey] = v.ID + pubKeyIDs := map[types.Pubkey]uint{} + for _, v := range pubIDs { + pubKeyIDs[v.PubKey] = v.ID + } + c.setPubKeyIDs(pubKeyIDs) } - c.setPubKeyIDs(pubKeyIDs) path := []byte{mainPrefix} _, enc := c.iavl.Get(path) - if len(enc) == 0 { - c.list = map[uint]*Candidate{} - } + if len(enc) != 0 { + var candidates []*Candidate + if err := rlp.DecodeBytes(enc, &candidates); err != nil { + panic(fmt.Sprintf("failed to decode candidates: %s", err)) + } - var candidates []*Candidate - if err := rlp.DecodeBytes(enc, &candidates); err != nil { - panic(fmt.Sprintf("failed to decode candidates: %s", err)) - } + for _, candidate := range candidates { + // load total stake + path = append([]byte{mainPrefix}, candidate.idBytes()...) + path = append(path, totalStakePrefix) + _, enc = c.iavl.Get(path) + if len(enc) == 0 { + candidate.totalBipStake = big.NewInt(0) + } else { + candidate.totalBipStake = big.NewInt(0).SetBytes(enc) + } - for _, candidate := range candidates { - // load total stake - path = append([]byte{mainPrefix}, candidate.idBytes()...) - path = append(path, totalStakePrefix) - _, enc = c.iavl.Get(path) - if len(enc) == 0 { - candidate.totalBipStake = big.NewInt(0) - } else { - candidate.totalBipStake = big.NewInt(0).SetBytes(enc) + candidate.setTmAddress() + c.setToMap(candidate.PubKey, candidate) } - - candidate.setTmAddress() - c.setToMap(candidate.PubKey, candidate) } _, blockListEnc := c.iavl.Get([]byte{blockListPrefix}) - if len(blockListEnc) == 0 { - c.blockList = map[types.Pubkey]struct{}{} - } - - var blockList []types.Pubkey - if err := rlp.DecodeBytes(enc, &blockList); err != nil { - panic(fmt.Sprintf("failed to decode candidates block list: %s", err)) - } + if len(blockListEnc) != 0 { + var blockList []types.Pubkey + if err := rlp.DecodeBytes(blockListEnc, &blockList); err != nil { + panic(fmt.Sprintf("failed to decode candidates block list: %s", err)) + } - blockListMap := map[types.Pubkey]struct{}{} - for _, pubkey := range blockList { - blockListMap[pubkey] = struct{}{} + blockListMap := map[types.Pubkey]struct{}{} + for _, pubkey := range blockList { + blockListMap[pubkey] = struct{}{} + } + c.setBlockList(blockListMap) } - c.setBlockList(blockListMap) _, valueMaxID := c.iavl.Get([]byte{maxIDPrefix}) - c.maxID = uint(binary.LittleEndian.Uint32(valueMaxID)) + if len(valueMaxID) != 0 { + c.maxID = uint(binary.LittleEndian.Uint32(valueMaxID)) + } } func (c *Candidates) checkAndSetLoaded() bool { @@ -1006,6 +1021,13 @@ func (c *Candidates) Export(state *types.AppState) { Stakes: stakes, }) } + + for pubkey := range c.blockList { + state.BlockListCandidates = append(state.BlockListCandidates, pubkey) + } + sort.SliceStable(state.BlockListCandidates, func(i, j int) bool { + return bytes.Compare(state.BlockListCandidates[i].Bytes(), state.BlockListCandidates[j].Bytes()) == 1 + }) } func (c *Candidates) getOrderedCandidates() []types.Pubkey { @@ -1187,6 +1209,13 @@ func (c *Candidates) setBlockPybKey(p types.Pubkey) { c.blockList[p] = struct{}{} } +func (c *Candidates) AddToBlockPybKey(p types.Pubkey) { + c.lock.Lock() + defer c.lock.Unlock() + + c.setBlockPybKey(p) +} + func (c *Candidates) maxIDBytes() []byte { bs := make([]byte, 4) binary.LittleEndian.PutUint32(bs, uint32(c.maxID)) diff --git a/core/state/state.go b/core/state/state.go index a1202623a..b3ab28720 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -258,6 +258,10 @@ func (s *State) Import(state types.AppState) error { s.Candidates.SetStakes(c.PubKey, c.Stakes, c.Updates) } + for _, pubkey := range state.BlockListCandidates { + s.Candidates.AddToBlockPybKey(pubkey) + } + for _, hashString := range state.UsedChecks { bytes, _ := hex.DecodeString(string(hashString)) var hash types.Hash diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index b6cf77ece..2bc2a90bc 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -19,7 +19,7 @@ type CandidateTx interface { type EditCandidateData struct { PubKey types.Pubkey - NewPubKey *types.Pubkey + NewPubKey *types.Pubkey `rlp:"nil"` RewardAddress types.Address OwnerAddress types.Address ControlAddress types.Address diff --git a/core/types/appstate.go b/core/types/appstate.go index ff5e056d3..544ecba17 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -8,17 +8,18 @@ import ( ) type AppState struct { - Note string `json:"note"` - StartHeight uint64 `json:"start_height"` - Validators []Validator `json:"validators,omitempty"` - Candidates []Candidate `json:"candidates,omitempty"` - Accounts []Account `json:"accounts,omitempty"` - Coins []Coin `json:"coins,omitempty"` - FrozenFunds []FrozenFund `json:"frozen_funds,omitempty"` - HaltBlocks []HaltBlock `json:"halt_blocks,omitempty"` - UsedChecks []UsedCheck `json:"used_checks,omitempty"` - MaxGas uint64 `json:"max_gas"` - TotalSlashed string `json:"total_slashed"` + Note string `json:"note"` + StartHeight uint64 `json:"start_height"` + Validators []Validator `json:"validators,omitempty"` + Candidates []Candidate `json:"candidates,omitempty"` + BlockListCandidates []Pubkey `json:"block_list_candidates,omitempty"` + Accounts []Account `json:"accounts,omitempty"` + Coins []Coin `json:"coins,omitempty"` + FrozenFunds []FrozenFund `json:"frozen_funds,omitempty"` + HaltBlocks []HaltBlock `json:"halt_blocks,omitempty"` + UsedChecks []UsedCheck `json:"used_checks,omitempty"` + MaxGas uint64 `json:"max_gas"` + TotalSlashed string `json:"total_slashed"` } func (s *AppState) Verify() error { From f1764de5a30bdac09eb68a31f19c5316e20186e2 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 15 Jul 2020 11:26:29 +0300 Subject: [PATCH 065/426] refactor --- api/v2/service/candidate.go | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/api/v2/service/candidate.go b/api/v2/service/candidate.go index 5c72deaeb..6b9362f14 100644 --- a/api/v2/service/candidate.go +++ b/api/v2/service/candidate.go @@ -57,35 +57,30 @@ func makeResponseCandidate(state *state.CheckState, c candidates.Candidate, incl Status: fmt.Sprintf("%d", c.Status), } - stakes := state.Candidates().GetStakes(c.PubKey) - usedSlots := len(stakes) - candidate.UsedSlots = fmt.Sprintf("%d", usedSlots) - addresses := map[types.Address]struct{}{} - minStake := big.NewInt(0) - for i, stake := range stakes { - addresses[stake.Owner] = struct{}{} - if usedSlots >= candidates.MaxDelegatorsPerCandidate { - if i != 0 && minStake.Cmp(stake.BipValue) != 1 { - continue - } - minStake = stake.BipValue - } - } - - candidate.UniqUsers = fmt.Sprintf("%d", len(addresses)) - candidate.MinStake = minStake.String() - if includeStakes { + addresses := map[types.Address]struct{}{} + minStake := big.NewInt(0) stakes := state.Candidates().GetStakes(c.PubKey) - candidate.Stakes = make([]*pb.CandidateResponse_Stake, 0, len(stakes)) - for _, stake := range stakes { + usedSlots := len(stakes) + candidate.UsedSlots = fmt.Sprintf("%d", usedSlots) + candidate.Stakes = make([]*pb.CandidateResponse_Stake, 0, usedSlots) + for i, stake := range stakes { candidate.Stakes = append(candidate.Stakes, &pb.CandidateResponse_Stake{ Owner: stake.Owner.String(), Coin: stake.Coin.String(), Value: stake.Value.String(), BipValue: stake.BipValue.String(), }) + addresses[stake.Owner] = struct{}{} + if usedSlots >= candidates.MaxDelegatorsPerCandidate { + if i != 0 && minStake.Cmp(stake.BipValue) != 1 { + continue + } + minStake = stake.BipValue + } } + candidate.UniqUsers = fmt.Sprintf("%d", len(addresses)) + candidate.MinStake = minStake.String() } return candidate From 5aaa33e71015079801fc04e4eb6b575d74fa1e1d Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 15 Jul 2020 11:27:38 +0300 Subject: [PATCH 066/426] refactor --- api/v2/service/candidate.go | 4 ++-- api/v2/service/candidates.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/v2/service/candidate.go b/api/v2/service/candidate.go index 6b9362f14..2dc885420 100644 --- a/api/v2/service/candidate.go +++ b/api/v2/service/candidate.go @@ -44,11 +44,11 @@ func (s *Service) Candidate(ctx context.Context, req *pb.CandidateRequest) (*pb. return new(pb.CandidateResponse), status.Error(codes.NotFound, "Candidate not found") } - result := makeResponseCandidate(cState, *candidate, true) + result := makeResponseCandidate(cState, candidate, true) return result, nil } -func makeResponseCandidate(state *state.CheckState, c candidates.Candidate, includeStakes bool) *pb.CandidateResponse { +func makeResponseCandidate(state *state.CheckState, c *candidates.Candidate, includeStakes bool) *pb.CandidateResponse { candidate := &pb.CandidateResponse{ RewardAddress: c.RewardAddress.String(), TotalStake: state.Candidates().GetTotalStake(c.PubKey).String(), diff --git a/api/v2/service/candidates.go b/api/v2/service/candidates.go index 2128cfe52..91d5a88c3 100644 --- a/api/v2/service/candidates.go +++ b/api/v2/service/candidates.go @@ -36,7 +36,7 @@ func (s *Service) Candidates(ctx context.Context, req *pb.CandidatesRequest) (*p return new(pb.CandidatesResponse), timeoutStatus.Err() } - response.Candidates = append(response.Candidates, makeResponseCandidate(cState, *candidate, req.IncludeStakes)) + response.Candidates = append(response.Candidates, makeResponseCandidate(cState, candidate, req.IncludeStakes)) } return response, nil From 64aaa8ec2c825f6f34ea2f395fc69591fd7320c0 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 15 Jul 2020 11:45:35 +0300 Subject: [PATCH 067/426] fix --- core/transaction/edit_candidate.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index 2bc2a90bc..7b8ef55cf 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -118,9 +118,9 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa if checkState.Candidates().IsBlockPubKey(data.NewPubKey) { return Response{ Code: code.PublicKeyInBlockList, - Log: fmt.Sprintf("Candidate with such public key (%s) exists in block list", data.PubKey.String()), + Log: fmt.Sprintf("Candidate with such public key (%s) exists in block list", data.NewPubKey.String()), Info: EncodeError(map[string]string{ - "public_key": data.PubKey.String(), + "public_key": data.NewPubKey.String(), }), } } @@ -132,10 +132,10 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa deliveryState.Coins.SubVolume(tx.GasCoin, commission) deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliveryState.Candidates.Edit(data.PubKey, data.RewardAddress, data.OwnerAddress, data.ControlAddress) if data.NewPubKey != nil { deliveryState.Candidates.ChangePubKey(data.PubKey, *data.NewPubKey) } - deliveryState.Candidates.Edit(data.PubKey, data.RewardAddress, data.OwnerAddress, data.ControlAddress) deliveryState.Accounts.SetNonce(sender, tx.Nonce) } From 38660d1803061460e4b571f19bdcb9fbff821d51 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 15 Jul 2020 12:16:40 +0300 Subject: [PATCH 068/426] MN-435: recreate coin, change owner txs --- api/coin_info.go | 25 +-- core/code/code.go | 3 + core/state/app/app.go | 4 + core/state/coins/bus.go | 1 - core/state/coins/coins.go | 122 +++++++++++++-- core/state/coins/model.go | 34 +++-- core/transaction/change_owner.go | 125 +++++++++++++++ core/transaction/create_coin.go | 2 - core/transaction/decoder.go | 2 + core/transaction/encoder/encoder.go | 12 +- core/transaction/encoder/resources.go | 96 ++++++++---- core/transaction/recreate_coin.go | 209 ++++++++++++++++++++++++++ core/transaction/transaction.go | 2 + 13 files changed, 565 insertions(+), 72 deletions(-) create mode 100644 core/transaction/change_owner.go create mode 100644 core/transaction/recreate_coin.go diff --git a/api/coin_info.go b/api/coin_info.go index 6f64fc14b..3c0c4a42e 100644 --- a/api/coin_info.go +++ b/api/coin_info.go @@ -6,14 +6,14 @@ import ( ) type CoinInfoResponse struct { - ID uint32 `json:"id"` - Name string `json:"name"` - Symbol string `json:"symbol"` - Volume string `json:"volume"` - Crr uint `json:"crr"` - ReserveBalance string `json:"reserve_balance"` - MaxSupply string `json:"max_supply"` - OwnerAddress *string `json:"owner_address"` + ID uint32 `json:"id"` + Name string `json:"name"` + Symbol string `json:"symbol"` + Volume string `json:"volume"` + Crr uint `json:"crr"` + ReserveBalance string `json:"reserve_balance"` + MaxSupply string `json:"max_supply"` + OwnerAddress *types.Address `json:"owner_address"` } func CoinInfo(coinSymbol string, height int) (*CoinInfoResponse, error) { @@ -30,9 +30,10 @@ func CoinInfo(coinSymbol string, height int) (*CoinInfoResponse, error) { return nil, rpctypes.RPCError{Code: 404, Message: "Coin not found"} } - var ownerAddress string - if coin.OwnerAddress() != (types.Address{}) { - ownerAddress = coin.OwnerAddress().String() + var ownerAddress *types.Address + info := cState.Coins().GetSymbolInfo(coin.Symbol()) + if info != nil && info.OwnerAddress() != nil { + ownerAddress = info.OwnerAddress() } return &CoinInfoResponse{ @@ -43,6 +44,6 @@ func CoinInfo(coinSymbol string, height int) (*CoinInfoResponse, error) { Crr: coin.Crr(), ReserveBalance: coin.Reserve().String(), MaxSupply: coin.MaxSupply().String(), - OwnerAddress: &ownerAddress, + OwnerAddress: ownerAddress, }, nil } diff --git a/core/code/code.go b/core/code/code.go index 12b283a8e..b5815b778 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -26,6 +26,9 @@ const ( InvalidCoinName uint32 = 204 WrongCoinSupply uint32 = 205 + // recreate coin + IsNotOwnerOfCoin uint32 = 206 + // convert CrossConvert uint32 = 301 MaximumValueToSellReached uint32 = 302 diff --git a/core/state/app/app.go b/core/state/app/app.go index b23eace64..7ba776b64 100644 --- a/core/state/app/app.go +++ b/core/state/app/app.go @@ -130,6 +130,10 @@ func (v *App) GetCoinsCount() uint32 { return v.getOrNew().getCoinsCount() } +func (v *App) GetNextCoinID() types.CoinID { + return types.CoinID(v.GetCoinsCount() + 1) +} + func (v *App) SetCoinsCount(count uint32) { v.getOrNew().setCoinsCount(count) } diff --git a/core/state/coins/bus.go b/core/state/coins/bus.go index fd1f7a3b7..4609458d5 100644 --- a/core/state/coins/bus.go +++ b/core/state/coins/bus.go @@ -28,7 +28,6 @@ func (b *Bus) GetCoin(id types.CoinID) *bus.Coin { Volume: coin.Volume(), Reserve: coin.Reserve(), Version: coin.Version(), - OwnerAddress: coin.OwnerAddress(), } } diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index 3610f4c12..ae3490eb2 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -17,6 +17,10 @@ const ( symbolPrefix = byte('s') ) +const ( + BaseVersion types.CoinVersion = 0 +) + type RCoins interface { Export(state *types.AppState) Exists(id types.CoinID) bool @@ -24,6 +28,7 @@ type RCoins interface { SubReserve(symbol types.CoinID, amount *big.Int) GetCoin(id types.CoinID) *Model GetCoinBySymbol(symbol types.CoinSymbol) *Model + GetSymbolInfo(symbol types.CoinSymbol) *SymbolInfo } type Coins struct { @@ -83,6 +88,16 @@ func (c *Coins) Commit() error { c.iavl.Set(getCoinInfoPath(id), data) coin.info.isDirty = false } + + if coin.IsSymbolInfoDirty() { + data, err := rlp.EncodeToBytes(coin.symbolInfo) + if err != nil { + return fmt.Errorf("can't encode object at %d: %v", id, err) + } + + c.iavl.Set(getSymbolInfoPath(coin.Symbol()), data) + coin.symbolInfo.isDirty = false + } } return nil @@ -92,6 +107,10 @@ func (c *Coins) GetCoin(id types.CoinID) *Model { return c.get(id) } +func (c *Coins) GetSymbolInfo(symbol types.CoinSymbol) *SymbolInfo { + return c.getSymbolInfo(symbol) +} + func (c *Coins) Exists(id types.CoinID) bool { if id.IsBaseCoin() { return true @@ -163,20 +182,65 @@ func (c *Coins) AddReserve(id types.CoinID, amount *big.Int) { func (c *Coins) Create(id types.CoinID, symbol types.CoinSymbol, name string, volume *big.Int, crr uint, reserve *big.Int, maxSupply *big.Int, owner *types.Address, ) { - if owner == nil { - owner = &types.Address{} + coin := &Model{ + CName: name, + CCrr: crr, + CMaxSupply: maxSupply, + CSymbol: symbol, + id: id, + markDirty: c.markDirty, + isDirty: true, + isCreated: true, + info: &Info{ + Volume: big.NewInt(0), + Reserve: big.NewInt(0), + isDirty: false, + }, + } + + if owner != nil { + coin.symbolInfo = &SymbolInfo{ + COwnerAddress: owner, + isDirty: true, + } + } + + c.setToMap(coin.id, coin) + + coin.SetReserve(reserve) + coin.SetVolume(volume) + + c.markDirty(coin.id) + + c.bus.Checker().AddCoin(types.GetBaseCoinID(), reserve) + c.bus.Checker().AddCoinVolume(coin.id, volume) +} + +func (c *Coins) Recreate(newID types.CoinID, recreateID types.CoinID, + volume *big.Int, crr uint, reserve *big.Int, maxSupply *big.Int, +) { + recreateCoin := c.GetCoin(recreateID) + if recreateCoin == nil { + panic("coin to recreate does not exists") } + // update version for recreating coin + symbolCoins := c.getBySymbol(recreateCoin.Symbol()) + lastRecreatedCoin := c.GetCoin(symbolCoins[len(symbolCoins)-1]) + recreateCoin.CVersion = lastRecreatedCoin.Version() + 1 + c.setToMap(recreateCoin.id, recreateCoin) + c.markDirty(recreateCoin.id) + coin := &Model{ - CName: name, - CCrr: crr, - CMaxSupply: maxSupply, - CSymbol: symbol, - COwnerAddress: *owner, - id: id, - markDirty: c.markDirty, - isDirty: true, - isCreated: true, + CName: "", + CCrr: crr, + CMaxSupply: maxSupply, + CSymbol: recreateCoin.Symbol(), + CVersion: BaseVersion, + id: newID, + markDirty: c.markDirty, + isDirty: true, + isCreated: true, info: &Info{ Volume: big.NewInt(0), Reserve: big.NewInt(0), @@ -194,6 +258,15 @@ func (c *Coins) Create(id types.CoinID, symbol types.CoinSymbol, name string, c.bus.Checker().AddCoinVolume(coin.id, volume) } +func (c *Coins) ChangeOwner(symbol types.CoinSymbol, owner types.Address) { + info := c.getSymbolInfo(symbol) + info.COwnerAddress = &owner + info.isDirty = true + + coin := c.GetCoinBySymbol(symbol) + c.markDirty(coin.ID()) +} + func (c *Coins) get(id types.CoinID) *Model { if id.IsBaseCoin() { // TODO: refactor @@ -240,6 +313,21 @@ func (c *Coins) get(id types.CoinID) *Model { return coin } +func (c *Coins) getSymbolInfo(symbol types.CoinSymbol) *SymbolInfo { + info := &SymbolInfo{} + + _, enc := c.iavl.Get(getSymbolInfoPath(symbol)) + if len(enc) == 0 { + return info + } + + if err := rlp.DecodeBytes(enc, info); err != nil { + panic(fmt.Sprintf("failed to decode coin symbol %s: %s", symbol.String(), err)) + } + + return info +} + func (c *Coins) getBySymbol(symbol types.CoinSymbol) []types.CoinID { var coins []types.CoinID @@ -280,7 +368,9 @@ func (c *Coins) Export(state *types.AppState) { } coinID := types.BytesToCoinID(key[1:]) - coin := c.GetCoin(coinID) + coin := c.get(coinID) + + owner := c.getSymbolInfo(coin.Symbol()).OwnerAddress() state.Coins = append(state.Coins, types.Coin{ ID: coin.ID(), @@ -291,7 +381,7 @@ func (c *Coins) Export(state *types.AppState) { Reserve: coin.Reserve().String(), MaxSupply: coin.MaxSupply().String(), Version: coin.Version(), - OwnerAddress: &coin.COwnerAddress, + OwnerAddress: owner, }) } @@ -318,6 +408,12 @@ func getSymbolCoinsPath(symbol types.CoinSymbol) []byte { return append(path, symbol.Bytes()...) } +func getSymbolInfoPath(symbol types.CoinSymbol) []byte { + path := append([]byte{mainPrefix}, []byte{symbolPrefix}...) + path = append(path, symbol.Bytes()...) + return append(path, []byte{infoPrefix}...) +} + func getCoinPath(id types.CoinID) []byte { return append([]byte{mainPrefix}, id.Bytes()...) } diff --git a/core/state/coins/model.go b/core/state/coins/model.go index 2e63dcdea..47da838e4 100644 --- a/core/state/coins/model.go +++ b/core/state/coins/model.go @@ -10,15 +10,15 @@ import ( var minCoinReserve = helpers.BipToPip(big.NewInt(10000)) type Model struct { - CName string - CCrr uint - CMaxSupply *big.Int - CVersion types.CoinVersion - CSymbol types.CoinSymbol - COwnerAddress types.Address + CName string + CCrr uint + CMaxSupply *big.Int + CVersion types.CoinVersion + CSymbol types.CoinSymbol - id types.CoinID - info *Info + id types.CoinID + info *Info + symbolInfo *SymbolInfo markDirty func(symbol types.CoinID) @@ -54,10 +54,6 @@ func (m Model) Version() uint16 { return m.CVersion } -func (m Model) OwnerAddress() types.Address { - return m.COwnerAddress -} - func (m *Model) SubVolume(amount *big.Int) { m.info.Volume.Sub(m.info.Volume, amount) m.markDirty(m.id) @@ -109,6 +105,10 @@ func (m Model) IsInfoDirty() bool { return m.info.isDirty } +func (m Model) IsSymbolInfoDirty() bool { + return m.symbolInfo != nil && m.symbolInfo.isDirty +} + func (m Model) IsDirty() bool { return m.isDirty } @@ -135,3 +135,13 @@ type Info struct { isDirty bool } + +type SymbolInfo struct { + COwnerAddress *types.Address + + isDirty bool +} + +func (i SymbolInfo) OwnerAddress() *types.Address { + return i.COwnerAddress +} diff --git a/core/transaction/change_owner.go b/core/transaction/change_owner.go new file mode 100644 index 000000000..196639072 --- /dev/null +++ b/core/transaction/change_owner.go @@ -0,0 +1,125 @@ +package transaction + +import ( + "encoding/hex" + "fmt" + "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/state" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/formula" + "github.com/tendermint/tendermint/libs/kv" + "math/big" +) + +type ChangeOwnerData struct { + Symbol types.CoinSymbol + NewOwner types.Address +} + +func (data ChangeOwnerData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { + panic("implement me") +} + +func (data ChangeOwnerData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { + sender, _ := tx.Sender() + + info := context.Coins().GetSymbolInfo(data.Symbol) + if info == nil { + return &Response{ + Code: code.CoinNotExists, + Log: fmt.Sprintf("Coin %s not exists", data.Symbol), + } + } + + if info.OwnerAddress() == nil || info.OwnerAddress().Compare(sender) != 0 { + return &Response{ + Code: code.IsNotOwnerOfCoin, + Log: "Sender is not owner of coin", + } + } + + return nil +} + +func (data ChangeOwnerData) String() string { + return fmt.Sprintf("CHANGE OWNER COIN symbol:%s new owner:%s", data.Symbol.String(), data.NewOwner.String()) +} + +func (data ChangeOwnerData) Gas() int64 { + return 10000000 // 10k bips +} + +func (data ChangeOwnerData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { + sender, _ := tx.Sender() + + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + response := data.BasicCheck(tx, checkState) + if response != nil { + return *response + } + + commissionInBaseCoin := tx.CommissionInBaseCoin() + commission := big.NewInt(0).Set(commissionInBaseCoin) + + if tx.GasCoin != types.GetBaseCoinID() { + coin := checkState.Coins().GetCoin(tx.GasCoin) + + errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) + if errResp != nil { + return *errResp + } + + if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { + return Response{ + Code: code.CoinReserveNotSufficient, + Log: fmt.Sprintf("Gas coin reserve balance is not sufficient for transaction. Has: %s %s, required %s %s", coin.Reserve().String(), types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), + Info: EncodeError(map[string]string{ + "has_value": coin.Reserve().String(), + "required_value": commissionInBaseCoin.String(), + "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), + }), + } + } + + commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + } + + if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + return Response{ + Code: code.InsufficientFunds, + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), tx.GasCoin), + Info: EncodeError(map[string]string{ + "sender": sender.String(), + "needed_value": commission.String(), + "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + }), + } + } + + if deliveryState, ok := context.(*state.State); ok { + rewardPool.Add(rewardPool, commissionInBaseCoin) + deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliveryState.Coins.SubVolume(tx.GasCoin, commission) + deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliveryState.Coins.ChangeOwner(data.Symbol, data.NewOwner) + deliveryState.Accounts.SetNonce(sender, tx.Nonce) + } + + tags := kv.Pairs{ + kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeChangeOwner)}))}, + kv.Pair{Key: []byte("tx.from"), Value: []byte(hex.EncodeToString(sender[:]))}, + kv.Pair{Key: []byte("tx.coin"), Value: []byte(data.Symbol.String())}, + } + + return Response{ + Code: code.OK, + Tags: tags, + GasUsed: tx.Gas(), + GasWanted: tx.Gas(), + } +} diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index ed14346ec..8bce575f8 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -214,8 +214,6 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) deliveryState.Coins.SubVolume(tx.GasCoin, commission) - deliveryState.App.GetCoinsCount() - deliveryState.Accounts.SubBalance(sender, types.GetBaseCoinID(), data.InitialReserve) deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) diff --git a/core/transaction/decoder.go b/core/transaction/decoder.go index 193920a7a..fd47dec78 100644 --- a/core/transaction/decoder.go +++ b/core/transaction/decoder.go @@ -27,6 +27,8 @@ func init() { TxDecoder.RegisterType(TypeCreateMultisig, CreateMultisigData{}) TxDecoder.RegisterType(TypeEditCandidate, EditCandidateData{}) TxDecoder.RegisterType(TypeSetHaltBlock, SetHaltBlockData{}) + TxDecoder.RegisterType(TypeRecreateCoin, RecreateCoinData{}) + TxDecoder.RegisterType(TypeChangeOwner, ChangeOwnerData{}) } type Decoder struct { diff --git a/core/transaction/encoder/encoder.go b/core/transaction/encoder/encoder.go index 33eab8943..2a4524386 100644 --- a/core/transaction/encoder/encoder.go +++ b/core/transaction/encoder/encoder.go @@ -11,7 +11,7 @@ import ( ) type TxEncoderJSON struct { - state *state.CheckState + context *state.CheckState } type TransactionResponse struct { @@ -48,10 +48,12 @@ var resourcesConfig = map[transaction.TxType]TxDataResource{ transaction.TypeMultisend: new(MultiSendDataResource), transaction.TypeEditCandidate: new(EditCandidateDataResource), transaction.TypeSetHaltBlock: new(SetHaltBlockDataResource), + transaction.TypeRecreateCoin: new(RecreateCoinDataResource), + transaction.TypeChangeOwner: new(ChangeOwnerDataResource), } -func NewTxEncoderJSON(state *state.CheckState) *TxEncoderJSON { - return &TxEncoderJSON{state} +func NewTxEncoderJSON(context *state.CheckState) *TxEncoderJSON { + return &TxEncoderJSON{context} } func (encoder *TxEncoderJSON) Encode(transaction *transaction.Transaction, tmTx *coretypes.ResultTx) (*TransactionResponse, error) { @@ -69,7 +71,7 @@ func (encoder *TxEncoderJSON) Encode(transaction *transaction.Transaction, tmTx tags[string(tag.Key)] = string(tag.Value) } - gasCoin := encoder.state.Coins().GetCoin(transaction.GasCoin) + gasCoin := encoder.context.Coins().GetCoin(transaction.GasCoin) txGasCoin := CoinResource{gasCoin.ID().Uint32(), gasCoin.GetFullSymbol()} return &TransactionResponse{ @@ -94,7 +96,7 @@ func (encoder *TxEncoderJSON) Encode(transaction *transaction.Transaction, tmTx func (encoder *TxEncoderJSON) EncodeData(decodedTx *transaction.Transaction) ([]byte, error) { if resource, exists := resourcesConfig[decodedTx.Type]; exists { return json.Marshal( - resource.Transform(decodedTx.GetDecodedData(), encoder.state), + resource.Transform(decodedTx.GetDecodedData(), encoder.context), ) } diff --git a/core/transaction/encoder/resources.go b/core/transaction/encoder/resources.go index 3e591c78c..03719fc12 100644 --- a/core/transaction/encoder/resources.go +++ b/core/transaction/encoder/resources.go @@ -9,7 +9,7 @@ import ( ) type TxDataResource interface { - Transform(txData interface{}, state *state.CheckState) TxDataResource + Transform(txData interface{}, context *state.CheckState) TxDataResource } type CoinResource struct { @@ -25,9 +25,9 @@ type SendDataResource struct { Value string `json:"value"` } -func (SendDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { +func (SendDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.SendData) - coin := state.Coins().GetCoin(data.Coin) + coin := context.Coins().GetCoin(data.Coin) return SendDataResource{ To: data.To.String(), @@ -45,10 +45,10 @@ type SellCoinDataResource struct { MinimumValueToBuy string `json:"minimum_value_to_buy"` } -func (SellCoinDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { +func (SellCoinDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.SellCoinData) - buyCoin := state.Coins().GetCoin(data.CoinToBuy) - sellCoin := state.Coins().GetCoin(data.CoinToSell) + buyCoin := context.Coins().GetCoin(data.CoinToBuy) + sellCoin := context.Coins().GetCoin(data.CoinToSell) return SellCoinDataResource{ ValueToSell: data.ValueToSell.String(), @@ -66,10 +66,10 @@ type SellAllCoinDataResource struct { MinimumValueToBuy string `json:"minimum_value_to_buy"` } -func (SellAllCoinDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { +func (SellAllCoinDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.SellAllCoinData) - buyCoin := state.Coins().GetCoin(data.CoinToBuy) - sellCoin := state.Coins().GetCoin(data.CoinToSell) + buyCoin := context.Coins().GetCoin(data.CoinToBuy) + sellCoin := context.Coins().GetCoin(data.CoinToSell) return SellAllCoinDataResource{ MinimumValueToBuy: data.MinimumValueToBuy.String(), @@ -87,10 +87,10 @@ type BuyCoinDataResource struct { MaximumValueToSell string `json:"maximum_value_to_sell"` } -func (BuyCoinDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { +func (BuyCoinDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.BuyCoinData) - buyCoin := state.Coins().GetCoin(data.CoinToBuy) - sellCoin := state.Coins().GetCoin(data.CoinToSell) + buyCoin := context.Coins().GetCoin(data.CoinToBuy) + sellCoin := context.Coins().GetCoin(data.CoinToSell) return BuyCoinDataResource{ ValueToBuy: data.ValueToBuy.String(), @@ -111,7 +111,7 @@ type CreateCoinDataResource struct { MaxSupply string `json:"max_supply"` } -func (CreateCoinDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { +func (CreateCoinDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.CreateCoinData) return CreateCoinDataResource{ @@ -134,9 +134,9 @@ type DeclareCandidacyDataResource struct { Stake string `json:"stake"` } -func (DeclareCandidacyDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { +func (DeclareCandidacyDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.DeclareCandidacyData) - coin := state.Coins().GetCoin(data.Coin) + coin := context.Coins().GetCoin(data.Coin) return DeclareCandidacyDataResource{ Address: data.Address.String(), @@ -155,9 +155,9 @@ type DelegateDataResource struct { Value string `json:"value"` } -func (DelegateDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { +func (DelegateDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.DelegateData) - coin := state.Coins().GetCoin(data.Coin) + coin := context.Coins().GetCoin(data.Coin) return DelegateDataResource{ PubKey: data.PubKey.String(), @@ -174,9 +174,9 @@ type UnbondDataResource struct { Value string `json:"value"` } -func (UnbondDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { +func (UnbondDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.UnbondData) - coin := state.Coins().GetCoin(data.Coin) + coin := context.Coins().GetCoin(data.Coin) return UnbondDataResource{ PubKey: data.PubKey.String(), @@ -192,7 +192,7 @@ type RedeemCheckDataResource struct { Proof string `json:"proof"` } -func (RedeemCheckDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { +func (RedeemCheckDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.RedeemCheckData) return RedeemCheckDataResource{ @@ -207,7 +207,7 @@ type SetCandidateOnDataResource struct { PubKey string `json:"pub_key"` } -func (SetCandidateOnDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { +func (SetCandidateOnDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.SetCandidateOnData) return SetCandidateOnDataResource{data.PubKey.String()} } @@ -218,7 +218,7 @@ type SetCandidateOffDataResource struct { PubKey string `json:"pub_key"` } -func (SetCandidateOffDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { +func (SetCandidateOffDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.SetCandidateOffData) return SetCandidateOffDataResource{data.PubKey.String()} } @@ -231,7 +231,7 @@ type CreateMultisigDataResource struct { Addresses []types.Address `json:"addresses"` } -func (CreateMultisigDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { +func (CreateMultisigDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.CreateMultisigData) var weights []string @@ -252,11 +252,11 @@ type MultiSendDataResource struct { List []SendDataResource `json:"list"` } -func (resource MultiSendDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { +func (resource MultiSendDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.MultisendData) for _, v := range data.List { - coin := state.Coins().GetCoin(v.Coin) + coin := context.Coins().GetCoin(v.Coin) resource.List = append(resource.List, SendDataResource{ Coin: CoinResource{coin.ID().Uint32(), coin.GetFullSymbol()}, @@ -276,7 +276,7 @@ type EditCandidateDataResource struct { OwnerAddress string `json:"owner_address"` } -func (EditCandidateDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { +func (EditCandidateDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.EditCandidateData) return EditCandidateDataResource{ @@ -293,7 +293,7 @@ type SetHaltBlockDataResource struct { Height string `json:"height"` } -func (SetHaltBlockDataResource) Transform(txData interface{}, state *state.CheckState) TxDataResource { +func (SetHaltBlockDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.SetHaltBlockData) return SetHaltBlockDataResource{ @@ -301,3 +301,45 @@ func (SetHaltBlockDataResource) Transform(txData interface{}, state *state.Check Height: strconv.FormatUint(data.Height, 10), } } + +// TxType 0x10 + +type RecreateCoinDataResource struct { + Coin CoinResource `json:"coin"` + InitialAmount string `json:"initial_amount"` + InitialReserve string `json:"initial_reserve"` + ConstantReserveRatio string `json:"constant_reserve_ratio"` + MaxSupply string `json:"max_supply"` +} + +func (RecreateCoinDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { + data := txData.(*transaction.RecreateCoinData) + coin := context.Coins().GetCoin(data.Coin) + + return RecreateCoinDataResource{ + Coin: CoinResource{ + ID: coin.ID().Uint32(), + Symbol: coin.GetFullSymbol(), + }, + InitialAmount: data.InitialAmount.String(), + InitialReserve: data.InitialReserve.String(), + ConstantReserveRatio: strconv.Itoa(int(data.ConstantReserveRatio)), + MaxSupply: data.MaxSupply.String(), + } +} + +// TxType 0x11 + +type ChangeOwnerDataResource struct { + Symbol types.CoinSymbol `json:"symbol"` + NewOwner types.Address `json:"new_owner"` +} + +func (ChangeOwnerDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { + data := txData.(*transaction.ChangeOwnerData) + + return ChangeOwnerDataResource{ + Symbol: data.Symbol, + NewOwner: data.NewOwner, + } +} diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go new file mode 100644 index 000000000..51f8aa5b1 --- /dev/null +++ b/core/transaction/recreate_coin.go @@ -0,0 +1,209 @@ +package transaction + +import ( + "encoding/hex" + "fmt" + "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/state" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/formula" + "github.com/tendermint/tendermint/libs/kv" + "math/big" +) + +type RecreateCoinData struct { + Coin types.CoinID + InitialAmount *big.Int + InitialReserve *big.Int + ConstantReserveRatio uint + MaxSupply *big.Int +} + +func (data RecreateCoinData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { + panic("implement me") +} + +func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { + if data.InitialReserve == nil || data.InitialAmount == nil || data.MaxSupply == nil { + return &Response{ + Code: code.DecodeError, + Log: "Incorrect tx data"} + } + + if data.ConstantReserveRatio < 10 || data.ConstantReserveRatio > 100 { + return &Response{ + Code: code.WrongCrr, + Log: fmt.Sprintf("Constant Reserve Ratio should be between 10 and 100")} + } + + if data.InitialAmount.Cmp(minCoinSupply) == -1 || data.InitialAmount.Cmp(data.MaxSupply) == 1 { + return &Response{ + Code: code.WrongCoinSupply, + Log: fmt.Sprintf("Coin supply should be between %s and %s", minCoinSupply.String(), data.MaxSupply.String())} + } + + if data.MaxSupply.Cmp(maxCoinSupply) == 1 { + return &Response{ + Code: code.WrongCoinSupply, + Log: fmt.Sprintf("Max coin supply should be less than %s", maxCoinSupply)} + } + + if data.InitialReserve.Cmp(minCoinReserve) == -1 { + return &Response{ + Code: code.WrongCoinSupply, + Log: fmt.Sprintf("Coin reserve should be greater than or equal to %s", minCoinReserve.String())} + } + + sender, _ := tx.Sender() + + coin := context.Coins().GetCoin(data.Coin) + if coin == nil { + return &Response{ + Code: code.CoinNotExists, + Log: fmt.Sprintf("Coin %s not exists", data.Coin), + } + } + + symbolInfo := context.Coins().GetSymbolInfo(coin.Symbol()) + if symbolInfo == nil || symbolInfo.OwnerAddress() == nil || symbolInfo.OwnerAddress().Compare(sender) != 0 { + return &Response{ + Code: code.IsNotOwnerOfCoin, + Log: "Sender is not owner of coin", + } + } + + return nil +} + +func (data RecreateCoinData) String() string { + return fmt.Sprintf("RECREATE COIN symbol:%s reserve:%s amount:%s crr:%d", + data.Coin.String(), data.InitialReserve, data.InitialAmount, data.ConstantReserveRatio) +} + +func (data RecreateCoinData) Gas() int64 { + return 10000000 // 10k bips +} + +func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { + sender, _ := tx.Sender() + + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + response := data.BasicCheck(tx, checkState) + if response != nil { + return *response + } + + commissionInBaseCoin := tx.CommissionInBaseCoin() + commission := big.NewInt(0).Set(commissionInBaseCoin) + + if tx.GasCoin != types.GetBaseCoinID() { + coin := checkState.Coins().GetCoin(tx.GasCoin) + + errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) + if errResp != nil { + return *errResp + } + + if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { + return Response{ + Code: code.CoinReserveNotSufficient, + Log: fmt.Sprintf("Gas coin reserve balance is not sufficient for transaction. Has: %s %s, required %s %s", coin.Reserve().String(), types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), + Info: EncodeError(map[string]string{ + "has_value": coin.Reserve().String(), + "required_value": commissionInBaseCoin.String(), + "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), + }), + } + } + + commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + } + + if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + return Response{ + Code: code.InsufficientFunds, + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), tx.GasCoin), + Info: EncodeError(map[string]string{ + "sender": sender.String(), + "needed_value": commission.String(), + "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + }), + } + } + + if checkState.Accounts().GetBalance(sender, types.GetBaseCoinID()).Cmp(data.InitialReserve) < 0 { + return Response{ + Code: code.InsufficientFunds, + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), data.InitialReserve.String(), types.GetBaseCoin()), + Info: EncodeError(map[string]string{ + "sender": sender.String(), + "needed_reserve": data.InitialReserve.String(), + "base_coin": fmt.Sprintf("%s", types.GetBaseCoin()), + }), + } + } + + if tx.GasCoin.IsBaseCoin() { + totalTxCost := big.NewInt(0) + totalTxCost.Add(totalTxCost, data.InitialReserve) + totalTxCost.Add(totalTxCost, commission) + + if checkState.Accounts().GetBalance(sender, types.GetBaseCoinID()).Cmp(totalTxCost) < 0 { + return Response{ + Code: code.InsufficientFunds, + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), tx.GasCoin), + Info: EncodeError(map[string]string{ + "sender": sender.String(), + "needed_value": totalTxCost.String(), + "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + }), + } + } + } + + tags := kv.Pairs{ + kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeRecreateCoin)}))}, + kv.Pair{Key: []byte("tx.from"), Value: []byte(hex.EncodeToString(sender[:]))}, + } + + if deliveryState, ok := context.(*state.State); ok { + rewardPool.Add(rewardPool, commissionInBaseCoin) + + deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliveryState.Coins.SubVolume(tx.GasCoin, commission) + + deliveryState.Accounts.SubBalance(sender, types.GetBaseCoinID(), data.InitialReserve) + deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) + + coinID := deliveryState.App.GetNextCoinID() + deliveryState.Coins.Recreate( + coinID, + data.Coin, + data.InitialAmount, + data.ConstantReserveRatio, + data.InitialReserve, + data.MaxSupply, + ) + + deliveryState.App.SetCoinsCount(coinID.Uint32()) + deliveryState.Accounts.AddBalance(sender, coinID, data.InitialAmount) + deliveryState.Accounts.SetNonce(sender, tx.Nonce) + + tags = append(tags, kv.Pair{ + Key: []byte("tx.coin"), + Value: coinID.Bytes(), + }) + } + + return Response{ + Code: code.OK, + Tags: tags, + GasUsed: tx.Gas(), + GasWanted: tx.Gas(), + } +} diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index b15658371..f1364ed49 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -34,6 +34,8 @@ const ( TypeMultisend TxType = 0x0D TypeEditCandidate TxType = 0x0E TypeSetHaltBlock TxType = 0x0F + TypeRecreateCoin TxType = 0x10 + TypeChangeOwner TxType = 0x11 SigTypeSingle SigType = 0x01 SigTypeMulti SigType = 0x02 From 25bc4e3b6bd628031f1eba42975a80f291a33e07 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 15 Jul 2020 12:52:00 +0300 Subject: [PATCH 069/426] edit err message --- core/transaction/edit_candidate.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index 7b8ef55cf..88ceb5521 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -118,9 +118,9 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa if checkState.Candidates().IsBlockPubKey(data.NewPubKey) { return Response{ Code: code.PublicKeyInBlockList, - Log: fmt.Sprintf("Candidate with such public key (%s) exists in block list", data.NewPubKey.String()), + Log: fmt.Sprintf("Public key (%s) exists in block list", data.NewPubKey.String()), Info: EncodeError(map[string]string{ - "public_key": data.NewPubKey.String(), + "new_public_key": data.NewPubKey.String(), }), } } From 620593cfba82fdb0e240f5cd9ddf764876665a0d Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 15 Jul 2020 13:03:37 +0300 Subject: [PATCH 070/426] MN-435: refactor --- api/transaction.go | 3 ++- api/transactions.go | 6 +++--- core/transaction/encoder/encoder.go | 8 +++++--- core/transaction/set_halt_block.go | 8 -------- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/api/transaction.go b/api/transaction.go index 4356b6f80..2ffbff114 100644 --- a/api/transaction.go +++ b/api/transaction.go @@ -1,11 +1,12 @@ package api import ( + "encoding/json" "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/core/transaction/encoder" ) -func Transaction(hash []byte) (*encoder.TransactionResponse, error) { +func Transaction(hash []byte) (json.RawMessage, error) { tx, err := client.Tx(hash, false) if err != nil { return nil, err diff --git a/api/transactions.go b/api/transactions.go index 650a405b4..31d461d2a 100644 --- a/api/transactions.go +++ b/api/transactions.go @@ -30,7 +30,7 @@ type ResultTxSearch struct { TotalCount int `json:"total_count"` } -func Transactions(query string, page, perPage int) (*[]encoder.TransactionResponse, error) { +func Transactions(query string, page, perPage int) (*[]json.RawMessage, error) { if page == 0 { page = 1 } @@ -43,7 +43,7 @@ func Transactions(query string, page, perPage int) (*[]encoder.TransactionRespon return nil, err } - result := make([]encoder.TransactionResponse, len(rpcResult.Txs)) + result := make([]json.RawMessage, len(rpcResult.Txs)) for i, tx := range rpcResult.Txs { cState, err := GetStateForHeight(int(tx.Height)) if err != nil { @@ -57,7 +57,7 @@ func Transactions(query string, page, perPage int) (*[]encoder.TransactionRespon return nil, err } - result[i] = *response + result[i] = response } return &result, nil diff --git a/core/transaction/encoder/encoder.go b/core/transaction/encoder/encoder.go index 2a4524386..a25d61340 100644 --- a/core/transaction/encoder/encoder.go +++ b/core/transaction/encoder/encoder.go @@ -56,7 +56,7 @@ func NewTxEncoderJSON(context *state.CheckState) *TxEncoderJSON { return &TxEncoderJSON{context} } -func (encoder *TxEncoderJSON) Encode(transaction *transaction.Transaction, tmTx *coretypes.ResultTx) (*TransactionResponse, error) { +func (encoder *TxEncoderJSON) Encode(transaction *transaction.Transaction, tmTx *coretypes.ResultTx) (json.RawMessage, error) { sender, _ := transaction.Sender() // prepare transaction data resource @@ -74,7 +74,7 @@ func (encoder *TxEncoderJSON) Encode(transaction *transaction.Transaction, tmTx gasCoin := encoder.context.Coins().GetCoin(transaction.GasCoin) txGasCoin := CoinResource{gasCoin.ID().Uint32(), gasCoin.GetFullSymbol()} - return &TransactionResponse{ + tx := TransactionResponse{ Hash: bytes.HexBytes(tmTx.Tx.Hash()).String(), RawTx: fmt.Sprintf("%x", []byte(tmTx.Tx)), Height: tmTx.Height, @@ -90,7 +90,9 @@ func (encoder *TxEncoderJSON) Encode(transaction *transaction.Transaction, tmTx Tags: tags, Code: tmTx.TxResult.Code, Log: tmTx.TxResult.Log, - }, nil + } + + return json.Marshal(tx) } func (encoder *TxEncoderJSON) EncodeData(decodedTx *transaction.Transaction) ([]byte, error) { diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index 1e8bb4ff7..f0b3bf545 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -10,7 +10,6 @@ import ( "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/MinterTeam/minter-go-node/hexutil" - "github.com/MinterTeam/minter-go-node/upgrades" "github.com/tendermint/tendermint/libs/kv" "math/big" "strconv" @@ -63,13 +62,6 @@ func (data SetHaltBlockData) Gas() int64 { } func (data SetHaltBlockData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { - if currentBlock < upgrades.UpgradeBlock4 { - return Response{ - Code: code.DecodeError, - Log: "Unknown transaction type", - } - } - sender, _ := tx.Sender() var checkState *state.CheckState From 223bc7be0839a23259f915d0e096091794eac871 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 15 Jul 2020 13:38:25 +0300 Subject: [PATCH 071/426] MN-435: refactor --- core/commissions/commissions.go | 2 ++ core/transaction/change_owner.go | 16 ++++++++++++++-- core/transaction/recreate_coin.go | 3 ++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/core/commissions/commissions.go b/core/commissions/commissions.go index 13181b60a..8a333425a 100644 --- a/core/commissions/commissions.go +++ b/core/commissions/commissions.go @@ -15,4 +15,6 @@ const ( MultisendDelta int64 = 5 RedeemCheckTx int64 = SendTx * 3 SetHaltBlock int64 = 1000 + RecreateCoin int64 = 10000000 + ChangeOwner int64 = 10000000 ) diff --git a/core/transaction/change_owner.go b/core/transaction/change_owner.go index 196639072..c60ab90b2 100644 --- a/core/transaction/change_owner.go +++ b/core/transaction/change_owner.go @@ -2,8 +2,10 @@ package transaction import ( "encoding/hex" + "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" @@ -12,10 +14,20 @@ import ( ) type ChangeOwnerData struct { - Symbol types.CoinSymbol + Symbol types.CoinSymbol NewOwner types.Address } +func (data ChangeOwnerData) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Symbol types.CoinSymbol `json:"address"` + NewOwner types.Address `json:"pub_key"` + }{ + Symbol: data.Symbol, + NewOwner: data.NewOwner, + }) +} + func (data ChangeOwnerData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { panic("implement me") } @@ -46,7 +58,7 @@ func (data ChangeOwnerData) String() string { } func (data ChangeOwnerData) Gas() int64 { - return 10000000 // 10k bips + return commissions.ChangeOwner } func (data ChangeOwnerData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 51f8aa5b1..84433f5c1 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "fmt" "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" @@ -81,7 +82,7 @@ func (data RecreateCoinData) String() string { } func (data RecreateCoinData) Gas() int64 { - return 10000000 // 10k bips + return commissions.RecreateCoin } func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { From 4d120e823a52609545b9115d1ebabadf44c1bda0 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 15 Jul 2020 14:15:14 +0300 Subject: [PATCH 072/426] MN-435: fix txs gas --- core/commissions/commissions.go | 2 +- core/state/coins/coins.go | 13 ++++++++++--- core/state/coins/model.go | 5 +++++ core/transaction/change_owner.go | 11 ----------- core/transaction/executor.go | 16 +++++++++++++--- core/types/types.go | 7 ++++--- 6 files changed, 33 insertions(+), 21 deletions(-) diff --git a/core/commissions/commissions.go b/core/commissions/commissions.go index 8a333425a..cf22d2270 100644 --- a/core/commissions/commissions.go +++ b/core/commissions/commissions.go @@ -17,4 +17,4 @@ const ( SetHaltBlock int64 = 1000 RecreateCoin int64 = 10000000 ChangeOwner int64 = 10000000 -) +) \ No newline at end of file diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index ae3490eb2..ccd0cb490 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -133,9 +133,14 @@ func (c *Coins) GetCoinBySymbol(symbol types.CoinSymbol) *Model { return nil } + version, err := symbol.GetVersion() + if err != nil { + return nil + } + for _, coinID := range coins { coin := c.get(coinID) - if coin.Version() == symbol.GetVersion() { + if coin.Version() == version { return coin } } @@ -260,10 +265,12 @@ func (c *Coins) Recreate(newID types.CoinID, recreateID types.CoinID, func (c *Coins) ChangeOwner(symbol types.CoinSymbol, owner types.Address) { info := c.getSymbolInfo(symbol) - info.COwnerAddress = &owner - info.isDirty = true + info.SetOwnerAddress(&owner) coin := c.GetCoinBySymbol(symbol) + coin.symbolInfo = info + + c.setToMap(coin.id, coin) c.markDirty(coin.ID()) } diff --git a/core/state/coins/model.go b/core/state/coins/model.go index 47da838e4..f2e138d35 100644 --- a/core/state/coins/model.go +++ b/core/state/coins/model.go @@ -142,6 +142,11 @@ type SymbolInfo struct { isDirty bool } +func (i SymbolInfo) SetOwnerAddress(address *types.Address) { + i.COwnerAddress = address + i.isDirty = true +} + func (i SymbolInfo) OwnerAddress() *types.Address { return i.COwnerAddress } diff --git a/core/transaction/change_owner.go b/core/transaction/change_owner.go index c60ab90b2..a2e3f5f12 100644 --- a/core/transaction/change_owner.go +++ b/core/transaction/change_owner.go @@ -2,7 +2,6 @@ package transaction import ( "encoding/hex" - "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" @@ -18,16 +17,6 @@ type ChangeOwnerData struct { NewOwner types.Address } -func (data ChangeOwnerData) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Symbol types.CoinSymbol `json:"address"` - NewOwner types.Address `json:"pub_key"` - }{ - Symbol: data.Symbol, - NewOwner: data.NewOwner, - }) -} - func (data ChangeOwnerData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { panic("implement me") } diff --git a/core/transaction/executor.go b/core/transaction/executor.go index e1662bdc6..550f511e5 100644 --- a/core/transaction/executor.go +++ b/core/transaction/executor.go @@ -20,7 +20,7 @@ const ( maxPayloadLength = 1024 maxServiceDataLength = 128 - createCoinGas = 5000 + coinGas = 5000 ) type Response struct { @@ -221,8 +221,18 @@ func RunTx(context state.Interface, response.GasPrice = tx.GasPrice if tx.Type == TypeCreateCoin { - response.GasUsed = createCoinGas - response.GasWanted = createCoinGas + response.GasUsed = coinGas + response.GasWanted = coinGas + } + + if tx.Type == TypeChangeOwner { + response.GasUsed = coinGas + response.GasWanted = coinGas + } + + if tx.Type == TypeRecreateCoin { + response.GasUsed = coinGas + response.GasWanted = coinGas } return response diff --git a/core/types/types.go b/core/types/types.go index 90079f86f..d31f530e0 100644 --- a/core/types/types.go +++ b/core/types/types.go @@ -155,13 +155,14 @@ func (c CoinSymbol) GetBaseSymbol() CoinSymbol { return StrToCoinSymbol(strings.Split(c.String(), "-")[0]) } -func (c CoinSymbol) GetVersion() uint16 { +func (c CoinSymbol) GetVersion() (CoinVersion, error) { parts := strings.Split(c.String(), "-") if len(parts) == 1 { - return 0 + return 0, nil } - return 1 + v, err := strconv.ParseUint(parts[1], 10, 16) + return CoinVersion(v), err } func StrToCoinSymbol(s string) CoinSymbol { From b447db9a6b7da029be5de8ec8aa05d2cb7d321e6 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 15 Jul 2020 14:18:36 +0300 Subject: [PATCH 073/426] MN-435: fix --- core/state/coins/model.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/state/coins/model.go b/core/state/coins/model.go index f2e138d35..61e7053a1 100644 --- a/core/state/coins/model.go +++ b/core/state/coins/model.go @@ -142,7 +142,7 @@ type SymbolInfo struct { isDirty bool } -func (i SymbolInfo) SetOwnerAddress(address *types.Address) { +func (i *SymbolInfo) SetOwnerAddress(address *types.Address) { i.COwnerAddress = address i.isDirty = true } From 72c2a42b44bc7ec68ee6c65f089f7878a60a11dc Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 15 Jul 2020 14:27:10 +0300 Subject: [PATCH 074/426] MN-400: fix api resources --- api/address.go | 15 ++++++++++++--- api/addresses.go | 15 ++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/api/address.go b/api/address.go index 62cc93a67..5f8af82d6 100644 --- a/api/address.go +++ b/api/address.go @@ -31,17 +31,26 @@ func Address(address types.Address, height int) (*AddressResponse, error) { TransactionCount: cState.Accounts().GetNonce(address), } + isBaseCoinExists := false for k, b := range balances { response.Balance[k] = BalanceItem{ CoinID: b.Coin.ID.Uint32(), Symbol: b.Coin.GetFullSymbol(), Value: b.Value.String(), } + + if b.Coin.ID.IsBaseCoin() { + isBaseCoinExists = true + } } - //if _, exists := response.Balance[types.GetBaseCoin().String()]; !exists { - // response.Balance[types.GetBaseCoin().String()] = "0" - //} + if !isBaseCoinExists { + response.Balance = append(response.Balance, BalanceItem{ + CoinID: types.GetBaseCoinID().Uint32(), + Symbol: types.GetBaseCoin().String(), + Value: "0", + }) + } return &response, nil } diff --git a/api/addresses.go b/api/addresses.go index 9c1510c83..d29963641 100644 --- a/api/addresses.go +++ b/api/addresses.go @@ -30,17 +30,26 @@ func Addresses(addresses []types.Address, height int) (*[]AddressesResponse, err TransactionCount: cState.Accounts().GetNonce(address), } + isBaseCoinExists := false for k, b := range balances { data.Balance[k] = BalanceItem{ CoinID: b.Coin.ID.Uint32(), Symbol: b.Coin.GetFullSymbol(), Value: b.Value.String(), } + + if b.Coin.ID.IsBaseCoin() { + isBaseCoinExists = true + } } - //if _, exists := data.Balance[types.GetBaseCoin().String()]; !exists { - // data.Balance[types.GetBaseCoin().String()] = "0" - //} + if !isBaseCoinExists { + data.Balance = append(data.Balance, BalanceItem{ + CoinID: types.GetBaseCoinID().Uint32(), + Symbol: types.GetBaseCoin().String(), + Value: "0", + }) + } response[i] = data } From dc2c98d187372d25c67ed0442ef604438d689d6c Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 15 Jul 2020 14:28:22 +0300 Subject: [PATCH 075/426] MN-435: refactor api resources --- api/address.go | 5 +++++ api/candidate.go | 5 ----- core/commissions/commissions.go | 2 +- core/state/coins/bus.go | 14 +++++++------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/api/address.go b/api/address.go index 5f8af82d6..2322618df 100644 --- a/api/address.go +++ b/api/address.go @@ -15,6 +15,11 @@ type BalanceItem struct { Value string `json:"value"` } +type Coin struct { + ID uint32 `json:"id"` + Symbol string `json:"symbol"` +} + func Address(address types.Address, height int) (*AddressResponse, error) { cState, err := GetStateForHeight(height) if err != nil { diff --git a/api/candidate.go b/api/candidate.go index 3e215b42f..f63dced26 100644 --- a/api/candidate.go +++ b/api/candidate.go @@ -7,11 +7,6 @@ import ( "github.com/MinterTeam/minter-go-node/rpc/lib/types" ) -type Coin struct { - ID uint32 `json:"id"` - Symbol string `json:"symbol"` -} - type Stake struct { Owner string `json:"owner"` Coin Coin `json:"coin"` diff --git a/core/commissions/commissions.go b/core/commissions/commissions.go index cf22d2270..8a333425a 100644 --- a/core/commissions/commissions.go +++ b/core/commissions/commissions.go @@ -17,4 +17,4 @@ const ( SetHaltBlock int64 = 1000 RecreateCoin int64 = 10000000 ChangeOwner int64 = 10000000 -) \ No newline at end of file +) diff --git a/core/state/coins/bus.go b/core/state/coins/bus.go index 4609458d5..7564262ed 100644 --- a/core/state/coins/bus.go +++ b/core/state/coins/bus.go @@ -21,13 +21,13 @@ func (b *Bus) GetCoin(id types.CoinID) *bus.Coin { } return &bus.Coin{ - ID: coin.id, - Name: coin.Name(), - Crr: coin.Crr(), - Symbol: coin.Symbol(), - Volume: coin.Volume(), - Reserve: coin.Reserve(), - Version: coin.Version(), + ID: coin.id, + Name: coin.Name(), + Crr: coin.Crr(), + Symbol: coin.Symbol(), + Volume: coin.Volume(), + Reserve: coin.Reserve(), + Version: coin.Version(), } } From 8b1ea689de41368488ac25366a0132232e2106a9 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 15 Jul 2020 15:19:52 +0300 Subject: [PATCH 076/426] MN-435: use symbol for RecreateCoin --- api/api.go | 1 + api/coin_id.go | 38 ++++++++++++++++++++++ core/commissions/commissions.go | 4 +-- core/state/coins/coins.go | 45 +++++++++------------------ core/transaction/encoder/resources.go | 16 ++++------ core/transaction/recreate_coin.go | 10 +++--- 6 files changed, 67 insertions(+), 47 deletions(-) create mode 100644 api/coin_id.go diff --git a/api/api.go b/api/api.go index 0bf796a9a..7b384d497 100644 --- a/api/api.go +++ b/api/api.go @@ -44,6 +44,7 @@ var Routes = map[string]*rpcserver.RPCFunc{ "events": rpcserver.NewRPCFunc(Events, "height"), "net_info": rpcserver.NewRPCFunc(NetInfo, ""), "coin_info": rpcserver.NewRPCFunc(CoinInfo, "symbol,height"), + "coin_id": rpcserver.NewRPCFunc(CoinIdInfo, "id,height"), "estimate_coin_sell": rpcserver.NewRPCFunc(EstimateCoinSell, "coin_to_sell,coin_to_buy,value_to_sell,height"), "estimate_coin_sell_all": rpcserver.NewRPCFunc(EstimateCoinSellAll, "coin_to_sell,coin_to_buy,value_to_sell,gas_price,height"), "estimate_coin_buy": rpcserver.NewRPCFunc(EstimateCoinBuy, "coin_to_sell,coin_to_buy,value_to_buy,height"), diff --git a/api/coin_id.go b/api/coin_id.go new file mode 100644 index 000000000..98e9370de --- /dev/null +++ b/api/coin_id.go @@ -0,0 +1,38 @@ +package api + +import ( + "github.com/MinterTeam/minter-go-node/core/types" + rpctypes "github.com/MinterTeam/minter-go-node/rpc/lib/types" +) + +func CoinIdInfo(id int, height int) (*CoinInfoResponse, error) { + cState, err := GetStateForHeight(height) + if err != nil { + return nil, err + } + + cState.RLock() + defer cState.RUnlock() + + coin := cState.Coins().GetCoin(types.CoinID(id)) + if coin == nil { + return nil, rpctypes.RPCError{Code: 404, Message: "Coin not found"} + } + + var ownerAddress *types.Address + info := cState.Coins().GetSymbolInfo(coin.Symbol()) + if info != nil && info.OwnerAddress() != nil { + ownerAddress = info.OwnerAddress() + } + + return &CoinInfoResponse{ + ID: coin.ID().Uint32(), + Name: coin.Name(), + Symbol: coin.GetFullSymbol(), + Volume: coin.Volume().String(), + Crr: coin.Crr(), + ReserveBalance: coin.Reserve().String(), + MaxSupply: coin.MaxSupply().String(), + OwnerAddress: ownerAddress, + }, nil +} diff --git a/core/commissions/commissions.go b/core/commissions/commissions.go index 8a333425a..ac8867679 100644 --- a/core/commissions/commissions.go +++ b/core/commissions/commissions.go @@ -15,6 +15,6 @@ const ( MultisendDelta int64 = 5 RedeemCheckTx int64 = SendTx * 3 SetHaltBlock int64 = 1000 - RecreateCoin int64 = 10000000 - ChangeOwner int64 = 10000000 + RecreateCoin int64 = 10 + ChangeOwner int64 = 10 ) diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index ccd0cb490..b3a1f8197 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -221,46 +221,31 @@ func (c *Coins) Create(id types.CoinID, symbol types.CoinSymbol, name string, c.bus.Checker().AddCoinVolume(coin.id, volume) } -func (c *Coins) Recreate(newID types.CoinID, recreateID types.CoinID, +func (c *Coins) Recreate(newID types.CoinID, symbol types.CoinSymbol, volume *big.Int, crr uint, reserve *big.Int, maxSupply *big.Int, ) { - recreateCoin := c.GetCoin(recreateID) + recreateCoin := c.GetCoinBySymbol(symbol) if recreateCoin == nil { panic("coin to recreate does not exists") } // update version for recreating coin - symbolCoins := c.getBySymbol(recreateCoin.Symbol()) - lastRecreatedCoin := c.GetCoin(symbolCoins[len(symbolCoins)-1]) - recreateCoin.CVersion = lastRecreatedCoin.Version() + 1 - c.setToMap(recreateCoin.id, recreateCoin) - c.markDirty(recreateCoin.id) - - coin := &Model{ - CName: "", - CCrr: crr, - CMaxSupply: maxSupply, - CSymbol: recreateCoin.Symbol(), - CVersion: BaseVersion, - id: newID, - markDirty: c.markDirty, - isDirty: true, - isCreated: true, - info: &Info{ - Volume: big.NewInt(0), - Reserve: big.NewInt(0), - isDirty: false, - }, + symbolCoins := c.getBySymbol(symbol) + + // TODO: change array to sorted array by version and get the last one + lastVersion := uint16(0) + for _, id := range symbolCoins { + coin := c.GetCoin(id) + if coin.Version() > lastVersion { + lastVersion = coin.Version() + } } - c.setToMap(coin.id, coin) - - coin.SetReserve(reserve) - coin.SetVolume(volume) - c.markDirty(coin.id) + recreateCoin.CVersion = lastVersion + 1 + c.setToMap(recreateCoin.id, recreateCoin) + c.markDirty(recreateCoin.id) - c.bus.Checker().AddCoin(types.GetBaseCoinID(), reserve) - c.bus.Checker().AddCoinVolume(coin.id, volume) + c.Create(newID, recreateCoin.Symbol(), "", volume, crr, reserve, maxSupply, nil) } func (c *Coins) ChangeOwner(symbol types.CoinSymbol, owner types.Address) { diff --git a/core/transaction/encoder/resources.go b/core/transaction/encoder/resources.go index 03719fc12..fda21cf8a 100644 --- a/core/transaction/encoder/resources.go +++ b/core/transaction/encoder/resources.go @@ -305,22 +305,18 @@ func (SetHaltBlockDataResource) Transform(txData interface{}, context *state.Che // TxType 0x10 type RecreateCoinDataResource struct { - Coin CoinResource `json:"coin"` - InitialAmount string `json:"initial_amount"` - InitialReserve string `json:"initial_reserve"` - ConstantReserveRatio string `json:"constant_reserve_ratio"` - MaxSupply string `json:"max_supply"` + Symbol types.CoinSymbol `json:"symbol"` + InitialAmount string `json:"initial_amount"` + InitialReserve string `json:"initial_reserve"` + ConstantReserveRatio string `json:"constant_reserve_ratio"` + MaxSupply string `json:"max_supply"` } func (RecreateCoinDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.RecreateCoinData) - coin := context.Coins().GetCoin(data.Coin) return RecreateCoinDataResource{ - Coin: CoinResource{ - ID: coin.ID().Uint32(), - Symbol: coin.GetFullSymbol(), - }, + Symbol: data.Symbol, InitialAmount: data.InitialAmount.String(), InitialReserve: data.InitialReserve.String(), ConstantReserveRatio: strconv.Itoa(int(data.ConstantReserveRatio)), diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 84433f5c1..5c92900fe 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -13,7 +13,7 @@ import ( ) type RecreateCoinData struct { - Coin types.CoinID + Symbol types.CoinSymbol InitialAmount *big.Int InitialReserve *big.Int ConstantReserveRatio uint @@ -57,11 +57,11 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta sender, _ := tx.Sender() - coin := context.Coins().GetCoin(data.Coin) + coin := context.Coins().GetCoinBySymbol(data.Symbol) if coin == nil { return &Response{ Code: code.CoinNotExists, - Log: fmt.Sprintf("Coin %s not exists", data.Coin), + Log: fmt.Sprintf("Coin %s not exists", data.Symbol), } } @@ -78,7 +78,7 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta func (data RecreateCoinData) String() string { return fmt.Sprintf("RECREATE COIN symbol:%s reserve:%s amount:%s crr:%d", - data.Coin.String(), data.InitialReserve, data.InitialAmount, data.ConstantReserveRatio) + data.Symbol.String(), data.InitialReserve, data.InitialAmount, data.ConstantReserveRatio) } func (data RecreateCoinData) Gas() int64 { @@ -184,7 +184,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar coinID := deliveryState.App.GetNextCoinID() deliveryState.Coins.Recreate( coinID, - data.Coin, + data.Symbol, data.InitialAmount, data.ConstantReserveRatio, data.InitialReserve, From 332f88d20a3655676c3e49f9c23783546309a340 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 15 Jul 2020 15:48:27 +0300 Subject: [PATCH 077/426] refactoring --- core/minter/minter.go | 4 ++-- core/state/state.go | 20 +--------------- core/transaction/buy_coin.go | 16 ++++++------- core/transaction/change_owner.go | 12 +++++----- core/transaction/create_coin.go | 20 ++++++++-------- core/transaction/create_multisig.go | 12 +++++----- core/transaction/declare_candidacy.go | 16 ++++++------- core/transaction/delegate.go | 14 +++++------ core/transaction/edit_candidate.go | 14 +++++------ core/transaction/executor.go | 3 +-- core/transaction/multisend.go | 14 +++++------ core/transaction/recreate_coin.go | 20 ++++++++-------- core/transaction/redeem_check.go | 16 ++++++------- core/transaction/sell_all_coin.go | 16 ++++++------- core/transaction/sell_coin.go | 16 ++++++------- core/transaction/send.go | 16 ++++++------- core/transaction/set_halt_block.go | 12 +++++----- core/transaction/switch_candidate_status.go | 26 ++++++++++----------- core/transaction/unbond.go | 14 +++++------ 19 files changed, 131 insertions(+), 150 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index 3520dae7a..06030490b 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -409,7 +409,7 @@ func (app *Blockchain) Info(req abciTypes.RequestInfo) (resInfo abciTypes.Respon // Deliver a tx for full processing func (app *Blockchain) DeliverTx(req abciTypes.RequestDeliverTx) abciTypes.ResponseDeliverTx { - response := transaction.RunTx(app.stateDeliver, false, req.Tx, app.rewards, app.height, &sync.Map{}, 0) + response := transaction.RunTx(app.stateDeliver, req.Tx, app.rewards, app.height, &sync.Map{}, 0) return abciTypes.ResponseDeliverTx{ Code: response.Code, @@ -429,7 +429,7 @@ func (app *Blockchain) DeliverTx(req abciTypes.RequestDeliverTx) abciTypes.Respo // Validate a tx for the mempool func (app *Blockchain) CheckTx(req abciTypes.RequestCheckTx) abciTypes.ResponseCheckTx { - response := transaction.RunTx(app.stateCheck, true, req.Tx, nil, app.height, app.currentMempool, app.MinGasPrice()) + response := transaction.RunTx(app.stateCheck, req.Tx, nil, app.height, app.currentMempool, app.MinGasPrice()) return abciTypes.ResponseCheckTx{ Code: response.Code, diff --git a/core/state/state.go b/core/state/state.go index caf92611b..e75a113b0 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -301,24 +301,6 @@ func (s *State) Export(height uint64) types.AppState { return *appState } -func (s *State) Export11To12(height uint64) types.AppState { - state, err := NewCheckStateAtHeight(height, s.db) - if err != nil { - log.Panicf("Create new state at height %d failed: %s", height, err) - } - - appState := new(types.AppState) - state.App().Export(appState, height) - state.Validators().Export(appState) - state.Candidates().Export11To12(appState) - state.FrozenFunds().Export(appState, height) - state.Accounts().Export(appState) - state.Coins().Export(appState) - state.Checks().Export(appState) - - return *appState -} - func (s *State) Export11To12(height uint64) types.AppState { iavlTree := tree.NewImmutableTree(height, s.db) @@ -361,7 +343,7 @@ func (s *State) Export11To12(height uint64) types.AppState { appState.Export(state, height) coinsState.Export(state) validatorsState.Export(state) - candidatesState.Export11To12(state) + candidatesState.Export(state) frozenFundsState.Export(state, height) accountsState.Export(state) checksState.Export(state) diff --git a/core/transaction/buy_coin.go b/core/transaction/buy_coin.go index 5c90726d4..fc144dad1 100644 --- a/core/transaction/buy_coin.go +++ b/core/transaction/buy_coin.go @@ -399,22 +399,22 @@ func (data BuyCoinData) Run(tx *Transaction, context state.Interface, rewardPool return *errResp } - if deliveryState, ok := context.(*state.State); ok { + if deliverState, ok := context.(*state.State); ok { for _, ts := range totalSpends { - deliveryState.Accounts.SubBalance(sender, ts.Coin, ts.Value) + deliverState.Accounts.SubBalance(sender, ts.Coin, ts.Value) } for _, conversion := range conversions { - deliveryState.Coins.SubVolume(conversion.FromCoin, conversion.FromAmount) - deliveryState.Coins.SubReserve(conversion.FromCoin, conversion.FromReserve) + deliverState.Coins.SubVolume(conversion.FromCoin, conversion.FromAmount) + deliverState.Coins.SubReserve(conversion.FromCoin, conversion.FromReserve) - deliveryState.Coins.AddVolume(conversion.ToCoin, conversion.ToAmount) - deliveryState.Coins.AddReserve(conversion.ToCoin, conversion.ToReserve) + deliverState.Coins.AddVolume(conversion.ToCoin, conversion.ToAmount) + deliverState.Coins.AddReserve(conversion.ToCoin, conversion.ToReserve) } rewardPool.Add(rewardPool, tx.CommissionInBaseCoin()) - deliveryState.Accounts.AddBalance(sender, data.CoinToBuy, data.ValueToBuy) - deliveryState.Accounts.SetNonce(sender, tx.Nonce) + deliverState.Accounts.AddBalance(sender, data.CoinToBuy, data.ValueToBuy) + deliverState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/change_owner.go b/core/transaction/change_owner.go index a2e3f5f12..119899fec 100644 --- a/core/transaction/change_owner.go +++ b/core/transaction/change_owner.go @@ -102,13 +102,13 @@ func (data ChangeOwnerData) Run(tx *Transaction, context state.Interface, reward } } - if deliveryState, ok := context.(*state.State); ok { + if deliverState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - deliveryState.Coins.SubVolume(tx.GasCoin, commission) - deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) - deliveryState.Coins.ChangeOwner(data.Symbol, data.NewOwner) - deliveryState.Accounts.SetNonce(sender, tx.Nonce) + deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliverState.Coins.SubVolume(tx.GasCoin, commission) + deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliverState.Coins.ChangeOwner(data.Symbol, data.NewOwner) + deliverState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index 8bce575f8..75ba39e7e 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -208,17 +208,17 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP } } - if deliveryState, ok := context.(*state.State); ok { + if deliverState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - deliveryState.Coins.SubVolume(tx.GasCoin, commission) + deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliverState.Coins.SubVolume(tx.GasCoin, commission) - deliveryState.Accounts.SubBalance(sender, types.GetBaseCoinID(), data.InitialReserve) - deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliverState.Accounts.SubBalance(sender, types.GetBaseCoinID(), data.InitialReserve) + deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) - coinID := deliveryState.App.GetCoinsCount() + 1 - deliveryState.Coins.Create( + coinID := deliverState.App.GetCoinsCount() + 1 + deliverState.Coins.Create( types.CoinID(coinID), data.Symbol, data.Name, @@ -229,9 +229,9 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP &sender, ) - deliveryState.App.SetCoinsCount(coinID) - deliveryState.Accounts.AddBalance(sender, types.CoinID(coinID), data.InitialAmount) - deliveryState.Accounts.SetNonce(sender, tx.Nonce) + deliverState.App.SetCoinsCount(coinID) + deliverState.Accounts.AddBalance(sender, types.CoinID(coinID), data.InitialAmount) + deliverState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index fecf43587..702cd1533 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -160,16 +160,16 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew } } - if deliveryState, ok := context.(*state.State); ok { + if deliverState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - deliveryState.Coins.SubVolume(tx.GasCoin, commission) - deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliverState.Coins.SubVolume(tx.GasCoin, commission) + deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) - deliveryState.Accounts.SetNonce(sender, tx.Nonce) + deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliverState.Accounts.SetNonce(sender, tx.Nonce) - deliveryState.Accounts.CreateMultisig(data.Weights, data.Addresses, data.Threshold, currentBlock) + deliverState.Accounts.CreateMultisig(data.Weights, data.Addresses, data.Threshold, currentBlock) } tags := kv.Pairs{ diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index 8d1535eed..1d12deca6 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -192,17 +192,17 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r } } - if deliveryState, ok := context.(*state.State); ok { + if deliverState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - deliveryState.Coins.SubVolume(tx.GasCoin, commission) + deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliverState.Coins.SubVolume(tx.GasCoin, commission) - deliveryState.Accounts.SubBalance(sender, data.Coin, data.Stake) - deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) - deliveryState.Candidates.Create(data.Address, sender, sender, data.PubKey, data.Commission) - deliveryState.Candidates.Delegate(sender, data.PubKey, data.Coin, data.Stake, big.NewInt(0)) - deliveryState.Accounts.SetNonce(sender, tx.Nonce) + deliverState.Accounts.SubBalance(sender, data.Coin, data.Stake) + deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliverState.Candidates.Create(data.Address, sender, sender, data.PubKey, data.Commission) + deliverState.Candidates.Delegate(sender, data.PubKey, data.Coin, data.Stake, big.NewInt(0)) + deliverState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index 55a859ddb..b7cff56e3 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -166,16 +166,16 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo } } - if deliveryState, ok := context.(*state.State); ok { + if deliverState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - deliveryState.Coins.SubVolume(tx.GasCoin, commission) + deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliverState.Coins.SubVolume(tx.GasCoin, commission) - deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) - deliveryState.Accounts.SubBalance(sender, data.Coin, data.Value) - deliveryState.Candidates.Delegate(sender, data.PubKey, data.Coin, data.Value, big.NewInt(0)) - deliveryState.Accounts.SetNonce(sender, tx.Nonce) + deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliverState.Accounts.SubBalance(sender, data.Coin, data.Value) + deliverState.Candidates.Delegate(sender, data.PubKey, data.Coin, data.Value, big.NewInt(0)) + deliverState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index 88ceb5521..fb3ba341c 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -125,18 +125,18 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa } } - if deliveryState, ok := context.(*state.State); ok { + if deliverState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - deliveryState.Coins.SubVolume(tx.GasCoin, commission) + deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliverState.Coins.SubVolume(tx.GasCoin, commission) - deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) - deliveryState.Candidates.Edit(data.PubKey, data.RewardAddress, data.OwnerAddress, data.ControlAddress) + deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliverState.Candidates.Edit(data.PubKey, data.RewardAddress, data.OwnerAddress, data.ControlAddress) if data.NewPubKey != nil { - deliveryState.Candidates.ChangePubKey(data.PubKey, *data.NewPubKey) + deliverState.Candidates.ChangePubKey(data.PubKey, *data.NewPubKey) } - deliveryState.Accounts.SetNonce(sender, tx.Nonce) + deliverState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/executor.go b/core/transaction/executor.go index 550f511e5..e8b1165d3 100644 --- a/core/transaction/executor.go +++ b/core/transaction/executor.go @@ -35,7 +35,6 @@ type Response struct { } func RunTx(context state.Interface, - isCheck bool, rawTx []byte, rewardPool *big.Int, currentBlock uint64, @@ -73,7 +72,7 @@ func RunTx(context state.Interface, } var checkState *state.CheckState - //var isCheck bool + var isCheck bool if checkState, isCheck = context.(*state.CheckState); !isCheck { checkState = state.NewCheckState(context.(*state.State)) } diff --git a/core/transaction/multisend.go b/core/transaction/multisend.go index a6819b4f8..60ea52dee 100644 --- a/core/transaction/multisend.go +++ b/core/transaction/multisend.go @@ -115,18 +115,18 @@ func (data MultisendData) Run(tx *Transaction, context state.Interface, rewardPo return *errResp } - if deliveryState, ok := context.(*state.State); ok { + if deliverState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - deliveryState.Coins.SubVolume(tx.GasCoin, commission) - deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliverState.Coins.SubVolume(tx.GasCoin, commission) + deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) for _, item := range data.List { - deliveryState.Accounts.SubBalance(sender, item.Coin, item.Value) - deliveryState.Accounts.AddBalance(item.To, item.Coin, item.Value) + deliverState.Accounts.SubBalance(sender, item.Coin, item.Value) + deliverState.Accounts.AddBalance(item.To, item.Coin, item.Value) } - deliveryState.Accounts.SetNonce(sender, tx.Nonce) + deliverState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 84433f5c1..b1ad8e57c 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -172,17 +172,17 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar kv.Pair{Key: []byte("tx.from"), Value: []byte(hex.EncodeToString(sender[:]))}, } - if deliveryState, ok := context.(*state.State); ok { + if deliverState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - deliveryState.Coins.SubVolume(tx.GasCoin, commission) + deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliverState.Coins.SubVolume(tx.GasCoin, commission) - deliveryState.Accounts.SubBalance(sender, types.GetBaseCoinID(), data.InitialReserve) - deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliverState.Accounts.SubBalance(sender, types.GetBaseCoinID(), data.InitialReserve) + deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) - coinID := deliveryState.App.GetNextCoinID() - deliveryState.Coins.Recreate( + coinID := deliverState.App.GetNextCoinID() + deliverState.Coins.Recreate( coinID, data.Coin, data.InitialAmount, @@ -191,9 +191,9 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar data.MaxSupply, ) - deliveryState.App.SetCoinsCount(coinID.Uint32()) - deliveryState.Accounts.AddBalance(sender, coinID, data.InitialAmount) - deliveryState.Accounts.SetNonce(sender, tx.Nonce) + deliverState.App.SetCoinsCount(coinID.Uint32()) + deliverState.Accounts.AddBalance(sender, coinID, data.InitialAmount) + deliverState.Accounts.SetNonce(sender, tx.Nonce) tags = append(tags, kv.Pair{ Key: []byte("tx.coin"), diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index 193528cc7..309045244 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -246,17 +246,17 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward } } - if deliveryState, ok := context.(*state.State); ok { - deliveryState.Checks.UseCheck(decodedCheck) + if deliverState, ok := context.(*state.State); ok { + deliverState.Checks.UseCheck(decodedCheck) rewardPool.Add(rewardPool, commissionInBaseCoin) - deliveryState.Coins.SubVolume(decodedCheck.GasCoin, commission) - deliveryState.Coins.SubReserve(decodedCheck.GasCoin, commissionInBaseCoin) + deliverState.Coins.SubVolume(decodedCheck.GasCoin, commission) + deliverState.Coins.SubReserve(decodedCheck.GasCoin, commissionInBaseCoin) - deliveryState.Accounts.SubBalance(checkSender, decodedCheck.GasCoin, commission) - deliveryState.Accounts.SubBalance(checkSender, decodedCheck.Coin, decodedCheck.Value) - deliveryState.Accounts.AddBalance(sender, decodedCheck.Coin, decodedCheck.Value) - deliveryState.Accounts.SetNonce(sender, tx.Nonce) + deliverState.Accounts.SubBalance(checkSender, decodedCheck.GasCoin, commission) + deliverState.Accounts.SubBalance(checkSender, decodedCheck.Coin, decodedCheck.Value) + deliverState.Accounts.AddBalance(sender, decodedCheck.Coin, decodedCheck.Value) + deliverState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/sell_all_coin.go b/core/transaction/sell_all_coin.go index ca8e41d97..e84eebd21 100644 --- a/core/transaction/sell_all_coin.go +++ b/core/transaction/sell_all_coin.go @@ -235,22 +235,22 @@ func (data SellAllCoinData) Run(tx *Transaction, context state.Interface, reward return *errResp } - if deliveryState, ok := context.(*state.State); ok { + if deliverState, ok := context.(*state.State); ok { for _, ts := range totalSpends { - deliveryState.Accounts.SubBalance(sender, ts.Coin, ts.Value) + deliverState.Accounts.SubBalance(sender, ts.Coin, ts.Value) } for _, conversion := range conversions { - deliveryState.Coins.SubVolume(conversion.FromCoin, conversion.FromAmount) - deliveryState.Coins.SubReserve(conversion.FromCoin, conversion.FromReserve) + deliverState.Coins.SubVolume(conversion.FromCoin, conversion.FromAmount) + deliverState.Coins.SubReserve(conversion.FromCoin, conversion.FromReserve) - deliveryState.Coins.AddVolume(conversion.ToCoin, conversion.ToAmount) - deliveryState.Coins.AddReserve(conversion.ToCoin, conversion.ToReserve) + deliverState.Coins.AddVolume(conversion.ToCoin, conversion.ToAmount) + deliverState.Coins.AddReserve(conversion.ToCoin, conversion.ToReserve) } rewardPool.Add(rewardPool, tx.CommissionInBaseCoin()) - deliveryState.Accounts.AddBalance(sender, data.CoinToBuy, value) - deliveryState.Accounts.SetNonce(sender, tx.Nonce) + deliverState.Accounts.AddBalance(sender, data.CoinToBuy, value) + deliverState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/sell_coin.go b/core/transaction/sell_coin.go index 022d35727..fb211ef89 100644 --- a/core/transaction/sell_coin.go +++ b/core/transaction/sell_coin.go @@ -366,22 +366,22 @@ func (data SellCoinData) Run(tx *Transaction, context state.Interface, rewardPoo return *errResp } - if deliveryState, ok := context.(*state.State); ok { + if deliverState, ok := context.(*state.State); ok { for _, ts := range totalSpends { - deliveryState.Accounts.SubBalance(sender, ts.Coin, ts.Value) + deliverState.Accounts.SubBalance(sender, ts.Coin, ts.Value) } for _, conversion := range conversions { - deliveryState.Coins.SubVolume(conversion.FromCoin, conversion.FromAmount) - deliveryState.Coins.SubReserve(conversion.FromCoin, conversion.FromReserve) + deliverState.Coins.SubVolume(conversion.FromCoin, conversion.FromAmount) + deliverState.Coins.SubReserve(conversion.FromCoin, conversion.FromReserve) - deliveryState.Coins.AddVolume(conversion.ToCoin, conversion.ToAmount) - deliveryState.Coins.AddReserve(conversion.ToCoin, conversion.ToReserve) + deliverState.Coins.AddVolume(conversion.ToCoin, conversion.ToAmount) + deliverState.Coins.AddReserve(conversion.ToCoin, conversion.ToReserve) } rewardPool.Add(rewardPool, tx.CommissionInBaseCoin()) - deliveryState.Accounts.AddBalance(sender, data.CoinToBuy, value) - deliveryState.Accounts.SetNonce(sender, tx.Nonce) + deliverState.Accounts.AddBalance(sender, data.CoinToBuy, value) + deliverState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/send.go b/core/transaction/send.go index 6ed519b2c..89bbaea34 100644 --- a/core/transaction/send.go +++ b/core/transaction/send.go @@ -147,22 +147,22 @@ func (data SendData) Run(tx *Transaction, context state.Interface, rewardPool *b } } - if deliveryState, ok := context.(*state.State); ok { + if deliverState, ok := context.(*state.State); ok { for _, ts := range totalSpends { - deliveryState.Accounts.SubBalance(sender, ts.Coin, ts.Value) + deliverState.Accounts.SubBalance(sender, ts.Coin, ts.Value) } for _, conversion := range conversions { - deliveryState.Coins.SubVolume(conversion.FromCoin, conversion.FromAmount) - deliveryState.Coins.SubReserve(conversion.FromCoin, conversion.FromReserve) + deliverState.Coins.SubVolume(conversion.FromCoin, conversion.FromAmount) + deliverState.Coins.SubReserve(conversion.FromCoin, conversion.FromReserve) - deliveryState.Coins.AddVolume(conversion.ToCoin, conversion.ToAmount) - deliveryState.Coins.AddReserve(conversion.ToCoin, conversion.ToReserve) + deliverState.Coins.AddVolume(conversion.ToCoin, conversion.ToAmount) + deliverState.Coins.AddReserve(conversion.ToCoin, conversion.ToReserve) } rewardPool.Add(rewardPool, tx.CommissionInBaseCoin()) - deliveryState.Accounts.AddBalance(data.To, data.Coin, data.Value) - deliveryState.Accounts.SetNonce(sender, tx.Nonce) + deliverState.Accounts.AddBalance(data.To, data.Coin, data.Value) + deliverState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index f0b3bf545..d9d884a3e 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -123,15 +123,15 @@ func (data SetHaltBlockData) Run(tx *Transaction, context state.Interface, rewar } } - if deliveryState, ok := context.(*state.State); ok { + if deliverState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - deliveryState.Coins.SubVolume(tx.GasCoin, commission) + deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliverState.Coins.SubVolume(tx.GasCoin, commission) - deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) - deliveryState.Halts.AddHaltBlock(data.Height, data.PubKey) - deliveryState.Accounts.SetNonce(sender, tx.Nonce) + deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliverState.Halts.AddHaltBlock(data.Height, data.PubKey) + deliverState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index 78f079b13..762ccfdc3 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -94,15 +94,15 @@ func (data SetCandidateOnData) Run(tx *Transaction, context state.Interface, rew } } - if deliveryState, ok := context.(*state.State); ok { + if deliverState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - deliveryState.Coins.SubVolume(tx.GasCoin, commission) + deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliverState.Coins.SubVolume(tx.GasCoin, commission) - deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) - deliveryState.Candidates.SetOnline(data.PubKey) - deliveryState.Accounts.SetNonce(sender, tx.Nonce) + deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliverState.Candidates.SetOnline(data.PubKey) + deliverState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ @@ -194,16 +194,16 @@ func (data SetCandidateOffData) Run(tx *Transaction, context state.Interface, re } } - if deliveryState, ok := context.(*state.State); ok { + if deliverState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) - deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - deliveryState.Coins.SubVolume(tx.GasCoin, commission) + deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliverState.Coins.SubVolume(tx.GasCoin, commission) - deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) - deliveryState.Candidates.SetOffline(data.PubKey) - deliveryState.Validators.SetToDrop(data.PubKey) - deliveryState.Accounts.SetNonce(sender, tx.Nonce) + deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliverState.Candidates.SetOffline(data.PubKey) + deliverState.Validators.SetToDrop(data.PubKey) + deliverState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 1e2de7aed..44d104818 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -147,19 +147,19 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool } } - if deliveryState, ok := context.(*state.State); ok { + if deliverState, ok := context.(*state.State); ok { // now + 30 days unbondAtBlock := currentBlock + unbondPeriod rewardPool.Add(rewardPool, commissionInBaseCoin) - deliveryState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) - deliveryState.Coins.SubVolume(tx.GasCoin, commission) + deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliverState.Coins.SubVolume(tx.GasCoin, commission) - deliveryState.Accounts.SubBalance(sender, tx.GasCoin, commission) - deliveryState.Candidates.SubStake(sender, data.PubKey, data.Coin, data.Value) - deliveryState.FrozenFunds.AddFund(unbondAtBlock, sender, data.PubKey, data.Coin, data.Value) - deliveryState.Accounts.SetNonce(sender, tx.Nonce) + deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliverState.Candidates.SubStake(sender, data.PubKey, data.Coin, data.Value) + deliverState.FrozenFunds.AddFund(unbondAtBlock, sender, data.PubKey, data.Coin, data.Value) + deliverState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ From 6045dad3249fed725beee96bdca22d8f48e0a6f6 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 15 Jul 2020 18:15:57 +0300 Subject: [PATCH 078/426] merge and refactoring --- cmd/minter/cmd/export.go | 2 +- core/state/state.go | 100 +++++++++++++++++++-------------------- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/cmd/minter/cmd/export.go b/cmd/minter/cmd/export.go index 195af26f3..e3cf37ba3 100644 --- a/cmd/minter/cmd/export.go +++ b/cmd/minter/cmd/export.go @@ -58,7 +58,7 @@ func export(cmd *cobra.Command, args []string) error { log.Panicf("Cannot load db: %s", err) } - currentState, err := state.NewState(height, ldb, nil, 1, 1) + currentState, err := state.NewCheckStateAtHeight(height, ldb) if err != nil { log.Panicf("Cannot new state at given height: %s", err) } diff --git a/core/state/state.go b/core/state/state.go index e75a113b0..f153e2bfd 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -86,6 +86,56 @@ func (cs *CheckState) Tree() tree.ReadOnlyTree { return cs.state.Tree() } +func (cs *CheckState) Export11To12(height uint64) types.AppState { + iavlTree := cs.state.tree + + candidatesState, err := legacyCandidates.NewCandidates(nil, iavlTree) + if err != nil { + log.Panicf("Create new state at height %d failed: %s", height, err) + } + + validatorsState, err := validators.NewValidators(nil, iavlTree) + if err != nil { + log.Panicf("Create new state at height %d failed: %s", height, err) + } + + appState, err := legacyApp.NewApp(nil, iavlTree) + if err != nil { + log.Panicf("Create new state at height %d failed: %s", height, err) + } + + frozenFundsState, err := legacyFrozenfunds.NewFrozenFunds(nil, iavlTree) + if err != nil { + log.Panicf("Create new state at height %d failed: %s", height, err) + } + + accountsState, err := legacyAccounts.NewAccounts(nil, iavlTree) + if err != nil { + log.Panicf("Create new state at height %d failed: %s", height, err) + } + + coinsState, err := legacyCoins.NewCoins(nil, iavlTree) + if err != nil { + log.Panicf("Create new state at height %d failed: %s", height, err) + } + + checksState, err := checks.NewChecks(iavlTree) + if err != nil { + log.Panicf("Create new state at height %d failed: %s", height, err) + } + + state := new(types.AppState) + appState.Export(state, height) + coinsState.Export(state) + validatorsState.Export(state) + candidatesState.Export(state) + frozenFundsState.Export(state, height) + accountsState.Export(state) + checksState.Export(state) + + return *state +} + type State struct { App *app.App Validators *validators.Validators @@ -301,56 +351,6 @@ func (s *State) Export(height uint64) types.AppState { return *appState } -func (s *State) Export11To12(height uint64) types.AppState { - iavlTree := tree.NewImmutableTree(height, s.db) - - candidatesState, err := legacyCandidates.NewCandidates(nil, iavlTree) - if err != nil { - log.Panicf("Create new state at height %d failed: %s", height, err) - } - - validatorsState, err := validators.NewValidators(nil, iavlTree) - if err != nil { - log.Panicf("Create new state at height %d failed: %s", height, err) - } - - appState, err := legacyApp.NewApp(nil, iavlTree) - if err != nil { - log.Panicf("Create new state at height %d failed: %s", height, err) - } - - frozenFundsState, err := legacyFrozenfunds.NewFrozenFunds(nil, iavlTree) - if err != nil { - log.Panicf("Create new state at height %d failed: %s", height, err) - } - - accountsState, err := legacyAccounts.NewAccounts(nil, iavlTree) - if err != nil { - log.Panicf("Create new state at height %d failed: %s", height, err) - } - - coinsState, err := legacyCoins.NewCoins(nil, iavlTree) - if err != nil { - log.Panicf("Create new state at height %d failed: %s", height, err) - } - - checksState, err := checks.NewChecks(iavlTree) - if err != nil { - log.Panicf("Create new state at height %d failed: %s", height, err) - } - - state := new(types.AppState) - appState.Export(state, height) - coinsState.Export(state) - validatorsState.Export(state) - candidatesState.Export(state) - frozenFundsState.Export(state, height) - accountsState.Export(state) - checksState.Export(state) - - return *state -} - func newCheckStateForTree(iavlTree tree.MTree, events eventsdb.IEventsDB, db db.DB, keepLastStates int64) (*CheckState, error) { stateForTree, err := newStateForTree(iavlTree, events, db, keepLastStates) if err != nil { From 62f7de8f46cfad2ee86d388e242116f81544e2bd Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 16 Jul 2020 10:12:23 +0300 Subject: [PATCH 079/426] MN-435: fix commissions --- core/commissions/commissions.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/commissions/commissions.go b/core/commissions/commissions.go index ac8867679..8a333425a 100644 --- a/core/commissions/commissions.go +++ b/core/commissions/commissions.go @@ -15,6 +15,6 @@ const ( MultisendDelta int64 = 5 RedeemCheckTx int64 = SendTx * 3 SetHaltBlock int64 = 1000 - RecreateCoin int64 = 10 - ChangeOwner int64 = 10 + RecreateCoin int64 = 10000000 + ChangeOwner int64 = 10000000 ) From c056e652986ff5e8f8070330623dbeadd05ac790 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Thu, 16 Jul 2020 10:32:27 +0300 Subject: [PATCH 080/426] Update version --- version/version.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/version/version.go b/version/version.go index 9fdaa462a..ae573008b 100755 --- a/version/version.go +++ b/version/version.go @@ -3,15 +3,15 @@ package version // Version components const ( Maj = "1" - Min = "1" - Fix = "7" + Min = "2" + Fix = "0" - AppVer = 6 + AppVer = 7 ) var ( // Must be a string because scripts like dist.sh read this file. - Version = "1.1.7" + Version = "1.2.0" // GitCommit is the current HEAD set using ldflags. GitCommit string From a17121543744df06d4108c9b0e8ede7ee97d237d Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 16 Jul 2020 17:52:17 +0300 Subject: [PATCH 081/426] update api v2 --- api/v2/service/address.go | 55 +++++++++++++----------- api/v2/service/addresses.go | 48 ++++++++++++--------- api/v2/service/candidate.go | 7 ++- api/v2/service/estimate_coin_buy.go | 10 ++--- api/v2/service/estimate_coin_sell.go | 22 ++++++---- api/v2/service/estimate_coin_sell_all.go | 8 ++-- api/v2/service/estimate_tx_commission.go | 4 +- api/v2/service/service.go | 9 +--- cmd/minter/cmd/node.go | 31 +++++++------ go.mod | 2 +- go.sum | 4 +- 11 files changed, 111 insertions(+), 89 deletions(-) diff --git a/api/v2/service/address.go b/api/v2/service/address.go index 34ca5010a..a2e2205ba 100644 --- a/api/v2/service/address.go +++ b/api/v2/service/address.go @@ -47,17 +47,17 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr } balances := cState.Accounts().GetBalances(address) - var response pb.AddressResponse + var res pb.AddressResponse totalStakesGroupByCoin := map[types.CoinID]*big.Int{} - response.Balance = make(map[string]*pb.AddressBalance, len(balances)) - for coin, value := range balances { - totalStakesGroupByCoin[coin] = value - response.Balance[coin.String()] = &pb.AddressBalance{ - Value: value.String(), - BipValue: customCoinBipBalance(coin, value, cState).String(), - } + res.Balance = make([]*pb.AddressBalance, 0, len(balances)) + for _, coin := range balances { + totalStakesGroupByCoin[coin.Coin.ID] = coin.Value + res.Balance = append(res.Balance, &pb.AddressBalance{ + Value: coin.Value.String(), + BipValue: customCoinBipBalance(coin.Coin.ID, coin.Value, cState).String(), + }) } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { @@ -87,18 +87,22 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr return new(pb.AddressResponse), timeoutStatus.Err() } - response.Delegated = make(map[string]*pb.AddressDelegatedBalance, len(userDelegatedStakesGroupByCoin)) - for coin, delegatedStake := range userDelegatedStakesGroupByCoin { - response.Delegated[coin.String()] = &pb.AddressDelegatedBalance{ + res.Delegated = make([]*pb.AddressDelegatedBalance, 0, len(userDelegatedStakesGroupByCoin)) + for coinID, delegatedStake := range userDelegatedStakesGroupByCoin { + res.Delegated = append(res.Delegated, &pb.AddressDelegatedBalance{ + Coin: &pb.Coin{ + Id: coinID.String(), + Symbol: cState.Coins().GetCoin(coinID).Symbol().String(), + }, Value: delegatedStake.Value.String(), DelegateBipValue: delegatedStake.BipValue.String(), - BipValue: customCoinBipBalance(coin, delegatedStake.Value, cState).String(), - } + BipValue: customCoinBipBalance(coinID, delegatedStake.Value, cState).String(), + }) - totalStake, ok := totalStakesGroupByCoin[coin] + totalStake, ok := totalStakesGroupByCoin[coinID] if !ok { totalStake = big.NewInt(0) - totalStakesGroupByCoin[coin] = totalStake + totalStakesGroupByCoin[coinID] = totalStake } totalStake.Add(totalStake, delegatedStake.Value) } @@ -109,21 +113,24 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr } coinsBipValue := big.NewInt(0) - response.Total = make(map[string]*pb.AddressBalance, len(totalStakesGroupByCoin)) - for coin, stake := range totalStakesGroupByCoin { - balance := customCoinBipBalance(coin, stake, cState) + res.Total = make([]*pb.AddressBalance, 0, len(totalStakesGroupByCoin)) + for coinID, stake := range totalStakesGroupByCoin { + balance := customCoinBipBalance(coinID, stake, cState) if req.Delegated { - response.Total[coin.String()] = &pb.AddressBalance{ + res.Total = append(res.Total, &pb.AddressBalance{ + Coin: &pb.Coin{ + Id: coinID.String(), + Symbol: cState.Coins().GetCoin(coinID).Symbol().String(), + }, Value: stake.String(), BipValue: balance.String(), - } + }) } coinsBipValue.Add(coinsBipValue, balance) } - response.BipValue = coinsBipValue.String() - - response.TransactionsCount = fmt.Sprintf("%d", cState.Accounts().GetNonce(address)) - return &response, nil + res.BipValue = coinsBipValue.String() + res.TransactionsCount = fmt.Sprintf("%d", cState.Accounts().GetNonce(address)) + return &res, nil } func customCoinBipBalance(coinToSell types.CoinID, valueToSell *big.Int, cState *state.CheckState) *big.Int { diff --git a/api/v2/service/addresses.go b/api/v2/service/addresses.go index d00925b34..91b511bb2 100644 --- a/api/v2/service/addresses.go +++ b/api/v2/service/addresses.go @@ -52,13 +52,13 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. totalStakesGroupByCoin := map[types.CoinID]*big.Int{} - res.Balance = make(map[string]*pb.AddressBalance, len(balances)) - for coin, value := range balances { - totalStakesGroupByCoin[coin] = value - res.Balance[coin.String()] = &pb.AddressBalance{ - Value: value.String(), - BipValue: customCoinBipBalance(coin, value, cState).String(), - } + res.Balance = make([]*pb.AddressBalance, 0, len(balances)) + for _, coin := range balances { + totalStakesGroupByCoin[coin.Coin.ID] = coin.Value + res.Balance = append(res.Balance, &pb.AddressBalance{ + Value: coin.Value.String(), + BipValue: customCoinBipBalance(coin.Coin.ID, coin.Value, cState).String(), + }) } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { @@ -88,36 +88,44 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. return new(pb.AddressesResponse), timeoutStatus.Err() } - res.Delegated = make(map[string]*pb.AddressDelegatedBalance, len(userDelegatedStakesGroupByCoin)) - for coin, delegatedStake := range userDelegatedStakesGroupByCoin { - res.Delegated[coin.String()] = &pb.AddressDelegatedBalance{ + res.Delegated = make([]*pb.AddressDelegatedBalance, 0, len(userDelegatedStakesGroupByCoin)) + for coinID, delegatedStake := range userDelegatedStakesGroupByCoin { + res.Delegated = append(res.Delegated, &pb.AddressDelegatedBalance{ + Coin: &pb.Coin{ + Id: coinID.String(), + Symbol: cState.Coins().GetCoin(coinID).Symbol().String(), + }, Value: delegatedStake.Value.String(), DelegateBipValue: delegatedStake.BipValue.String(), - BipValue: customCoinBipBalance(coin, delegatedStake.Value, cState).String(), - } + BipValue: customCoinBipBalance(coinID, delegatedStake.Value, cState).String(), + }) - totalStake, ok := totalStakesGroupByCoin[coin] + totalStake, ok := totalStakesGroupByCoin[coinID] if !ok { totalStake = big.NewInt(0) - totalStakesGroupByCoin[coin] = totalStake + totalStakesGroupByCoin[coinID] = totalStake } totalStake.Add(totalStake, delegatedStake.Value) } } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return response, timeoutStatus.Err() + return new(pb.AddressesResponse), timeoutStatus.Err() } coinsBipValue := big.NewInt(0) - res.Total = make(map[string]*pb.AddressBalance, len(totalStakesGroupByCoin)) - for coin, stake := range totalStakesGroupByCoin { - balance := customCoinBipBalance(coin, stake, cState) + res.Total = make([]*pb.AddressBalance, 0, len(totalStakesGroupByCoin)) + for coinID, stake := range totalStakesGroupByCoin { + balance := customCoinBipBalance(coinID, stake, cState) if req.Delegated { - res.Total[coin.String()] = &pb.AddressBalance{ + res.Total = append(res.Total, &pb.AddressBalance{ + Coin: &pb.Coin{ + Id: coinID.String(), + Symbol: cState.Coins().GetCoin(coinID).Symbol().String(), + }, Value: stake.String(), BipValue: balance.String(), - } + }) } coinsBipValue.Add(coinsBipValue, balance) } diff --git a/api/v2/service/candidate.go b/api/v2/service/candidate.go index 2dc885420..dd6242500 100644 --- a/api/v2/service/candidate.go +++ b/api/v2/service/candidate.go @@ -66,8 +66,11 @@ func makeResponseCandidate(state *state.CheckState, c *candidates.Candidate, inc candidate.Stakes = make([]*pb.CandidateResponse_Stake, 0, usedSlots) for i, stake := range stakes { candidate.Stakes = append(candidate.Stakes, &pb.CandidateResponse_Stake{ - Owner: stake.Owner.String(), - Coin: stake.Coin.String(), + Owner: stake.Owner.String(), + Coin: &pb.Coin{ + Id: stake.Coin.String(), + Symbol: state.Coins().GetCoin(stake.Coin).Symbol().String(), + }, Value: stake.Value.String(), BipValue: stake.BipValue.String(), }) diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index 8b62987a5..3c3676e69 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -22,8 +22,8 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe cState.RLock() defer cState.RUnlock() - coinToSell := types.StrToCoinSymbol(req.CoinToSell) - coinToBuy := types.StrToCoinSymbol(req.CoinToBuy) + coinToSell := types.CoinID(req.CoinIdToSell) + coinToBuy := types.CoinID(req.CoinIdToBuy) if coinToSell == coinToBuy { return new(pb.EstimateCoinBuyResponse), status.Error(codes.FailedPrecondition, "\"From\" coin equals to \"to\" coin") @@ -44,7 +44,7 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe coinFrom := cState.Coins().GetCoin(coinToSell) coinTo := cState.Coins().GetCoin(coinToBuy) - if coinToSell != types.GetBaseCoin() { + if !coinToSell.IsBaseCoin() { if coinFrom.Reserve().Cmp(commissionInBaseCoin) < 0 { return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coinFrom.Reserve().String(), commissionInBaseCoin.String())), transaction.EncodeError(map[string]string{ @@ -62,14 +62,14 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe } value := valueToBuy - if coinToSell != types.GetBaseCoin() { + if !coinToSell.IsBaseCoin() { value = formula.CalculatePurchaseAmount(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToBuy) if errResp := transaction.CheckReserveUnderflow(coinFrom, value); errResp != nil { return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } } - if coinToBuy != types.GetBaseCoin() { + if !coinToBuy.IsBaseCoin() { if errResp := transaction.CheckForCoinSupplyOverflow(coinTo.Volume(), value, coinTo.MaxSupply()); errResp != nil { return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index 0702c3865..98a16c27d 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -22,25 +22,29 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell cState.RLock() defer cState.RUnlock() - coinToSell := types.StrToCoinSymbol(req.CoinToSell) - coinToBuy := types.StrToCoinSymbol(req.CoinToBuy) + coinToSell := types.CoinID(req.CoinIdToSell) + coinToBuy := types.CoinID(req.CoinIdToBuy) if coinToSell == coinToBuy { return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), transaction.EncodeError(map[string]string{ - "coin_to_sell": coinToSell.String(), - "coin_to_buy": coinToBuy.String(), + "coin_id_to_sell": coinToSell.String(), + "coin_to_sell": cState.Coins().GetCoin(coinToSell).Symbol().String(), + "coin_id_to_buy": coinToBuy.String(), + "coin_to_buy": cState.Coins().GetCoin(coinToBuy).Symbol().String(), })) } if !cState.Coins().Exists(coinToSell) { return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ - "coin_to_sell": coinToSell.String(), + "coin_id_to_sell": coinToSell.String(), + "coin_to_sell": cState.Coins().GetCoin(coinToSell).Symbol().String(), })) } if !cState.Coins().Exists(coinToBuy) { return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ - "coin_to_buy": coinToSell.String(), + "coin_id_to_buy": coinToBuy.String(), + "coin_to_buy": cState.Coins().GetCoin(coinToBuy).Symbol().String(), })) } @@ -56,7 +60,7 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell coinFrom := cState.Coins().GetCoin(coinToSell) coinTo := cState.Coins().GetCoin(coinToBuy) - if coinToSell != types.GetBaseCoin() { + if !coinToSell.IsBaseCoin() { if coinFrom.Volume().Cmp(valueToSell) < 0 { return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin volume balance is not sufficient for transaction. Has: %s, required %s", @@ -78,14 +82,14 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell } value := valueToSell - if coinToSell != types.GetBaseCoin() { + if !coinToSell.IsBaseCoin() { value = formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) if errResp := transaction.CheckReserveUnderflow(coinFrom, value); errResp != nil { return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } } - if coinToBuy != types.GetBaseCoin() { + if !coinToBuy.IsBaseCoin() { if errResp := transaction.CheckForCoinSupplyOverflow(coinTo.Volume(), value, coinTo.MaxSupply()); errResp != nil { return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index b7a0a44d9..553ecfdf2 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -26,8 +26,8 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS gasPrice = 1 } - coinToSell := types.StrToCoinSymbol(req.CoinToSell) - coinToBuy := types.StrToCoinSymbol(req.CoinToBuy) + coinToSell := types.CoinID(req.CoinIdToSell) + coinToBuy := types.CoinID(req.CoinIdToBuy) valueToSell, ok := big.NewInt(0).SetString(req.ValueToSell, 10) //todo: mb delete? if !ok { return new(pb.EstimateCoinSellAllResponse), status.Error(codes.InvalidArgument, "Value to sell not specified") @@ -59,14 +59,14 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS coinTo := cState.Coins().GetCoin(coinToBuy) value := valueToSell - if coinToSell != types.GetBaseCoin() { + if !coinToSell.IsBaseCoin() { value = formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) if errResp := transaction.CheckReserveUnderflow(coinFrom, value); errResp != nil { return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } } - if coinToBuy != types.GetBaseCoin() { + if !coinToBuy.IsBaseCoin() { if errResp := transaction.CheckForCoinSupplyOverflow(coinTo.Volume(), value, coinTo.MaxSupply()); errResp != nil { return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } diff --git a/api/v2/service/estimate_tx_commission.go b/api/v2/service/estimate_tx_commission.go index d50585761..bd1d3ed91 100644 --- a/api/v2/service/estimate_tx_commission.go +++ b/api/v2/service/estimate_tx_commission.go @@ -106,13 +106,13 @@ func commissionCoinForData(data *pb.EstimateTxCommissionRequest_TransactionData, totalCommissionInBaseCoin := new(big.Int).Mul(big.NewInt(0).Add(commissionInBaseCoin, big.NewInt(int64(lenPayload))), transaction.CommissionMultiplier) - if data.GasCoin == "BIP" { + if types.CoinID(data.GasCoinId).IsBaseCoin() { return &pb.EstimateTxCommissionResponse{ Commission: totalCommissionInBaseCoin.String(), }, nil } - coin := cState.Coins().GetCoin(types.StrToCoinSymbol(data.GasCoin)) + coin := cState.Coins().GetCoin(types.CoinID(data.GasCoinId)) if coin == nil { return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "Gas Coin not found") diff --git a/api/v2/service/service.go b/api/v2/service/service.go index 860f0ad07..630694d1d 100644 --- a/api/v2/service/service.go +++ b/api/v2/service/service.go @@ -5,7 +5,6 @@ import ( "github.com/MinterTeam/minter-go-node/config" "github.com/MinterTeam/minter-go-node/core/minter" _struct "github.com/golang/protobuf/ptypes/struct" - "github.com/prometheus/client_golang/prometheus" "github.com/tendermint/go-amino" tmNode "github.com/tendermint/tendermint/node" rpc "github.com/tendermint/tendermint/rpc/client/local" @@ -24,12 +23,8 @@ type Service struct { } func NewService(cdc *amino.Codec, blockchain *minter.Blockchain, client *rpc.Local, node *tmNode.Node, minterCfg *config.Config, version string) *Service { - prometheusTimeoutErrorsTotal := prometheus.NewCounterVec(prometheus.CounterOpts{ - Name: "timeout_errors_total", - Help: "A counter of the occurred timeout errors separated by requests.", - }, []string{"path"}) - prometheus.MustRegister(prometheusTimeoutErrorsTotal) - return &Service{cdc: cdc, + return &Service{ + cdc: cdc, blockchain: blockchain, client: client, minterCfg: minterCfg, diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index a06c59c76..d1202dc57 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -3,13 +3,17 @@ package cmd import ( "fmt" api_v1 "github.com/MinterTeam/minter-go-node/api" + api_v2 "github.com/MinterTeam/minter-go-node/api/v2" + service_api "github.com/MinterTeam/minter-go-node/api/v2/service" "github.com/MinterTeam/minter-go-node/cli/service" "github.com/MinterTeam/minter-go-node/cmd/utils" "github.com/MinterTeam/minter-go-node/config" "github.com/MinterTeam/minter-go-node/core/minter" "github.com/MinterTeam/minter-go-node/core/statistics" "github.com/MinterTeam/minter-go-node/log" + "github.com/MinterTeam/minter-go-node/version" "github.com/spf13/cobra" + "github.com/tendermint/go-amino" "github.com/tendermint/tendermint/abci/types" tmCfg "github.com/tendermint/tendermint/config" tmlog "github.com/tendermint/tendermint/libs/log" @@ -24,6 +28,7 @@ import ( "io" "net/http" _ "net/http/pprof" + "net/url" "os" "syscall" ) @@ -107,19 +112,19 @@ func runNode(cmd *cobra.Command) error { app.SetTmNode(node) if !cfg.ValidatorMode { - //go func(srv *service_api.Service) { - // grpcUrl, err := url.Parse(cfg.GRPCListenAddress) - // if err != nil { - // logger.Error("Failed to parse gRPC address", err) - // } - // apiV2url, err := url.Parse(cfg.APIv2ListenAddress) - // if err != nil { - // logger.Error("Failed to parse API v2 address", err) - // } - // traceLog := os.Getenv("API_V2_LOG_LEVEL") == "trace" - // logger.Error("Failed to start Api V2 in both gRPC and RESTful", - // api_v2.Run(srv, grpcUrl.Host, apiV2url.Host, traceLog)) - //}(service_api.NewService(amino.NewCodec(), app, client, node, cfg, version.Version)) + go func(srv *service_api.Service) { + grpcUrl, err := url.Parse(cfg.GRPCListenAddress) + if err != nil { + logger.Error("Failed to parse gRPC address", err) + } + apiV2url, err := url.Parse(cfg.APIv2ListenAddress) + if err != nil { + logger.Error("Failed to parse API v2 address", err) + } + traceLog := os.Getenv("API_V2_LOG_LEVEL") == "trace" + logger.Error("Failed to start Api V2 in both gRPC and RESTful", + api_v2.Run(srv, grpcUrl.Host, apiV2url.Host, traceLog)) + }(service_api.NewService(amino.NewCodec(), app, client, node, cfg, version.Version)) go api_v1.RunAPI(app, client, cfg, logger) } diff --git a/go.mod b/go.mod index 4019d0412..db692f259 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200708082254-89679228c4b1 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200716145033-405dcd98baf8 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 158564f05..d55100b39 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200708082254-89679228c4b1 h1:KzB/n+6r9Ue8IPBNnkpa2lvtF/F0xbb7zJDB4fBRzrE= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200708082254-89679228c4b1/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200716145033-405dcd98baf8 h1:9zS6KyUaVomAxyJDq5kjaN3qbLlw8rMLfzPW3v3hkQk= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200716145033-405dcd98baf8/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 9e70255470f4fa5e9a5e2080cd90b4f3824bf9b2 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 17 Jul 2020 13:44:11 +0300 Subject: [PATCH 082/426] export --- core/state/state.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/state/state.go b/core/state/state.go index f153e2bfd..4f9d79062 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -15,7 +15,6 @@ import ( "github.com/MinterTeam/minter-go-node/core/state/halts" legacyAccounts "github.com/MinterTeam/minter-go-node/core/state/legacy/accounts" legacyApp "github.com/MinterTeam/minter-go-node/core/state/legacy/app" - legacyCandidates "github.com/MinterTeam/minter-go-node/core/state/legacy/candidates" legacyCoins "github.com/MinterTeam/minter-go-node/core/state/legacy/coins" legacyFrozenfunds "github.com/MinterTeam/minter-go-node/core/state/legacy/frozenfunds" "github.com/MinterTeam/minter-go-node/core/state/validators" @@ -89,7 +88,7 @@ func (cs *CheckState) Tree() tree.ReadOnlyTree { func (cs *CheckState) Export11To12(height uint64) types.AppState { iavlTree := cs.state.tree - candidatesState, err := legacyCandidates.NewCandidates(nil, iavlTree) + candidatesState, err := candidates.NewCandidates(nil, iavlTree) if err != nil { log.Panicf("Create new state at height %d failed: %s", height, err) } @@ -128,7 +127,7 @@ func (cs *CheckState) Export11To12(height uint64) types.AppState { appState.Export(state, height) coinsState.Export(state) validatorsState.Export(state) - candidatesState.Export(state) + candidatesState.Export11To12(state) frozenFundsState.Export(state, height) accountsState.Export(state) checksState.Export(state) From 5bf77984bc95fb4b911d010c714e37278c14acb3 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Mon, 20 Jul 2020 09:56:03 +0300 Subject: [PATCH 083/426] MN-435: return coin id as string in tags --- core/transaction/recreate_coin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 5c92900fe..54de099ea 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -197,7 +197,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar tags = append(tags, kv.Pair{ Key: []byte("tx.coin"), - Value: coinID.Bytes(), + Value: []byte(coinID.String()), }) } From fddd43417fcaa2d6c5dd8ba3225bf2d66cc46986 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Mon, 20 Jul 2020 11:10:33 +0300 Subject: [PATCH 084/426] MN-435: fix recreate coin --- api/transaction.go | 3 +++ core/state/coins/coins.go | 4 +++- core/transaction/recreate_coin.go | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/api/transaction.go b/api/transaction.go index 2ffbff114..1541ea41e 100644 --- a/api/transaction.go +++ b/api/transaction.go @@ -19,6 +19,9 @@ func Transaction(hash []byte) (json.RawMessage, error) { return nil, err } + cState.RLock() + defer cState.RUnlock() + txJsonEncoder := encoder.NewTxEncoderJSON(cState) return txJsonEncoder.Encode(decodedTx, tx) diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index b3a1f8197..4cf7e10e1 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -235,13 +235,15 @@ func (c *Coins) Recreate(newID types.CoinID, symbol types.CoinSymbol, // TODO: change array to sorted array by version and get the last one lastVersion := uint16(0) for _, id := range symbolCoins { - coin := c.GetCoin(id) + coin := c.get(id) if coin.Version() > lastVersion { lastVersion = coin.Version() } } recreateCoin.CVersion = lastVersion + 1 + recreateCoin.isDirty = true + c.setToMap(recreateCoin.id, recreateCoin) c.markDirty(recreateCoin.id) diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 54de099ea..57e64d49e 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -197,7 +197,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar tags = append(tags, kv.Pair{ Key: []byte("tx.coin"), - Value: []byte(coinID.String()), + Value: []byte(data.Symbol.String()), }) } From b78ce66463f4e66e23e512024505f77ca632feac Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Mon, 20 Jul 2020 11:36:22 +0300 Subject: [PATCH 085/426] MN-435: fix export state --- core/state/legacy/accounts/accounts.go | 4 ++-- core/state/legacy/candidates/candidates.go | 11 +++-------- core/state/legacy/coins/coins.go | 7 ++++++- core/state/legacy/frozenfunds/frozen_funds.go | 9 ++------- core/state/state.go | 6 +++--- 5 files changed, 16 insertions(+), 21 deletions(-) diff --git a/core/state/legacy/accounts/accounts.go b/core/state/legacy/accounts/accounts.go index 3252551fa..948170202 100644 --- a/core/state/legacy/accounts/accounts.go +++ b/core/state/legacy/accounts/accounts.go @@ -134,7 +134,7 @@ func (a *Accounts) markDirty(addr types.Address) { a.dirty[addr] = struct{}{} } -func (a *Accounts) Export(state *types.AppState) { +func (a *Accounts) Export(state *types.AppState, coinsMap map[types.CoinSymbol]types.CoinID) { // todo: iterate range? a.iavl.Iterate(func(key []byte, value []byte) bool { if key[0] == mainPrefix { @@ -159,7 +159,7 @@ func (a *Accounts) Export(state *types.AppState) { state.Coins[key].OwnerAddress = &account.address } } - } + } balance = append(balance, types.Balance{ Coin: id, diff --git a/core/state/legacy/candidates/candidates.go b/core/state/legacy/candidates/candidates.go index 0748874b3..b096ce8b9 100644 --- a/core/state/legacy/candidates/candidates.go +++ b/core/state/legacy/candidates/candidates.go @@ -231,15 +231,10 @@ func (c *Candidates) LoadStakes() { } } -func (c *Candidates) Export(state *types.AppState) { +func (c *Candidates) Export(state *types.AppState, coinsMap map[types.CoinSymbol]types.CoinID) { c.LoadCandidates() c.LoadStakes() - coinsSymbolToID := make(map[types.CoinSymbol]types.CoinID, len(state.Coins)) - for _, c := range state.Coins { - coinsSymbolToID[c.Symbol] = c.ID - } - candidates := c.GetCandidates() for _, candidate := range candidates { candidateStakes := c.GetStakes(candidate.PubKey) @@ -247,7 +242,7 @@ func (c *Candidates) Export(state *types.AppState) { for i, s := range candidateStakes { stakes[i] = types.Stake{ Owner: s.Owner, - Coin: coinsSymbolToID[s.Coin], + Coin: coinsMap[s.Coin], Value: s.Value.String(), BipValue: s.BipValue.String(), } @@ -257,7 +252,7 @@ func (c *Candidates) Export(state *types.AppState) { for i, u := range candidate.updates { updates[i] = types.Stake{ Owner: u.Owner, - Coin: coinsSymbolToID[u.Coin], + Coin: coinsMap[u.Coin], Value: u.Value.String(), BipValue: u.BipValue.String(), } diff --git a/core/state/legacy/coins/coins.go b/core/state/legacy/coins/coins.go index 8928fccef..6bcf68941 100644 --- a/core/state/legacy/coins/coins.go +++ b/core/state/legacy/coins/coins.go @@ -101,7 +101,7 @@ func (c *Coins) getOrderedDirtyCoins() []types.CoinSymbol { return keys } -func (c *Coins) Export(state *types.AppState) { +func (c *Coins) Export(state *types.AppState) map[types.CoinSymbol]types.CoinID { var coins []types.Coin c.iavl.Iterate(func(key []byte, value []byte) bool { @@ -133,12 +133,17 @@ func (c *Coins) Export(state *types.AppState) { return helpers.StringToBigInt(coins[i].Reserve).Cmp(helpers.StringToBigInt(coins[j].Reserve)) == 1 }) + coinsMap := make(map[types.CoinSymbol]types.CoinID, len(coins)) + for i, _ := range coins { coins[i].ID = types.CoinID(i + 1) + coinsMap[coins[i].Symbol] = coins[i].ID } state.Coins = coins state.CoinsCount = uint32(len(state.Coins)) + + return coinsMap } func (c *Coins) getFromMap(symbol types.CoinSymbol) *Model { diff --git a/core/state/legacy/frozenfunds/frozen_funds.go b/core/state/legacy/frozenfunds/frozen_funds.go index 77d72f72f..ce90e0ce0 100644 --- a/core/state/legacy/frozenfunds/frozen_funds.go +++ b/core/state/legacy/frozenfunds/frozen_funds.go @@ -73,12 +73,7 @@ func (f *FrozenFunds) getOrderedDirty() []uint64 { return keys } -func (f *FrozenFunds) Export(state *types.AppState, height uint64) { - coinsSymbolToID := make(map[types.CoinSymbol]types.CoinID, len(state.Coins)) - for _, c := range state.Coins { - coinsSymbolToID[c.Symbol] = c.ID - } - +func (f *FrozenFunds) Export(state *types.AppState, height uint64, coinsMap map[types.CoinSymbol]types.CoinID) { for i := height; i <= height+candidates.UnbondPeriod; i++ { frozenFunds := f.get(i) if frozenFunds == nil { @@ -90,7 +85,7 @@ func (f *FrozenFunds) Export(state *types.AppState, height uint64) { Height: i, Address: frozenFund.Address, CandidateKey: frozenFund.CandidateKey, - Coin: coinsSymbolToID[frozenFund.Coin], + Coin: coinsMap[frozenFund.Coin], Value: frozenFund.Value.String(), }) } diff --git a/core/state/state.go b/core/state/state.go index 846614525..948659ec4 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -337,10 +337,10 @@ func (s *State) Export11To12(height uint64) types.AppState { state := new(types.AppState) appState.Export(state, height) - coinsState.Export(state) + coinsMap := coinsState.Export(state) validatorsState.Export(state) - candidatesState.Export(state) - frozenFundsState.Export(state, height) + candidatesState.Export(state, coinsMap) + frozenFundsState.Export(state, height, coinsMap) accountsState.Export(state) checksState.Export(state) From a2dc97bf74cb6148e57e30e02a3b6ba2f81b0638 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 21 Jul 2020 17:45:34 +0300 Subject: [PATCH 086/426] add coin --- api/v2/service/address.go | 4 ++++ api/v2/service/addresses.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/api/v2/service/address.go b/api/v2/service/address.go index a2e2205ba..fdd7dea61 100644 --- a/api/v2/service/address.go +++ b/api/v2/service/address.go @@ -55,6 +55,10 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr for _, coin := range balances { totalStakesGroupByCoin[coin.Coin.ID] = coin.Value res.Balance = append(res.Balance, &pb.AddressBalance{ + Coin: &pb.Coin{ + Id: coin.Coin.ID.String(), + Symbol: cState.Coins().GetCoin(coin.Coin.ID).Symbol().String(), + }, Value: coin.Value.String(), BipValue: customCoinBipBalance(coin.Coin.ID, coin.Value, cState).String(), }) diff --git a/api/v2/service/addresses.go b/api/v2/service/addresses.go index 91b511bb2..ed4814ac9 100644 --- a/api/v2/service/addresses.go +++ b/api/v2/service/addresses.go @@ -56,6 +56,10 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. for _, coin := range balances { totalStakesGroupByCoin[coin.Coin.ID] = coin.Value res.Balance = append(res.Balance, &pb.AddressBalance{ + Coin: &pb.Coin{ + Id: coin.Coin.ID.String(), + Symbol: cState.Coins().GetCoin(coin.Coin.ID).Symbol().String(), + }, Value: coin.Value.String(), BipValue: customCoinBipBalance(coin.Coin.ID, coin.Value, cState).String(), }) From bfe7eb79718efe47593fb0f9d9b366f33d7686ee Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 22 Jul 2020 01:36:55 +0300 Subject: [PATCH 087/426] add coin_id method --- api/v2/service/coin_id.go | 46 +++++++++++++++++++++++++++++++++++++ api/v2/service/coin_info.go | 13 +++++++++++ go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 api/v2/service/coin_id.go diff --git a/api/v2/service/coin_id.go b/api/v2/service/coin_id.go new file mode 100644 index 000000000..5afa43cff --- /dev/null +++ b/api/v2/service/coin_id.go @@ -0,0 +1,46 @@ +package service + +import ( + "context" + "fmt" + "github.com/MinterTeam/minter-go-node/core/types" + pb "github.com/MinterTeam/node-grpc-gateway/api_pb" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (s *Service) CoinId(ctx context.Context, req *pb.CoinIdRequest) (*pb.CoinInfoResponse, error) { + cState, err := s.blockchain.GetStateForHeight(req.Height) + if err != nil { + return new(pb.CoinInfoResponse), status.Error(codes.NotFound, err.Error()) + } + + cState.RLock() + defer cState.RUnlock() + + coin := cState.Coins().GetCoin(types.CoinID(req.Id)) + if coin == nil { + return new(pb.CoinInfoResponse), status.Error(codes.FailedPrecondition, "Coin not found") + } + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.CoinInfoResponse), timeoutStatus.Err() + } + + var ownerAddress string + info := cState.Coins().GetSymbolInfo(coin.Symbol()) + if info != nil && info.OwnerAddress() != nil { + ownerAddress = info.OwnerAddress().String() + } + + return &pb.CoinInfoResponse{ + Id: coin.ID().String(), + Name: coin.Name(), + Symbol: coin.Symbol().String(), + Volume: coin.Volume().String(), + Crr: fmt.Sprintf("%d", coin.Crr()), + ReserveBalance: coin.Reserve().String(), + MaxSupply: coin.MaxSupply().String(), + OwnerAddress: ownerAddress, + }, nil +} diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index 3fd9b6609..92ce159dc 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -23,11 +23,24 @@ func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.Co return new(pb.CoinInfoResponse), status.Error(codes.FailedPrecondition, "Coin not found") } + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.CoinInfoResponse), timeoutStatus.Err() + } + + var ownerAddress string + info := cState.Coins().GetSymbolInfo(coin.Symbol()) + if info != nil && info.OwnerAddress() != nil { + ownerAddress = info.OwnerAddress().String() + } + return &pb.CoinInfoResponse{ + Id: coin.ID().String(), Name: coin.Name(), Symbol: coin.Symbol().String(), Volume: coin.Volume().String(), Crr: fmt.Sprintf("%d", coin.Crr()), ReserveBalance: coin.Reserve().String(), + MaxSupply: coin.MaxSupply().String(), + OwnerAddress: ownerAddress, }, nil } diff --git a/go.mod b/go.mod index db692f259..7e8ff3e21 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200716145033-405dcd98baf8 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200721223527-f6c600c7be2f github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index d55100b39..7f0772151 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200716145033-405dcd98baf8 h1:9zS6KyUaVomAxyJDq5kjaN3qbLlw8rMLfzPW3v3hkQk= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200716145033-405dcd98baf8/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200721223527-f6c600c7be2f h1:qxWi/xCtkhsRSzjXlVHVOUF30VkYhfg4KFgEAe4mMeM= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200721223527-f6c600c7be2f/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 9143e183d98b9019e145e78ca120ff024a95c96b Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 22 Jul 2020 13:04:46 +0300 Subject: [PATCH 088/426] fixes and optimisations --- core/code/code.go | 1 + core/state/candidates/candidates.go | 124 ++++++++++++-------- core/state/state.go | 2 +- core/transaction/buy_coin.go | 2 + core/transaction/change_owner.go | 6 +- core/transaction/create_coin.go | 2 + core/transaction/create_multisig.go | 2 + core/transaction/declare_candidacy.go | 2 + core/transaction/delegate.go | 2 + core/transaction/edit_candidate.go | 13 ++ core/transaction/multisend.go | 2 + core/transaction/recreate_coin.go | 2 + core/transaction/redeem_check.go | 2 + core/transaction/sell_all_coin.go | 2 + core/transaction/sell_coin.go | 2 + core/transaction/send.go | 2 + core/transaction/set_halt_block.go | 2 + core/transaction/switch_candidate_status.go | 4 + core/transaction/unbond.go | 2 + 19 files changed, 123 insertions(+), 53 deletions(-) diff --git a/core/code/code.go b/core/code/code.go index aa333ae56..66e57c0ae 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -45,6 +45,7 @@ const ( StakeShouldBePositive uint32 = 408 TooLowStake uint32 = 409 PublicKeyInBlockList uint32 = 410 + NewPublicKeyIsBad uint32 = 411 // check CheckInvalidLock uint32 = 501 diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 833f281c1..83e11c36f 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -64,6 +64,8 @@ type Candidates struct { lock sync.RWMutex loaded bool + + isDirty bool } func NewCandidates(bus *bus.Bus, iavl tree.MTree) (*Candidates, error) { @@ -98,37 +100,40 @@ func (c *Candidates) Commit() error { c.iavl.Set(path, data) } - var pubIDs []pubkeyID - for pk, v := range c.pubKeyIDs { - pubIDs = append(pubIDs, pubkeyID{ - PubKey: pk, - ID: v, + if c.isDirty { + + var pubIDs []pubkeyID + for pk, v := range c.pubKeyIDs { + pubIDs = append(pubIDs, pubkeyID{ + PubKey: pk, + ID: v, + }) + } + sort.SliceStable(pubIDs, func(i, j int) bool { + return pubIDs[i].ID < pubIDs[j].ID }) - } - sort.SliceStable(pubIDs, func(i, j int) bool { - return pubIDs[i].ID < pubIDs[j].ID - }) - pubIDenc, err := rlp.EncodeToBytes(pubIDs) - if err != nil { - panic(fmt.Sprintf("failed to encode candidates public key with ID: %s", err)) - } + pubIDenc, err := rlp.EncodeToBytes(pubIDs) + if err != nil { + panic(fmt.Sprintf("failed to encode candidates public key with ID: %s", err)) + } - c.iavl.Set([]byte{pubKeyIDPrefix}, pubIDenc) + c.iavl.Set([]byte{pubKeyIDPrefix}, pubIDenc) - var blockList []types.Pubkey - for pubKey := range c.blockList { - blockList = append(blockList, pubKey) - } - sort.SliceStable(blockList, func(i, j int) bool { - return bytes.Compare(blockList[i].Bytes(), blockList[j].Bytes()) == 1 - }) - blockListData, err := rlp.EncodeToBytes(blockList) - if err != nil { - return fmt.Errorf("can't encode block list of candidates: %v", err) - } - c.iavl.Set([]byte{blockListPrefix}, blockListData) + var blockList []types.Pubkey + for pubKey := range c.blockList { + blockList = append(blockList, pubKey) + } + sort.SliceStable(blockList, func(i, j int) bool { + return bytes.Compare(blockList[i].Bytes(), blockList[j].Bytes()) == 1 + }) + blockListData, err := rlp.EncodeToBytes(blockList) + if err != nil { + return fmt.Errorf("can't encode block list of candidates: %v", err) + } + c.iavl.Set([]byte{blockListPrefix}, blockListData) - c.iavl.Set([]byte{maxIDPrefix}, c.maxIDBytes()) + c.iavl.Set([]byte{maxIDPrefix}, c.maxIDBytes()) + } for _, pubkey := range keys { candidate := c.getFromMap(pubkey) @@ -772,11 +777,45 @@ func (c *Candidates) GetCandidateControl(pubkey types.Pubkey) types.Address { return c.getFromMap(pubkey).ControlAddress } +// Load only list candidates (for read) func (c *Candidates) LoadCandidates() { if c.checkAndSetLoaded() { return } + c.loadCandidatesList() +} + +// Load full info about candidates (for edit) +func (c *Candidates) LoadCandidatesDeliver() { + if c.checkAndSetLoaded() { + return + } + + c.loadCandidatesList() + + _, blockListEnc := c.iavl.Get([]byte{blockListPrefix}) + if len(blockListEnc) != 0 { + var blockList []types.Pubkey + if err := rlp.DecodeBytes(blockListEnc, &blockList); err != nil { + panic(fmt.Sprintf("failed to decode candidates block list: %s", err)) + } + + blockListMap := map[types.Pubkey]struct{}{} + for _, pubkey := range blockList { + blockListMap[pubkey] = struct{}{} + } + c.setBlockList(blockListMap) + } + + _, valueMaxID := c.iavl.Get([]byte{maxIDPrefix}) + if len(valueMaxID) != 0 { + c.maxID = uint(binary.LittleEndian.Uint32(valueMaxID)) + } + +} + +func (c *Candidates) loadCandidatesList() { _, pubIDenc := c.iavl.Get([]byte{pubKeyIDPrefix}) if len(pubIDenc) != 0 { var pubIDs []pubkeyID @@ -814,25 +853,6 @@ func (c *Candidates) LoadCandidates() { c.setToMap(candidate.PubKey, candidate) } } - - _, blockListEnc := c.iavl.Get([]byte{blockListPrefix}) - if len(blockListEnc) != 0 { - var blockList []types.Pubkey - if err := rlp.DecodeBytes(blockListEnc, &blockList); err != nil { - panic(fmt.Sprintf("failed to decode candidates block list: %s", err)) - } - - blockListMap := map[types.Pubkey]struct{}{} - for _, pubkey := range blockList { - blockListMap[pubkey] = struct{}{} - } - c.setBlockList(blockListMap) - } - - _, valueMaxID := c.iavl.Get([]byte{maxIDPrefix}) - if len(valueMaxID) != 0 { - c.maxID = uint(binary.LittleEndian.Uint32(valueMaxID)) - } } func (c *Candidates) checkAndSetLoaded() bool { @@ -981,7 +1001,7 @@ func (c *Candidates) SetStakes(pubkey types.Pubkey, stakes []types.Stake, update } func (c *Candidates) Export(state *types.AppState) { - c.LoadCandidates() + c.LoadCandidatesDeliver() c.LoadStakes() candidates := c.GetCandidates() @@ -1155,13 +1175,18 @@ func (c *Candidates) LoadStakesOfCandidate(pubkey types.Pubkey) { } func (c *Candidates) ChangePubKey(old types.Pubkey, new types.Pubkey) { - c.getFromMap(old).PubKey = new + if old == new { + return + } + c.lock.Lock() defer c.lock.Unlock() if c.isBlock(new) { panic("Candidate with such public key (" + new.String() + ") exists in block list") } + + c.getFromMap(old).PubKey = new c.setBlockPybKey(old) c.setPubKeyID(new, c.pubKeyIDs[old]) delete(c.pubKeyIDs, old) @@ -1178,6 +1203,7 @@ func (c *Candidates) getOrNewID(pubKey types.Pubkey) uint { c.lock.Lock() defer c.lock.Unlock() + c.isDirty = true c.maxID++ id = c.maxID c.setPubKeyID(pubKey, id) @@ -1200,6 +1226,7 @@ func (c *Candidates) setPubKeyID(pubkey types.Pubkey, u uint) { c.pubKeyIDs = map[types.Pubkey]uint{} } c.pubKeyIDs[pubkey] = u + c.isDirty = true } func (c *Candidates) setBlockPybKey(p types.Pubkey) { @@ -1207,6 +1234,7 @@ func (c *Candidates) setBlockPybKey(p types.Pubkey) { c.blockList = map[types.Pubkey]struct{}{} } c.blockList[p] = struct{}{} + c.isDirty = true } func (c *Candidates) AddToBlockPybKey(p types.Pubkey) { diff --git a/core/state/state.go b/core/state/state.go index 25640df0c..dbbde31ec 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -166,7 +166,7 @@ func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, return nil, err } - state.Candidates.LoadCandidates() + state.Candidates.LoadCandidatesDeliver() state.Candidates.LoadStakes() state.Validators.LoadValidators() diff --git a/core/transaction/buy_coin.go b/core/transaction/buy_coin.go index fc144dad1..ae02e5665 100644 --- a/core/transaction/buy_coin.go +++ b/core/transaction/buy_coin.go @@ -400,6 +400,8 @@ func (data BuyCoinData) Run(tx *Transaction, context state.Interface, rewardPool } if deliverState, ok := context.(*state.State); ok { + deliverState.Lock() + defer deliverState.Unlock() for _, ts := range totalSpends { deliverState.Accounts.SubBalance(sender, ts.Coin, ts.Value) } diff --git a/core/transaction/change_owner.go b/core/transaction/change_owner.go index 119899fec..c2a0c9870 100644 --- a/core/transaction/change_owner.go +++ b/core/transaction/change_owner.go @@ -17,10 +17,6 @@ type ChangeOwnerData struct { NewOwner types.Address } -func (data ChangeOwnerData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { - panic("implement me") -} - func (data ChangeOwnerData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { sender, _ := tx.Sender() @@ -103,6 +99,8 @@ func (data ChangeOwnerData) Run(tx *Transaction, context state.Interface, reward } if deliverState, ok := context.(*state.State); ok { + deliverState.Lock() + defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) deliverState.Coins.SubVolume(tx.GasCoin, commission) diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index 75ba39e7e..a0c4d83c9 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -209,6 +209,8 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP } if deliverState, ok := context.(*state.State); ok { + deliverState.Lock() + defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index 702cd1533..5b6f35267 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -161,6 +161,8 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew } if deliverState, ok := context.(*state.State); ok { + deliverState.Lock() + defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubVolume(tx.GasCoin, commission) diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index 1d12deca6..7c029806b 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -193,6 +193,8 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r } if deliverState, ok := context.(*state.State); ok { + deliverState.Lock() + defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index b7cff56e3..e83cef4fc 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -167,6 +167,8 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo } if deliverState, ok := context.(*state.State); ok { + deliverState.Lock() + defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index fb3ba341c..ad6de4791 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -77,6 +77,17 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa return *response } + if data.NewPubKey != nil && data.PubKey == *data.NewPubKey { + return Response{ + Code: code.NewPublicKeyIsBad, + Log: fmt.Sprintf("Current public key (%s) equals new public key (%s)", data.PubKey.String(), data.NewPubKey.String()), + Info: EncodeError(map[string]string{ + "public_key": data.PubKey.String(), + "new_public_key": data.NewPubKey.String(), + }), + } + } + commissionInBaseCoin := tx.CommissionInBaseCoin() commission := big.NewInt(0).Set(commissionInBaseCoin) @@ -126,6 +137,8 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa } if deliverState, ok := context.(*state.State); ok { + deliverState.Lock() + defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) diff --git a/core/transaction/multisend.go b/core/transaction/multisend.go index 60ea52dee..9403b9df0 100644 --- a/core/transaction/multisend.go +++ b/core/transaction/multisend.go @@ -116,6 +116,8 @@ func (data MultisendData) Run(tx *Transaction, context state.Interface, rewardPo } if deliverState, ok := context.(*state.State); ok { + deliverState.Lock() + defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubVolume(tx.GasCoin, commission) diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index caf228a73..a79309be1 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -173,6 +173,8 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar } if deliverState, ok := context.(*state.State); ok { + deliverState.Lock() + defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index 309045244..ff678f9a0 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -247,6 +247,8 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward } if deliverState, ok := context.(*state.State); ok { + deliverState.Lock() + defer deliverState.Unlock() deliverState.Checks.UseCheck(decodedCheck) rewardPool.Add(rewardPool, commissionInBaseCoin) diff --git a/core/transaction/sell_all_coin.go b/core/transaction/sell_all_coin.go index e84eebd21..03b23f047 100644 --- a/core/transaction/sell_all_coin.go +++ b/core/transaction/sell_all_coin.go @@ -236,6 +236,8 @@ func (data SellAllCoinData) Run(tx *Transaction, context state.Interface, reward } if deliverState, ok := context.(*state.State); ok { + deliverState.Lock() + defer deliverState.Unlock() for _, ts := range totalSpends { deliverState.Accounts.SubBalance(sender, ts.Coin, ts.Value) } diff --git a/core/transaction/sell_coin.go b/core/transaction/sell_coin.go index fb211ef89..46e41ee07 100644 --- a/core/transaction/sell_coin.go +++ b/core/transaction/sell_coin.go @@ -367,6 +367,8 @@ func (data SellCoinData) Run(tx *Transaction, context state.Interface, rewardPoo } if deliverState, ok := context.(*state.State); ok { + deliverState.Lock() + defer deliverState.Unlock() for _, ts := range totalSpends { deliverState.Accounts.SubBalance(sender, ts.Coin, ts.Value) } diff --git a/core/transaction/send.go b/core/transaction/send.go index 89bbaea34..9b0b6bdb2 100644 --- a/core/transaction/send.go +++ b/core/transaction/send.go @@ -148,6 +148,8 @@ func (data SendData) Run(tx *Transaction, context state.Interface, rewardPool *b } if deliverState, ok := context.(*state.State); ok { + deliverState.Lock() + defer deliverState.Unlock() for _, ts := range totalSpends { deliverState.Accounts.SubBalance(sender, ts.Coin, ts.Value) } diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index d9d884a3e..08ba5e5e5 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -124,6 +124,8 @@ func (data SetHaltBlockData) Run(tx *Transaction, context state.Interface, rewar } if deliverState, ok := context.(*state.State); ok { + deliverState.Lock() + defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index 762ccfdc3..7b07d575f 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -95,6 +95,8 @@ func (data SetCandidateOnData) Run(tx *Transaction, context state.Interface, rew } if deliverState, ok := context.(*state.State); ok { + deliverState.Lock() + defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) @@ -195,6 +197,8 @@ func (data SetCandidateOffData) Run(tx *Transaction, context state.Interface, re } if deliverState, ok := context.(*state.State); ok { + deliverState.Lock() + defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 44d104818..4fd510f83 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -148,6 +148,8 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool } if deliverState, ok := context.(*state.State); ok { + deliverState.Lock() + defer deliverState.Unlock() // now + 30 days unbondAtBlock := currentBlock + unbondPeriod From 85a06376b1e46074f14d55f649e1ce611b1bbf2c Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 22 Jul 2020 14:36:42 +0300 Subject: [PATCH 089/426] MN-435: use coin symbol for error response --- core/state/legacy/accounts/accounts.go | 2 +- core/transaction/buy_coin.go | 6 +++-- core/transaction/change_owner.go | 18 +++++++------ core/transaction/create_coin.go | 12 ++++++--- core/transaction/create_multisig.go | 20 +++++++------- core/transaction/declare_candidacy.go | 29 +++++++++++---------- core/transaction/delegate.go | 29 +++++++++++---------- core/transaction/edit_candidate.go | 20 +++++++------- core/transaction/multisend.go | 5 ++-- core/transaction/recreate_coin.go | 26 ++++++++++-------- core/transaction/redeem_check.go | 20 +++++++------- core/transaction/sell_all_coin.go | 6 +++-- core/transaction/sell_coin.go | 7 +++-- core/transaction/send.go | 6 +++-- core/transaction/set_halt_block.go | 20 +++++++------- core/transaction/switch_candidate_status.go | 20 +++++++------- core/transaction/transaction.go | 2 +- core/transaction/unbond.go | 20 +++++++------- core/types/appstate.go | 24 ++++++++--------- 19 files changed, 160 insertions(+), 132 deletions(-) diff --git a/core/state/legacy/accounts/accounts.go b/core/state/legacy/accounts/accounts.go index de24d5ea0..03aaf47ca 100644 --- a/core/state/legacy/accounts/accounts.go +++ b/core/state/legacy/accounts/accounts.go @@ -152,7 +152,7 @@ func (a *Accounts) Export(state *types.AppState, coinsMap map[types.CoinSymbol]t // set account address as owner address of coin if account contains whole volume if coin.Reserve == value.String() { - state.Coins[coin.ID - 1].OwnerAddress = &account.address + state.Coins[coin.ID-1].OwnerAddress = &account.address } balance = append(balance, types.Balance{ diff --git a/core/transaction/buy_coin.go b/core/transaction/buy_coin.go index fc144dad1..ebe8b465a 100644 --- a/core/transaction/buy_coin.go +++ b/core/transaction/buy_coin.go @@ -379,16 +379,18 @@ func (data BuyCoinData) Run(tx *Transaction, context state.Interface, rewardPool for _, ts := range totalSpends { if checkState.Accounts().GetBalance(sender, ts.Coin).Cmp(ts.Value) < 0 { + coin := checkState.Coins().GetCoin(ts.Coin) + return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s.", sender.String(), ts.Value.String(), - ts.Coin), + coin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": ts.Value.String(), - "coin": fmt.Sprintf("%s", ts.Coin), + "coin": coin.GetFullSymbol(), }), } } diff --git a/core/transaction/change_owner.go b/core/transaction/change_owner.go index 119899fec..1dcada96a 100644 --- a/core/transaction/change_owner.go +++ b/core/transaction/change_owner.go @@ -68,36 +68,38 @@ func (data ChangeOwnerData) Run(tx *Transaction, context state.Interface, reward commission := big.NewInt(0).Set(commissionInBaseCoin) if tx.GasCoin != types.GetBaseCoinID() { - coin := checkState.Coins().GetCoin(tx.GasCoin) + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) - errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) + errResp := CheckReserveUnderflow(gasCoin, commissionInBaseCoin) if errResp != nil { return *errResp } - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { + if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { return Response{ Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Gas coin reserve balance is not sufficient for transaction. Has: %s %s, required %s %s", coin.Reserve().String(), types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), + Log: fmt.Sprintf("Gas coin reserve balance is not sufficient for transaction. Has: %s %s, required %s %s", gasCoin.Reserve().String(), types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), Info: EncodeError(map[string]string{ - "has_value": coin.Reserve().String(), + "has_value": gasCoin.Reserve().String(), "required_value": commissionInBaseCoin.String(), "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) + return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), tx.GasCoin), + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + "gas_coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index 75ba39e7e..538455b3d 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -167,13 +167,15 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP } if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) + return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), tx.GasCoin), + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + "gas_coin": gasCoin.GetFullSymbol(), }), } } @@ -196,13 +198,15 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP totalTxCost.Add(totalTxCost, commission) if checkState.Accounts().GetBalance(sender, types.GetBaseCoinID()).Cmp(totalTxCost) < 0 { + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) + return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), tx.GasCoin), + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": totalTxCost.String(), - "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + "gas_coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index 702cd1533..29477accb 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -109,37 +109,37 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew commissionInBaseCoin := tx.CommissionInBaseCoin() commission := big.NewInt(0).Set(commissionInBaseCoin) - if !tx.GasCoin.IsBaseCoin() { - coin := checkState.Coins().GetCoin(tx.GasCoin) + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) - errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) + if !tx.GasCoin.IsBaseCoin() { + errResp := CheckReserveUnderflow(gasCoin, commissionInBaseCoin) if errResp != nil { return *errResp } - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { + if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { return Response{ Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String()), + Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "has_reserve": coin.Reserve().String(), + "has_reserve": gasCoin.Reserve().String(), "commission": commissionInBaseCoin.String(), - "gas_coin": coin.CName, + "gas_coin": gasCoin.GetFullSymbol(), }), } } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, tx.GasCoin), + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + "gas_coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index 1d12deca6..4b13ebf3f 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -127,37 +127,38 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r commissionInBaseCoin.Mul(commissionInBaseCoin, CommissionMultiplier) commission := big.NewInt(0).Set(commissionInBaseCoin) - if !tx.GasCoin.IsBaseCoin() { - coin := checkState.Coins().GetCoin(tx.GasCoin) + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) + coin := checkState.Coins().GetCoin(data.Coin) - errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) + if !tx.GasCoin.IsBaseCoin() { + errResp := CheckReserveUnderflow(gasCoin, commissionInBaseCoin) if errResp != nil { return *errResp } - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { + if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { return Response{ Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String()), + Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "has_reserve": coin.Reserve().String(), + "has_reserve": gasCoin.Reserve().String(), "commission": commissionInBaseCoin.String(), - "gas_coin": coin.CName, + "gas_coin": gasCoin.CName, }), } } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } if checkState.Accounts().GetBalance(sender, data.Coin).Cmp(data.Stake) < 0 { return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), data.Stake, data.Coin), + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), data.Stake, coin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": data.Stake.String(), - "coin": fmt.Sprintf("%s", data.Coin), + "coin": coin.GetFullSymbol(), }), } } @@ -165,11 +166,11 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, tx.GasCoin), + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + "gas_coin": gasCoin.GetFullSymbol(), }), } } @@ -182,11 +183,11 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(totalTxCost) < 0 { return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), tx.GasCoin), + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": totalTxCost.String(), - "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + "gas_coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index b7cff56e3..9542b9709 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -101,37 +101,38 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo commissionInBaseCoin := tx.CommissionInBaseCoin() commission := big.NewInt(0).Set(commissionInBaseCoin) - if !tx.GasCoin.IsBaseCoin() { - coin := checkState.Coins().GetCoin(tx.GasCoin) + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) + coin := checkState.Coins().GetCoin(data.Coin) - errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) + if !tx.GasCoin.IsBaseCoin() { + errResp := CheckReserveUnderflow(gasCoin, commissionInBaseCoin) if errResp != nil { return *errResp } - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { + if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { return Response{ Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String()), + Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "has_reserve": coin.Reserve().String(), + "has_reserve": gasCoin.Reserve().String(), "commission": commissionInBaseCoin.String(), - "gas_coin": coin.CName, + "gas_coin": gasCoin.GetFullSymbol(), }), } } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, tx.GasCoin), + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + "gas_coin": gasCoin.GetFullSymbol(), }), } } @@ -139,11 +140,11 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo if checkState.Accounts().GetBalance(sender, data.Coin).Cmp(data.Value) < 0 { return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), data.Value, data.Coin), + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), data.Value, coin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": data.Value.String(), - "coin": fmt.Sprintf("%s", data.Coin), + "coin": coin.GetFullSymbol(), }), } } @@ -156,11 +157,11 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(totalTxCost) < 0 { return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), tx.GasCoin), + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": totalTxCost.String(), - "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + "gas_coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index fb3ba341c..5062827be 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -80,37 +80,37 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa commissionInBaseCoin := tx.CommissionInBaseCoin() commission := big.NewInt(0).Set(commissionInBaseCoin) - if !tx.GasCoin.IsBaseCoin() { - coin := checkState.Coins().GetCoin(tx.GasCoin) + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) - errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) + if !tx.GasCoin.IsBaseCoin() { + errResp := CheckReserveUnderflow(gasCoin, commissionInBaseCoin) if errResp != nil { return *errResp } - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { + if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { return Response{ Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String()), + Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "has_reserve": coin.Reserve().String(), + "has_reserve": gasCoin.Reserve().String(), "commission": commissionInBaseCoin.String(), - "gas_coin": coin.CName, + "gas_coin": gasCoin.GetFullSymbol(), }), } } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), tx.GasCoin), + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + "gas_coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/multisend.go b/core/transaction/multisend.go index 60ea52dee..0d0f4ae5a 100644 --- a/core/transaction/multisend.go +++ b/core/transaction/multisend.go @@ -166,14 +166,15 @@ func checkBalances(context *state.CheckState, sender types.Address, items []Mult for _, coin := range coins { value := total[coin] + coinData := context.Coins().GetCoin(coin) if context.Accounts().GetBalance(sender, coin).Cmp(value) < 0 { return &Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), value, coin), + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), value, coinData.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": fmt.Sprintf("%d", value), - "coin": fmt.Sprintf("%d", coin), + "coin": coinData.GetFullSymbol(), }), } } diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index caf228a73..62da4b1de 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -103,36 +103,38 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar commission := big.NewInt(0).Set(commissionInBaseCoin) if tx.GasCoin != types.GetBaseCoinID() { - coin := checkState.Coins().GetCoin(tx.GasCoin) + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) - errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) + errResp := CheckReserveUnderflow(gasCoin, commissionInBaseCoin) if errResp != nil { return *errResp } - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { + if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { return Response{ Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Gas coin reserve balance is not sufficient for transaction. Has: %s %s, required %s %s", coin.Reserve().String(), types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), + Log: fmt.Sprintf("Gas coin reserve balance is not sufficient for transaction. Has: %s %s, required %s %s", gasCoin.Reserve().String(), types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), Info: EncodeError(map[string]string{ - "has_value": coin.Reserve().String(), + "has_value": gasCoin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "gas_coin": gasCoin.GetFullSymbol(), }), } } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) + return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), tx.GasCoin), + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + "gas_coin": gasCoin.GetFullSymbol(), }), } } @@ -150,6 +152,8 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar } if tx.GasCoin.IsBaseCoin() { + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) + totalTxCost := big.NewInt(0) totalTxCost.Add(totalTxCost, data.InitialReserve) totalTxCost.Add(totalTxCost, commission) @@ -157,11 +161,11 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar if checkState.Accounts().GetBalance(sender, types.GetBaseCoinID()).Cmp(totalTxCost) < 0 { return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), tx.GasCoin), + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": totalTxCost.String(), - "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + "gas_coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index 309045244..581424bca 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -198,13 +198,15 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward commissionInBaseCoin.Mul(commissionInBaseCoin, CommissionMultiplier) commission := big.NewInt(0).Set(commissionInBaseCoin) + gasCoin := checkState.Coins().GetCoin(decodedCheck.GasCoin) + coin := checkState.Coins().GetCoin(decodedCheck.Coin) + if !decodedCheck.GasCoin.IsBaseCoin() { - coin := checkState.Coins().GetCoin(decodedCheck.GasCoin) - errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) + errResp := CheckReserveUnderflow(gasCoin, commissionInBaseCoin) if errResp != nil { return *errResp } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } if decodedCheck.Coin == decodedCheck.GasCoin { @@ -212,10 +214,10 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward if checkState.Accounts().GetBalance(checkSender, decodedCheck.Coin).Cmp(totalTxCost) < 0 { return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", decodedCheck.Coin, checkSender.String(), totalTxCost.String(), decodedCheck.Coin), + Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", decodedCheck.Coin, checkSender.String(), totalTxCost.String(), coin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": checkSender.String(), - "coin": fmt.Sprintf("%s", decodedCheck.Coin), + "coin": coin.GetFullSymbol(), "total_tx_cost": totalTxCost.String(), }), } @@ -224,10 +226,10 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward if checkState.Accounts().GetBalance(checkSender, decodedCheck.Coin).Cmp(decodedCheck.Value) < 0 { return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", checkSender.String(), decodedCheck.Coin, decodedCheck.Value.String(), decodedCheck.Coin), + Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", checkSender.String(), decodedCheck.Coin, decodedCheck.Value.String(), coin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": checkSender.String(), - "coin": fmt.Sprintf("%s", decodedCheck.Coin), + "coin": coin.GetFullSymbol(), "value": decodedCheck.Value.String(), }), } @@ -236,10 +238,10 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward if checkState.Accounts().GetBalance(checkSender, decodedCheck.GasCoin).Cmp(commission) < 0 { return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", checkSender.String(), decodedCheck.GasCoin, commission.String(), decodedCheck.GasCoin), + Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", checkSender.String(), decodedCheck.GasCoin, commission.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), - "gas_coin": fmt.Sprintf("%s", decodedCheck.GasCoin), + "gas_coin": gasCoin.GetFullSymbol(), "commission": commission.String(), }), } diff --git a/core/transaction/sell_all_coin.go b/core/transaction/sell_all_coin.go index e84eebd21..674af3138 100644 --- a/core/transaction/sell_all_coin.go +++ b/core/transaction/sell_all_coin.go @@ -215,16 +215,18 @@ func (data SellAllCoinData) Run(tx *Transaction, context state.Interface, reward for _, ts := range totalSpends { if checkState.Accounts().GetBalance(sender, ts.Coin).Cmp(ts.Value) < 0 { + coin := checkState.Coins().GetCoin(ts.Coin) + return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s.", sender.String(), ts.Value.String(), - ts.Coin), + coin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": ts.Value.String(), - "coin": fmt.Sprintf("%s", ts.Coin), + "coin": coin.GetFullSymbol(), }), } } diff --git a/core/transaction/sell_coin.go b/core/transaction/sell_coin.go index fb211ef89..6730ff06e 100644 --- a/core/transaction/sell_coin.go +++ b/core/transaction/sell_coin.go @@ -346,16 +346,19 @@ func (data SellCoinData) Run(tx *Transaction, context state.Interface, rewardPoo for _, ts := range totalSpends { if checkState.Accounts().GetBalance(sender, ts.Coin).Cmp(ts.Value) < 0 { + coin := checkState.Coins().GetCoin(ts.Coin) + return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s.", sender.String(), ts.Value.String(), - ts.Coin), + coin.GetFullSymbol(), + ), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": ts.Value.String(), - "coin": fmt.Sprintf("%s", ts.Coin), + "coin": coin.GetFullSymbol(), }), } } diff --git a/core/transaction/send.go b/core/transaction/send.go index 89bbaea34..f0cea7f5a 100644 --- a/core/transaction/send.go +++ b/core/transaction/send.go @@ -132,16 +132,18 @@ func (data SendData) Run(tx *Transaction, context state.Interface, rewardPool *b for _, ts := range totalSpends { if checkState.Accounts().GetBalance(sender, ts.Coin).Cmp(ts.Value) < 0 { + coin := checkState.Coins().GetCoin(ts.Coin) + return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s.", sender.String(), ts.Value.String(), - ts.Coin), + coin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": ts.Value.String(), - "coin": fmt.Sprintf("%s", ts.Coin), + "coin": coin.GetFullSymbol(), }), } } diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index d9d884a3e..4d848b328 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -89,36 +89,38 @@ func (data SetHaltBlockData) Run(tx *Transaction, context state.Interface, rewar commission := big.NewInt(0).Set(commissionInBaseCoin) if !tx.GasCoin.IsBaseCoin() { - coin := checkState.Coins().GetCoin(tx.GasCoin) + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) - errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) + errResp := CheckReserveUnderflow(gasCoin, commissionInBaseCoin) if errResp != nil { return *errResp } - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { + if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { return Response{ Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String()), + Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "has_reserve": coin.Reserve().String(), + "has_reserve": gasCoin.Reserve().String(), "commission": commissionInBaseCoin.String(), - "gas_coin": coin.CName, + "gas_coin": gasCoin.GetFullSymbol(), }), } } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) + return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, tx.GasCoin), + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + "gas_coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index 762ccfdc3..2aa656eff 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -60,36 +60,38 @@ func (data SetCandidateOnData) Run(tx *Transaction, context state.Interface, rew commission := big.NewInt(0).Set(commissionInBaseCoin) if !tx.GasCoin.IsBaseCoin() { - coin := checkState.Coins().GetCoin(tx.GasCoin) + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) - errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) + errResp := CheckReserveUnderflow(gasCoin, commissionInBaseCoin) if errResp != nil { return *errResp } - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { + if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { return Response{ Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String()), + Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "has_reserve": coin.Reserve().String(), + "has_reserve": gasCoin.Reserve().String(), "commission": commissionInBaseCoin.String(), - "gas_coin": coin.CName, + "gas_coin": gasCoin.GetFullSymbol(), }), } } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) + return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, tx.GasCoin), + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + "gas_coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index f1364ed49..70b672f27 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -319,7 +319,7 @@ func CheckReserveUnderflow(m *coins.Model, delta *big.Int) *Response { min := big.NewInt(0).Add(minCoinReserve, delta) return &Response{ Code: code.CoinReserveUnderflow, - Log: fmt.Sprintf("coin %s reserve is too small (%s, required at least %s)", m.Symbol().String(), m.Reserve().String(), min.String()), + Log: fmt.Sprintf("coin %s reserve is too small (%s, required at least %s)", m.GetFullSymbol(), m.Reserve().String(), min.String()), Info: EncodeError(map[string]string{ "coin": m.Symbol().String(), "coin_reserve": m.Reserve().String(), diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 44d104818..de6720fad 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -112,37 +112,37 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool commissionInBaseCoin := tx.CommissionInBaseCoin() commission := big.NewInt(0).Set(commissionInBaseCoin) - if !tx.GasCoin.IsBaseCoin() { - coin := checkState.Coins().GetCoin(tx.GasCoin) + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) - errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) + if !tx.GasCoin.IsBaseCoin() { + errResp := CheckReserveUnderflow(gasCoin, commissionInBaseCoin) if errResp != nil { return *errResp } - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { + if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { return Response{ Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String()), + Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "has_reserve": coin.Reserve().String(), + "has_reserve": gasCoin.Reserve().String(), "commission": commissionInBaseCoin.String(), - "gas_coin": coin.CName, + "gas_coin": gasCoin.GetFullSymbol(), }), } } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { return Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, tx.GasCoin), + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + "gas_coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/types/appstate.go b/core/types/appstate.go index 41c0679ec..dc38fc058 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -8,19 +8,19 @@ import ( ) type AppState struct { - Note string `json:"note"` - StartHeight uint64 `json:"start_height"` - Validators []Validator `json:"validators,omitempty"` - Candidates []Candidate `json:"candidates,omitempty"` + Note string `json:"note"` + StartHeight uint64 `json:"start_height"` + Validators []Validator `json:"validators,omitempty"` + Candidates []Candidate `json:"candidates,omitempty"` BlockListCandidates []Pubkey `json:"block_list_candidates,omitempty"` - Accounts []Account `json:"accounts,omitempty"` - Coins []Coin `json:"coins,omitempty"` - FrozenFunds []FrozenFund `json:"frozen_funds,omitempty"` - HaltBlocks []HaltBlock `json:"halt_blocks,omitempty"` - UsedChecks []UsedCheck `json:"used_checks,omitempty"` - MaxGas uint64 `json:"max_gas"` - TotalSlashed string `json:"total_slashed"` - CoinsCount uint32 `json:"coins_count"` + Accounts []Account `json:"accounts,omitempty"` + Coins []Coin `json:"coins,omitempty"` + FrozenFunds []FrozenFund `json:"frozen_funds,omitempty"` + HaltBlocks []HaltBlock `json:"halt_blocks,omitempty"` + UsedChecks []UsedCheck `json:"used_checks,omitempty"` + MaxGas uint64 `json:"max_gas"` + TotalSlashed string `json:"total_slashed"` + CoinsCount uint32 `json:"coins_count"` } func (s *AppState) Verify() error { From 9727fd08b141a72b9159b9c0456d45e6c84dc41e Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 22 Jul 2020 16:23:09 +0300 Subject: [PATCH 090/426] update api --- api/block.go | 13 ++-- api/v2/service/block.go | 23 +++++-- api/v2/service/estimate_tx_commission.go | 15 +++-- api/v2/service/events.go | 5 +- api/v2/service/genesis.go | 5 +- api/v2/service/service.go | 5 +- api/v2/service/transaction.go | 60 +++++------------- api/v2/service/transactions.go | 78 ++++++++++++++---------- api/v2/service/ws.go | 6 +- core/appdb/appdb.go | 8 ++- go.mod | 4 ++ 11 files changed, 113 insertions(+), 109 deletions(-) diff --git a/api/block.go b/api/block.go index 22e62a8d7..ae09b53f1 100644 --- a/api/block.go +++ b/api/block.go @@ -75,6 +75,13 @@ func Block(height int64) (*BlockResponse, error) { totalValidators = append(totalValidators, tmValidators.Validators...) } + cState, err := GetStateForHeight(int(height)) + if err != nil { + return nil, err + } + + txJsonEncoder := encoder.NewTxEncoderJSON(cState) + txs := make([]BlockTransactionResponse, len(block.Block.Data.Txs)) for i, rawTx := range block.Block.Data.Txs { tx, _ := transaction.TxDecoder.DecodeFromBytes(rawTx) @@ -89,12 +96,6 @@ func Block(height int64) (*BlockResponse, error) { tags[string(tag.Key)] = string(tag.Value) } - cState, err := GetStateForHeight(int(height)) - if err != nil { - return nil, err - } - - txJsonEncoder := encoder.NewTxEncoderJSON(cState) data, err := txJsonEncoder.EncodeData(tx) if err != nil { return nil, err diff --git a/api/v2/service/block.go b/api/v2/service/block.go index b1c5ce29b..3b2e72c66 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/MinterTeam/minter-go-node/core/rewards" "github.com/MinterTeam/minter-go-node/core/transaction" + "github.com/MinterTeam/minter-go-node/core/transaction/encoder" "github.com/MinterTeam/minter-go-node/core/types" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" core_types "github.com/tendermint/tendermint/rpc/core/types" @@ -50,7 +51,13 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes return new(pb.BlockResponse), timeoutStatus.Err() } - response.Transactions, err = s.blockTransaction(block, blockResults) + cState, err := s.blockchain.GetStateForHeight(uint64(height)) + if err != nil { + return nil, err + } + + txJsonEncoder := encoder.NewTxEncoderJSON(cState) + response.Transactions, err = s.blockTransaction(block, blockResults, txJsonEncoder) if err != nil { return new(pb.BlockResponse), err } @@ -99,7 +106,7 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes case pb.BlockRequest_block_reward: response.BlockReward = rewards.GetRewardForBlock(uint64(height)).String() case pb.BlockRequest_transactions: - response.Transactions, err = s.blockTransaction(block, blockResults) + response.Transactions, err = s.blockTransaction(block, blockResults, nil) if err != nil { return new(pb.BlockResponse), err } @@ -174,8 +181,9 @@ func blockProposer(block *core_types.ResultBlock, totalValidators []*tmTypes.Val return "", nil } -func (s *Service) blockTransaction(block *core_types.ResultBlock, blockResults *core_types.ResultBlockResults) ([]*pb.BlockResponse_Transaction, error) { +func (s *Service) blockTransaction(block *core_types.ResultBlock, blockResults *core_types.ResultBlockResults, jsonEncoder *encoder.TxEncoderJSON) ([]*pb.BlockResponse_Transaction, error) { txs := make([]*pb.BlockResponse_Transaction, 0, len(block.Block.Data.Txs)) + for i, rawTx := range block.Block.Data.Txs { tx, _ := transaction.TxDecoder.DecodeFromBytes(rawTx) sender, _ := tx.Sender() @@ -185,9 +193,14 @@ func (s *Service) blockTransaction(block *core_types.ResultBlock, blockResults * tags[string(tag.Key)] = string(tag.Value) } - dataStruct, err := s.encodeTxData(tx) + data, err := jsonEncoder.EncodeData(tx) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + dataStruct, err := encodeToStruct(data) if err != nil { - return nil, status.Error(codes.InvalidArgument, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } txs = append(txs, &pb.BlockResponse_Transaction{ diff --git a/api/v2/service/estimate_tx_commission.go b/api/v2/service/estimate_tx_commission.go index bd1d3ed91..5d6360ac1 100644 --- a/api/v2/service/estimate_tx_commission.go +++ b/api/v2/service/estimate_tx_commission.go @@ -13,6 +13,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "math/big" + "strings" ) func (s *Service) EstimateTxCommission(ctx context.Context, req *pb.EstimateTxCommissionRequest) (*pb.EstimateTxCommissionResponse, error) { @@ -24,7 +25,7 @@ func (s *Service) EstimateTxCommission(ctx context.Context, req *pb.EstimateTxCo cState.RLock() defer cState.RUnlock() - if len(req.GetTx()) < 3 { + if req.GetTx() == "" { data := req.GetData() if data == nil { return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "invalid tx and data") @@ -33,6 +34,10 @@ func (s *Service) EstimateTxCommission(ctx context.Context, req *pb.EstimateTxCo return commissionCoinForData(data, cState) } + if !strings.HasPrefix(strings.Title(req.GetTx()), "Mt") { + return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "invalid transaction") + } + decodeString, err := hex.DecodeString(req.GetTx()[2:]) if err != nil { return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, err.Error()) @@ -52,7 +57,7 @@ func (s *Service) EstimateTxCommission(ctx context.Context, req *pb.EstimateTxCo if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { return new(pb.EstimateTxCommissionResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String())), transaction.EncodeError(map[string]string{ - "commission_in_base_coin": coin.Reserve().String(), + "commission_in_base_coin": commissionInBaseCoin.String(), "value_has": coin.Reserve().String(), "value_required": commissionInBaseCoin.String(), })) @@ -92,16 +97,16 @@ func commissionCoinForData(data *pb.EstimateTxCommissionRequest_TransactionData, commissionInBaseCoin = big.NewInt(commissions.CreateMultisig) case pb.EstimateTxCommissionRequest_TransactionData_Multisend: if data.Mtxs <= 0 { - return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "Set number of txs for multisend (mtxs)") + return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "Set number of transactions for multisend (mtxs)") } commissionInBaseCoin = big.NewInt(commissions.MultisendDelta*(data.Mtxs-1) + 10) default: - return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "Set correct txtype for tx") + return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "Set correct transaction type for tx") } lenPayload := len(data.Payload) if lenPayload > 1024 { - return new(pb.EstimateTxCommissionResponse), status.Errorf(codes.InvalidArgument, "TX payload length is over %d bytes", 1024) + return new(pb.EstimateTxCommissionResponse), status.Errorf(codes.InvalidArgument, "Transaction payload length is over %d bytes", 1024) } totalCommissionInBaseCoin := new(big.Int).Mul(big.NewInt(0).Add(commissionInBaseCoin, big.NewInt(int64(lenPayload))), transaction.CommissionMultiplier) diff --git a/api/v2/service/events.go b/api/v2/service/events.go index 52470064f..b00c4d4bf 100644 --- a/api/v2/service/events.go +++ b/api/v2/service/events.go @@ -5,7 +5,6 @@ import ( "encoding/json" eventsdb "github.com/MinterTeam/minter-go-node/core/events" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" - _struct "github.com/golang/protobuf/ptypes/struct" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -37,8 +36,8 @@ func (s *Service) Events(ctx context.Context, req *pb.EventsRequest) (*pb.Events return new(pb.EventsResponse), status.Error(codes.Internal, err.Error()) } - data := &_struct.Struct{} - if err := data.UnmarshalJSON(b); err != nil { + data, err := encodeToStruct(b) + if err != nil { return new(pb.EventsResponse), status.Error(codes.Internal, err.Error()) } diff --git a/api/v2/service/genesis.go b/api/v2/service/genesis.go index 42b4882dc..b125b9078 100644 --- a/api/v2/service/genesis.go +++ b/api/v2/service/genesis.go @@ -5,7 +5,6 @@ import ( "fmt" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "github.com/golang/protobuf/ptypes/empty" - _struct "github.com/golang/protobuf/ptypes/struct" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "time" @@ -21,8 +20,8 @@ func (s *Service) Genesis(ctx context.Context, _ *empty.Empty) (*pb.GenesisRespo return new(pb.GenesisResponse), timeoutStatus.Err() } - appState := &_struct.Struct{} - if err := appState.UnmarshalJSON(result.Genesis.AppState); err != nil { + appState, err := encodeToStruct(result.Genesis.AppState) + if err != nil { return new(pb.GenesisResponse), status.Error(codes.Internal, err.Error()) } diff --git a/api/v2/service/service.go b/api/v2/service/service.go index 630694d1d..77063471d 100644 --- a/api/v2/service/service.go +++ b/api/v2/service/service.go @@ -4,7 +4,6 @@ import ( "context" "github.com/MinterTeam/minter-go-node/config" "github.com/MinterTeam/minter-go-node/core/minter" - _struct "github.com/golang/protobuf/ptypes/struct" "github.com/tendermint/go-amino" tmNode "github.com/tendermint/tendermint/node" rpc "github.com/tendermint/tendermint/rpc/client/local" @@ -38,8 +37,8 @@ func (s *Service) createError(statusErr *status.Status, data string) error { return statusErr.Err() } - detailsMap := &_struct.Struct{} - if err := detailsMap.UnmarshalJSON([]byte(data)); err != nil { + detailsMap, err := encodeToStruct([]byte(data)) + if err != nil { s.client.Logger.Error(err.Error()) return statusErr.Err() } diff --git a/api/v2/service/transaction.go b/api/v2/service/transaction.go index cc1387401..d7ecf762c 100644 --- a/api/v2/service/transaction.go +++ b/api/v2/service/transaction.go @@ -3,9 +3,9 @@ package service import ( "context" "encoding/hex" - "errors" "fmt" "github.com/MinterTeam/minter-go-node/core/transaction" + "github.com/MinterTeam/minter-go-node/core/transaction/encoder" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" _struct "github.com/golang/protobuf/ptypes/struct" tmbytes "github.com/tendermint/tendermint/libs/bytes" @@ -35,7 +35,18 @@ func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) ( tags[string(tag.Key)] = string(tag.Value) } - dataStruct, err := s.encodeTxData(decodedTx) + cState, err := s.blockchain.GetStateForHeight(uint64(tx.Height)) + if err != nil { + return new(pb.TransactionResponse), status.Error(codes.Internal, err.Error()) + } + + txJsonEncoder := encoder.NewTxEncoderJSON(cState) + data, err := txJsonEncoder.Encode(decodedTx, tx) + if err != nil { + return new(pb.TransactionResponse), status.Error(codes.Internal, err.Error()) + } + + dataStruct, err := encodeToStruct(data) if err != nil { return new(pb.TransactionResponse), status.Error(codes.FailedPrecondition, err.Error()) } @@ -59,50 +70,7 @@ func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) ( }, nil } -func (s *Service) encodeTxData(decodedTx *transaction.Transaction) (*_struct.Struct, error) { - var ( - err error - b []byte - ) - switch decodedTx.Type { - case transaction.TypeSend: - b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.SendData)) - case transaction.TypeRedeemCheck: - b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.RedeemCheckData)) - case transaction.TypeSellCoin: - b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.SellCoinData)) - case transaction.TypeSellAllCoin: - b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.SellAllCoinData)) - case transaction.TypeBuyCoin: - b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.BuyCoinData)) - case transaction.TypeCreateCoin: - b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.CreateCoinData)) - case transaction.TypeDeclareCandidacy: - b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.DeclareCandidacyData)) - case transaction.TypeDelegate: - b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.DelegateData)) - case transaction.TypeSetCandidateOnline: - b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.SetCandidateOnData)) - case transaction.TypeSetCandidateOffline: - b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.SetCandidateOffData)) - case transaction.TypeUnbond: - b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.UnbondData)) - case transaction.TypeMultisend: - b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.MultisendData)) - case transaction.TypeCreateMultisig: - b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.CreateMultisigData)) - case transaction.TypeEditCandidate: - b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.EditCandidateData)) - case transaction.TypeSetHaltBlock: - b, err = s.cdc.MarshalJSON(decodedTx.GetDecodedData().(*transaction.SetHaltBlockData)) - default: - return nil, errors.New("unknown tx type") - } - - if err != nil { - return nil, err - } - +func encodeToStruct(b []byte) (*_struct.Struct, error) { dataStruct := &_struct.Struct{} if err := dataStruct.UnmarshalJSON(b); err != nil { return nil, err diff --git a/api/v2/service/transactions.go b/api/v2/service/transactions.go index ae6b0d73b..d8e091156 100644 --- a/api/v2/service/transactions.go +++ b/api/v2/service/transactions.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "github.com/MinterTeam/minter-go-node/core/transaction" + "github.com/MinterTeam/minter-go-node/core/transaction/encoder" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "github.com/tendermint/tendermint/libs/bytes" "google.golang.org/grpc/codes" @@ -25,45 +26,58 @@ func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) return new(pb.TransactionsResponse), status.Error(codes.FailedPrecondition, err.Error()) } - result := make([]*pb.TransactionResponse, 0, len(rpcResult.Txs)) - for _, tx := range rpcResult.Txs { + lenTx := len(rpcResult.Txs) + result := make([]*pb.TransactionResponse, 0, lenTx) + if lenTx != 0 { - if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.TransactionsResponse), timeoutStatus.Err() + cState, err := s.blockchain.GetStateForHeight(uint64(rpcResult.Txs[0].Height)) + if err != nil { + return new(pb.TransactionsResponse), status.Error(codes.Internal, err.Error()) } + for _, tx := range rpcResult.Txs { - decodedTx, _ := transaction.TxDecoder.DecodeFromBytes(tx.Tx) - sender, _ := decodedTx.Sender() + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.TransactionsResponse), timeoutStatus.Err() + } - tags := make(map[string]string) - for _, tag := range tx.TxResult.Events[0].Attributes { - tags[string(tag.Key)] = string(tag.Value) - } + decodedTx, _ := transaction.TxDecoder.DecodeFromBytes(tx.Tx) + sender, _ := decodedTx.Sender() - dataStruct, err := s.encodeTxData(decodedTx) - if err != nil { - return new(pb.TransactionsResponse), status.Error(codes.FailedPrecondition, err.Error()) - } + tags := make(map[string]string) + for _, tag := range tx.TxResult.Events[0].Attributes { + tags[string(tag.Key)] = string(tag.Value) + } - result = append(result, &pb.TransactionResponse{ - Hash: bytes.HexBytes(tx.Tx.Hash()).String(), - RawTx: fmt.Sprintf("%x", []byte(tx.Tx)), - Height: fmt.Sprintf("%d", tx.Height), - Index: fmt.Sprintf("%d", tx.Index), - From: sender.String(), - Nonce: fmt.Sprintf("%d", decodedTx.Nonce), - GasPrice: fmt.Sprintf("%d", decodedTx.GasPrice), - GasCoin: decodedTx.GasCoin.String(), - Gas: fmt.Sprintf("%d", decodedTx.Gas()), - Type: fmt.Sprintf("%d", uint8(decodedTx.Type)), - Data: dataStruct, - Payload: decodedTx.Payload, - Tags: tags, - Code: fmt.Sprintf("%d", tx.TxResult.Code), - Log: tx.TxResult.Log, - }) - } + txJsonEncoder := encoder.NewTxEncoderJSON(cState) + data, err := txJsonEncoder.Encode(decodedTx, tx) + if err != nil { + return new(pb.TransactionsResponse), status.Error(codes.Internal, err.Error()) + } + + dataStruct, err := encodeToStruct(data) + if err != nil { + return new(pb.TransactionsResponse), status.Error(codes.FailedPrecondition, err.Error()) + } + result = append(result, &pb.TransactionResponse{ + Hash: bytes.HexBytes(tx.Tx.Hash()).String(), + RawTx: fmt.Sprintf("%x", []byte(tx.Tx)), + Height: fmt.Sprintf("%d", tx.Height), + Index: fmt.Sprintf("%d", tx.Index), + From: sender.String(), + Nonce: fmt.Sprintf("%d", decodedTx.Nonce), + GasPrice: fmt.Sprintf("%d", decodedTx.GasPrice), + GasCoin: decodedTx.GasCoin.String(), + Gas: fmt.Sprintf("%d", decodedTx.Gas()), + Type: fmt.Sprintf("%d", uint8(decodedTx.Type)), + Data: dataStruct, + Payload: decodedTx.Payload, + Tags: tags, + Code: fmt.Sprintf("%d", tx.TxResult.Code), + Log: tx.TxResult.Log, + }) + } + } return &pb.TransactionsResponse{ Transactions: result, }, nil diff --git a/api/v2/service/ws.go b/api/v2/service/ws.go index 6fd8bd717..401ec0756 100644 --- a/api/v2/service/ws.go +++ b/api/v2/service/ws.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" - _struct "github.com/golang/protobuf/ptypes/struct" "github.com/google/uuid" core_types "github.com/tendermint/tendermint/rpc/core/types" "google.golang.org/grpc/codes" @@ -71,9 +70,8 @@ func subscribeResponse(msg core_types.ResultEvent) (*pb.SubscribeResponse, error return nil, err } - data := &_struct.Struct{} - - if err := data.UnmarshalJSON(byteData); err != nil { + data, err := encodeToStruct(byteData) + if err != nil { return nil, err } diff --git a/core/appdb/appdb.go b/core/appdb/appdb.go index f5a177a97..57f700628 100644 --- a/core/appdb/appdb.go +++ b/core/appdb/appdb.go @@ -45,7 +45,9 @@ func (appDB *AppDB) GetLastBlockHash() []byte { } func (appDB *AppDB) SetLastBlockHash(hash []byte) { - appDB.db.Set([]byte(hashPath), hash) + if err := appDB.db.Set([]byte(hashPath), hash); err != nil { + panic(err) + } } func (appDB *AppDB) GetLastHeight() uint64 { @@ -65,7 +67,9 @@ func (appDB *AppDB) GetLastHeight() uint64 { func (appDB *AppDB) SetLastHeight(height uint64) { h := make([]byte, 8) binary.BigEndian.PutUint64(h, height) - appDB.db.Set([]byte(heightPath), h) + if err := appDB.db.Set([]byte(heightPath), h); err != nil { + panic(err) + } } func (appDB *AppDB) SetStartHeight(height uint64) { diff --git a/go.mod b/go.mod index 7e8ff3e21..d730d1b71 100644 --- a/go.mod +++ b/go.mod @@ -40,3 +40,7 @@ require ( google.golang.org/protobuf v1.25.0 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 ) + +replace ( + github.com/MinterTeam/node-grpc-gateway => /Users/klim0v/GolandProjects/node-grpc-gateway +) \ No newline at end of file From e002ed0eb4a0fd9dd2103d8a5ca458a400238481 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 22 Jul 2020 18:23:59 +0300 Subject: [PATCH 091/426] wip --- core/state/candidates/candidates.go | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 83e11c36f..923f0a41b 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -54,7 +54,9 @@ type RCandidates interface { } type Candidates struct { - list map[uint]*Candidate + list map[uint]*Candidate + + isDirty bool blockList map[types.Pubkey]struct{} pubKeyIDs map[types.Pubkey]uint maxID uint @@ -64,8 +66,6 @@ type Candidates struct { lock sync.RWMutex loaded bool - - isDirty bool } func NewCandidates(bus *bus.Bus, iavl tree.MTree) (*Candidates, error) { @@ -101,7 +101,7 @@ func (c *Candidates) Commit() error { } if c.isDirty { - + c.isDirty = false var pubIDs []pubkeyID for pk, v := range c.pubKeyIDs { pubIDs = append(pubIDs, pubkeyID{ @@ -783,7 +783,7 @@ func (c *Candidates) LoadCandidates() { return } - c.loadCandidatesList() + _ = c.loadCandidatesList() } // Load full info about candidates (for edit) @@ -792,7 +792,7 @@ func (c *Candidates) LoadCandidatesDeliver() { return } - c.loadCandidatesList() + c.maxID = c.loadCandidatesList() _, blockListEnc := c.iavl.Get([]byte{blockListPrefix}) if len(blockListEnc) != 0 { @@ -815,7 +815,7 @@ func (c *Candidates) LoadCandidatesDeliver() { } -func (c *Candidates) loadCandidatesList() { +func (c *Candidates) loadCandidatesList() (maxID uint) { _, pubIDenc := c.iavl.Get([]byte{pubKeyIDPrefix}) if len(pubIDenc) != 0 { var pubIDs []pubkeyID @@ -826,6 +826,9 @@ func (c *Candidates) loadCandidatesList() { pubKeyIDs := map[types.Pubkey]uint{} for _, v := range pubIDs { pubKeyIDs[v.PubKey] = v.ID + if v.ID > maxID { + maxID = v.ID + } } c.setPubKeyIDs(pubKeyIDs) } @@ -853,6 +856,8 @@ func (c *Candidates) loadCandidatesList() { c.setToMap(candidate.PubKey, candidate) } } + + return maxID } func (c *Candidates) checkAndSetLoaded() bool { From 0faa735ade87007f068b4780a30031119c0c1a3b Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 23 Jul 2020 14:33:16 +0300 Subject: [PATCH 092/426] small refactor --- core/state/state.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/state/state.go b/core/state/state.go index dbbde31ec..4f0962a18 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -305,6 +305,10 @@ func (s *State) Import(state types.AppState) error { } s.Validators.SetValidators(vals) + for _, pubkey := range state.BlockListCandidates { + s.Candidates.AddToBlockPybKey(pubkey) + } + for _, c := range state.Candidates { s.Candidates.Create(c.OwnerAddress, c.RewardAddress, c.ControlAddress, c.PubKey, c.Commission) if c.Status == candidates.CandidateStatusOnline { @@ -315,10 +319,6 @@ func (s *State) Import(state types.AppState) error { s.Candidates.SetStakes(c.PubKey, c.Stakes, c.Updates) } - for _, pubkey := range state.BlockListCandidates { - s.Candidates.AddToBlockPybKey(pubkey) - } - for _, hashString := range state.UsedChecks { bytes, _ := hex.DecodeString(string(hashString)) var hash types.Hash From e2a6141c0c36b92eed0dd1c2960eea96a112e74b Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 23 Jul 2020 16:29:42 +0300 Subject: [PATCH 093/426] fix --- api/v2/service/block.go | 8 +++++- core/state/candidates/candidates.go | 32 +++++++++++++-------- core/state/state.go | 2 +- core/transaction/buy_coin.go | 2 -- core/transaction/change_owner.go | 2 -- core/transaction/create_coin.go | 2 -- core/transaction/create_multisig.go | 2 -- core/transaction/declare_candidacy.go | 2 -- core/transaction/delegate.go | 2 -- core/transaction/edit_candidate.go | 2 -- core/transaction/multisend.go | 2 -- core/transaction/recreate_coin.go | 2 -- core/transaction/redeem_check.go | 2 -- core/transaction/sell_all_coin.go | 2 -- core/transaction/sell_coin.go | 2 -- core/transaction/send.go | 2 -- core/transaction/set_halt_block.go | 2 -- core/transaction/switch_candidate_status.go | 4 --- core/transaction/unbond.go | 2 -- 19 files changed, 28 insertions(+), 48 deletions(-) diff --git a/api/v2/service/block.go b/api/v2/service/block.go index 3b2e72c66..fb6069b19 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -106,7 +106,13 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes case pb.BlockRequest_block_reward: response.BlockReward = rewards.GetRewardForBlock(uint64(height)).String() case pb.BlockRequest_transactions: - response.Transactions, err = s.blockTransaction(block, blockResults, nil) + cState, err := s.blockchain.GetStateForHeight(uint64(height)) + if err != nil { + return nil, err + } + + txJsonEncoder := encoder.NewTxEncoderJSON(cState) + response.Transactions, err = s.blockTransaction(block, blockResults, txJsonEncoder) if err != nil { return new(pb.BlockResponse), err } diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 923f0a41b..29439145d 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -236,6 +236,13 @@ func (c *Candidates) Create(ownerAddress, rewardAddress, controlAddress types.Ad c.setToMap(pubkey, candidate) } +func (c *Candidates) CreateWithID(ownerAddress, rewardAddress, controlAddress types.Address, pubkey types.Pubkey, commission uint, id uint) { + if id != 0 { + c.setPubKeyID(pubkey, id) + } + c.Create(ownerAddress, rewardAddress, controlAddress, pubkey, commission) +} + func (c *Candidates) PunishByzantineCandidate(height uint64, tmAddress types.TmAddress) { candidate := c.GetCandidateByTendermintAddress(tmAddress) stakes := c.GetStakes(candidate.PubKey) @@ -609,6 +616,9 @@ func (c *Candidates) IsBlockPubKey(pubkey *types.Pubkey) bool { } func (c *Candidates) isBlock(pubKey types.Pubkey) bool { + c.lock.Lock() + defer c.lock.Unlock() + _, exists := c.blockList[pubKey] return exists } @@ -1082,13 +1092,12 @@ func (c *Candidates) setToMap(pubkey types.Pubkey, model *Candidate) { id := model.ID if id == 0 { id = c.getOrNewID(pubkey) - - c.lock.Lock() - defer c.lock.Unlock() - model.ID = id } + c.lock.Lock() + defer c.lock.Unlock() + if c.list == nil { c.list = map[uint]*Candidate{} } @@ -1184,9 +1193,6 @@ func (c *Candidates) ChangePubKey(old types.Pubkey, new types.Pubkey) { return } - c.lock.Lock() - defer c.lock.Unlock() - if c.isBlock(new) { panic("Candidate with such public key (" + new.String() + ") exists in block list") } @@ -1206,10 +1212,10 @@ func (c *Candidates) getOrNewID(pubKey types.Pubkey) uint { } c.lock.Lock() - defer c.lock.Unlock() - c.isDirty = true c.maxID++ + c.lock.Unlock() + id = c.maxID c.setPubKeyID(pubKey, id) return id @@ -1227,6 +1233,9 @@ func (c *Candidates) ID(pubKey types.Pubkey) uint { } func (c *Candidates) setPubKeyID(pubkey types.Pubkey, u uint) { + c.lock.Lock() + defer c.lock.Unlock() + if c.pubKeyIDs == nil { c.pubKeyIDs = map[types.Pubkey]uint{} } @@ -1235,6 +1244,8 @@ func (c *Candidates) setPubKeyID(pubkey types.Pubkey, u uint) { } func (c *Candidates) setBlockPybKey(p types.Pubkey) { + c.lock.Lock() + defer c.lock.Unlock() if c.blockList == nil { c.blockList = map[types.Pubkey]struct{}{} } @@ -1243,9 +1254,6 @@ func (c *Candidates) setBlockPybKey(p types.Pubkey) { } func (c *Candidates) AddToBlockPybKey(p types.Pubkey) { - c.lock.Lock() - defer c.lock.Unlock() - c.setBlockPybKey(p) } diff --git a/core/state/state.go b/core/state/state.go index 4f0962a18..ac07193ff 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -310,7 +310,7 @@ func (s *State) Import(state types.AppState) error { } for _, c := range state.Candidates { - s.Candidates.Create(c.OwnerAddress, c.RewardAddress, c.ControlAddress, c.PubKey, c.Commission) + s.Candidates.CreateWithID(c.OwnerAddress, c.RewardAddress, c.ControlAddress, c.PubKey, c.Commission, c.ID) if c.Status == candidates.CandidateStatusOnline { s.Candidates.SetOnline(c.PubKey) } diff --git a/core/transaction/buy_coin.go b/core/transaction/buy_coin.go index ae02e5665..fc144dad1 100644 --- a/core/transaction/buy_coin.go +++ b/core/transaction/buy_coin.go @@ -400,8 +400,6 @@ func (data BuyCoinData) Run(tx *Transaction, context state.Interface, rewardPool } if deliverState, ok := context.(*state.State); ok { - deliverState.Lock() - defer deliverState.Unlock() for _, ts := range totalSpends { deliverState.Accounts.SubBalance(sender, ts.Coin, ts.Value) } diff --git a/core/transaction/change_owner.go b/core/transaction/change_owner.go index c2a0c9870..5d4ba104c 100644 --- a/core/transaction/change_owner.go +++ b/core/transaction/change_owner.go @@ -99,8 +99,6 @@ func (data ChangeOwnerData) Run(tx *Transaction, context state.Interface, reward } if deliverState, ok := context.(*state.State); ok { - deliverState.Lock() - defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) deliverState.Coins.SubVolume(tx.GasCoin, commission) diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index a0c4d83c9..75ba39e7e 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -209,8 +209,6 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP } if deliverState, ok := context.(*state.State); ok { - deliverState.Lock() - defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index 5b6f35267..702cd1533 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -161,8 +161,6 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew } if deliverState, ok := context.(*state.State); ok { - deliverState.Lock() - defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubVolume(tx.GasCoin, commission) diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index 7c029806b..1d12deca6 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -193,8 +193,6 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r } if deliverState, ok := context.(*state.State); ok { - deliverState.Lock() - defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index e83cef4fc..b7cff56e3 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -167,8 +167,6 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo } if deliverState, ok := context.(*state.State); ok { - deliverState.Lock() - defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index ad6de4791..59aa62770 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -137,8 +137,6 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa } if deliverState, ok := context.(*state.State); ok { - deliverState.Lock() - defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) diff --git a/core/transaction/multisend.go b/core/transaction/multisend.go index 9403b9df0..60ea52dee 100644 --- a/core/transaction/multisend.go +++ b/core/transaction/multisend.go @@ -116,8 +116,6 @@ func (data MultisendData) Run(tx *Transaction, context state.Interface, rewardPo } if deliverState, ok := context.(*state.State); ok { - deliverState.Lock() - defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubVolume(tx.GasCoin, commission) diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index a79309be1..caf228a73 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -173,8 +173,6 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar } if deliverState, ok := context.(*state.State); ok { - deliverState.Lock() - defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index ff678f9a0..309045244 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -247,8 +247,6 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward } if deliverState, ok := context.(*state.State); ok { - deliverState.Lock() - defer deliverState.Unlock() deliverState.Checks.UseCheck(decodedCheck) rewardPool.Add(rewardPool, commissionInBaseCoin) diff --git a/core/transaction/sell_all_coin.go b/core/transaction/sell_all_coin.go index 03b23f047..e84eebd21 100644 --- a/core/transaction/sell_all_coin.go +++ b/core/transaction/sell_all_coin.go @@ -236,8 +236,6 @@ func (data SellAllCoinData) Run(tx *Transaction, context state.Interface, reward } if deliverState, ok := context.(*state.State); ok { - deliverState.Lock() - defer deliverState.Unlock() for _, ts := range totalSpends { deliverState.Accounts.SubBalance(sender, ts.Coin, ts.Value) } diff --git a/core/transaction/sell_coin.go b/core/transaction/sell_coin.go index 46e41ee07..fb211ef89 100644 --- a/core/transaction/sell_coin.go +++ b/core/transaction/sell_coin.go @@ -367,8 +367,6 @@ func (data SellCoinData) Run(tx *Transaction, context state.Interface, rewardPoo } if deliverState, ok := context.(*state.State); ok { - deliverState.Lock() - defer deliverState.Unlock() for _, ts := range totalSpends { deliverState.Accounts.SubBalance(sender, ts.Coin, ts.Value) } diff --git a/core/transaction/send.go b/core/transaction/send.go index 9b0b6bdb2..89bbaea34 100644 --- a/core/transaction/send.go +++ b/core/transaction/send.go @@ -148,8 +148,6 @@ func (data SendData) Run(tx *Transaction, context state.Interface, rewardPool *b } if deliverState, ok := context.(*state.State); ok { - deliverState.Lock() - defer deliverState.Unlock() for _, ts := range totalSpends { deliverState.Accounts.SubBalance(sender, ts.Coin, ts.Value) } diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index 08ba5e5e5..d9d884a3e 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -124,8 +124,6 @@ func (data SetHaltBlockData) Run(tx *Transaction, context state.Interface, rewar } if deliverState, ok := context.(*state.State); ok { - deliverState.Lock() - defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index 7b07d575f..762ccfdc3 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -95,8 +95,6 @@ func (data SetCandidateOnData) Run(tx *Transaction, context state.Interface, rew } if deliverState, ok := context.(*state.State); ok { - deliverState.Lock() - defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) @@ -197,8 +195,6 @@ func (data SetCandidateOffData) Run(tx *Transaction, context state.Interface, re } if deliverState, ok := context.(*state.State); ok { - deliverState.Lock() - defer deliverState.Unlock() rewardPool.Add(rewardPool, commissionInBaseCoin) deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 4fd510f83..44d104818 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -148,8 +148,6 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool } if deliverState, ok := context.(*state.State); ok { - deliverState.Lock() - defer deliverState.Unlock() // now + 30 days unbondAtBlock := currentBlock + unbondPeriod From 45baba0beadac95efcfe0575716a041557293287 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 23 Jul 2020 17:19:14 +0300 Subject: [PATCH 094/426] fix --- core/state/candidates/candidates.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 29439145d..ab40749ea 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -609,9 +609,6 @@ func (c *Candidates) IsBlockPubKey(pubkey *types.Pubkey) bool { return false } - c.lock.RLock() - defer c.lock.RUnlock() - return c.isBlock(*pubkey) } From 622d1fc56f40eb7d20b84eb17705b9e0add6e7b7 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 23 Jul 2020 17:39:18 +0300 Subject: [PATCH 095/426] edit model for transaction list in api --- core/transaction/edit_candidate.go | 5 ++--- core/transaction/encoder/resources.go | 21 ++++++++++++++------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index 4fba59779..d3831de6b 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -26,10 +26,9 @@ type EditCandidateData struct { } func (data EditCandidateData) MarshalJSON() ([]byte, error) { - newPubKey := data.NewPubKey newPubKeyStr := "" - if newPubKey != nil { - newPubKeyStr = newPubKey.String() + if data.NewPubKey != nil { + newPubKeyStr = data.NewPubKey.String() } return json.Marshal(struct { PubKey string `json:"pub_key"` diff --git a/core/transaction/encoder/resources.go b/core/transaction/encoder/resources.go index fda21cf8a..d3fbef639 100644 --- a/core/transaction/encoder/resources.go +++ b/core/transaction/encoder/resources.go @@ -271,18 +271,25 @@ func (resource MultiSendDataResource) Transform(txData interface{}, context *sta // TxType 0x0E type EditCandidateDataResource struct { - PubKey string `json:"pub_key"` - RewardAddress string `json:"reward_address"` - OwnerAddress string `json:"owner_address"` + PubKey string `json:"pub_key"` + NewPubKey string `json:"new_pub_key"` + RewardAddress string `json:"reward_address"` + OwnerAddress string `json:"owner_address"` + ControlAddress string `json:"control_address"` } func (EditCandidateDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.EditCandidateData) - + newPubKeyStr := "" + if data.NewPubKey != nil { + newPubKeyStr = data.NewPubKey.String() + } return EditCandidateDataResource{ - PubKey: data.PubKey.String(), - RewardAddress: data.RewardAddress.String(), - OwnerAddress: data.OwnerAddress.String(), + PubKey: data.PubKey.String(), + NewPubKey: newPubKeyStr, + RewardAddress: data.RewardAddress.String(), + OwnerAddress: data.OwnerAddress.String(), + ControlAddress: data.ControlAddress.String(), } } From 1496753c259aa8ea012ecbe415a6b5b7d6023a02 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Fri, 24 Jul 2020 10:56:44 +0300 Subject: [PATCH 096/426] fix transactions tests --- core/transaction/buy_coin_test.go | 253 +++++++++--------- core/transaction/create_coin_test.go | 18 +- core/transaction/create_multisig_test.go | 16 +- core/transaction/declare_candidacy_test.go | 12 +- core/transaction/delegate_test.go | 6 +- core/transaction/edit_candidate_test.go | 6 +- core/transaction/executor_test.go | 74 ++--- core/transaction/multisend_test.go | 4 +- core/transaction/redeem_check_test.go | 6 +- core/transaction/sell_all_coin_test.go | 10 +- core/transaction/sell_coin_test.go | 134 +++++----- core/transaction/send_test.go | 12 +- core/transaction/set_halt_block_test.go | 18 +- .../switch_candidate_status_test.go | 6 +- core/transaction/unbond_test.go | 4 +- 15 files changed, 291 insertions(+), 288 deletions(-) diff --git a/core/transaction/buy_coin_test.go b/core/transaction/buy_coin_test.go index 6055cef6b..3af8e52b8 100644 --- a/core/transaction/buy_coin_test.go +++ b/core/transaction/buy_coin_test.go @@ -43,28 +43,33 @@ func getTestCoinSymbol() types.CoinSymbol { return coin } -func createTestCoin(stateDB *state.State) { +func createTestCoin(stateDB *state.State) types.CoinID { volume := helpers.BipToPip(big.NewInt(100000)) reserve := helpers.BipToPip(big.NewInt(100000)) - stateDB.Coins.Create(getTestCoinSymbol(), "TEST COIN", volume, 10, reserve, big.NewInt(0).Mul(volume, big.NewInt(10))) + id := stateDB.App.GetNextCoinID() + stateDB.Coins.Create(id, getTestCoinSymbol(), "TEST COIN", volume, 10, reserve, + big.NewInt(0).Mul(volume, big.NewInt(10)), nil) + stateDB.App.SetCoinsCount(id.Uint32()) + + return id } func TestBuyCoinTxBaseToCustom(t *testing.T) { cState := getState() - createTestCoin(cState) + coinToBuyID := createTestCoin(cState) privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) toBuy := helpers.BipToPip(big.NewInt(10)) maxValToSell, _ := big.NewInt(0).SetString("159374246010000000000", 10) data := BuyCoinData{ - CoinToBuy: getTestCoinSymbol(), + CoinToBuy: coinToBuyID, ValueToBuy: toBuy, CoinToSell: coin, MaximumValueToSell: maxValToSell, @@ -96,7 +101,7 @@ func TestBuyCoinTxBaseToCustom(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) @@ -108,7 +113,7 @@ func TestBuyCoinTxBaseToCustom(t *testing.T) { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", coin, targetBalance, balance) } - testBalance := cState.Accounts.GetBalance(addr, getTestCoinSymbol()) + testBalance := cState.Accounts.GetBalance(addr, coinToBuyID) if testBalance.Cmp(toBuy) != 0 { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", getTestCoinSymbol(), toBuy, testBalance) } @@ -117,18 +122,18 @@ func TestBuyCoinTxBaseToCustom(t *testing.T) { func TestBuyCoinTxInsufficientFunds(t *testing.T) { cState := getState() - createTestCoin(cState) + coinToBuyID := createTestCoin(cState) privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1))) toBuy := helpers.BipToPip(big.NewInt(10)) maxValToSell, _ := big.NewInt(0).SetString("159374246010000000000", 10) data := BuyCoinData{ - CoinToBuy: getTestCoinSymbol(), + CoinToBuy: coinToBuyID, ValueToBuy: toBuy, CoinToSell: coin, MaximumValueToSell: maxValToSell, @@ -161,7 +166,7 @@ func TestBuyCoinTxInsufficientFunds(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) @@ -171,12 +176,14 @@ func TestBuyCoinTxInsufficientFunds(t *testing.T) { func TestBuyCoinTxEqualCoins(t *testing.T) { cState := getState() + coinID := createTestCoin(cState) + privateKey, _ := crypto.GenerateKey() data := BuyCoinData{ - CoinToBuy: getTestCoinSymbol(), + CoinToBuy: coinID, ValueToBuy: big.NewInt(0), - CoinToSell: getTestCoinSymbol(), + CoinToSell: coinID, } encodedData, err := rlp.EncodeToBytes(data) @@ -189,7 +196,7 @@ func TestBuyCoinTxEqualCoins(t *testing.T) { Nonce: 1, GasPrice: 1, ChainID: types.CurrentChainID, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), Type: TypeBuyCoin, Data: encodedData, SignatureType: SigTypeSingle, @@ -205,7 +212,7 @@ func TestBuyCoinTxEqualCoins(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.CrossConvert { t.Fatalf("Response code is not %d. Error %s", code.CrossConvert, response.Log) @@ -218,9 +225,9 @@ func TestBuyCoinTxNotExistsBuyCoin(t *testing.T) { privateKey, _ := crypto.GenerateKey() data := BuyCoinData{ - CoinToBuy: types.CoinSymbol{}, + CoinToBuy: cState.App.GetNextCoinID(), ValueToBuy: big.NewInt(0), - CoinToSell: types.GetBaseCoin(), + CoinToSell: types.GetBaseCoinID(), } encodedData, err := rlp.EncodeToBytes(data) @@ -233,7 +240,7 @@ func TestBuyCoinTxNotExistsBuyCoin(t *testing.T) { Nonce: 1, GasPrice: 1, ChainID: types.CurrentChainID, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), Type: TypeBuyCoin, Data: encodedData, SignatureType: SigTypeSingle, @@ -249,7 +256,7 @@ func TestBuyCoinTxNotExistsBuyCoin(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.CoinNotExists { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) @@ -262,9 +269,9 @@ func TestBuyCoinTxNotExistsSellCoin(t *testing.T) { privateKey, _ := crypto.GenerateKey() data := BuyCoinData{ - CoinToBuy: types.GetBaseCoin(), + CoinToBuy: types.GetBaseCoinID(), ValueToBuy: big.NewInt(0), - CoinToSell: types.CoinSymbol{}, + CoinToSell: cState.App.GetNextCoinID(), } encodedData, err := rlp.EncodeToBytes(data) @@ -277,7 +284,7 @@ func TestBuyCoinTxNotExistsSellCoin(t *testing.T) { Nonce: 1, GasPrice: 1, ChainID: types.CurrentChainID, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), Type: TypeBuyCoin, Data: encodedData, SignatureType: SigTypeSingle, @@ -293,7 +300,7 @@ func TestBuyCoinTxNotExistsSellCoin(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.CoinNotExists { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) @@ -303,14 +310,14 @@ func TestBuyCoinTxNotExistsSellCoin(t *testing.T) { func TestBuyCoinTxNotExistsGasCoin(t *testing.T) { cState := getState() - createTestCoin(cState) + coinToSellID := createTestCoin(cState) privateKey, _ := crypto.GenerateKey() data := BuyCoinData{ - CoinToBuy: types.GetBaseCoin(), + CoinToBuy: types.GetBaseCoinID(), ValueToBuy: big.NewInt(0), - CoinToSell: getTestCoinSymbol(), + CoinToSell: coinToSellID, } encodedData, err := rlp.EncodeToBytes(data) @@ -323,7 +330,7 @@ func TestBuyCoinTxNotExistsGasCoin(t *testing.T) { Nonce: 1, GasPrice: 1, ChainID: types.CurrentChainID, - GasCoin: types.CoinSymbol{}, + GasCoin: cState.App.GetNextCoinID(), Type: TypeBuyCoin, Data: encodedData, SignatureType: SigTypeSingle, @@ -339,7 +346,7 @@ func TestBuyCoinTxNotExistsGasCoin(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.CoinNotExists { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) @@ -349,17 +356,17 @@ func TestBuyCoinTxNotExistsGasCoin(t *testing.T) { func TestBuyCoinTxNotGasCoin(t *testing.T) { cState := getState() - createTestCoin(cState) + coinToSellID := createTestCoin(cState) privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - cState.Accounts.AddBalance(addr, getTestCoinSymbol(), helpers.BipToPip(big.NewInt(1000))) + cState.Accounts.AddBalance(addr, coinToSellID, helpers.BipToPip(big.NewInt(1000))) data := BuyCoinData{ - CoinToBuy: types.GetBaseCoin(), + CoinToBuy: types.GetBaseCoinID(), ValueToBuy: big.NewInt(1), - CoinToSell: getTestCoinSymbol(), + CoinToSell: coinToSellID, MaximumValueToSell: big.NewInt(10004502852067863), } @@ -373,7 +380,7 @@ func TestBuyCoinTxNotGasCoin(t *testing.T) { Nonce: 1, GasPrice: 1, ChainID: types.CurrentChainID, - GasCoin: getTestCoinSymbol(), + GasCoin: coinToSellID, Type: TypeBuyCoin, Data: encodedData, SignatureType: SigTypeSingle, @@ -389,7 +396,7 @@ func TestBuyCoinTxNotGasCoin(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) @@ -397,13 +404,15 @@ func TestBuyCoinTxNotGasCoin(t *testing.T) { } func TestBuyCoinTxJSON(t *testing.T) { - str := "{\"coin_to_buy\":\"%s\",\"value_to_buy\":\"1\",\"coin_to_sell\":\"TEST\",\"maximum_value_to_sell\":\"1\"}" - out := []byte(fmt.Sprintf(str, types.GetBaseCoin().String())) + str := "{\"coin_to_buy\":\"%d\",\"value_to_buy\":\"1\",\"coin_to_sell\":\"1\",\"maximum_value_to_sell\":\"1\"}" + out := []byte(fmt.Sprintf(str, types.GetBaseCoinID())) + + coinID := createTestCoin(getState()) buyCoinData := BuyCoinData{ - CoinToBuy: types.GetBaseCoin(), + CoinToBuy: types.GetBaseCoinID(), ValueToBuy: big.NewInt(1), - CoinToSell: getTestCoinSymbol(), + CoinToSell: coinID, MaximumValueToSell: big.NewInt(1), } @@ -421,20 +430,19 @@ func TestBuyCoinTxJSON(t *testing.T) { func TestBuyCoinTxCustomToBase(t *testing.T) { cState := getState() - createTestCoin(cState) + coinToSellID := createTestCoin(cState) privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := getTestCoinSymbol() - cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(10000000))) + cState.Accounts.AddBalance(addr, coinToSellID, helpers.BipToPip(big.NewInt(10000000))) toBuy := helpers.BipToPip(big.NewInt(10)) maxValToSell, _ := big.NewInt(0).SetString("159374246010000000000", 10) data := BuyCoinData{ - CoinToBuy: types.GetBaseCoin(), + CoinToBuy: types.GetBaseCoinID(), ValueToBuy: toBuy, - CoinToSell: coin, + CoinToSell: coinToSellID, MaximumValueToSell: maxValToSell, } @@ -448,7 +456,7 @@ func TestBuyCoinTxCustomToBase(t *testing.T) { Nonce: 1, GasPrice: 1, ChainID: types.CurrentChainID, - GasCoin: coin, + GasCoin: coinToSellID, Type: TypeBuyCoin, Data: encodedData, SignatureType: SigTypeSingle, @@ -464,53 +472,52 @@ func TestBuyCoinTxCustomToBase(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) } targetBalance, _ := big.NewInt(0).SetString("9999998989954092563427063", 10) - balance := cState.Accounts.GetBalance(addr, coin) + balance := cState.Accounts.GetBalance(addr, coinToSellID) if balance.Cmp(targetBalance) != 0 { - t.Fatalf("Target %s balance is not correct. Expected %s, got %s", coin, targetBalance, balance) + t.Fatalf("Target %s balance is not correct. Expected %s, got %s", coinToSellID.String(), targetBalance, balance) } - baseBalance := cState.Accounts.GetBalance(addr, types.GetBaseCoin()) + baseBalance := cState.Accounts.GetBalance(addr, types.GetBaseCoinID()) if baseBalance.Cmp(toBuy) != 0 { - t.Fatalf("Target %s balance is not correct. Expected %s, got %s", types.GetBaseCoin(), toBuy, baseBalance) + t.Fatalf("Target %s balance is not correct. Expected %s, got %s", types.GetBaseCoinID(), toBuy, baseBalance) } - coinData := cState.Coins.GetCoin(coin) + coinData := cState.Coins.GetCoin(coinToSellID) targetReserve, _ := big.NewInt(0).SetString("99989900000000000000000", 10) if coinData.Reserve().Cmp(targetReserve) != 0 { - t.Fatalf("Target %s reserve is not correct. Expected %s, got %s", coin, targetBalance, coinData.Reserve()) + t.Fatalf("Target %s reserve is not correct. Expected %s, got %s", coinToSellID.String(), targetBalance, coinData.Reserve()) } targetVolume, _ := big.NewInt(0).SetString("99998989954092563427063", 10) if coinData.Volume().Cmp(targetVolume) != 0 { - t.Fatalf("Target %s volume is not correct. Expected %s, got %s", coin, targetVolume, coinData.Volume()) + t.Fatalf("Target %s volume is not correct. Expected %s, got %s", coinToSellID.String(), targetVolume, coinData.Volume()) } } func TestBuyCoinReserveUnderflow(t *testing.T) { cState := getState() - createTestCoin(cState) + coinToSellID := createTestCoin(cState) privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := getTestCoinSymbol() - cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(10000000))) + cState.Accounts.AddBalance(addr, coinToSellID, helpers.BipToPip(big.NewInt(10000000))) toBuy := helpers.BipToPip(big.NewInt(99000)) maxValToSell, _ := big.NewInt(0).SetString("36904896537720035723223", 10) data := BuyCoinData{ - CoinToBuy: types.GetBaseCoin(), + CoinToBuy: types.GetBaseCoinID(), ValueToBuy: toBuy, - CoinToSell: coin, + CoinToSell: coinToSellID, MaximumValueToSell: maxValToSell, } @@ -524,7 +531,7 @@ func TestBuyCoinReserveUnderflow(t *testing.T) { Nonce: 1, GasPrice: 1, ChainID: types.CurrentChainID, - GasCoin: coin, + GasCoin: coinToSellID, Type: TypeBuyCoin, Data: encodedData, SignatureType: SigTypeSingle, @@ -540,7 +547,7 @@ func TestBuyCoinReserveUnderflow(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) @@ -552,19 +559,19 @@ func TestBuyCoinTxBaseToCustomBaseCommission(t *testing.T) { // buy_coin: TEST // gas_coin: MNT - coinToSell := types.GetBaseCoin() + coinToSell := types.GetBaseCoinID() coinToBuy := types.StrToCoinSymbol("TEST") - gasCoin := types.GetBaseCoin() + gasCoin := types.GetBaseCoinID() initialBalance := helpers.BipToPip(big.NewInt(10000000)) toBuy := helpers.BipToPip(big.NewInt(100)) cState := getState() - initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToBuy) + coinToBuyID, initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToBuy) privateKey, addr := getAccount() cState.Accounts.AddBalance(addr, coinToSell, initialBalance) - tx := createBuyCoinTx(coinToSell, coinToBuy, gasCoin, toBuy, 1) + tx := createBuyCoinTx(coinToSell, coinToBuyID, gasCoin, toBuy, 1) if err := tx.Sign(privateKey); err != nil { t.Fatal(err) } @@ -575,13 +582,13 @@ func TestBuyCoinTxBaseToCustomBaseCommission(t *testing.T) { } // check response - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.OK { t.Fatalf("Response code is not 0. Error %s", response.Log) } // check received coins - buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuy) + buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuyID) if buyCoinBalance.Cmp(toBuy) != 0 { t.Fatalf("Buy coin balance is not correct") } @@ -596,7 +603,7 @@ func TestBuyCoinTxBaseToCustomBaseCommission(t *testing.T) { } // check reserve and supply - coinData := cState.Coins.GetCoin(coinToBuy) + coinData := cState.Coins.GetCoin(coinToBuyID) estimatedReserve := big.NewInt(0).Set(initialReserve) estimatedReserve.Add(estimatedReserve, formula.CalculatePurchaseAmount(initialVolume, initialReserve, crr, toBuy)) @@ -617,20 +624,20 @@ func TestBuyCoinTxCustomToBaseBaseCommission(t *testing.T) { // gas_coin: MNT coinToSell := types.StrToCoinSymbol("TEST") - coinToBuy := types.GetBaseCoin() - gasCoin := types.GetBaseCoin() + coinToBuy := types.GetBaseCoinID() + gasCoin := types.GetBaseCoinID() initialBalance := helpers.BipToPip(big.NewInt(10000000)) initialGasBalance, _ := big.NewInt(0).SetString("100000000000000000", 10) toBuy := helpers.BipToPip(big.NewInt(100)) cState := getState() - initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToSell) + coinToSellID, initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToSell) privateKey, addr := getAccount() - cState.Accounts.AddBalance(addr, coinToSell, initialBalance) + cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) cState.Accounts.AddBalance(addr, gasCoin, initialGasBalance) - tx := createBuyCoinTx(coinToSell, coinToBuy, gasCoin, toBuy, 1) + tx := createBuyCoinTx(coinToSellID, coinToBuy, gasCoin, toBuy, 1) if err := tx.Sign(privateKey); err != nil { t.Fatal(err) } @@ -641,7 +648,7 @@ func TestBuyCoinTxCustomToBaseBaseCommission(t *testing.T) { } // check response - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.OK { t.Fatalf("Response code is not 0. Error %s", response.Log) } @@ -653,7 +660,7 @@ func TestBuyCoinTxCustomToBaseBaseCommission(t *testing.T) { } // check sold coins - sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSell) + sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSellID) estimatedSellCoinBalance := big.NewInt(0).Set(initialBalance) estimatedSellCoinBalance.Sub(estimatedSellCoinBalance, formula.CalculateSaleAmount(initialVolume, initialReserve, crr, toBuy)) if sellCoinBalance.Cmp(estimatedSellCoinBalance) != 0 { @@ -661,7 +668,7 @@ func TestBuyCoinTxCustomToBaseBaseCommission(t *testing.T) { } // check reserve and supply - coinData := cState.Coins.GetCoin(coinToSell) + coinData := cState.Coins.GetCoin(coinToSellID) estimatedReserve := big.NewInt(0).Set(initialReserve) estimatedReserve.Sub(estimatedReserve, toBuy) @@ -683,21 +690,21 @@ func TestBuyCoinTxCustomToCustomBaseCommission(t *testing.T) { coinToSell := types.StrToCoinSymbol("TEST1") coinToBuy := types.StrToCoinSymbol("TEST12") - gasCoin := types.GetBaseCoin() + gasCoin := types.GetBaseCoinID() initialBalance := helpers.BipToPip(big.NewInt(10000000)) initialGasBalance, _ := big.NewInt(0).SetString("100000000000000000", 10) toBuy := helpers.BipToPip(big.NewInt(100)) cState := getState() - initialVolume1, initialReserve1, crr1 := createTestCoinWithSymbol(cState, coinToSell) - initialVolume2, initialReserve2, crr2 := createTestCoinWithSymbol(cState, coinToBuy) + coinToSellID, initialVolume1, initialReserve1, crr1 := createTestCoinWithSymbol(cState, coinToSell) + coinToBuyID, initialVolume2, initialReserve2, crr2 := createTestCoinWithSymbol(cState, coinToBuy) privateKey, addr := getAccount() - cState.Accounts.AddBalance(addr, coinToSell, initialBalance) + cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) cState.Accounts.AddBalance(addr, gasCoin, initialGasBalance) - tx := createBuyCoinTx(coinToSell, coinToBuy, gasCoin, toBuy, 1) + tx := createBuyCoinTx(coinToSellID, coinToBuyID, gasCoin, toBuy, 1) if err := tx.Sign(privateKey); err != nil { t.Fatal(err) } @@ -708,19 +715,19 @@ func TestBuyCoinTxCustomToCustomBaseCommission(t *testing.T) { } // check response - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.OK { t.Fatalf("Response code is not 0. Error %s", response.Log) } // check received coins - buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuy) + buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuyID) if buyCoinBalance.Cmp(toBuy) != 0 { t.Fatalf("Buy coin balance is not correct") } // check sold coins - sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSell) + sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSellID) estimatedSellCoinBalance := big.NewInt(0).Set(initialBalance) toSellBaseCoin := formula.CalculatePurchaseAmount(initialVolume2, initialReserve2, crr2, toBuy) toSell := formula.CalculateSaleAmount(initialVolume1, initialReserve1, crr1, toSellBaseCoin) @@ -730,7 +737,7 @@ func TestBuyCoinTxCustomToCustomBaseCommission(t *testing.T) { } // check reserve and supply - coinData := cState.Coins.GetCoin(coinToSell) + coinData := cState.Coins.GetCoin(coinToSellID) estimatedReserve := big.NewInt(0).Set(initialReserve1) estimatedReserve.Sub(estimatedReserve, formula.CalculatePurchaseAmount(initialVolume2, initialReserve2, crr2, toBuy)) @@ -750,21 +757,20 @@ func TestBuyCoinTxBaseToCustomCustomCommission(t *testing.T) { // buy_coin: TEST // gas_coin: TEST - coinToSell := types.GetBaseCoin() + coinToSell := types.GetBaseCoinID() coinToBuy := types.StrToCoinSymbol("TEST") - gasCoin := types.StrToCoinSymbol("TEST") initialBalance := helpers.BipToPip(big.NewInt(10000000)) initialGasBalance := helpers.BipToPip(big.NewInt(1)) toBuy := helpers.BipToPip(big.NewInt(100)) cState := getState() - initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToBuy) + coinToBuyID, initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToBuy) privateKey, addr := getAccount() cState.Accounts.AddBalance(addr, coinToSell, initialBalance) - cState.Accounts.AddBalance(addr, gasCoin, initialGasBalance) + cState.Accounts.AddBalance(addr, coinToBuyID, initialGasBalance) - tx := createBuyCoinTx(coinToSell, coinToBuy, gasCoin, toBuy, 1) + tx := createBuyCoinTx(coinToSell, coinToBuyID, coinToBuyID, toBuy, 1) if err := tx.Sign(privateKey); err != nil { t.Fatal(err) } @@ -775,13 +781,13 @@ func TestBuyCoinTxBaseToCustomCustomCommission(t *testing.T) { } // check response - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.OK { t.Fatalf("Response code is not 0. Error %s", response.Log) } // check received coins + commission - buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuy) + buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuyID) estimatedBuyCoinBalance := big.NewInt(0).Set(toBuy) estimatedBuyCoinBalance.Add(estimatedBuyCoinBalance, initialGasBalance) toReserve := formula.CalculatePurchaseAmount(initialVolume, initialReserve, crr, toBuy) @@ -800,7 +806,7 @@ func TestBuyCoinTxBaseToCustomCustomCommission(t *testing.T) { } // check reserve and supply - coinData := cState.Coins.GetCoin(coinToBuy) + coinData := cState.Coins.GetCoin(coinToBuyID) estimatedReserve := big.NewInt(0).Set(initialReserve) estimatedReserve.Add(estimatedReserve, formula.CalculatePurchaseAmount(initialVolume, initialReserve, crr, toBuy)) @@ -823,18 +829,17 @@ func TestBuyCoinTxCustomToBaseCustomCommission(t *testing.T) { // gas_coin: TEST coinToSell := types.StrToCoinSymbol("TEST") - coinToBuy := types.GetBaseCoin() - gasCoin := types.StrToCoinSymbol("TEST") + coinToBuy := types.GetBaseCoinID() initialBalance := helpers.BipToPip(big.NewInt(10000000)) toBuy := helpers.BipToPip(big.NewInt(100)) cState := getState() - initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToSell) + coinToSellID, initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToSell) privateKey, addr := getAccount() - cState.Accounts.AddBalance(addr, coinToSell, initialBalance) + cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) - tx := createBuyCoinTx(coinToSell, coinToBuy, gasCoin, toBuy, 1) + tx := createBuyCoinTx(coinToSellID, coinToBuy, coinToSellID, toBuy, 1) if err := tx.Sign(privateKey); err != nil { t.Fatal(err) } @@ -845,7 +850,7 @@ func TestBuyCoinTxCustomToBaseCustomCommission(t *testing.T) { } // check response - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.OK { t.Fatalf("Response code is not 0. Error %s", response.Log) } @@ -857,7 +862,7 @@ func TestBuyCoinTxCustomToBaseCustomCommission(t *testing.T) { } // check sold coins - sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSell) + sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSellID) estimatedSellCoinBalance := big.NewInt(0).Set(initialBalance) shouldGive := formula.CalculateSaleAmount(initialVolume, initialReserve, crr, big.NewInt(0).Add(toBuy, tx.CommissionInBaseCoin())) estimatedSellCoinBalance.Sub(estimatedSellCoinBalance, shouldGive) @@ -867,7 +872,7 @@ func TestBuyCoinTxCustomToBaseCustomCommission(t *testing.T) { // check reserve and supply { - coinData := cState.Coins.GetCoin(coinToSell) + coinData := cState.Coins.GetCoin(coinToSellID) estimatedReserve := big.NewInt(0).Set(initialReserve) estimatedReserve.Sub(estimatedReserve, toBuy) @@ -892,18 +897,17 @@ func TestBuyCoinTxCustomToCustomCustom1Commission(t *testing.T) { coinToSell := types.StrToCoinSymbol("TEST1") coinToBuy := types.StrToCoinSymbol("TEST2") - gasCoin := types.StrToCoinSymbol("TEST1") initialBalance := helpers.BipToPip(big.NewInt(10000000)) toBuy := helpers.BipToPip(big.NewInt(100)) cState := getState() - initialVolume1, initialReserve1, crr1 := createTestCoinWithSymbol(cState, coinToSell) - initialVolume2, initialReserve2, crr2 := createTestCoinWithSymbol(cState, coinToBuy) + coinToSellID, initialVolume1, initialReserve1, crr1 := createTestCoinWithSymbol(cState, coinToSell) + coinToBuyID, initialVolume2, initialReserve2, crr2 := createTestCoinWithSymbol(cState, coinToBuy) privateKey, addr := getAccount() - cState.Accounts.AddBalance(addr, coinToSell, initialBalance) + cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) - tx := createBuyCoinTx(coinToSell, coinToBuy, gasCoin, toBuy, 1) + tx := createBuyCoinTx(coinToSellID, coinToBuyID, coinToSellID, toBuy, 1) if err := tx.Sign(privateKey); err != nil { t.Fatal(err) } @@ -914,19 +918,19 @@ func TestBuyCoinTxCustomToCustomCustom1Commission(t *testing.T) { } // check response - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.OK { t.Fatalf("Response code is not 0. Error %s", response.Log) } // check received coins - buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuy) + buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuyID) if buyCoinBalance.Cmp(toBuy) != 0 { t.Fatalf("Buy coin balance is not correct") } // check sold coins - sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSell) + sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSellID) estimatedSellCoinBalance := big.NewInt(0).Set(initialBalance) toSellBaseCoin := formula.CalculatePurchaseAmount(initialVolume2, initialReserve2, crr2, toBuy) toSell := formula.CalculateSaleAmount(initialVolume1, initialReserve1, crr1, toSellBaseCoin) @@ -939,7 +943,7 @@ func TestBuyCoinTxCustomToCustomCustom1Commission(t *testing.T) { // check reserve and supply { - coinData := cState.Coins.GetCoin(coinToSell) + coinData := cState.Coins.GetCoin(coinToSellID) estimatedReserve := big.NewInt(0).Set(initialReserve1) estimatedReserve.Sub(estimatedReserve, formula.CalculatePurchaseAmount(initialVolume2, initialReserve2, crr2, toBuy)) @@ -957,7 +961,7 @@ func TestBuyCoinTxCustomToCustomCustom1Commission(t *testing.T) { } { - coinData := cState.Coins.GetCoin(coinToBuy) + coinData := cState.Coins.GetCoin(coinToBuyID) estimatedReserve := big.NewInt(0).Set(initialReserve2) estimatedReserve.Add(estimatedReserve, formula.CalculatePurchaseAmount(initialVolume2, initialReserve2, crr2, toBuy)) @@ -980,20 +984,19 @@ func TestBuyCoinTxCustomToCustomCustom2Commission(t *testing.T) { coinToSell := types.StrToCoinSymbol("TEST1") coinToBuy := types.StrToCoinSymbol("TEST2") - gasCoin := types.StrToCoinSymbol("TEST2") initialBalance := helpers.BipToPip(big.NewInt(10000000)) initialGasBalance := helpers.BipToPip(big.NewInt(1)) toBuy := helpers.BipToPip(big.NewInt(100)) cState := getState() - initialVolume1, initialReserve1, crr1 := createTestCoinWithSymbol(cState, coinToSell) - initialVolume2, initialReserve2, crr2 := createTestCoinWithSymbol(cState, coinToBuy) + coinToSellID, initialVolume1, initialReserve1, crr1 := createTestCoinWithSymbol(cState, coinToSell) + coinToBuyID, initialVolume2, initialReserve2, crr2 := createTestCoinWithSymbol(cState, coinToBuy) privateKey, addr := getAccount() - cState.Accounts.AddBalance(addr, coinToSell, initialBalance) - cState.Accounts.AddBalance(addr, gasCoin, initialGasBalance) + cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) + cState.Accounts.AddBalance(addr, coinToBuyID, initialGasBalance) - tx := createBuyCoinTx(coinToSell, coinToBuy, gasCoin, toBuy, 1) + tx := createBuyCoinTx(coinToSellID, coinToBuyID, coinToBuyID, toBuy, 1) if err := tx.Sign(privateKey); err != nil { t.Fatal(err) } @@ -1004,13 +1007,13 @@ func TestBuyCoinTxCustomToCustomCustom2Commission(t *testing.T) { } // check response - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.OK { t.Fatalf("Response code is not 0. Error %s", response.Log) } // check received coins - buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuy) + buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuyID) buyCoinBalance.Sub(buyCoinBalance, initialGasBalance) toReserve := formula.CalculatePurchaseAmount(initialVolume2, initialReserve2, crr2, toBuy) commission := formula.CalculateSaleAmount(big.NewInt(0).Add(initialVolume2, toBuy), big.NewInt(0).Add(initialReserve2, toReserve), crr2, tx.CommissionInBaseCoin()) @@ -1020,7 +1023,7 @@ func TestBuyCoinTxCustomToCustomCustom2Commission(t *testing.T) { } // check sold coins - sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSell) + sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSellID) estimatedSellCoinBalance := big.NewInt(0).Set(initialBalance) toSellBaseCoin := formula.CalculatePurchaseAmount(initialVolume2, initialReserve2, crr2, toBuy) toSell := formula.CalculateSaleAmount(initialVolume1, initialReserve1, crr1, toSellBaseCoin) @@ -1031,7 +1034,7 @@ func TestBuyCoinTxCustomToCustomCustom2Commission(t *testing.T) { // check reserve and supply { - coinData := cState.Coins.GetCoin(coinToSell) + coinData := cState.Coins.GetCoin(coinToSellID) estimatedReserve := big.NewInt(0).Set(initialReserve1) estimatedReserve.Sub(estimatedReserve, formula.CalculatePurchaseAmount(initialVolume2, initialReserve2, crr2, toBuy)) @@ -1047,7 +1050,7 @@ func TestBuyCoinTxCustomToCustomCustom2Commission(t *testing.T) { } { - coinData := cState.Coins.GetCoin(coinToBuy) + coinData := cState.Coins.GetCoin(coinToBuyID) estimatedReserve := big.NewInt(0).Set(initialReserve2) estimatedReserve.Add(estimatedReserve, formula.CalculatePurchaseAmount(initialVolume2, initialReserve2, crr2, toBuy)) @@ -1065,7 +1068,7 @@ func TestBuyCoinTxCustomToCustomCustom2Commission(t *testing.T) { } } -func createBuyCoinTx(sellCoin, buyCoin, gasCoin types.CoinSymbol, valueToBuy *big.Int, nonce uint64) *Transaction { +func createBuyCoinTx(sellCoin, buyCoin, gasCoin types.CoinID, valueToBuy *big.Int, nonce uint64) *Transaction { maxValToSell, _ := big.NewInt(0).SetString("100000000000000000000000000000", 10) data := BuyCoinData{ CoinToBuy: buyCoin, @@ -1100,7 +1103,7 @@ func getAccount() (*ecdsa.PrivateKey, types.Address) { return privateKey, addr } -func createTestCoinWithSymbol(stateDB *state.State, symbol types.CoinSymbol) (*big.Int, *big.Int, uint) { +func createTestCoinWithSymbol(stateDB *state.State, symbol types.CoinSymbol) (types.CoinID, *big.Int, *big.Int, uint) { volume := helpers.BipToPip(big.NewInt(100000)) reserve := helpers.BipToPip(big.NewInt(100000)) volume.Mul(volume, big.NewInt(int64(rnd.Intn(9))+1)) @@ -1108,7 +1111,9 @@ func createTestCoinWithSymbol(stateDB *state.State, symbol types.CoinSymbol) (*b crr := uint(10 + rnd.Intn(90)) - stateDB.Coins.Create(symbol, "TEST COIN", volume, crr, reserve, big.NewInt(0).Mul(volume, big.NewInt(10))) + id := stateDB.App.GetNextCoinID() + stateDB.Coins.Create(id, symbol, "TEST COIN", volume, crr, reserve, big.NewInt(0).Mul(volume, big.NewInt(10)), nil) + stateDB.App.SetCoinsCount(id.Uint32()) - return big.NewInt(0).Set(volume), big.NewInt(0).Set(reserve), crr + return id, big.NewInt(0).Set(volume), big.NewInt(0).Set(reserve), crr } diff --git a/core/transaction/create_coin_test.go b/core/transaction/create_coin_test.go index dc1249d1d..124bc4d67 100644 --- a/core/transaction/create_coin_test.go +++ b/core/transaction/create_coin_test.go @@ -15,13 +15,11 @@ func TestCreateCoinTx(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) - var toCreate types.CoinSymbol - copy(toCreate[:], []byte("ABCDEF")) - + toCreate := types.StrToCoinSymbol("ABCDEF") reserve := helpers.BipToPip(big.NewInt(10000)) amount := helpers.BipToPip(big.NewInt(100)) crr := uint(50) @@ -29,7 +27,7 @@ func TestCreateCoinTx(t *testing.T) { data := CreateCoinData{ Name: name, - Symbol: toCreate, + Symbol: types.StrToCoinSymbol("ABCDEF"), InitialAmount: amount, InitialReserve: reserve, ConstantReserveRatio: crr, @@ -62,19 +60,23 @@ func TestCreateCoinTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) - + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) } + err = cState.Coins.Commit() + if err != nil { + t.Fatalf("Commit coins failed. Error %s", err) + } + targetBalance, _ := big.NewInt(0).SetString("989000000000000000000000", 10) balance := cState.Accounts.GetBalance(addr, coin) if balance.Cmp(targetBalance) != 0 { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", coin, targetBalance, balance) } - stateCoin := cState.Coins.GetCoin(toCreate) + stateCoin := cState.Coins.GetCoinBySymbol(toCreate) if stateCoin == nil { t.Fatalf("Coin %s not found in state", toCreate) diff --git a/core/transaction/create_multisig_test.go b/core/transaction/create_multisig_test.go index b00c135b4..7cf19e219 100644 --- a/core/transaction/create_multisig_test.go +++ b/core/transaction/create_multisig_test.go @@ -22,7 +22,7 @@ func TestCreateMultisigTx(t *testing.T) { privateKey2, _ := crypto.GenerateKey() addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) @@ -65,7 +65,7 @@ func TestCreateMultisigTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) @@ -115,7 +115,7 @@ func TestCreateMultisigFromExistingAccountTx(t *testing.T) { privateKey2, _ := crypto.GenerateKey() addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) @@ -139,7 +139,7 @@ func TestCreateMultisigFromExistingAccountTx(t *testing.T) { }).Address() initialBalance := big.NewInt(10) - cState.Accounts.AddBalance(msigAddr, types.GetBaseCoin(), initialBalance) + cState.Accounts.AddBalance(msigAddr, types.GetBaseCoinID(), initialBalance) encodedData, err := rlp.EncodeToBytes(data) if err != nil { @@ -166,7 +166,7 @@ func TestCreateMultisigFromExistingAccountTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) @@ -206,7 +206,7 @@ func TestCreateMultisigFromExistingAccountTx(t *testing.T) { t.Fatalf("Threshold is not correct") } - if cState.Accounts.GetBalance(msigAddr, types.GetBaseCoin()).Cmp(initialBalance) != 0 { + if cState.Accounts.GetBalance(msigAddr, types.GetBaseCoinID()).Cmp(initialBalance) != 0 { t.Fatalf("Msig balance was not persisted") } } @@ -220,7 +220,7 @@ func TestCreateExistingMultisigTx(t *testing.T) { privateKey2, _ := crypto.GenerateKey() addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) @@ -260,7 +260,7 @@ func TestCreateExistingMultisigTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.MultisigExists { t.Fatalf("Response code is not %d. Got %d", code.MultisigExists, response.Code) diff --git a/core/transaction/declare_candidacy_test.go b/core/transaction/declare_candidacy_test.go index f522db515..e3a732034 100644 --- a/core/transaction/declare_candidacy_test.go +++ b/core/transaction/declare_candidacy_test.go @@ -20,7 +20,7 @@ func TestDeclareCandidacyTx(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) @@ -65,7 +65,7 @@ func TestDeclareCandidacyTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) @@ -110,8 +110,8 @@ func TestDeclareCandidacyTxOverflow(t *testing.T) { for i := 0; i < maxCandidatesCount; i++ { pubkey := types.Pubkey{byte(i)} - cState.Candidates.Create(types.Address{}, types.Address{}, pubkey, 10) - cState.Candidates.Delegate(types.Address{}, pubkey, types.GetBaseCoin(), helpers.BipToPip(big.NewInt(10)), helpers.BipToPip(big.NewInt(10))) + cState.Candidates.Create(types.Address{}, types.Address{}, types.Address{}, pubkey, 10) + cState.Candidates.Delegate(types.Address{}, pubkey, types.GetBaseCoinID(), helpers.BipToPip(big.NewInt(10)), helpers.BipToPip(big.NewInt(10))) } cState.Candidates.RecalculateStakes(upgrades.UpgradeBlock3) @@ -119,7 +119,7 @@ func TestDeclareCandidacyTxOverflow(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) @@ -162,7 +162,7 @@ func TestDeclareCandidacyTxOverflow(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.TooLowStake { t.Fatalf("Response code is not %d. Got %d", code.TooLowStake, response.Code) diff --git a/core/transaction/delegate_test.go b/core/transaction/delegate_test.go index 09036d299..f5273088a 100644 --- a/core/transaction/delegate_test.go +++ b/core/transaction/delegate_test.go @@ -18,7 +18,7 @@ func createTestCandidate(stateDB *state.State) types.Pubkey { pubkey := types.Pubkey{} rand.Read(pubkey[:]) - stateDB.Candidates.Create(address, address, pubkey, 10) + stateDB.Candidates.Create(address, address, address, pubkey, 10) return pubkey } @@ -31,7 +31,7 @@ func TestDelegateTx(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) @@ -69,7 +69,7 @@ func TestDelegateTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) diff --git a/core/transaction/edit_candidate_test.go b/core/transaction/edit_candidate_test.go index 0f5523395..8bb084279 100644 --- a/core/transaction/edit_candidate_test.go +++ b/core/transaction/edit_candidate_test.go @@ -16,13 +16,13 @@ func TestEditCandidateTx(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) pubkey := [32]byte{} rand.Read(pubkey[:]) - cState.Candidates.Create(addr, addr, pubkey, 10) + cState.Candidates.Create(addr, addr, addr, pubkey, 10) cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) newRewardAddress := types.Address{1} @@ -60,7 +60,7 @@ func TestEditCandidateTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) diff --git a/core/transaction/executor_test.go b/core/transaction/executor_test.go index 5c473d4ae..c68c39f88 100644 --- a/core/transaction/executor_test.go +++ b/core/transaction/executor_test.go @@ -15,7 +15,7 @@ import ( func TestTooLongTx(t *testing.T) { fakeTx := make([]byte, 10000) - response := RunTx(getState(), false, fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(getState(), fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.TxTooLarge { t.Fatalf("Response code is not correct") @@ -26,7 +26,7 @@ func TestIncorrectTx(t *testing.T) { fakeTx := make([]byte, 1) rand.Read(fakeTx) - response := RunTx(getState(), false, fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(getState(), fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.DecodeError { t.Fatalf("Response code is not correct") @@ -38,7 +38,7 @@ func TestTooLongPayloadTx(t *testing.T) { rand.Read(payload) txData := SendData{ - Coin: types.GetBaseCoin(), + Coin: types.GetBaseCoinID(), To: types.Address{}, Value: big.NewInt(1), } @@ -48,7 +48,7 @@ func TestTooLongPayloadTx(t *testing.T) { Nonce: 1, GasPrice: 1, ChainID: types.CurrentChainID, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), Type: TypeSend, Data: encodedData, Payload: payload, @@ -66,7 +66,7 @@ func TestTooLongPayloadTx(t *testing.T) { fakeTx, _ := rlp.EncodeToBytes(tx) - response := RunTx(getState(), false, fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(getState(), fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.TxPayloadTooLarge { t.Fatalf("Response code is not correct. Expected %d, got %d", code.TxPayloadTooLarge, response.Code) @@ -78,7 +78,7 @@ func TestTooLongServiceDataTx(t *testing.T) { rand.Read(serviceData) txData := SendData{ - Coin: types.GetBaseCoin(), + Coin: types.GetBaseCoinID(), To: types.Address{}, Value: big.NewInt(1), } @@ -88,7 +88,7 @@ func TestTooLongServiceDataTx(t *testing.T) { Nonce: 1, GasPrice: 1, ChainID: types.CurrentChainID, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), Type: TypeSend, Data: encodedData, ServiceData: serviceData, @@ -105,7 +105,7 @@ func TestTooLongServiceDataTx(t *testing.T) { fakeTx, _ := rlp.EncodeToBytes(tx) - response := RunTx(getState(), false, fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(getState(), fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.TxServiceDataTooLarge { t.Fatalf("Response code is not correct. Expected %d, got %d", code.TxServiceDataTooLarge, response.Code) @@ -114,7 +114,7 @@ func TestTooLongServiceDataTx(t *testing.T) { func TestUnexpectedNonceTx(t *testing.T) { txData := SendData{ - Coin: types.GetBaseCoin(), + Coin: types.GetBaseCoinID(), To: types.Address{}, Value: big.NewInt(1), } @@ -124,7 +124,7 @@ func TestUnexpectedNonceTx(t *testing.T) { Nonce: 2, GasPrice: 1, ChainID: types.CurrentChainID, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), Type: TypeSend, Data: encodedData, SignatureType: SigTypeSingle, @@ -140,7 +140,7 @@ func TestUnexpectedNonceTx(t *testing.T) { fakeTx, _ := rlp.EncodeToBytes(tx) - response := RunTx(getState(), false, fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(getState(), fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.WrongNonce { t.Fatalf("Response code is not correct. Expected %d, got %d", code.WrongNonce, response.Code) @@ -149,7 +149,7 @@ func TestUnexpectedNonceTx(t *testing.T) { func TestInvalidSigTx(t *testing.T) { txData := SendData{ - Coin: types.GetBaseCoin(), + Coin: types.GetBaseCoinID(), To: types.Address{}, Value: big.NewInt(1), } @@ -158,7 +158,7 @@ func TestInvalidSigTx(t *testing.T) { tx := Transaction{ Nonce: 1, GasPrice: 1, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), ChainID: types.CurrentChainID, Type: TypeSend, Data: encodedData, @@ -178,7 +178,7 @@ func TestInvalidSigTx(t *testing.T) { fakeTx, _ := rlp.EncodeToBytes(tx) - response := RunTx(getState(), false, fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(getState(), fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.DecodeError { t.Fatalf("Response code is not correct. Expected %d, got %d", code.DecodeError, response.Code) @@ -187,7 +187,7 @@ func TestInvalidSigTx(t *testing.T) { func TestNotExistMultiSigTx(t *testing.T) { txData := SendData{ - Coin: types.GetBaseCoin(), + Coin: types.GetBaseCoinID(), To: types.Address{}, Value: big.NewInt(1), } @@ -196,7 +196,7 @@ func TestNotExistMultiSigTx(t *testing.T) { tx := Transaction{ Nonce: 1, GasPrice: 1, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), Type: TypeSend, ChainID: types.CurrentChainID, Data: encodedData, @@ -217,7 +217,7 @@ func TestNotExistMultiSigTx(t *testing.T) { fakeTx, _ := rlp.EncodeToBytes(tx) - response := RunTx(getState(), false, fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(getState(), fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.MultisigNotExists { t.Fatalf("Response code is not correct. Expected %d, got %d", code.MultisigNotExists, response.Code) @@ -229,13 +229,13 @@ func TestMultiSigTx(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() msigAddress := cState.Accounts.CreateMultisig([]uint{1}, []types.Address{addr}, 1, 1) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ - Coin: types.GetBaseCoin(), + Coin: types.GetBaseCoinID(), To: types.Address{}, Value: big.NewInt(1), } @@ -244,7 +244,7 @@ func TestMultiSigTx(t *testing.T) { tx := Transaction{ Nonce: 1, GasPrice: 1, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), ChainID: types.CurrentChainID, Type: TypeSend, Data: encodedData, @@ -261,7 +261,7 @@ func TestMultiSigTx(t *testing.T) { txBytes, _ := rlp.EncodeToBytes(tx) - response := RunTx(cState, false, txBytes, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, txBytes, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Error code is not 0. Error: %s", response.Log) @@ -273,13 +273,13 @@ func TestMultiSigDoubleSignTx(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() msigAddress := cState.Accounts.CreateMultisig([]uint{1, 1}, []types.Address{addr, {}}, 2, 1) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ - Coin: types.GetBaseCoin(), + Coin: types.GetBaseCoinID(), To: types.Address{}, Value: big.NewInt(1), } @@ -288,7 +288,7 @@ func TestMultiSigDoubleSignTx(t *testing.T) { tx := Transaction{ Nonce: 1, GasPrice: 1, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), Type: TypeSend, ChainID: types.CurrentChainID, Data: encodedData, @@ -309,7 +309,7 @@ func TestMultiSigDoubleSignTx(t *testing.T) { txBytes, _ := rlp.EncodeToBytes(tx) - response := RunTx(cState, false, txBytes, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, txBytes, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.IncorrectMultiSignature { t.Fatalf("Error code is not %d, got %d", code.IncorrectMultiSignature, response.Code) @@ -321,13 +321,13 @@ func TestMultiSigTooManySignsTx(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() msigAddress := cState.Accounts.CreateMultisig([]uint{1, 1}, []types.Address{addr, {}}, 2, 1) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ - Coin: types.GetBaseCoin(), + Coin: types.GetBaseCoinID(), To: types.Address{}, Value: big.NewInt(1), } @@ -336,7 +336,7 @@ func TestMultiSigTooManySignsTx(t *testing.T) { tx := Transaction{ Nonce: 1, GasPrice: 1, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), ChainID: types.CurrentChainID, Type: TypeSend, Data: encodedData, @@ -360,7 +360,7 @@ func TestMultiSigTooManySignsTx(t *testing.T) { txBytes, _ := rlp.EncodeToBytes(tx) - response := RunTx(cState, false, txBytes, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, txBytes, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.IncorrectMultiSignature { t.Fatalf("Error code is not %d, got %d", code.IncorrectMultiSignature, response.Code) @@ -372,13 +372,13 @@ func TestMultiSigNotEnoughTx(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() msigAddress := cState.Accounts.CreateMultisig([]uint{1}, []types.Address{addr}, 2, 1) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ - Coin: types.GetBaseCoin(), + Coin: types.GetBaseCoinID(), To: types.Address{}, Value: big.NewInt(1), } @@ -388,7 +388,7 @@ func TestMultiSigNotEnoughTx(t *testing.T) { Nonce: 1, GasPrice: 1, ChainID: types.CurrentChainID, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), Type: TypeSend, Data: encodedData, SignatureType: SigTypeMulti, @@ -404,7 +404,7 @@ func TestMultiSigNotEnoughTx(t *testing.T) { txBytes, _ := rlp.EncodeToBytes(tx) - response := RunTx(cState, false, txBytes, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, txBytes, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.IncorrectMultiSignature { t.Fatalf("Error code is not %d. Error: %d", code.IncorrectMultiSignature, response.Code) @@ -416,13 +416,13 @@ func TestMultiSigIncorrectSignsTx(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() msigAddress := cState.Accounts.CreateMultisig([]uint{1}, []types.Address{addr}, 1, 1) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ - Coin: types.GetBaseCoin(), + Coin: types.GetBaseCoinID(), To: types.Address{}, Value: big.NewInt(1), } @@ -432,7 +432,7 @@ func TestMultiSigIncorrectSignsTx(t *testing.T) { Nonce: 1, GasPrice: 1, ChainID: types.CurrentChainID, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), Type: TypeSend, Data: encodedData, SignatureType: SigTypeMulti, @@ -449,7 +449,7 @@ func TestMultiSigIncorrectSignsTx(t *testing.T) { txBytes, _ := rlp.EncodeToBytes(tx) - response := RunTx(cState, false, txBytes, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, txBytes, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.IncorrectMultiSignature { t.Fatalf("Error code is not %d, got %d", code.IncorrectMultiSignature, response.Code) diff --git a/core/transaction/multisend_test.go b/core/transaction/multisend_test.go index d0f7579d2..4baef31ba 100644 --- a/core/transaction/multisend_test.go +++ b/core/transaction/multisend_test.go @@ -15,7 +15,7 @@ func TestMultisendTx(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) @@ -58,7 +58,7 @@ func TestMultisendTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error: %s", response.Log) diff --git a/core/transaction/redeem_check_test.go b/core/transaction/redeem_check_test.go index fcbc4fb10..d1039e6dc 100644 --- a/core/transaction/redeem_check_test.go +++ b/core/transaction/redeem_check_test.go @@ -15,7 +15,7 @@ import ( func TestRedeemCheckTx(t *testing.T) { cState := getState() - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() senderPrivateKey, _ := crypto.GenerateKey() senderAddr := crypto.PubkeyToAddress(senderPrivateKey.PublicKey) @@ -40,7 +40,7 @@ func TestRedeemCheckTx(t *testing.T) { DueBlock: 1, Coin: coin, Value: checkValue, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), } lock, err := crypto.Sign(check.HashWithoutLock().Bytes(), passphrasePk) @@ -105,7 +105,7 @@ func TestRedeemCheckTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) diff --git a/core/transaction/sell_all_coin_test.go b/core/transaction/sell_all_coin_test.go index 0930828fc..cac8e7956 100644 --- a/core/transaction/sell_all_coin_test.go +++ b/core/transaction/sell_all_coin_test.go @@ -13,18 +13,18 @@ import ( func TestSellAllCoinTx(t *testing.T) { cState := getState() - createTestCoin(cState) + coinID := createTestCoin(cState) privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) minValToBuy, _ := big.NewInt(0).SetString("151191152412701306252", 10) data := SellAllCoinData{ CoinToSell: coin, - CoinToBuy: getTestCoinSymbol(), + CoinToBuy: coinID, MinimumValueToBuy: minValToBuy, } @@ -54,7 +54,7 @@ func TestSellAllCoinTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) @@ -66,7 +66,7 @@ func TestSellAllCoinTx(t *testing.T) { } targetTestBalance, _ := big.NewInt(0).SetString("27098160365576186275223", 10) - testBalance := cState.Accounts.GetBalance(addr, getTestCoinSymbol()) + testBalance := cState.Accounts.GetBalance(addr, coinID) if testBalance.Cmp(targetTestBalance) != 0 { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", getTestCoinSymbol(), targetTestBalance, testBalance) } diff --git a/core/transaction/sell_coin_test.go b/core/transaction/sell_coin_test.go index a227dcb7b..922e9e377 100644 --- a/core/transaction/sell_coin_test.go +++ b/core/transaction/sell_coin_test.go @@ -15,11 +15,11 @@ import ( func TestSellCoinTx(t *testing.T) { cState := getState() - createTestCoin(cState) + buyCoinID := createTestCoin(cState) privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) @@ -27,7 +27,7 @@ func TestSellCoinTx(t *testing.T) { data := SellCoinData{ CoinToSell: coin, ValueToSell: helpers.BipToPip(big.NewInt(10)), - CoinToBuy: getTestCoinSymbol(), + CoinToBuy: buyCoinID, MinimumValueToBuy: minValToBuy, } @@ -57,7 +57,7 @@ func TestSellCoinTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error: %s", response.Log) @@ -70,7 +70,7 @@ func TestSellCoinTx(t *testing.T) { } targetTestBalance, _ := big.NewInt(0).SetString("999955002849793446", 10) - testBalance := cState.Accounts.GetBalance(addr, getTestCoinSymbol()) + testBalance := cState.Accounts.GetBalance(addr, buyCoinID) if testBalance.Cmp(targetTestBalance) != 0 { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", getTestCoinSymbol(), targetTestBalance, testBalance) } @@ -80,20 +80,20 @@ func TestSellCoinTxBaseToCustomBaseCommission(t *testing.T) { // sell_coin: MNT // buy_coin: TEST // gas_coin: MNT + cState := getState() - coinToSell := types.GetBaseCoin() + coinToSell := types.GetBaseCoinID() coinToBuy := types.StrToCoinSymbol("TEST") - gasCoin := types.GetBaseCoin() + gasCoin := types.GetBaseCoinID() initialBalance := helpers.BipToPip(big.NewInt(10000000)) toSell := helpers.BipToPip(big.NewInt(100)) - cState := getState() - initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToBuy) + coinToBuyID, initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToBuy) privateKey, addr := getAccount() cState.Accounts.AddBalance(addr, coinToSell, initialBalance) - tx := createSellCoinTx(coinToSell, coinToBuy, gasCoin, toSell, 1) + tx := createSellCoinTx(coinToSell, coinToBuyID, gasCoin, toSell, 1) if err := tx.Sign(privateKey); err != nil { t.Fatal(err) } @@ -104,13 +104,13 @@ func TestSellCoinTxBaseToCustomBaseCommission(t *testing.T) { } // check response - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.OK { t.Fatalf("Response code is not 0. Error %s", response.Log) } // check received coins - buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuy) + buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuyID) estimatedBuyBalance := formula.CalculatePurchaseReturn(initialVolume, initialReserve, crr, toSell) if buyCoinBalance.Cmp(estimatedBuyBalance) != 0 { t.Fatalf("Buy coin balance is not correct. Expected %s, got %s", estimatedBuyBalance.String(), buyCoinBalance.String()) @@ -126,7 +126,7 @@ func TestSellCoinTxBaseToCustomBaseCommission(t *testing.T) { } // check reserve and supply - coinData := cState.Coins.GetCoin(coinToBuy) + coinData := cState.Coins.GetCoin(coinToBuyID) estimatedReserve := big.NewInt(0).Set(initialReserve) estimatedReserve.Add(estimatedReserve, toSell) @@ -147,20 +147,20 @@ func TestSellCoinTxCustomToBaseBaseCommission(t *testing.T) { // gas_coin: MNT coinToSell := types.StrToCoinSymbol("TEST") - coinToBuy := types.GetBaseCoin() - gasCoin := types.GetBaseCoin() + coinToBuy := types.GetBaseCoinID() + gasCoin := types.GetBaseCoinID() initialBalance := helpers.BipToPip(big.NewInt(10000000)) initialGasBalance := helpers.BipToPip(big.NewInt(1)) toSell := helpers.BipToPip(big.NewInt(100)) cState := getState() - initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToSell) + coinToSellID, initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToSell) privateKey, addr := getAccount() - cState.Accounts.AddBalance(addr, coinToSell, initialBalance) + cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) cState.Accounts.AddBalance(addr, gasCoin, initialGasBalance) - tx := createSellCoinTx(coinToSell, coinToBuy, gasCoin, toSell, 1) + tx := createSellCoinTx(coinToSellID, coinToBuy, gasCoin, toSell, 1) if err := tx.Sign(privateKey); err != nil { t.Fatal(err) } @@ -171,7 +171,7 @@ func TestSellCoinTxCustomToBaseBaseCommission(t *testing.T) { } // check response - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.OK { t.Fatalf("Response code is not 0. Error %s", response.Log) } @@ -186,7 +186,7 @@ func TestSellCoinTxCustomToBaseBaseCommission(t *testing.T) { } // check sold coins - sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSell) + sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSellID) estimatedSellCoinBalance := big.NewInt(0).Set(initialBalance) estimatedSellCoinBalance.Sub(estimatedSellCoinBalance, toSell) if sellCoinBalance.Cmp(estimatedSellCoinBalance) != 0 { @@ -194,7 +194,7 @@ func TestSellCoinTxCustomToBaseBaseCommission(t *testing.T) { } // check reserve and supply - coinData := cState.Coins.GetCoin(coinToSell) + coinData := cState.Coins.GetCoin(coinToSellID) estimatedReserve := big.NewInt(0).Set(initialReserve) estimatedReserve.Sub(estimatedReserve, formula.CalculateSaleReturn(initialVolume, initialReserve, crr, toSell)) @@ -216,20 +216,20 @@ func TestSellCoinTxCustomToCustomBaseCommission(t *testing.T) { coinToSell := types.StrToCoinSymbol("TEST1") coinToBuy := types.StrToCoinSymbol("TEST2") - gasCoin := types.GetBaseCoin() + gasCoin := types.GetBaseCoinID() initialBalance := helpers.BipToPip(big.NewInt(10000000)) initialGasBalance := helpers.BipToPip(big.NewInt(1)) toSell := helpers.BipToPip(big.NewInt(100)) cState := getState() - initialVolume1, initialReserve1, crr1 := createTestCoinWithSymbol(cState, coinToSell) - initialVolume2, initialReserve2, crr2 := createTestCoinWithSymbol(cState, coinToBuy) + coinToSellID, initialVolume1, initialReserve1, crr1 := createTestCoinWithSymbol(cState, coinToSell) + coinToBuyID, initialVolume2, initialReserve2, crr2 := createTestCoinWithSymbol(cState, coinToBuy) privateKey, addr := getAccount() - cState.Accounts.AddBalance(addr, coinToSell, initialBalance) + cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) cState.Accounts.AddBalance(addr, gasCoin, initialGasBalance) - tx := createSellCoinTx(coinToSell, coinToBuy, gasCoin, toSell, 1) + tx := createSellCoinTx(coinToSellID, coinToBuyID, gasCoin, toSell, 1) if err := tx.Sign(privateKey); err != nil { t.Fatal(err) } @@ -240,20 +240,20 @@ func TestSellCoinTxCustomToCustomBaseCommission(t *testing.T) { } // check response - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.OK { t.Fatalf("Response code is not 0. Error %s", response.Log) } // check received coins - buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuy) + buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuyID) estimatedBuyBalance := formula.CalculatePurchaseReturn(initialVolume2, initialReserve2, crr2, formula.CalculateSaleReturn(initialVolume1, initialReserve1, crr1, toSell)) if buyCoinBalance.Cmp(estimatedBuyBalance) != 0 { t.Fatalf("Buy coin balance is not correct. Expected %s, got %s", estimatedBuyBalance.String(), buyCoinBalance.String()) } // check sold coins - sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSell) + sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSellID) estimatedSellCoinBalance := big.NewInt(0).Set(initialBalance) estimatedSellCoinBalance.Sub(estimatedSellCoinBalance, toSell) if sellCoinBalance.Cmp(estimatedSellCoinBalance) != 0 { @@ -262,7 +262,7 @@ func TestSellCoinTxCustomToCustomBaseCommission(t *testing.T) { // check reserve and supply { - coinData := cState.Coins.GetCoin(coinToSell) + coinData := cState.Coins.GetCoin(coinToSellID) estimatedReserve := big.NewInt(0).Set(initialReserve1) estimatedReserve.Sub(estimatedReserve, formula.CalculateSaleReturn(initialVolume1, initialReserve1, crr1, toSell)) @@ -278,7 +278,7 @@ func TestSellCoinTxCustomToCustomBaseCommission(t *testing.T) { } { - coinData := cState.Coins.GetCoin(coinToBuy) + coinData := cState.Coins.GetCoin(coinToBuyID) estimatedReserve := big.NewInt(0).Set(initialReserve2) estimatedReserve.Add(estimatedReserve, formula.CalculateSaleReturn(initialVolume1, initialReserve1, crr1, toSell)) @@ -299,21 +299,20 @@ func TestSellCoinTxBaseToCustomCustomCommission(t *testing.T) { // buy_coin: TEST // gas_coin: TEST - coinToSell := types.GetBaseCoin() + coinToSell := types.GetBaseCoinID() coinToBuy := types.StrToCoinSymbol("TEST") - gasCoin := types.StrToCoinSymbol("TEST") initialBalance := helpers.BipToPip(big.NewInt(10000000)) initialGasBalance := helpers.BipToPip(big.NewInt(1)) toSell := helpers.BipToPip(big.NewInt(100)) cState := getState() - initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToBuy) + coinToBuyID, initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToBuy) privateKey, addr := getAccount() cState.Accounts.AddBalance(addr, coinToSell, initialBalance) - cState.Accounts.AddBalance(addr, gasCoin, initialGasBalance) + cState.Accounts.AddBalance(addr, coinToBuyID, initialGasBalance) - tx := createSellCoinTx(coinToSell, coinToBuy, gasCoin, toSell, 1) + tx := createSellCoinTx(coinToSell, coinToBuyID, coinToBuyID, toSell, 1) if err := tx.Sign(privateKey); err != nil { t.Fatal(err) } @@ -324,13 +323,13 @@ func TestSellCoinTxBaseToCustomCustomCommission(t *testing.T) { } // check response - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.OK { t.Fatalf("Response code is not 0. Error %s", response.Log) } // check received coins + commission - buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuy) + buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuyID) estimatedReturn := formula.CalculatePurchaseReturn(initialVolume, initialReserve, crr, toSell) estimatedBuyBalance := big.NewInt(0).Set(estimatedReturn) estimatedBuyBalance.Add(estimatedBuyBalance, initialGasBalance) @@ -348,7 +347,7 @@ func TestSellCoinTxBaseToCustomCustomCommission(t *testing.T) { } // check reserve and supply - coinData := cState.Coins.GetCoin(coinToBuy) + coinData := cState.Coins.GetCoin(coinToBuyID) estimatedReserve := big.NewInt(0).Set(initialReserve) estimatedReserve.Add(estimatedReserve, toSell) @@ -371,18 +370,17 @@ func TestSellCoinTxCustomToBaseCustomCommission(t *testing.T) { // gas_coin: TEST coinToSell := types.StrToCoinSymbol("TEST") - coinToBuy := types.GetBaseCoin() - gasCoin := types.StrToCoinSymbol("TEST") + coinToBuy := types.GetBaseCoinID() initialBalance := helpers.BipToPip(big.NewInt(10000000)) toSell := helpers.BipToPip(big.NewInt(100)) cState := getState() - initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToSell) + coinToSellID, initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToSell) privateKey, addr := getAccount() - cState.Accounts.AddBalance(addr, coinToSell, initialBalance) + cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) - tx := createSellCoinTx(coinToSell, coinToBuy, gasCoin, toSell, 1) + tx := createSellCoinTx(coinToSellID, coinToBuy, coinToSellID, toSell, 1) if err := tx.Sign(privateKey); err != nil { t.Fatal(err) } @@ -393,7 +391,7 @@ func TestSellCoinTxCustomToBaseCustomCommission(t *testing.T) { } // check response - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.OK { t.Fatalf("Response code is not 0. Error %s", response.Log) } @@ -407,7 +405,7 @@ func TestSellCoinTxCustomToBaseCustomCommission(t *testing.T) { } // check sold coins + commission - sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSell) + sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSellID) estimatedSellCoinBalance := big.NewInt(0).Set(initialBalance) estimatedSellCoinBalance.Sub(estimatedSellCoinBalance, toSell) estimatedSellCoinBalance.Sub(estimatedSellCoinBalance, formula.CalculateSaleAmount(big.NewInt(0).Sub(initialVolume, toSell), big.NewInt(0).Sub(initialReserve, estimatedReturn), crr, tx.CommissionInBaseCoin())) @@ -416,7 +414,7 @@ func TestSellCoinTxCustomToBaseCustomCommission(t *testing.T) { } // check reserve and supply - coinData := cState.Coins.GetCoin(coinToSell) + coinData := cState.Coins.GetCoin(coinToSellID) estimatedReserve := big.NewInt(0).Set(initialReserve) estimatedReserve.Sub(estimatedReserve, estimatedReturn) @@ -440,18 +438,17 @@ func TestSellCoinTxCustomToCustomCustom1Commission(t *testing.T) { coinToSell := types.StrToCoinSymbol("TEST1") coinToBuy := types.StrToCoinSymbol("TEST2") - gasCoin := types.StrToCoinSymbol("TEST1") initialBalance := helpers.BipToPip(big.NewInt(10000000)) toSell := helpers.BipToPip(big.NewInt(100)) cState := getState() - initialVolume1, initialReserve1, crr1 := createTestCoinWithSymbol(cState, coinToSell) - initialVolume2, initialReserve2, crr2 := createTestCoinWithSymbol(cState, coinToBuy) + coinToSellID, initialVolume1, initialReserve1, crr1 := createTestCoinWithSymbol(cState, coinToSell) + coinToBuyID, initialVolume2, initialReserve2, crr2 := createTestCoinWithSymbol(cState, coinToBuy) privateKey, addr := getAccount() - cState.Accounts.AddBalance(addr, coinToSell, initialBalance) + cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) - tx := createSellCoinTx(coinToSell, coinToBuy, gasCoin, toSell, 1) + tx := createSellCoinTx(coinToSellID, coinToBuyID, coinToSellID, toSell, 1) if err := tx.Sign(privateKey); err != nil { t.Fatal(err) } @@ -462,13 +459,13 @@ func TestSellCoinTxCustomToCustomCustom1Commission(t *testing.T) { } // check response - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.OK { t.Fatalf("Response code is not 0. Error %s", response.Log) } // check received coins - buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuy) + buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuyID) bipReturn := formula.CalculateSaleReturn(initialVolume1, initialReserve1, crr1, toSell) estimatedBuyBalance := formula.CalculatePurchaseReturn(initialVolume2, initialReserve2, crr2, bipReturn) if buyCoinBalance.Cmp(estimatedBuyBalance) != 0 { @@ -476,7 +473,7 @@ func TestSellCoinTxCustomToCustomCustom1Commission(t *testing.T) { } // check sold coins - sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSell) + sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSellID) estimatedSellCoinBalance := big.NewInt(0).Set(initialBalance) estimatedSellCoinBalance.Sub(estimatedSellCoinBalance, toSell) commission := formula.CalculateSaleAmount(big.NewInt(0).Sub(initialVolume1, toSell), big.NewInt(0).Sub(initialReserve1, bipReturn), crr1, tx.CommissionInBaseCoin()) @@ -487,7 +484,7 @@ func TestSellCoinTxCustomToCustomCustom1Commission(t *testing.T) { // check reserve and supply { - coinData := cState.Coins.GetCoin(coinToSell) + coinData := cState.Coins.GetCoin(coinToSellID) estimatedReserve := big.NewInt(0).Set(initialReserve1) estimatedReserve.Sub(estimatedReserve, formula.CalculateSaleReturn(initialVolume1, initialReserve1, crr1, toSell)) @@ -505,7 +502,7 @@ func TestSellCoinTxCustomToCustomCustom1Commission(t *testing.T) { } { - coinData := cState.Coins.GetCoin(coinToBuy) + coinData := cState.Coins.GetCoin(coinToBuyID) estimatedReserve := big.NewInt(0).Set(initialReserve2) estimatedReserve.Add(estimatedReserve, formula.CalculateSaleReturn(initialVolume1, initialReserve1, crr1, toSell)) @@ -528,20 +525,19 @@ func TestSellCoinTxCustomToCustomCustom2Commission(t *testing.T) { coinToSell := types.StrToCoinSymbol("TEST1") coinToBuy := types.StrToCoinSymbol("TEST2") - gasCoin := types.StrToCoinSymbol("TEST2") initialBalance := helpers.BipToPip(big.NewInt(10000000)) initialGasBalance := helpers.BipToPip(big.NewInt(1)) toSell := helpers.BipToPip(big.NewInt(100)) cState := getState() - initialVolume1, initialReserve1, crr1 := createTestCoinWithSymbol(cState, coinToSell) - initialVolume2, initialReserve2, crr2 := createTestCoinWithSymbol(cState, coinToBuy) + coinToSellID, initialVolume1, initialReserve1, crr1 := createTestCoinWithSymbol(cState, coinToSell) + coinToBuyID, initialVolume2, initialReserve2, crr2 := createTestCoinWithSymbol(cState, coinToBuy) privateKey, addr := getAccount() - cState.Accounts.AddBalance(addr, coinToSell, initialBalance) - cState.Accounts.AddBalance(addr, gasCoin, initialGasBalance) + cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) + cState.Accounts.AddBalance(addr, coinToBuyID, initialGasBalance) - tx := createSellCoinTx(coinToSell, coinToBuy, gasCoin, toSell, 1) + tx := createSellCoinTx(coinToSellID, coinToBuyID, coinToBuyID, toSell, 1) if err := tx.Sign(privateKey); err != nil { t.Fatal(err) } @@ -552,13 +548,13 @@ func TestSellCoinTxCustomToCustomCustom2Commission(t *testing.T) { } // check response - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.OK { t.Fatalf("Response code is not 0. Error %s", response.Log) } // check received coins - buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuy) + buyCoinBalance := cState.Accounts.GetBalance(addr, coinToBuyID) bipReturn := formula.CalculateSaleReturn(initialVolume1, initialReserve1, crr1, toSell) estimatedReturn := formula.CalculatePurchaseReturn(initialVolume2, initialReserve2, crr2, bipReturn) commission := formula.CalculateSaleAmount(big.NewInt(0).Add(initialVolume2, estimatedReturn), big.NewInt(0).Add(initialReserve2, bipReturn), crr2, tx.CommissionInBaseCoin()) @@ -571,7 +567,7 @@ func TestSellCoinTxCustomToCustomCustom2Commission(t *testing.T) { } // check sold coins - sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSell) + sellCoinBalance := cState.Accounts.GetBalance(addr, coinToSellID) estimatedSellCoinBalance := big.NewInt(0).Set(initialBalance) estimatedSellCoinBalance.Sub(estimatedSellCoinBalance, toSell) if sellCoinBalance.Cmp(estimatedSellCoinBalance) != 0 { @@ -580,7 +576,7 @@ func TestSellCoinTxCustomToCustomCustom2Commission(t *testing.T) { // check reserve and supply { - coinData := cState.Coins.GetCoin(coinToSell) + coinData := cState.Coins.GetCoin(coinToSellID) estimatedReserve := big.NewInt(0).Set(initialReserve1) estimatedReserve.Sub(estimatedReserve, formula.CalculateSaleReturn(initialVolume1, initialReserve1, crr1, toSell)) @@ -596,7 +592,7 @@ func TestSellCoinTxCustomToCustomCustom2Commission(t *testing.T) { } { - coinData := cState.Coins.GetCoin(coinToBuy) + coinData := cState.Coins.GetCoin(coinToBuyID) estimatedReserve := big.NewInt(0).Set(initialReserve2) estimatedReserve.Add(estimatedReserve, formula.CalculateSaleReturn(initialVolume1, initialReserve1, crr1, toSell)) @@ -614,7 +610,7 @@ func TestSellCoinTxCustomToCustomCustom2Commission(t *testing.T) { } } -func createSellCoinTx(sellCoin, buyCoin, gasCoin types.CoinSymbol, valueToSell *big.Int, nonce uint64) *Transaction { +func createSellCoinTx(sellCoin, buyCoin, gasCoin types.CoinID, valueToSell *big.Int, nonce uint64) *Transaction { data := SellCoinData{ CoinToSell: sellCoin, ValueToSell: valueToSell, diff --git a/core/transaction/send_test.go b/core/transaction/send_test.go index 97378715f..237ab95ff 100644 --- a/core/transaction/send_test.go +++ b/core/transaction/send_test.go @@ -16,7 +16,7 @@ func TestSendTx(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) @@ -53,7 +53,7 @@ func TestSendTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error: %s", response.Log) } @@ -80,7 +80,7 @@ func TestSendMultisigTx(t *testing.T) { privateKey2, _ := crypto.GenerateKey() addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() msig := cState.Accounts.CreateMultisig([]uint{1, 1}, []types.Address{addr1, addr2}, 1, 1) @@ -121,7 +121,7 @@ func TestSendMultisigTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error: %s", response.Log) } @@ -148,7 +148,7 @@ func TestSendFailedMultisigTx(t *testing.T) { privateKey2, _ := crypto.GenerateKey() addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() msig := cState.Accounts.CreateMultisig([]uint{1, 3}, []types.Address{addr1, addr2}, 3, 1) @@ -189,7 +189,7 @@ func TestSendFailedMultisigTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.IncorrectMultiSignature { t.Fatalf("Response code is not %d. Gor: %d", code.IncorrectMultiSignature, response.Code) } diff --git a/core/transaction/set_halt_block_test.go b/core/transaction/set_halt_block_test.go index 90b53a624..a53c4b8f0 100644 --- a/core/transaction/set_halt_block_test.go +++ b/core/transaction/set_halt_block_test.go @@ -24,12 +24,12 @@ func TestSetHaltBlockTx(t *testing.T) { haltHeight := upgrades.UpgradeBlock4 + uint64(100) privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() pubkey := [32]byte{} rand.Read(pubkey[:]) - cState.Candidates.Create(addr, addr, pubkey, 10) + cState.Candidates.Create(addr, addr, addr, pubkey, 10) cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1))) @@ -63,7 +63,7 @@ func TestSetHaltBlockTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), upgrades.UpgradeBlock4, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), upgrades.UpgradeBlock4, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) } @@ -100,12 +100,12 @@ func TestSetHaltBlockTxWithWrongHeight(t *testing.T) { haltHeight := currentHeight - 1 privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() pubkey := [32]byte{} rand.Read(pubkey[:]) - cState.Candidates.Create(addr, addr, pubkey, 10) + cState.Candidates.Create(addr, addr, addr, pubkey, 10) cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1))) @@ -139,7 +139,7 @@ func TestSetHaltBlockTxWithWrongHeight(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), currentHeight, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), currentHeight, &sync.Map{}, 0) if response.Code != code.WrongHaltHeight { t.Fatalf("Response code is not %d", code.WrongHaltHeight) } @@ -160,12 +160,12 @@ func TestSetHaltBlockTxWithWrongOwnership(t *testing.T) { haltHeight := currentHeight + 1 privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() pubkey := [32]byte{} rand.Read(pubkey[:]) - cState.Candidates.Create(addr, addr, pubkey, 10) + cState.Candidates.Create(addr, addr, addr, pubkey, 10) cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1))) @@ -200,7 +200,7 @@ func TestSetHaltBlockTxWithWrongOwnership(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), currentHeight, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), currentHeight, &sync.Map{}, 0) if response.Code != code.IsNotOwnerOfCandidate { t.Fatalf("Response code is not %d", code.IsNotOwnerOfCandidate) } diff --git a/core/transaction/switch_candidate_status_test.go b/core/transaction/switch_candidate_status_test.go index cab55ca3f..f0c221206 100644 --- a/core/transaction/switch_candidate_status_test.go +++ b/core/transaction/switch_candidate_status_test.go @@ -17,13 +17,13 @@ func TestSwitchCandidateStatusTx(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) pubkey := types.Pubkey{} rand.Read(pubkey[:]) - cState.Candidates.Create(addr, addr, pubkey, 10) + cState.Candidates.Create(addr, addr, addr, pubkey, 10) data := SetCandidateOnData{ PubKey: pubkey, @@ -55,7 +55,7 @@ func TestSwitchCandidateStatusTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) diff --git a/core/transaction/unbond_test.go b/core/transaction/unbond_test.go index 2162e1341..29afe7988 100644 --- a/core/transaction/unbond_test.go +++ b/core/transaction/unbond_test.go @@ -18,7 +18,7 @@ func TestUnbondTx(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) @@ -59,7 +59,7 @@ func TestUnbondTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, false, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) From f9deb97f6c1fe7aa5153fe60f27eb6aa54dd0dcf Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Fri, 24 Jul 2020 11:49:52 +0300 Subject: [PATCH 097/426] create test for ChangeOwner transaction --- core/state/coins/coins.go | 2 +- core/transaction/buy_coin_test.go | 18 +++ core/transaction/change_owner_test.go | 188 ++++++++++++++++++++++++++ 3 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 core/transaction/change_owner_test.go diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index 4cf7e10e1..4ddffd508 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -312,7 +312,7 @@ func (c *Coins) getSymbolInfo(symbol types.CoinSymbol) *SymbolInfo { _, enc := c.iavl.Get(getSymbolInfoPath(symbol)) if len(enc) == 0 { - return info + return nil } if err := rlp.DecodeBytes(enc, info); err != nil { diff --git a/core/transaction/buy_coin_test.go b/core/transaction/buy_coin_test.go index 3af8e52b8..b65bd3a50 100644 --- a/core/transaction/buy_coin_test.go +++ b/core/transaction/buy_coin_test.go @@ -13,6 +13,7 @@ import ( "github.com/MinterTeam/minter-go-node/rlp" "github.com/tendermint/go-amino" "github.com/tendermint/tm-db" + "log" "math/big" "math/rand" "sync" @@ -55,6 +56,23 @@ func createTestCoin(stateDB *state.State) types.CoinID { return id } +func createTestCoinWithOwner(stateDB *state.State, owner types.Address) types.CoinID { + volume := helpers.BipToPip(big.NewInt(100000)) + reserve := helpers.BipToPip(big.NewInt(100000)) + + id := stateDB.App.GetNextCoinID() + stateDB.Coins.Create(id, getTestCoinSymbol(), "TEST COIN", volume, 10, reserve, + big.NewInt(0).Mul(volume, big.NewInt(10)), &owner) + stateDB.App.SetCoinsCount(id.Uint32()) + + err := stateDB.Coins.Commit() + if err != nil { + log.Fatalf("failed to commit coins: %s", err) + } + + return id +} + func TestBuyCoinTxBaseToCustom(t *testing.T) { cState := getState() diff --git a/core/transaction/change_owner_test.go b/core/transaction/change_owner_test.go new file mode 100644 index 000000000..2663c394b --- /dev/null +++ b/core/transaction/change_owner_test.go @@ -0,0 +1,188 @@ +package transaction + +import ( + "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/state" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/crypto" + "github.com/MinterTeam/minter-go-node/helpers" + "github.com/MinterTeam/minter-go-node/rlp" + "github.com/MinterTeam/minter-go-node/upgrades" + db "github.com/tendermint/tm-db" + "math/big" + "sync" + "testing" +) + +func TestChangeOwnerTx(t *testing.T) { + cState, err := state.NewState(0, db.NewMemDB(), nil, 1, 1) + if err != nil { + t.Fatalf("Cannot load state. Error %s", err) + } + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + + newOwnerPrivateKey, _ := crypto.GenerateKey() + newOwner := crypto.PubkeyToAddress(newOwnerPrivateKey.PublicKey) + + createTestCoinWithOwner(cState, addr) + + gasCoin := types.GetBaseCoinID() + cState.Accounts.AddBalance(addr, gasCoin, helpers.BipToPip(big.NewInt(10000))) + + data := ChangeOwnerData{ + Symbol: getTestCoinSymbol(), + NewOwner: newOwner, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: gasCoin, + Type: TypeChangeOwner, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), upgrades.UpgradeBlock4, &sync.Map{}, 0) + if response.Code != 0 { + t.Fatalf("Response code is not 0. Error %s", response.Log) + } + + err = cState.Coins.Commit() + if err != nil { + t.Fatalf("Failed to commit coins: %s", err) + } + + targetBalance, _ := big.NewInt(0).SetString("0", 10) + balance := cState.Accounts.GetBalance(addr, gasCoin) + if balance.Cmp(targetBalance) != 0 { + t.Fatalf("Target %s balance is not correct. Expected %d, got %s", gasCoin, targetBalance, balance) + } + + symbol := cState.Coins.GetSymbolInfo(getTestCoinSymbol()) + if symbol == nil { + t.Fatal("Symbol info not found") + } + + if *symbol.OwnerAddress() != newOwner { + t.Fatalf("Target owner address is not correct. Excpected %s, got %s", newOwner.String(), symbol.OwnerAddress().String()) + } +} + +func TestChangeOwnerTxWithWrongOwner(t *testing.T) { + cState, err := state.NewState(0, db.NewMemDB(), nil, 1, 1) + if err != nil { + t.Fatalf("Cannot load state. Error %s", err) + } + + privateKey, _ := crypto.GenerateKey() + + newOwnerPrivateKey, _ := crypto.GenerateKey() + newOwner := crypto.PubkeyToAddress(newOwnerPrivateKey.PublicKey) + + createTestCoinWithOwner(cState, newOwner) + + gasCoin := types.GetBaseCoinID() + + data := ChangeOwnerData{ + Symbol: getTestCoinSymbol(), + NewOwner: newOwner, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: gasCoin, + Type: TypeChangeOwner, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), upgrades.UpgradeBlock4, &sync.Map{}, 0) + if response.Code != code.IsNotOwnerOfCoin { + t.Fatalf("Response code is not 206. Error %s", response.Log) + } +} + +func TestChangeOwnerTxWithWrongSymbol(t *testing.T) { + cState, err := state.NewState(0, db.NewMemDB(), nil, 1, 1) + if err != nil { + t.Fatalf("Cannot load state. Error %s", err) + } + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + + newOwnerPrivateKey, _ := crypto.GenerateKey() + newOwner := crypto.PubkeyToAddress(newOwnerPrivateKey.PublicKey) + + createTestCoinWithOwner(cState, addr) + + gasCoin := types.GetBaseCoinID() + + data := ChangeOwnerData{ + Symbol: types.StrToCoinSymbol("TESTCOIN"), + NewOwner: newOwner, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: gasCoin, + Type: TypeChangeOwner, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), upgrades.UpgradeBlock4, &sync.Map{}, 0) + if response.Code != code.CoinNotExists { + t.Fatalf("Response code is not 102. Error %s", response.Log) + } +} From 1f4b1a0aa430f44759fcb17b7ce2ffb4e311bca7 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Fri, 24 Jul 2020 11:53:08 +0300 Subject: [PATCH 098/426] check ownership of coin in CreateCoin tx test --- core/transaction/create_coin_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/transaction/create_coin_test.go b/core/transaction/create_coin_test.go index 124bc4d67..a4f68c413 100644 --- a/core/transaction/create_coin_test.go +++ b/core/transaction/create_coin_test.go @@ -97,4 +97,13 @@ func TestCreateCoinTx(t *testing.T) { if stateCoin.Name() != name { t.Fatalf("Name in state is not correct. Expected %s, got %s", name, stateCoin.Name()) } + + symbolInfo := cState.Coins.GetSymbolInfo(toCreate) + if symbolInfo == nil { + t.Fatalf("Symbol %s info not found in state", toCreate) + } + + if *symbolInfo.OwnerAddress() != addr { + t.Fatalf("Target owner address is not correct. Expected %s, got %s", addr.String(), symbolInfo.OwnerAddress().String()) + } } From 3c70fb40399eeacd87c73488c1c3e018f82bffbe Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Fri, 24 Jul 2020 12:53:32 +0300 Subject: [PATCH 099/426] create test for ChangeOwner tx --- core/transaction/change_owner_test.go | 80 +++------- core/transaction/create_coin_test.go | 6 +- core/transaction/recreate_coin_test.go | 197 +++++++++++++++++++++++++ 3 files changed, 226 insertions(+), 57 deletions(-) create mode 100644 core/transaction/recreate_coin_test.go diff --git a/core/transaction/change_owner_test.go b/core/transaction/change_owner_test.go index 2663c394b..79054c3de 100644 --- a/core/transaction/change_owner_test.go +++ b/core/transaction/change_owner_test.go @@ -1,6 +1,7 @@ package transaction import ( + "crypto/ecdsa" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" @@ -36,31 +37,12 @@ func TestChangeOwnerTx(t *testing.T) { NewOwner: newOwner, } - encodedData, err := rlp.EncodeToBytes(data) + tx, err := makeTestChangeOwnerTx(data, privateKey) if err != nil { t.Fatal(err) } - tx := Transaction{ - Nonce: 1, - GasPrice: 1, - ChainID: types.CurrentChainID, - GasCoin: gasCoin, - Type: TypeChangeOwner, - Data: encodedData, - SignatureType: SigTypeSingle, - } - - if err := tx.Sign(privateKey); err != nil { - t.Fatal(err) - } - - encodedTx, err := rlp.EncodeToBytes(tx) - if err != nil { - t.Fatal(err) - } - - response := RunTx(cState, encodedTx, big.NewInt(0), upgrades.UpgradeBlock4, &sync.Map{}, 0) + response := RunTx(cState, tx, big.NewInt(0), upgrades.UpgradeBlock4, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) } @@ -99,38 +81,17 @@ func TestChangeOwnerTxWithWrongOwner(t *testing.T) { createTestCoinWithOwner(cState, newOwner) - gasCoin := types.GetBaseCoinID() - data := ChangeOwnerData{ Symbol: getTestCoinSymbol(), NewOwner: newOwner, } - encodedData, err := rlp.EncodeToBytes(data) - if err != nil { - t.Fatal(err) - } - - tx := Transaction{ - Nonce: 1, - GasPrice: 1, - ChainID: types.CurrentChainID, - GasCoin: gasCoin, - Type: TypeChangeOwner, - Data: encodedData, - SignatureType: SigTypeSingle, - } - - if err := tx.Sign(privateKey); err != nil { - t.Fatal(err) - } - - encodedTx, err := rlp.EncodeToBytes(tx) + tx, err := makeTestChangeOwnerTx(data, privateKey) if err != nil { t.Fatal(err) } - response := RunTx(cState, encodedTx, big.NewInt(0), upgrades.UpgradeBlock4, &sync.Map{}, 0) + response := RunTx(cState, tx, big.NewInt(0), upgrades.UpgradeBlock4, &sync.Map{}, 0) if response.Code != code.IsNotOwnerOfCoin { t.Fatalf("Response code is not 206. Error %s", response.Log) } @@ -150,39 +111,46 @@ func TestChangeOwnerTxWithWrongSymbol(t *testing.T) { createTestCoinWithOwner(cState, addr) - gasCoin := types.GetBaseCoinID() - data := ChangeOwnerData{ - Symbol: types.StrToCoinSymbol("TESTCOIN"), + Symbol: types.StrToCoinSymbol("UNKNOWN"), NewOwner: newOwner, } - encodedData, err := rlp.EncodeToBytes(data) + tx, err := makeTestChangeOwnerTx(data, privateKey) if err != nil { t.Fatal(err) } + response := RunTx(cState, tx, big.NewInt(0), upgrades.UpgradeBlock4, &sync.Map{}, 0) + if response.Code != code.CoinNotExists { + t.Fatalf("Response code is not 102. Error %s", response.Log) + } +} + +func makeTestChangeOwnerTx(data ChangeOwnerData, privateKey *ecdsa.PrivateKey) ([]byte, error) { + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + return nil, err + } + tx := Transaction{ Nonce: 1, GasPrice: 1, ChainID: types.CurrentChainID, - GasCoin: gasCoin, + GasCoin: types.GetBaseCoinID(), Type: TypeChangeOwner, Data: encodedData, SignatureType: SigTypeSingle, } if err := tx.Sign(privateKey); err != nil { - t.Fatal(err) + return nil, err } encodedTx, err := rlp.EncodeToBytes(tx) if err != nil { - t.Fatal(err) + return nil, err } - response := RunTx(cState, encodedTx, big.NewInt(0), upgrades.UpgradeBlock4, &sync.Map{}, 0) - if response.Code != code.CoinNotExists { - t.Fatalf("Response code is not 102. Error %s", response.Log) - } -} + return encodedTx, nil +} \ No newline at end of file diff --git a/core/transaction/create_coin_test.go b/core/transaction/create_coin_test.go index a4f68c413..ff67cc2ce 100644 --- a/core/transaction/create_coin_test.go +++ b/core/transaction/create_coin_test.go @@ -27,7 +27,7 @@ func TestCreateCoinTx(t *testing.T) { data := CreateCoinData{ Name: name, - Symbol: types.StrToCoinSymbol("ABCDEF"), + Symbol: toCreate, InitialAmount: amount, InitialReserve: reserve, ConstantReserveRatio: crr, @@ -98,6 +98,10 @@ func TestCreateCoinTx(t *testing.T) { t.Fatalf("Name in state is not correct. Expected %s, got %s", name, stateCoin.Name()) } + if stateCoin.Version() != 0 { + t.Fatalf("Version in state is not correct. Expected %d, got %d", 0, stateCoin.Version()) + } + symbolInfo := cState.Coins.GetSymbolInfo(toCreate) if symbolInfo == nil { t.Fatalf("Symbol %s info not found in state", toCreate) diff --git a/core/transaction/recreate_coin_test.go b/core/transaction/recreate_coin_test.go new file mode 100644 index 000000000..fc61715ec --- /dev/null +++ b/core/transaction/recreate_coin_test.go @@ -0,0 +1,197 @@ +package transaction + +import ( + "crypto/ecdsa" + "fmt" + "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/crypto" + "github.com/MinterTeam/minter-go-node/helpers" + "github.com/MinterTeam/minter-go-node/rlp" + "math/big" + "sync" + "testing" +) + +func TestRecreateCoinTx(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + + coin := createTestCoinWithOwner(cState, addr) + 1 + gasCoin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, gasCoin, helpers.BipToPip(big.NewInt(20000))) + + reserve := helpers.BipToPip(big.NewInt(10000)) + amount := helpers.BipToPip(big.NewInt(100)) + crr := uint(50) + + data := RecreateCoinData{ + Symbol: getTestCoinSymbol(), + InitialAmount: amount, + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: big.NewInt(0).Mul(amount, big.NewInt(10)), + } + + tx, err := makeTestRecreateCoinTx(data, privateKey) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, tx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != 0 { + t.Fatalf("Response code is not 0. Error %s", response.Log) + } + + err = cState.Coins.Commit() + if err != nil { + t.Fatalf("Commit coins failed. Error %s", err) + } + + targetBalance, _ := big.NewInt(0).SetString("0", 10) + balance := cState.Accounts.GetBalance(addr, gasCoin) + if balance.Cmp(targetBalance) != 0 { + t.Fatalf("Target %d balance is not correct. Expected %s, got %s", gasCoin, targetBalance, balance) + } + + targetBalance = helpers.BipToPip(big.NewInt(100)) + balance = cState.Accounts.GetBalance(addr, coin) + if balance.Cmp(targetBalance) != 0 { + t.Fatalf("Target %d balance is not correct. Expected %s, got %s", coin, targetBalance, balance) + } + + newCoinSymbol := getTestCoinSymbol() + stateCoin := cState.Coins.GetCoinBySymbol(newCoinSymbol) + + if stateCoin == nil { + t.Fatalf("Coin %s not found in state", newCoinSymbol) + } + + if stateCoin.Reserve().Cmp(reserve) != 0 { + t.Fatalf("Reserve balance in state is not correct. Expected %s, got %s", reserve, stateCoin.Reserve()) + } + + if stateCoin.Volume().Cmp(amount) != 0 { + t.Fatalf("Volume in state is not correct. Expected %s, got %s", amount, stateCoin.Volume()) + } + + if stateCoin.Crr() != crr { + t.Fatalf("Crr in state is not correct. Expected %d, got %d", crr, stateCoin.Crr()) + } + + if stateCoin.Version() != 0 { + t.Fatalf("Version in state is not correct. Expected %d, got %d", 0, stateCoin.Version()) + } + + archiveCoinSymbol := types.StrToCoinSymbol(fmt.Sprintf("%s-1", getTestCoinSymbol())) + stateCoin = cState.Coins.GetCoinBySymbol(archiveCoinSymbol) + + if stateCoin == nil { + t.Fatalf("Coin %s not found in state", newCoinSymbol) + } + + if stateCoin.Version() != 1 { + t.Fatalf("Version in state is not correct. Expected %d, got %d", 1, stateCoin.Version()) + } +} + +func TestRecreateCoinTxWithWrongOwner(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + + privateKey2, _ := crypto.GenerateKey() + + createTestCoinWithOwner(cState, addr) + gasCoin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, gasCoin, helpers.BipToPip(big.NewInt(20000))) + + reserve := helpers.BipToPip(big.NewInt(10000)) + amount := helpers.BipToPip(big.NewInt(100)) + crr := uint(50) + + data := RecreateCoinData{ + Symbol: getTestCoinSymbol(), + InitialAmount: amount, + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: big.NewInt(0).Mul(amount, big.NewInt(10)), + } + + tx, err := makeTestRecreateCoinTx(data, privateKey2) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, tx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.IsNotOwnerOfCoin { + t.Fatalf("Response code is not 206. Error %s", response.Log) + } +} + +func TestRecreateCoinTxWithWrongSymbol(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + + createTestCoinWithOwner(cState, addr) + gasCoin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, gasCoin, helpers.BipToPip(big.NewInt(20000))) + + reserve := helpers.BipToPip(big.NewInt(10000)) + amount := helpers.BipToPip(big.NewInt(100)) + crr := uint(50) + + data := RecreateCoinData{ + Symbol: types.StrToCoinSymbol("UNKNOWN"), + InitialAmount: amount, + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: big.NewInt(0).Mul(amount, big.NewInt(10)), + } + + tx, err := makeTestRecreateCoinTx(data, privateKey) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, tx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinNotExists { + t.Fatalf("Response code is not 102. Error %s", response.Log) + } +} + +func makeTestRecreateCoinTx(data RecreateCoinData, privateKey *ecdsa.PrivateKey) ([]byte, error) { + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + return nil, err + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeRecreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + return nil, err + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + return nil, err + } + + return encodedTx, nil +} \ No newline at end of file From ffac945e8860605113ac526b6100537ecdd537e5 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Fri, 24 Jul 2020 12:57:57 +0300 Subject: [PATCH 100/426] fix validators, types tests --- core/types/types_test.go | 6 +++--- core/validators/validators_test.go | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/types/types_test.go b/core/types/types_test.go index c2365c12e..7fec5dd93 100644 --- a/core/types/types_test.go +++ b/core/types/types_test.go @@ -153,7 +153,7 @@ func TestAppState(t *testing.T) { Stakes: []Stake{ { Owner: testAddr, - Coin: GetBaseCoin(), + Coin: GetBaseCoinID(), Value: big.NewInt(1).String(), BipValue: big.NewInt(1).String(), }, @@ -166,7 +166,7 @@ func TestAppState(t *testing.T) { Address: testAddr, Balance: []Balance{ { - Coin: GetBaseCoin(), + Coin: GetBaseCoinID(), Value: big.NewInt(1).String(), }, }, @@ -192,7 +192,7 @@ func TestAppState(t *testing.T) { Height: 1, Address: testAddr, CandidateKey: &pubkey, - Coin: GetBaseCoin(), + Coin: GetBaseCoinID(), Value: big.NewInt(1).String(), }, }, diff --git a/core/validators/validators_test.go b/core/validators/validators_test.go index 1e2f8a68a..ef529395c 100644 --- a/core/validators/validators_test.go +++ b/core/validators/validators_test.go @@ -13,19 +13,19 @@ func TestGetValidatorsCountForBlock(t *testing.T) { data := []Results{ { Block: 1, - Result: 16, + Result: 64, }, { Block: 518400 * 2, - Result: 24, + Result: 64, }, { Block: 31104000, - Result: 256, + Result: 64, }, { Block: 31104000 * 2, - Result: 256, + Result: 64, }, } From 564142cb47417f8ebc4418953e3440a9ff687edc Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Fri, 24 Jul 2020 13:19:09 +0300 Subject: [PATCH 101/426] fix state, candidates tests --- core/state/candidates_test.go | 18 +++++++------- core/state/coins/coins.go | 8 +++++-- core/state/state_test.go | 45 +++++++++++++++++++++-------------- 3 files changed, 42 insertions(+), 29 deletions(-) diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index 39b3a3a93..bde1d88b8 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -19,7 +19,7 @@ func TestSimpleDelegate(t *testing.T) { st := getState() address := types.Address{} - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() amount := big.NewInt(1) pubkey := createTestCandidate(st) @@ -44,7 +44,7 @@ func TestDelegate(t *testing.T) { st := getState() address := types.Address{} - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() amount := big.NewInt(1) totalAmount := big.NewInt(0) pubkey := createTestCandidate(st) @@ -73,7 +73,7 @@ func TestDelegate(t *testing.T) { func TestComplexDelegate(t *testing.T) { st := getState() - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() pubkey := createTestCandidate(st) for i := uint64(0); i < 2000; i++ { @@ -173,7 +173,7 @@ func TestComplexDelegate(t *testing.T) { func TestStakeSufficiency(t *testing.T) { st := getState() - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() pubkey := createTestCandidate(st) for i := uint64(0); i < 1000; i++ { @@ -224,7 +224,7 @@ func TestDoubleSignPenalty(t *testing.T) { pubkey := createTestCandidate(st) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() amount := big.NewInt(100) var addr types.Address binary.BigEndian.PutUint64(addr[:], 1) @@ -271,7 +271,7 @@ func TestAbsentPenalty(t *testing.T) { pubkey := createTestCandidate(st) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() amount := big.NewInt(100) var addr types.Address binary.BigEndian.PutUint64(addr[:], 1) @@ -301,7 +301,7 @@ func TestDoubleAbsentPenalty(t *testing.T) { pubkey := createTestCandidate(st) - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() amount := big.NewInt(100) var addr types.Address binary.BigEndian.PutUint64(addr[:], 1) @@ -335,7 +335,7 @@ func TestDoubleAbsentPenalty(t *testing.T) { func TestDelegationAfterUnbond(t *testing.T) { st := getState() - coin := types.GetBaseCoin() + coin := types.GetBaseCoinID() pubkey := createTestCandidate(st) for i := uint64(0); i < 1000; i++ { @@ -404,7 +404,7 @@ func createTestCandidate(stateDB *State) types.Pubkey { pubkey := types.Pubkey{} _, _ = rand.Read(pubkey[:]) - stateDB.Candidates.Create(address, address, pubkey, 10) + stateDB.Candidates.Create(address, address, address, pubkey, 10) return pubkey } diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index 4ddffd508..a7094c7d8 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -357,14 +357,18 @@ func (c *Coins) getOrderedDirtyCoins() []types.CoinID { func (c *Coins) Export(state *types.AppState) { c.iavl.Iterate(func(key []byte, value []byte) bool { if key[0] == mainPrefix { - if key[1] == symbolPrefix { + if key[1] == symbolPrefix || key[len(key) - 1] == infoPrefix { return false } coinID := types.BytesToCoinID(key[1:]) coin := c.get(coinID) - owner := c.getSymbolInfo(coin.Symbol()).OwnerAddress() + owner := &types.Address{} + info := c.getSymbolInfo(coin.Symbol()) + if info != nil { + owner = info.OwnerAddress() + } state.Coins = append(state.Coins, types.Coin{ ID: coin.ID(), diff --git a/core/state/state_test.go b/core/state/state_test.go index cc3637c46..62d749130 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -23,33 +23,42 @@ func TestStateExport(t *testing.T) { coinTest := types.StrToCoinSymbol("TEST") coinTest2 := types.StrToCoinSymbol("TEST2") + coinTestID := state.App.GetNextCoinID() + coinTest2ID := coinTestID + 1 + state.Coins.Create( + coinTestID, coinTest, "TEST", helpers.BipToPip(big.NewInt(1)), 10, helpers.BipToPip(big.NewInt(100)), helpers.BipToPip(big.NewInt(100)), + nil, ) state.Coins.Create( + coinTest2ID, coinTest2, "TEST2", helpers.BipToPip(big.NewInt(2)), 50, helpers.BipToPip(big.NewInt(200)), helpers.BipToPip(big.NewInt(200)), + nil, ) + state.App.SetCoinsCount(coinTest2ID.Uint32()) + privateKey1, _ := crypto.GenerateKey() address1 := crypto.PubkeyToAddress(privateKey1.PublicKey) privateKey2, _ := crypto.GenerateKey() address2 := crypto.PubkeyToAddress(privateKey2.PublicKey) - state.Accounts.AddBalance(address1, types.GetBaseCoin(), helpers.BipToPip(big.NewInt(1))) - state.Accounts.AddBalance(address1, coinTest, helpers.BipToPip(big.NewInt(1))) - state.Accounts.AddBalance(address2, coinTest2, helpers.BipToPip(big.NewInt(2))) + state.Accounts.AddBalance(address1, types.GetBaseCoinID(), helpers.BipToPip(big.NewInt(1))) + state.Accounts.AddBalance(address1, coinTestID, helpers.BipToPip(big.NewInt(1))) + state.Accounts.AddBalance(address2, coinTest2ID, helpers.BipToPip(big.NewInt(2))) candidatePubKey1 := [32]byte{} rand.Read(candidatePubKey1[:]) @@ -57,21 +66,21 @@ func TestStateExport(t *testing.T) { candidatePubKey2 := [32]byte{} rand.Read(candidatePubKey2[:]) - state.Candidates.Create(address1, address1, candidatePubKey1, 10) - state.Candidates.Create(address2, address2, candidatePubKey2, 30) + state.Candidates.Create(address1, address1, address1, candidatePubKey1, 10) + state.Candidates.Create(address2, address2, address2, candidatePubKey2, 30) state.Validators.Create(candidatePubKey1, helpers.BipToPip(big.NewInt(1))) - state.FrozenFunds.AddFund(height, address1, candidatePubKey1, coinTest, helpers.BipToPip(big.NewInt(100))) - state.FrozenFunds.AddFund(height+10, address1, candidatePubKey1, types.GetBaseCoin(), helpers.BipToPip(big.NewInt(3))) - state.FrozenFunds.AddFund(height+100, address2, candidatePubKey1, coinTest, helpers.BipToPip(big.NewInt(500))) - state.FrozenFunds.AddFund(height+150, address2, candidatePubKey1, coinTest2, helpers.BipToPip(big.NewInt(1000))) + state.FrozenFunds.AddFund(height, address1, candidatePubKey1, coinTestID, helpers.BipToPip(big.NewInt(100))) + state.FrozenFunds.AddFund(height+10, address1, candidatePubKey1, types.GetBaseCoinID(), helpers.BipToPip(big.NewInt(3))) + state.FrozenFunds.AddFund(height+100, address2, candidatePubKey1, coinTestID, helpers.BipToPip(big.NewInt(500))) + state.FrozenFunds.AddFund(height+150, address2, candidatePubKey1, coinTest2ID, helpers.BipToPip(big.NewInt(1000))) newCheck := &check.Check{ Nonce: []byte("test nonce"), ChainID: types.CurrentChainID, DueBlock: height + 1, - Coin: coinTest, + Coin: coinTestID, Value: helpers.BipToPip(big.NewInt(100)), - GasCoin: coinTest2, + GasCoin: coinTest2ID, } err = newCheck.Sign(privateKey1) @@ -136,7 +145,7 @@ func TestStateExport(t *testing.T) { if funds.Height != height || funds.Address != address1 || - funds.Coin != coinTest || + funds.Coin != coinTestID || *funds.CandidateKey != types.Pubkey(candidatePubKey1) || funds.Value != helpers.BipToPip(big.NewInt(100)).String() { t.Fatalf("Wrong new state frozen fund data") @@ -144,7 +153,7 @@ func TestStateExport(t *testing.T) { if funds1.Height != height+10 || funds1.Address != address1 || - funds1.Coin != types.GetBaseCoin() || + funds1.Coin != types.GetBaseCoinID() || *funds1.CandidateKey != types.Pubkey(candidatePubKey1) || funds1.Value != helpers.BipToPip(big.NewInt(3)).String() { t.Fatalf("Wrong new state frozen fund data") @@ -152,7 +161,7 @@ func TestStateExport(t *testing.T) { if funds2.Height != height+100 || funds2.Address != address2 || - funds2.Coin != coinTest || + funds2.Coin != coinTestID || *funds2.CandidateKey != types.Pubkey(candidatePubKey1) || funds2.Value != helpers.BipToPip(big.NewInt(500)).String() { t.Fatalf("Wrong new state frozen fund data") @@ -160,7 +169,7 @@ func TestStateExport(t *testing.T) { if funds3.Height != height+150 || funds3.Address != address2 || - funds3.Coin != coinTest2 || + funds3.Coin != coinTest2ID || *funds3.CandidateKey != types.Pubkey(candidatePubKey1) || funds3.Value != helpers.BipToPip(big.NewInt(1000)).String() { t.Fatalf("Wrong new state frozen fund data") @@ -198,15 +207,15 @@ func TestStateExport(t *testing.T) { t.Fatal("Wrong new state account balances size") } - if account1.Balance[0].Coin != coinTest || account1.Balance[0].Value != helpers.BipToPip(big.NewInt(1)).String() { + if account1.Balance[0].Coin != coinTestID || account1.Balance[0].Value != helpers.BipToPip(big.NewInt(1)).String() { t.Fatal("Wrong new state account balance data") } - if account1.Balance[1].Coin != types.GetBaseCoin() || account1.Balance[1].Value != helpers.BipToPip(big.NewInt(1)).String() { + if account1.Balance[1].Coin != types.GetBaseCoinID() || account1.Balance[1].Value != helpers.BipToPip(big.NewInt(1)).String() { t.Fatal("Wrong new state account balance data") } - if account2.Balance[0].Coin != coinTest2 || account2.Balance[0].Value != helpers.BipToPip(big.NewInt(2)).String() { + if account2.Balance[0].Coin != coinTest2ID || account2.Balance[0].Value != helpers.BipToPip(big.NewInt(2)).String() { t.Fatal("Wrong new state account balance data") } From 5606b418f5c3453e6ced34c45e277ced159f578c Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Fri, 24 Jul 2020 13:24:58 +0300 Subject: [PATCH 102/426] fix minter test --- core/minter/minter_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index 979ac409d..beb76af98 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -143,7 +143,7 @@ func TestSendTx(t *testing.T) { to := types.Address([20]byte{1}) data := transaction.SendData{ - Coin: types.GetBaseCoin(), + Coin: types.GetBaseCoinID(), To: to, Value: value, } @@ -157,7 +157,7 @@ func TestSendTx(t *testing.T) { Nonce: nonce, ChainID: types.CurrentChainID, GasPrice: 1, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), Type: transaction.TypeSend, Data: encodedData, SignatureType: transaction.SigTypeSingle, @@ -209,7 +209,7 @@ func TestSmallStakeValidator(t *testing.T) { Address: crypto.PubkeyToAddress(privateKey.PublicKey), PubKey: pubkey, Commission: 10, - Coin: types.GetBaseCoin(), + Coin: types.GetBaseCoinID(), Stake: big.NewInt(0), } @@ -222,7 +222,7 @@ func TestSmallStakeValidator(t *testing.T) { Nonce: nonce, ChainID: types.CurrentChainID, GasPrice: 1, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), Type: transaction.TypeDeclareCandidacy, Data: encodedData, SignatureType: transaction.SigTypeSingle, @@ -257,7 +257,7 @@ func TestSmallStakeValidator(t *testing.T) { Nonce: nonce, GasPrice: 1, ChainID: types.CurrentChainID, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), Type: transaction.TypeSetCandidateOnline, Data: encodedData, SignatureType: transaction.SigTypeSingle, @@ -325,7 +325,7 @@ func TestSmallStakeValidator(t *testing.T) { Nonce: nonce, GasPrice: 1, ChainID: types.CurrentChainID, - GasCoin: types.GetBaseCoin(), + GasCoin: types.GetBaseCoinID(), Type: transaction.TypeSetCandidateOnline, Data: encodedData, SignatureType: transaction.SigTypeSingle, @@ -435,7 +435,7 @@ func getGenesis() (*types2.GenesisDoc, error) { Address: crypto.PubkeyToAddress(privateKey.PublicKey), Balance: []types.Balance{ { - Coin: types.GetBaseCoin(), + Coin: types.GetBaseCoinID(), Value: helpers.BipToPip(big.NewInt(1000000)).String(), }, }, @@ -500,7 +500,7 @@ func makeValidatorsAndCandidates(pubkeys []string, stake *big.Int) ([]types.Vali Stakes: []types.Stake{ { Owner: addr, - Coin: types.GetBaseCoin(), + Coin: types.GetBaseCoinID(), Value: stake.String(), BipValue: stake.String(), }, From e3972f6fa90d673f9a8e981f955a3bfe402c2b0b Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 24 Jul 2020 16:28:48 +0300 Subject: [PATCH 103/426] edit model for transaction list in api --- core/minter/minter_test.go | 12 +++++++----- core/state/legacy/candidates/candidates.go | 19 ++++++++++--------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index beb76af98..e33e22600 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -492,11 +492,13 @@ func makeValidatorsAndCandidates(pubkeys []string, stake *big.Int) ([]types.Vali } candidates[i] = types.Candidate{ - RewardAddress: addr, - OwnerAddress: addr, - TotalBipStake: big.NewInt(1).String(), - PubKey: pkey, - Commission: 100, + ID: uint(i) + 1, + RewardAddress: addr, + OwnerAddress: addr, + ControlAddress: addr, + TotalBipStake: big.NewInt(1).String(), + PubKey: pkey, + Commission: 100, Stakes: []types.Stake{ { Owner: addr, diff --git a/core/state/legacy/candidates/candidates.go b/core/state/legacy/candidates/candidates.go index 4aa5cc2a4..43dafe903 100644 --- a/core/state/legacy/candidates/candidates.go +++ b/core/state/legacy/candidates/candidates.go @@ -259,15 +259,16 @@ func (c *Candidates) Export(state *types.AppState, coinsMap map[types.CoinSymbol } state.Candidates = append(state.Candidates, types.Candidate{ - ID: maxID, - RewardAddress: candidate.RewardAddress, - OwnerAddress: candidate.OwnerAddress, - TotalBipStake: candidate.GetTotalBipStake().String(), - PubKey: candidate.PubKey, - Commission: candidate.Commission, - Status: candidate.Status, - Updates: updates, - Stakes: stakes, + ID: maxID, + RewardAddress: candidate.RewardAddress, + OwnerAddress: candidate.OwnerAddress, + ControlAddress: candidate.OwnerAddress, + TotalBipStake: candidate.GetTotalBipStake().String(), + PubKey: candidate.PubKey, + Commission: candidate.Commission, + Status: candidate.Status, + Updates: updates, + Stakes: stakes, }) maxID++ From ac87269355b4a2316748056089735ce410fad165 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 24 Jul 2020 17:07:24 +0300 Subject: [PATCH 104/426] tests EditCandidate and DeclareCandidacy --- core/transaction/declare_candidacy_test.go | 93 +++++++++++++++++++ core/transaction/edit_candidate_test.go | 102 ++++++++++++++++++++- 2 files changed, 192 insertions(+), 3 deletions(-) diff --git a/core/transaction/declare_candidacy_test.go b/core/transaction/declare_candidacy_test.go index e3a732034..7e572b31a 100644 --- a/core/transaction/declare_candidacy_test.go +++ b/core/transaction/declare_candidacy_test.go @@ -91,6 +91,10 @@ func TestDeclareCandidacyTx(t *testing.T) { t.Fatalf("Reward address is not correct") } + if candidate.ControlAddress != addr { + t.Fatalf("Control address is not correct") + } + if candidate.GetTotalBipStake() != nil && candidate.GetTotalBipStake().Cmp(types.Big0) != 0 { t.Fatalf("Total stake is not correct") } @@ -168,3 +172,92 @@ func TestDeclareCandidacyTxOverflow(t *testing.T) { t.Fatalf("Response code is not %d. Got %d", code.TooLowStake, response.Code) } } + +func TestDeclareCandidacyTxWithBlockPybKey(t *testing.T) { + cState := getState() + + pkey, _ := crypto.GenerateKey() + publicKeyBytes := crypto.FromECDSAPub(&pkey.PublicKey)[:32] + var publicKey types.Pubkey + copy(publicKey[:], publicKeyBytes) + + cState.Candidates.Create(types.Address{}, types.Address{}, types.Address{}, publicKey, 10) + pkeyNew, _ := crypto.GenerateKey() + publicKeyNewBytes := crypto.FromECDSAPub(&pkeyNew.PublicKey)[:32] + var publicKeyNew types.Pubkey + copy(publicKeyNew[:], publicKeyNewBytes) + + cState.Candidates.ChangePubKey(publicKey, publicKeyNew) + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + + coin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + commission := uint(10) + + data := DeclareCandidacyData{ + Address: addr, + PubKey: publicKey, + Commission: commission, + Coin: coin, + Stake: helpers.BipToPip(big.NewInt(100)), + } + + encodedData, err := rlp.EncodeToBytes(data) + + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeDeclareCandidacy, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + + if response.Code == 0 { + t.Fatal("Response code is not 1. Want error") + } + + if cState.Candidates.GetCandidate(publicKey) != nil { + t.Fatalf("Candidate found with old pub key") + } + + candidate := cState.Candidates.GetCandidate(publicKeyNew) + + if candidate == nil { + t.Fatalf("Candidate not found") + } + + if candidate.OwnerAddress == addr { + t.Fatalf("OwnerAddress has changed") + } + + if candidate.RewardAddress == addr { + t.Fatalf("RewardAddress has changed") + } + + if candidate.ControlAddress == addr { + t.Fatalf("ControlAddress has changed") + } + +} diff --git a/core/transaction/edit_candidate_test.go b/core/transaction/edit_candidate_test.go index 8bb084279..687d97be3 100644 --- a/core/transaction/edit_candidate_test.go +++ b/core/transaction/edit_candidate_test.go @@ -27,11 +27,13 @@ func TestEditCandidateTx(t *testing.T) { newRewardAddress := types.Address{1} newOwnerAddress := types.Address{2} + newControlAddress := types.Address{3} data := EditCandidateData{ - PubKey: pubkey, - RewardAddress: newRewardAddress, - OwnerAddress: newOwnerAddress, + PubKey: pubkey, + RewardAddress: newRewardAddress, + OwnerAddress: newOwnerAddress, + ControlAddress: newControlAddress, } encodedData, err := rlp.EncodeToBytes(data) @@ -85,4 +87,98 @@ func TestEditCandidateTx(t *testing.T) { if candidate.RewardAddress != newRewardAddress { t.Fatalf("RewardAddress has not changed") } + + if candidate.ControlAddress != newControlAddress { + t.Fatalf("ControlAddress has not changed") + } +} + +func TestEditCandidateNewPubKeyTx(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + newpubkey := [32]byte{} + rand.Read(newpubkey[:]) + + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + + newRewardAddress := types.Address{1} + newOwnerAddress := types.Address{2} + newControlAddress := types.Address{3} + + p := types.Pubkey(newpubkey) + data := EditCandidateData{ + PubKey: pubkey, + NewPubKey: &p, + RewardAddress: newRewardAddress, + OwnerAddress: newOwnerAddress, + ControlAddress: newControlAddress, + } + + encodedData, err := rlp.EncodeToBytes(data) + + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditCandidate, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + + if response.Code != 0 { + t.Fatalf("Response code is not 0. Error %s", response.Log) + } + + targetBalance, _ := big.NewInt(0).SetString("999990000000000000000000", 10) + balance := cState.Accounts.GetBalance(addr, coin) + if balance.Cmp(targetBalance) != 0 { + t.Fatalf("Target %s balance is not correct. Expected %s, got %s", coin, targetBalance, balance) + } + + if cState.Candidates.GetCandidate(pubkey) != nil { + t.Fatalf("Candidate found with old pub key") + } + + candidate := cState.Candidates.GetCandidate(newpubkey) + + if candidate == nil { + t.Fatalf("Candidate not found") + } + + if candidate.OwnerAddress != newOwnerAddress { + t.Fatalf("OwnerAddress has not changed") + } + + if candidate.RewardAddress != newRewardAddress { + t.Fatalf("RewardAddress has not changed") + } + + if candidate.ControlAddress != newControlAddress { + t.Fatalf("ControlAddress has not changed") + } } From 501f83434b2bea55cb6a25fc9e8290bec52f6c4b Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 28 Jul 2020 18:23:38 +0300 Subject: [PATCH 105/426] edit maxID to uint32 --- core/state/bus/candidates.go | 2 +- core/state/candidates/candidates.go | 28 +++++++++++----------- core/state/candidates/export_v11_old.go | 4 ++-- core/state/candidates/model.go | 6 ++--- core/state/legacy/candidates/candidates.go | 2 +- core/types/appstate.go | 2 +- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/core/state/bus/candidates.go b/core/state/bus/candidates.go index b9cdbaf0d..f53e0512d 100644 --- a/core/state/bus/candidates.go +++ b/core/state/bus/candidates.go @@ -21,7 +21,7 @@ type Stake struct { } type Candidate struct { - ID uint + ID uint32 PubKey types.Pubkey RewardAddress types.Address OwnerAddress types.Address diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index ab40749ea..5b5b88ed0 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -54,12 +54,12 @@ type RCandidates interface { } type Candidates struct { - list map[uint]*Candidate + list map[uint32]*Candidate isDirty bool blockList map[types.Pubkey]struct{} - pubKeyIDs map[types.Pubkey]uint - maxID uint + pubKeyIDs map[types.Pubkey]uint32 + maxID uint32 iavl tree.MTree bus *bus.Bus @@ -236,7 +236,7 @@ func (c *Candidates) Create(ownerAddress, rewardAddress, controlAddress types.Ad c.setToMap(pubkey, candidate) } -func (c *Candidates) CreateWithID(ownerAddress, rewardAddress, controlAddress types.Address, pubkey types.Pubkey, commission uint, id uint) { +func (c *Candidates) CreateWithID(ownerAddress, rewardAddress, controlAddress types.Address, pubkey types.Pubkey, commission uint, id uint32) { if id != 0 { c.setPubKeyID(pubkey, id) } @@ -817,12 +817,12 @@ func (c *Candidates) LoadCandidatesDeliver() { _, valueMaxID := c.iavl.Get([]byte{maxIDPrefix}) if len(valueMaxID) != 0 { - c.maxID = uint(binary.LittleEndian.Uint32(valueMaxID)) + c.maxID = binary.LittleEndian.Uint32(valueMaxID) } } -func (c *Candidates) loadCandidatesList() (maxID uint) { +func (c *Candidates) loadCandidatesList() (maxID uint32) { _, pubIDenc := c.iavl.Get([]byte{pubKeyIDPrefix}) if len(pubIDenc) != 0 { var pubIDs []pubkeyID @@ -830,7 +830,7 @@ func (c *Candidates) loadCandidatesList() (maxID uint) { panic(fmt.Sprintf("failed to decode candidates: %s", err)) } - pubKeyIDs := map[types.Pubkey]uint{} + pubKeyIDs := map[types.Pubkey]uint32{} for _, v := range pubIDs { pubKeyIDs[v.PubKey] = v.ID if v.ID > maxID { @@ -1096,7 +1096,7 @@ func (c *Candidates) setToMap(pubkey types.Pubkey, model *Candidate) { defer c.lock.Unlock() if c.list == nil { - c.list = map[uint]*Candidate{} + c.list = map[uint32]*Candidate{} } c.list[id] = model } @@ -1108,7 +1108,7 @@ func (c *Candidates) setBlockList(blockList map[types.Pubkey]struct{}) { c.blockList = blockList } -func (c *Candidates) setPubKeyIDs(list map[types.Pubkey]uint) { +func (c *Candidates) setPubKeyIDs(list map[types.Pubkey]uint32) { c.lock.Lock() defer c.lock.Unlock() @@ -1200,7 +1200,7 @@ func (c *Candidates) ChangePubKey(old types.Pubkey, new types.Pubkey) { delete(c.pubKeyIDs, old) } -func (c *Candidates) getOrNewID(pubKey types.Pubkey) uint { +func (c *Candidates) getOrNewID(pubKey types.Pubkey) uint32 { c.lock.RLock() id := c.id(pubKey) c.lock.RUnlock() @@ -1218,23 +1218,23 @@ func (c *Candidates) getOrNewID(pubKey types.Pubkey) uint { return id } -func (c *Candidates) id(pubKey types.Pubkey) uint { +func (c *Candidates) id(pubKey types.Pubkey) uint32 { return c.pubKeyIDs[pubKey] } -func (c *Candidates) ID(pubKey types.Pubkey) uint { +func (c *Candidates) ID(pubKey types.Pubkey) uint32 { c.lock.RLock() defer c.lock.RUnlock() return c.pubKeyIDs[pubKey] } -func (c *Candidates) setPubKeyID(pubkey types.Pubkey, u uint) { +func (c *Candidates) setPubKeyID(pubkey types.Pubkey, u uint32) { c.lock.Lock() defer c.lock.Unlock() if c.pubKeyIDs == nil { - c.pubKeyIDs = map[types.Pubkey]uint{} + c.pubKeyIDs = map[types.Pubkey]uint32{} } c.pubKeyIDs[pubkey] = u c.isDirty = true diff --git a/core/state/candidates/export_v11_old.go b/core/state/candidates/export_v11_old.go index f521c676a..b8fae7cfe 100644 --- a/core/state/candidates/export_v11_old.go +++ b/core/state/candidates/export_v11_old.go @@ -91,7 +91,7 @@ func (c *Candidates) LoadCandidates11() { path := []byte{mainPrefix} _, enc := c.iavl.Get(path) if len(enc) == 0 { - c.list = map[uint]*Candidate{} + c.list = map[uint32]*Candidate{} return } @@ -100,7 +100,7 @@ func (c *Candidates) LoadCandidates11() { panic(fmt.Sprintf("failed to decode candidates: %s", err)) } - c.list = map[uint]*Candidate{} + c.list = map[uint32]*Candidate{} for _, candidate := range candidates { // load total stake path = append([]byte{mainPrefix}, candidate.PubKey.Bytes()...) diff --git a/core/state/candidates/model.go b/core/state/candidates/model.go index d1f91eeb0..cc2b49e06 100644 --- a/core/state/candidates/model.go +++ b/core/state/candidates/model.go @@ -10,7 +10,7 @@ import ( type pubkeyID struct { PubKey types.Pubkey - ID uint + ID uint32 } type Candidate struct { @@ -20,7 +20,7 @@ type Candidate struct { ControlAddress types.Address Commission uint Status byte - ID uint + ID uint32 totalBipStake *big.Int stakesCount int @@ -36,7 +36,7 @@ type Candidate struct { func (candidate *Candidate) idBytes() []byte { bs := make([]byte, 4) - binary.LittleEndian.PutUint32(bs, uint32(candidate.ID)) + binary.LittleEndian.PutUint32(bs, candidate.ID) return bs } diff --git a/core/state/legacy/candidates/candidates.go b/core/state/legacy/candidates/candidates.go index 43dafe903..5c1eb7bd1 100644 --- a/core/state/legacy/candidates/candidates.go +++ b/core/state/legacy/candidates/candidates.go @@ -235,7 +235,7 @@ func (c *Candidates) Export(state *types.AppState, coinsMap map[types.CoinSymbol c.LoadCandidates() c.LoadStakes() - candidates, maxID := c.GetCandidates(), uint(1) + candidates, maxID := c.GetCandidates(), uint32(1) for _, candidate := range candidates { candidateStakes := c.GetStakes(candidate.PubKey) stakes := make([]types.Stake, len(candidateStakes)) diff --git a/core/types/appstate.go b/core/types/appstate.go index dc38fc058..36309c484 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -211,7 +211,7 @@ type Validator struct { } type Candidate struct { - ID uint `json:"id"` + ID uint32 `json:"id"` RewardAddress Address `json:"reward_address"` OwnerAddress Address `json:"owner_address"` ControlAddress Address `json:"control_address"` From ba856ca1c61602bd8bdb44857d66630dc76d12d2 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 28 Jul 2020 19:09:22 +0300 Subject: [PATCH 106/426] add missed_blocks back --- api/api.go | 1 + api/missed_blocks.go | 43 +++++++++++++++++++++++++++++++++++++++++ api/v2/service/block.go | 29 ++++++++++++++++++++++----- 3 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 api/missed_blocks.go diff --git a/api/api.go b/api/api.go index 7b384d497..cd54bc181 100644 --- a/api/api.go +++ b/api/api.go @@ -53,6 +53,7 @@ var Routes = map[string]*rpcserver.RPCFunc{ "max_gas": rpcserver.NewRPCFunc(MaxGas, "height"), "min_gas_price": rpcserver.NewRPCFunc(MinGasPrice, ""), "genesis": rpcserver.NewRPCFunc(Genesis, ""), + "missed_blocks": rpcserver.NewRPCFunc(MissedBlocks, "pub_key,height"), } func responseTime(b *minter.Blockchain) func(f func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) { diff --git a/api/missed_blocks.go b/api/missed_blocks.go new file mode 100644 index 000000000..3f0e7c324 --- /dev/null +++ b/api/missed_blocks.go @@ -0,0 +1,43 @@ +package api + +import ( + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/rpc/lib/types" +) + +type MissedBlocksResponse struct { + MissedBlocks *types.BitArray `json:"missed_blocks"` + MissedBlocksCount int `json:"missed_blocks_count"` +} + +func MissedBlocks(pubkey types.Pubkey, height int) (*MissedBlocksResponse, error) { + cState, err := GetStateForHeight(height) + if err != nil { + return nil, err + } + + if height != 0 { + cState.Lock() + cState.Validators().LoadValidators() + cState.Unlock() + } + + cState.RLock() + defer cState.RUnlock() + + vals := cState.Validators().GetValidators() + if vals == nil { + return nil, rpctypes.RPCError{Code: 404, Message: "Validators not found"} + } + + for _, val := range vals { + if val.PubKey == pubkey { + return &MissedBlocksResponse{ + MissedBlocks: val.AbsentTimes, + MissedBlocksCount: val.CountAbsentTimes(), + }, nil + } + } + + return nil, rpctypes.RPCError{Code: 404, Message: "Validator not found"} +} diff --git a/api/v2/service/block.go b/api/v2/service/block.go index fb6069b19..aa4c418f7 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -6,6 +6,7 @@ import ( "encoding/hex" "fmt" "github.com/MinterTeam/minter-go-node/core/rewards" + "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/core/transaction/encoder" "github.com/MinterTeam/minter-go-node/core/types" @@ -42,6 +43,7 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes } var totalValidators []*tmTypes.Validator + var cState *state.CheckState if len(req.Fields) == 0 { response.Size = fmt.Sprintf("%d", len(s.cdc.MustMarshalBinaryLengthPrefixed(block))) @@ -51,7 +53,7 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes return new(pb.BlockResponse), timeoutStatus.Err() } - cState, err := s.blockchain.GetStateForHeight(uint64(height)) + cState, err = s.blockchain.GetStateForHeight(uint64(height)) if err != nil { return nil, err } @@ -105,10 +107,17 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes response.Size = fmt.Sprintf("%d", len(s.cdc.MustMarshalBinaryLengthPrefixed(block))) case pb.BlockRequest_block_reward: response.BlockReward = rewards.GetRewardForBlock(uint64(height)).String() - case pb.BlockRequest_transactions: - cState, err := s.blockchain.GetStateForHeight(uint64(height)) - if err != nil { - return nil, err + case pb.BlockRequest_transactions, pb.BlockRequest_missed: + if cState == nil { + cState, err = s.blockchain.GetStateForHeight(uint64(height)) + if err != nil { + return nil, err + } + } + + if pb.BlockRequest_missed == field { + response.Missed = missedBlockValidators(cState) + continue } txJsonEncoder := encoder.NewTxEncoderJSON(cState) @@ -116,6 +125,7 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes if err != nil { return new(pb.BlockResponse), err } + case pb.BlockRequest_proposer, pb.BlockRequest_validators: if len(totalValidators) == 0 { tmValidators, err := s.client.Validators(&valHeight, 1, 100) @@ -175,6 +185,15 @@ func blockValidators(totalValidators []*tmTypes.Validator, block *core_types.Res return validators } +func missedBlockValidators(s *state.CheckState) []string { + var missedBloks []string + for _, val := range s.Validators().GetValidators() { + missedBloks = append(missedBloks, val.AbsentTimes.String()) + } + + return missedBloks +} + func blockProposer(block *core_types.ResultBlock, totalValidators []*tmTypes.Validator) (string, error) { p, err := getBlockProposer(block, totalValidators) if err != nil { From cfa632b391def59c64d4750b0b1b053bf94d918d Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 28 Jul 2020 19:11:47 +0300 Subject: [PATCH 107/426] const candidate count --- core/validators/validators.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/validators/validators.go b/core/validators/validators.go index 13dcd8a43..974b27baa 100644 --- a/core/validators/validators.go +++ b/core/validators/validators.go @@ -5,5 +5,5 @@ func GetValidatorsCountForBlock(block uint64) int { } func GetCandidatesCountForBlock(block uint64) int { - return GetValidatorsCountForBlock(block) * 3 + return 192 } From b3eb6ed759cbcc9ca906ad3116cbc273987db272 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 28 Jul 2020 19:19:18 +0300 Subject: [PATCH 108/426] change config and refactor --- api/v2/service/address.go | 4 ++-- api/v2/service/service.go | 2 +- config/config.go | 4 ++-- config/toml.go | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/api/v2/service/address.go b/api/v2/service/address.go index fdd7dea61..78f68f235 100644 --- a/api/v2/service/address.go +++ b/api/v2/service/address.go @@ -144,12 +144,12 @@ func customCoinBipBalance(coinToSell types.CoinID, valueToSell *big.Int, cState return valueToSell } - if coinToSell == types.GetBaseCoinID() { + if coinToSell.IsBaseCoin() { coin := cState.Coins().GetCoin(coinToBuy) return formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) } - if coinToBuy == types.GetBaseCoinID() { + if coinToBuy.IsBaseCoin() { coin := cState.Coins().GetCoin(coinToSell) return formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) } diff --git a/api/v2/service/service.go b/api/v2/service/service.go index 77063471d..429a49a1c 100644 --- a/api/v2/service/service.go +++ b/api/v2/service/service.go @@ -53,7 +53,7 @@ func (s *Service) createError(statusErr *status.Status, data string) error { } func (s *Service) TimeoutDuration() time.Duration { - return time.Duration(s.minterCfg.APIv2TimeoutDuration) + return s.minterCfg.APIv2TimeoutDuration } func (s *Service) checkTimeout(ctx context.Context) *status.Status { diff --git a/config/config.go b/config/config.go index 179a1e5ff..9e00a7623 100644 --- a/config/config.go +++ b/config/config.go @@ -234,7 +234,7 @@ type BaseConfig struct { APIv2ListenAddress string `mapstructure:"api_v2_listen_addr"` // API v2 Timeout - APIv2TimeoutDuration int64 `mapstructure:"api_v2_timeout_duration"` + APIv2TimeoutDuration time.Duration `mapstructure:"api_v2_timeout_duration"` ValidatorMode bool `mapstructure:"validator_mode"` @@ -268,7 +268,7 @@ func DefaultBaseConfig() BaseConfig { APIListenAddress: "tcp://0.0.0.0:8841", GRPCListenAddress: "tcp://0.0.0.0:8842", APIv2ListenAddress: "tcp://0.0.0.0:8843", - APIv2TimeoutDuration: 10 * time.Second.Nanoseconds(), + APIv2TimeoutDuration: 10 * time.Second, ValidatorMode: false, KeepLastStates: 120, StateCacheSize: 1000000, diff --git a/config/toml.go b/config/toml.go index 205248b16..b38076ab3 100644 --- a/config/toml.go +++ b/config/toml.go @@ -58,7 +58,7 @@ func WriteConfigFile(configFilePath string, config *Config) { // Note: any changes to the comments/variables/mapstructure // must be reflected in the appropriate struct in config/config.go -const defaultConfigTemplate = `# This is a TOML config file. +const defaultConfigTemplate string = `# This is a TOML config file. # For more information, see https://github.com/toml-lang/toml ##### main base config options ##### @@ -81,7 +81,7 @@ api_v2_timeout_duration = "{{ .BaseConfig.APIv2TimeoutDuration }}" # Sets node to be in validator mode. Disables API, events, history of blocks, indexes, etc. validator_mode = {{ .BaseConfig.ValidatorMode }} -# Sets number of last stated to be saved on disk. If the value is 0, then the KeepEver and KeepRecent strategies are used. +# Sets number of last stated to be saved on disk. keep_last_states = {{ .BaseConfig.KeepLastStates }} # State cache size From bb7fe2b283e4740c7022cdf4a5e846d9982edd89 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 28 Jul 2020 22:35:29 +0300 Subject: [PATCH 109/426] refactor candidates --- core/minter/minter.go | 2 +- core/state/candidates/candidates.go | 38 +++++++++++---------------- core/transaction/declare_candidacy.go | 2 +- core/transaction/edit_candidate.go | 2 +- 4 files changed, 19 insertions(+), 25 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index 06030490b..d021b76b3 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -536,7 +536,7 @@ func (app *Blockchain) MissedBlocks(pubKey string, height uint64) (missedBlocks cState.RLock() defer cState.RUnlock() - val := cState.Validators().GetByPublicKey(types.HexToPubkey(pubKey[2:])) + val := cState.Validators().GetByPublicKey(types.HexToPubkey(pubKey)) if val == nil { return "", 0, status.Error(codes.NotFound, "Validator not found") } diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 5b5b88ed0..648f80896 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -25,19 +25,19 @@ const ( MaxDelegatorsPerCandidate = 1000 mainPrefix = 'c' - pubKeyIDPrefix = 'p' - blockListPrefix = 'b' + pubKeyIDPrefix = mainPrefix + 'p' + blockListPrefix = mainPrefix + 'b' stakesPrefix = 's' totalStakePrefix = 't' updatesPrefix = 'u' - maxIDPrefix = 'i' + maxIDPrefix = mainPrefix + 'i' ) type RCandidates interface { Export11To12(state *types.AppState) //todo: delete after start Node v1.1 Export(state *types.AppState) Exists(pubkey types.Pubkey) bool - IsBlockPubKey(pubkey *types.Pubkey) bool + IsBlockedPubKey(pubkey types.Pubkey) bool Count() int IsNewCandidateStakeSufficient(coin types.CoinID, stake *big.Int, limit int) bool IsDelegatorStakeSufficient(address types.Address, pubkey types.Pubkey, coin types.CoinID, amount *big.Int) bool @@ -112,12 +112,12 @@ func (c *Candidates) Commit() error { sort.SliceStable(pubIDs, func(i, j int) bool { return pubIDs[i].ID < pubIDs[j].ID }) - pubIDenc, err := rlp.EncodeToBytes(pubIDs) + pubIdData, err := rlp.EncodeToBytes(pubIDs) if err != nil { panic(fmt.Sprintf("failed to encode candidates public key with ID: %s", err)) } - c.iavl.Set([]byte{pubKeyIDPrefix}, pubIDenc) + c.iavl.Set([]byte{pubKeyIDPrefix}, pubIdData) var blockList []types.Pubkey for pubKey := range c.blockList { @@ -237,9 +237,7 @@ func (c *Candidates) Create(ownerAddress, rewardAddress, controlAddress types.Ad } func (c *Candidates) CreateWithID(ownerAddress, rewardAddress, controlAddress types.Address, pubkey types.Pubkey, commission uint, id uint32) { - if id != 0 { - c.setPubKeyID(pubkey, id) - } + c.setPubKeyID(pubkey, id) c.Create(ownerAddress, rewardAddress, controlAddress, pubkey, commission) } @@ -604,15 +602,11 @@ func (c *Candidates) existPubKey(pubKey types.Pubkey) bool { return exists } -func (c *Candidates) IsBlockPubKey(pubkey *types.Pubkey) bool { - if pubkey == nil { - return false - } - - return c.isBlock(*pubkey) +func (c *Candidates) IsBlockedPubKey(pubkey types.Pubkey) bool { + return c.isBlocked(pubkey) } -func (c *Candidates) isBlock(pubKey types.Pubkey) bool { +func (c *Candidates) isBlocked(pubKey types.Pubkey) bool { c.lock.Lock() defer c.lock.Unlock() @@ -870,7 +864,7 @@ func (c *Candidates) loadCandidatesList() (maxID uint32) { func (c *Candidates) checkAndSetLoaded() bool { c.lock.RLock() if c.loaded { - c.lock.RLock() + c.lock.RUnlock() return true } c.lock.RUnlock() @@ -1186,11 +1180,7 @@ func (c *Candidates) LoadStakesOfCandidate(pubkey types.Pubkey) { } func (c *Candidates) ChangePubKey(old types.Pubkey, new types.Pubkey) { - if old == new { - return - } - - if c.isBlock(new) { + if c.isBlocked(new) { panic("Candidate with such public key (" + new.String() + ") exists in block list") } @@ -1230,6 +1220,10 @@ func (c *Candidates) ID(pubKey types.Pubkey) uint32 { } func (c *Candidates) setPubKeyID(pubkey types.Pubkey, u uint32) { + if u == 0 { + panic("public key of candidate cannot be equal 0") + } + c.lock.Lock() defer c.lock.Unlock() diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index 4b13ebf3f..95476e630 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -69,7 +69,7 @@ func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.Chec } } - if context.Candidates().IsBlockPubKey(&data.PubKey) { + if context.Candidates().IsBlockedPubKey(data.PubKey) { return &Response{ Code: code.PublicKeyInBlockList, Log: fmt.Sprintf("Candidate with such public key (%s) exists in block list", data.PubKey.String()), diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index d3831de6b..ff82794da 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -125,7 +125,7 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa } } - if checkState.Candidates().IsBlockPubKey(data.NewPubKey) { + if data.NewPubKey != nil && checkState.Candidates().IsBlockedPubKey(*data.NewPubKey) { return Response{ Code: code.PublicKeyInBlockList, Log: fmt.Sprintf("Public key (%s) exists in block list", data.NewPubKey.String()), From ca0573b52f25f4e1f85b6efca664cb1f9cd6ae0f Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 28 Jul 2020 22:36:39 +0300 Subject: [PATCH 110/426] Missed in api block method --- api/v2/service/block.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/api/v2/service/block.go b/api/v2/service/block.go index aa4c418f7..f463c1269 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -95,6 +95,12 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes response.Evidence = blockEvidence(block) + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.BlockResponse), timeoutStatus.Err() + } + + response.Missed = missedBlockValidators(cState) + return response, nil } From 4f2ef7a93014314eb3e8a15c6865c90e68f7fa28 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 28 Jul 2020 22:39:13 +0300 Subject: [PATCH 111/426] fix --- api/v2/service/block.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/v2/service/block.go b/api/v2/service/block.go index f463c1269..d4f21288b 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -192,12 +192,12 @@ func blockValidators(totalValidators []*tmTypes.Validator, block *core_types.Res } func missedBlockValidators(s *state.CheckState) []string { - var missedBloks []string + var missedBlocks []string for _, val := range s.Validators().GetValidators() { - missedBloks = append(missedBloks, val.AbsentTimes.String()) + missedBlocks = append(missedBlocks, val.AbsentTimes.String()) } - return missedBloks + return missedBlocks } func blockProposer(block *core_types.ResultBlock, totalValidators []*tmTypes.Validator) (string, error) { From bf8a62087aeef866268f7bffe39b7baa0883ea61 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 28 Jul 2020 22:41:04 +0300 Subject: [PATCH 112/426] fix --- core/state/candidates/candidates.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 648f80896..56591bd0c 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -27,10 +27,10 @@ const ( mainPrefix = 'c' pubKeyIDPrefix = mainPrefix + 'p' blockListPrefix = mainPrefix + 'b' + maxIDPrefix = mainPrefix + 'i' stakesPrefix = 's' totalStakePrefix = 't' updatesPrefix = 'u' - maxIDPrefix = mainPrefix + 'i' ) type RCandidates interface { From ffd968ecb7f0c602a98feb869743c68aeabe1f29 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 29 Jul 2020 11:02:43 +0300 Subject: [PATCH 113/426] add name to recreate coin tx --- core/state/coins/coins.go | 4 ++-- core/transaction/recreate_coin.go | 8 ++++++++ core/transaction/recreate_coin_test.go | 5 +++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index a7094c7d8..be92e91f6 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -221,7 +221,7 @@ func (c *Coins) Create(id types.CoinID, symbol types.CoinSymbol, name string, c.bus.Checker().AddCoinVolume(coin.id, volume) } -func (c *Coins) Recreate(newID types.CoinID, symbol types.CoinSymbol, +func (c *Coins) Recreate(newID types.CoinID, name string, symbol types.CoinSymbol, volume *big.Int, crr uint, reserve *big.Int, maxSupply *big.Int, ) { recreateCoin := c.GetCoinBySymbol(symbol) @@ -247,7 +247,7 @@ func (c *Coins) Recreate(newID types.CoinID, symbol types.CoinSymbol, c.setToMap(recreateCoin.id, recreateCoin) c.markDirty(recreateCoin.id) - c.Create(newID, recreateCoin.Symbol(), "", volume, crr, reserve, maxSupply, nil) + c.Create(newID, recreateCoin.Symbol(), name, volume, crr, reserve, maxSupply, nil) } func (c *Coins) ChangeOwner(symbol types.CoinSymbol, owner types.Address) { diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 62da4b1de..629b2d89e 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -13,6 +13,7 @@ import ( ) type RecreateCoinData struct { + Name string Symbol types.CoinSymbol InitialAmount *big.Int InitialReserve *big.Int @@ -31,6 +32,12 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta Log: "Incorrect tx data"} } + if len(data.Name) > maxCoinNameBytes { + return &Response{ + Code: code.InvalidCoinName, + Log: fmt.Sprintf("Coin name is invalid. Allowed up to %d bytes.", maxCoinNameBytes)} + } + if data.ConstantReserveRatio < 10 || data.ConstantReserveRatio > 100 { return &Response{ Code: code.WrongCrr, @@ -188,6 +195,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar coinID := deliverState.App.GetNextCoinID() deliverState.Coins.Recreate( coinID, + data.Name, data.Symbol, data.InitialAmount, data.ConstantReserveRatio, diff --git a/core/transaction/recreate_coin_test.go b/core/transaction/recreate_coin_test.go index fc61715ec..03444b2f0 100644 --- a/core/transaction/recreate_coin_test.go +++ b/core/transaction/recreate_coin_test.go @@ -29,6 +29,7 @@ func TestRecreateCoinTx(t *testing.T) { crr := uint(50) data := RecreateCoinData{ + Name: "TEST", Symbol: getTestCoinSymbol(), InitialAmount: amount, InitialReserve: reserve, @@ -86,6 +87,10 @@ func TestRecreateCoinTx(t *testing.T) { t.Fatalf("Version in state is not correct. Expected %d, got %d", 0, stateCoin.Version()) } + if stateCoin.Name() != "TEST" { + t.Fatalf("Name in state is not correct. Expected TEST, got %s", stateCoin.Name()) + } + archiveCoinSymbol := types.StrToCoinSymbol(fmt.Sprintf("%s-1", getTestCoinSymbol())) stateCoin = cState.Coins.GetCoinBySymbol(archiveCoinSymbol) From b830e65bca9ce03d6e8c2c4fe33b348d78f5086f Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 29 Jul 2020 12:04:49 +0300 Subject: [PATCH 114/426] merge coin_id and coin_info endpoints --- api/addresses.go | 2 +- api/api.go | 3 +- api/coin_id.go | 38 -------------------------- api/coin_info.go | 20 +++++++++++--- api/v2/service/coin_info.go | 2 +- core/state/coins/coins.go | 17 ++++-------- core/transaction/change_owner_test.go | 2 +- core/transaction/create_coin_test.go | 2 +- core/transaction/recreate_coin.go | 2 +- core/transaction/recreate_coin_test.go | 8 ++---- core/types/types.go | 22 ++++++--------- 11 files changed, 40 insertions(+), 78 deletions(-) delete mode 100644 api/coin_id.go diff --git a/api/addresses.go b/api/addresses.go index d29963641..13940e303 100644 --- a/api/addresses.go +++ b/api/addresses.go @@ -6,7 +6,7 @@ import ( type AddressesResponse struct { Address string `json:"address"` - Balance []BalanceItem `json:"balances"` + Balance []BalanceItem `json:"balance"` TransactionCount uint64 `json:"transaction_count"` } diff --git a/api/api.go b/api/api.go index 7b384d497..d8481ee6d 100644 --- a/api/api.go +++ b/api/api.go @@ -43,8 +43,7 @@ var Routes = map[string]*rpcserver.RPCFunc{ "block": rpcserver.NewRPCFunc(Block, "height"), "events": rpcserver.NewRPCFunc(Events, "height"), "net_info": rpcserver.NewRPCFunc(NetInfo, ""), - "coin_info": rpcserver.NewRPCFunc(CoinInfo, "symbol,height"), - "coin_id": rpcserver.NewRPCFunc(CoinIdInfo, "id,height"), + "coin_info": rpcserver.NewRPCFunc(CoinInfo, "symbol,id,height"), "estimate_coin_sell": rpcserver.NewRPCFunc(EstimateCoinSell, "coin_to_sell,coin_to_buy,value_to_sell,height"), "estimate_coin_sell_all": rpcserver.NewRPCFunc(EstimateCoinSellAll, "coin_to_sell,coin_to_buy,value_to_sell,gas_price,height"), "estimate_coin_buy": rpcserver.NewRPCFunc(EstimateCoinBuy, "coin_to_sell,coin_to_buy,value_to_buy,height"), diff --git a/api/coin_id.go b/api/coin_id.go deleted file mode 100644 index 98e9370de..000000000 --- a/api/coin_id.go +++ /dev/null @@ -1,38 +0,0 @@ -package api - -import ( - "github.com/MinterTeam/minter-go-node/core/types" - rpctypes "github.com/MinterTeam/minter-go-node/rpc/lib/types" -) - -func CoinIdInfo(id int, height int) (*CoinInfoResponse, error) { - cState, err := GetStateForHeight(height) - if err != nil { - return nil, err - } - - cState.RLock() - defer cState.RUnlock() - - coin := cState.Coins().GetCoin(types.CoinID(id)) - if coin == nil { - return nil, rpctypes.RPCError{Code: 404, Message: "Coin not found"} - } - - var ownerAddress *types.Address - info := cState.Coins().GetSymbolInfo(coin.Symbol()) - if info != nil && info.OwnerAddress() != nil { - ownerAddress = info.OwnerAddress() - } - - return &CoinInfoResponse{ - ID: coin.ID().Uint32(), - Name: coin.Name(), - Symbol: coin.GetFullSymbol(), - Volume: coin.Volume().String(), - Crr: coin.Crr(), - ReserveBalance: coin.Reserve().String(), - MaxSupply: coin.MaxSupply().String(), - OwnerAddress: ownerAddress, - }, nil -} diff --git a/api/coin_info.go b/api/coin_info.go index 3c0c4a42e..d77ee7410 100644 --- a/api/coin_info.go +++ b/api/coin_info.go @@ -1,6 +1,7 @@ package api import ( + "github.com/MinterTeam/minter-go-node/core/state/coins" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/rpc/lib/types" ) @@ -16,7 +17,9 @@ type CoinInfoResponse struct { OwnerAddress *types.Address `json:"owner_address"` } -func CoinInfo(coinSymbol string, height int) (*CoinInfoResponse, error) { +func CoinInfo(coinSymbol *string, id *int, height int) (*CoinInfoResponse, error) { + var coin *coins.Model + cState, err := GetStateForHeight(height) if err != nil { return nil, err @@ -25,9 +28,18 @@ func CoinInfo(coinSymbol string, height int) (*CoinInfoResponse, error) { cState.RLock() defer cState.RUnlock() - coin := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinSymbol)) - if coin == nil { - return nil, rpctypes.RPCError{Code: 404, Message: "Coin not found"} + if coinSymbol != nil { + coin = cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(*coinSymbol), types.GetVersionFromSymbol(*coinSymbol)) + if coin == nil { + return nil, rpctypes.RPCError{Code: 404, Message: "Coin not found"} + } + } + + if id != nil { + coin = cState.Coins().GetCoin(types.CoinID(*id)) + if coin == nil { + return nil, rpctypes.RPCError{Code: 404, Message: "Coin not found"} + } } var ownerAddress *types.Address diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index 92ce159dc..ea5bacce5 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -18,7 +18,7 @@ func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.Co cState.RLock() defer cState.RUnlock() - coin := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.Symbol)) + coin := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.Symbol), 0) if coin == nil { return new(pb.CoinInfoResponse), status.Error(codes.FailedPrecondition, "Coin not found") } diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index be92e91f6..07f2ba850 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -27,7 +27,7 @@ type RCoins interface { ExistsBySymbol(symbol types.CoinSymbol) bool SubReserve(symbol types.CoinID, amount *big.Int) GetCoin(id types.CoinID) *Model - GetCoinBySymbol(symbol types.CoinSymbol) *Model + GetCoinBySymbol(symbol types.CoinSymbol, version types.CoinVersion) *Model GetSymbolInfo(symbol types.CoinSymbol) *SymbolInfo } @@ -127,17 +127,12 @@ func (c *Coins) ExistsBySymbol(symbol types.CoinSymbol) bool { return c.getBySymbol(symbol) != nil } -func (c *Coins) GetCoinBySymbol(symbol types.CoinSymbol) *Model { - coins := c.getBySymbol(symbol.GetBaseSymbol()) +func (c *Coins) GetCoinBySymbol(symbol types.CoinSymbol, version types.CoinVersion) *Model { + coins := c.getBySymbol(symbol) if len(coins) == 0 { return nil } - version, err := symbol.GetVersion() - if err != nil { - return nil - } - for _, coinID := range coins { coin := c.get(coinID) if coin.Version() == version { @@ -224,7 +219,7 @@ func (c *Coins) Create(id types.CoinID, symbol types.CoinSymbol, name string, func (c *Coins) Recreate(newID types.CoinID, name string, symbol types.CoinSymbol, volume *big.Int, crr uint, reserve *big.Int, maxSupply *big.Int, ) { - recreateCoin := c.GetCoinBySymbol(symbol) + recreateCoin := c.GetCoinBySymbol(symbol, 0) if recreateCoin == nil { panic("coin to recreate does not exists") } @@ -254,7 +249,7 @@ func (c *Coins) ChangeOwner(symbol types.CoinSymbol, owner types.Address) { info := c.getSymbolInfo(symbol) info.SetOwnerAddress(&owner) - coin := c.GetCoinBySymbol(symbol) + coin := c.GetCoinBySymbol(symbol, 0) coin.symbolInfo = info c.setToMap(coin.id, coin) @@ -357,7 +352,7 @@ func (c *Coins) getOrderedDirtyCoins() []types.CoinID { func (c *Coins) Export(state *types.AppState) { c.iavl.Iterate(func(key []byte, value []byte) bool { if key[0] == mainPrefix { - if key[1] == symbolPrefix || key[len(key) - 1] == infoPrefix { + if key[1] == symbolPrefix || key[len(key)-1] == infoPrefix { return false } diff --git a/core/transaction/change_owner_test.go b/core/transaction/change_owner_test.go index 79054c3de..c40d8ee65 100644 --- a/core/transaction/change_owner_test.go +++ b/core/transaction/change_owner_test.go @@ -153,4 +153,4 @@ func makeTestChangeOwnerTx(data ChangeOwnerData, privateKey *ecdsa.PrivateKey) ( } return encodedTx, nil -} \ No newline at end of file +} diff --git a/core/transaction/create_coin_test.go b/core/transaction/create_coin_test.go index ff67cc2ce..8b50c63a9 100644 --- a/core/transaction/create_coin_test.go +++ b/core/transaction/create_coin_test.go @@ -76,7 +76,7 @@ func TestCreateCoinTx(t *testing.T) { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", coin, targetBalance, balance) } - stateCoin := cState.Coins.GetCoinBySymbol(toCreate) + stateCoin := cState.Coins.GetCoinBySymbol(toCreate, 0) if stateCoin == nil { t.Fatalf("Coin %s not found in state", toCreate) diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 629b2d89e..9330720d5 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -64,7 +64,7 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta sender, _ := tx.Sender() - coin := context.Coins().GetCoinBySymbol(data.Symbol) + coin := context.Coins().GetCoinBySymbol(data.Symbol, 0) if coin == nil { return &Response{ Code: code.CoinNotExists, diff --git a/core/transaction/recreate_coin_test.go b/core/transaction/recreate_coin_test.go index 03444b2f0..e3259e52b 100644 --- a/core/transaction/recreate_coin_test.go +++ b/core/transaction/recreate_coin_test.go @@ -2,7 +2,6 @@ package transaction import ( "crypto/ecdsa" - "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" @@ -65,7 +64,7 @@ func TestRecreateCoinTx(t *testing.T) { } newCoinSymbol := getTestCoinSymbol() - stateCoin := cState.Coins.GetCoinBySymbol(newCoinSymbol) + stateCoin := cState.Coins.GetCoinBySymbol(newCoinSymbol, 0) if stateCoin == nil { t.Fatalf("Coin %s not found in state", newCoinSymbol) @@ -91,8 +90,7 @@ func TestRecreateCoinTx(t *testing.T) { t.Fatalf("Name in state is not correct. Expected TEST, got %s", stateCoin.Name()) } - archiveCoinSymbol := types.StrToCoinSymbol(fmt.Sprintf("%s-1", getTestCoinSymbol())) - stateCoin = cState.Coins.GetCoinBySymbol(archiveCoinSymbol) + stateCoin = cState.Coins.GetCoinBySymbol(newCoinSymbol, 1) if stateCoin == nil { t.Fatalf("Coin %s not found in state", newCoinSymbol) @@ -199,4 +197,4 @@ func makeTestRecreateCoinTx(data RecreateCoinData, privateKey *ecdsa.PrivateKey) } return encodedTx, nil -} \ No newline at end of file +} diff --git a/core/types/types.go b/core/types/types.go index d31f530e0..3569b171d 100644 --- a/core/types/types.go +++ b/core/types/types.go @@ -151,24 +151,20 @@ func (c CoinSymbol) IsBaseCoin() bool { return c.Compare(GetBaseCoin()) == 0 } -func (c CoinSymbol) GetBaseSymbol() CoinSymbol { - return StrToCoinSymbol(strings.Split(c.String(), "-")[0]) +func StrToCoinSymbol(s string) CoinSymbol { + var symbol CoinSymbol + copy(symbol[:], []byte(s)) + return symbol } -func (c CoinSymbol) GetVersion() (CoinVersion, error) { - parts := strings.Split(c.String(), "-") +func GetVersionFromSymbol(s string) CoinVersion { + parts := strings.Split(s, "-") if len(parts) == 1 { - return 0, nil + return 0 } - v, err := strconv.ParseUint(parts[1], 10, 16) - return CoinVersion(v), err -} - -func StrToCoinSymbol(s string) CoinSymbol { - var symbol CoinSymbol - copy(symbol[:], []byte(s)) - return symbol + v, _ := strconv.ParseUint(parts[1], 10, 16) + return CoinVersion(v) } type CoinID uint32 From 2527fe4a933341349ba3a89d5e33d92e38e32171 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 29 Jul 2020 12:09:11 +0300 Subject: [PATCH 115/426] fix coin_info --- api/coin_info.go | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/api/coin_info.go b/api/coin_info.go index d77ee7410..5193f6865 100644 --- a/api/coin_info.go +++ b/api/coin_info.go @@ -7,14 +7,14 @@ import ( ) type CoinInfoResponse struct { - ID uint32 `json:"id"` - Name string `json:"name"` - Symbol string `json:"symbol"` - Volume string `json:"volume"` - Crr uint `json:"crr"` - ReserveBalance string `json:"reserve_balance"` - MaxSupply string `json:"max_supply"` - OwnerAddress *types.Address `json:"owner_address"` + ID uint32 `json:"id"` + Name string `json:"name"` + Symbol string `json:"symbol"` + Volume string `json:"volume"` + Crr uint `json:"crr"` + ReserveBalance string `json:"reserve_balance"` + MaxSupply string `json:"max_supply"` + OwnerAddress *string `json:"owner_address"` } func CoinInfo(coinSymbol *string, id *int, height int) (*CoinInfoResponse, error) { @@ -28,6 +28,10 @@ func CoinInfo(coinSymbol *string, id *int, height int) (*CoinInfoResponse, error cState.RLock() defer cState.RUnlock() + if coinSymbol == nil && id == nil { + return nil, rpctypes.RPCError{Code: 404, Message: "Coin not found"} + } + if coinSymbol != nil { coin = cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(*coinSymbol), types.GetVersionFromSymbol(*coinSymbol)) if coin == nil { @@ -42,10 +46,11 @@ func CoinInfo(coinSymbol *string, id *int, height int) (*CoinInfoResponse, error } } - var ownerAddress *types.Address + var ownerAddress *string info := cState.Coins().GetSymbolInfo(coin.Symbol()) if info != nil && info.OwnerAddress() != nil { - ownerAddress = info.OwnerAddress() + owner := info.OwnerAddress().String() + ownerAddress = &owner } return &CoinInfoResponse{ From 2020ed6106ac81c2b406440e94803af1920e3ac4 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 29 Jul 2020 12:15:23 +0300 Subject: [PATCH 116/426] remove tx json marshaling --- core/transaction/buy_coin.go | 15 ------------ core/transaction/buy_coin_test.go | 26 --------------------- core/transaction/create_coin.go | 20 ---------------- core/transaction/create_multisig.go | 19 --------------- core/transaction/declare_candidacy.go | 18 -------------- core/transaction/delegate.go | 13 ----------- core/transaction/edit_candidate.go | 21 ----------------- core/transaction/redeem_check.go | 12 ---------- core/transaction/sell_all_coin.go | 13 ----------- core/transaction/sell_coin.go | 15 ------------ core/transaction/send.go | 16 ------------- core/transaction/set_halt_block.go | 11 --------- core/transaction/switch_candidate_status.go | 8 ------- core/transaction/unbond.go | 13 ----------- 14 files changed, 220 deletions(-) diff --git a/core/transaction/buy_coin.go b/core/transaction/buy_coin.go index ebe8b465a..1bf51814f 100644 --- a/core/transaction/buy_coin.go +++ b/core/transaction/buy_coin.go @@ -2,7 +2,6 @@ package transaction import ( "encoding/hex" - "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" @@ -20,20 +19,6 @@ type BuyCoinData struct { MaximumValueToSell *big.Int } -func (data BuyCoinData) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - CoinToBuy string `json:"coin_to_buy"` - ValueToBuy string `json:"value_to_buy"` - CoinToSell string `json:"coin_to_sell"` - MaximumValueToSell string `json:"maximum_value_to_sell"` - }{ - CoinToBuy: data.CoinToBuy.String(), - ValueToBuy: data.ValueToBuy.String(), - CoinToSell: data.CoinToSell.String(), - MaximumValueToSell: data.MaximumValueToSell.String(), - }) -} - func (data BuyCoinData) String() string { return fmt.Sprintf("BUY COIN sell:%s buy:%s %s", data.CoinToSell.String(), data.ValueToBuy.String(), data.CoinToBuy.String()) diff --git a/core/transaction/buy_coin_test.go b/core/transaction/buy_coin_test.go index b65bd3a50..91a5cf10b 100644 --- a/core/transaction/buy_coin_test.go +++ b/core/transaction/buy_coin_test.go @@ -1,9 +1,7 @@ package transaction import ( - "bytes" "crypto/ecdsa" - "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" @@ -421,30 +419,6 @@ func TestBuyCoinTxNotGasCoin(t *testing.T) { } } -func TestBuyCoinTxJSON(t *testing.T) { - str := "{\"coin_to_buy\":\"%d\",\"value_to_buy\":\"1\",\"coin_to_sell\":\"1\",\"maximum_value_to_sell\":\"1\"}" - out := []byte(fmt.Sprintf(str, types.GetBaseCoinID())) - - coinID := createTestCoin(getState()) - - buyCoinData := BuyCoinData{ - CoinToBuy: types.GetBaseCoinID(), - ValueToBuy: big.NewInt(1), - CoinToSell: coinID, - MaximumValueToSell: big.NewInt(1), - } - - result, err := cdc.MarshalJSON(buyCoinData) - - if err != nil { - t.Fatalf("Error: %s", err.Error()) - } - - if !bytes.Equal(out, result) { - t.Fatalf("Error: result is not correct %s, expected %s", string(result), string(out)) - } -} - func TestBuyCoinTxCustomToBase(t *testing.T) { cState := getState() diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index 538455b3d..9ca8f5669 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -2,7 +2,6 @@ package transaction import ( "encoding/hex" - "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/state" @@ -12,7 +11,6 @@ import ( "github.com/tendermint/tendermint/libs/kv" "math/big" "regexp" - "strconv" ) const maxCoinNameBytes = 64 @@ -33,24 +31,6 @@ type CreateCoinData struct { MaxSupply *big.Int } -func (data CreateCoinData) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Name string `json:"name"` - Symbol string `json:"symbol"` - InitialAmount string `json:"initial_amount"` - InitialReserve string `json:"initial_reserve"` - ConstantReserveRatio string `json:"constant_reserve_ratio"` - MaxSupply string `json:"max_supply"` - }{ - Name: data.Name, - Symbol: data.Symbol.String(), - InitialAmount: data.InitialAmount.String(), - InitialReserve: data.InitialReserve.String(), - ConstantReserveRatio: strconv.Itoa(int(data.ConstantReserveRatio)), - MaxSupply: data.MaxSupply.String(), - }) -} - func (data CreateCoinData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { panic("implement me") } diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index 29477accb..3ff8cdfcb 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -2,7 +2,6 @@ package transaction import ( "encoding/hex" - "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" @@ -12,7 +11,6 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" "math/big" - "strconv" ) type CreateMultisigData struct { @@ -21,23 +19,6 @@ type CreateMultisigData struct { Addresses []types.Address } -func (data CreateMultisigData) MarshalJSON() ([]byte, error) { - var weights []string - for _, weight := range data.Weights { - weights = append(weights, strconv.Itoa(int(weight))) - } - - return json.Marshal(struct { - Threshold string `json:"threshold"` - Weights []string `json:"weights"` - Addresses []types.Address `json:"addresses"` - }{ - Threshold: strconv.Itoa(int(data.Threshold)), - Weights: weights, - Addresses: data.Addresses, - }) -} - func (data CreateMultisigData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { panic("implement me") } diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index 4b13ebf3f..72efbe83a 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -2,7 +2,6 @@ package transaction import ( "encoding/hex" - "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" @@ -12,7 +11,6 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" "math/big" - "strconv" ) const minCommission = 0 @@ -26,22 +24,6 @@ type DeclareCandidacyData struct { Stake *big.Int } -func (data DeclareCandidacyData) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Address string `json:"address"` - PubKey string `json:"pub_key"` - Commission string `json:"commission"` - Coin string `json:"coin"` - Stake string `json:"stake"` - }{ - Address: data.Address.String(), - PubKey: data.PubKey.String(), - Commission: strconv.Itoa(int(data.Commission)), - Coin: data.Coin.String(), - Stake: data.Stake.String(), - }) -} - func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if data.Stake == nil { return &Response{ diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index 9542b9709..bd5cb694b 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -2,7 +2,6 @@ package transaction import ( "encoding/hex" - "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" @@ -20,18 +19,6 @@ type DelegateData struct { Value *big.Int } -func (data DelegateData) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - PubKey string `json:"pub_key"` - Coin string `json:"coin"` - Value string `json:"value"` - }{ - PubKey: data.PubKey.String(), - Coin: data.Coin.String(), - Value: data.Value.String(), - }) -} - func (data DelegateData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { panic("implement me") } diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index d3831de6b..c1aeb0d14 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -2,7 +2,6 @@ package transaction import ( "encoding/hex" - "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" @@ -25,26 +24,6 @@ type EditCandidateData struct { ControlAddress types.Address } -func (data EditCandidateData) MarshalJSON() ([]byte, error) { - newPubKeyStr := "" - if data.NewPubKey != nil { - newPubKeyStr = data.NewPubKey.String() - } - return json.Marshal(struct { - PubKey string `json:"pub_key"` - NewPubKey string `json:"new_pub_key"` - RewardAddress string `json:"reward_address"` - OwnerAddress string `json:"owner_address"` - ControlAddress string `json:"owner_address"` - }{ - PubKey: data.PubKey.String(), - NewPubKey: newPubKeyStr, - RewardAddress: data.RewardAddress.String(), - OwnerAddress: data.OwnerAddress.String(), - ControlAddress: data.ControlAddress.String(), - }) -} - func (data EditCandidateData) GetPubKey() types.Pubkey { return data.PubKey } diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index 581424bca..976728b4f 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -2,9 +2,7 @@ package transaction import ( "bytes" - "encoding/base64" "encoding/hex" - "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/check" "github.com/MinterTeam/minter-go-node/core/code" @@ -24,16 +22,6 @@ type RedeemCheckData struct { Proof [65]byte } -func (data RedeemCheckData) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - RawCheck string `json:"raw_check"` - Proof string `json:"proof"` - }{ - RawCheck: base64.StdEncoding.EncodeToString(data.RawCheck), - Proof: base64.StdEncoding.EncodeToString(data.Proof[:]), - }) -} - func (data RedeemCheckData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { panic("implement me") } diff --git a/core/transaction/sell_all_coin.go b/core/transaction/sell_all_coin.go index 674af3138..180e146d6 100644 --- a/core/transaction/sell_all_coin.go +++ b/core/transaction/sell_all_coin.go @@ -2,7 +2,6 @@ package transaction import ( "encoding/hex" - "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" @@ -19,18 +18,6 @@ type SellAllCoinData struct { MinimumValueToBuy *big.Int } -func (data SellAllCoinData) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - CoinToSell string `json:"coin_to_sell"` - CoinToBuy string `json:"coin_to_buy"` - MinimumValueToBuy string `json:"minimum_value_to_buy"` - }{ - CoinToSell: data.CoinToSell.String(), - CoinToBuy: data.CoinToBuy.String(), - MinimumValueToBuy: data.MinimumValueToBuy.String(), - }) -} - func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { sender, _ := tx.Sender() diff --git a/core/transaction/sell_coin.go b/core/transaction/sell_coin.go index 6730ff06e..7992a0a16 100644 --- a/core/transaction/sell_coin.go +++ b/core/transaction/sell_coin.go @@ -2,7 +2,6 @@ package transaction import ( "encoding/hex" - "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" @@ -20,20 +19,6 @@ type SellCoinData struct { MinimumValueToBuy *big.Int } -func (data SellCoinData) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - CoinToSell string `json:"coin_to_sell"` - ValueToSell string `json:"value_to_sell"` - CoinToBuy string `json:"coin_to_buy"` - MinimumValueToBuy string `json:"minimum_value_to_buy"` - }{ - CoinToSell: data.CoinToSell.String(), - ValueToSell: data.ValueToSell.String(), - CoinToBuy: data.CoinToBuy.String(), - MinimumValueToBuy: data.MinimumValueToBuy.String(), - }) -} - func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { total := TotalSpends{} var conversions []Conversion diff --git a/core/transaction/send.go b/core/transaction/send.go index f0cea7f5a..42417cb01 100644 --- a/core/transaction/send.go +++ b/core/transaction/send.go @@ -2,7 +2,6 @@ package transaction import ( "encoding/hex" - "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" @@ -24,21 +23,6 @@ type Coin struct { Symbol string `json:"symbol"` } -func (data SendData) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Coin Coin `json:"coin"` - To string `json:"to"` - Value string `json:"value"` - }{ - Coin: Coin{ - ID: data.Coin.Uint32(), - Symbol: "", - }, - To: data.To.String(), - Value: data.Value.String(), - }) -} - func (data SendData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { total := TotalSpends{} var conversions []Conversion diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index 4d848b328..1fa70f3aa 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -2,7 +2,6 @@ package transaction import ( "encoding/hex" - "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" @@ -20,16 +19,6 @@ type SetHaltBlockData struct { Height uint64 } -func (data SetHaltBlockData) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - PubKey string `json:"pub_key"` - Height string `json:"height"` - }{ - PubKey: data.PubKey.String(), - Height: strconv.FormatUint(data.Height, 10), - }) -} - func (data SetHaltBlockData) GetPubKey() types.Pubkey { return data.PubKey } diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index 2aa656eff..e86d02a8b 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -17,14 +17,6 @@ type SetCandidateOnData struct { PubKey types.Pubkey } -func (data SetCandidateOnData) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - PubKey string `json:"pub_key"` - }{ - PubKey: data.PubKey.String(), - }) -} - func (data SetCandidateOnData) GetPubKey() types.Pubkey { return data.PubKey } diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index de6720fad..88e35f69f 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -2,7 +2,6 @@ package transaction import ( "encoding/hex" - "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" @@ -22,18 +21,6 @@ type UnbondData struct { Value *big.Int } -func (data UnbondData) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - PubKey string `json:"pub_key"` - Coin string `json:"coin"` - Value string `json:"value"` - }{ - PubKey: data.PubKey.String(), - Coin: data.Coin.String(), - Value: data.Value.String(), - }) -} - func (data UnbondData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { panic("implement me") } From 2b884f02c9c617b62e86c2c50be420e41b6fe189 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 29 Jul 2020 12:19:10 +0300 Subject: [PATCH 117/426] fix endian at halts, coins --- core/state/halts/halts.go | 2 +- core/types/types.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/state/halts/halts.go b/core/state/halts/halts.go index fb9ada436..d5999d085 100644 --- a/core/state/halts/halts.go +++ b/core/state/halts/halts.go @@ -163,7 +163,7 @@ func (hb *HaltBlocks) setToMap(height uint64, model *Model) { func getPath(height uint64) []byte { b := make([]byte, 8) - binary.BigEndian.PutUint64(b, height) + binary.LittleEndian.PutUint64(b, height) return append([]byte{mainPrefix}, b...) } diff --git a/core/types/types.go b/core/types/types.go index 3569b171d..43d9944f4 100644 --- a/core/types/types.go +++ b/core/types/types.go @@ -179,7 +179,7 @@ func (c CoinID) String() string { func (c CoinID) Bytes() []byte { b := make([]byte, 4) - binary.BigEndian.PutUint32(b, c.Uint32()) + binary.LittleEndian.PutUint32(b, c.Uint32()) return b } @@ -188,7 +188,7 @@ func (c CoinID) Uint32() uint32 { } func BytesToCoinID(bytes []byte) CoinID { - return CoinID(binary.BigEndian.Uint32(bytes)) + return CoinID(binary.LittleEndian.Uint32(bytes)) } type CoinVersion = uint16 From 8c64b73a040c8a418b0fd9c440dcddb58d70a522 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 29 Jul 2020 12:22:42 +0300 Subject: [PATCH 118/426] fix --- api/api.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/api.go b/api/api.go index d8481ee6d..e3936b2e3 100644 --- a/api/api.go +++ b/api/api.go @@ -44,9 +44,9 @@ var Routes = map[string]*rpcserver.RPCFunc{ "events": rpcserver.NewRPCFunc(Events, "height"), "net_info": rpcserver.NewRPCFunc(NetInfo, ""), "coin_info": rpcserver.NewRPCFunc(CoinInfo, "symbol,id,height"), - "estimate_coin_sell": rpcserver.NewRPCFunc(EstimateCoinSell, "coin_to_sell,coin_to_buy,value_to_sell,height"), - "estimate_coin_sell_all": rpcserver.NewRPCFunc(EstimateCoinSellAll, "coin_to_sell,coin_to_buy,value_to_sell,gas_price,height"), - "estimate_coin_buy": rpcserver.NewRPCFunc(EstimateCoinBuy, "coin_to_sell,coin_to_buy,value_to_buy,height"), + "estimate_coin_sell": rpcserver.NewRPCFunc(EstimateCoinSell, "coin_id_to_sell,coin_id_to_buy,value_to_sell,height"), + "estimate_coin_sell_all": rpcserver.NewRPCFunc(EstimateCoinSellAll, "coin_id_to_sell,coin_id_to_buy,value_to_sell,gas_price,height"), + "estimate_coin_buy": rpcserver.NewRPCFunc(EstimateCoinBuy, "coin_id_to_sell,coin_id_to_buy,value_to_buy,height"), "estimate_tx_commission": rpcserver.NewRPCFunc(EstimateTxCommission, "tx,height"), "unconfirmed_txs": rpcserver.NewRPCFunc(UnconfirmedTxs, "limit"), "max_gas": rpcserver.NewRPCFunc(MaxGas, "height"), From a6160339126b54f6eab3481764c3da28a44c5334 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 29 Jul 2020 12:31:38 +0300 Subject: [PATCH 119/426] refactor estimate endpoints --- api/estimate_coin_buy.go | 28 ++++++++++++++-------------- api/estimate_coin_sell.go | 26 +++++++++++++------------- api/estimate_coin_sell_all.go | 24 ++++++++++++------------ core/minter/minter.go | 10 +++------- core/state/bus/coins.go | 1 - 5 files changed, 42 insertions(+), 47 deletions(-) diff --git a/api/estimate_coin_buy.go b/api/estimate_coin_buy.go index 0b19e9888..347fa2532 100644 --- a/api/estimate_coin_buy.go +++ b/api/estimate_coin_buy.go @@ -15,7 +15,7 @@ type EstimateCoinBuyResponse struct { Commission string `json:"commission"` } -func EstimateCoinBuy(coinIdToSell uint64, coinIdToBuy uint64, valueToBuy *big.Int, height int) (*EstimateCoinBuyResponse, error) { +func EstimateCoinBuy(coinIdToSell uint32, coinIdToBuy uint32, valueToBuy *big.Int, height int) (*EstimateCoinBuyResponse, error) { cState, err := GetStateForHeight(height) if err != nil { return nil, err @@ -24,20 +24,20 @@ func EstimateCoinBuy(coinIdToSell uint64, coinIdToBuy uint64, valueToBuy *big.In cState.RLock() defer cState.RUnlock() - coinToSell := types.CoinID(coinIdToSell) - coinToBuy := types.CoinID(coinIdToBuy) + sellCoinID := types.CoinID(coinIdToSell) + buyCoinID := types.CoinID(coinIdToBuy) var result *big.Int - if coinToSell == coinToBuy { + if sellCoinID == buyCoinID { return nil, rpctypes.RPCError{Code: 400, Message: "\"From\" coin equals to \"to\" coin"} } - if !cState.Coins().Exists(coinToSell) { + if !cState.Coins().Exists(sellCoinID) { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to sell not exists"} } - if !cState.Coins().Exists(coinToBuy) { + if !cState.Coins().Exists(buyCoinID) { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to buy not exists"} } @@ -45,8 +45,8 @@ func EstimateCoinBuy(coinIdToSell uint64, coinIdToBuy uint64, valueToBuy *big.In commissionInBaseCoin.Mul(commissionInBaseCoin, transaction.CommissionMultiplier) commission := big.NewInt(0).Set(commissionInBaseCoin) - if coinToSell != types.GetBaseCoinID() { - coin := cState.Coins().GetCoin(coinToSell) + if !sellCoinID.IsBaseCoin() { + coin := cState.Coins().GetCoin(sellCoinID) if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { return nil, rpctypes.RPCError{Code: 400, Message: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", @@ -57,11 +57,11 @@ func EstimateCoinBuy(coinIdToSell uint64, coinIdToBuy uint64, valueToBuy *big.In } switch { - case coinToSell == types.GetBaseCoinID(): - coin := cState.Coins().GetCoin(coinToBuy) + case sellCoinID.IsBaseCoin(): + coin := cState.Coins().GetCoin(buyCoinID) result = formula.CalculatePurchaseAmount(coin.Volume(), coin.Reserve(), coin.Crr(), valueToBuy) - case coinToBuy == types.GetBaseCoinID(): - coin := cState.Coins().GetCoin(coinToSell) + case buyCoinID.IsBaseCoin(): + coin := cState.Coins().GetCoin(sellCoinID) if coin.Reserve().Cmp(valueToBuy) < 0 { return nil, rpctypes.RPCError{Code: 400, Message: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", @@ -70,8 +70,8 @@ func EstimateCoinBuy(coinIdToSell uint64, coinIdToBuy uint64, valueToBuy *big.In result = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), valueToBuy) default: - coinFrom := cState.Coins().GetCoin(coinToSell) - coinTo := cState.Coins().GetCoin(coinToBuy) + coinFrom := cState.Coins().GetCoin(sellCoinID) + coinTo := cState.Coins().GetCoin(buyCoinID) baseCoinNeeded := formula.CalculatePurchaseAmount(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), valueToBuy) if coinFrom.Reserve().Cmp(baseCoinNeeded) < 0 { diff --git a/api/estimate_coin_sell.go b/api/estimate_coin_sell.go index d622c24a8..eaf73cbbd 100644 --- a/api/estimate_coin_sell.go +++ b/api/estimate_coin_sell.go @@ -24,20 +24,20 @@ func EstimateCoinSell(coinIdToSell uint64, coinIdToBuy uint64, valueToSell *big. cState.RLock() defer cState.RUnlock() - coinToSell := types.CoinID(coinIdToSell) - coinToBuy := types.CoinID(coinIdToBuy) + sellCoinID := types.CoinID(coinIdToSell) + buyCoinID := types.CoinID(coinIdToBuy) var result *big.Int - if coinToSell == coinToBuy { + if sellCoinID == buyCoinID { return nil, rpctypes.RPCError{Code: 400, Message: "\"From\" coin equals to \"to\" coin"} } - if !cState.Coins().Exists(coinToSell) { + if !cState.Coins().Exists(sellCoinID) { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to sell not exists"} } - if !cState.Coins().Exists(coinToBuy) { + if !cState.Coins().Exists(buyCoinID) { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to buy not exists"} } @@ -45,8 +45,8 @@ func EstimateCoinSell(coinIdToSell uint64, coinIdToBuy uint64, valueToSell *big. commissionInBaseCoin.Mul(commissionInBaseCoin, transaction.CommissionMultiplier) commission := big.NewInt(0).Set(commissionInBaseCoin) - if coinToSell != types.GetBaseCoinID() { - coin := cState.Coins().GetCoin(coinToSell) + if !sellCoinID.IsBaseCoin() { + coin := cState.Coins().GetCoin(sellCoinID) if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { return nil, rpctypes.RPCError{Code: 400, Message: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", @@ -62,15 +62,15 @@ func EstimateCoinSell(coinIdToSell uint64, coinIdToBuy uint64, valueToSell *big. } switch { - case coinToSell == types.GetBaseCoinID(): - coin := cState.Coins().GetCoin(coinToBuy) + case sellCoinID.IsBaseCoin(): + coin := cState.Coins().GetCoin(buyCoinID) result = formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) - case coinToBuy == types.GetBaseCoinID(): - coin := cState.Coins().GetCoin(coinToSell) + case buyCoinID.IsBaseCoin(): + coin := cState.Coins().GetCoin(sellCoinID) result = formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) default: - coinFrom := cState.Coins().GetCoin(coinToSell) - coinTo := cState.Coins().GetCoin(coinToBuy) + coinFrom := cState.Coins().GetCoin(sellCoinID) + coinTo := cState.Coins().GetCoin(buyCoinID) basecoinValue := formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) result = formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), basecoinValue) } diff --git a/api/estimate_coin_sell_all.go b/api/estimate_coin_sell_all.go index 9c72d9572..cbf26c6ae 100644 --- a/api/estimate_coin_sell_all.go +++ b/api/estimate_coin_sell_all.go @@ -13,7 +13,7 @@ type EstimateCoinSellAllResponse struct { WillGet string `json:"will_get"` } -func EstimateCoinSellAll(coinIdToSell uint64, coinIdToBuy uint64, valueToSell *big.Int, gasPrice uint64, height int) (*EstimateCoinSellAllResponse, +func EstimateCoinSellAll(coinIdToSell uint32, coinIdToBuy uint32, valueToSell *big.Int, gasPrice uint64, height int) (*EstimateCoinSellAllResponse, error) { cState, err := GetStateForHeight(height) if err != nil { @@ -27,20 +27,20 @@ func EstimateCoinSellAll(coinIdToSell uint64, coinIdToBuy uint64, valueToSell *b gasPrice = 1 } - coinToSell := types.CoinID(coinIdToSell) - coinToBuy := types.CoinID(coinIdToBuy) + sellCoinID := types.CoinID(coinIdToSell) + buyCoinID := types.CoinID(coinIdToBuy) var result *big.Int - if coinToSell == coinToBuy { + if sellCoinID == buyCoinID { return nil, rpctypes.RPCError{Code: 400, Message: "\"From\" coin equals to \"to\" coin"} } - if !cState.Coins().Exists(coinToSell) { + if !cState.Coins().Exists(sellCoinID) { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to sell not exists"} } - if !cState.Coins().Exists(coinToBuy) { + if !cState.Coins().Exists(buyCoinID) { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to buy not exists"} } @@ -49,8 +49,8 @@ func EstimateCoinSellAll(coinIdToSell uint64, coinIdToBuy uint64, valueToSell *b commission := big.NewInt(0).Set(commissionInBaseCoin) switch { - case coinToSell == types.GetBaseCoinID(): - coin := cState.Coins().GetCoin(coinToBuy) + case sellCoinID.IsBaseCoin(): + coin := cState.Coins().GetCoin(buyCoinID) valueToSell.Sub(valueToSell, commission) if valueToSell.Cmp(big.NewInt(0)) != 1 { @@ -58,8 +58,8 @@ func EstimateCoinSellAll(coinIdToSell uint64, coinIdToBuy uint64, valueToSell *b } result = formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) - case coinToBuy == types.GetBaseCoinID(): - coin := cState.Coins().GetCoin(coinToSell) + case buyCoinID.IsBaseCoin(): + coin := cState.Coins().GetCoin(sellCoinID) result = formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) result.Sub(result, commission) @@ -67,8 +67,8 @@ func EstimateCoinSellAll(coinIdToSell uint64, coinIdToBuy uint64, valueToSell *b return nil, rpctypes.RPCError{Code: 400, Message: "Not enough coins to pay commission"} } default: - coinFrom := cState.Coins().GetCoin(coinToSell) - coinTo := cState.Coins().GetCoin(coinToBuy) + coinFrom := cState.Coins().GetCoin(sellCoinID) + coinTo := cState.Coins().GetCoin(buyCoinID) basecoinValue := formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) basecoinValue.Sub(basecoinValue, commission) diff --git a/core/minter/minter.go b/core/minter/minter.go index 06030490b..42d22d2e1 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -710,15 +710,11 @@ func (app *Blockchain) isApplicationHalted(height uint64) bool { return true } - if height < upgrades.UpgradeBlock4 { - return false - } - halts := app.stateDeliver.Halts.GetHaltBlocks(height) if halts != nil { // calculate total power of validators vals := app.stateDeliver.Validators.GetValidators() - totalPower, totalVotingPower := big.NewInt(0), big.NewInt(0) + totalPower, totalVotedPower := big.NewInt(0), big.NewInt(0) for _, val := range vals { // skip if candidate is not present if val.IsToDrop() || app.validatorsStatuses[val.GetAddress()] != ValidatorPresent { @@ -727,7 +723,7 @@ func (app *Blockchain) isApplicationHalted(height uint64) bool { for _, halt := range halts.List { if halt.Pubkey == val.PubKey { - totalVotingPower.Add(totalVotingPower, val.GetTotalBipStake()) + totalVotedPower.Add(totalVotedPower, val.GetTotalBipStake()) } } @@ -739,7 +735,7 @@ func (app *Blockchain) isApplicationHalted(height uint64) bool { } votingResult := new(big.Float).Quo( - new(big.Float).SetInt(totalVotingPower), + new(big.Float).SetInt(totalVotedPower), new(big.Float).SetInt(totalPower), ) diff --git a/core/state/bus/coins.go b/core/state/bus/coins.go index f85533c5a..9af9266c9 100644 --- a/core/state/bus/coins.go +++ b/core/state/bus/coins.go @@ -20,7 +20,6 @@ type Coin struct { Version types.CoinVersion Volume *big.Int Reserve *big.Int - OwnerAddress types.Address } func (m Coin) GetFullSymbol() string { From adb1a96d503882048c104bee74fcca4e08d68068 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 29 Jul 2020 14:40:38 +0300 Subject: [PATCH 120/426] fixes --- core/state/candidates/candidates.go | 8 ++++---- core/state/state.go | 2 +- core/transaction/encoder/resources.go | 15 ++++++++------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 56591bd0c..cccc48923 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -1185,7 +1185,7 @@ func (c *Candidates) ChangePubKey(old types.Pubkey, new types.Pubkey) { } c.getFromMap(old).PubKey = new - c.setBlockPybKey(old) + c.setBlockPubKey(old) c.setPubKeyID(new, c.pubKeyIDs[old]) delete(c.pubKeyIDs, old) } @@ -1234,7 +1234,7 @@ func (c *Candidates) setPubKeyID(pubkey types.Pubkey, u uint32) { c.isDirty = true } -func (c *Candidates) setBlockPybKey(p types.Pubkey) { +func (c *Candidates) setBlockPubKey(p types.Pubkey) { c.lock.Lock() defer c.lock.Unlock() if c.blockList == nil { @@ -1244,8 +1244,8 @@ func (c *Candidates) setBlockPybKey(p types.Pubkey) { c.isDirty = true } -func (c *Candidates) AddToBlockPybKey(p types.Pubkey) { - c.setBlockPybKey(p) +func (c *Candidates) AddToBlockPubKey(p types.Pubkey) { + c.setBlockPubKey(p) } func (c *Candidates) maxIDBytes() []byte { diff --git a/core/state/state.go b/core/state/state.go index ac07193ff..dd53079cc 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -306,7 +306,7 @@ func (s *State) Import(state types.AppState) error { s.Validators.SetValidators(vals) for _, pubkey := range state.BlockListCandidates { - s.Candidates.AddToBlockPybKey(pubkey) + s.Candidates.AddToBlockPubKey(pubkey) } for _, c := range state.Candidates { diff --git a/core/transaction/encoder/resources.go b/core/transaction/encoder/resources.go index d3fbef639..6def0d909 100644 --- a/core/transaction/encoder/resources.go +++ b/core/transaction/encoder/resources.go @@ -271,18 +271,19 @@ func (resource MultiSendDataResource) Transform(txData interface{}, context *sta // TxType 0x0E type EditCandidateDataResource struct { - PubKey string `json:"pub_key"` - NewPubKey string `json:"new_pub_key"` - RewardAddress string `json:"reward_address"` - OwnerAddress string `json:"owner_address"` - ControlAddress string `json:"control_address"` + PubKey string `json:"pub_key"` + NewPubKey *string `json:"new_pub_key"` + RewardAddress string `json:"reward_address"` + OwnerAddress string `json:"owner_address"` + ControlAddress string `json:"control_address"` } func (EditCandidateDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.EditCandidateData) - newPubKeyStr := "" + var newPubKeyStr *string if data.NewPubKey != nil { - newPubKeyStr = data.NewPubKey.String() + s := data.NewPubKey.String() + newPubKeyStr = &s } return EditCandidateDataResource{ PubKey: data.PubKey.String(), From 9d9b803ad117731eb78ef4e586029513b4071e02 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 29 Jul 2020 14:55:37 +0300 Subject: [PATCH 121/426] fix --- core/state/coins/coins.go | 1 - core/transaction/recreate_coin.go | 4 ---- 2 files changed, 5 deletions(-) diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index 07f2ba850..c205aa96a 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -227,7 +227,6 @@ func (c *Coins) Recreate(newID types.CoinID, name string, symbol types.CoinSymbo // update version for recreating coin symbolCoins := c.getBySymbol(symbol) - // TODO: change array to sorted array by version and get the last one lastVersion := uint16(0) for _, id := range symbolCoins { coin := c.get(id) diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 9330720d5..d0708be77 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -21,10 +21,6 @@ type RecreateCoinData struct { MaxSupply *big.Int } -func (data RecreateCoinData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { - panic("implement me") -} - func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if data.InitialReserve == nil || data.InitialAmount == nil || data.MaxSupply == nil { return &Response{ From 4ae0181673e3f73d245dec1535f7a747fb32b22c Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 29 Jul 2020 14:59:41 +0300 Subject: [PATCH 122/426] remove TotalSpend --- core/transaction/create_coin.go | 4 ---- core/transaction/create_multisig.go | 4 ---- core/transaction/delegate.go | 4 ---- core/transaction/multisend.go | 4 ---- core/transaction/recreate_coin.go | 4 ---- core/transaction/redeem_check.go | 8 -------- core/transaction/set_halt_block.go | 4 ---- core/transaction/unbond.go | 4 ---- 8 files changed, 36 deletions(-) diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index 9ca8f5669..d20338b18 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -31,10 +31,6 @@ type CreateCoinData struct { MaxSupply *big.Int } -func (data CreateCoinData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { - panic("implement me") -} - func (data CreateCoinData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if data.InitialReserve == nil || data.InitialAmount == nil || data.MaxSupply == nil { return &Response{ diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index 3ff8cdfcb..98eaa7911 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -19,10 +19,6 @@ type CreateMultisigData struct { Addresses []types.Address } -func (data CreateMultisigData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { - panic("implement me") -} - func (data CreateMultisigData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { lenWeights := len(data.Weights) if lenWeights > 32 { diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index bd5cb694b..fc7084038 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -19,10 +19,6 @@ type DelegateData struct { Value *big.Int } -func (data DelegateData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { - panic("implement me") -} - func (data DelegateData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if data.Value == nil { return &Response{ diff --git a/core/transaction/multisend.go b/core/transaction/multisend.go index 0d0f4ae5a..8e7ca4fec 100644 --- a/core/transaction/multisend.go +++ b/core/transaction/multisend.go @@ -19,10 +19,6 @@ type MultisendData struct { List []MultisendDataItem `json:"list"` } -func (data MultisendData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { - panic("implement me") -} - func (data MultisendData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { quantity := len(data.List) if quantity < 1 || quantity > 100 { diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 9330720d5..d0708be77 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -21,10 +21,6 @@ type RecreateCoinData struct { MaxSupply *big.Int } -func (data RecreateCoinData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { - panic("implement me") -} - func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if data.InitialReserve == nil || data.InitialAmount == nil || data.MaxSupply == nil { return &Response{ diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index 976728b4f..07a28d8c1 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -22,14 +22,6 @@ type RedeemCheckData struct { Proof [65]byte } -func (data RedeemCheckData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { - panic("implement me") -} - -func (data RedeemCheckData) CommissionInBaseCoin(tx *Transaction) *big.Int { - panic("implement me") -} - func (data RedeemCheckData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if data.RawCheck == nil { return &Response{ diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index 1fa70f3aa..63288b4b8 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -23,10 +23,6 @@ func (data SetHaltBlockData) GetPubKey() types.Pubkey { return data.PubKey } -func (data SetHaltBlockData) TotalSpend(tx *Transaction, context *state.State) (TotalSpends, []Conversion, *big.Int, *Response) { - panic("implement me") -} - func (data SetHaltBlockData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if !context.Candidates().Exists(data.PubKey) { return &Response{ diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 88e35f69f..403b7a13e 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -21,10 +21,6 @@ type UnbondData struct { Value *big.Int } -func (data UnbondData) TotalSpend(tx *Transaction, context *state.CheckState) (TotalSpends, []Conversion, *big.Int, *Response) { - panic("implement me") -} - func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { if data.Value == nil { return &Response{ From d6b4391191ac17e71fd185c2f19564130c85edf5 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 29 Jul 2020 15:15:46 +0300 Subject: [PATCH 123/426] apiV2 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 402b5f738..01e279bae 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200722132702-359ed49dcb7e + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200729121255-fdd723dc81d0 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 3f52ca27c..e4d22b71e 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200722132702-359ed49dcb7e h1:OcZyAKVZ7nhmxoeJ2aywygwUedmHi1WZxher/31LmnY= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200722132702-359ed49dcb7e/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200729121255-fdd723dc81d0 h1:dDVKqowm+p/rhQrggg1hk0ZSLfi3g9J1JHsr8JQRsvM= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200729121255-fdd723dc81d0/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From e3db039ffb72b46abb287be4a1a23889a983e64f Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 29 Jul 2020 15:30:02 +0300 Subject: [PATCH 124/426] remove UpgradeBlocks --- core/minter/minter.go | 18 +----------- core/minter/minter_test.go | 6 ++-- core/state/accounts/accounts.go | 6 +--- core/state/candidates/candidates.go | 10 ++----- core/state/candidates_test.go | 4 +-- core/state/validators/validators.go | 7 ++--- core/transaction/change_owner_test.go | 8 +++--- core/transaction/declare_candidacy_test.go | 4 +-- core/transaction/delegate_test.go | 4 +-- core/transaction/set_halt_block_test.go | 12 ++++---- core/transaction/unbond_test.go | 6 ++-- upgrades/blocks.go | 18 ------------ upgrades/grace.go | 32 ---------------------- 13 files changed, 28 insertions(+), 107 deletions(-) delete mode 100644 upgrades/blocks.go delete mode 100644 upgrades/grace.go diff --git a/core/minter/minter.go b/core/minter/minter.go index e09fe5044..f6969e0ac 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -16,7 +16,7 @@ import ( "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/core/validators" "github.com/MinterTeam/minter-go-node/helpers" - "github.com/MinterTeam/minter-go-node/upgrades" + "github.com/MinterTeam/minter-go-node/version" "github.com/syndtr/goleveldb/leveldb/filter" "github.com/syndtr/goleveldb/leveldb/opt" @@ -175,17 +175,6 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res panic(fmt.Sprintf("Application halted at height %d", height)) } - app.lock.Lock() - if upgrades.IsUpgradeBlock(height) { - var err error - app.stateDeliver, err = state.NewState(app.height, app.stateDB, app.eventsDB, app.cfg.StateCacheSize, app.cfg.KeepLastStates) - if err != nil { - panic(err) - } - app.stateCheck = state.NewCheckState(app.stateDeliver) - } - app.lock.Unlock() - app.stateDeliver.Lock() // compute max gas @@ -248,11 +237,6 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res app.stateDeliver.FrozenFunds.Delete(frozenFunds.Height()) } - if height >= upgrades.UpgradeBlock4 { - // delete halts from db - app.stateDeliver.Halts.Delete(height) - } - return abciTypes.ResponseBeginBlock{} } diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index e33e22600..1014d1810 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -17,7 +17,7 @@ import ( "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/log" "github.com/MinterTeam/minter-go-node/rlp" - "github.com/MinterTeam/minter-go-node/upgrades" + "github.com/tendermint/go-amino" tmConfig "github.com/tendermint/tendermint/config" log2 "github.com/tendermint/tendermint/libs/log" @@ -386,7 +386,7 @@ FORLOOP2: } func TestStopNetworkByHaltBlocks(t *testing.T) { - haltHeight := upgrades.UpgradeBlock4 + uint64(5) + haltHeight := 500000 + uint64(5) v1Pubkey := [32]byte{} v2Pubkey := [32]byte{} @@ -492,7 +492,7 @@ func makeValidatorsAndCandidates(pubkeys []string, stake *big.Int) ([]types.Vali } candidates[i] = types.Candidate{ - ID: uint(i) + 1, + ID: uint32(i) + 1, RewardAddress: addr, OwnerAddress: addr, ControlAddress: addr, diff --git a/core/state/accounts/accounts.go b/core/state/accounts/accounts.go index 2c2661df1..42228d5a7 100644 --- a/core/state/accounts/accounts.go +++ b/core/state/accounts/accounts.go @@ -8,7 +8,7 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/MinterTeam/minter-go-node/rlp" "github.com/MinterTeam/minter-go-node/tree" - "github.com/MinterTeam/minter-go-node/upgrades" + "math/big" "sort" "sync" @@ -216,10 +216,6 @@ func (a *Accounts) CreateMultisig(weights []uint, addresses []types.Address, thr account.MultisigData = msig account.markDirty(account.address) - if height > upgrades.UpgradeBlock1 { - account.isDirty = true - } - a.setToMap(address, account) return address diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index cccc48923..9073ab5ad 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -11,7 +11,7 @@ import ( "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/rlp" "github.com/MinterTeam/minter-go-node/tree" - "github.com/MinterTeam/minter-go-node/upgrades" + "math/big" "sort" "sync" @@ -291,13 +291,7 @@ func (c *Candidates) GetCandidateByTendermintAddress(address types.TmAddress) *C } func (c *Candidates) RecalculateStakes(height uint64) { - if height >= upgrades.UpgradeBlock3 { - c.recalculateStakesNew(height) - } else if height >= upgrades.UpgradeBlock2 { - c.recalculateStakesOld2(height) - } else { - c.recalculateStakesOld1(height) - } + c.recalculateStakesNew(height) } func (c *Candidates) recalculateStakesOld1(height uint64) { diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index bde1d88b8..e3add6f7d 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -6,14 +6,14 @@ import ( eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/state/candidates" "github.com/MinterTeam/minter-go-node/core/types" - "github.com/MinterTeam/minter-go-node/upgrades" + "github.com/tendermint/tendermint/crypto/ed25519" db "github.com/tendermint/tm-db" "math/big" "testing" ) -const height = upgrades.UpgradeBlock4 +const height = 500000 func TestSimpleDelegate(t *testing.T) { st := getState() diff --git a/core/state/validators/validators.go b/core/state/validators/validators.go index 5cc235751..2b294c5e4 100644 --- a/core/state/validators/validators.go +++ b/core/state/validators/validators.go @@ -10,7 +10,7 @@ import ( "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/rlp" "github.com/MinterTeam/minter-go-node/tree" - "github.com/MinterTeam/minter-go-node/upgrades" + "math/big" ) @@ -113,10 +113,7 @@ func (v *Validators) SetValidatorAbsent(height uint64, address types.TmAddress) validator.SetAbsent(height) if validator.CountAbsentTimes() > ValidatorMaxAbsentTimes { - if !upgrades.IsGraceBlock(height) { - v.punishValidator(height, address) - } - + v.punishValidator(height, address) v.turnValidatorOff(address) } } diff --git a/core/transaction/change_owner_test.go b/core/transaction/change_owner_test.go index c40d8ee65..6dc50071e 100644 --- a/core/transaction/change_owner_test.go +++ b/core/transaction/change_owner_test.go @@ -8,7 +8,7 @@ import ( "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/rlp" - "github.com/MinterTeam/minter-go-node/upgrades" + db "github.com/tendermint/tm-db" "math/big" "sync" @@ -42,7 +42,7 @@ func TestChangeOwnerTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, tx, big.NewInt(0), upgrades.UpgradeBlock4, &sync.Map{}, 0) + response := RunTx(cState, tx, big.NewInt(0), 500000, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) } @@ -91,7 +91,7 @@ func TestChangeOwnerTxWithWrongOwner(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, tx, big.NewInt(0), upgrades.UpgradeBlock4, &sync.Map{}, 0) + response := RunTx(cState, tx, big.NewInt(0), 500000, &sync.Map{}, 0) if response.Code != code.IsNotOwnerOfCoin { t.Fatalf("Response code is not 206. Error %s", response.Log) } @@ -121,7 +121,7 @@ func TestChangeOwnerTxWithWrongSymbol(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, tx, big.NewInt(0), upgrades.UpgradeBlock4, &sync.Map{}, 0) + response := RunTx(cState, tx, big.NewInt(0), 500000, &sync.Map{}, 0) if response.Code != code.CoinNotExists { t.Fatalf("Response code is not 102. Error %s", response.Log) } diff --git a/core/transaction/declare_candidacy_test.go b/core/transaction/declare_candidacy_test.go index 7e572b31a..81215792f 100644 --- a/core/transaction/declare_candidacy_test.go +++ b/core/transaction/declare_candidacy_test.go @@ -8,7 +8,7 @@ import ( "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/rlp" - "github.com/MinterTeam/minter-go-node/upgrades" + "math/big" "sync" "testing" @@ -118,7 +118,7 @@ func TestDeclareCandidacyTxOverflow(t *testing.T) { cState.Candidates.Delegate(types.Address{}, pubkey, types.GetBaseCoinID(), helpers.BipToPip(big.NewInt(10)), helpers.BipToPip(big.NewInt(10))) } - cState.Candidates.RecalculateStakes(upgrades.UpgradeBlock3) + cState.Candidates.RecalculateStakes(109000) privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) diff --git a/core/transaction/delegate_test.go b/core/transaction/delegate_test.go index f5273088a..934a121f7 100644 --- a/core/transaction/delegate_test.go +++ b/core/transaction/delegate_test.go @@ -6,7 +6,7 @@ import ( "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/rlp" - "github.com/MinterTeam/minter-go-node/upgrades" + "math/big" "math/rand" "sync" @@ -81,7 +81,7 @@ func TestDelegateTx(t *testing.T) { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", coin, targetBalance, balance) } - cState.Candidates.RecalculateStakes(upgrades.UpgradeBlock3) + cState.Candidates.RecalculateStakes(109000) stake := cState.Candidates.GetStakeOfAddress(pubkey, addr, coin) diff --git a/core/transaction/set_halt_block_test.go b/core/transaction/set_halt_block_test.go index a53c4b8f0..c24a329cd 100644 --- a/core/transaction/set_halt_block_test.go +++ b/core/transaction/set_halt_block_test.go @@ -7,7 +7,7 @@ import ( "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/rlp" - "github.com/MinterTeam/minter-go-node/upgrades" + db "github.com/tendermint/tm-db" "math/big" "math/rand" @@ -16,12 +16,12 @@ import ( ) func TestSetHaltBlockTx(t *testing.T) { - cState, err := state.NewState(upgrades.UpgradeBlock4, db.NewMemDB(), nil, 1, 1) + cState, err := state.NewState(500000, db.NewMemDB(), nil, 1, 1) if err != nil { t.Fatalf("Cannot load state. Error %s", err) } - haltHeight := upgrades.UpgradeBlock4 + uint64(100) + haltHeight := 500000 + uint64(100) privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() @@ -63,7 +63,7 @@ func TestSetHaltBlockTx(t *testing.T) { t.Fatal(err) } - response := RunTx(cState, encodedTx, big.NewInt(0), upgrades.UpgradeBlock4, &sync.Map{}, 0) + response := RunTx(cState, encodedTx, big.NewInt(0), 500000, &sync.Map{}, 0) if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) } @@ -91,7 +91,7 @@ func TestSetHaltBlockTx(t *testing.T) { } func TestSetHaltBlockTxWithWrongHeight(t *testing.T) { - currentHeight := uint64(upgrades.UpgradeBlock4 + 5) + currentHeight := uint64(500000 + 5) cState, err := state.NewState(currentHeight, db.NewMemDB(), nil, 1, 1) if err != nil { t.Fatalf("Cannot load state. Error %s", err) @@ -151,7 +151,7 @@ func TestSetHaltBlockTxWithWrongHeight(t *testing.T) { } func TestSetHaltBlockTxWithWrongOwnership(t *testing.T) { - currentHeight := uint64(upgrades.UpgradeBlock4 + 5) + currentHeight := uint64(500000 + 5) cState, err := state.NewState(currentHeight, db.NewMemDB(), nil, 1, 1) if err != nil { t.Fatalf("Cannot load state. Error %s", err) diff --git a/core/transaction/unbond_test.go b/core/transaction/unbond_test.go index 29afe7988..a3c501555 100644 --- a/core/transaction/unbond_test.go +++ b/core/transaction/unbond_test.go @@ -5,7 +5,7 @@ import ( "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/rlp" - "github.com/MinterTeam/minter-go-node/upgrades" + "math/big" "sync" "testing" @@ -25,7 +25,7 @@ func TestUnbondTx(t *testing.T) { value := helpers.BipToPip(big.NewInt(100)) cState.Candidates.Delegate(addr, pubkey, coin, value, big.NewInt(0)) - cState.Candidates.RecalculateStakes(upgrades.UpgradeBlock3) + cState.Candidates.RecalculateStakes(109000) data := UnbondData{ PubKey: pubkey, @@ -65,7 +65,7 @@ func TestUnbondTx(t *testing.T) { t.Fatalf("Response code is not 0. Error %s", response.Log) } - cState.Candidates.RecalculateStakes(upgrades.UpgradeBlock3) + cState.Candidates.RecalculateStakes(109000) targetBalance, _ := big.NewInt(0).SetString("999999800000000000000000", 10) balance := cState.Accounts.GetBalance(addr, coin) diff --git a/upgrades/blocks.go b/upgrades/blocks.go deleted file mode 100644 index b76b7b56e..000000000 --- a/upgrades/blocks.go +++ /dev/null @@ -1,18 +0,0 @@ -package upgrades - -const UpgradeBlock1 = 5000 -const UpgradeBlock2 = 38519 -const UpgradeBlock3 = 109000 -const UpgradeBlock4 = 500000 // TODO: fix this value - -func IsUpgradeBlock(height uint64) bool { - upgradeBlocks := []uint64{UpgradeBlock1, UpgradeBlock2, UpgradeBlock3, UpgradeBlock4} - - for _, block := range upgradeBlocks { - if height == block { - return true - } - } - - return false -} diff --git a/upgrades/grace.go b/upgrades/grace.go deleted file mode 100644 index e350ab55f..000000000 --- a/upgrades/grace.go +++ /dev/null @@ -1,32 +0,0 @@ -package upgrades - -var gracePeriods = []*gracePeriod{ - NewGracePeriod(1, 120), - NewGracePeriod(UpgradeBlock1, UpgradeBlock1+120), - NewGracePeriod(UpgradeBlock2, UpgradeBlock2+120), - NewGracePeriod(UpgradeBlock3, UpgradeBlock3+120), - NewGracePeriod(UpgradeBlock4, UpgradeBlock4+120), -} - -type gracePeriod struct { - from uint64 - to uint64 -} - -func (gp *gracePeriod) IsApplicable(block uint64) bool { - return block >= gp.from && block <= gp.to -} - -func NewGracePeriod(from uint64, to uint64) *gracePeriod { - return &gracePeriod{from: from, to: to} -} - -func IsGraceBlock(block uint64) bool { - for _, gp := range gracePeriods { - if gp.IsApplicable(block) { - return true - } - } - - return false -} From d77842682b7d1f7fd979513eac2f02ed83ae3030 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 29 Jul 2020 15:55:04 +0300 Subject: [PATCH 125/426] fixes --- core/minter/minter.go | 2 + core/state/accounts/accounts.go | 2 +- core/state/candidates/candidates.go | 1 - core/state/candidates/export_v11_old.go | 198 ------------------------ 4 files changed, 3 insertions(+), 200 deletions(-) delete mode 100644 core/state/candidates/export_v11_old.go diff --git a/core/minter/minter.go b/core/minter/minter.go index f6969e0ac..90db29276 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -237,6 +237,8 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res app.stateDeliver.FrozenFunds.Delete(frozenFunds.Height()) } + app.stateDeliver.Halts.Delete(height) + return abciTypes.ResponseBeginBlock{} } diff --git a/core/state/accounts/accounts.go b/core/state/accounts/accounts.go index 42228d5a7..c60aaacdc 100644 --- a/core/state/accounts/accounts.go +++ b/core/state/accounts/accounts.go @@ -215,7 +215,7 @@ func (a *Accounts) CreateMultisig(weights []uint, addresses []types.Address, thr account.MultisigData = msig account.markDirty(account.address) - + account.isDirty = true a.setToMap(address, account) return address diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 9073ab5ad..599d71f30 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -34,7 +34,6 @@ const ( ) type RCandidates interface { - Export11To12(state *types.AppState) //todo: delete after start Node v1.1 Export(state *types.AppState) Exists(pubkey types.Pubkey) bool IsBlockedPubKey(pubkey types.Pubkey) bool diff --git a/core/state/candidates/export_v11_old.go b/core/state/candidates/export_v11_old.go deleted file mode 100644 index b8fae7cfe..000000000 --- a/core/state/candidates/export_v11_old.go +++ /dev/null @@ -1,198 +0,0 @@ -package candidates - -import ( - "fmt" - "github.com/MinterTeam/minter-go-node/core/types" - "github.com/MinterTeam/minter-go-node/rlp" - "github.com/tendermint/tendermint/crypto/ed25519" - "math/big" -) - -type Candidate11 struct { - PubKey types.Pubkey - RewardAddress types.Address - OwnerAddress types.Address - Commission uint - Status byte - - totalBipStake *big.Int - stakesCount int - stakes [MaxDelegatorsPerCandidate]*Stake - updates []*Stake - tmAddress *types.TmAddress - - isDirty bool - isTotalStakeDirty bool - isUpdatesDirty bool - dirtyStakes [MaxDelegatorsPerCandidate]bool -} - -func (candidate *Candidate11) setTmAddress() { - // set tm address - var pubkey ed25519.PubKeyEd25519 - copy(pubkey[:], candidate.PubKey[:]) - - var address types.TmAddress - copy(address[:], pubkey.Address().Bytes()) - - candidate.tmAddress = &address -} - -func (c *Candidates) Export11To12(state *types.AppState) { - c.LoadCandidates11() - c.LoadStakes11() - - candidates := c.GetCandidates() - for _, candidate := range candidates { - candidateStakes := c.GetStakes(candidate.PubKey) - stakes := make([]types.Stake, len(candidateStakes)) - for i, s := range candidateStakes { - stakes[i] = types.Stake{ - Owner: s.Owner, - Coin: s.Coin, - Value: s.Value.String(), - BipValue: s.BipValue.String(), - } - } - - updates := make([]types.Stake, len(candidate.updates)) - for i, u := range candidate.updates { - updates[i] = types.Stake{ - Owner: u.Owner, - Coin: u.Coin, - Value: u.Value.String(), - BipValue: u.BipValue.String(), - } - } - - state.Candidates = append(state.Candidates, types.Candidate{ - ID: c.getOrNewID(candidate.PubKey), - RewardAddress: candidate.RewardAddress, - OwnerAddress: candidate.OwnerAddress, - ControlAddress: candidate.ControlAddress, - TotalBipStake: candidate.GetTotalBipStake().String(), - PubKey: candidate.PubKey, - Commission: candidate.Commission, - Status: candidate.Status, - Updates: updates, - Stakes: stakes, - }) - } - - return -} - -func (c *Candidates) LoadCandidates11() { - if c.loaded { - return - } - c.loaded = true - - path := []byte{mainPrefix} - _, enc := c.iavl.Get(path) - if len(enc) == 0 { - c.list = map[uint32]*Candidate{} - return - } - - var candidates []*Candidate11 - if err := rlp.DecodeBytes(enc, &candidates); err != nil { - panic(fmt.Sprintf("failed to decode candidates: %s", err)) - } - - c.list = map[uint32]*Candidate{} - for _, candidate := range candidates { - // load total stake - path = append([]byte{mainPrefix}, candidate.PubKey.Bytes()...) - path = append(path, totalStakePrefix) - _, enc = c.iavl.Get(path) - if len(enc) == 0 { - candidate.totalBipStake = big.NewInt(0) - } else { - candidate.totalBipStake = big.NewInt(0).SetBytes(enc) - } - - candidate.setTmAddress() - c.setToMap(candidate.PubKey, &Candidate{ - PubKey: candidate.PubKey, - RewardAddress: candidate.RewardAddress, - OwnerAddress: candidate.OwnerAddress, - ControlAddress: types.HexToAddress("Mxf8a88c0ed668e995639cb8a08ffb38541bcc9045"), - Commission: candidate.Commission, - Status: candidate.Status, - ID: c.getOrNewID(candidate.PubKey), - }) - } -} - -func (c *Candidates) LoadStakes11() { - for _, candidate := range c.list { - c.LoadStakesOfCandidate11(candidate.PubKey) - } -} - -func (c *Candidates) LoadStakesOfCandidate11(pubkey types.Pubkey) { - candidate := c.GetCandidate(pubkey) - - // load stakes - stakesCount := 0 - for index := 0; index < MaxDelegatorsPerCandidate; index++ { - path := []byte{mainPrefix} - path = append(path, candidate.PubKey.Bytes()...) - path = append(path, stakesPrefix) - path = append(path, []byte(fmt.Sprintf("%d", index))...) - _, enc := c.iavl.Get(path) - if len(enc) == 0 { - candidate.stakes[index] = nil - continue - } - - stake := &Stake{} - if err := rlp.DecodeBytes(enc, stake); err != nil { - panic(fmt.Sprintf("failed to decode stake: %s", err)) - } - - candidate.SetStakeAtIndex(index, stake, false) - - stakesCount++ - } - - candidate.stakesCount = stakesCount - - // load updates - path := []byte{mainPrefix} - path = append(path, candidate.PubKey.Bytes()...) - path = append(path, updatesPrefix) - _, enc := c.iavl.Get(path) - if len(enc) == 0 { - candidate.updates = nil - } else { - var updates []*Stake - if err := rlp.DecodeBytes(enc, &updates); err != nil { - panic(fmt.Sprintf("failed to decode updated: %s", err)) - } - - for _, update := range updates { - update.markDirty = (func(candidate *Candidate) func(int) { - return func(i int) { - candidate.isUpdatesDirty = true - } - })(candidate) - } - - candidate.updates = updates - } - - // load total stake - path = append([]byte{mainPrefix}, candidate.PubKey.Bytes()...) - path = append(path, totalStakePrefix) - _, enc = c.iavl.Get(path) - if len(enc) == 0 { - candidate.totalBipStake = big.NewInt(0) - } else { - candidate.totalBipStake = big.NewInt(0).SetBytes(enc) - } - - candidate.setTmAddress() - c.setToMap(candidate.PubKey, candidate) -} From 976257e9c5697e58586a4c202bb909917b16bf87 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 30 Jul 2020 13:14:02 +0300 Subject: [PATCH 126/426] update gateway --- api/v2/service/coin_id.go | 46 ------------------------------------- api/v2/service/coin_info.go | 45 ++++++++++++++++++++++++++++++++++-- go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 46 insertions(+), 51 deletions(-) delete mode 100644 api/v2/service/coin_id.go diff --git a/api/v2/service/coin_id.go b/api/v2/service/coin_id.go deleted file mode 100644 index 5afa43cff..000000000 --- a/api/v2/service/coin_id.go +++ /dev/null @@ -1,46 +0,0 @@ -package service - -import ( - "context" - "fmt" - "github.com/MinterTeam/minter-go-node/core/types" - pb "github.com/MinterTeam/node-grpc-gateway/api_pb" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -func (s *Service) CoinId(ctx context.Context, req *pb.CoinIdRequest) (*pb.CoinInfoResponse, error) { - cState, err := s.blockchain.GetStateForHeight(req.Height) - if err != nil { - return new(pb.CoinInfoResponse), status.Error(codes.NotFound, err.Error()) - } - - cState.RLock() - defer cState.RUnlock() - - coin := cState.Coins().GetCoin(types.CoinID(req.Id)) - if coin == nil { - return new(pb.CoinInfoResponse), status.Error(codes.FailedPrecondition, "Coin not found") - } - - if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.CoinInfoResponse), timeoutStatus.Err() - } - - var ownerAddress string - info := cState.Coins().GetSymbolInfo(coin.Symbol()) - if info != nil && info.OwnerAddress() != nil { - ownerAddress = info.OwnerAddress().String() - } - - return &pb.CoinInfoResponse{ - Id: coin.ID().String(), - Name: coin.Name(), - Symbol: coin.Symbol().String(), - Volume: coin.Volume().String(), - Crr: fmt.Sprintf("%d", coin.Crr()), - ReserveBalance: coin.Reserve().String(), - MaxSupply: coin.MaxSupply().String(), - OwnerAddress: ownerAddress, - }, nil -} diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index ea5bacce5..012618399 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/MinterTeam/minter-go-node/core/types" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" + "github.com/golang/protobuf/ptypes/wrappers" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -27,10 +28,50 @@ func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.Co return new(pb.CoinInfoResponse), timeoutStatus.Err() } - var ownerAddress string + var ownerAddress *wrappers.StringValue info := cState.Coins().GetSymbolInfo(coin.Symbol()) if info != nil && info.OwnerAddress() != nil { - ownerAddress = info.OwnerAddress().String() + ownerAddress = &wrappers.StringValue{ + Value: info.OwnerAddress().String(), + } + } + + return &pb.CoinInfoResponse{ + Id: coin.ID().String(), + Name: coin.Name(), + Symbol: coin.Symbol().String(), + Volume: coin.Volume().String(), + Crr: fmt.Sprintf("%d", coin.Crr()), + ReserveBalance: coin.Reserve().String(), + MaxSupply: coin.MaxSupply().String(), + OwnerAddress: ownerAddress, + }, nil +} + +func (s *Service) CoinInfoById(ctx context.Context, req *pb.CoinIdRequest) (*pb.CoinInfoResponse, error) { + cState, err := s.blockchain.GetStateForHeight(req.Height) + if err != nil { + return new(pb.CoinInfoResponse), status.Error(codes.NotFound, err.Error()) + } + + cState.RLock() + defer cState.RUnlock() + + coin := cState.Coins().GetCoin(types.CoinID(req.Id)) + if coin == nil { + return new(pb.CoinInfoResponse), status.Error(codes.FailedPrecondition, "Coin not found") + } + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.CoinInfoResponse), timeoutStatus.Err() + } + + var ownerAddress *wrappers.StringValue + info := cState.Coins().GetSymbolInfo(coin.Symbol()) + if info != nil && info.OwnerAddress() != nil { + ownerAddress = &wrappers.StringValue{ + Value: info.OwnerAddress().String(), + } } return &pb.CoinInfoResponse{ diff --git a/go.mod b/go.mod index 01e279bae..a8ebc1058 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200729121255-fdd723dc81d0 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200730101125-365dbd271301 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index e4d22b71e..fef645b54 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200729121255-fdd723dc81d0 h1:dDVKqowm+p/rhQrggg1hk0ZSLfi3g9J1JHsr8JQRsvM= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200729121255-fdd723dc81d0/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200730101125-365dbd271301 h1:rdhrvUzHSJ90suROMZqLLdM0YoaMcLliAazxmnKi8z0= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200730101125-365dbd271301/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 5e4332a51ec740e9625119a7fd8505513df0e216 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Mon, 3 Aug 2020 16:03:37 +0300 Subject: [PATCH 127/426] skip validators with less than 1000 BIP stake --- core/state/candidates/candidates.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index ab40749ea..13731fa2d 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -199,7 +199,7 @@ func (c *Candidates) GetNewCandidates(valCount int) []Candidate { continue } - if candidate.totalBipStake.Cmp(big.NewInt(0)) == 0 { + if candidate.totalBipStake.Cmp(helpers.BipToPip(big.NewInt(1000))) == 1 { continue } From c3a04025a3071345913741889bd9ee5f37874f19 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Mon, 3 Aug 2020 16:05:19 +0300 Subject: [PATCH 128/426] refactor --- core/state/candidates/candidates.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index d67cb0af2..df44a5e24 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -33,6 +33,10 @@ const ( updatesPrefix = 'u' ) +var ( + minValidatorBipStake = big.NewInt(1000) +) + type RCandidates interface { Export(state *types.AppState) Exists(pubkey types.Pubkey) bool @@ -198,7 +202,7 @@ func (c *Candidates) GetNewCandidates(valCount int) []Candidate { continue } - if candidate.totalBipStake.Cmp(helpers.BipToPip(big.NewInt(1000))) == 1 { + if candidate.totalBipStake.Cmp(helpers.BipToPip(minValidatorBipStake)) == 1 { continue } From 288bd71249065895c4bd01029dfc52f7c16deabd Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Mon, 3 Aug 2020 16:07:33 +0300 Subject: [PATCH 129/426] fix --- core/state/candidates/candidates.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index df44a5e24..adc7f2286 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -202,7 +202,7 @@ func (c *Candidates) GetNewCandidates(valCount int) []Candidate { continue } - if candidate.totalBipStake.Cmp(helpers.BipToPip(minValidatorBipStake)) == 1 { + if candidate.totalBipStake.Cmp(helpers.BipToPip(minValidatorBipStake)) == -1 { continue } From 5439386c16fb31c7aa8c72a0e42b5f2d1d5c5042 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Mon, 3 Aug 2020 16:26:28 +0300 Subject: [PATCH 130/426] fix candidates test --- core/state/candidates/candidates.go | 2 +- core/state/candidates_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index adc7f2286..b1c982f72 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -202,7 +202,7 @@ func (c *Candidates) GetNewCandidates(valCount int) []Candidate { continue } - if candidate.totalBipStake.Cmp(helpers.BipToPip(minValidatorBipStake)) == -1 { + if candidate.totalBipStake.Cmp(minValidatorBipStake) == -1 { continue } diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index e3add6f7d..2869070cc 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -302,7 +302,7 @@ func TestDoubleAbsentPenalty(t *testing.T) { pubkey := createTestCandidate(st) coin := types.GetBaseCoinID() - amount := big.NewInt(100) + amount := big.NewInt(1000) var addr types.Address binary.BigEndian.PutUint64(addr[:], 1) st.Candidates.Delegate(addr, pubkey, coin, amount, big.NewInt(0)) From 9e28f0949e5375b2de454a48f8c42e0da9f451b7 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 4 Aug 2020 15:26:45 +0300 Subject: [PATCH 131/426] add zero stake penalty test --- core/state/candidates_test.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index 2869070cc..1d59c6dec 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -332,6 +332,38 @@ func TestDoubleAbsentPenalty(t *testing.T) { } } +func TestZeroStakePenalty(t *testing.T) { + st := getState() + + pubkey := createTestCandidate(st) + + coin := types.GetBaseCoinID() + amount := big.NewInt(10000) + var addr types.Address + binary.BigEndian.PutUint64(addr[:], 1) + st.Candidates.Delegate(addr, pubkey, coin, amount, big.NewInt(0)) + + st.Candidates.RecalculateStakes(height) + + st.Candidates.SubStake(addr, pubkey, coin, amount) + st.FrozenFunds.AddFund(518400, addr, pubkey, coin, amount) + + var pk ed25519.PubKeyEd25519 + copy(pk[:], pubkey[:]) + + var tmAddr types.TmAddress + copy(tmAddr[:], pk.Address().Bytes()) + + st.Candidates.Punish(1, tmAddr) + + stake := st.Candidates.GetStakeValueOfAddress(pubkey, addr, coin) + newValue := big.NewInt(0) + + if stake.Cmp(newValue) != 0 { + t.Fatalf("Stake is not correct. Expected %s, got %s", newValue, stake.String()) + } +} + func TestDelegationAfterUnbond(t *testing.T) { st := getState() From 2aa6c7091e41d8d06c160ab3e8fddd137ac51e64 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 6 Aug 2020 15:18:38 +0300 Subject: [PATCH 132/426] add transaction data EditMultisigOwners and PriceVote --- api/v2/service/stakes.go | 92 ------------------ core/commissions/commissions.go | 30 +++--- core/state/accounts/accounts.go | 20 +++- core/state/accounts/model.go | 16 +++ core/state/state.go | 2 +- core/transaction/create_multisig.go | 8 +- core/transaction/create_multisig_test.go | 2 +- core/transaction/decoder.go | 2 + core/transaction/edit_multisig_owners.go | 119 +++++++++++++++++++++++ core/transaction/encoder/encoder.go | 2 + core/transaction/encoder/resources.go | 38 ++++++++ core/transaction/executor.go | 3 + core/transaction/executor_test.go | 11 ++- core/transaction/price_vote.go | 105 ++++++++++++++++++++ core/transaction/send_test.go | 5 +- core/transaction/transaction.go | 2 + 16 files changed, 333 insertions(+), 124 deletions(-) delete mode 100644 api/v2/service/stakes.go create mode 100644 core/transaction/edit_multisig_owners.go create mode 100644 core/transaction/price_vote.go diff --git a/api/v2/service/stakes.go b/api/v2/service/stakes.go deleted file mode 100644 index 3f7314eaa..000000000 --- a/api/v2/service/stakes.go +++ /dev/null @@ -1,92 +0,0 @@ -package service - -import ( - "context" - "encoding/hex" - "github.com/MinterTeam/minter-go-node/core/state/candidates" - "github.com/MinterTeam/minter-go-node/core/types" - pb "github.com/MinterTeam/node-grpc-gateway/api_pb" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "strings" -) - -func (s *Service) Stakes(ctx context.Context, req *pb.StakesRequest) (*pb.StakesResponse, error) { - if !strings.HasPrefix(req.PublicKey, "Mp") { - return new(pb.StakesResponse), status.Error(codes.InvalidArgument, "public key don't has prefix 'Mp'") - } - - pubKey := types.HexToPubkey(req.PublicKey[2:]) - - var address types.Address - if req.Address != "" { - if !strings.HasPrefix(strings.Title(req.Address), "Mx") { - return new(pb.StakesResponse), status.Error(codes.InvalidArgument, "invalid address") - } - - decodeAddr, err := hex.DecodeString(req.Address[2:]) - if err != nil { - return new(pb.StakesResponse), status.Error(codes.InvalidArgument, "invalid address") - } - - address = types.BytesToAddress(decodeAddr) - } - - cState, err := s.blockchain.GetStateForHeight(req.Height) - if err != nil { - return nil, err - } - - if req.Height != 0 { - cState.Lock() - cState.Candidates().LoadCandidates() - cState.Candidates().LoadStakes() - cState.Unlock() - } - - cState.RLock() - defer cState.RUnlock() - - var allCandidates []*candidates.Candidate - if req.PublicKey == "" { - allCandidates = cState.Candidates().GetCandidates() - } else { - allCandidates = []*candidates.Candidate{cState.Candidates().GetCandidate(pubKey)} - } - - var result []*pb.StakesResponse_Stake - for _, candidate := range allCandidates { - - if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.StakesResponse), timeoutStatus.Err() - } - - var multi bool - var allPubkeyStakes bool - - if req.Coin != "" && req.Address != "" { - multi = true - } - if req.Coin == "" && req.Address == "" { - allPubkeyStakes = true - } - - stakes := cState.Candidates().GetStakes(pubKey) - for _, stake := range stakes { - if !((multi && stake.Coin.String() == req.Coin && stake.Owner == address) || (!multi && (stake.Coin.String() == req.Coin || stake.Owner == address || allPubkeyStakes))) { - continue - } - result = append(result, &pb.StakesResponse_Stake{ - Address: stake.Owner.String(), - PubKey: candidate.PubKey.String(), - Coin: stake.Coin.String(), - Value: stake.Value.String(), - BipValue: stake.BipValue.String(), - }) - } - } - - return &pb.StakesResponse{ - Stakes: result, - }, nil -} diff --git a/core/commissions/commissions.go b/core/commissions/commissions.go index 8a333425a..1c451a557 100644 --- a/core/commissions/commissions.go +++ b/core/commissions/commissions.go @@ -3,18 +3,20 @@ package commissions // all commissions are divided by 10^15 // actual commission is SendTx * 10^15 = 10 000 000 000 000 000 PIP = 0,01 BIP const ( - SendTx int64 = 10 - CreateMultisig int64 = 100 - ConvertTx int64 = 100 - DeclareCandidacyTx int64 = 10000 - DelegateTx int64 = 200 - UnbondTx int64 = 200 - PayloadByte int64 = 2 - ToggleCandidateStatus int64 = 100 - EditCandidate int64 = 10000 - MultisendDelta int64 = 5 - RedeemCheckTx int64 = SendTx * 3 - SetHaltBlock int64 = 1000 - RecreateCoin int64 = 10000000 - ChangeOwner int64 = 10000000 + SendTx int64 = 10 + CreateMultisig int64 = 100 + ConvertTx int64 = 100 + DeclareCandidacyTx int64 = 10000 + DelegateTx int64 = 200 + UnbondTx int64 = 200 + PayloadByte int64 = 2 + ToggleCandidateStatus int64 = 100 + EditCandidate int64 = 10000 + MultisendDelta int64 = 5 + RedeemCheckTx = SendTx * 3 + SetHaltBlock int64 = 1000 + RecreateCoin int64 = 10000000 + ChangeOwner int64 = 10000000 + EditMultisigOwnersData int64 = 1000 + PriceVoteData int64 = 10 ) diff --git a/core/state/accounts/accounts.go b/core/state/accounts/accounts.go index c60aaacdc..a56925540 100644 --- a/core/state/accounts/accounts.go +++ b/core/state/accounts/accounts.go @@ -191,20 +191,18 @@ func (a *Accounts) ExistsMultisig(msigAddress types.Address) bool { return false } -func (a *Accounts) CreateMultisig(weights []uint, addresses []types.Address, threshold uint, height uint64) types.Address { +func (a *Accounts) CreateMultisig(weights []uint, addresses []types.Address, threshold uint, height uint64, address types.Address) types.Address { msig := Multisig{ Weights: weights, Threshold: threshold, Addresses: addresses, } - address := msig.Address() account := a.get(address) if account == nil { account = &Model{ Nonce: 0, - MultisigData: msig, address: address, coins: []types.CoinID{}, balances: map[types.CoinID]*big.Int{}, @@ -220,6 +218,22 @@ func (a *Accounts) CreateMultisig(weights []uint, addresses []types.Address, thr return address } +func (a *Accounts) EditMultisig(weights []uint, addresses []types.Address, address types.Address) types.Address { + account := a.get(address) + + msig := Multisig{ + Threshold: account.Multisig().Threshold, + Weights: weights, + Addresses: addresses, + } + + account.MultisigData = msig + account.markDirty(account.address) + account.isDirty = true + a.setToMap(address, account) + + return address +} func (a *Accounts) get(address types.Address) *Model { if account := a.getFromMap(address); account != nil { diff --git a/core/state/accounts/model.go b/core/state/accounts/model.go index 38f80205d..c4472a5b3 100644 --- a/core/state/accounts/model.go +++ b/core/state/accounts/model.go @@ -32,6 +32,7 @@ type Multisig struct { Addresses []types.Address } +// Deprecated. Don't use. Use CreateMultisigAddress(owner types.Address, nonce uint64) func (m *Multisig) Address() types.Address { b, err := rlp.EncodeToBytes(m) if err != nil { @@ -44,6 +45,21 @@ func (m *Multisig) Address() types.Address { return addr } +func CreateMultisigAddress(owner types.Address, nonce uint64) types.Address { + b, err := rlp.EncodeToBytes(&struct { + Owner types.Address + Nonce uint64 + }{Owner: owner, Nonce: nonce}) + if err != nil { + panic(err) + } + + var addr types.Address + copy(addr[:], crypto.Keccak256(b)[12:]) + + return addr +} + func (m *Multisig) GetWeight(address types.Address) uint { for i, addr := range m.Addresses { if addr == address { diff --git a/core/state/state.go b/core/state/state.go index dd53079cc..30e8d0eb1 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -276,7 +276,7 @@ func (s *State) Import(state types.AppState) error { for _, a := range state.Accounts { if a.MultisigData != nil { - s.Accounts.CreateMultisig(a.MultisigData.Weights, a.MultisigData.Addresses, a.MultisigData.Threshold, 1) + s.Accounts.CreateMultisig(a.MultisigData.Weights, a.MultisigData.Addresses, a.MultisigData.Threshold, 1, a.Address) } s.Accounts.SetNonce(a.Address, a.Nonce) diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index 98eaa7911..1dfc56b68 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -121,11 +121,7 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew } } - msigAddress := (&accounts.Multisig{ - Weights: data.Weights, - Threshold: data.Threshold, - Addresses: data.Addresses, - }).Address() + msigAddress := accounts.CreateMultisigAddress(sender, tx.Nonce) if checkState.Accounts().ExistsMultisig(msigAddress) { return Response{ @@ -146,7 +142,7 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) deliverState.Accounts.SetNonce(sender, tx.Nonce) - deliverState.Accounts.CreateMultisig(data.Weights, data.Addresses, data.Threshold, currentBlock) + deliverState.Accounts.CreateMultisig(data.Weights, data.Addresses, data.Threshold, currentBlock, msigAddress) } tags := kv.Pairs{ diff --git a/core/transaction/create_multisig_test.go b/core/transaction/create_multisig_test.go index 7cf19e219..9e9a1addd 100644 --- a/core/transaction/create_multisig_test.go +++ b/core/transaction/create_multisig_test.go @@ -233,7 +233,7 @@ func TestCreateExistingMultisigTx(t *testing.T) { }, } - cState.Accounts.CreateMultisig(data.Weights, data.Addresses, data.Threshold, 1) + cState.Accounts.CreateMultisig(data.Weights, data.Addresses, data.Threshold, 1, accounts.CreateMultisigAddress(addr, 1)) encodedData, err := rlp.EncodeToBytes(data) if err != nil { diff --git a/core/transaction/decoder.go b/core/transaction/decoder.go index fd47dec78..276470492 100644 --- a/core/transaction/decoder.go +++ b/core/transaction/decoder.go @@ -29,6 +29,8 @@ func init() { TxDecoder.RegisterType(TypeSetHaltBlock, SetHaltBlockData{}) TxDecoder.RegisterType(TypeRecreateCoin, RecreateCoinData{}) TxDecoder.RegisterType(TypeChangeOwner, ChangeOwnerData{}) + TxDecoder.RegisterType(TypeEditMultisigOwner, EditMultisigOwnersData{}) + TxDecoder.RegisterType(TypePriceVote, PriceVoteData{}) } type Decoder struct { diff --git a/core/transaction/edit_multisig_owners.go b/core/transaction/edit_multisig_owners.go new file mode 100644 index 000000000..bf0989057 --- /dev/null +++ b/core/transaction/edit_multisig_owners.go @@ -0,0 +1,119 @@ +package transaction + +import ( + "encoding/hex" + "fmt" + "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/commissions" + "github.com/MinterTeam/minter-go-node/core/state" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/formula" + "github.com/tendermint/tendermint/libs/kv" + "math/big" +) + +type EditMultisigOwnersData struct { + MultisigAddress types.Address + Weights []uint + Addresses []types.Address +} + +func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { + if context.Accounts().GetAccount(data.MultisigAddress).IsMultisig() { + return &Response{ + Code: code.MultisigNotExists, + Log: "Multisig does not exists", + Info: EncodeError(map[string]string{ + "multisig_address": data.MultisigAddress.String(), + }), + } + } + + return nil +} + +func (data EditMultisigOwnersData) String() string { + return fmt.Sprintf("EDIT MULTISIG OWNERS address: %x", data.MultisigAddress) +} + +func (data EditMultisigOwnersData) Gas() int64 { + return commissions.EditMultisigOwnersData +} + +func (data EditMultisigOwnersData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { + sender, _ := tx.Sender() + + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + response := data.BasicCheck(tx, checkState) + if response != nil { + return *response + } + + commissionInBaseCoin := tx.CommissionInBaseCoin() + commission := big.NewInt(0).Set(commissionInBaseCoin) + + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) + + if !tx.GasCoin.IsBaseCoin() { + errResp := CheckReserveUnderflow(gasCoin, commissionInBaseCoin) + if errResp != nil { + return *errResp + } + + if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { + return Response{ + Code: code.CoinReserveNotSufficient, + Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), + Info: EncodeError(map[string]string{ + "has_reserve": gasCoin.Reserve().String(), + "commission": commissionInBaseCoin.String(), + "gas_coin": gasCoin.GetFullSymbol(), + }), + } + } + + commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) + } + + if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + return Response{ + Code: code.InsufficientFunds, + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), + Info: EncodeError(map[string]string{ + "sender": sender.String(), + "needed_value": commission.String(), + "gas_coin": gasCoin.GetFullSymbol(), + }), + } + } + + if deliverState, ok := context.(*state.State); ok { + rewardPool.Add(rewardPool, commissionInBaseCoin) + + deliverState.Coins.SubVolume(tx.GasCoin, commission) + deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + + deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliverState.Accounts.SetNonce(sender, tx.Nonce) + + deliverState.Accounts.EditMultisig(data.Weights, data.Addresses, sender) + } + + address := []byte(hex.EncodeToString(sender[:])) + tags := kv.Pairs{ + kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeEditMultisigOwner)}))}, + kv.Pair{Key: []byte("tx.from"), Value: address}, + } + + return Response{ + Code: code.OK, + GasUsed: tx.Gas(), + GasWanted: tx.Gas(), + Tags: tags, + } +} diff --git a/core/transaction/encoder/encoder.go b/core/transaction/encoder/encoder.go index a25d61340..2048f144e 100644 --- a/core/transaction/encoder/encoder.go +++ b/core/transaction/encoder/encoder.go @@ -50,6 +50,8 @@ var resourcesConfig = map[transaction.TxType]TxDataResource{ transaction.TypeSetHaltBlock: new(SetHaltBlockDataResource), transaction.TypeRecreateCoin: new(RecreateCoinDataResource), transaction.TypeChangeOwner: new(ChangeOwnerDataResource), + transaction.TypeEditMultisigOwner: new(EditMultisigOwnersResource), + transaction.TypePriceVote: new(PriceVoteResource), } func NewTxEncoderJSON(context *state.CheckState) *TxEncoderJSON { diff --git a/core/transaction/encoder/resources.go b/core/transaction/encoder/resources.go index 6def0d909..e103abbf7 100644 --- a/core/transaction/encoder/resources.go +++ b/core/transaction/encoder/resources.go @@ -347,3 +347,41 @@ func (ChangeOwnerDataResource) Transform(txData interface{}, context *state.Chec NewOwner: data.NewOwner, } } + +// TxType 0x12 + +type EditMultisigOwnersResource struct { + MultisigAddress types.Address `json:"multisig_address"` + Weights []uint32 `json:"weight"` + Addresses []types.Address `json:"addresses"` +} + +func (EditMultisigOwnersResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { + data := txData.(*transaction.EditMultisigOwnersData) + + resource := EditMultisigOwnersResource{ + MultisigAddress: data.MultisigAddress, + Addresses: data.Addresses, + } + + resource.Weights = make([]uint32, 0, len(data.Weights)) + for _, weight := range data.Weights { + resource.Weights = append(resource.Weights, uint32(weight)) + } + + return resource +} + +// TxType 0x13 + +type PriceVoteResource struct { + Price uint32 `json:"price"` +} + +func (PriceVoteResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { + data := txData.(*transaction.PriceVoteData) + + return PriceVoteResource{ + Price: uint32(data.Price), + } +} diff --git a/core/transaction/executor.go b/core/transaction/executor.go index e8b1165d3..81330a633 100644 --- a/core/transaction/executor.go +++ b/core/transaction/executor.go @@ -153,6 +153,9 @@ func RunTx(context state.Interface, return Response{ Code: code.MultisigNotExists, Log: "Multisig does not exists", + Info: EncodeError(map[string]string{ + "multisig_address": tx.multisig.Multisig.String(), + }), } } diff --git a/core/transaction/executor_test.go b/core/transaction/executor_test.go index c68c39f88..f77fa0129 100644 --- a/core/transaction/executor_test.go +++ b/core/transaction/executor_test.go @@ -2,6 +2,7 @@ package transaction import ( "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/state/accounts" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/helpers" @@ -231,7 +232,7 @@ func TestMultiSigTx(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - msigAddress := cState.Accounts.CreateMultisig([]uint{1}, []types.Address{addr}, 1, 1) + msigAddress := cState.Accounts.CreateMultisig([]uint{1}, []types.Address{addr}, 1, 1, accounts.CreateMultisigAddress(addr, 1)) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ @@ -275,7 +276,7 @@ func TestMultiSigDoubleSignTx(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - msigAddress := cState.Accounts.CreateMultisig([]uint{1, 1}, []types.Address{addr, {}}, 2, 1) + msigAddress := cState.Accounts.CreateMultisig([]uint{1, 1}, []types.Address{addr, {}}, 2, 1, accounts.CreateMultisigAddress(addr, 1)) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ @@ -323,7 +324,7 @@ func TestMultiSigTooManySignsTx(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - msigAddress := cState.Accounts.CreateMultisig([]uint{1, 1}, []types.Address{addr, {}}, 2, 1) + msigAddress := cState.Accounts.CreateMultisig([]uint{1, 1}, []types.Address{addr, {}}, 2, 1, accounts.CreateMultisigAddress(addr, 1)) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ @@ -374,7 +375,7 @@ func TestMultiSigNotEnoughTx(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - msigAddress := cState.Accounts.CreateMultisig([]uint{1}, []types.Address{addr}, 2, 1) + msigAddress := cState.Accounts.CreateMultisig([]uint{1}, []types.Address{addr}, 2, 1, accounts.CreateMultisigAddress(addr, 1)) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ @@ -418,7 +419,7 @@ func TestMultiSigIncorrectSignsTx(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - msigAddress := cState.Accounts.CreateMultisig([]uint{1}, []types.Address{addr}, 1, 1) + msigAddress := cState.Accounts.CreateMultisig([]uint{1}, []types.Address{addr}, 1, 1, accounts.CreateMultisigAddress(addr, 1)) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ diff --git a/core/transaction/price_vote.go b/core/transaction/price_vote.go new file mode 100644 index 000000000..ace4c4455 --- /dev/null +++ b/core/transaction/price_vote.go @@ -0,0 +1,105 @@ +package transaction + +import ( + "encoding/hex" + "fmt" + "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/commissions" + "github.com/MinterTeam/minter-go-node/core/state" + "github.com/MinterTeam/minter-go-node/formula" + "github.com/tendermint/tendermint/libs/kv" + "math/big" +) + +type PriceVoteData struct { + Price uint +} + +func (data PriceVoteData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { + return nil +} + +func (data PriceVoteData) String() string { + return fmt.Sprintf("PRICE VOTE price: %d", data.Price) +} + +func (data PriceVoteData) Gas() int64 { + return commissions.PriceVoteData +} + +func (data PriceVoteData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { + sender, _ := tx.Sender() + + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + response := data.BasicCheck(tx, checkState) + if response != nil { + return *response + } + + commissionInBaseCoin := tx.CommissionInBaseCoin() + commission := big.NewInt(0).Set(commissionInBaseCoin) + + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) + + if !tx.GasCoin.IsBaseCoin() { + errResp := CheckReserveUnderflow(gasCoin, commissionInBaseCoin) + if errResp != nil { + return *errResp + } + + if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { + return Response{ + Code: code.CoinReserveNotSufficient, + Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), + Info: EncodeError(map[string]string{ + "has_reserve": gasCoin.Reserve().String(), + "commission": commissionInBaseCoin.String(), + "gas_coin": gasCoin.GetFullSymbol(), + }), + } + } + + commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) + } + + if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + return Response{ + Code: code.InsufficientFunds, + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), + Info: EncodeError(map[string]string{ + "sender": sender.String(), + "needed_value": commission.String(), + "gas_coin": gasCoin.GetFullSymbol(), + }), + } + } + + if deliverState, ok := context.(*state.State); ok { + rewardPool.Add(rewardPool, commissionInBaseCoin) + + deliverState.Coins.SubVolume(tx.GasCoin, commission) + deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + + deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliverState.Accounts.SetNonce(sender, tx.Nonce) + + //todo + } + + tags := kv.Pairs{ + kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypePriceVote)}))}, + kv.Pair{Key: []byte("tx.from"), Value: []byte(hex.EncodeToString(sender[:]))}, + } + + return Response{ + Code: code.OK, + GasUsed: tx.Gas(), + GasWanted: tx.Gas(), + Tags: tags, + } +} diff --git a/core/transaction/send_test.go b/core/transaction/send_test.go index 237ab95ff..8c840a1e4 100644 --- a/core/transaction/send_test.go +++ b/core/transaction/send_test.go @@ -2,6 +2,7 @@ package transaction import ( "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/state/accounts" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/helpers" @@ -82,7 +83,7 @@ func TestSendMultisigTx(t *testing.T) { coin := types.GetBaseCoinID() - msig := cState.Accounts.CreateMultisig([]uint{1, 1}, []types.Address{addr1, addr2}, 1, 1) + msig := cState.Accounts.CreateMultisig([]uint{1, 1}, []types.Address{addr1, addr2}, 1, 1, accounts.CreateMultisigAddress(addr1, 1)) cState.Accounts.AddBalance(msig, coin, helpers.BipToPip(big.NewInt(1000000))) @@ -150,7 +151,7 @@ func TestSendFailedMultisigTx(t *testing.T) { coin := types.GetBaseCoinID() - msig := cState.Accounts.CreateMultisig([]uint{1, 3}, []types.Address{addr1, addr2}, 3, 1) + msig := cState.Accounts.CreateMultisig([]uint{1, 3}, []types.Address{addr1, addr2}, 3, 1, accounts.CreateMultisigAddress(addr1, 1)) cState.Accounts.AddBalance(msig, coin, helpers.BipToPip(big.NewInt(1000000))) diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index 70b672f27..b008d5370 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -36,6 +36,8 @@ const ( TypeSetHaltBlock TxType = 0x0F TypeRecreateCoin TxType = 0x10 TypeChangeOwner TxType = 0x11 + TypeEditMultisigOwner TxType = 0x12 + TypePriceVote TxType = 0x13 SigTypeSingle SigType = 0x01 SigTypeMulti SigType = 0x02 From 9fdc84ac2879bdbb9b446d012f1119f7a9e67624 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 6 Aug 2020 16:18:10 +0300 Subject: [PATCH 133/426] add test EditMultisigOwners --- core/state/accounts/accounts.go | 1 + core/transaction/edit_multisig_owners.go | 2 +- core/transaction/edit_multisig_owners_test.go | 96 +++++++++++++++++++ 3 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 core/transaction/edit_multisig_owners_test.go diff --git a/core/state/accounts/accounts.go b/core/state/accounts/accounts.go index a56925540..196d04904 100644 --- a/core/state/accounts/accounts.go +++ b/core/state/accounts/accounts.go @@ -218,6 +218,7 @@ func (a *Accounts) CreateMultisig(weights []uint, addresses []types.Address, thr return address } + func (a *Accounts) EditMultisig(weights []uint, addresses []types.Address, address types.Address) types.Address { account := a.get(address) diff --git a/core/transaction/edit_multisig_owners.go b/core/transaction/edit_multisig_owners.go index bf0989057..1e1cafcb2 100644 --- a/core/transaction/edit_multisig_owners.go +++ b/core/transaction/edit_multisig_owners.go @@ -19,7 +19,7 @@ type EditMultisigOwnersData struct { } func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { - if context.Accounts().GetAccount(data.MultisigAddress).IsMultisig() { + if !context.Accounts().GetAccount(data.MultisigAddress).IsMultisig() { return &Response{ Code: code.MultisigNotExists, Log: "Multisig does not exists", diff --git a/core/transaction/edit_multisig_owners_test.go b/core/transaction/edit_multisig_owners_test.go new file mode 100644 index 000000000..92377e42c --- /dev/null +++ b/core/transaction/edit_multisig_owners_test.go @@ -0,0 +1,96 @@ +package transaction + +import ( + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/crypto" + "github.com/MinterTeam/minter-go-node/helpers" + "github.com/MinterTeam/minter-go-node/rlp" + "math/big" + "math/rand" + "reflect" + "sync" + "testing" +) + +func TestEditMultisigOwnersTx(t *testing.T) { + cState := getState() + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + addr := types.Address{0} + privateKey1, _ := crypto.GenerateKey() + addr1 := crypto.PubkeyToAddress(privateKey1.PublicKey) + privateKey2, _ := crypto.GenerateKey() + addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) + privateKey3, _ := crypto.GenerateKey() + addr3 := crypto.PubkeyToAddress(privateKey3.PublicKey) + privateKey4, _ := crypto.GenerateKey() + addr4 := crypto.PubkeyToAddress(privateKey4.PublicKey) + + cState.Accounts.CreateMultisig([]uint{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + + coin := types.GetBaseCoinID() + initialBalance := big.NewInt(1) + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(initialBalance)) + + data := EditMultisigOwnersData{ + MultisigAddress: addr, + Weights: []uint{2, 1, 2}, + Addresses: []types.Address{addr1, addr2, addr4}, + } + + encodedData, err := rlp.EncodeToBytes(data) + + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditMultisigOwner, + Data: encodedData, + SignatureType: SigTypeMulti, + } + + tx.SetMultisigAddress(addr) + + if err := tx.Sign(privateKey3); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + + if response.Code != 0 { + t.Fatalf("Response code is not 0. Error %s", response.Log) + } + + account := cState.Accounts.GetAccount(addr) + + if !account.IsMultisig() { + t.Fatalf("Multisig %s is not created", addr.String()) + } + + msigData := account.Multisig() + + if !reflect.DeepEqual(msigData.Addresses, data.Addresses) { + t.Fatalf("Addresses are not correct") + } + + if !reflect.DeepEqual(msigData.Weights, data.Weights) { + t.Fatalf("Weights are not correct") + } + + if msigData.Threshold != 3 { + t.Fatalf("Threshold is not correct") + } +} From aa4f12607bb7f2e37f6ea0cdcb9905427c6ce7ab Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 6 Aug 2020 23:23:43 +0300 Subject: [PATCH 134/426] fix --- core/transaction/set_halt_block.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index 63288b4b8..9f29b5c68 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -122,7 +122,7 @@ func (data SetHaltBlockData) Run(tx *Transaction, context state.Interface, rewar } tags := kv.Pairs{ - kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeUnbond)}))}, + kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeSetHaltBlock)}))}, kv.Pair{Key: []byte("tx.from"), Value: []byte(hex.EncodeToString(sender[:]))}, } From b137263d0536408d4b9230e494b921382252bfa2 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 10 Aug 2020 11:00:16 +0300 Subject: [PATCH 135/426] stake value calculation changes --- core/state/candidates/candidates.go | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 599d71f30..e69879a24 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -873,8 +873,9 @@ func (c *Candidates) LoadStakes() { } } -func (c *Candidates) calculateBipValue(CoinID types.CoinID, amount *big.Int, includeSelf, includeUpdates bool, coinsCache *coinsCache) *big.Int { - if CoinID.IsBaseCoin() { +func (c *Candidates) calculateBipValue(coinID types.CoinID, amount *big.Int, includeSelf, includeUpdates bool, coinsCache *coinsCache) *big.Int { + + if coinID.IsBaseCoin() { return big.NewInt(0).Set(amount) } @@ -883,35 +884,38 @@ func (c *Candidates) calculateBipValue(CoinID types.CoinID, amount *big.Int, inc totalAmount.Set(amount) } - var totalPower *big.Int + var totalDelegatedValue *big.Int + coin := c.bus.Coins().GetCoin(coinID) - if coinsCache.Exists(CoinID) { - totalPower, totalAmount = coinsCache.Get(CoinID) + if coinsCache.Exists(coinID) { + totalDelegatedValue, totalAmount = coinsCache.Get(coinID) } else { candidates := c.GetCandidates() for _, candidate := range candidates { for _, stake := range candidate.stakes { - if stake != nil && stake.Coin == CoinID { + if stake != nil && stake.Coin == coinID { totalAmount.Add(totalAmount, stake.Value) } } if includeUpdates { for _, update := range candidate.updates { - if update.Coin == CoinID { + if update.Coin == coinID { totalAmount.Add(totalAmount, update.Value) } } } } - coin := c.bus.Coins().GetCoin(CoinID) + coin := c.bus.Coins().GetCoin(coinID) - totalPower = formula.CalculateSaleReturn(coin.Volume, coin.Reserve, coin.Crr, totalAmount) - coinsCache.Set(CoinID, totalPower, totalAmount) + totalDelegatedValue = formula.CalculateSaleReturn(coin.Volume, coin.Reserve, coin.Crr, totalAmount) + coinsCache.Set(coinID, totalDelegatedValue, totalAmount) } - return big.NewInt(0).Div(big.NewInt(0).Mul(totalPower, amount), totalAmount) + nonLockedSupply := big.NewInt(0).Sub(coin.Reserve, totalDelegatedValue) + saleReturn := formula.CalculateSaleReturn(coin.Volume, coin.Reserve, coin.Crr, nonLockedSupply) + return big.NewInt(0).Div(big.NewInt(0).Mul(big.NewInt(0).Sub(coin.Reserve, saleReturn), amount), totalDelegatedValue) } func (c *Candidates) Punish(height uint64, address types.TmAddress) *big.Int { From 59730c8818a42d39daa6d2609450af89c97ca2da Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 10 Aug 2020 12:00:49 +0300 Subject: [PATCH 136/426] stake value calculation changes --- core/state/candidates/candidates.go | 218 +--------------------------- core/state/candidates/model.go | 7 +- 2 files changed, 10 insertions(+), 215 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 3e3b254d3..bc738a094 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -297,206 +297,6 @@ func (c *Candidates) RecalculateStakes(height uint64) { c.recalculateStakesNew(height) } -func (c *Candidates) recalculateStakesOld1(height uint64) { - coinsCache := newCoinsCache() - - for _, pubkey := range c.getOrderedCandidates() { - candidate := c.getFromMap(pubkey) - stakes := c.GetStakes(candidate.PubKey) - for _, stake := range stakes { - stake.setBipValue(c.calculateBipValue(stake.Coin, stake.Value, false, true, coinsCache)) - } - - // apply updates for existing stakes - for _, update := range candidate.updates { - stake := c.GetStakeOfAddress(candidate.PubKey, update.Owner, update.Coin) - if stake != nil { - stake.addValue(update.Value) - update.setValue(big.NewInt(0)) - stake.setBipValue(c.calculateBipValue(stake.Coin, stake.Value, false, true, coinsCache)) - } - } - - updates := candidate.GetFilteredUpdates() - for _, update := range updates { - update.setBipValue(c.calculateBipValue(update.Coin, update.Value, false, true, coinsCache)) - } - // Sort updates in descending order - sort.SliceStable(updates, func(i, j int) bool { - return updates[i].BipValue.Cmp(updates[j].BipValue) == 1 - }) - - for _, update := range updates { - if candidate.stakesCount < MaxDelegatorsPerCandidate { - candidate.SetStakeAtIndex(candidate.stakesCount, update, true) - candidate.stakesCount++ - stakes = c.GetStakes(candidate.PubKey) - } else { - // find and replace smallest stake - index := -1 - var smallestStake *big.Int - for i, stake := range stakes { - if stake == nil { - index = i - smallestStake = big.NewInt(0) - break - } - - if smallestStake == nil || smallestStake.Cmp(stake.BipValue) == 1 { - smallestStake = big.NewInt(0).Set(stake.BipValue) - index = i - } - } - - if index == -1 || smallestStake.Cmp(update.BipValue) == 1 { - c.bus.Events().AddEvent(uint32(height), &eventsdb.UnbondEvent{ - Address: update.Owner, - Amount: update.Value.String(), - Coin: update.Coin, - ValidatorPubKey: candidate.PubKey, - }) - c.bus.Accounts().AddBalance(update.Owner, update.Coin, update.Value) - c.bus.Checker().AddCoin(update.Coin, big.NewInt(0).Neg(update.Value)) - update.setValue(big.NewInt(0)) - continue - } - - if stakes[index] != nil { - c.bus.Events().AddEvent(uint32(height), &eventsdb.UnbondEvent{ - Address: stakes[index].Owner, - Amount: stakes[index].Value.String(), - Coin: stakes[index].Coin, - ValidatorPubKey: candidate.PubKey, - }) - c.bus.Accounts().AddBalance(stakes[index].Owner, stakes[index].Coin, stakes[index].Value) - c.bus.Checker().AddCoin(stakes[index].Coin, big.NewInt(0).Neg(stakes[index].Value)) - } - - candidate.SetStakeAtIndex(index, update, true) - stakes = c.GetStakes(candidate.PubKey) - } - } - - candidate.clearUpdates() - - totalBipValue := big.NewInt(0) - for _, stake := range c.GetStakes(candidate.PubKey) { - if stake == nil { - continue - } - totalBipValue.Add(totalBipValue, stake.BipValue) - } - - candidate.setTotalBipStake(totalBipValue) - candidate.updateStakesCount() - } -} - -func (c *Candidates) recalculateStakesOld2(height uint64) { - coinsCache := newCoinsCache() - - for _, pubkey := range c.getOrderedCandidates() { - candidate := c.getFromMap(pubkey) - stakes := c.GetStakes(candidate.PubKey) - for _, stake := range stakes { - stake.setBipValue(c.calculateBipValue(stake.Coin, stake.Value, false, true, coinsCache)) - } - - // apply updates for existing stakes - candidate.FilterUpdates() - for _, update := range candidate.updates { - stake := c.GetStakeOfAddress(candidate.PubKey, update.Owner, update.Coin) - if stake != nil { - stake.addValue(update.Value) - update.setValue(big.NewInt(0)) - stake.setBipValue(c.calculateBipValue(stake.Coin, stake.Value, false, true, coinsCache)) - } - } - - candidate.FilterUpdates() - for _, update := range candidate.updates { - update.setBipValue(c.calculateBipValue(update.Coin, update.Value, false, true, coinsCache)) - } - - for _, update := range candidate.updates { - // find and replace smallest stake - index := -1 - var smallestStake *big.Int - - if len(stakes) == 0 { - index = 0 - smallestStake = big.NewInt(0) - } else if len(stakes) < MaxDelegatorsPerCandidate { - for i, stake := range stakes { - if stake == nil { - index = i - break - } - } - - if index == -1 { - index = len(stakes) - } - - smallestStake = big.NewInt(0) - } else { - for i, stake := range stakes { - if stake == nil { - index = i - smallestStake = big.NewInt(0) - break - } - - if smallestStake == nil || smallestStake.Cmp(stake.BipValue) == 1 { - smallestStake = big.NewInt(0).Set(stake.BipValue) - index = i - } - } - } - - if index == -1 || smallestStake.Cmp(update.BipValue) == 1 { - c.bus.Events().AddEvent(uint32(height), &eventsdb.UnbondEvent{ - Address: update.Owner, - Amount: update.Value.String(), - Coin: update.Coin, - ValidatorPubKey: candidate.PubKey, - }) - c.bus.Accounts().AddBalance(update.Owner, update.Coin, update.Value) - c.bus.Checker().AddCoin(update.Coin, big.NewInt(0).Neg(update.Value)) - update.setValue(big.NewInt(0)) - continue - } - - if len(stakes) > index && stakes[index] != nil { - c.bus.Events().AddEvent(uint32(height), &eventsdb.UnbondEvent{ - Address: stakes[index].Owner, - Amount: stakes[index].Value.String(), - Coin: stakes[index].Coin, - ValidatorPubKey: candidate.PubKey, - }) - c.bus.Accounts().AddBalance(stakes[index].Owner, stakes[index].Coin, stakes[index].Value) - c.bus.Checker().AddCoin(stakes[index].Coin, big.NewInt(0).Neg(stakes[index].Value)) - } - - candidate.SetStakeAtIndex(index, update, true) - stakes = c.GetStakes(candidate.PubKey) - } - - candidate.clearUpdates() - - totalBipValue := big.NewInt(0) - for _, stake := range c.GetStakes(candidate.PubKey) { - if stake == nil { - continue - } - totalBipValue.Add(totalBipValue, stake.BipValue) - } - - candidate.setTotalBipStake(totalBipValue) - candidate.updateStakesCount() - } -} - func (c *Candidates) recalculateStakesNew(height uint64) { coinsCache := newCoinsCache() @@ -883,41 +683,37 @@ func (c *Candidates) calculateBipValue(coinID types.CoinID, amount *big.Int, inc return big.NewInt(0).Set(amount) } - totalAmount := big.NewInt(0) + totalDelegatedValue := big.NewInt(0) if includeSelf { - totalAmount.Set(amount) + totalDelegatedValue.Set(amount) } - var totalDelegatedValue *big.Int coin := c.bus.Coins().GetCoin(coinID) if coinsCache.Exists(coinID) { - totalDelegatedValue, totalAmount = coinsCache.Get(coinID) + totalDelegatedValue = coinsCache.Get(coinID) } else { candidates := c.GetCandidates() for _, candidate := range candidates { for _, stake := range candidate.stakes { if stake != nil && stake.Coin == coinID { - totalAmount.Add(totalAmount, stake.Value) + totalDelegatedValue.Add(totalDelegatedValue, stake.Value) } } if includeUpdates { for _, update := range candidate.updates { if update.Coin == coinID { - totalAmount.Add(totalAmount, update.Value) + totalDelegatedValue.Add(totalDelegatedValue, update.Value) } } } } - coin := c.bus.Coins().GetCoin(coinID) - - totalDelegatedValue = formula.CalculateSaleReturn(coin.Volume, coin.Reserve, coin.Crr, totalAmount) - coinsCache.Set(coinID, totalDelegatedValue, totalAmount) + coinsCache.Set(coinID, totalDelegatedValue) } - nonLockedSupply := big.NewInt(0).Sub(coin.Reserve, totalDelegatedValue) + nonLockedSupply := big.NewInt(0).Sub(coin.Volume, totalDelegatedValue) saleReturn := formula.CalculateSaleReturn(coin.Volume, coin.Reserve, coin.Crr, nonLockedSupply) return big.NewInt(0).Div(big.NewInt(0).Mul(big.NewInt(0).Sub(coin.Reserve, saleReturn), amount), totalDelegatedValue) } diff --git a/core/state/candidates/model.go b/core/state/candidates/model.go index cc2b49e06..941eb5fc4 100644 --- a/core/state/candidates/model.go +++ b/core/state/candidates/model.go @@ -252,11 +252,11 @@ func (c *coinsCache) Exists(id types.CoinID) bool { return exists } -func (c *coinsCache) Get(id types.CoinID) (totalPower *big.Int, totalAmount *big.Int) { - return c.list[id].totalPower, c.list[id].totalAmount +func (c *coinsCache) Get(id types.CoinID) (totalAmount *big.Int) { + return c.list[id].totalAmount } -func (c *coinsCache) Set(id types.CoinID, totalPower *big.Int, totalAmount *big.Int) { +func (c *coinsCache) Set(id types.CoinID, totalAmount *big.Int) { if c == nil { return } @@ -266,5 +266,4 @@ func (c *coinsCache) Set(id types.CoinID, totalPower *big.Int, totalAmount *big. } c.list[id].totalAmount = totalAmount - c.list[id].totalPower = totalPower } From 3f30d5b597dbd9308936cadcff93a0997fdc53d9 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 10 Aug 2020 12:07:29 +0300 Subject: [PATCH 137/426] refactor stake value calculation changes --- core/state/candidates/candidates.go | 11 ++++++----- core/state/candidates/model.go | 9 +++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index bc738a094..d6e37521b 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -297,6 +297,7 @@ func (c *Candidates) RecalculateStakes(height uint64) { c.recalculateStakesNew(height) } +// todo: wip func (c *Candidates) recalculateStakesNew(height uint64) { coinsCache := newCoinsCache() @@ -690,8 +691,9 @@ func (c *Candidates) calculateBipValue(coinID types.CoinID, amount *big.Int, inc coin := c.bus.Coins().GetCoin(coinID) + var saleReturn *big.Int if coinsCache.Exists(coinID) { - totalDelegatedValue = coinsCache.Get(coinID) + saleReturn, totalDelegatedValue = coinsCache.Get(coinID) } else { candidates := c.GetCandidates() for _, candidate := range candidates { @@ -709,12 +711,11 @@ func (c *Candidates) calculateBipValue(coinID types.CoinID, amount *big.Int, inc } } } - - coinsCache.Set(coinID, totalDelegatedValue) + nonLockedSupply := big.NewInt(0).Sub(coin.Volume, totalDelegatedValue) + saleReturn = formula.CalculateSaleReturn(coin.Volume, coin.Reserve, coin.Crr, nonLockedSupply) + coinsCache.Set(coinID, saleReturn, totalDelegatedValue) } - nonLockedSupply := big.NewInt(0).Sub(coin.Volume, totalDelegatedValue) - saleReturn := formula.CalculateSaleReturn(coin.Volume, coin.Reserve, coin.Crr, nonLockedSupply) return big.NewInt(0).Div(big.NewInt(0).Mul(big.NewInt(0).Sub(coin.Reserve, saleReturn), amount), totalDelegatedValue) } diff --git a/core/state/candidates/model.go b/core/state/candidates/model.go index 941eb5fc4..257691818 100644 --- a/core/state/candidates/model.go +++ b/core/state/candidates/model.go @@ -238,7 +238,7 @@ func newCoinsCache() *coinsCache { } type coinsCacheItem struct { - totalPower *big.Int + saleReturn *big.Int totalAmount *big.Int } @@ -252,11 +252,11 @@ func (c *coinsCache) Exists(id types.CoinID) bool { return exists } -func (c *coinsCache) Get(id types.CoinID) (totalAmount *big.Int) { - return c.list[id].totalAmount +func (c *coinsCache) Get(id types.CoinID) (saleReturn *big.Int, totalAmount *big.Int) { + return c.list[id].totalAmount, c.list[id].totalAmount } -func (c *coinsCache) Set(id types.CoinID, totalAmount *big.Int) { +func (c *coinsCache) Set(id types.CoinID, saleReturn *big.Int, totalAmount *big.Int) { if c == nil { return } @@ -266,4 +266,5 @@ func (c *coinsCache) Set(id types.CoinID, totalAmount *big.Int) { } c.list[id].totalAmount = totalAmount + c.list[id].saleReturn = saleReturn } From 05e9b38e1dfbf587102543e87519bce155dccfeb Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Mon, 10 Aug 2020 16:12:39 +0300 Subject: [PATCH 138/426] add watchlist state --- core/state/watchlist/bus.go | 18 ++++ core/state/watchlist/model.go | 27 +++++ core/state/watchlist/watchlist.go | 157 ++++++++++++++++++++++++++++++ 3 files changed, 202 insertions(+) create mode 100644 core/state/watchlist/bus.go create mode 100644 core/state/watchlist/model.go create mode 100644 core/state/watchlist/watchlist.go diff --git a/core/state/watchlist/bus.go b/core/state/watchlist/bus.go new file mode 100644 index 000000000..993777107 --- /dev/null +++ b/core/state/watchlist/bus.go @@ -0,0 +1,18 @@ +package watchlist + +import ( + "github.com/MinterTeam/minter-go-node/core/types" + "math/big" +) + +type Bus struct { + watchlist *WatchList +} + +func (b *Bus) AddFrozenFund(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { + b.watchlist.AddWatchList(address, pubkey, coin, value) +} + +func NewBus(watchlist *WatchList) *Bus { + return &Bus{watchlist: watchlist} +} diff --git a/core/state/watchlist/model.go b/core/state/watchlist/model.go new file mode 100644 index 000000000..de8728edf --- /dev/null +++ b/core/state/watchlist/model.go @@ -0,0 +1,27 @@ +package watchlist + +import ( + "github.com/MinterTeam/minter-go-node/core/types" + "math/big" +) + +type Item struct { + PublicKey types.Pubkey + Coin types.CoinID + Value *big.Int +} + +type Model struct { + List []Item + + address types.Address + markDirty func(address types.Address) +} + +func (m *Model) AddToList(publicKey types.Pubkey, coin types.CoinID, value *big.Int) { + m.List = append(m.List, Item{ + PublicKey: publicKey, + Coin: coin, + Value: value, + }) +} diff --git a/core/state/watchlist/watchlist.go b/core/state/watchlist/watchlist.go new file mode 100644 index 000000000..a2bdd2b64 --- /dev/null +++ b/core/state/watchlist/watchlist.go @@ -0,0 +1,157 @@ +package watchlist + +import ( + "bytes" + "fmt" + "github.com/MinterTeam/minter-go-node/core/state/bus" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/rlp" + "github.com/MinterTeam/minter-go-node/tree" + "log" + "math/big" + "sort" + "sync" +) + +const mainPrefix = byte('w') + +type RWatchList interface { + GetByAddress(address types.Address) *Model + AddWatchList(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) + Delete(address types.Address, pubkey types.Pubkey, coin types.CoinID) +} + +type WatchList struct { + list map[types.Address]*Model + dirty map[types.Address]interface{} + + bus *bus.Bus + iavl tree.MTree + + lock sync.RWMutex +} + +func NewWatchList(stateBus *bus.Bus, iavl tree.MTree) (*WatchList, error) { + watchlist := &WatchList{ + bus: stateBus, + iavl: iavl, + list: map[types.Address]*Model{}, + dirty: map[types.Address]interface{}{}, + } + + return watchlist, nil +} + +func (wl *WatchList) Commit() error { + dirty := wl.getOrderedDirty() + for _, address := range dirty { + w := wl.getFromMap(address) + + wl.lock.Lock() + delete(wl.dirty, address) + wl.lock.Unlock() + + data, err := rlp.EncodeToBytes(w) + if err != nil { + return fmt.Errorf("can't encode object at %s: %v", address.String(), err) + } + + path := append([]byte{mainPrefix}, address.Bytes()...) + wl.iavl.Set(path, data) + } + + return nil +} + +func (wl *WatchList) GetByAddress(address types.Address) *Model { + return wl.get(address) +} + +func (wl *WatchList) AddWatchList(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { + w := wl.getOrNew(address) + w.AddToList(pubkey, coin, value) + wl.setToMap(address, w) + w.markDirty(address) +} + +func (wl *WatchList) Delete(address types.Address, pubkey types.Pubkey, coin types.CoinID) { + w := wl.get(address) + if w == nil || len(w.List) == 0 { + log.Panicf("Watchlist not found for %s", address.String()) + } + + items := make([]Item, len(w.List)-1) + for i, item := range w.List { + if item.PublicKey != pubkey && item.Coin != coin { + items[i] = item + } + } + + w.List = items + wl.markDirty(address) + wl.setToMap(address, w) +} + +func (wl *WatchList) getOrNew(address types.Address) *Model { + w := wl.get(address) + if w == nil { + w = &Model{List: make([]Item, 0), address: address, markDirty: wl.markDirty} + wl.setToMap(address, w) + } + + return w +} + +func (wl *WatchList) get(address types.Address) *Model { + if ff := wl.getFromMap(address); ff != nil { + return ff + } + + path := append([]byte{mainPrefix}, address.Bytes()...) + _, enc := wl.iavl.Get(path) + if len(enc) == 0 { + return nil + } + + m := new(Model) + if err := rlp.DecodeBytes(enc, m); err != nil { + panic(fmt.Sprintf("failed to decode watchlists for address %d: %s", address.String(), err)) + } + + m.address = address + m.markDirty = wl.markDirty + wl.setToMap(address, m) + + return m +} + +func (wl *WatchList) getFromMap(address types.Address) *Model { + wl.lock.RLock() + defer wl.lock.RUnlock() + + return wl.list[address] +} + +func (wl *WatchList) setToMap(address types.Address, model *Model) { + wl.lock.Lock() + defer wl.lock.Unlock() + + wl.list[address] = model +} + +func (wl *WatchList) markDirty(address types.Address) { + wl.dirty[address] = struct{}{} +} + +func (wl *WatchList) getOrderedDirty() []types.Address { + keys := make([]types.Address, 0, len(wl.dirty)) + for k := range wl.dirty { + keys = append(keys, k) + } + + sort.SliceStable(keys, func(i, j int) bool { + return bytes.Compare(keys[i].Bytes(), keys[j].Bytes()) == 1 + }) + + return keys +} From b50a175513a18f4e8d95877d4660c06c750115c6 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 10 Aug 2020 17:49:36 +0300 Subject: [PATCH 139/426] edit unbound --- core/state/bus/bus.go | 9 ++++++++ core/state/bus/watchlist.go | 10 +++++++++ core/state/candidates/candidates.go | 35 ++++++++++++++--------------- core/state/state.go | 11 ++++++++- core/state/watchlist/model.go | 12 ++++++++++ core/state/watchlist/watchlist.go | 6 ++--- core/transaction/delegate.go | 7 ++++++ core/transaction/unbond.go | 11 +++++++-- 8 files changed, 77 insertions(+), 24 deletions(-) create mode 100644 core/state/bus/watchlist.go diff --git a/core/state/bus/bus.go b/core/state/bus/bus.go index 64a431cbd..03413465c 100644 --- a/core/state/bus/bus.go +++ b/core/state/bus/bus.go @@ -9,6 +9,7 @@ type Bus struct { candidates Candidates frozenfunds FrozenFunds halts HaltBlocks + watchlist WatchList events eventsdb.IEventsDB checker Checker } @@ -65,6 +66,14 @@ func (b *Bus) Halts() HaltBlocks { return b.halts } +func (b *Bus) SetWatchList(watchList WatchList) { + b.watchlist = watchList +} + +func (b *Bus) WatchList() WatchList { + return b.watchlist +} + func (b *Bus) SetEvents(events eventsdb.IEventsDB) { b.events = events } diff --git a/core/state/bus/watchlist.go b/core/state/bus/watchlist.go new file mode 100644 index 000000000..a0b3ceec0 --- /dev/null +++ b/core/state/bus/watchlist.go @@ -0,0 +1,10 @@ +package bus + +import ( + "github.com/MinterTeam/minter-go-node/core/types" + "math/big" +) + +type WatchList interface { + AddFrozenFund(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) +} diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index d6e37521b..5548ed105 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -297,7 +297,6 @@ func (c *Candidates) RecalculateStakes(height uint64) { c.recalculateStakesNew(height) } -// todo: wip func (c *Candidates) recalculateStakesNew(height uint64) { coinsCache := newCoinsCache() @@ -345,27 +344,13 @@ func (c *Candidates) recalculateStakesNew(height uint64) { } if smallestStake.Cmp(update.BipValue) == 1 { - c.bus.Events().AddEvent(uint32(height), &eventsdb.UnbondEvent{ - Address: update.Owner, - Amount: update.Value.String(), - Coin: update.Coin, - ValidatorPubKey: candidate.PubKey, - }) - c.bus.Accounts().AddBalance(update.Owner, update.Coin, update.Value) - c.bus.Checker().AddCoin(update.Coin, big.NewInt(0).Neg(update.Value)) + c.unbond(update.Owner, update.Value, update.Coin, candidate.PubKey, height) update.setValue(big.NewInt(0)) continue } if stakes[index] != nil { - c.bus.Events().AddEvent(uint32(height), &eventsdb.UnbondEvent{ - Address: stakes[index].Owner, - Amount: stakes[index].Value.String(), - Coin: stakes[index].Coin, - ValidatorPubKey: candidate.PubKey, - }) - c.bus.Accounts().AddBalance(stakes[index].Owner, stakes[index].Coin, stakes[index].Value) - c.bus.Checker().AddCoin(stakes[index].Coin, big.NewInt(0).Neg(stakes[index].Value)) + c.unbond(update.Owner, update.Value, update.Coin, candidate.PubKey, height) } candidate.SetStakeAtIndex(index, update, true) @@ -385,6 +370,19 @@ func (c *Candidates) recalculateStakesNew(height uint64) { } } +func (c *Candidates) unbond(owner types.Address, value *big.Int, coin types.CoinID, pubKey types.Pubkey, height uint64) { + c.bus.WatchList().AddFrozenFund(owner, pubKey, coin, value) + //todo rename event + c.bus.Events().AddEvent(uint32(height), &eventsdb.UnbondEvent{ + Address: owner, + Amount: value.String(), + Coin: coin, + ValidatorPubKey: pubKey, + }) + c.bus.Accounts().AddBalance(owner, coin, value) + c.bus.Checker().AddCoin(coin, big.NewInt(0).Neg(value)) +} + func (c *Candidates) Exists(pubkey types.Pubkey) bool { c.lock.RLock() defer c.lock.RUnlock() @@ -472,6 +470,7 @@ func (c *Candidates) Delegate(address types.Address, pubkey types.Pubkey, coin t } candidate := c.GetCandidate(pubkey) + candidate.addUpdate(stake) c.bus.Checker().AddCoin(coin, value) @@ -1048,6 +1047,6 @@ func (c *Candidates) AddToBlockPubKey(p types.Pubkey) { func (c *Candidates) maxIDBytes() []byte { bs := make([]byte, 4) - binary.LittleEndian.PutUint32(bs, uint32(c.maxID)) + binary.LittleEndian.PutUint32(bs, c.maxID) return bs } diff --git a/core/state/state.go b/core/state/state.go index 30e8d0eb1..f52980981 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -19,6 +19,7 @@ import ( legacyCoins "github.com/MinterTeam/minter-go-node/core/state/legacy/coins" legacyFrozenfunds "github.com/MinterTeam/minter-go-node/core/state/legacy/frozenfunds" "github.com/MinterTeam/minter-go-node/core/state/validators" + "github.com/MinterTeam/minter-go-node/core/state/watchlist" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/tree" @@ -146,6 +147,7 @@ type State struct { Coins *coins.Coins Checks *checks.Checks Checker *checker.Checker + Watchlist *watchlist.WatchList db db.DB events eventsdb.IEventsDB @@ -406,6 +408,11 @@ func newStateForTree(iavlTree tree.MTree, events eventsdb.IEventsDB, db db.DB, k return nil, err } + watchlistState, err := watchlist.NewWatchList(stateBus, iavlTree) + if err != nil { + return nil, err + } + state := &State{ Validators: validatorsState, App: appState, @@ -416,7 +423,9 @@ func newStateForTree(iavlTree tree.MTree, events eventsdb.IEventsDB, db db.DB, k Checks: checksState, Checker: stateChecker, Halts: haltsState, - bus: stateBus, + Watchlist: watchlistState, + + bus: stateBus, db: db, events: events, diff --git a/core/state/watchlist/model.go b/core/state/watchlist/model.go index de8728edf..190807cec 100644 --- a/core/state/watchlist/model.go +++ b/core/state/watchlist/model.go @@ -25,3 +25,15 @@ func (m *Model) AddToList(publicKey types.Pubkey, coin types.CoinID, value *big. Value: value, }) } + +func (m *Model) GetValue(pubkey types.Pubkey, coin types.CoinID) *big.Int { + value := big.NewInt(0) + + for _, item := range m.List { + if item.PublicKey == pubkey && item.Coin == coin { + value.Add(value, item.Value) + } + } + + return value +} diff --git a/core/state/watchlist/watchlist.go b/core/state/watchlist/watchlist.go index a2bdd2b64..44b23f09a 100644 --- a/core/state/watchlist/watchlist.go +++ b/core/state/watchlist/watchlist.go @@ -80,10 +80,10 @@ func (wl *WatchList) Delete(address types.Address, pubkey types.Pubkey, coin typ log.Panicf("Watchlist not found for %s", address.String()) } - items := make([]Item, len(w.List)-1) - for i, item := range w.List { + items := make([]Item, 0, len(w.List)) + for _, item := range w.List { if item.PublicKey != pubkey && item.Coin != coin { - items[i] = item + items = append(items, item) } } diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index fc7084038..fe9b2ec7b 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -158,7 +158,14 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) deliverState.Accounts.SubBalance(sender, data.Coin, data.Value) + value := data.Value + if watchList := deliverState.Watchlist.GetByAddress(sender); watchList != nil { + watchListValue := watchList.GetValue(data.PubKey, data.Coin) + value.Add(value, watchListValue) + deliverState.Watchlist.Delete(sender, data.PubKey, data.Coin) + } deliverState.Candidates.Delegate(sender, data.PubKey, data.Coin, data.Value, big.NewInt(0)) + deliverState.Accounts.SetNonce(sender, tx.Nonce) } diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 403b7a13e..1a07b3c6b 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -140,8 +140,15 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool deliverState.Coins.SubVolume(tx.GasCoin, commission) deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) - deliverState.Candidates.SubStake(sender, data.PubKey, data.Coin, data.Value) - deliverState.FrozenFunds.AddFund(unbondAtBlock, sender, data.PubKey, data.Coin, data.Value) + + value := data.Value + if watchList := deliverState.Watchlist.GetByAddress(sender); watchList != nil { + watchListValue := watchList.GetValue(data.PubKey, data.Coin) + value.Add(value, watchListValue) + deliverState.Watchlist.Delete(sender, data.PubKey, data.Coin) + } + deliverState.Candidates.SubStake(sender, data.PubKey, data.Coin, value) + deliverState.FrozenFunds.AddFund(unbondAtBlock, sender, data.PubKey, data.Coin, value) deliverState.Accounts.SetNonce(sender, tx.Nonce) } From 27990b9b4102eaaaec6d475ef649fcf229524395 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 11 Aug 2020 09:15:21 +0300 Subject: [PATCH 140/426] watchlist methods --- core/state/bus/coins.go | 14 ++++++------ core/state/candidates_test.go | 2 +- core/state/watchlist/bus.go | 2 +- core/state/watchlist/watchlist.go | 37 +++++++++++++++++++++++++++++++ core/transaction/delegate.go | 8 +++---- core/transaction/unbond.go | 6 ++--- 6 files changed, 53 insertions(+), 16 deletions(-) diff --git a/core/state/bus/coins.go b/core/state/bus/coins.go index 9af9266c9..e26c7474b 100644 --- a/core/state/bus/coins.go +++ b/core/state/bus/coins.go @@ -13,13 +13,13 @@ type Coins interface { } type Coin struct { - ID types.CoinID - Name string - Crr uint - Symbol types.CoinSymbol - Version types.CoinVersion - Volume *big.Int - Reserve *big.Int + ID types.CoinID + Name string + Crr uint + Symbol types.CoinSymbol + Version types.CoinVersion + Volume *big.Int + Reserve *big.Int } func (m Coin) GetFullSymbol() string { diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index 1d59c6dec..bac2404eb 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -346,7 +346,7 @@ func TestZeroStakePenalty(t *testing.T) { st.Candidates.RecalculateStakes(height) st.Candidates.SubStake(addr, pubkey, coin, amount) - st.FrozenFunds.AddFund(518400, addr, pubkey, coin, amount) + st.FrozenFunds.AddFund(518400, addr, pubkey, coin, amount) var pk ed25519.PubKeyEd25519 copy(pk[:], pubkey[:]) diff --git a/core/state/watchlist/bus.go b/core/state/watchlist/bus.go index 993777107..4b5033bf2 100644 --- a/core/state/watchlist/bus.go +++ b/core/state/watchlist/bus.go @@ -9,7 +9,7 @@ type Bus struct { watchlist *WatchList } -func (b *Bus) AddFrozenFund(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { +func (b *Bus) AddToWatchList(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { b.watchlist.AddWatchList(address, pubkey, coin, value) } diff --git a/core/state/watchlist/watchlist.go b/core/state/watchlist/watchlist.go index 44b23f09a..d13793193 100644 --- a/core/state/watchlist/watchlist.go +++ b/core/state/watchlist/watchlist.go @@ -16,7 +16,9 @@ import ( const mainPrefix = byte('w') type RWatchList interface { + Get(address types.Address, pubkey types.Pubkey, coin types.CoinID) *Item GetByAddress(address types.Address) *Model + GetByAddressAndPubKey(address types.Address, pubkey types.Pubkey) []Item AddWatchList(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) Delete(address types.Address, pubkey types.Pubkey, coin types.CoinID) } @@ -67,6 +69,41 @@ func (wl *WatchList) GetByAddress(address types.Address) *Model { return wl.get(address) } +func (wl *WatchList) Get(address types.Address, pubkey types.Pubkey, coin types.CoinID) *Item { + watchlist := wl.get(address) + if watchlist == nil { + return nil + } + + for _, item := range watchlist.List { + if item.PublicKey == pubkey && item.Coin == coin { + return &item + } + } + + return nil +} + +func (wl *WatchList) GetByAddressAndPubKey(address types.Address, pubkey types.Pubkey) []Item { + watchlist := wl.get(address) + if watchlist == nil { + return nil + } + + items := make([]Item, 0) + for i, item := range watchlist.List { + if item.PublicKey == pubkey { + items[i] = item + } + } + + if len(items) == 0 { + return nil + } + + return items +} + func (wl *WatchList) AddWatchList(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { w := wl.getOrNew(address) w.AddToList(pubkey, coin, value) diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index fe9b2ec7b..bb2fc399c 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -158,14 +158,14 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) deliverState.Accounts.SubBalance(sender, data.Coin, data.Value) + value := data.Value - if watchList := deliverState.Watchlist.GetByAddress(sender); watchList != nil { - watchListValue := watchList.GetValue(data.PubKey, data.Coin) - value.Add(value, watchListValue) + if watchList := deliverState.Watchlist.Get(sender, data.PubKey, data.Coin); watchList != nil { + value.Add(value, watchList.Value) deliverState.Watchlist.Delete(sender, data.PubKey, data.Coin) } - deliverState.Candidates.Delegate(sender, data.PubKey, data.Coin, data.Value, big.NewInt(0)) + deliverState.Candidates.Delegate(sender, data.PubKey, data.Coin, data.Value, big.NewInt(0)) deliverState.Accounts.SetNonce(sender, tx.Nonce) } diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 1a07b3c6b..a4e94b489 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -142,11 +142,11 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) value := data.Value - if watchList := deliverState.Watchlist.GetByAddress(sender); watchList != nil { - watchListValue := watchList.GetValue(data.PubKey, data.Coin) - value.Add(value, watchListValue) + if watchList := deliverState.Watchlist.Get(sender, data.PubKey, data.Coin); watchList != nil { + value.Add(value, watchList.Value) deliverState.Watchlist.Delete(sender, data.PubKey, data.Coin) } + deliverState.Candidates.SubStake(sender, data.PubKey, data.Coin, value) deliverState.FrozenFunds.AddFund(unbondAtBlock, sender, data.PubKey, data.Coin, value) deliverState.Accounts.SetNonce(sender, tx.Nonce) From 72341cbc04952a541719322ab6f67b210abc940f Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 11 Aug 2020 09:28:07 +0300 Subject: [PATCH 141/426] fix watchlist bus --- core/state/bus/watchlist.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/state/bus/watchlist.go b/core/state/bus/watchlist.go index a0b3ceec0..f092090f3 100644 --- a/core/state/bus/watchlist.go +++ b/core/state/bus/watchlist.go @@ -6,5 +6,5 @@ import ( ) type WatchList interface { - AddFrozenFund(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) + AddToWatchList(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) } From 6dac9074980973b8303074b2b6c6c9542d68e762 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 11 Aug 2020 09:30:18 +0300 Subject: [PATCH 142/426] fix --- core/state/watchlist/watchlist.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/state/watchlist/watchlist.go b/core/state/watchlist/watchlist.go index d13793193..efd1c0eea 100644 --- a/core/state/watchlist/watchlist.go +++ b/core/state/watchlist/watchlist.go @@ -90,7 +90,7 @@ func (wl *WatchList) GetByAddressAndPubKey(address types.Address, pubkey types.P return nil } - items := make([]Item, 0) + items := make([]Item, 0, len(watchlist.List)) for i, item := range watchlist.List { if item.PublicKey == pubkey { items[i] = item From 2c00c9819f99d8d367b3f9a0c8e57c6a98755e07 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 11 Aug 2020 10:45:34 +0300 Subject: [PATCH 143/426] add watchlist delegation test --- core/state/candidates/candidates.go | 2 +- core/state/candidates_test.go | 34 ++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 5548ed105..389a4c87d 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -371,7 +371,7 @@ func (c *Candidates) recalculateStakesNew(height uint64) { } func (c *Candidates) unbond(owner types.Address, value *big.Int, coin types.CoinID, pubKey types.Pubkey, height uint64) { - c.bus.WatchList().AddFrozenFund(owner, pubKey, coin, value) + c.bus.WatchList().AddToWatchList(owner, pubKey, coin, value) //todo rename event c.bus.Events().AddEvent(uint32(height), &eventsdb.UnbondEvent{ Address: owner, diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index bac2404eb..562b2e9c2 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -6,7 +6,6 @@ import ( eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/state/candidates" "github.com/MinterTeam/minter-go-node/core/types" - "github.com/tendermint/tendermint/crypto/ed25519" db "github.com/tendermint/tm-db" "math/big" @@ -421,6 +420,39 @@ func TestDelegationAfterUnbond(t *testing.T) { } +func TestDelegationWithWatchList(t *testing.T) { + st := getState() + + coin := types.GetBaseCoinID() + pubkey := createTestCandidate(st) + stakeAmount := big.NewInt(10000) + watchlistAmount := big.NewInt(1000) + amount := new(big.Int).Add(stakeAmount, watchlistAmount) + + var addr types.Address + binary.BigEndian.PutUint64(addr[:], 1) + + st.Watchlist.AddWatchList(addr, pubkey, coin, watchlistAmount) + + if watchList := st.Watchlist.Get(addr, pubkey, coin); watchList != nil { + stakeAmount.Add(stakeAmount, watchList.Value) + st.Watchlist.Delete(addr, pubkey, coin) + } + + st.Candidates.Delegate(addr, pubkey, coin, stakeAmount, stakeAmount) + st.Candidates.RecalculateStakes(height) + + value := st.Candidates.GetStakeValueOfAddress(pubkey, addr, coin) + if value == nil || value.Cmp(amount) != 0 { + t.Fatalf("Stake of address %s is not correct. Expected %s, got %s", addr.String(), amount, value) + } + + wl := st.Watchlist.Get(addr, pubkey, coin) + if wl != nil { + t.Fatalf("Watchlist is not deleted") + } +} + func getState() *State { s, err := NewState(0, db.NewMemDB(), emptyEvents{}, 1, 1) From 36ab56e00642ee18f7817810311f589bfd9364d4 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 11 Aug 2020 11:12:27 +0300 Subject: [PATCH 144/426] add tests for watchlist --- core/state/candidates_test.go | 33 --------------- core/transaction/delegate_test.go | 64 +++++++++++++++++++++++++++++ core/transaction/unbond.go | 4 +- core/transaction/unbond_test.go | 68 +++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 35 deletions(-) diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index 562b2e9c2..f63610b81 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -420,39 +420,6 @@ func TestDelegationAfterUnbond(t *testing.T) { } -func TestDelegationWithWatchList(t *testing.T) { - st := getState() - - coin := types.GetBaseCoinID() - pubkey := createTestCandidate(st) - stakeAmount := big.NewInt(10000) - watchlistAmount := big.NewInt(1000) - amount := new(big.Int).Add(stakeAmount, watchlistAmount) - - var addr types.Address - binary.BigEndian.PutUint64(addr[:], 1) - - st.Watchlist.AddWatchList(addr, pubkey, coin, watchlistAmount) - - if watchList := st.Watchlist.Get(addr, pubkey, coin); watchList != nil { - stakeAmount.Add(stakeAmount, watchList.Value) - st.Watchlist.Delete(addr, pubkey, coin) - } - - st.Candidates.Delegate(addr, pubkey, coin, stakeAmount, stakeAmount) - st.Candidates.RecalculateStakes(height) - - value := st.Candidates.GetStakeValueOfAddress(pubkey, addr, coin) - if value == nil || value.Cmp(amount) != 0 { - t.Fatalf("Stake of address %s is not correct. Expected %s, got %s", addr.String(), amount, value) - } - - wl := st.Watchlist.Get(addr, pubkey, coin) - if wl != nil { - t.Fatalf("Watchlist is not deleted") - } -} - func getState() *State { s, err := NewState(0, db.NewMemDB(), emptyEvents{}, 1, 1) diff --git a/core/transaction/delegate_test.go b/core/transaction/delegate_test.go index 934a121f7..f06598236 100644 --- a/core/transaction/delegate_test.go +++ b/core/transaction/delegate_test.go @@ -93,3 +93,67 @@ func TestDelegateTx(t *testing.T) { t.Fatalf("Stake value is not corrent. Expected %s, got %s", value, stake.Value) } } + +func TestDelegateTxWithWatchlist(t *testing.T) { + cState := getState() + pubkey := createTestCandidate(cState) + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + value := helpers.BipToPip(big.NewInt(100)) + watchlistAmount := helpers.BipToPip(big.NewInt(1000)) + + cState.Watchlist.AddWatchList(addr, pubkey, coin, watchlistAmount) + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + data := DelegateData{ + PubKey: pubkey, + Coin: coin, + Value: value, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeDelegate, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != 0 { + t.Fatalf("Response code is not 0. Error %s", response.Log) + } + + cState.Candidates.RecalculateStakes(109000) + stake := cState.Candidates.GetStakeOfAddress(pubkey, addr, coin) + if stake == nil { + t.Fatalf("Stake not found") + } + + amount := new(big.Int).Add(value, watchlistAmount) + if stake.Value.Cmp(amount) != 0 { + t.Fatalf("Stake value is not corrent. Expected %s, got %s", amount, stake.Value) + } + + wl := cState.Watchlist.Get(addr, pubkey, coin) + if wl != nil { + t.Fatalf("Watchlist is not deleted") + } +} diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index a4e94b489..d7d6e4f46 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -141,13 +141,13 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) - value := data.Value + value := new(big.Int).Set(data.Value) if watchList := deliverState.Watchlist.Get(sender, data.PubKey, data.Coin); watchList != nil { value.Add(value, watchList.Value) deliverState.Watchlist.Delete(sender, data.PubKey, data.Coin) } - deliverState.Candidates.SubStake(sender, data.PubKey, data.Coin, value) + deliverState.Candidates.SubStake(sender, data.PubKey, data.Coin, data.Value) deliverState.FrozenFunds.AddFund(unbondAtBlock, sender, data.PubKey, data.Coin, value) deliverState.Accounts.SetNonce(sender, tx.Nonce) } diff --git a/core/transaction/unbond_test.go b/core/transaction/unbond_test.go index a3c501555..9de5468d8 100644 --- a/core/transaction/unbond_test.go +++ b/core/transaction/unbond_test.go @@ -1,6 +1,7 @@ package transaction import ( + "github.com/MinterTeam/minter-go-node/core/state/candidates" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/helpers" @@ -79,3 +80,70 @@ func TestUnbondTx(t *testing.T) { t.Fatalf("Stake value is not corrent. Expected %s, got %s", types.Big0, stake.Value) } } + +func TestUnbondTxWithWatchlist(t *testing.T) { + cState := getState() + pubkey := createTestCandidate(cState) + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + watchlistAmount := helpers.BipToPip(big.NewInt(1000)) + value := helpers.BipToPip(big.NewInt(100)) + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + cState.Candidates.Delegate(addr, pubkey, coin, value, value) + cState.Watchlist.AddWatchList(addr, pubkey, coin, watchlistAmount) + cState.Candidates.RecalculateStakes(109000) + + data := UnbondData{ + PubKey: pubkey, + Coin: coin, + Value: value, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeUnbond, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != 0 { + t.Fatalf("Response code is not 0. Error %s", response.Log) + } + + cState.Candidates.RecalculateStakes(109000) + funds := cState.FrozenFunds.GetFrozenFunds(candidates.UnbondPeriod) + if funds == nil || len(funds.List) != 1 { + t.Fatalf("Frozen funds are not correct") + } + + stake := cState.Candidates.GetStakeOfAddress(pubkey, addr, coin) + if stake.Value.Cmp(types.Big0) != 0 { + t.Fatalf("Stake value is not corrent. Expected %s, got %s", types.Big0, stake.Value) + } + + amount := new(big.Int).Add(value, watchlistAmount) + if funds.List[0].Value.Cmp(amount) != 0 { + t.Fatalf("Stake value is not corrent. Expected %s, got %s", amount, funds.List[0].Value) + } +} From 79cb1d38a9a5d5f7ac04477e2bb51ef4a08e467f Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 11 Aug 2020 11:35:28 +0300 Subject: [PATCH 145/426] add test with full unbond --- core/transaction/unbond_test.go | 82 ++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 2 deletions(-) diff --git a/core/transaction/unbond_test.go b/core/transaction/unbond_test.go index 9de5468d8..1eb69de55 100644 --- a/core/transaction/unbond_test.go +++ b/core/transaction/unbond_test.go @@ -81,7 +81,7 @@ func TestUnbondTx(t *testing.T) { } } -func TestUnbondTxWithWatchlist(t *testing.T) { +func TestFullUnbondTxWithWatchlist(t *testing.T) { cState := getState() pubkey := createTestCandidate(cState) @@ -144,6 +144,84 @@ func TestUnbondTxWithWatchlist(t *testing.T) { amount := new(big.Int).Add(value, watchlistAmount) if funds.List[0].Value.Cmp(amount) != 0 { - t.Fatalf("Stake value is not corrent. Expected %s, got %s", amount, funds.List[0].Value) + t.Fatalf("Frozen funds value is not corrent. Expected %s, got %s", amount, funds.List[0].Value) + } + + wl := cState.Watchlist.Get(addr, pubkey, coin) + if wl != nil { + t.Fatalf("Watchlist is not deleted") + } +} + +func TestUnbondTxWithWatchlist(t *testing.T) { + cState := getState() + pubkey := createTestCandidate(cState) + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + watchlistAmount := helpers.BipToPip(big.NewInt(1000)) + value := helpers.BipToPip(big.NewInt(100)) + unbondAmount := helpers.BipToPip(big.NewInt(50)) + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + cState.Candidates.Delegate(addr, pubkey, coin, value, value) + cState.Watchlist.AddWatchList(addr, pubkey, coin, watchlistAmount) + cState.Candidates.RecalculateStakes(109000) + + data := UnbondData{ + PubKey: pubkey, + Coin: coin, + Value: unbondAmount, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeUnbond, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != 0 { + t.Fatalf("Response code is not 0. Error %s", response.Log) + } + + cState.Candidates.RecalculateStakes(109000) + funds := cState.FrozenFunds.GetFrozenFunds(candidates.UnbondPeriod) + if funds == nil || len(funds.List) != 1 { + t.Fatalf("Frozen funds are not correct") + } + + stake := cState.Candidates.GetStakeOfAddress(pubkey, addr, coin) + if stake.Value.Cmp(unbondAmount) != 0 { + t.Fatalf("Stake value is not corrent. Expected %s, got %s", unbondAmount, stake.Value) + } + + amount := new(big.Int).Add(unbondAmount, watchlistAmount) + if funds.List[0].Value.Cmp(amount) != 0 { + t.Fatalf("Frozen funds value is not corrent. Expected %s, got %s", amount, funds.List[0].Value) + } + + wl := cState.Watchlist.Get(addr, pubkey, coin) + if wl != nil { + t.Fatalf("Watchlist is not deleted") } } From d5cf2714b1b9200b73d2cfd83345762656116c82 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 11 Aug 2020 17:14:48 +0300 Subject: [PATCH 146/426] edit unbound --- core/state/state.go | 7 ++++++ core/state/watchlist/watchlist.go | 2 -- core/transaction/unbond.go | 39 ++++++++++++++++++++++--------- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/core/state/state.go b/core/state/state.go index f52980981..a04356e11 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -83,6 +83,9 @@ func (cs *CheckState) Coins() coins.RCoins { func (cs *CheckState) Checks() checks.RChecks { return cs.state.Checks } +func (cs *CheckState) Watchlist() watchlist.RWatchList { + return cs.state.Watchlist +} func (cs *CheckState) Tree() tree.ReadOnlyTree { return cs.state.Tree() } @@ -257,6 +260,10 @@ func (s *State) Commit() ([]byte, error) { return nil, err } + if err := s.Watchlist.Commit(); err != nil { + return nil, err + } + hash, version, err := s.tree.SaveVersion() if err != nil { return hash, err diff --git a/core/state/watchlist/watchlist.go b/core/state/watchlist/watchlist.go index efd1c0eea..4f9385b33 100644 --- a/core/state/watchlist/watchlist.go +++ b/core/state/watchlist/watchlist.go @@ -19,8 +19,6 @@ type RWatchList interface { Get(address types.Address, pubkey types.Pubkey, coin types.CoinID) *Item GetByAddress(address types.Address) *Model GetByAddressAndPubKey(address types.Address, pubkey types.Pubkey) []Item - AddWatchList(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) - Delete(address types.Address, pubkey types.Pubkey, coin types.CoinID) } type WatchList struct { diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index d7d6e4f46..43ea5a373 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -38,17 +38,29 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R } } + errorInfo := map[string]string{ + "pub_key": data.PubKey.String(), + } if !context.Candidates().Exists(data.PubKey) { return &Response{ Code: code.CandidateNotFound, Log: fmt.Sprintf("Candidate with such public key not found"), - Info: EncodeError(map[string]string{ - "pub_key": data.PubKey.String(), - }), + Info: EncodeError(errorInfo), } } sender, _ := tx.Sender() + + value := big.NewInt(0).Set(data.Value) + if watchlist := context.Watchlist().Get(sender, data.PubKey, data.Coin); watchlist != nil { + value.Sub(value, watchlist.Value) + errorInfo["watchlist"] = watchlist.Value.String() + } + + if value.Cmp(big.NewInt(0)) < 1 { + return nil + } + stake := context.Candidates().GetStakeValueOfAddress(data.PubKey, sender, data.Coin) if stake == nil { @@ -57,13 +69,12 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R Log: fmt.Sprintf("Stake of current user not found")} } - if stake.Cmp(data.Value) < 0 { + if stake.Cmp(value) < 0 { + errorInfo["stake"] = stake.String() return &Response{ Code: code.InsufficientStake, Log: fmt.Sprintf("Insufficient stake for sender account"), - Info: EncodeError(map[string]string{ - "pub_key": data.PubKey.String(), - })} + Info: EncodeError(errorInfo)} } return nil @@ -143,12 +154,18 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool value := new(big.Int).Set(data.Value) if watchList := deliverState.Watchlist.Get(sender, data.PubKey, data.Coin); watchList != nil { - value.Add(value, watchList.Value) - deliverState.Watchlist.Delete(sender, data.PubKey, data.Coin) + value.Sub(value, watchList.Value) + if value.Cmp(big.NewInt(0)) < 1 { + deliverState.Watchlist.Delete(sender, data.PubKey, data.Coin) + if value.Cmp(big.NewInt(0)) == 0 { + deliverState.Watchlist.AddWatchList(sender, data.PubKey, data.Coin, value.Neg(value)) + } + value = big.NewInt(0) + } } - deliverState.Candidates.SubStake(sender, data.PubKey, data.Coin, data.Value) - deliverState.FrozenFunds.AddFund(unbondAtBlock, sender, data.PubKey, data.Coin, value) + deliverState.Candidates.SubStake(sender, data.PubKey, data.Coin, value) + deliverState.FrozenFunds.AddFund(unbondAtBlock, sender, data.PubKey, data.Coin, data.Value) deliverState.Accounts.SetNonce(sender, tx.Nonce) } From 509a70ac35d9450f424543fb09e025fc06638087 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 11 Aug 2020 18:41:47 +0300 Subject: [PATCH 147/426] add StakeKick event --- core/events/types.go | 59 +++++++++++++++++++++++++++++ core/state/candidates/candidates.go | 3 +- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/core/events/types.go b/core/events/types.go index 9a46d3f4a..96a426448 100644 --- a/core/events/types.go +++ b/core/events/types.go @@ -15,6 +15,8 @@ func RegisterAminoEvents(codec *amino.Codec) { "minter/SlashEvent", nil) codec.RegisterConcrete(UnbondEvent{}, "minter/UnbondEvent", nil) + codec.RegisterConcrete(StakeKickEvent{}, + "minter/StakeKick", nil) } type Event interface { @@ -242,3 +244,60 @@ func (ue *UnbondEvent) convert(pubKeyID uint16, addressID uint32) compactEvent { result.PubKeyID = pubKeyID return result } + +type stakeKick struct { + AddressID uint32 + Amount []byte + Coin [10]byte + PubKeyID uint16 +} + +func (u *stakeKick) compile(pubKey string, address [20]byte) Event { + event := new(StakeKickEvent) + copy(event.ValidatorPubKey[:], pubKey) + copy(event.Address[:], address[:]) + copy(event.Coin.Bytes(), u.Coin[:]) + event.Amount = big.NewInt(0).SetBytes(u.Amount).String() + return event +} + +func (u *stakeKick) addressID() uint32 { + return u.AddressID +} + +func (u *stakeKick) pubKeyID() uint16 { + return u.PubKeyID +} + +type StakeKickEvent struct { + Address types.Address `json:"address"` + Amount string `json:"amount"` + Coin types.CoinID `json:"coin"` + ValidatorPubKey types.Pubkey `json:"validator_pub_key"` +} + +func (ue *StakeKickEvent) AddressString() string { + return ue.Address.String() +} + +func (ue *StakeKickEvent) address() types.Address { + return ue.Address +} + +func (ue *StakeKickEvent) ValidatorPubKeyString() string { + return ue.ValidatorPubKey.String() +} + +func (ue *StakeKickEvent) validatorPubKey() types.Pubkey { + return ue.ValidatorPubKey +} + +func (ue *StakeKickEvent) convert(pubKeyID uint16, addressID uint32) compactEvent { + result := new(stakeKick) + result.AddressID = addressID + copy(result.Coin[:], ue.Coin.Bytes()) + bi, _ := big.NewInt(0).SetString(ue.Amount, 10) + result.Amount = bi.Bytes() + result.PubKeyID = pubKeyID + return result +} diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 389a4c87d..8ff37175d 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -372,8 +372,7 @@ func (c *Candidates) recalculateStakesNew(height uint64) { func (c *Candidates) unbond(owner types.Address, value *big.Int, coin types.CoinID, pubKey types.Pubkey, height uint64) { c.bus.WatchList().AddToWatchList(owner, pubKey, coin, value) - //todo rename event - c.bus.Events().AddEvent(uint32(height), &eventsdb.UnbondEvent{ + c.bus.Events().AddEvent(uint32(height), &eventsdb.StakeKickEvent{ Address: owner, Amount: value.String(), Coin: coin, From 2d8857c7b084193237950b6e673dc0e88616682d Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 12 Aug 2020 08:33:16 +0300 Subject: [PATCH 148/426] refactor unbound and delegate --- core/code/code.go | 1 + core/state/candidates/candidates.go | 6 ++-- core/transaction/delegate.go | 4 +-- core/transaction/unbond.go | 46 ++++++++++++++++------------- core/transaction/unbond_test.go | 31 ++++++++----------- 5 files changed, 44 insertions(+), 44 deletions(-) diff --git a/core/code/code.go b/core/code/code.go index 66e57c0ae..fb025511e 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -46,6 +46,7 @@ const ( TooLowStake uint32 = 409 PublicKeyInBlockList uint32 = 410 NewPublicKeyIsBad uint32 = 411 + InsufficientWatchList uint32 = 412 // check CheckInvalidLock uint32 = 501 diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 8ff37175d..d727af0da 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -344,13 +344,13 @@ func (c *Candidates) recalculateStakesNew(height uint64) { } if smallestStake.Cmp(update.BipValue) == 1 { - c.unbond(update.Owner, update.Value, update.Coin, candidate.PubKey, height) + c.stakeKick(update.Owner, update.Value, update.Coin, candidate.PubKey, height) update.setValue(big.NewInt(0)) continue } if stakes[index] != nil { - c.unbond(update.Owner, update.Value, update.Coin, candidate.PubKey, height) + c.stakeKick(update.Owner, update.Value, update.Coin, candidate.PubKey, height) } candidate.SetStakeAtIndex(index, update, true) @@ -370,7 +370,7 @@ func (c *Candidates) recalculateStakesNew(height uint64) { } } -func (c *Candidates) unbond(owner types.Address, value *big.Int, coin types.CoinID, pubKey types.Pubkey, height uint64) { +func (c *Candidates) stakeKick(owner types.Address, value *big.Int, coin types.CoinID, pubKey types.Pubkey, height uint64) { c.bus.WatchList().AddToWatchList(owner, pubKey, coin, value) c.bus.Events().AddEvent(uint32(height), &eventsdb.StakeKickEvent{ Address: owner, diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index bb2fc399c..d5b7e49b2 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -159,13 +159,13 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) deliverState.Accounts.SubBalance(sender, data.Coin, data.Value) - value := data.Value + value := big.NewInt(0).Set(data.Value) if watchList := deliverState.Watchlist.Get(sender, data.PubKey, data.Coin); watchList != nil { value.Add(value, watchList.Value) deliverState.Watchlist.Delete(sender, data.PubKey, data.Coin) } - deliverState.Candidates.Delegate(sender, data.PubKey, data.Coin, data.Value, big.NewInt(0)) + deliverState.Candidates.Delegate(sender, data.PubKey, data.Coin, value, big.NewInt(0)) deliverState.Accounts.SetNonce(sender, tx.Nonce) } diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 43ea5a373..741ac6a3a 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -39,7 +39,8 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R } errorInfo := map[string]string{ - "pub_key": data.PubKey.String(), + "pub_key": data.PubKey.String(), + "unbound_value": data.Value.String(), } if !context.Candidates().Exists(data.PubKey) { return &Response{ @@ -51,14 +52,17 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R sender, _ := tx.Sender() - value := big.NewInt(0).Set(data.Value) if watchlist := context.Watchlist().Get(sender, data.PubKey, data.Coin); watchlist != nil { - value.Sub(value, watchlist.Value) - errorInfo["watchlist"] = watchlist.Value.String() - } - - if value.Cmp(big.NewInt(0)) < 1 { - return nil + value := big.NewInt(0).Sub(data.Value, watchlist.Value) + if value.Sign() < 1 { + return nil + } + errorInfo["watchlist_value"] = watchlist.Value.String() + return &Response{ + Code: code.InsufficientWatchList, + Log: fmt.Sprintf("Insufficient amount at watchlist for sender account"), + Info: EncodeError(errorInfo), + } } stake := context.Candidates().GetStakeValueOfAddress(data.PubKey, sender, data.Coin) @@ -66,15 +70,18 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R if stake == nil { return &Response{ Code: code.StakeNotFound, - Log: fmt.Sprintf("Stake of current user not found")} + Log: fmt.Sprintf("Stake of current user not found"), + Info: EncodeError(errorInfo), + } } - if stake.Cmp(value) < 0 { - errorInfo["stake"] = stake.String() + if stake.Cmp(data.Value) < 0 { + errorInfo["stake_value"] = stake.String() return &Response{ Code: code.InsufficientStake, Log: fmt.Sprintf("Insufficient stake for sender account"), - Info: EncodeError(errorInfo)} + Info: EncodeError(errorInfo), + } } return nil @@ -152,19 +159,16 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) - value := new(big.Int).Set(data.Value) if watchList := deliverState.Watchlist.Get(sender, data.PubKey, data.Coin); watchList != nil { - value.Sub(value, watchList.Value) - if value.Cmp(big.NewInt(0)) < 1 { - deliverState.Watchlist.Delete(sender, data.PubKey, data.Coin) - if value.Cmp(big.NewInt(0)) == 0 { - deliverState.Watchlist.AddWatchList(sender, data.PubKey, data.Coin, value.Neg(value)) - } - value = big.NewInt(0) + diffValue := big.NewInt(0).Sub(data.Value, watchList.Value) + deliverState.Watchlist.Delete(sender, data.PubKey, data.Coin) + if diffValue.Sign() == -1 { + deliverState.Watchlist.AddWatchList(sender, data.PubKey, data.Coin, big.NewInt(0).Neg(diffValue)) } + } else { + deliverState.Candidates.SubStake(sender, data.PubKey, data.Coin, data.Value) } - deliverState.Candidates.SubStake(sender, data.PubKey, data.Coin, value) deliverState.FrozenFunds.AddFund(unbondAtBlock, sender, data.PubKey, data.Coin, data.Value) deliverState.Accounts.SetNonce(sender, tx.Nonce) } diff --git a/core/transaction/unbond_test.go b/core/transaction/unbond_test.go index 1eb69de55..12bfbc16d 100644 --- a/core/transaction/unbond_test.go +++ b/core/transaction/unbond_test.go @@ -89,10 +89,9 @@ func TestFullUnbondTxWithWatchlist(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() watchlistAmount := helpers.BipToPip(big.NewInt(1000)) - value := helpers.BipToPip(big.NewInt(100)) + value := helpers.BipToPip(big.NewInt(1000)) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) - cState.Candidates.Delegate(addr, pubkey, coin, value, value) cState.Watchlist.AddWatchList(addr, pubkey, coin, watchlistAmount) cState.Candidates.RecalculateStakes(109000) @@ -138,13 +137,12 @@ func TestFullUnbondTxWithWatchlist(t *testing.T) { } stake := cState.Candidates.GetStakeOfAddress(pubkey, addr, coin) - if stake.Value.Cmp(types.Big0) != 0 { - t.Fatalf("Stake value is not corrent. Expected %s, got %s", types.Big0, stake.Value) + if stake != nil { + t.Fatalf("Stake value is not empty.") } - amount := new(big.Int).Add(value, watchlistAmount) - if funds.List[0].Value.Cmp(amount) != 0 { - t.Fatalf("Frozen funds value is not corrent. Expected %s, got %s", amount, funds.List[0].Value) + if funds.List[0].Value.Cmp(value) != 0 { + t.Fatalf("Frozen funds value is not corrent. Expected %s, got %s", value, funds.List[0].Value) } wl := cState.Watchlist.Get(addr, pubkey, coin) @@ -161,11 +159,9 @@ func TestUnbondTxWithWatchlist(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() watchlistAmount := helpers.BipToPip(big.NewInt(1000)) - value := helpers.BipToPip(big.NewInt(100)) unbondAmount := helpers.BipToPip(big.NewInt(50)) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) - cState.Candidates.Delegate(addr, pubkey, coin, value, value) cState.Watchlist.AddWatchList(addr, pubkey, coin, watchlistAmount) cState.Candidates.RecalculateStakes(109000) @@ -210,18 +206,17 @@ func TestUnbondTxWithWatchlist(t *testing.T) { t.Fatalf("Frozen funds are not correct") } - stake := cState.Candidates.GetStakeOfAddress(pubkey, addr, coin) - if stake.Value.Cmp(unbondAmount) != 0 { - t.Fatalf("Stake value is not corrent. Expected %s, got %s", unbondAmount, stake.Value) + if funds.List[0].Value.Cmp(unbondAmount) != 0 { + t.Fatalf("Frozen funds value is not corrent. Expected %s, got %s", unbondAmount, funds.List[0].Value) } - amount := new(big.Int).Add(unbondAmount, watchlistAmount) - if funds.List[0].Value.Cmp(amount) != 0 { - t.Fatalf("Frozen funds value is not corrent. Expected %s, got %s", amount, funds.List[0].Value) + wl := cState.Watchlist.Get(addr, pubkey, coin) + if wl == nil { + t.Fatalf("Watchlist is empty") } - wl := cState.Watchlist.Get(addr, pubkey, coin) - if wl != nil { - t.Fatalf("Watchlist is not deleted") + amount := new(big.Int).Sub(watchlistAmount, unbondAmount) + if wl.Value.Cmp(amount) != 0 { + t.Fatalf("Watchlist is not correct") } } From b63f256ac9f6d24c63d060ea183b2b261a6e7a7b Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 12 Aug 2020 08:47:44 +0300 Subject: [PATCH 149/426] add waitlist api method --- api/api.go | 1 + api/waitlist.go | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 api/waitlist.go diff --git a/api/api.go b/api/api.go index 3ab612293..aff3d8481 100644 --- a/api/api.go +++ b/api/api.go @@ -53,6 +53,7 @@ var Routes = map[string]*rpcserver.RPCFunc{ "min_gas_price": rpcserver.NewRPCFunc(MinGasPrice, ""), "genesis": rpcserver.NewRPCFunc(Genesis, ""), "missed_blocks": rpcserver.NewRPCFunc(MissedBlocks, "pub_key,height"), + "waitlist": rpcserver.NewRPCFunc(Waitlist, "pub_key,address,height"), } func responseTime(b *minter.Blockchain) func(f func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) { diff --git a/api/waitlist.go b/api/waitlist.go new file mode 100644 index 000000000..6e9f492d9 --- /dev/null +++ b/api/waitlist.go @@ -0,0 +1,39 @@ +package api + +import ( + "github.com/MinterTeam/minter-go-node/core/types" +) + +type WaitlistResponse struct { + List []*Wait `json:"list"` +} + +type Wait struct { + Coin Coin `json:"coin"` + Value string `json:"value"` +} + +func Waitlist(pubkey types.Pubkey, address types.Address, height int) (*WaitlistResponse, error) { + cState, err := GetStateForHeight(height) + if err != nil { + return nil, err + } + + cState.RLock() + defer cState.RUnlock() + + response := new(WaitlistResponse) + items := cState.Watchlist().GetByAddressAndPubKey(address, pubkey) + response.List = make([]*Wait, 0, len(items)) + for _, item := range items { + response.List = append(response.List, &Wait{ + Coin: Coin{ + ID: item.Coin.Uint32(), + Symbol: cState.Coins().GetCoin(item.Coin).CSymbol.String(), + }, + Value: item.Value.String(), + }) + } + + return response, nil +} From 174677c2ca21a574848a46d133b33f9db5df64f1 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 12 Aug 2020 09:15:33 +0300 Subject: [PATCH 150/426] rename watchlist to waitlist --- core/code/code.go | 2 +- core/state/bus/bus.go | 10 ++-- core/state/bus/watchlist.go | 4 +- core/state/candidates/candidates.go | 2 +- core/state/state.go | 10 ++-- core/state/waitlist/bus.go | 18 +++++++ core/state/{watchlist => waitlist}/model.go | 2 +- .../watchlist.go => waitlist/waitlist.go} | 52 +++++++++---------- core/state/watchlist/bus.go | 18 ------- core/transaction/delegate_test.go | 6 +-- core/transaction/unbond.go | 12 ++--- core/transaction/unbond_test.go | 10 ++-- 12 files changed, 73 insertions(+), 73 deletions(-) create mode 100644 core/state/waitlist/bus.go rename core/state/{watchlist => waitlist}/model.go (97%) rename core/state/{watchlist/watchlist.go => waitlist/waitlist.go} (66%) delete mode 100644 core/state/watchlist/bus.go diff --git a/core/code/code.go b/core/code/code.go index fb025511e..0b4e86ef8 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -46,7 +46,7 @@ const ( TooLowStake uint32 = 409 PublicKeyInBlockList uint32 = 410 NewPublicKeyIsBad uint32 = 411 - InsufficientWatchList uint32 = 412 + InsufficientWaitList uint32 = 412 // check CheckInvalidLock uint32 = 501 diff --git a/core/state/bus/bus.go b/core/state/bus/bus.go index 03413465c..a4b8217e2 100644 --- a/core/state/bus/bus.go +++ b/core/state/bus/bus.go @@ -9,7 +9,7 @@ type Bus struct { candidates Candidates frozenfunds FrozenFunds halts HaltBlocks - watchlist WatchList + waitlist WaitList events eventsdb.IEventsDB checker Checker } @@ -66,12 +66,12 @@ func (b *Bus) Halts() HaltBlocks { return b.halts } -func (b *Bus) SetWatchList(watchList WatchList) { - b.watchlist = watchList +func (b *Bus) SetWatchList(watchList WaitList) { + b.waitlist = watchList } -func (b *Bus) WatchList() WatchList { - return b.watchlist +func (b *Bus) WatchList() WaitList { + return b.waitlist } func (b *Bus) SetEvents(events eventsdb.IEventsDB) { diff --git a/core/state/bus/watchlist.go b/core/state/bus/watchlist.go index f092090f3..25ae9e707 100644 --- a/core/state/bus/watchlist.go +++ b/core/state/bus/watchlist.go @@ -5,6 +5,6 @@ import ( "math/big" ) -type WatchList interface { - AddToWatchList(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) +type WaitList interface { + AddToWaitList(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) } diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index d727af0da..6874a983f 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -371,7 +371,7 @@ func (c *Candidates) recalculateStakesNew(height uint64) { } func (c *Candidates) stakeKick(owner types.Address, value *big.Int, coin types.CoinID, pubKey types.Pubkey, height uint64) { - c.bus.WatchList().AddToWatchList(owner, pubKey, coin, value) + c.bus.WatchList().AddToWaitList(owner, pubKey, coin, value) c.bus.Events().AddEvent(uint32(height), &eventsdb.StakeKickEvent{ Address: owner, Amount: value.String(), diff --git a/core/state/state.go b/core/state/state.go index a04356e11..c0332dd7e 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -19,7 +19,7 @@ import ( legacyCoins "github.com/MinterTeam/minter-go-node/core/state/legacy/coins" legacyFrozenfunds "github.com/MinterTeam/minter-go-node/core/state/legacy/frozenfunds" "github.com/MinterTeam/minter-go-node/core/state/validators" - "github.com/MinterTeam/minter-go-node/core/state/watchlist" + "github.com/MinterTeam/minter-go-node/core/state/waitlist" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/tree" @@ -83,7 +83,7 @@ func (cs *CheckState) Coins() coins.RCoins { func (cs *CheckState) Checks() checks.RChecks { return cs.state.Checks } -func (cs *CheckState) Watchlist() watchlist.RWatchList { +func (cs *CheckState) Watchlist() waitlist.RWaitList { return cs.state.Watchlist } func (cs *CheckState) Tree() tree.ReadOnlyTree { @@ -150,7 +150,7 @@ type State struct { Coins *coins.Coins Checks *checks.Checks Checker *checker.Checker - Watchlist *watchlist.WatchList + Watchlist *waitlist.WaitList db db.DB events eventsdb.IEventsDB @@ -415,7 +415,7 @@ func newStateForTree(iavlTree tree.MTree, events eventsdb.IEventsDB, db db.DB, k return nil, err } - watchlistState, err := watchlist.NewWatchList(stateBus, iavlTree) + waitlistState, err := waitlist.NewWatchList(stateBus, iavlTree) if err != nil { return nil, err } @@ -430,7 +430,7 @@ func newStateForTree(iavlTree tree.MTree, events eventsdb.IEventsDB, db db.DB, k Checks: checksState, Checker: stateChecker, Halts: haltsState, - Watchlist: watchlistState, + Watchlist: waitlistState, bus: stateBus, diff --git a/core/state/waitlist/bus.go b/core/state/waitlist/bus.go new file mode 100644 index 000000000..7b0d858bd --- /dev/null +++ b/core/state/waitlist/bus.go @@ -0,0 +1,18 @@ +package waitlist + +import ( + "github.com/MinterTeam/minter-go-node/core/types" + "math/big" +) + +type Bus struct { + waitlist *WaitList +} + +func (b *Bus) AddToWaitList(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { + b.waitlist.AddWaitList(address, pubkey, coin, value) +} + +func NewBus(waitlist *WaitList) *Bus { + return &Bus{waitlist: waitlist} +} diff --git a/core/state/watchlist/model.go b/core/state/waitlist/model.go similarity index 97% rename from core/state/watchlist/model.go rename to core/state/waitlist/model.go index 190807cec..28796be06 100644 --- a/core/state/watchlist/model.go +++ b/core/state/waitlist/model.go @@ -1,4 +1,4 @@ -package watchlist +package waitlist import ( "github.com/MinterTeam/minter-go-node/core/types" diff --git a/core/state/watchlist/watchlist.go b/core/state/waitlist/waitlist.go similarity index 66% rename from core/state/watchlist/watchlist.go rename to core/state/waitlist/waitlist.go index 4f9385b33..e93604bc8 100644 --- a/core/state/watchlist/watchlist.go +++ b/core/state/waitlist/waitlist.go @@ -1,4 +1,4 @@ -package watchlist +package waitlist import ( "bytes" @@ -15,13 +15,13 @@ import ( const mainPrefix = byte('w') -type RWatchList interface { +type RWaitList interface { Get(address types.Address, pubkey types.Pubkey, coin types.CoinID) *Item GetByAddress(address types.Address) *Model GetByAddressAndPubKey(address types.Address, pubkey types.Pubkey) []Item } -type WatchList struct { +type WaitList struct { list map[types.Address]*Model dirty map[types.Address]interface{} @@ -31,18 +31,18 @@ type WatchList struct { lock sync.RWMutex } -func NewWatchList(stateBus *bus.Bus, iavl tree.MTree) (*WatchList, error) { - watchlist := &WatchList{ +func NewWatchList(stateBus *bus.Bus, iavl tree.MTree) (*WaitList, error) { + waitlist := &WaitList{ bus: stateBus, iavl: iavl, list: map[types.Address]*Model{}, dirty: map[types.Address]interface{}{}, } - return watchlist, nil + return waitlist, nil } -func (wl *WatchList) Commit() error { +func (wl *WaitList) Commit() error { dirty := wl.getOrderedDirty() for _, address := range dirty { w := wl.getFromMap(address) @@ -63,17 +63,17 @@ func (wl *WatchList) Commit() error { return nil } -func (wl *WatchList) GetByAddress(address types.Address) *Model { +func (wl *WaitList) GetByAddress(address types.Address) *Model { return wl.get(address) } -func (wl *WatchList) Get(address types.Address, pubkey types.Pubkey, coin types.CoinID) *Item { - watchlist := wl.get(address) - if watchlist == nil { +func (wl *WaitList) Get(address types.Address, pubkey types.Pubkey, coin types.CoinID) *Item { + waitlist := wl.get(address) + if waitlist == nil { return nil } - for _, item := range watchlist.List { + for _, item := range waitlist.List { if item.PublicKey == pubkey && item.Coin == coin { return &item } @@ -82,14 +82,14 @@ func (wl *WatchList) Get(address types.Address, pubkey types.Pubkey, coin types. return nil } -func (wl *WatchList) GetByAddressAndPubKey(address types.Address, pubkey types.Pubkey) []Item { - watchlist := wl.get(address) - if watchlist == nil { +func (wl *WaitList) GetByAddressAndPubKey(address types.Address, pubkey types.Pubkey) []Item { + waitlist := wl.get(address) + if waitlist == nil { return nil } - items := make([]Item, 0, len(watchlist.List)) - for i, item := range watchlist.List { + items := make([]Item, 0, len(waitlist.List)) + for i, item := range waitlist.List { if item.PublicKey == pubkey { items[i] = item } @@ -102,14 +102,14 @@ func (wl *WatchList) GetByAddressAndPubKey(address types.Address, pubkey types.P return items } -func (wl *WatchList) AddWatchList(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { +func (wl *WaitList) AddWaitList(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { w := wl.getOrNew(address) w.AddToList(pubkey, coin, value) wl.setToMap(address, w) w.markDirty(address) } -func (wl *WatchList) Delete(address types.Address, pubkey types.Pubkey, coin types.CoinID) { +func (wl *WaitList) Delete(address types.Address, pubkey types.Pubkey, coin types.CoinID) { w := wl.get(address) if w == nil || len(w.List) == 0 { log.Panicf("Watchlist not found for %s", address.String()) @@ -127,7 +127,7 @@ func (wl *WatchList) Delete(address types.Address, pubkey types.Pubkey, coin typ wl.setToMap(address, w) } -func (wl *WatchList) getOrNew(address types.Address) *Model { +func (wl *WaitList) getOrNew(address types.Address) *Model { w := wl.get(address) if w == nil { w = &Model{List: make([]Item, 0), address: address, markDirty: wl.markDirty} @@ -137,7 +137,7 @@ func (wl *WatchList) getOrNew(address types.Address) *Model { return w } -func (wl *WatchList) get(address types.Address) *Model { +func (wl *WaitList) get(address types.Address) *Model { if ff := wl.getFromMap(address); ff != nil { return ff } @@ -150,7 +150,7 @@ func (wl *WatchList) get(address types.Address) *Model { m := new(Model) if err := rlp.DecodeBytes(enc, m); err != nil { - panic(fmt.Sprintf("failed to decode watchlists for address %d: %s", address.String(), err)) + panic(fmt.Sprintf("failed to decode waitlists for address %d: %s", address.String(), err)) } m.address = address @@ -160,25 +160,25 @@ func (wl *WatchList) get(address types.Address) *Model { return m } -func (wl *WatchList) getFromMap(address types.Address) *Model { +func (wl *WaitList) getFromMap(address types.Address) *Model { wl.lock.RLock() defer wl.lock.RUnlock() return wl.list[address] } -func (wl *WatchList) setToMap(address types.Address, model *Model) { +func (wl *WaitList) setToMap(address types.Address, model *Model) { wl.lock.Lock() defer wl.lock.Unlock() wl.list[address] = model } -func (wl *WatchList) markDirty(address types.Address) { +func (wl *WaitList) markDirty(address types.Address) { wl.dirty[address] = struct{}{} } -func (wl *WatchList) getOrderedDirty() []types.Address { +func (wl *WaitList) getOrderedDirty() []types.Address { keys := make([]types.Address, 0, len(wl.dirty)) for k := range wl.dirty { keys = append(keys, k) diff --git a/core/state/watchlist/bus.go b/core/state/watchlist/bus.go deleted file mode 100644 index 4b5033bf2..000000000 --- a/core/state/watchlist/bus.go +++ /dev/null @@ -1,18 +0,0 @@ -package watchlist - -import ( - "github.com/MinterTeam/minter-go-node/core/types" - "math/big" -) - -type Bus struct { - watchlist *WatchList -} - -func (b *Bus) AddToWatchList(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { - b.watchlist.AddWatchList(address, pubkey, coin, value) -} - -func NewBus(watchlist *WatchList) *Bus { - return &Bus{watchlist: watchlist} -} diff --git a/core/transaction/delegate_test.go b/core/transaction/delegate_test.go index f06598236..f75bfd858 100644 --- a/core/transaction/delegate_test.go +++ b/core/transaction/delegate_test.go @@ -101,9 +101,9 @@ func TestDelegateTxWithWatchlist(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() value := helpers.BipToPip(big.NewInt(100)) - watchlistAmount := helpers.BipToPip(big.NewInt(1000)) + waitlistAmount := helpers.BipToPip(big.NewInt(1000)) - cState.Watchlist.AddWatchList(addr, pubkey, coin, watchlistAmount) + cState.Watchlist.AddWaitList(addr, pubkey, coin, waitlistAmount) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) data := DelegateData{ @@ -147,7 +147,7 @@ func TestDelegateTxWithWatchlist(t *testing.T) { t.Fatalf("Stake not found") } - amount := new(big.Int).Add(value, watchlistAmount) + amount := new(big.Int).Add(value, waitlistAmount) if stake.Value.Cmp(amount) != 0 { t.Fatalf("Stake value is not corrent. Expected %s, got %s", amount, stake.Value) } diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 741ac6a3a..cb4590c5e 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -52,15 +52,15 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R sender, _ := tx.Sender() - if watchlist := context.Watchlist().Get(sender, data.PubKey, data.Coin); watchlist != nil { - value := big.NewInt(0).Sub(data.Value, watchlist.Value) + if waitlist := context.Watchlist().Get(sender, data.PubKey, data.Coin); waitlist != nil { + value := big.NewInt(0).Sub(data.Value, waitlist.Value) if value.Sign() < 1 { return nil } - errorInfo["watchlist_value"] = watchlist.Value.String() + errorInfo["waitlist_value"] = waitlist.Value.String() return &Response{ - Code: code.InsufficientWatchList, - Log: fmt.Sprintf("Insufficient amount at watchlist for sender account"), + Code: code.InsufficientWaitList, + Log: fmt.Sprintf("Insufficient amount at waitlist for sender account"), Info: EncodeError(errorInfo), } } @@ -163,7 +163,7 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool diffValue := big.NewInt(0).Sub(data.Value, watchList.Value) deliverState.Watchlist.Delete(sender, data.PubKey, data.Coin) if diffValue.Sign() == -1 { - deliverState.Watchlist.AddWatchList(sender, data.PubKey, data.Coin, big.NewInt(0).Neg(diffValue)) + deliverState.Watchlist.AddWaitList(sender, data.PubKey, data.Coin, big.NewInt(0).Neg(diffValue)) } } else { deliverState.Candidates.SubStake(sender, data.PubKey, data.Coin, data.Value) diff --git a/core/transaction/unbond_test.go b/core/transaction/unbond_test.go index 12bfbc16d..1e93c3797 100644 --- a/core/transaction/unbond_test.go +++ b/core/transaction/unbond_test.go @@ -88,11 +88,11 @@ func TestFullUnbondTxWithWatchlist(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - watchlistAmount := helpers.BipToPip(big.NewInt(1000)) + waitlistAmount := helpers.BipToPip(big.NewInt(1000)) value := helpers.BipToPip(big.NewInt(1000)) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) - cState.Watchlist.AddWatchList(addr, pubkey, coin, watchlistAmount) + cState.Watchlist.AddWaitList(addr, pubkey, coin, waitlistAmount) cState.Candidates.RecalculateStakes(109000) data := UnbondData{ @@ -158,11 +158,11 @@ func TestUnbondTxWithWatchlist(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - watchlistAmount := helpers.BipToPip(big.NewInt(1000)) + waitlistAmount := helpers.BipToPip(big.NewInt(1000)) unbondAmount := helpers.BipToPip(big.NewInt(50)) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) - cState.Watchlist.AddWatchList(addr, pubkey, coin, watchlistAmount) + cState.Watchlist.AddWaitList(addr, pubkey, coin, waitlistAmount) cState.Candidates.RecalculateStakes(109000) data := UnbondData{ @@ -215,7 +215,7 @@ func TestUnbondTxWithWatchlist(t *testing.T) { t.Fatalf("Watchlist is empty") } - amount := new(big.Int).Sub(watchlistAmount, unbondAmount) + amount := new(big.Int).Sub(waitlistAmount, unbondAmount) if wl.Value.Cmp(amount) != 0 { t.Fatalf("Watchlist is not correct") } From 05b3591247fcbbd739dfaef58268065e96e37168 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 12 Aug 2020 10:10:19 +0300 Subject: [PATCH 151/426] add test waitlist --- core/state/bus/bus.go | 6 ++--- core/state/candidates/candidates.go | 2 +- core/state/candidates_test.go | 37 +++++++++++++++++++++++++++++ core/state/state.go | 10 ++++---- core/state/waitlist/waitlist.go | 5 ++-- core/transaction/delegate.go | 4 ++-- core/transaction/delegate_test.go | 6 ++--- core/transaction/unbond.go | 6 ++--- core/transaction/unbond_test.go | 14 +++++------ 9 files changed, 64 insertions(+), 26 deletions(-) diff --git a/core/state/bus/bus.go b/core/state/bus/bus.go index a4b8217e2..d19fb4d42 100644 --- a/core/state/bus/bus.go +++ b/core/state/bus/bus.go @@ -66,11 +66,11 @@ func (b *Bus) Halts() HaltBlocks { return b.halts } -func (b *Bus) SetWatchList(watchList WaitList) { - b.waitlist = watchList +func (b *Bus) SetWaitList(waitList WaitList) { + b.waitlist = waitList } -func (b *Bus) WatchList() WaitList { +func (b *Bus) WaitList() WaitList { return b.waitlist } diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 6874a983f..69088b928 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -371,7 +371,7 @@ func (c *Candidates) recalculateStakesNew(height uint64) { } func (c *Candidates) stakeKick(owner types.Address, value *big.Int, coin types.CoinID, pubKey types.Pubkey, height uint64) { - c.bus.WatchList().AddToWaitList(owner, pubKey, coin, value) + c.bus.WaitList().AddToWaitList(owner, pubKey, coin, value) c.bus.Events().AddEvent(uint32(height), &eventsdb.StakeKickEvent{ Address: owner, Amount: value.String(), diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index f63610b81..d94797b34 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -420,6 +420,43 @@ func TestDelegationAfterUnbond(t *testing.T) { } +func TestStakeKick(t *testing.T) { + st := getState() + + coin := types.GetBaseCoinID() + pubkey := createTestCandidate(st) + + for i := uint64(0); i < 1000; i++ { + amount := big.NewInt(int64(1000 - i)) + var addr types.Address + binary.BigEndian.PutUint64(addr[:], i) + st.Candidates.Delegate(addr, pubkey, coin, amount, big.NewInt(0)) + } + + st.Candidates.RecalculateStakes(height) + + { + amount := big.NewInt(1001) + var addr types.Address + binary.BigEndian.PutUint64(addr[:], 1001) + st.Candidates.Delegate(addr, pubkey, coin, amount, big.NewInt(0)) + } + + st.Candidates.RecalculateStakes(height) + + var addr types.Address + binary.BigEndian.PutUint64(addr[:], 999) + wl := st.Waitlist.Get(addr, pubkey, coin) + + if wl == nil { + t.Fatalf("Waitlist is empty") + } + + if wl.Value.Cmp(big.NewInt(1)) != 0 { + t.Fatalf("Waitlist is not correct") + } +} + func getState() *State { s, err := NewState(0, db.NewMemDB(), emptyEvents{}, 1, 1) diff --git a/core/state/state.go b/core/state/state.go index c0332dd7e..5d83b06dd 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -84,7 +84,7 @@ func (cs *CheckState) Checks() checks.RChecks { return cs.state.Checks } func (cs *CheckState) Watchlist() waitlist.RWaitList { - return cs.state.Watchlist + return cs.state.Waitlist } func (cs *CheckState) Tree() tree.ReadOnlyTree { return cs.state.Tree() @@ -150,7 +150,7 @@ type State struct { Coins *coins.Coins Checks *checks.Checks Checker *checker.Checker - Watchlist *waitlist.WaitList + Waitlist *waitlist.WaitList db db.DB events eventsdb.IEventsDB @@ -260,7 +260,7 @@ func (s *State) Commit() ([]byte, error) { return nil, err } - if err := s.Watchlist.Commit(); err != nil { + if err := s.Waitlist.Commit(); err != nil { return nil, err } @@ -415,7 +415,7 @@ func newStateForTree(iavlTree tree.MTree, events eventsdb.IEventsDB, db db.DB, k return nil, err } - waitlistState, err := waitlist.NewWatchList(stateBus, iavlTree) + waitlistState, err := waitlist.NewWaitList(stateBus, iavlTree) if err != nil { return nil, err } @@ -430,7 +430,7 @@ func newStateForTree(iavlTree tree.MTree, events eventsdb.IEventsDB, db db.DB, k Checks: checksState, Checker: stateChecker, Halts: haltsState, - Watchlist: waitlistState, + Waitlist: waitlistState, bus: stateBus, diff --git a/core/state/waitlist/waitlist.go b/core/state/waitlist/waitlist.go index e93604bc8..1bb03a67e 100644 --- a/core/state/waitlist/waitlist.go +++ b/core/state/waitlist/waitlist.go @@ -31,13 +31,14 @@ type WaitList struct { lock sync.RWMutex } -func NewWatchList(stateBus *bus.Bus, iavl tree.MTree) (*WaitList, error) { +func NewWaitList(stateBus *bus.Bus, iavl tree.MTree) (*WaitList, error) { waitlist := &WaitList{ bus: stateBus, iavl: iavl, list: map[types.Address]*Model{}, dirty: map[types.Address]interface{}{}, } + waitlist.bus.SetWaitList(NewBus(waitlist)) return waitlist, nil } @@ -112,7 +113,7 @@ func (wl *WaitList) AddWaitList(address types.Address, pubkey types.Pubkey, coin func (wl *WaitList) Delete(address types.Address, pubkey types.Pubkey, coin types.CoinID) { w := wl.get(address) if w == nil || len(w.List) == 0 { - log.Panicf("Watchlist not found for %s", address.String()) + log.Panicf("Waitlist not found for %s", address.String()) } items := make([]Item, 0, len(w.List)) diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index d5b7e49b2..ebdad638f 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -160,9 +160,9 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo deliverState.Accounts.SubBalance(sender, data.Coin, data.Value) value := big.NewInt(0).Set(data.Value) - if watchList := deliverState.Watchlist.Get(sender, data.PubKey, data.Coin); watchList != nil { + if watchList := deliverState.Waitlist.Get(sender, data.PubKey, data.Coin); watchList != nil { value.Add(value, watchList.Value) - deliverState.Watchlist.Delete(sender, data.PubKey, data.Coin) + deliverState.Waitlist.Delete(sender, data.PubKey, data.Coin) } deliverState.Candidates.Delegate(sender, data.PubKey, data.Coin, value, big.NewInt(0)) diff --git a/core/transaction/delegate_test.go b/core/transaction/delegate_test.go index f75bfd858..04e9e5249 100644 --- a/core/transaction/delegate_test.go +++ b/core/transaction/delegate_test.go @@ -103,7 +103,7 @@ func TestDelegateTxWithWatchlist(t *testing.T) { value := helpers.BipToPip(big.NewInt(100)) waitlistAmount := helpers.BipToPip(big.NewInt(1000)) - cState.Watchlist.AddWaitList(addr, pubkey, coin, waitlistAmount) + cState.Waitlist.AddWaitList(addr, pubkey, coin, waitlistAmount) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) data := DelegateData{ @@ -152,8 +152,8 @@ func TestDelegateTxWithWatchlist(t *testing.T) { t.Fatalf("Stake value is not corrent. Expected %s, got %s", amount, stake.Value) } - wl := cState.Watchlist.Get(addr, pubkey, coin) + wl := cState.Waitlist.Get(addr, pubkey, coin) if wl != nil { - t.Fatalf("Watchlist is not deleted") + t.Fatalf("Waitlist is not deleted") } } diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index cb4590c5e..0d6e413df 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -159,11 +159,11 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) - if watchList := deliverState.Watchlist.Get(sender, data.PubKey, data.Coin); watchList != nil { + if watchList := deliverState.Waitlist.Get(sender, data.PubKey, data.Coin); watchList != nil { diffValue := big.NewInt(0).Sub(data.Value, watchList.Value) - deliverState.Watchlist.Delete(sender, data.PubKey, data.Coin) + deliverState.Waitlist.Delete(sender, data.PubKey, data.Coin) if diffValue.Sign() == -1 { - deliverState.Watchlist.AddWaitList(sender, data.PubKey, data.Coin, big.NewInt(0).Neg(diffValue)) + deliverState.Waitlist.AddWaitList(sender, data.PubKey, data.Coin, big.NewInt(0).Neg(diffValue)) } } else { deliverState.Candidates.SubStake(sender, data.PubKey, data.Coin, data.Value) diff --git a/core/transaction/unbond_test.go b/core/transaction/unbond_test.go index 1e93c3797..cb6b032b5 100644 --- a/core/transaction/unbond_test.go +++ b/core/transaction/unbond_test.go @@ -92,7 +92,7 @@ func TestFullUnbondTxWithWatchlist(t *testing.T) { value := helpers.BipToPip(big.NewInt(1000)) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) - cState.Watchlist.AddWaitList(addr, pubkey, coin, waitlistAmount) + cState.Waitlist.AddWaitList(addr, pubkey, coin, waitlistAmount) cState.Candidates.RecalculateStakes(109000) data := UnbondData{ @@ -145,9 +145,9 @@ func TestFullUnbondTxWithWatchlist(t *testing.T) { t.Fatalf("Frozen funds value is not corrent. Expected %s, got %s", value, funds.List[0].Value) } - wl := cState.Watchlist.Get(addr, pubkey, coin) + wl := cState.Waitlist.Get(addr, pubkey, coin) if wl != nil { - t.Fatalf("Watchlist is not deleted") + t.Fatalf("Waitlist is not deleted") } } @@ -162,7 +162,7 @@ func TestUnbondTxWithWatchlist(t *testing.T) { unbondAmount := helpers.BipToPip(big.NewInt(50)) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) - cState.Watchlist.AddWaitList(addr, pubkey, coin, waitlistAmount) + cState.Waitlist.AddWaitList(addr, pubkey, coin, waitlistAmount) cState.Candidates.RecalculateStakes(109000) data := UnbondData{ @@ -210,13 +210,13 @@ func TestUnbondTxWithWatchlist(t *testing.T) { t.Fatalf("Frozen funds value is not corrent. Expected %s, got %s", unbondAmount, funds.List[0].Value) } - wl := cState.Watchlist.Get(addr, pubkey, coin) + wl := cState.Waitlist.Get(addr, pubkey, coin) if wl == nil { - t.Fatalf("Watchlist is empty") + t.Fatalf("Waitlist is empty") } amount := new(big.Int).Sub(waitlistAmount, unbondAmount) if wl.Value.Cmp(amount) != 0 { - t.Fatalf("Watchlist is not correct") + t.Fatalf("Waitlist is not correct") } } From 7364aaf7701e39c7e0a0c0de45c0e4f92ae3a4a7 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 12 Aug 2020 10:23:40 +0300 Subject: [PATCH 152/426] fix stake kick --- core/state/candidates/candidates.go | 2 +- core/state/candidates_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 69088b928..4b49d6467 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -350,7 +350,7 @@ func (c *Candidates) recalculateStakesNew(height uint64) { } if stakes[index] != nil { - c.stakeKick(update.Owner, update.Value, update.Coin, candidate.PubKey, height) + c.stakeKick(stakes[index].Owner, stakes[index].Value, stakes[index].Coin, candidate.PubKey, height) } candidate.SetStakeAtIndex(index, update, true) diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index d94797b34..f8fd1bc45 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -443,7 +443,7 @@ func TestStakeKick(t *testing.T) { } st.Candidates.RecalculateStakes(height) - + st.Waitlist.Commit() var addr types.Address binary.BigEndian.PutUint64(addr[:], 999) wl := st.Waitlist.Get(addr, pubkey, coin) From f0b2003c30df4331ba6ce7c09d1b483834b5df49 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 12 Aug 2020 11:06:17 +0300 Subject: [PATCH 153/426] fix tests --- core/state/candidates_test.go | 2 +- core/state/waitlist/waitlist.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index f8fd1bc45..d94797b34 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -443,7 +443,7 @@ func TestStakeKick(t *testing.T) { } st.Candidates.RecalculateStakes(height) - st.Waitlist.Commit() + var addr types.Address binary.BigEndian.PutUint64(addr[:], 999) wl := st.Waitlist.Get(addr, pubkey, coin) diff --git a/core/state/waitlist/waitlist.go b/core/state/waitlist/waitlist.go index 1bb03a67e..257359e38 100644 --- a/core/state/waitlist/waitlist.go +++ b/core/state/waitlist/waitlist.go @@ -151,7 +151,7 @@ func (wl *WaitList) get(address types.Address) *Model { m := new(Model) if err := rlp.DecodeBytes(enc, m); err != nil { - panic(fmt.Sprintf("failed to decode waitlists for address %d: %s", address.String(), err)) + panic(fmt.Sprintf("failed to decode waitlists for address %s: %s", address.String(), err)) } m.address = address From 269b9bbafc1367302a647566922f78aaccb54863 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 12 Aug 2020 12:06:13 +0300 Subject: [PATCH 154/426] fix grpc transaction data --- api/v2/service/transaction.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v2/service/transaction.go b/api/v2/service/transaction.go index d7ecf762c..9364fd650 100644 --- a/api/v2/service/transaction.go +++ b/api/v2/service/transaction.go @@ -41,7 +41,7 @@ func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) ( } txJsonEncoder := encoder.NewTxEncoderJSON(cState) - data, err := txJsonEncoder.Encode(decodedTx, tx) + data, err := txJsonEncoder.EncodeData(decodedTx) if err != nil { return new(pb.TransactionResponse), status.Error(codes.Internal, err.Error()) } From 7f067a7d543d0a3f51abd775a6d824be99f416e4 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 12 Aug 2020 15:09:44 +0300 Subject: [PATCH 155/426] fix max id candidates --- core/state/candidates/candidates.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 4b49d6467..97163749a 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -1023,6 +1023,10 @@ func (c *Candidates) setPubKeyID(pubkey types.Pubkey, u uint32) { c.lock.Lock() defer c.lock.Unlock() + if c.maxID < u { + c.maxID = u + } + if c.pubKeyIDs == nil { c.pubKeyIDs = map[types.Pubkey]uint32{} } From 02614ff253be38fce1b2a2a27e92c9ed9d701859 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 12 Aug 2020 16:37:21 +0300 Subject: [PATCH 156/426] update gateway --- api/v2/service/block.go | 19 +-- api/v2/service/data_encoder.go | 222 +++++++++++++++++++++++++++++++++ api/v2/service/transaction.go | 9 +- api/v2/service/transactions.go | 11 +- go.mod | 2 +- go.sum | 4 +- 6 files changed, 234 insertions(+), 33 deletions(-) create mode 100644 api/v2/service/data_encoder.go diff --git a/api/v2/service/block.go b/api/v2/service/block.go index d4f21288b..abaa08032 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -7,8 +7,8 @@ import ( "fmt" "github.com/MinterTeam/minter-go-node/core/rewards" "github.com/MinterTeam/minter-go-node/core/state" + "github.com/MinterTeam/minter-go-node/core/state/coins" "github.com/MinterTeam/minter-go-node/core/transaction" - "github.com/MinterTeam/minter-go-node/core/transaction/encoder" "github.com/MinterTeam/minter-go-node/core/types" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" core_types "github.com/tendermint/tendermint/rpc/core/types" @@ -58,8 +58,7 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes return nil, err } - txJsonEncoder := encoder.NewTxEncoderJSON(cState) - response.Transactions, err = s.blockTransaction(block, blockResults, txJsonEncoder) + response.Transactions, err = s.blockTransaction(block, blockResults, cState.Coins()) if err != nil { return new(pb.BlockResponse), err } @@ -126,8 +125,7 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes continue } - txJsonEncoder := encoder.NewTxEncoderJSON(cState) - response.Transactions, err = s.blockTransaction(block, blockResults, txJsonEncoder) + response.Transactions, err = s.blockTransaction(block, blockResults, cState.Coins()) if err != nil { return new(pb.BlockResponse), err } @@ -212,7 +210,7 @@ func blockProposer(block *core_types.ResultBlock, totalValidators []*tmTypes.Val return "", nil } -func (s *Service) blockTransaction(block *core_types.ResultBlock, blockResults *core_types.ResultBlockResults, jsonEncoder *encoder.TxEncoderJSON) ([]*pb.BlockResponse_Transaction, error) { +func (s *Service) blockTransaction(block *core_types.ResultBlock, blockResults *core_types.ResultBlockResults, coins coins.RCoins) ([]*pb.BlockResponse_Transaction, error) { txs := make([]*pb.BlockResponse_Transaction, 0, len(block.Block.Data.Txs)) for i, rawTx := range block.Block.Data.Txs { @@ -224,12 +222,7 @@ func (s *Service) blockTransaction(block *core_types.ResultBlock, blockResults * tags[string(tag.Key)] = string(tag.Value) } - data, err := jsonEncoder.EncodeData(tx) - if err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } - - dataStruct, err := encodeToStruct(data) + data, err := encode(tx.GetDecodedData(), coins) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } @@ -241,7 +234,7 @@ func (s *Service) blockTransaction(block *core_types.ResultBlock, blockResults * Nonce: fmt.Sprintf("%d", tx.Nonce), GasPrice: fmt.Sprintf("%d", tx.GasPrice), Type: fmt.Sprintf("%d", tx.Type), - Data: dataStruct, + Data: data, Payload: tx.Payload, ServiceData: tx.ServiceData, Gas: fmt.Sprintf("%d", tx.Gas()), diff --git a/api/v2/service/data_encoder.go b/api/v2/service/data_encoder.go new file mode 100644 index 000000000..623931101 --- /dev/null +++ b/api/v2/service/data_encoder.go @@ -0,0 +1,222 @@ +package service + +import ( + "encoding/base64" + "errors" + "github.com/MinterTeam/minter-go-node/core/state/coins" + "github.com/MinterTeam/minter-go-node/core/transaction" + pb "github.com/MinterTeam/node-grpc-gateway/api_pb" + "github.com/golang/protobuf/ptypes/any" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/wrapperspb" + "strconv" +) + +func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { + var m proto.Message + switch data.(type) { + case *transaction.BuyCoinData: + d := data.(*transaction.BuyCoinData) + m = &pb.BuyCoin{ + CoinToBuy: &pb.Coin{ + Id: d.CoinToBuy.String(), + Symbol: coins.GetCoin(d.CoinToBuy).Symbol().String(), + }, + ValueToBuy: d.ValueToBuy.String(), + CoinToSell: &pb.Coin{ + Id: d.CoinToSell.String(), + Symbol: coins.GetCoin(d.CoinToSell).Symbol().String(), + }, + MaximumValueToSell: d.MaximumValueToSell.String(), + } + case *transaction.ChangeOwnerData: + d := data.(*transaction.ChangeOwnerData) + m = &pb.ChangeOwnerData{ + Symbol: d.Symbol.String(), + NewOwner: d.NewOwner.String(), + } + case *transaction.CreateCoinData: + d := data.(*transaction.CreateCoinData) + m = &pb.CreateCoinData{ + Name: d.Name, + Symbol: d.Symbol.String(), + InitialAmount: d.InitialAmount.String(), + InitialReserve: d.InitialReserve.String(), + ConstantReserveRatio: strconv.Itoa(int(d.ConstantReserveRatio)), + MaxSupply: d.MaxSupply.String(), + } + case *transaction.CreateMultisigData: + d := data.(*transaction.CreateMultisigData) + weights := make([]string, 0, len(d.Weights)) + for _, weight := range d.Weights { + weights = append(weights, strconv.Itoa(int(weight))) + } + addresses := make([]string, 0, len(d.Addresses)) + for _, address := range d.Addresses { + addresses = append(addresses, address.String()) + } + m = &pb.CreateMultisigData{ + Threshold: strconv.Itoa(int(d.Threshold)), + Weights: weights, + Addresses: addresses, + } + case *transaction.DeclareCandidacyData: + d := data.(*transaction.DeclareCandidacyData) + m = &pb.DeclareCandidacyData{ + Address: d.Address.String(), + PubKey: d.PubKey.String(), + Commission: strconv.Itoa(int(d.Commission)), + Coin: &pb.Coin{ + Id: d.Coin.String(), + Symbol: coins.GetCoin(d.Coin).Symbol().String(), + }, + Stake: d.Stake.String(), + } + case *transaction.DelegateData: + d := data.(*transaction.DelegateData) + m = &pb.DelegateData{ + PubKey: d.PubKey.String(), + Coin: &pb.Coin{ + Id: d.Coin.String(), + Symbol: coins.GetCoin(d.Coin).Symbol().String(), + }, + Value: d.Value.String(), + } + case *transaction.EditCandidateData: + d := data.(*transaction.EditCandidateData) + var newPubKey *wrapperspb.StringValue + if d.NewPubKey != nil { + newPubKey = wrapperspb.String(d.NewPubKey.String()) + } + m = &pb.EditCandidateData{ + PubKey: d.PubKey.String(), + NewPubKey: newPubKey, + RewardAddress: d.RewardAddress.String(), + OwnerAddress: d.OwnerAddress.String(), + ControlAddress: d.ControlAddress.String(), + } + case *transaction.EditMultisigOwnersData: + d := data.(*transaction.EditMultisigOwnersData) + weights := make([]string, 0, len(d.Weights)) + for _, weight := range d.Weights { + weights = append(weights, strconv.Itoa(int(weight))) + } + addresses := make([]string, 0, len(d.Addresses)) + for _, address := range d.Addresses { + addresses = append(addresses, address.String()) + } + m = &pb.EditMultisigOwnersData{ + MultisigAddress: d.MultisigAddress.String(), + Weight: weights, + Addresses: addresses, + } + case *transaction.MultisendData: + d := data.(*transaction.MultisendData) + list := make([]*pb.SendData, 0, len(d.List)) + for _, item := range d.List { + list = append(list, &pb.SendData{ + Coin: &pb.Coin{ + Id: item.Coin.String(), + Symbol: coins.GetCoin(item.Coin).Symbol().String(), + }, + To: item.To.String(), + Value: item.Value.String(), + }) + } + m = &pb.MultiSendData{ + List: list, + } + case *transaction.PriceVoteData: + d := data.(*transaction.PriceVoteData) + m = &pb.PriceVoteData{ + Price: strconv.Itoa(int(d.Price)), + } + case *transaction.RecreateCoinData: + d := data.(*transaction.RecreateCoinData) + m = &pb.RecreateCoinData{ + Symbol: d.Symbol.String(), + InitialAmount: d.InitialAmount.String(), + InitialReserve: d.InitialReserve.String(), + ConstantReserveRatio: strconv.Itoa(int(d.ConstantReserveRatio)), + MaxSupply: d.MaxSupply.String(), + } + case *transaction.RedeemCheckData: + d := data.(*transaction.RedeemCheckData) + m = &pb.RedeemCheckData{ + RawCheck: base64.StdEncoding.EncodeToString(d.RawCheck), + Proof: base64.StdEncoding.EncodeToString(d.Proof[:]), + } + case *transaction.SellAllCoinData: + d := data.(*transaction.SellAllCoinData) + m = &pb.SellAllCoinData{ + CoinToSell: &pb.Coin{ + Id: d.CoinToSell.String(), + Symbol: coins.GetCoin(d.CoinToSell).Symbol().String(), + }, + CoinToBuy: &pb.Coin{ + Id: d.CoinToBuy.String(), + Symbol: coins.GetCoin(d.CoinToBuy).Symbol().String(), + }, + MinimumValueToBuy: d.MinimumValueToBuy.String(), + } + case *transaction.SellCoinData: + d := data.(*transaction.SellCoinData) + m = &pb.SellCoinData{ + CoinToSell: &pb.Coin{ + Id: d.CoinToSell.String(), + Symbol: coins.GetCoin(d.CoinToSell).Symbol().String(), + }, + ValueToSell: d.ValueToSell.String(), + CoinToBuy: &pb.Coin{ + Id: d.CoinToBuy.String(), + Symbol: coins.GetCoin(d.CoinToBuy).Symbol().String(), + }, + MinimumValueToBuy: d.MinimumValueToBuy.String(), + } + case *transaction.SendData: + d := data.(*transaction.SendData) + m = &pb.SendData{ + Coin: &pb.Coin{ + Id: d.Coin.String(), + Symbol: coins.GetCoin(d.Coin).Symbol().String(), + }, + To: d.To.String(), + Value: d.Value.String(), + } + case *transaction.SetHaltBlockData: + d := data.(*transaction.SetHaltBlockData) + m = &pb.SetHaltBlockData{ + PubKey: d.PubKey.String(), + Height: strconv.Itoa(int(d.Height)), + } + case *transaction.SetCandidateOnData: + d := data.(*transaction.SetCandidateOnData) + m = &pb.SetCandidateOnData{ + PubKey: d.PubKey.String(), + } + case *transaction.SetCandidateOffData: + d := data.(*transaction.SetCandidateOffData) + m = &pb.SetCandidateOffData{ + PubKey: d.PubKey.String(), + } + case *transaction.UnbondData: + d := data.(*transaction.UnbondData) + m = &pb.UnbondData{ + PubKey: d.PubKey.String(), + Coin: &pb.Coin{ + Id: d.Coin.String(), + Symbol: coins.GetCoin(d.Coin).Symbol().String(), + }, + Value: d.Value.String(), + } + default: + return nil, errors.New("unknown tx type") + } + + a := &any.Any{} + if err := a.MarshalFrom(m); err != nil { + return nil, err + } + + return a, nil +} diff --git a/api/v2/service/transaction.go b/api/v2/service/transaction.go index 9364fd650..fad90be1d 100644 --- a/api/v2/service/transaction.go +++ b/api/v2/service/transaction.go @@ -5,7 +5,6 @@ import ( "encoding/hex" "fmt" "github.com/MinterTeam/minter-go-node/core/transaction" - "github.com/MinterTeam/minter-go-node/core/transaction/encoder" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" _struct "github.com/golang/protobuf/ptypes/struct" tmbytes "github.com/tendermint/tendermint/libs/bytes" @@ -40,17 +39,11 @@ func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) ( return new(pb.TransactionResponse), status.Error(codes.Internal, err.Error()) } - txJsonEncoder := encoder.NewTxEncoderJSON(cState) - data, err := txJsonEncoder.EncodeData(decodedTx) + dataStruct, err := encode(decodedTx.GetDecodedData(), cState.Coins()) if err != nil { return new(pb.TransactionResponse), status.Error(codes.Internal, err.Error()) } - dataStruct, err := encodeToStruct(data) - if err != nil { - return new(pb.TransactionResponse), status.Error(codes.FailedPrecondition, err.Error()) - } - return &pb.TransactionResponse{ Hash: tmbytes.HexBytes(tx.Tx.Hash()).String(), RawTx: fmt.Sprintf("%x", []byte(tx.Tx)), diff --git a/api/v2/service/transactions.go b/api/v2/service/transactions.go index d8e091156..46fbebe56 100644 --- a/api/v2/service/transactions.go +++ b/api/v2/service/transactions.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "github.com/MinterTeam/minter-go-node/core/transaction" - "github.com/MinterTeam/minter-go-node/core/transaction/encoder" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "github.com/tendermint/tendermint/libs/bytes" "google.golang.org/grpc/codes" @@ -48,17 +47,11 @@ func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) tags[string(tag.Key)] = string(tag.Value) } - txJsonEncoder := encoder.NewTxEncoderJSON(cState) - data, err := txJsonEncoder.Encode(decodedTx, tx) + data, err := encode(decodedTx.GetDecodedData(), cState.Coins()) if err != nil { return new(pb.TransactionsResponse), status.Error(codes.Internal, err.Error()) } - dataStruct, err := encodeToStruct(data) - if err != nil { - return new(pb.TransactionsResponse), status.Error(codes.FailedPrecondition, err.Error()) - } - result = append(result, &pb.TransactionResponse{ Hash: bytes.HexBytes(tx.Tx.Hash()).String(), RawTx: fmt.Sprintf("%x", []byte(tx.Tx)), @@ -70,7 +63,7 @@ func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) GasCoin: decodedTx.GasCoin.String(), Gas: fmt.Sprintf("%d", decodedTx.Gas()), Type: fmt.Sprintf("%d", uint8(decodedTx.Type)), - Data: dataStruct, + Data: data, Payload: decodedTx.Payload, Tags: tags, Code: fmt.Sprintf("%d", tx.TxResult.Code), diff --git a/go.mod b/go.mod index a8ebc1058..179e83a63 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200730101125-365dbd271301 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200812133203-3a59608e4fa5 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index fef645b54..705f22657 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200730101125-365dbd271301 h1:rdhrvUzHSJ90suROMZqLLdM0YoaMcLliAazxmnKi8z0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200730101125-365dbd271301/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200812133203-3a59608e4fa5 h1:mC0P2rZogtGgtjcJwxLGcZ+iZ9hk2jY7eiARq39f4rw= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200812133203-3a59608e4fa5/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 5b1f2d1698ca7a7685dc8dbb87713adcfec345fb Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 13 Aug 2020 11:37:00 +0300 Subject: [PATCH 157/426] fix stake calculation --- core/state/candidates/candidates.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 97163749a..866dc5f76 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -677,22 +677,22 @@ func (c *Candidates) LoadStakes() { } func (c *Candidates) calculateBipValue(coinID types.CoinID, amount *big.Int, includeSelf, includeUpdates bool, coinsCache *coinsCache) *big.Int { - if coinID.IsBaseCoin() { return big.NewInt(0).Set(amount) } - totalDelegatedValue := big.NewInt(0) - if includeSelf { - totalDelegatedValue.Set(amount) - } - coin := c.bus.Coins().GetCoin(coinID) - var saleReturn *big.Int + saleReturn, totalDelegatedValue := big.NewInt(0), big.NewInt(0) if coinsCache.Exists(coinID) { saleReturn, totalDelegatedValue = coinsCache.Get(coinID) - } else { + } + + if includeSelf { + totalDelegatedValue.Set(amount) + } + + if !coinsCache.Exists(coinID) { candidates := c.GetCandidates() for _, candidate := range candidates { for _, stake := range candidate.stakes { @@ -709,6 +709,7 @@ func (c *Candidates) calculateBipValue(coinID types.CoinID, amount *big.Int, inc } } } + nonLockedSupply := big.NewInt(0).Sub(coin.Volume, totalDelegatedValue) saleReturn = formula.CalculateSaleReturn(coin.Volume, coin.Reserve, coin.Crr, nonLockedSupply) coinsCache.Set(coinID, saleReturn, totalDelegatedValue) From fe586a4500df3cf7ee0d00c23f7f236596da61c9 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 13 Aug 2020 11:39:46 +0300 Subject: [PATCH 158/426] fix --- core/state/candidates/candidates.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 866dc5f76..f5b361eeb 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -689,7 +689,7 @@ func (c *Candidates) calculateBipValue(coinID types.CoinID, amount *big.Int, inc } if includeSelf { - totalDelegatedValue.Set(amount) + totalDelegatedValue.Add(totalDelegatedValue, amount) } if !coinsCache.Exists(coinID) { From 612b10c1ea77b4fa15b5dbf78f4d71c3dd68d1cb Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 13 Aug 2020 12:30:06 +0300 Subject: [PATCH 159/426] add custom coin delegation --- core/state/candidates_test.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index d94797b34..096417442 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -6,6 +6,7 @@ import ( eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/state/candidates" "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/helpers" "github.com/tendermint/tendermint/crypto/ed25519" db "github.com/tendermint/tm-db" "math/big" @@ -69,6 +70,38 @@ func TestDelegate(t *testing.T) { } } +func TestCustomDelegate(t *testing.T) { + st := getState() + + volume := helpers.BipToPip(big.NewInt(1000000)) + reserve := helpers.BipToPip(big.NewInt(1000000)) + + coinID := st.App.GetNextCoinID() + st.Coins.Create(coinID, types.StrToCoinSymbol("TEST"), "TEST COIN", volume, 10, reserve, volume, nil) + st.App.SetCoinsCount(coinID.Uint32()) + + address := types.Address{} + amount := helpers.BipToPip(big.NewInt(500000)) + pubkey := createTestCandidate(st) + + st.Candidates.Delegate(address, pubkey, coinID, amount, big.NewInt(0)) + st.Candidates.RecalculateStakes(height) + + stake := st.Candidates.GetStakeOfAddress(pubkey, address, coinID) + if stake == nil { + t.Fatalf("Stake of address %s not found", address.String()) + } + + if stake.Value.Cmp(amount) != 0 { + t.Errorf("Stake of address %s should be %s, got %s", address.String(), amount.String(), stake.Value.String()) + } + + bipValue := big.NewInt(0).Mul(big.NewInt(9765625), big.NewInt(100000000000000)) + if stake.BipValue.Cmp(bipValue) != 0 { + t.Errorf("Bip value of stake of address %s should be %s, got %s", address.String(), bipValue.String(), stake.BipValue.String()) + } +} + func TestComplexDelegate(t *testing.T) { st := getState() From 9ecfd29236a6217368e1e49133aa0cd0e5f7e8aa Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 13 Aug 2020 13:23:37 +0300 Subject: [PATCH 160/426] unmarshal coin id --- core/types/types.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/types/types.go b/core/types/types.go index 43d9944f4..a04efe7f3 100644 --- a/core/types/types.go +++ b/core/types/types.go @@ -187,6 +187,12 @@ func (c CoinID) Uint32() uint32 { return uint32(c) } +// UnmarshalJSON parses a hash in hex syntax. +func (a *CoinID) UnmarshalJSON(input []byte) error { + *a = BytesToCoinID(input) + return nil +} + func BytesToCoinID(bytes []byte) CoinID { return CoinID(binary.LittleEndian.Uint32(bytes)) } From ff47a6d979fbbb63259acc0daba16f336ef3f64a Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 13 Aug 2020 14:28:32 +0300 Subject: [PATCH 161/426] update gateway --- api/v2/service/data_encoder.go | 5 +- api/v2/service/transaction.go | 6 ++ api/v2/service/waitlist.go | 61 ++++++++++++++ core/minter/minter_test.go | 147 +++++++++++++++++++++++++++++++++ core/state/candidates_test.go | 21 +++++ go.mod | 2 +- go.sum | 4 +- 7 files changed, 241 insertions(+), 5 deletions(-) create mode 100644 api/v2/service/waitlist.go diff --git a/api/v2/service/data_encoder.go b/api/v2/service/data_encoder.go index 623931101..e66a4bdd0 100644 --- a/api/v2/service/data_encoder.go +++ b/api/v2/service/data_encoder.go @@ -8,6 +8,7 @@ import ( pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "github.com/golang/protobuf/ptypes/any" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/wrapperspb" "strconv" ) @@ -213,8 +214,8 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { return nil, errors.New("unknown tx type") } - a := &any.Any{} - if err := a.MarshalFrom(m); err != nil { + a, err := anypb.New(m) + if err != nil { return nil, err } diff --git a/api/v2/service/transaction.go b/api/v2/service/transaction.go index fad90be1d..98363a103 100644 --- a/api/v2/service/transaction.go +++ b/api/v2/service/transaction.go @@ -39,6 +39,12 @@ func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) ( return new(pb.TransactionResponse), status.Error(codes.Internal, err.Error()) } + cState.RLock() + defer cState.RUnlock() + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.TransactionResponse), timeoutStatus.Err() + } dataStruct, err := encode(decodedTx.GetDecodedData(), cState.Coins()) if err != nil { return new(pb.TransactionResponse), status.Error(codes.Internal, err.Error()) diff --git a/api/v2/service/waitlist.go b/api/v2/service/waitlist.go new file mode 100644 index 000000000..00da30e74 --- /dev/null +++ b/api/v2/service/waitlist.go @@ -0,0 +1,61 @@ +package service + +import ( + "context" + "encoding/hex" + "github.com/MinterTeam/minter-go-node/core/types" + pb "github.com/MinterTeam/node-grpc-gateway/api_pb" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "strings" +) + +func (s *Service) WaitList(ctx context.Context, req *pb.WaitListRequest) (*pb.WaitListResponse, error) { + if !strings.HasPrefix(strings.Title(req.Address), "Mx") { + return new(pb.WaitListResponse), status.Error(codes.InvalidArgument, "invalid address") + } + + decodeString, err := hex.DecodeString(req.Address[2:]) + if err != nil { + return new(pb.WaitListResponse), status.Error(codes.InvalidArgument, "invalid address") + } + + address := types.BytesToAddress(decodeString) + + if !strings.HasPrefix(req.PublicKey, "Mp") { + return new(pb.WaitListResponse), status.Error(codes.InvalidArgument, "public key don't has prefix 'Mp'") + } + + publickKey := types.HexToPubkey(req.PublicKey) + + cState, err := s.blockchain.GetStateForHeight(req.Height) + if err != nil { + return nil, err + } + + cState.RLock() + defer cState.RUnlock() + + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.WaitListResponse), timeoutStatus.Err() + } + + response := new(pb.WaitListResponse) + items := cState.Watchlist().GetByAddressAndPubKey(address, publickKey) + response.List = make([]*pb.WaitListResponse_Wait, 0, len(items)) + for _, item := range items { + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.WaitListResponse), timeoutStatus.Err() + } + + response.List = append(response.List, &pb.WaitListResponse_Wait{ + Coin: &pb.Coin{ + Id: item.Coin.String(), + Symbol: cState.Coins().GetCoin(item.Coin).CSymbol.String(), + }, + Value: item.Value.String(), + }) + } + + return response, nil +} diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index 1014d1810..8d646f4fe 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -423,6 +423,153 @@ func TestStopNetworkByHaltBlocks(t *testing.T) { } } +func TestRecalculateStakes(t *testing.T) { + for blockchain.Height() < 2 { + time.Sleep(time.Millisecond) + } + + symbol := types.StrToCoinSymbol("AAA123") + data := transaction.CreateCoinData{ + Name: "nAAA123", + Symbol: symbol, + InitialAmount: helpers.BipToPip(big.NewInt(1000000)), + InitialReserve: helpers.BipToPip(big.NewInt(10000)), + ConstantReserveRatio: 70, + MaxSupply: big.NewInt(0).Exp(big.NewInt(10), big.NewInt(15+18), nil), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := transaction.Transaction{ + Nonce: nonce, + ChainID: types.CurrentChainID, + GasPrice: 1, + GasCoin: types.GetBaseCoinID(), + Type: transaction.TypeCreateCoin, + Data: encodedData, + SignatureType: transaction.SigTypeSingle, + } + nonce++ + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + txBytes, _ := tx.Serialize() + res, err := tmCli.BroadcastTxSync(txBytes) + if err != nil { + t.Fatalf("Failed: %s", err.Error()) + } + if res.Code != 0 { + t.Fatalf("CheckTx code is not 0: %d", res.Code) + } + + time.Sleep(time.Second) + + coinID := blockchain.stateCheck.Coins().GetCoinBySymbol(symbol, 0).ID() + buyCoinData := transaction.BuyCoinData{ + CoinToBuy: coinID, + ValueToBuy: helpers.BipToPip(big.NewInt(10000000)), + CoinToSell: 0, + MaximumValueToSell: helpers.BipToPip(big.NewInt(10000000000000000)), + } + + encodedData, err = rlp.EncodeToBytes(buyCoinData) + if err != nil { + t.Fatal(err) + } + + tx = transaction.Transaction{ + Nonce: nonce, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: transaction.TypeBuyCoin, + Data: encodedData, + SignatureType: transaction.SigTypeSingle, + } + nonce++ + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + txBytes, _ = tx.Serialize() + res, err = tmCli.BroadcastTxSync(txBytes) + if err != nil { + t.Fatalf("Failed: %s", err.Error()) + } + if res.Code != 0 { + t.Fatalf("CheckTx code is not 0: %d", res.Code) + } + + time.Sleep(time.Second) + + delegateData := transaction.DelegateData{ + PubKey: blockchain.stateCheck.Candidates().GetCandidates()[0].PubKey, + Coin: coinID, + Value: helpers.BipToPip(big.NewInt(9000000)), + } + + encodedData, err = rlp.EncodeToBytes(delegateData) + if err != nil { + t.Fatal(err) + } + + tx = transaction.Transaction{ + Nonce: nonce, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: transaction.TypeDelegate, + Data: encodedData, + SignatureType: transaction.SigTypeSingle, + } + nonce++ + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + txBytes, _ = tx.Serialize() + res, err = tmCli.BroadcastTxSync(txBytes) + if err != nil { + t.Fatalf("Failed: %s", err.Error()) + } + if res.Code != 0 { + t.Fatalf("CheckTx code is not 0: %d", res.Code) + } + + time.Sleep(time.Second) + + blocks, err := tmCli.Subscribe(context.TODO(), "test-client", "tm.event = 'NewBlock'") + if err != nil { + panic(err) + } + + defer func() { + err = tmCli.UnsubscribeAll(context.TODO(), "test-client") + if err != nil { + panic(err) + } + }() + for { + select { + case block := <-blocks: + if block.Data.(types2.EventDataNewBlock).Block.Height < 150 { + continue + } + + return + case <-time.After(10 * time.Second): + t.Fatalf("Timeout waiting for the block") + } + } +} + func getGenesis() (*types2.GenesisDoc, error) { appHash := [32]byte{} diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index d94797b34..adbbc70e8 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -6,6 +6,7 @@ import ( eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/state/candidates" "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/helpers" "github.com/tendermint/tendermint/crypto/ed25519" db "github.com/tendermint/tm-db" "math/big" @@ -457,6 +458,26 @@ func TestStakeKick(t *testing.T) { } } +func TestRecalculateStakes(t *testing.T) { + st := getState() + + st.Coins.Create(1, [10]byte{1}, "TestCoin", helpers.BipToPip(big.NewInt(100000)), 70, helpers.BipToPip(big.NewInt(10000)), nil, nil) + pubkey := createTestCandidate(st) + + amount := helpers.BipToPip(big.NewInt(1000)) + st.Candidates.Delegate([20]byte{1}, pubkey, 1, amount, big.NewInt(0)) + + st.Candidates.RecalculateStakes(height) + err := st.Candidates.Commit() + if err != nil { + t.Fatal(err) + } + stake := st.Candidates.GetStakeOfAddress(pubkey, [20]byte{1}, 1) + + t.Log(stake.Value.String()) + t.Log(stake.BipValue.String()) +} + func getState() *State { s, err := NewState(0, db.NewMemDB(), emptyEvents{}, 1, 1) diff --git a/go.mod b/go.mod index 179e83a63..844fd59e9 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200812133203-3a59608e4fa5 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200813111959-9b43734535eb github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 705f22657..5f01ff7f4 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200812133203-3a59608e4fa5 h1:mC0P2rZogtGgtjcJwxLGcZ+iZ9hk2jY7eiARq39f4rw= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200812133203-3a59608e4fa5/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200813111959-9b43734535eb h1:BO6caE+wn77Rnthv2cIyEZovwv/Ee7OTjcK7HehX8jI= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200813111959-9b43734535eb/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 20263572e6cf8732e9ccf8706822828110b4252c Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 13 Aug 2020 14:54:26 +0300 Subject: [PATCH 162/426] fix --- core/types/types.go | 6 ------ core/types/types_test.go | 1 + 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/core/types/types.go b/core/types/types.go index a04efe7f3..43d9944f4 100644 --- a/core/types/types.go +++ b/core/types/types.go @@ -187,12 +187,6 @@ func (c CoinID) Uint32() uint32 { return uint32(c) } -// UnmarshalJSON parses a hash in hex syntax. -func (a *CoinID) UnmarshalJSON(input []byte) error { - *a = BytesToCoinID(input) - return nil -} - func BytesToCoinID(bytes []byte) CoinID { return CoinID(binary.LittleEndian.Uint32(bytes)) } diff --git a/core/types/types_test.go b/core/types/types_test.go index 7fec5dd93..a743d6b18 100644 --- a/core/types/types_test.go +++ b/core/types/types_test.go @@ -180,6 +180,7 @@ func TestAppState(t *testing.T) { }, Coins: []Coin{ { + ID: GetBaseCoinID(), Name: "ASD", Symbol: GetBaseCoin(), Volume: big.NewInt(1).String(), From 36eb377bbff605a43b05e0a57e7b217f20da69f0 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 13 Aug 2020 17:06:02 +0300 Subject: [PATCH 163/426] refactor --- core/state/state.go | 6 +++++- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/core/state/state.go b/core/state/state.go index 5d83b06dd..ee359424a 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -47,6 +47,10 @@ func (cs *CheckState) Lock() { cs.state.lock.Lock() } +func (cs *CheckState) Export(height uint64) types.AppState { + return cs.state.Export(height) +} + func (cs *CheckState) Unlock() { cs.state.lock.Unlock() } @@ -181,7 +185,7 @@ func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, func NewCheckStateAtHeight(height uint64, db db.DB) (*CheckState, error) { iavlTree := tree.NewImmutableTree(height, db) - return newCheckStateForTree(iavlTree, nil, nil, 0) + return newCheckStateForTree(iavlTree, nil, db, 0) } func (s *State) Tree() tree.MTree { diff --git a/go.mod b/go.mod index 844fd59e9..d0e4ed5fe 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d github.com/tendermint/go-amino v0.15.1 github.com/tendermint/iavl v0.14.0 - github.com/tendermint/tendermint v0.33.6 + github.com/tendermint/tendermint v0.33.8 github.com/tendermint/tm-db v0.5.1 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 github.com/urfave/cli/v2 v2.0.0 diff --git a/go.sum b/go.sum index 5f01ff7f4..138d21210 100644 --- a/go.sum +++ b/go.sum @@ -467,8 +467,8 @@ github.com/tendermint/iavl v0.14.0 h1:Jkff+IFrXxRWtH9Jn/ga/2cxNnzMTv58xEKgCJsKUB github.com/tendermint/iavl v0.14.0/go.mod h1:QmfViflFiXzxKLQE4tAUuWQHq+RSuQFxablW5oJZ6sE= github.com/tendermint/tendermint v0.33.5 h1:jYgRd9ImkzA9iOyhpmgreYsqSB6tpDa6/rXYPb8HKE8= github.com/tendermint/tendermint v0.33.5/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM= -github.com/tendermint/tendermint v0.33.6 h1:W4UOsXY4ROJZ3TLLGVVv71VXD4WK2gJRb3gzeced+mg= -github.com/tendermint/tendermint v0.33.6/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM= +github.com/tendermint/tendermint v0.33.8 h1:Xxu4QhpqcomSE0iQDw1MqLgfsa8fqtPtWFJK6zZOVso= +github.com/tendermint/tendermint v0.33.8/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM= github.com/tendermint/tm-db v0.5.1 h1:H9HDq8UEA7Eeg13kdYckkgwwkQLBnJGgX4PgLJRhieY= github.com/tendermint/tm-db v0.5.1/go.mod h1:g92zWjHpCYlEvQXvy9M168Su8V1IBEeawpXVVBaK4f4= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= From 58fc6b671d644484ce9411a15d87ced4240a898c Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Mon, 17 Aug 2020 10:33:01 +0300 Subject: [PATCH 164/426] remove coins count from genesis --- core/state/legacy/coins/coins.go | 1 - core/state/state.go | 2 +- core/types/appstate.go | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/core/state/legacy/coins/coins.go b/core/state/legacy/coins/coins.go index 729ac3b15..e3fe6b590 100644 --- a/core/state/legacy/coins/coins.go +++ b/core/state/legacy/coins/coins.go @@ -142,7 +142,6 @@ func (c *Coins) Export(state *types.AppState) map[types.CoinSymbol]types.Coin { } state.Coins = coins - state.CoinsCount = uint32(len(state.Coins)) return coinsMap } diff --git a/core/state/state.go b/core/state/state.go index ee359424a..f70cd960d 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -285,7 +285,7 @@ func (s *State) Commit() ([]byte, error) { func (s *State) Import(state types.AppState) error { s.App.SetMaxGas(state.MaxGas) s.App.SetTotalSlashed(helpers.StringToBigInt(state.TotalSlashed)) - s.App.SetCoinsCount(state.CoinsCount) + s.App.SetCoinsCount(uint32(len(state.Coins))) for _, a := range state.Accounts { if a.MultisigData != nil { diff --git a/core/types/appstate.go b/core/types/appstate.go index 36309c484..a1e21dafe 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -20,7 +20,6 @@ type AppState struct { UsedChecks []UsedCheck `json:"used_checks,omitempty"` MaxGas uint64 `json:"max_gas"` TotalSlashed string `json:"total_slashed"` - CoinsCount uint32 `json:"coins_count"` } func (s *AppState) Verify() error { From 98fa2a994f9303fe69783ac0b5cfcc6c8666fea4 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 18 Aug 2020 01:28:35 +0300 Subject: [PATCH 165/426] update gateway --- api/v2/service/address.go | 2 +- api/v2/service/addresses.go | 2 +- api/v2/service/block.go | 8 ++++---- api/v2/service/unconfirmed_txs.go | 2 +- go.mod | 2 +- go.sum | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/api/v2/service/address.go b/api/v2/service/address.go index 78f68f235..c0ec81cdf 100644 --- a/api/v2/service/address.go +++ b/api/v2/service/address.go @@ -133,7 +133,7 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr coinsBipValue.Add(coinsBipValue, balance) } res.BipValue = coinsBipValue.String() - res.TransactionsCount = fmt.Sprintf("%d", cState.Accounts().GetNonce(address)) + res.TransactionCount = fmt.Sprintf("%d", cState.Accounts().GetNonce(address)) return &res, nil } diff --git a/api/v2/service/addresses.go b/api/v2/service/addresses.go index ed4814ac9..ca2acd95e 100644 --- a/api/v2/service/addresses.go +++ b/api/v2/service/addresses.go @@ -134,7 +134,7 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. coinsBipValue.Add(coinsBipValue, balance) } res.BipValue = coinsBipValue.String() - res.TransactionsCount = fmt.Sprintf("%d", cState.Accounts().GetNonce(address)) + res.TransactionCount = fmt.Sprintf("%d", cState.Accounts().GetNonce(address)) response.Addresses[addr] = &res } diff --git a/api/v2/service/block.go b/api/v2/service/block.go index abaa08032..776b92559 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -36,10 +36,10 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes } response := &pb.BlockResponse{ - Hash: hex.EncodeToString(block.Block.Hash()), - Height: fmt.Sprintf("%d", block.Block.Height), - Time: block.Block.Time.Format(time.RFC3339Nano), - TransactionsCount: fmt.Sprintf("%d", len(block.Block.Txs)), + Hash: hex.EncodeToString(block.Block.Hash()), + Height: fmt.Sprintf("%d", block.Block.Height), + Time: block.Block.Time.Format(time.RFC3339Nano), + TransactionCount: fmt.Sprintf("%d", len(block.Block.Txs)), } var totalValidators []*tmTypes.Validator diff --git a/api/v2/service/unconfirmed_txs.go b/api/v2/service/unconfirmed_txs.go index 666430715..93d25d2c0 100644 --- a/api/v2/service/unconfirmed_txs.go +++ b/api/v2/service/unconfirmed_txs.go @@ -14,7 +14,7 @@ func (s *Service) UnconfirmedTxs(ctx context.Context, req *pb.UnconfirmedTxsRequ return new(pb.UnconfirmedTxsResponse), status.Error(codes.Internal, err.Error()) } return &pb.UnconfirmedTxsResponse{ - TransactionsCount: fmt.Sprintf("%d", txs.Count), + TransactionCount: fmt.Sprintf("%d", txs.Count), TotalTransactions: fmt.Sprintf("%d", txs.Total), TotalBytes: fmt.Sprintf("%d", txs.TotalBytes), }, nil diff --git a/go.mod b/go.mod index d0e4ed5fe..c0b52bd60 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200813111959-9b43734535eb + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200817221822-398a8a87d81e github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 138d21210..6bdab14a9 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200813111959-9b43734535eb h1:BO6caE+wn77Rnthv2cIyEZovwv/Ee7OTjcK7HehX8jI= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200813111959-9b43734535eb/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200817221822-398a8a87d81e h1:9Pw3k7RUWSIxnrs7EfCxQEw87pcjW+bhTysnP7h9zfY= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200817221822-398a8a87d81e/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From b9ba6cccda29a94784e86b7a54e172be4db4f916 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 18 Aug 2020 09:15:58 +0300 Subject: [PATCH 166/426] MN-497: change coin owner data --- api/v2/service/data_encoder.go | 4 ++-- .../{change_owner.go => change_coin_owner.go} | 10 +++++----- ...{change_owner_test.go => change_coin_owner_test.go} | 8 ++++---- core/transaction/decoder.go | 2 +- core/transaction/encoder/encoder.go | 2 +- core/transaction/encoder/resources.go | 8 ++++---- 6 files changed, 17 insertions(+), 17 deletions(-) rename core/transaction/{change_owner.go => change_coin_owner.go} (90%) rename core/transaction/{change_owner_test.go => change_coin_owner_test.go} (95%) diff --git a/api/v2/service/data_encoder.go b/api/v2/service/data_encoder.go index e66a4bdd0..feef2ce91 100644 --- a/api/v2/service/data_encoder.go +++ b/api/v2/service/data_encoder.go @@ -30,8 +30,8 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { }, MaximumValueToSell: d.MaximumValueToSell.String(), } - case *transaction.ChangeOwnerData: - d := data.(*transaction.ChangeOwnerData) + case *transaction.ChangeCoinOwnerData: + d := data.(*transaction.ChangeCoinOwnerData) m = &pb.ChangeOwnerData{ Symbol: d.Symbol.String(), NewOwner: d.NewOwner.String(), diff --git a/core/transaction/change_owner.go b/core/transaction/change_coin_owner.go similarity index 90% rename from core/transaction/change_owner.go rename to core/transaction/change_coin_owner.go index f7cd67ad3..64bf5fd93 100644 --- a/core/transaction/change_owner.go +++ b/core/transaction/change_coin_owner.go @@ -12,12 +12,12 @@ import ( "math/big" ) -type ChangeOwnerData struct { +type ChangeCoinOwnerData struct { Symbol types.CoinSymbol NewOwner types.Address } -func (data ChangeOwnerData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { +func (data ChangeCoinOwnerData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { sender, _ := tx.Sender() info := context.Coins().GetSymbolInfo(data.Symbol) @@ -38,15 +38,15 @@ func (data ChangeOwnerData) BasicCheck(tx *Transaction, context *state.CheckStat return nil } -func (data ChangeOwnerData) String() string { +func (data ChangeCoinOwnerData) String() string { return fmt.Sprintf("CHANGE OWNER COIN symbol:%s new owner:%s", data.Symbol.String(), data.NewOwner.String()) } -func (data ChangeOwnerData) Gas() int64 { +func (data ChangeCoinOwnerData) Gas() int64 { return commissions.ChangeOwner } -func (data ChangeOwnerData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { +func (data ChangeCoinOwnerData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { sender, _ := tx.Sender() var checkState *state.CheckState diff --git a/core/transaction/change_owner_test.go b/core/transaction/change_coin_owner_test.go similarity index 95% rename from core/transaction/change_owner_test.go rename to core/transaction/change_coin_owner_test.go index 6dc50071e..af3c60fc9 100644 --- a/core/transaction/change_owner_test.go +++ b/core/transaction/change_coin_owner_test.go @@ -32,7 +32,7 @@ func TestChangeOwnerTx(t *testing.T) { gasCoin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, gasCoin, helpers.BipToPip(big.NewInt(10000))) - data := ChangeOwnerData{ + data := ChangeCoinOwnerData{ Symbol: getTestCoinSymbol(), NewOwner: newOwner, } @@ -81,7 +81,7 @@ func TestChangeOwnerTxWithWrongOwner(t *testing.T) { createTestCoinWithOwner(cState, newOwner) - data := ChangeOwnerData{ + data := ChangeCoinOwnerData{ Symbol: getTestCoinSymbol(), NewOwner: newOwner, } @@ -111,7 +111,7 @@ func TestChangeOwnerTxWithWrongSymbol(t *testing.T) { createTestCoinWithOwner(cState, addr) - data := ChangeOwnerData{ + data := ChangeCoinOwnerData{ Symbol: types.StrToCoinSymbol("UNKNOWN"), NewOwner: newOwner, } @@ -127,7 +127,7 @@ func TestChangeOwnerTxWithWrongSymbol(t *testing.T) { } } -func makeTestChangeOwnerTx(data ChangeOwnerData, privateKey *ecdsa.PrivateKey) ([]byte, error) { +func makeTestChangeOwnerTx(data ChangeCoinOwnerData, privateKey *ecdsa.PrivateKey) ([]byte, error) { encodedData, err := rlp.EncodeToBytes(data) if err != nil { return nil, err diff --git a/core/transaction/decoder.go b/core/transaction/decoder.go index 276470492..6f4b72e1e 100644 --- a/core/transaction/decoder.go +++ b/core/transaction/decoder.go @@ -28,7 +28,7 @@ func init() { TxDecoder.RegisterType(TypeEditCandidate, EditCandidateData{}) TxDecoder.RegisterType(TypeSetHaltBlock, SetHaltBlockData{}) TxDecoder.RegisterType(TypeRecreateCoin, RecreateCoinData{}) - TxDecoder.RegisterType(TypeChangeOwner, ChangeOwnerData{}) + TxDecoder.RegisterType(TypeChangeOwner, ChangeCoinOwnerData{}) TxDecoder.RegisterType(TypeEditMultisigOwner, EditMultisigOwnersData{}) TxDecoder.RegisterType(TypePriceVote, PriceVoteData{}) } diff --git a/core/transaction/encoder/encoder.go b/core/transaction/encoder/encoder.go index 2048f144e..f4d94037f 100644 --- a/core/transaction/encoder/encoder.go +++ b/core/transaction/encoder/encoder.go @@ -49,7 +49,7 @@ var resourcesConfig = map[transaction.TxType]TxDataResource{ transaction.TypeEditCandidate: new(EditCandidateDataResource), transaction.TypeSetHaltBlock: new(SetHaltBlockDataResource), transaction.TypeRecreateCoin: new(RecreateCoinDataResource), - transaction.TypeChangeOwner: new(ChangeOwnerDataResource), + transaction.TypeChangeOwner: new(ChangeCoinOwnerDataResource), transaction.TypeEditMultisigOwner: new(EditMultisigOwnersResource), transaction.TypePriceVote: new(PriceVoteResource), } diff --git a/core/transaction/encoder/resources.go b/core/transaction/encoder/resources.go index e103abbf7..52ec68280 100644 --- a/core/transaction/encoder/resources.go +++ b/core/transaction/encoder/resources.go @@ -334,15 +334,15 @@ func (RecreateCoinDataResource) Transform(txData interface{}, context *state.Che // TxType 0x11 -type ChangeOwnerDataResource struct { +type ChangeCoinOwnerDataResource struct { Symbol types.CoinSymbol `json:"symbol"` NewOwner types.Address `json:"new_owner"` } -func (ChangeOwnerDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { - data := txData.(*transaction.ChangeOwnerData) +func (ChangeCoinOwnerDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { + data := txData.(*transaction.ChangeCoinOwnerData) - return ChangeOwnerDataResource{ + return ChangeCoinOwnerDataResource{ Symbol: data.Symbol, NewOwner: data.NewOwner, } From 153b0fcdeb4a20cdea770e47dc5897bb8a2e8942 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 18 Aug 2020 09:18:29 +0300 Subject: [PATCH 167/426] MN-497: rename change coin owner --- core/transaction/change_coin_owner.go | 2 +- core/transaction/change_coin_owner_test.go | 2 +- core/transaction/decoder.go | 2 +- core/transaction/encoder/encoder.go | 2 +- core/transaction/executor.go | 2 +- core/transaction/transaction.go | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/transaction/change_coin_owner.go b/core/transaction/change_coin_owner.go index 64bf5fd93..de3eb1bfe 100644 --- a/core/transaction/change_coin_owner.go +++ b/core/transaction/change_coin_owner.go @@ -110,7 +110,7 @@ func (data ChangeCoinOwnerData) Run(tx *Transaction, context state.Interface, re } tags := kv.Pairs{ - kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeChangeOwner)}))}, + kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeChangeCoinOwner)}))}, kv.Pair{Key: []byte("tx.from"), Value: []byte(hex.EncodeToString(sender[:]))}, kv.Pair{Key: []byte("tx.coin"), Value: []byte(data.Symbol.String())}, } diff --git a/core/transaction/change_coin_owner_test.go b/core/transaction/change_coin_owner_test.go index af3c60fc9..30b7a4eb9 100644 --- a/core/transaction/change_coin_owner_test.go +++ b/core/transaction/change_coin_owner_test.go @@ -138,7 +138,7 @@ func makeTestChangeOwnerTx(data ChangeCoinOwnerData, privateKey *ecdsa.PrivateKe GasPrice: 1, ChainID: types.CurrentChainID, GasCoin: types.GetBaseCoinID(), - Type: TypeChangeOwner, + Type: TypeChangeCoinOwner, Data: encodedData, SignatureType: SigTypeSingle, } diff --git a/core/transaction/decoder.go b/core/transaction/decoder.go index 6f4b72e1e..81bdecb22 100644 --- a/core/transaction/decoder.go +++ b/core/transaction/decoder.go @@ -28,7 +28,7 @@ func init() { TxDecoder.RegisterType(TypeEditCandidate, EditCandidateData{}) TxDecoder.RegisterType(TypeSetHaltBlock, SetHaltBlockData{}) TxDecoder.RegisterType(TypeRecreateCoin, RecreateCoinData{}) - TxDecoder.RegisterType(TypeChangeOwner, ChangeCoinOwnerData{}) + TxDecoder.RegisterType(TypeChangeCoinOwner, ChangeCoinOwnerData{}) TxDecoder.RegisterType(TypeEditMultisigOwner, EditMultisigOwnersData{}) TxDecoder.RegisterType(TypePriceVote, PriceVoteData{}) } diff --git a/core/transaction/encoder/encoder.go b/core/transaction/encoder/encoder.go index f4d94037f..e6ed7f991 100644 --- a/core/transaction/encoder/encoder.go +++ b/core/transaction/encoder/encoder.go @@ -49,7 +49,7 @@ var resourcesConfig = map[transaction.TxType]TxDataResource{ transaction.TypeEditCandidate: new(EditCandidateDataResource), transaction.TypeSetHaltBlock: new(SetHaltBlockDataResource), transaction.TypeRecreateCoin: new(RecreateCoinDataResource), - transaction.TypeChangeOwner: new(ChangeCoinOwnerDataResource), + transaction.TypeChangeCoinOwner: new(ChangeCoinOwnerDataResource), transaction.TypeEditMultisigOwner: new(EditMultisigOwnersResource), transaction.TypePriceVote: new(PriceVoteResource), } diff --git a/core/transaction/executor.go b/core/transaction/executor.go index 81330a633..e99444b36 100644 --- a/core/transaction/executor.go +++ b/core/transaction/executor.go @@ -227,7 +227,7 @@ func RunTx(context state.Interface, response.GasWanted = coinGas } - if tx.Type == TypeChangeOwner { + if tx.Type == TypeChangeCoinOwner { response.GasUsed = coinGas response.GasWanted = coinGas } diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index b008d5370..f35f551dc 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -35,7 +35,7 @@ const ( TypeEditCandidate TxType = 0x0E TypeSetHaltBlock TxType = 0x0F TypeRecreateCoin TxType = 0x10 - TypeChangeOwner TxType = 0x11 + TypeChangeCoinOwner TxType = 0x11 TypeEditMultisigOwner TxType = 0x12 TypePriceVote TxType = 0x13 From 9883b0d87d19953832fd9366321e97918f501d5a Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 18 Aug 2020 13:53:37 +0300 Subject: [PATCH 168/426] fixes --- api/v2/service/data_encoder.go | 5 +- core/state/accounts/accounts.go | 4 +- core/transaction/create_multisig.go | 6 +-- core/transaction/edit_multisig_owners.go | 69 +++++++++++++++++++++++- core/transaction/encoder/resources.go | 9 ++-- go.mod | 2 +- go.sum | 4 +- 7 files changed, 85 insertions(+), 14 deletions(-) diff --git a/api/v2/service/data_encoder.go b/api/v2/service/data_encoder.go index e66a4bdd0..eb8d6d7c0 100644 --- a/api/v2/service/data_encoder.go +++ b/api/v2/service/data_encoder.go @@ -32,7 +32,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { } case *transaction.ChangeOwnerData: d := data.(*transaction.ChangeOwnerData) - m = &pb.ChangeOwnerData{ + m = &pb.ChangeCoinOwnerData{ Symbol: d.Symbol.String(), NewOwner: d.NewOwner.String(), } @@ -108,7 +108,8 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { } m = &pb.EditMultisigOwnersData{ MultisigAddress: d.MultisigAddress.String(), - Weight: weights, + Threshold: strconv.Itoa(int(d.Threshold)), + Weights: weights, Addresses: addresses, } case *transaction.MultisendData: diff --git a/core/state/accounts/accounts.go b/core/state/accounts/accounts.go index 196d04904..ed2c68212 100644 --- a/core/state/accounts/accounts.go +++ b/core/state/accounts/accounts.go @@ -219,11 +219,11 @@ func (a *Accounts) CreateMultisig(weights []uint, addresses []types.Address, thr return address } -func (a *Accounts) EditMultisig(weights []uint, addresses []types.Address, address types.Address) types.Address { +func (a *Accounts) EditMultisig(threshold uint, weights []uint, addresses []types.Address, address types.Address) types.Address { account := a.get(address) msig := Multisig{ - Threshold: account.Multisig().Threshold, + Threshold: threshold, Weights: weights, Addresses: addresses, } diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index 1dfc56b68..10e48087c 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -24,7 +24,7 @@ func (data CreateMultisigData) BasicCheck(tx *Transaction, context *state.CheckS if lenWeights > 32 { return &Response{ Code: code.TooLargeOwnersList, - Log: fmt.Sprintf("Owners list is limited to 32 items")} + Log: "Owners list is limited to 32 items"} } lenAddresses := len(data.Addresses) @@ -43,7 +43,7 @@ func (data CreateMultisigData) BasicCheck(tx *Transaction, context *state.CheckS if weight > 1023 { return &Response{ Code: code.IncorrectWeights, - Log: fmt.Sprintf("Incorrect multisig weights")} + Log: "Incorrect multisig weights"} } } @@ -52,7 +52,7 @@ func (data CreateMultisigData) BasicCheck(tx *Transaction, context *state.CheckS if usedAddresses[address] { return &Response{ Code: code.DuplicatedAddresses, - Log: fmt.Sprintf("Duplicated multisig addresses")} + Log: "Duplicated multisig addresses"} } usedAddresses[address] = true diff --git a/core/transaction/edit_multisig_owners.go b/core/transaction/edit_multisig_owners.go index 1e1cafcb2..95e1b5bab 100644 --- a/core/transaction/edit_multisig_owners.go +++ b/core/transaction/edit_multisig_owners.go @@ -14,11 +14,25 @@ import ( type EditMultisigOwnersData struct { MultisigAddress types.Address + Threshold uint Weights []uint Addresses []types.Address } func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { + sender, _ := tx.Sender() + + if sender != data.MultisigAddress { + return &Response{ + Code: code.IncorrectMultiSignature, + Log: "Sender is not multisig adress", + Info: EncodeError(map[string]string{ + "multisig_address": data.MultisigAddress.String(), + "sender": sender.String(), + }), + } + } + if !context.Accounts().GetAccount(data.MultisigAddress).IsMultisig() { return &Response{ Code: code.MultisigNotExists, @@ -29,6 +43,59 @@ func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.Ch } } + lenWeights := len(data.Weights) + if lenWeights > 32 { + return &Response{ + Code: code.TooLargeOwnersList, + Log: fmt.Sprintf("Owners list is limited to 32 items")} + } + + lenAddresses := len(data.Addresses) + if lenAddresses != lenWeights { + return &Response{ + Code: code.IncorrectWeights, + Log: fmt.Sprintf("Incorrect multisig weights"), + Info: EncodeError(map[string]string{ + "count_weights": fmt.Sprintf("%d", lenWeights), + "count_addresses": fmt.Sprintf("%d", lenAddresses), + }), + } + } + + for _, weight := range data.Weights { + if weight > 1023 { + return &Response{ + Code: code.IncorrectWeights, + Log: "Incorrect multisig weights"} + } + } + + usedAddresses := map[types.Address]bool{} + for _, address := range data.Addresses { + if usedAddresses[address] { + return &Response{ + Code: code.DuplicatedAddresses, + Log: fmt.Sprintf("Duplicated multisig addresses")} + } + + usedAddresses[address] = true + } + + var totalWeight uint + for _, weight := range data.Weights { + totalWeight += weight + } + if data.Threshold > totalWeight { + return &Response{ + Code: code.IncorrectWeights, + Log: "Incorrect multisig weights", + Info: EncodeError(map[string]string{ + "total_weight": fmt.Sprintf("%d", totalWeight), + "threshold": fmt.Sprintf("%d", data.Threshold), + }), + } + } + return nil } @@ -101,7 +168,7 @@ func (data EditMultisigOwnersData) Run(tx *Transaction, context state.Interface, deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) deliverState.Accounts.SetNonce(sender, tx.Nonce) - deliverState.Accounts.EditMultisig(data.Weights, data.Addresses, sender) + deliverState.Accounts.EditMultisig(data.Threshold, data.Weights, data.Addresses, sender) } address := []byte(hex.EncodeToString(sender[:])) diff --git a/core/transaction/encoder/resources.go b/core/transaction/encoder/resources.go index e103abbf7..677da5eb5 100644 --- a/core/transaction/encoder/resources.go +++ b/core/transaction/encoder/resources.go @@ -352,7 +352,8 @@ func (ChangeOwnerDataResource) Transform(txData interface{}, context *state.Chec type EditMultisigOwnersResource struct { MultisigAddress types.Address `json:"multisig_address"` - Weights []uint32 `json:"weight"` + Threshold string `json:"threshold"` + Weights []string `json:"weights"` Addresses []types.Address `json:"addresses"` } @@ -364,11 +365,13 @@ func (EditMultisigOwnersResource) Transform(txData interface{}, context *state.C Addresses: data.Addresses, } - resource.Weights = make([]uint32, 0, len(data.Weights)) + resource.Weights = make([]string, 0, len(data.Weights)) for _, weight := range data.Weights { - resource.Weights = append(resource.Weights, uint32(weight)) + resource.Weights = append(resource.Weights, strconv.Itoa(int(weight))) } + resource.Threshold = strconv.Itoa(int(data.Threshold)) + return resource } diff --git a/go.mod b/go.mod index c0b52bd60..5d49d4fd1 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200817221822-398a8a87d81e + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818104841-2bc949f4b30a github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 6bdab14a9..32600969c 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200817221822-398a8a87d81e h1:9Pw3k7RUWSIxnrs7EfCxQEw87pcjW+bhTysnP7h9zfY= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200817221822-398a8a87d81e/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818104841-2bc949f4b30a h1:5TX1AkSKv55jXCuKSwx0rp2y/gioOyU6SH6fpNh4fYQ= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818104841-2bc949f4b30a/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 78af516099d7a1a645bb4e5e6f680784f13aeff2 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 18 Aug 2020 14:02:56 +0300 Subject: [PATCH 169/426] update gateway --- api/v2/service/candidate.go | 1 + go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/api/v2/service/candidate.go b/api/v2/service/candidate.go index dd6242500..4d70545e3 100644 --- a/api/v2/service/candidate.go +++ b/api/v2/service/candidate.go @@ -51,6 +51,7 @@ func (s *Service) Candidate(ctx context.Context, req *pb.CandidateRequest) (*pb. func makeResponseCandidate(state *state.CheckState, c *candidates.Candidate, includeStakes bool) *pb.CandidateResponse { candidate := &pb.CandidateResponse{ RewardAddress: c.RewardAddress.String(), + OwnerAddress: c.OwnerAddress.String(), TotalStake: state.Candidates().GetTotalStake(c.PubKey).String(), PublicKey: c.PubKey.String(), Commission: fmt.Sprintf("%d", c.Commission), diff --git a/go.mod b/go.mod index 5d49d4fd1..8854a42ac 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818104841-2bc949f4b30a + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818110134-9c66c81517e3 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 32600969c..3e07629fe 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818104841-2bc949f4b30a h1:5TX1AkSKv55jXCuKSwx0rp2y/gioOyU6SH6fpNh4fYQ= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818104841-2bc949f4b30a/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818110134-9c66c81517e3 h1:J8ADM/ckZO+ZGUE85iAK8iFySGJNjgUKgNxk5upS2Ts= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818110134-9c66c81517e3/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 0a5036ba81f5b1771163bbfa743988e3299d7f68 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 18 Aug 2020 14:11:48 +0300 Subject: [PATCH 170/426] fix error message --- core/transaction/edit_multisig_owners.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/transaction/edit_multisig_owners.go b/core/transaction/edit_multisig_owners.go index 95e1b5bab..4d06d8729 100644 --- a/core/transaction/edit_multisig_owners.go +++ b/core/transaction/edit_multisig_owners.go @@ -25,7 +25,7 @@ func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.Ch if sender != data.MultisigAddress { return &Response{ Code: code.IncorrectMultiSignature, - Log: "Sender is not multisig adress", + Log: "Sender is not multisig address", Info: EncodeError(map[string]string{ "multisig_address": data.MultisigAddress.String(), "sender": sender.String(), From 56bc275f1e51df29aacecf57a88869167c580446 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 18 Aug 2020 14:36:36 +0300 Subject: [PATCH 171/426] edit multisig owners data --- api/v2/service/data_encoder.go | 7 +++---- core/transaction/create_multisig.go | 2 +- core/transaction/edit_multisig_owners.go | 24 ++++++------------------ core/transaction/encoder/resources.go | 6 ++---- go.mod | 2 +- go.sum | 4 ++-- 6 files changed, 15 insertions(+), 30 deletions(-) diff --git a/api/v2/service/data_encoder.go b/api/v2/service/data_encoder.go index 5506d7c22..699938b1e 100644 --- a/api/v2/service/data_encoder.go +++ b/api/v2/service/data_encoder.go @@ -107,10 +107,9 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { addresses = append(addresses, address.String()) } m = &pb.EditMultisigOwnersData{ - MultisigAddress: d.MultisigAddress.String(), - Threshold: strconv.Itoa(int(d.Threshold)), - Weights: weights, - Addresses: addresses, + Threshold: strconv.Itoa(int(d.Threshold)), + Weights: weights, + Addresses: addresses, } case *transaction.MultisendData: d := data.(*transaction.MultisendData) diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index 10e48087c..96add517f 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -62,7 +62,7 @@ func (data CreateMultisigData) BasicCheck(tx *Transaction, context *state.CheckS } func (data CreateMultisigData) String() string { - return fmt.Sprintf("CREATE MULTISIG") + return "CREATE MULTISIG" } func (data CreateMultisigData) Gas() int64 { diff --git a/core/transaction/edit_multisig_owners.go b/core/transaction/edit_multisig_owners.go index 4d06d8729..a6751654a 100644 --- a/core/transaction/edit_multisig_owners.go +++ b/core/transaction/edit_multisig_owners.go @@ -13,32 +13,20 @@ import ( ) type EditMultisigOwnersData struct { - MultisigAddress types.Address - Threshold uint - Weights []uint - Addresses []types.Address + Threshold uint + Weights []uint + Addresses []types.Address } func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { sender, _ := tx.Sender() - if sender != data.MultisigAddress { - return &Response{ - Code: code.IncorrectMultiSignature, - Log: "Sender is not multisig address", - Info: EncodeError(map[string]string{ - "multisig_address": data.MultisigAddress.String(), - "sender": sender.String(), - }), - } - } - - if !context.Accounts().GetAccount(data.MultisigAddress).IsMultisig() { + if !context.Accounts().GetAccount(sender).IsMultisig() { return &Response{ Code: code.MultisigNotExists, Log: "Multisig does not exists", Info: EncodeError(map[string]string{ - "multisig_address": data.MultisigAddress.String(), + "multisig_address": sender.String(), }), } } @@ -100,7 +88,7 @@ func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.Ch } func (data EditMultisigOwnersData) String() string { - return fmt.Sprintf("EDIT MULTISIG OWNERS address: %x", data.MultisigAddress) + return "EDIT MULTISIG OWNERS" } func (data EditMultisigOwnersData) Gas() int64 { diff --git a/core/transaction/encoder/resources.go b/core/transaction/encoder/resources.go index c4d16128d..8aeb67b9f 100644 --- a/core/transaction/encoder/resources.go +++ b/core/transaction/encoder/resources.go @@ -361,8 +361,8 @@ func (EditMultisigOwnersResource) Transform(txData interface{}, context *state.C data := txData.(*transaction.EditMultisigOwnersData) resource := EditMultisigOwnersResource{ - MultisigAddress: data.MultisigAddress, - Addresses: data.Addresses, + Addresses: data.Addresses, + Threshold: strconv.Itoa(int(data.Threshold)), } resource.Weights = make([]string, 0, len(data.Weights)) @@ -370,8 +370,6 @@ func (EditMultisigOwnersResource) Transform(txData interface{}, context *state.C resource.Weights = append(resource.Weights, strconv.Itoa(int(weight))) } - resource.Threshold = strconv.Itoa(int(data.Threshold)) - return resource } diff --git a/go.mod b/go.mod index 8854a42ac..3d476a8b3 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818110134-9c66c81517e3 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818113440-fe9f21434b29 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 3e07629fe..e77e9db19 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818110134-9c66c81517e3 h1:J8ADM/ckZO+ZGUE85iAK8iFySGJNjgUKgNxk5upS2Ts= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818110134-9c66c81517e3/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818113440-fe9f21434b29 h1:MnKjbs8Lii+I4TSEWiXxRgQuOZ99WGf52KUWr0M53u0= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818113440-fe9f21434b29/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 0a24ebb0a40da0d01c639830d55ccc78a97f3862 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 20 Aug 2020 13:05:39 +0300 Subject: [PATCH 172/426] add owner address to RecreateCoinData resource --- core/transaction/encoder/resources.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/transaction/encoder/resources.go b/core/transaction/encoder/resources.go index 52ec68280..7941891d7 100644 --- a/core/transaction/encoder/resources.go +++ b/core/transaction/encoder/resources.go @@ -313,6 +313,7 @@ func (SetHaltBlockDataResource) Transform(txData interface{}, context *state.Che // TxType 0x10 type RecreateCoinDataResource struct { + Name string `json:"name"` Symbol types.CoinSymbol `json:"symbol"` InitialAmount string `json:"initial_amount"` InitialReserve string `json:"initial_reserve"` @@ -324,6 +325,7 @@ func (RecreateCoinDataResource) Transform(txData interface{}, context *state.Che data := txData.(*transaction.RecreateCoinData) return RecreateCoinDataResource{ + Name: data.Name, Symbol: data.Symbol, InitialAmount: data.InitialAmount.String(), InitialReserve: data.InitialReserve.String(), From 30717f14d668a3493c3d962a2d92e20877e353a7 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 20 Aug 2020 13:08:10 +0300 Subject: [PATCH 173/426] add name field to recreate coin data for api v2 --- api/v2/service/data_encoder.go | 1 + go.mod | 6 +++--- go.sum | 18 ++++++++---------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/api/v2/service/data_encoder.go b/api/v2/service/data_encoder.go index feef2ce91..5f8bf3ad5 100644 --- a/api/v2/service/data_encoder.go +++ b/api/v2/service/data_encoder.go @@ -135,6 +135,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { case *transaction.RecreateCoinData: d := data.(*transaction.RecreateCoinData) m = &pb.RecreateCoinData{ + Name: d.Name, Symbol: d.Symbol.String(), InitialAmount: d.InitialAmount.String(), InitialReserve: d.InitialReserve.String(), diff --git a/go.mod b/go.mod index d0e4ed5fe..378873301 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200813111959-9b43734535eb + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200819125246-3a79c4eeb87f github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 @@ -13,7 +13,7 @@ require ( github.com/gorilla/websocket v1.4.2 github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 - github.com/grpc-ecosystem/grpc-gateway v1.14.6 + github.com/grpc-ecosystem/grpc-gateway v1.14.7 github.com/marcusolsson/tui-go v0.4.0 github.com/mattn/go-tty v0.0.3 // indirect github.com/pkg/errors v0.9.1 @@ -36,7 +36,7 @@ require ( golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e golang.org/x/sys v0.0.0-20200523222454-059865788121 - google.golang.org/grpc v1.30.0 + google.golang.org/grpc v1.31.0 google.golang.org/protobuf v1.25.0 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 ) diff --git a/go.sum b/go.sum index 138d21210..47d6c98ee 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200813111959-9b43734535eb h1:BO6caE+wn77Rnthv2cIyEZovwv/Ee7OTjcK7HehX8jI= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200813111959-9b43734535eb/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200819125246-3a79c4eeb87f h1:YS2NxABCtvC7efGDqvlzsUnZQM9VQ7XrO9Pfq6eSfwc= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200819125246-3a79c4eeb87f/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= @@ -196,8 +196,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0 h1:bM6ZAFZmc/wPFaRDi0d5L7hGEZEx/2u+Tmr2evNHDiI= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.14.6 h1:8ERzHx8aj1Sc47mu9n/AksaKCSWrMchFtkdrS4BIj5o= -github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= +github.com/grpc-ecosystem/grpc-gateway v1.14.7 h1:Nk5kuHrnWUTf/0GL1a/vchH/om9Ap2/HnVna+jYZgTY= +github.com/grpc-ecosystem/grpc-gateway v1.14.7/go.mod h1:oYZKL012gGh6LMyg/xA7Q2yq6j8bu0wa+9w14EEthWU= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f h1:8N8XWLZelZNibkhM1FuF+3Ad3YIbgirjdMiVA0eUkaM= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= @@ -623,8 +623,8 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2El google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200702021140-07506425bd67 h1:4BC1C1i30F3MZeiIO6y6IIo4DxrtOwITK87bQl3lhFA= -google.golang.org/genproto v0.0.0-20200702021140-07506425bd67/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70 h1:wboULUXGF3c5qdUnKp+6gLAccE6PRpa/czkYvQ4UXv8= +google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -641,10 +641,8 @@ google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k= google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0 h1:T7P4R73V3SSDPhH7WW7ATbfViLtmamH0DKrP3f9AuDI= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 8fa7b359d8c41db4df2d1619ee6d42e781fa62ee Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 20 Aug 2020 13:15:17 +0300 Subject: [PATCH 174/426] Revert "add name field to recreate coin data for api v2" This reverts commit 30717f14d668a3493c3d962a2d92e20877e353a7. --- api/v2/service/data_encoder.go | 1 - go.mod | 6 +++--- go.sum | 18 ++++++++++-------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/api/v2/service/data_encoder.go b/api/v2/service/data_encoder.go index 5f8bf3ad5..feef2ce91 100644 --- a/api/v2/service/data_encoder.go +++ b/api/v2/service/data_encoder.go @@ -135,7 +135,6 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { case *transaction.RecreateCoinData: d := data.(*transaction.RecreateCoinData) m = &pb.RecreateCoinData{ - Name: d.Name, Symbol: d.Symbol.String(), InitialAmount: d.InitialAmount.String(), InitialReserve: d.InitialReserve.String(), diff --git a/go.mod b/go.mod index 378873301..d0e4ed5fe 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200819125246-3a79c4eeb87f + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200813111959-9b43734535eb github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 @@ -13,7 +13,7 @@ require ( github.com/gorilla/websocket v1.4.2 github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 - github.com/grpc-ecosystem/grpc-gateway v1.14.7 + github.com/grpc-ecosystem/grpc-gateway v1.14.6 github.com/marcusolsson/tui-go v0.4.0 github.com/mattn/go-tty v0.0.3 // indirect github.com/pkg/errors v0.9.1 @@ -36,7 +36,7 @@ require ( golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e golang.org/x/sys v0.0.0-20200523222454-059865788121 - google.golang.org/grpc v1.31.0 + google.golang.org/grpc v1.30.0 google.golang.org/protobuf v1.25.0 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 ) diff --git a/go.sum b/go.sum index 47d6c98ee..138d21210 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200819125246-3a79c4eeb87f h1:YS2NxABCtvC7efGDqvlzsUnZQM9VQ7XrO9Pfq6eSfwc= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200819125246-3a79c4eeb87f/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200813111959-9b43734535eb h1:BO6caE+wn77Rnthv2cIyEZovwv/Ee7OTjcK7HehX8jI= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200813111959-9b43734535eb/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= @@ -196,8 +196,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0 h1:bM6ZAFZmc/wPFaRDi0d5L7hGEZEx/2u+Tmr2evNHDiI= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.14.7 h1:Nk5kuHrnWUTf/0GL1a/vchH/om9Ap2/HnVna+jYZgTY= -github.com/grpc-ecosystem/grpc-gateway v1.14.7/go.mod h1:oYZKL012gGh6LMyg/xA7Q2yq6j8bu0wa+9w14EEthWU= +github.com/grpc-ecosystem/grpc-gateway v1.14.6 h1:8ERzHx8aj1Sc47mu9n/AksaKCSWrMchFtkdrS4BIj5o= +github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f h1:8N8XWLZelZNibkhM1FuF+3Ad3YIbgirjdMiVA0eUkaM= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= @@ -623,8 +623,8 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2El google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70 h1:wboULUXGF3c5qdUnKp+6gLAccE6PRpa/czkYvQ4UXv8= -google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200702021140-07506425bd67 h1:4BC1C1i30F3MZeiIO6y6IIo4DxrtOwITK87bQl3lhFA= +google.golang.org/genproto v0.0.0-20200702021140-07506425bd67/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -641,8 +641,10 @@ google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k= google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.31.0 h1:T7P4R73V3SSDPhH7WW7ATbfViLtmamH0DKrP3f9AuDI= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From bdde19ba604963c69437d23fbb020adb957715b8 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 20 Aug 2020 13:17:27 +0300 Subject: [PATCH 175/426] fix --- api/v2/service/data_encoder.go | 1 + go.mod | 6 +++--- go.sum | 8 ++++++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/api/v2/service/data_encoder.go b/api/v2/service/data_encoder.go index 699938b1e..7ac262e92 100644 --- a/api/v2/service/data_encoder.go +++ b/api/v2/service/data_encoder.go @@ -135,6 +135,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { case *transaction.RecreateCoinData: d := data.(*transaction.RecreateCoinData) m = &pb.RecreateCoinData{ + Name: d.Name, Symbol: d.Symbol.String(), InitialAmount: d.InitialAmount.String(), InitialReserve: d.InitialReserve.String(), diff --git a/go.mod b/go.mod index 3d476a8b3..378873301 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818113440-fe9f21434b29 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200819125246-3a79c4eeb87f github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 @@ -13,7 +13,7 @@ require ( github.com/gorilla/websocket v1.4.2 github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 - github.com/grpc-ecosystem/grpc-gateway v1.14.6 + github.com/grpc-ecosystem/grpc-gateway v1.14.7 github.com/marcusolsson/tui-go v0.4.0 github.com/mattn/go-tty v0.0.3 // indirect github.com/pkg/errors v0.9.1 @@ -36,7 +36,7 @@ require ( golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e golang.org/x/sys v0.0.0-20200523222454-059865788121 - google.golang.org/grpc v1.30.0 + google.golang.org/grpc v1.31.0 google.golang.org/protobuf v1.25.0 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 ) diff --git a/go.sum b/go.sum index e77e9db19..bd4726760 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,8 @@ github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818113440-fe9f21434b29 h1:MnKjbs8Lii+I4TSEWiXxRgQuOZ99WGf52KUWr0M53u0= github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818113440-fe9f21434b29/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200819125246-3a79c4eeb87f h1:YS2NxABCtvC7efGDqvlzsUnZQM9VQ7XrO9Pfq6eSfwc= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200819125246-3a79c4eeb87f/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= @@ -198,6 +200,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.14.6 h1:8ERzHx8aj1Sc47mu9n/AksaKCSWrMchFtkdrS4BIj5o= github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= +github.com/grpc-ecosystem/grpc-gateway v1.14.7 h1:Nk5kuHrnWUTf/0GL1a/vchH/om9Ap2/HnVna+jYZgTY= +github.com/grpc-ecosystem/grpc-gateway v1.14.7/go.mod h1:oYZKL012gGh6LMyg/xA7Q2yq6j8bu0wa+9w14EEthWU= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f h1:8N8XWLZelZNibkhM1FuF+3Ad3YIbgirjdMiVA0eUkaM= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= @@ -625,6 +629,8 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200702021140-07506425bd67 h1:4BC1C1i30F3MZeiIO6y6IIo4DxrtOwITK87bQl3lhFA= google.golang.org/genproto v0.0.0-20200702021140-07506425bd67/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70 h1:wboULUXGF3c5qdUnKp+6gLAccE6PRpa/czkYvQ4UXv8= +google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -645,6 +651,8 @@ google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0 h1:T7P4R73V3SSDPhH7WW7ATbfViLtmamH0DKrP3f9AuDI= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 5c657cd1cb3d017b4f092782e641a69e4fa7e737 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 20 Aug 2020 13:24:17 +0300 Subject: [PATCH 176/426] fix tests --- core/transaction/edit_multisig_owners_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/transaction/edit_multisig_owners_test.go b/core/transaction/edit_multisig_owners_test.go index 92377e42c..b2298e371 100644 --- a/core/transaction/edit_multisig_owners_test.go +++ b/core/transaction/edit_multisig_owners_test.go @@ -35,7 +35,7 @@ func TestEditMultisigOwnersTx(t *testing.T) { cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(initialBalance)) data := EditMultisigOwnersData{ - MultisigAddress: addr, + Threshold: 3, Weights: []uint{2, 1, 2}, Addresses: []types.Address{addr1, addr2, addr4}, } From 2e5a751cab9254da83526d6c4da1ff4ddc04a384 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Thu, 20 Aug 2020 17:40:05 +0300 Subject: [PATCH 177/426] Test framework --- core/transaction/encoder/encoder.go | 2 +- tests/helpers.go | 140 ++++++++++++++++++++++++++++ tests/send_test.go | 67 +++++++++++++ 3 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 tests/helpers.go create mode 100644 tests/send_test.go diff --git a/core/transaction/encoder/encoder.go b/core/transaction/encoder/encoder.go index e6ed7f991..b0b175a6c 100644 --- a/core/transaction/encoder/encoder.go +++ b/core/transaction/encoder/encoder.go @@ -49,7 +49,7 @@ var resourcesConfig = map[transaction.TxType]TxDataResource{ transaction.TypeEditCandidate: new(EditCandidateDataResource), transaction.TypeSetHaltBlock: new(SetHaltBlockDataResource), transaction.TypeRecreateCoin: new(RecreateCoinDataResource), - transaction.TypeChangeCoinOwner: new(ChangeCoinOwnerDataResource), + transaction.TypeChangeCoinOwner: new(ChangeCoinOwnerDataResource), transaction.TypeEditMultisigOwner: new(EditMultisigOwnersResource), transaction.TypePriceVote: new(PriceVoteResource), } diff --git a/tests/helpers.go b/tests/helpers.go new file mode 100644 index 000000000..2e6c87fac --- /dev/null +++ b/tests/helpers.go @@ -0,0 +1,140 @@ +package tests + +import ( + "crypto/ecdsa" + "github.com/MinterTeam/minter-go-node/cmd/utils" + "github.com/MinterTeam/minter-go-node/config" + "github.com/MinterTeam/minter-go-node/core/minter" + "github.com/MinterTeam/minter-go-node/core/transaction" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/crypto" + "github.com/MinterTeam/minter-go-node/rlp" + "github.com/tendermint/go-amino" + tmTypes "github.com/tendermint/tendermint/abci/types" + "os" + "path/filepath" + "time" +) + +func CreateApp(state types.AppState) *minter.Blockchain { + utils.MinterHome = os.ExpandEnv(filepath.Join("$HOME", ".minter_test")) + _ = os.RemoveAll(utils.MinterHome) + + jsonState, err := amino.MarshalJSON(state) + if err != nil { + panic(err) + } + + cfg := config.GetConfig() + app := minter.NewMinterBlockchain(cfg) + app.InitChain(tmTypes.RequestInitChain{ + Time: time.Now(), + ChainId: "test", + Validators: []tmTypes.ValidatorUpdate{ + { + PubKey: tmTypes.PubKey{}, + Power: 1, + }, + }, + AppStateBytes: jsonState, + }) + + return app +} + +func SendCommit(app *minter.Blockchain) tmTypes.ResponseCommit { + return app.Commit() +} + +func SendBeginBlock(app *minter.Blockchain) tmTypes.ResponseBeginBlock { + return app.BeginBlock(tmTypes.RequestBeginBlock{ + Hash: nil, + Header: tmTypes.Header{ + Version: tmTypes.Version{}, + ChainID: "", + Height: 1, + Time: time.Time{}, + LastBlockId: tmTypes.BlockID{}, + LastCommitHash: nil, + DataHash: nil, + ValidatorsHash: nil, + NextValidatorsHash: nil, + ConsensusHash: nil, + AppHash: nil, + LastResultsHash: nil, + EvidenceHash: nil, + ProposerAddress: nil, + }, + LastCommitInfo: tmTypes.LastCommitInfo{ + Round: 0, + Votes: nil, + }, + ByzantineValidators: nil, + }) +} + +func SendEndBlock(app *minter.Blockchain) tmTypes.ResponseEndBlock { + return app.EndBlock(tmTypes.RequestEndBlock{ + Height: 0, + }) +} + +func CreateTx(app *minter.Blockchain, address types.Address, txType transaction.TxType, data interface{}) transaction.Transaction { + nonce := app.CurrentState().Accounts().GetNonce(address) + 1 + bData, err := rlp.EncodeToBytes(data) + if err != nil { + panic(err) + } + + tx := transaction.Transaction{ + Nonce: nonce, + ChainID: types.CurrentChainID, + GasPrice: 1, + GasCoin: types.GetBaseCoinID(), + Type: txType, + Data: bData, + SignatureType: transaction.SigTypeSingle, + } + + return tx +} + +func SendTx(app *minter.Blockchain, bytes []byte) tmTypes.ResponseDeliverTx { + return app.DeliverTx(tmTypes.RequestDeliverTx{ + Tx: bytes, + }) +} + +func SignTx(pk *ecdsa.PrivateKey, tx transaction.Transaction) []byte { + err := tx.Sign(pk) + if err != nil { + panic(err) + } + + b, _ := rlp.EncodeToBytes(tx) + + return b +} + +func CreateAddress() (types.Address, *ecdsa.PrivateKey) { + pk, _ := crypto.GenerateKey() + + return crypto.PubkeyToAddress(pk.PublicKey), pk +} + +func DefaultAppState() types.AppState { + return types.AppState{ + Note: "", + StartHeight: 1, + Validators: nil, + Candidates: nil, + BlockListCandidates: nil, + Accounts: nil, + Coins: nil, + FrozenFunds: nil, + HaltBlocks: nil, + UsedChecks: nil, + MaxGas: 0, + TotalSlashed: "0", + } +} diff --git a/tests/send_test.go b/tests/send_test.go new file mode 100644 index 000000000..9abd9ea70 --- /dev/null +++ b/tests/send_test.go @@ -0,0 +1,67 @@ +package tests + +import ( + "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/transaction" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/helpers" + "math/big" + "testing" +) + +func TestSend(t *testing.T) { + address, pk := CreateAddress() // create account for test + + state := DefaultAppState() // generate default state + + // add address to genesis state + state.Accounts = append(state.Accounts, types.Account{ + Address: address, + Balance: []types.Balance{ + { + Coin: types.GetBaseCoinID(), + Value: helpers.BipToPip(big.NewInt(1)).String(), + }, + }, + Nonce: 0, + MultisigData: nil, + }) + + app := CreateApp(state) // create application + SendBeginBlock(app) // send BeginBlock + + recipient, _ := CreateAddress() // generate recipient + value := big.NewInt(1) + + tx := CreateTx(app, address, transaction.TypeSend, transaction.SendData{ + Coin: types.GetBaseCoinID(), + To: recipient, + Value: value, + }) + + response := SendTx(app, SignTx(pk, 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) // send EndBlock + SendCommit(app) // send Commit + + // check recipient's balance + { + balance := app.CurrentState().Accounts().GetBalance(recipient, types.GetBaseCoinID()) + if balance.Cmp(value) != 0 { + t.Fatalf("Recipient balance is not correct. Expected %s, got %s", value, balance) + } + } + + // check sender's balance + { + balance := app.CurrentState().Accounts().GetBalance(address, types.GetBaseCoinID()) + if balance.String() != "989999999999999999" { + t.Fatalf("Recipient balance is not correct. Expected %s, got %s", "989999999999999999", balance) + } + } +} From 20062516f27e3da79a38ce37f63e035d95a5bd7d Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Mon, 24 Aug 2020 10:59:15 +0300 Subject: [PATCH 178/426] use candidate id for waitlist --- core/state/waitlist/model.go | 18 +++++++++--------- core/state/waitlist/waitlist.go | 29 +++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/core/state/waitlist/model.go b/core/state/waitlist/model.go index 28796be06..1d08ac13a 100644 --- a/core/state/waitlist/model.go +++ b/core/state/waitlist/model.go @@ -6,9 +6,9 @@ import ( ) type Item struct { - PublicKey types.Pubkey - Coin types.CoinID - Value *big.Int + CandidateId uint32 + Coin types.CoinID + Value *big.Int } type Model struct { @@ -18,19 +18,19 @@ type Model struct { markDirty func(address types.Address) } -func (m *Model) AddToList(publicKey types.Pubkey, coin types.CoinID, value *big.Int) { +func (m *Model) AddToList(candidateId uint32, coin types.CoinID, value *big.Int) { m.List = append(m.List, Item{ - PublicKey: publicKey, - Coin: coin, - Value: value, + CandidateId: candidateId, + Coin: coin, + Value: value, }) } -func (m *Model) GetValue(pubkey types.Pubkey, coin types.CoinID) *big.Int { +func (m *Model) GetValue(candidateId uint32, coin types.CoinID) *big.Int { value := big.NewInt(0) for _, item := range m.List { - if item.PublicKey == pubkey && item.Coin == coin { + if item.CandidateId == candidateId && item.Coin == coin { value.Add(value, item.Value) } } diff --git a/core/state/waitlist/waitlist.go b/core/state/waitlist/waitlist.go index 257359e38..19e14621c 100644 --- a/core/state/waitlist/waitlist.go +++ b/core/state/waitlist/waitlist.go @@ -74,8 +74,13 @@ func (wl *WaitList) Get(address types.Address, pubkey types.Pubkey, coin types.C return nil } + candidate := wl.bus.Candidates().GetCandidate(pubkey) + if candidate == nil { + log.Panicf("Candidate not found: %s", pubkey.String()) + } + for _, item := range waitlist.List { - if item.PublicKey == pubkey && item.Coin == coin { + if item.CandidateId == candidate.ID && item.Coin == coin { return &item } } @@ -89,9 +94,14 @@ func (wl *WaitList) GetByAddressAndPubKey(address types.Address, pubkey types.Pu return nil } + candidate := wl.bus.Candidates().GetCandidate(pubkey) + if candidate == nil { + log.Panicf("Candidate not found: %s", pubkey.String()) + } + items := make([]Item, 0, len(waitlist.List)) for i, item := range waitlist.List { - if item.PublicKey == pubkey { + if item.CandidateId == candidate.ID { items[i] = item } } @@ -105,7 +115,13 @@ func (wl *WaitList) GetByAddressAndPubKey(address types.Address, pubkey types.Pu func (wl *WaitList) AddWaitList(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { w := wl.getOrNew(address) - w.AddToList(pubkey, coin, value) + + candidate := wl.bus.Candidates().GetCandidate(pubkey) + if candidate == nil { + log.Panicf("Candidate not found: %s", pubkey.String()) + } + + w.AddToList(candidate.ID, coin, value) wl.setToMap(address, w) w.markDirty(address) } @@ -116,9 +132,14 @@ func (wl *WaitList) Delete(address types.Address, pubkey types.Pubkey, coin type log.Panicf("Waitlist not found for %s", address.String()) } + candidate := wl.bus.Candidates().GetCandidate(pubkey) + if candidate == nil { + log.Panicf("Candidate not found: %s", pubkey.String()) + } + items := make([]Item, 0, len(w.List)) for _, item := range w.List { - if item.PublicKey != pubkey && item.Coin != coin { + if item.CandidateId != candidate.ID && item.Coin != coin { items = append(items, item) } } From 2622df6e77d822a0e1d0df88d5fcc4f150697dc3 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 27 Aug 2020 10:54:47 +0300 Subject: [PATCH 179/426] fixes --- api/v2/service/data_encoder.go | 2 +- go.mod | 2 +- go.sum | 14 ++------------ 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/api/v2/service/data_encoder.go b/api/v2/service/data_encoder.go index 7ac262e92..9e18ebd48 100644 --- a/api/v2/service/data_encoder.go +++ b/api/v2/service/data_encoder.go @@ -18,7 +18,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { switch data.(type) { case *transaction.BuyCoinData: d := data.(*transaction.BuyCoinData) - m = &pb.BuyCoin{ + m = &pb.BuyCoinData{ CoinToBuy: &pb.Coin{ Id: d.CoinToBuy.String(), Symbol: coins.GetCoin(d.CoinToBuy).Symbol().String(), diff --git a/go.mod b/go.mod index 378873301..abdc0fa1b 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200819125246-3a79c4eeb87f + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200827075149-9a899154bdc5 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index bd4726760..90511aaf8 100644 --- a/go.sum +++ b/go.sum @@ -6,10 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818113440-fe9f21434b29 h1:MnKjbs8Lii+I4TSEWiXxRgQuOZ99WGf52KUWr0M53u0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200818113440-fe9f21434b29/go.mod h1:p9MrIZ6o73db4NeV3+vsuWB4NzQM+e9y2nvGVayTEQw= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200819125246-3a79c4eeb87f h1:YS2NxABCtvC7efGDqvlzsUnZQM9VQ7XrO9Pfq6eSfwc= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200819125246-3a79c4eeb87f/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200827075149-9a899154bdc5 h1:ALM3TTNVX9Tx65o1aZixOTZM7M20s/+qcLudCVU/tvc= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200827075149-9a899154bdc5/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= @@ -198,8 +196,6 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0 h1:bM6ZAFZmc/wPFaRDi0d5L7hGEZEx/2u+Tmr2evNHDiI= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.14.6 h1:8ERzHx8aj1Sc47mu9n/AksaKCSWrMchFtkdrS4BIj5o= -github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= github.com/grpc-ecosystem/grpc-gateway v1.14.7 h1:Nk5kuHrnWUTf/0GL1a/vchH/om9Ap2/HnVna+jYZgTY= github.com/grpc-ecosystem/grpc-gateway v1.14.7/go.mod h1:oYZKL012gGh6LMyg/xA7Q2yq6j8bu0wa+9w14EEthWU= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f h1:8N8XWLZelZNibkhM1FuF+3Ad3YIbgirjdMiVA0eUkaM= @@ -627,8 +623,6 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2El google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200702021140-07506425bd67 h1:4BC1C1i30F3MZeiIO6y6IIo4DxrtOwITK87bQl3lhFA= -google.golang.org/genproto v0.0.0-20200702021140-07506425bd67/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70 h1:wboULUXGF3c5qdUnKp+6gLAccE6PRpa/czkYvQ4UXv8= google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -647,10 +641,6 @@ google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k= google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0 h1:T7P4R73V3SSDPhH7WW7ATbfViLtmamH0DKrP3f9AuDI= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= From f0ce502dc4d6f1fbed18a38fce692ef14523d454 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 27 Aug 2020 14:28:45 +0300 Subject: [PATCH 180/426] rename to public_key in genesis --- api/genesis.go | 59 +++++++++++++++++++++++++++++++++++++++--- core/types/appstate.go | 4 +-- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/api/genesis.go b/api/genesis.go index cf07b4792..4e23cd38d 100644 --- a/api/genesis.go +++ b/api/genesis.go @@ -1,9 +1,62 @@ package api import ( - core_types "github.com/tendermint/tendermint/rpc/core/types" + "encoding/json" + "github.com/tendermint/tendermint/crypto" + tmbytes "github.com/tendermint/tendermint/libs/bytes" + "github.com/tendermint/tendermint/types" + "time" ) -func Genesis() (*core_types.ResultGenesis, error) { - return client.Genesis() +// Genesis file +type ResultGenesis struct { + Genesis *GenesisDoc `json:"genesis"` +} + +// GenesisValidator is an initial validator. +type GenesisValidator struct { + Address types.Address `json:"address"` + PubKey crypto.PubKey `json:"public_key"` + Power int64 `json:"power"` + Name string `json:"name"` +} + +// GenesisDoc defines the initial conditions for a tendermint blockchain, in particular its validator set. +type GenesisDoc struct { + GenesisTime time.Time `json:"genesis_time"` + ChainID string `json:"chain_id"` + ConsensusParams *types.ConsensusParams `json:"consensus_params,omitempty"` + Validators []GenesisValidator `json:"validators,omitempty"` + AppHash tmbytes.HexBytes `json:"app_hash"` + AppState json.RawMessage `json:"app_state,omitempty"` +} + +func Genesis() (*ResultGenesis, error) { + result, err := client.Genesis() + if err != nil { + return nil, err + } + + return &ResultGenesis{ + Genesis: &GenesisDoc{ + GenesisTime: result.Genesis.GenesisTime, + ChainID: result.Genesis.ChainID, + ConsensusParams: &types.ConsensusParams{ + Block: types.BlockParams{ + MaxBytes: result.Genesis.ConsensusParams.Block.MaxBytes, + MaxGas: result.Genesis.ConsensusParams.Block.MaxGas, + TimeIotaMs: result.Genesis.ConsensusParams.Block.TimeIotaMs, + }, + Evidence: types.EvidenceParams{ + MaxAgeNumBlocks: result.Genesis.ConsensusParams.Evidence.MaxAgeNumBlocks, + MaxAgeDuration: result.Genesis.ConsensusParams.Evidence.MaxAgeDuration, + }, + Validator: types.ValidatorParams{ + PubKeyTypes: result.Genesis.ConsensusParams.Validator.PubKeyTypes, + }, + }, + AppHash: result.Genesis.AppHash, + AppState: result.Genesis.AppState, + }, + }, nil } diff --git a/core/types/appstate.go b/core/types/appstate.go index a1e21dafe..416cfaa27 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -204,7 +204,7 @@ func (s *AppState) Verify() error { type Validator struct { TotalBipStake string `json:"total_bip_stake"` - PubKey Pubkey `json:"pub_key"` + PubKey Pubkey `json:"public_key"` AccumReward string `json:"accum_reward"` AbsentTimes *BitArray `json:"absent_times"` } @@ -215,7 +215,7 @@ type Candidate struct { OwnerAddress Address `json:"owner_address"` ControlAddress Address `json:"control_address"` TotalBipStake string `json:"total_bip_stake"` - PubKey Pubkey `json:"pub_key"` + PubKey Pubkey `json:"public_key"` Commission uint `json:"commission"` Stakes []Stake `json:"stakes"` Updates []Stake `json:"updates"` From e9af9f2ef92eb3712d91ca9bafbf17206ba041d9 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 27 Aug 2020 14:44:47 +0300 Subject: [PATCH 181/426] fix --- api/genesis.go | 61 +++----------------------------------------------- 1 file changed, 3 insertions(+), 58 deletions(-) diff --git a/api/genesis.go b/api/genesis.go index 4e23cd38d..a8e8dabd7 100644 --- a/api/genesis.go +++ b/api/genesis.go @@ -1,62 +1,7 @@ package api -import ( - "encoding/json" - "github.com/tendermint/tendermint/crypto" - tmbytes "github.com/tendermint/tendermint/libs/bytes" - "github.com/tendermint/tendermint/types" - "time" -) +import core_types "github.com/tendermint/tendermint/rpc/core/types" -// Genesis file -type ResultGenesis struct { - Genesis *GenesisDoc `json:"genesis"` -} - -// GenesisValidator is an initial validator. -type GenesisValidator struct { - Address types.Address `json:"address"` - PubKey crypto.PubKey `json:"public_key"` - Power int64 `json:"power"` - Name string `json:"name"` -} - -// GenesisDoc defines the initial conditions for a tendermint blockchain, in particular its validator set. -type GenesisDoc struct { - GenesisTime time.Time `json:"genesis_time"` - ChainID string `json:"chain_id"` - ConsensusParams *types.ConsensusParams `json:"consensus_params,omitempty"` - Validators []GenesisValidator `json:"validators,omitempty"` - AppHash tmbytes.HexBytes `json:"app_hash"` - AppState json.RawMessage `json:"app_state,omitempty"` -} - -func Genesis() (*ResultGenesis, error) { - result, err := client.Genesis() - if err != nil { - return nil, err - } - - return &ResultGenesis{ - Genesis: &GenesisDoc{ - GenesisTime: result.Genesis.GenesisTime, - ChainID: result.Genesis.ChainID, - ConsensusParams: &types.ConsensusParams{ - Block: types.BlockParams{ - MaxBytes: result.Genesis.ConsensusParams.Block.MaxBytes, - MaxGas: result.Genesis.ConsensusParams.Block.MaxGas, - TimeIotaMs: result.Genesis.ConsensusParams.Block.TimeIotaMs, - }, - Evidence: types.EvidenceParams{ - MaxAgeNumBlocks: result.Genesis.ConsensusParams.Evidence.MaxAgeNumBlocks, - MaxAgeDuration: result.Genesis.ConsensusParams.Evidence.MaxAgeDuration, - }, - Validator: types.ValidatorParams{ - PubKeyTypes: result.Genesis.ConsensusParams.Validator.PubKeyTypes, - }, - }, - AppHash: result.Genesis.AppHash, - AppState: result.Genesis.AppState, - }, - }, nil +func Genesis() (*core_types.ResultGenesis, error) { + return client.Genesis() } From b0f7c4ca259f011ecf8858284d00347feaf9005a Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 27 Aug 2020 16:15:13 +0300 Subject: [PATCH 182/426] add ControlAddress to /candidates --- api/v2/service/candidate.go | 13 +++++++------ go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/api/v2/service/candidate.go b/api/v2/service/candidate.go index 4d70545e3..71f2623bf 100644 --- a/api/v2/service/candidate.go +++ b/api/v2/service/candidate.go @@ -50,12 +50,13 @@ func (s *Service) Candidate(ctx context.Context, req *pb.CandidateRequest) (*pb. func makeResponseCandidate(state *state.CheckState, c *candidates.Candidate, includeStakes bool) *pb.CandidateResponse { candidate := &pb.CandidateResponse{ - RewardAddress: c.RewardAddress.String(), - OwnerAddress: c.OwnerAddress.String(), - TotalStake: state.Candidates().GetTotalStake(c.PubKey).String(), - PublicKey: c.PubKey.String(), - Commission: fmt.Sprintf("%d", c.Commission), - Status: fmt.Sprintf("%d", c.Status), + RewardAddress: c.RewardAddress.String(), + OwnerAddress: c.OwnerAddress.String(), + ControlAddress: c.ControlAddress.String(), + TotalStake: state.Candidates().GetTotalStake(c.PubKey).String(), + PublicKey: c.PubKey.String(), + Commission: fmt.Sprintf("%d", c.Commission), + Status: fmt.Sprintf("%d", c.Status), } if includeStakes { diff --git a/go.mod b/go.mod index abdc0fa1b..6239f2a87 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200827075149-9a899154bdc5 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200827131141-8b2620700577 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 90511aaf8..c076aaf0c 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200827075149-9a899154bdc5 h1:ALM3TTNVX9Tx65o1aZixOTZM7M20s/+qcLudCVU/tvc= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200827075149-9a899154bdc5/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200827131141-8b2620700577 h1:QFPT9LYNLLub4i3VdP7ipeoRMEELpfWSWoX7wbd+3GM= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200827131141-8b2620700577/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From dbab57f52d26311ee58aef8efd80b6bc2130eb83 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Fri, 28 Aug 2020 14:54:02 +0300 Subject: [PATCH 183/426] MN-520: add tests --- core/transaction/change_coin_owner_test.go | 30 ++ core/transaction/create_coin_test.go | 464 ++++++++++++++++++ core/transaction/edit_multisig_owners_test.go | 6 +- core/transaction/sell_all_coin_test.go | 207 ++++++++ core/transaction/send_test.go | 105 ++++ 5 files changed, 809 insertions(+), 3 deletions(-) diff --git a/core/transaction/change_coin_owner_test.go b/core/transaction/change_coin_owner_test.go index 30b7a4eb9..a35b0d4a7 100644 --- a/core/transaction/change_coin_owner_test.go +++ b/core/transaction/change_coin_owner_test.go @@ -127,6 +127,36 @@ func TestChangeOwnerTxWithWrongSymbol(t *testing.T) { } } +func TestChangeOwnerTxWithInsufficientFunds(t *testing.T) { + cState, err := state.NewState(0, db.NewMemDB(), nil, 1, 1) + if err != nil { + t.Fatalf("Cannot load state. Error %s", err) + } + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + + newOwnerPrivateKey, _ := crypto.GenerateKey() + newOwner := crypto.PubkeyToAddress(newOwnerPrivateKey.PublicKey) + + createTestCoinWithOwner(cState, addr) + + data := ChangeCoinOwnerData{ + Symbol: getTestCoinSymbol(), + NewOwner: newOwner, + } + + tx, err := makeTestChangeOwnerTx(data, privateKey) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, tx, big.NewInt(0), 500000, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} + func makeTestChangeOwnerTx(data ChangeCoinOwnerData, privateKey *ecdsa.PrivateKey) ([]byte, error) { encodedData, err := rlp.EncodeToBytes(data) if err != nil { diff --git a/core/transaction/create_coin_test.go b/core/transaction/create_coin_test.go index 8b50c63a9..eba8bcfa0 100644 --- a/core/transaction/create_coin_test.go +++ b/core/transaction/create_coin_test.go @@ -1,6 +1,8 @@ package transaction import ( + "encoding/binary" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/helpers" @@ -111,3 +113,465 @@ func TestCreateCoinTx(t *testing.T) { t.Fatalf("Target owner address is not correct. Expected %s, got %s", addr.String(), symbolInfo.OwnerAddress().String()) } } + +func TestCreateCoinWithIncorrectName(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + toCreate := types.StrToCoinSymbol("ABCDEF") + reserve := helpers.BipToPip(big.NewInt(10000)) + amount := helpers.BipToPip(big.NewInt(100)) + crr := uint(50) + + var name [65]byte + binary.BigEndian.PutUint64(name[:], 0) + + data := CreateCoinData{ + Name: string(name[:]), + Symbol: toCreate, + InitialAmount: amount, + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: big.NewInt(0).Mul(amount, big.NewInt(10)), + } + + encodedData, err := rlp.EncodeToBytes(data) + + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeCreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InvalidCoinName { + t.Fatalf("Response code is not %d. Error %s", code.InvalidCoinName, response.Log) + } +} + +func TestCreateCoinWithInvalidSymbol(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + toCreate := types.StrToCoinSymbol("ABC-DEF") + reserve := helpers.BipToPip(big.NewInt(10000)) + amount := helpers.BipToPip(big.NewInt(100)) + crr := uint(50) + name := "My Test Coin" + + data := CreateCoinData{ + Name: name, + Symbol: toCreate, + InitialAmount: amount, + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: big.NewInt(0).Mul(amount, big.NewInt(10)), + } + + encodedData, err := rlp.EncodeToBytes(data) + + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeCreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InvalidCoinSymbol { + t.Fatalf("Response code is not %d. Error %s", code.InvalidCoinSymbol, response.Log) + } +} + +func TestCreateCoinWithExistingSymbol(t *testing.T) { + cState := getState() + + createTestCoin(cState) + cState.Commit() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + toCreate := types.StrToCoinSymbol("TEST") + reserve := helpers.BipToPip(big.NewInt(10000)) + amount := helpers.BipToPip(big.NewInt(100)) + crr := uint(50) + name := "My Test Coin" + + data := CreateCoinData{ + Name: name, + Symbol: toCreate, + InitialAmount: amount, + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: big.NewInt(0).Mul(amount, big.NewInt(10)), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeCreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinAlreadyExists { + t.Fatalf("Response code is not %d. Error %s", code.CoinAlreadyExists, response.Log) + } +} + +func TestCreateCoinWithWrongCrr(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + toCreate := types.StrToCoinSymbol("ABCDEF") + reserve := helpers.BipToPip(big.NewInt(10000)) + amount := helpers.BipToPip(big.NewInt(100)) + crr := uint(9) + name := "My Test Coin" + + data := CreateCoinData{ + Name: name, + Symbol: toCreate, + InitialAmount: amount, + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: big.NewInt(0).Mul(amount, big.NewInt(10)), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeCreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.WrongCrr { + t.Fatalf("Response code is not %d. Error %s", code.WrongCrr, response.Log) + } + + data.ConstantReserveRatio = uint(101) + + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx = Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeCreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.WrongCrr { + t.Fatalf("Response code is not %d. Error %s", code.WrongCrr, response.Log) + } +} + +func TestCreateCoinWithWrongCoinSupply(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + toCreate := types.StrToCoinSymbol("ABCDEF") + reserve := helpers.BipToPip(big.NewInt(10000)) + crr := uint(50) + name := "My Test Coin" + + data := CreateCoinData{ + Name: name, + Symbol: toCreate, + InitialAmount: big.NewInt(1), + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: helpers.BipToPip(big.NewInt(100000)), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeCreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.WrongCoinSupply { + t.Fatalf("Response code is not %d. Error %s", code.WrongCoinSupply, response.Log) + } + + data.InitialAmount = helpers.BipToPip(big.NewInt(1000000)) + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx = Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeCreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.WrongCoinSupply { + t.Fatalf("Response code is not %d. Error %s", code.WrongCoinSupply, response.Log) + } + + data.MaxSupply = big.NewInt(0).Exp(big.NewInt(100), big.NewInt(15+18), nil) + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.WrongCoinSupply { + t.Fatalf("Response code is not %d. Error %s", code.WrongCoinSupply, response.Log) + } + + data.MaxSupply = maxCoinSupply + data.InitialReserve = helpers.BipToPip(big.NewInt(1000)) + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.WrongCoinSupply { + t.Fatalf("Response code is not %d. Error %s", code.WrongCoinSupply, response.Log) + } +} + +func TestCreateCoinGas(t *testing.T) { + data := CreateCoinData{ + Symbol: types.StrToCoinSymbol("ABC"), + } + + if data.Gas() != 1000000000 { + t.Fatal("Gas for symbol with length 3 is not correct.") + } + + data.Symbol = types.StrToCoinSymbol("ABCD") + if data.Gas() != 100000000 { + t.Fatal("Gas for symbol with length 4 is not correct.") + } + + data.Symbol = types.StrToCoinSymbol("ABCDE") + if data.Gas() != 10000000 { + t.Fatal("Gas for symbol with length 5 is not correct.") + } + + data.Symbol = types.StrToCoinSymbol("ABCDEF") + if data.Gas() != 1000000 { + t.Fatal("Gas for symbol with length 6 is not correct.") + } + + data.Symbol = types.StrToCoinSymbol("ABCDEFG") + if data.Gas() != 100000 { + t.Fatal("Gas for symbol with length 7 is not correct.") + } +} + +func TestCreateCoinWithInsufficientFundsForGas(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + coin := types.GetBaseCoinID() + + toCreate := types.StrToCoinSymbol("ABCDEF") + reserve := helpers.BipToPip(big.NewInt(10000)) + crr := uint(50) + name := "My Test Coin" + + data := CreateCoinData{ + Name: name, + Symbol: toCreate, + InitialAmount: helpers.BipToPip(big.NewInt(10)), + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: helpers.BipToPip(big.NewInt(100)), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeCreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} diff --git a/core/transaction/edit_multisig_owners_test.go b/core/transaction/edit_multisig_owners_test.go index b2298e371..bdbdc82c2 100644 --- a/core/transaction/edit_multisig_owners_test.go +++ b/core/transaction/edit_multisig_owners_test.go @@ -35,9 +35,9 @@ func TestEditMultisigOwnersTx(t *testing.T) { cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(initialBalance)) data := EditMultisigOwnersData{ - Threshold: 3, - Weights: []uint{2, 1, 2}, - Addresses: []types.Address{addr1, addr2, addr4}, + Threshold: 3, + Weights: []uint{2, 1, 2}, + Addresses: []types.Address{addr1, addr2, addr4}, } encodedData, err := rlp.EncodeToBytes(data) diff --git a/core/transaction/sell_all_coin_test.go b/core/transaction/sell_all_coin_test.go index cac8e7956..bbbd618ad 100644 --- a/core/transaction/sell_all_coin_test.go +++ b/core/transaction/sell_all_coin_test.go @@ -1,6 +1,7 @@ package transaction import ( + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/helpers" @@ -71,3 +72,209 @@ func TestSellAllCoinTx(t *testing.T) { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", getTestCoinSymbol(), targetTestBalance, testBalance) } } + +func TestSellAllCoinTxWithSameCoins(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + minValToBuy, _ := big.NewInt(0).SetString("151191152412701306252", 10) + data := SellAllCoinData{ + CoinToSell: coin, + CoinToBuy: coin, + MinimumValueToBuy: minValToBuy, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSellAllCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CrossConvert { + t.Fatalf("Response code is not %d. Error %s", code.CrossConvert, response.Log) + } +} + +func TestSellAllCoinTxWithInvalidCoins(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.CoinID(5) + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + minValToBuy, _ := big.NewInt(0).SetString("151191152412701306252", 10) + data := SellAllCoinData{ + CoinToSell: coin, + CoinToBuy: types.GetBaseCoinID(), + MinimumValueToBuy: minValToBuy, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeSellAllCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinNotExists { + t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) + } + + data.CoinToSell = types.GetBaseCoinID() + data.CoinToBuy = types.CoinID(5) + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinNotExists { + t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) + } +} + +func TestSellAllCoinTxWithMinimumValueToBuy(t *testing.T) { + cState := getState() + coinID := createTestCoin(cState) + privateKey, _ := crypto.GenerateKey() + coin := types.GetBaseCoinID() + + minValToBuy, _ := big.NewInt(0).SetString("151191152412701306252", 10) + data := SellAllCoinData{ + CoinToSell: coin, + CoinToBuy: coinID, + MinimumValueToBuy: minValToBuy, + } + + encodedData, err := rlp.EncodeToBytes(data) + + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSellAllCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.MinimumValueToBuyReached { + t.Fatalf("Response code is not %d. Error %s", code.MinimumValueToBuyReached, response.Log) + } +} + +func TestSellAllCoinTxWithInsufficientFunds(t *testing.T) { + cState := getState() + coinID := createTestCoin(cState) + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1))) + + minValToBuy, _ := big.NewInt(0).SetString("0", 10) + data := SellAllCoinData{ + CoinToSell: coinID, + CoinToBuy: coin, + MinimumValueToBuy: minValToBuy, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSellAllCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} diff --git a/core/transaction/send_test.go b/core/transaction/send_test.go index 8c840a1e4..8a5d7e0dc 100644 --- a/core/transaction/send_test.go +++ b/core/transaction/send_test.go @@ -207,3 +207,108 @@ func TestSendFailedMultisigTx(t *testing.T) { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", to.String(), targetTestBalance, testBalance) } } + +func TestSendWithNotExistedCoin(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + coin := types.CoinID(5) + + value := helpers.BipToPip(big.NewInt(10)) + to := types.Address([20]byte{1}) + + data := SendData{ + Coin: coin, + To: to, + Value: value, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeSend, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinNotExists { + t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) + } +} + +func TestSendTxWithCustomCoin(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := createTestCoin(cState) + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + value := helpers.BipToPip(big.NewInt(10)) + to := types.Address([20]byte{1}) + + data := SendData{ + Coin: coin, + To: to, + Value: value, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSend, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != 0 { + t.Fatalf("Response code is not 0. Error: %s", response.Log) + } + + targetBalance, _ := big.NewInt(0).SetString("999989998999999954999998", 10) + balance := cState.Accounts.GetBalance(addr, coin) + if balance.Cmp(targetBalance) != 0 { + t.Fatalf("Target %s balance is not correct. Expected %s, got %s", addr.String(), targetBalance, balance) + } + + targetTestBalance, _ := big.NewInt(0).SetString("10000000000000000000", 10) + testBalance := cState.Accounts.GetBalance(to, coin) + if testBalance.Cmp(targetTestBalance) != 0 { + t.Fatalf("Target %s balance is not correct. Expected %s, got %s", to.String(), targetTestBalance, testBalance) + } +} From 103cd9ba4a0d52cd42d226a8cdd1897ca11acbac Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 1 Sep 2020 10:43:10 +0300 Subject: [PATCH 184/426] transaction tests --- core/transaction/create_multisig_test.go | 256 ++++++++++++++ core/transaction/delegate.go | 4 +- core/transaction/delegate_test.go | 289 ++++++++++++++++ core/transaction/edit_candidate_test.go | 279 +++++++++++++++ core/transaction/edit_multisig_owners_test.go | 307 +++++++++++++++++ core/transaction/multisend.go | 13 - core/transaction/multisend_test.go | 224 ++++++++++++ core/transaction/recreate_coin_test.go | 322 ++++++++++++++++++ core/transaction/set_halt_block_test.go | 105 ++++++ core/transaction/switch_candidate_status.go | 9 - .../switch_candidate_status_test.go | 160 ++++++++- 11 files changed, 1941 insertions(+), 27 deletions(-) diff --git a/core/transaction/create_multisig_test.go b/core/transaction/create_multisig_test.go index 9e9a1addd..f7f90c9ae 100644 --- a/core/transaction/create_multisig_test.go +++ b/core/transaction/create_multisig_test.go @@ -2,6 +2,7 @@ package transaction import ( "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/state/accounts" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" @@ -266,3 +267,258 @@ func TestCreateExistingMultisigTx(t *testing.T) { t.Fatalf("Response code is not %d. Got %d", code.MultisigExists, response.Code) } } + +func TestCreateMultisigOwnersTxToNonExistenAddress(t *testing.T) { + cState := getState() + + addr := types.Address{0} + privateKey1, _ := crypto.GenerateKey() + addr1 := crypto.PubkeyToAddress(privateKey1.PublicKey) + privateKey2, _ := crypto.GenerateKey() + addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) + privateKey3, _ := crypto.GenerateKey() + addr3 := crypto.PubkeyToAddress(privateKey3.PublicKey) + + data := EditMultisigOwnersData{ + Threshold: 3, + Weights: []uint{2, 1, 2}, + Addresses: []types.Address{addr1, addr2, addr3}, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeEditMultisigOwner, + Data: encodedData, + SignatureType: SigTypeMulti, + } + + tx.SetMultisigAddress(addr) + + if err := tx.Sign(privateKey3); err != nil { + t.Fatal(err) + } + + checkState := state.NewCheckState(cState) + response := data.BasicCheck(&tx, checkState) + if response.Code != code.MultisigNotExists { + t.Fatalf("Response code is not %d. Error %s", code.MultisigNotExists, response.Log) + } +} + +func TestCreateMultisigOwnersTxToTooLargeOwnersList(t *testing.T) { + cState := getState() + + privateKey1, _ := crypto.GenerateKey() + addr1 := crypto.PubkeyToAddress(privateKey1.PublicKey) + privateKey2, _ := crypto.GenerateKey() + addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) + privateKey3, _ := crypto.GenerateKey() + addr3 := crypto.PubkeyToAddress(privateKey3.PublicKey) + + coin := types.GetBaseCoinID() + + weights := make([]uint, 33) + for i := uint(0); i <= 32; i++ { + weights[i] = i + } + + data := CreateMultisigData{ + Threshold: 3, + Weights: weights, + Addresses: []types.Address{addr1, addr2, addr3}, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeCreateMultisig, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey3); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.TooLargeOwnersList { + t.Fatalf("Response code is not %d. Error %s", code.TooLargeOwnersList, response.Log) + } +} + +func TestCreateMultisigOwnersTxIncorrectWeights(t *testing.T) { + cState := getState() + + privateKey1, _ := crypto.GenerateKey() + addr1 := crypto.PubkeyToAddress(privateKey1.PublicKey) + privateKey2, _ := crypto.GenerateKey() + addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) + privateKey3, _ := crypto.GenerateKey() + addr3 := crypto.PubkeyToAddress(privateKey3.PublicKey) + + data := CreateMultisigData{ + Threshold: 3, + Weights: []uint{1, 2, 3, 4}, + Addresses: []types.Address{addr1, addr2, addr3}, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeCreateMultisig, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey3); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.IncorrectWeights { + t.Fatalf("Response code is not %d. Error %s", code.IncorrectWeights, response.Log) + } + + data.Weights = []uint{1, 2, 1024} + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey3); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.IncorrectWeights { + t.Fatalf("Response code is not %d. Error %s", code.IncorrectWeights, response.Log) + } +} + +func TestCreateMultisigOwnersTxToAddressDuplication(t *testing.T) { + cState := getState() + + privateKey1, _ := crypto.GenerateKey() + addr1 := crypto.PubkeyToAddress(privateKey1.PublicKey) + privateKey3, _ := crypto.GenerateKey() + addr3 := crypto.PubkeyToAddress(privateKey3.PublicKey) + + data := CreateMultisigData{ + Threshold: 3, + Weights: []uint{1, 2, 3}, + Addresses: []types.Address{addr1, addr1, addr3}, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeCreateMultisig, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey3); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.DuplicatedAddresses { + t.Fatalf("Response code is not %d. Error %s", code.DuplicatedAddresses, response.Log) + } +} + +func TestCreateMultisigOwnersTxToInsufficientFunds(t *testing.T) { + cState := getState() + + privateKey1, _ := crypto.GenerateKey() + addr1 := crypto.PubkeyToAddress(privateKey1.PublicKey) + privateKey2, _ := crypto.GenerateKey() + addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) + privateKey3, _ := crypto.GenerateKey() + addr3 := crypto.PubkeyToAddress(privateKey3.PublicKey) + + data := CreateMultisigData{ + Threshold: 3, + Weights: []uint{1, 2, 3}, + Addresses: []types.Address{addr1, addr2, addr3}, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeCreateMultisig, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey3); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index ebdad638f..0dd0697dd 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -26,10 +26,10 @@ func (data DelegateData) BasicCheck(tx *Transaction, context *state.CheckState) Log: "Incorrect tx data"} } - if !context.Coins().Exists(tx.GasCoin) { + if !context.Coins().Exists(data.Coin) { return &Response{ Code: code.CoinNotExists, - Log: fmt.Sprintf("Coin %s not exists", tx.GasCoin)} + Log: fmt.Sprintf("Coin %d not exists", data.Coin)} } if data.Value.Cmp(types.Big0) < 1 { diff --git a/core/transaction/delegate_test.go b/core/transaction/delegate_test.go index 04e9e5249..75114d07c 100644 --- a/core/transaction/delegate_test.go +++ b/core/transaction/delegate_test.go @@ -1,6 +1,8 @@ package transaction import ( + "encoding/binary" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" @@ -157,3 +159,290 @@ func TestDelegateTxWithWatchlist(t *testing.T) { t.Fatalf("Waitlist is not deleted") } } + +func TestDelegateTxToNonExistenCoin(t *testing.T) { + cState := getState() + + pubkey := createTestCandidate(cState) + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + value := helpers.BipToPip(big.NewInt(100)) + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + data := DelegateData{ + PubKey: pubkey, + Coin: 5, + Value: value, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeDelegate, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinNotExists { + t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) + } +} + +func TestDelegateTxToPositiveStake(t *testing.T) { + cState := getState() + + pubkey := createTestCandidate(cState) + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + value := big.NewInt(0) + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + data := DelegateData{ + PubKey: pubkey, + Coin: coin, + Value: value, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeDelegate, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.StakeShouldBePositive { + t.Fatalf("Response code is not %d. Error %s", code.StakeShouldBePositive, response.Log) + } +} + +func TestDelegateTxToNonExistenCandidate(t *testing.T) { + cState := getState() + + pubkey := types.Pubkey{0} + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + value := helpers.BipToPip(big.NewInt(10000)) + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + data := DelegateData{ + PubKey: pubkey, + Coin: coin, + Value: value, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeDelegate, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CandidateNotFound { + t.Fatalf("Response code is not %d. Error %s", code.CandidateNotFound, response.Log) + } +} + +func TestDelegateTxToLowStake(t *testing.T) { + cState := getState() + + pubkey := createTestCandidate(cState) + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + value := helpers.BipToPip(big.NewInt(1000)) + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + for i := uint64(0); i < 1000; i++ { + var addr3 types.Address + binary.BigEndian.PutUint64(addr3[:], i) + cState.Candidates.Delegate(addr3, pubkey, coin, helpers.BipToPip(big.NewInt(12000)), helpers.BipToPip(big.NewInt(12000))) + } + + cState.Candidates.RecalculateStakes(0) + cState.Commit() + + data := DelegateData{ + PubKey: pubkey, + Coin: coin, + Value: value, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeDelegate, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.TooLowStake { + t.Fatalf("Response code is not %d. Error %s", code.TooLowStake, response.Log) + } +} + +func TestDelegateTxToInsufficientFunds(t *testing.T) { + cState := getState() + + pubkey := createTestCandidate(cState) + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + value := big.NewInt(1) + customCoin := createTestCoin(cState) + + data := DelegateData{ + PubKey: pubkey, + Coin: coin, + Value: value, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeDelegate, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } + + cState.Accounts.AddBalance(addr, coin, big.NewInt(2e17)) + + data.Coin = customCoin + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } + + data.Coin = coin + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} diff --git a/core/transaction/edit_candidate_test.go b/core/transaction/edit_candidate_test.go index 687d97be3..77feeaa2c 100644 --- a/core/transaction/edit_candidate_test.go +++ b/core/transaction/edit_candidate_test.go @@ -1,6 +1,7 @@ package transaction import ( + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/helpers" @@ -182,3 +183,281 @@ func TestEditCandidateNewPubKeyTx(t *testing.T) { t.Fatalf("ControlAddress has not changed") } } + +func TestEditCandidateTxToNonExistenCandidate(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + newRewardAddress := types.Address{1} + newOwnerAddress := types.Address{2} + newControlAddress := types.Address{3} + + data := EditCandidateData{ + PubKey: pubkey, + RewardAddress: newRewardAddress, + OwnerAddress: newOwnerAddress, + ControlAddress: newControlAddress, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditCandidate, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CandidateNotFound { + t.Fatalf("Response code is not %d. Error %s", code.CandidateNotFound, response.Log) + } +} + +func TestEditCandidateTxToCandidateOwnership(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + addr2 := types.Address{0} + coin := types.GetBaseCoinID() + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + cState.Candidates.Create(addr2, addr2, addr2, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + + newRewardAddress := types.Address{1} + newOwnerAddress := types.Address{2} + newControlAddress := types.Address{3} + + data := EditCandidateData{ + PubKey: pubkey, + RewardAddress: newRewardAddress, + OwnerAddress: newOwnerAddress, + ControlAddress: newControlAddress, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditCandidate, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.IsNotOwnerOfCandidate { + t.Fatalf("Response code is not %d. Error %s", code.IsNotOwnerOfCandidate, response.Log) + } +} + +func TestEditCandidateTxToNewPublicKey(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + + newRewardAddress := types.Address{1} + newOwnerAddress := types.Address{2} + newControlAddress := types.Address{3} + newPubKey := types.Pubkey(pubkey) + + data := EditCandidateData{ + PubKey: pubkey, + NewPubKey: &newPubKey, + RewardAddress: newRewardAddress, + OwnerAddress: newOwnerAddress, + ControlAddress: newControlAddress, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditCandidate, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.NewPublicKeyIsBad { + t.Fatalf("Response code is not %d. Error %s", code.NewPublicKeyIsBad, response.Log) + } +} + +func TestEditCandidateTxToInsufficientFunds(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + + newRewardAddress := types.Address{1} + newOwnerAddress := types.Address{2} + newControlAddress := types.Address{3} + + data := EditCandidateData{ + PubKey: pubkey, + RewardAddress: newRewardAddress, + OwnerAddress: newOwnerAddress, + ControlAddress: newControlAddress, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditCandidate, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} + +func TestEditCandidateTxToNewPublicKeyInBlockList(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + pubkey2 := types.Pubkey{1} + + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + cState.Candidates.AddToBlockPubKey(pubkey2) + + newRewardAddress := types.Address{1} + newOwnerAddress := types.Address{2} + newControlAddress := types.Address{3} + + data := EditCandidateData{ + PubKey: pubkey, + NewPubKey: &pubkey2, + RewardAddress: newRewardAddress, + OwnerAddress: newOwnerAddress, + ControlAddress: newControlAddress, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditCandidate, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.PublicKeyInBlockList { + t.Fatalf("Response code is not %d. Error %s", code.PublicKeyInBlockList, response.Log) + } +} diff --git a/core/transaction/edit_multisig_owners_test.go b/core/transaction/edit_multisig_owners_test.go index bdbdc82c2..89985b73e 100644 --- a/core/transaction/edit_multisig_owners_test.go +++ b/core/transaction/edit_multisig_owners_test.go @@ -1,6 +1,8 @@ package transaction import ( + "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/helpers" @@ -94,3 +96,308 @@ func TestEditMultisigOwnersTx(t *testing.T) { t.Fatalf("Threshold is not correct") } } + +func TestEditMultisigOwnersTxToNonExistenAddress(t *testing.T) { + cState := getState() + + addr := types.Address{0} + privateKey1, _ := crypto.GenerateKey() + addr1 := crypto.PubkeyToAddress(privateKey1.PublicKey) + privateKey2, _ := crypto.GenerateKey() + addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) + privateKey3, _ := crypto.GenerateKey() + addr3 := crypto.PubkeyToAddress(privateKey3.PublicKey) + + data := EditMultisigOwnersData{ + Threshold: 3, + Weights: []uint{2, 1, 2}, + Addresses: []types.Address{addr1, addr2, addr3}, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeEditMultisigOwner, + Data: encodedData, + SignatureType: SigTypeMulti, + } + + tx.SetMultisigAddress(addr) + + if err := tx.Sign(privateKey3); err != nil { + t.Fatal(err) + } + + checkState := state.NewCheckState(cState) + response := data.BasicCheck(&tx, checkState) + if response.Code != code.MultisigNotExists { + t.Fatalf("Response code is not %d. Error %s", code.MultisigNotExists, response.Log) + } +} + +func TestEditMultisigOwnersTxToTooLargeOwnersList(t *testing.T) { + cState := getState() + + addr := types.Address{0} + privateKey1, _ := crypto.GenerateKey() + addr1 := crypto.PubkeyToAddress(privateKey1.PublicKey) + privateKey2, _ := crypto.GenerateKey() + addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) + privateKey3, _ := crypto.GenerateKey() + addr3 := crypto.PubkeyToAddress(privateKey3.PublicKey) + + coin := types.GetBaseCoinID() + + cState.Accounts.CreateMultisig([]uint{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + + weights := make([]uint, 33) + for i := uint(0); i <= 32; i++ { + weights[i] = i + } + + data := EditMultisigOwnersData{ + Threshold: 3, + Weights: weights, + Addresses: []types.Address{addr1, addr2, addr3}, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditMultisigOwner, + Data: encodedData, + SignatureType: SigTypeMulti, + } + + tx.SetMultisigAddress(addr) + + if err := tx.Sign(privateKey3); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.TooLargeOwnersList { + t.Fatalf("Response code is not %d. Error %s", code.TooLargeOwnersList, response.Log) + } +} + +func TestEditMultisigOwnersTxIncorrectWeights(t *testing.T) { + cState := getState() + + addr := types.Address{0} + privateKey1, _ := crypto.GenerateKey() + addr1 := crypto.PubkeyToAddress(privateKey1.PublicKey) + privateKey2, _ := crypto.GenerateKey() + addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) + privateKey3, _ := crypto.GenerateKey() + addr3 := crypto.PubkeyToAddress(privateKey3.PublicKey) + + coin := types.GetBaseCoinID() + + cState.Accounts.CreateMultisig([]uint{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + + data := EditMultisigOwnersData{ + Threshold: 3, + Weights: []uint{1, 2, 3, 4}, + Addresses: []types.Address{addr1, addr2, addr3}, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditMultisigOwner, + Data: encodedData, + SignatureType: SigTypeMulti, + } + + tx.SetMultisigAddress(addr) + + if err := tx.Sign(privateKey3); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.IncorrectWeights { + t.Fatalf("Response code is not %d. Error %s", code.IncorrectWeights, response.Log) + } + + data.Weights = []uint{1, 2, 1024} + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey3); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.IncorrectWeights { + t.Fatalf("Response code is not %d. Error %s", code.IncorrectWeights, response.Log) + } + + data.Weights = []uint{1, 2, 3} + data.Threshold = 7 + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey3); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.IncorrectWeights { + t.Fatalf("Response code is not %d. Error %s", code.IncorrectWeights, response.Log) + } +} + +func TestEditMultisigOwnersTxToAddressDuplication(t *testing.T) { + cState := getState() + + addr := types.Address{0} + privateKey1, _ := crypto.GenerateKey() + addr1 := crypto.PubkeyToAddress(privateKey1.PublicKey) + privateKey2, _ := crypto.GenerateKey() + addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) + privateKey3, _ := crypto.GenerateKey() + addr3 := crypto.PubkeyToAddress(privateKey3.PublicKey) + + coin := types.GetBaseCoinID() + + cState.Accounts.CreateMultisig([]uint{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + + data := EditMultisigOwnersData{ + Threshold: 3, + Weights: []uint{1, 2, 3}, + Addresses: []types.Address{addr1, addr1, addr3}, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditMultisigOwner, + Data: encodedData, + SignatureType: SigTypeMulti, + } + + tx.SetMultisigAddress(addr) + + if err := tx.Sign(privateKey3); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.DuplicatedAddresses { + t.Fatalf("Response code is not %d. Error %s", code.DuplicatedAddresses, response.Log) + } +} + +func TestEditMultisigOwnersTxToInsufficientFunds(t *testing.T) { + cState := getState() + + addr := types.Address{0} + privateKey1, _ := crypto.GenerateKey() + addr1 := crypto.PubkeyToAddress(privateKey1.PublicKey) + privateKey2, _ := crypto.GenerateKey() + addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) + privateKey3, _ := crypto.GenerateKey() + addr3 := crypto.PubkeyToAddress(privateKey3.PublicKey) + + coin := types.GetBaseCoinID() + + cState.Accounts.CreateMultisig([]uint{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + + data := EditMultisigOwnersData{ + Threshold: 3, + Weights: []uint{1, 2, 3}, + Addresses: []types.Address{addr1, addr2, addr3}, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditMultisigOwner, + Data: encodedData, + SignatureType: SigTypeMulti, + } + + tx.SetMultisigAddress(addr) + + if err := tx.Sign(privateKey3); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} diff --git a/core/transaction/multisend.go b/core/transaction/multisend.go index 8e7ca4fec..770a73a0e 100644 --- a/core/transaction/multisend.go +++ b/core/transaction/multisend.go @@ -2,7 +2,6 @@ package transaction import ( "encoding/hex" - "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" @@ -47,18 +46,6 @@ type MultisendDataItem struct { Value *big.Int } -func (item MultisendDataItem) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - Coin string `json:"coin"` - To string `json:"to"` - Value string `json:"value"` - }{ - Coin: item.Coin.String(), - To: item.To.String(), - Value: item.Value.String(), - }) -} - func (data MultisendData) String() string { return fmt.Sprintf("MULTISEND") } diff --git a/core/transaction/multisend_test.go b/core/transaction/multisend_test.go index 4baef31ba..7a7199523 100644 --- a/core/transaction/multisend_test.go +++ b/core/transaction/multisend_test.go @@ -1,6 +1,7 @@ package transaction import ( + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/helpers" @@ -76,3 +77,226 @@ func TestMultisendTx(t *testing.T) { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", to.String(), targetTestBalance, testBalance) } } + +func TestMultisendTxToInvalidDataLength(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + coin := types.GetBaseCoinID() + + data := MultisendData{ + List: nil, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + GasCoin: coin, + ChainID: types.CurrentChainID, + Type: TypeMultisend, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InvalidMultisendData { + t.Fatalf("Response code is not %d. Error %s", code.InvalidMultisendData, response.Log) + } + + list := make([]MultisendDataItem, 101) + for i := 0; i <= 100; i++ { + list[i] = MultisendDataItem{ + Coin: types.GetBaseCoinID(), + To: [20]byte{1}, + Value: helpers.BipToPip(big.NewInt(10)), + } + } + + data.List = list + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InvalidMultisendData { + t.Fatalf("Response code is not %d. Error %s", code.InvalidMultisendData, response.Log) + } +} + +func TestMultisendTxToInsufficientFunds(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + coin := types.GetBaseCoinID() + + value := helpers.BipToPip(big.NewInt(10)) + to := types.Address([20]byte{1}) + + data := MultisendData{ + List: []MultisendDataItem{ + { + Coin: coin, + To: to, + Value: value, + }, + }, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + GasCoin: coin, + ChainID: types.CurrentChainID, + Type: TypeMultisend, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} + +func TestMultisendToInvalidCoin(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.CoinID(5) + + cState.Accounts.AddBalance(addr, types.GetBaseCoinID(), helpers.BipToPip(big.NewInt(1000000))) + + value := helpers.BipToPip(big.NewInt(10)) + to := types.Address([20]byte{1}) + + data := MultisendData{ + List: []MultisendDataItem{ + { + Coin: coin, + To: to, + Value: value, + }, + }, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + GasCoin: types.GetBaseCoinID(), + ChainID: types.CurrentChainID, + Type: TypeMultisend, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinNotExists { + t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) + } +} + +func TestMultisendToInsufficientReserve(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.CoinID(5) + + cState.Accounts.AddBalance(addr, types.GetBaseCoinID(), helpers.BipToPip(big.NewInt(1000000))) + + value := helpers.BipToPip(big.NewInt(10)) + to := types.Address([20]byte{1}) + + data := MultisendData{ + List: []MultisendDataItem{ + { + Coin: coin, + To: to, + Value: value, + }, + }, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + GasCoin: types.GetBaseCoinID(), + ChainID: types.CurrentChainID, + Type: TypeMultisend, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinNotExists { + t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) + } +} diff --git a/core/transaction/recreate_coin_test.go b/core/transaction/recreate_coin_test.go index e3259e52b..f0a0b05df 100644 --- a/core/transaction/recreate_coin_test.go +++ b/core/transaction/recreate_coin_test.go @@ -2,6 +2,7 @@ package transaction import ( "crypto/ecdsa" + "encoding/binary" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" @@ -171,6 +172,327 @@ func TestRecreateCoinTxWithWrongSymbol(t *testing.T) { } } +func TestRecreateCoinWithIncorrectName(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + toCreate := types.StrToCoinSymbol("ABCDEF") + reserve := helpers.BipToPip(big.NewInt(10000)) + amount := helpers.BipToPip(big.NewInt(100)) + crr := uint(50) + + var name [65]byte + binary.BigEndian.PutUint64(name[:], 0) + + data := RecreateCoinData{ + Name: string(name[:]), + Symbol: toCreate, + InitialAmount: amount, + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: big.NewInt(0).Mul(amount, big.NewInt(10)), + } + + encodedData, err := rlp.EncodeToBytes(data) + + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeRecreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InvalidCoinName { + t.Fatalf("Response code is not %d. Error %s", code.InvalidCoinName, response.Log) + } +} + +func TestRecreateCoinWithWrongCrr(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + toCreate := types.StrToCoinSymbol("ABCDEF") + reserve := helpers.BipToPip(big.NewInt(10000)) + amount := helpers.BipToPip(big.NewInt(100)) + crr := uint(9) + name := "My Test Coin" + + data := RecreateCoinData{ + Name: name, + Symbol: toCreate, + InitialAmount: amount, + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: big.NewInt(0).Mul(amount, big.NewInt(10)), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeRecreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.WrongCrr { + t.Fatalf("Response code is not %d. Error %s", code.WrongCrr, response.Log) + } + + data.ConstantReserveRatio = uint(101) + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx = Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeRecreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.WrongCrr { + t.Fatalf("Response code is not %d. Error %s", code.WrongCrr, response.Log) + } +} + +func TestRecreateCoinWithWrongCoinSupply(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + toCreate := types.StrToCoinSymbol("ABCDEF") + reserve := helpers.BipToPip(big.NewInt(10000)) + crr := uint(50) + name := "My Test Coin" + + data := RecreateCoinData{ + Name: name, + Symbol: toCreate, + InitialAmount: big.NewInt(1), + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: helpers.BipToPip(big.NewInt(100000)), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeRecreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.WrongCoinSupply { + t.Fatalf("Response code is not %d. Error %s", code.WrongCoinSupply, response.Log) + } + + data.InitialAmount = helpers.BipToPip(big.NewInt(1000000)) + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx = Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeRecreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.WrongCoinSupply { + t.Fatalf("Response code is not %d. Error %s", code.WrongCoinSupply, response.Log) + } + + data.MaxSupply = big.NewInt(0).Exp(big.NewInt(100), big.NewInt(15+18), nil) + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.WrongCoinSupply { + t.Fatalf("Response code is not %d. Error %s", code.WrongCoinSupply, response.Log) + } + + data.MaxSupply = maxCoinSupply + data.InitialReserve = helpers.BipToPip(big.NewInt(1000)) + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.WrongCoinSupply { + t.Fatalf("Response code is not %d. Error %s", code.WrongCoinSupply, response.Log) + } +} + +func TestRecreateCoinWithInsufficientFundsForGas(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + createTestCoinWithOwner(cState, crypto.PubkeyToAddress(privateKey.PublicKey)) + cState.Commit() + + coin := types.GetBaseCoinID() + + toCreate := types.StrToCoinSymbol("TEST") + reserve := helpers.BipToPip(big.NewInt(10000)) + crr := uint(50) + name := "My Test Coin" + + data := RecreateCoinData{ + Name: name, + Symbol: toCreate, + InitialAmount: helpers.BipToPip(big.NewInt(10)), + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: helpers.BipToPip(big.NewInt(100)), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeRecreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} + func makeTestRecreateCoinTx(data RecreateCoinData, privateKey *ecdsa.PrivateKey) ([]byte, error) { encodedData, err := rlp.EncodeToBytes(data) if err != nil { diff --git a/core/transaction/set_halt_block_test.go b/core/transaction/set_halt_block_test.go index c24a329cd..a88121599 100644 --- a/core/transaction/set_halt_block_test.go +++ b/core/transaction/set_halt_block_test.go @@ -210,3 +210,108 @@ func TestSetHaltBlockTxWithWrongOwnership(t *testing.T) { t.Fatalf("Halts found at height: %d", haltHeight) } } + +func TestSetHaltBlockTxToNonExistenCandidate(t *testing.T) { + cState, err := state.NewState(500000, db.NewMemDB(), nil, 1, 1) + if err != nil { + t.Fatalf("Cannot load state. Error %s", err) + } + + haltHeight := 500000 + uint64(100) + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1))) + + data := SetHaltBlockData{ + PubKey: pubkey, + Height: haltHeight, + } + + encodedData, err := rlp.EncodeToBytes(data) + + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSetHaltBlock, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 500000, &sync.Map{}, 0) + if response.Code != code.CandidateNotFound { + t.Fatalf("Response code is not %d. Error %s", code.CandidateNotFound, response.Log) + } +} + +func TestSetHaltBlockTxToInsufficientFunds(t *testing.T) { + cState, err := state.NewState(500000, db.NewMemDB(), nil, 1, 1) + if err != nil { + t.Fatalf("Cannot load state. Error %s", err) + } + + haltHeight := 500000 + uint64(100) + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + + data := SetHaltBlockData{ + PubKey: pubkey, + Height: haltHeight, + } + + encodedData, err := rlp.EncodeToBytes(data) + + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSetHaltBlock, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 500000, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index e86d02a8b..c2c1f18c6 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -2,7 +2,6 @@ package transaction import ( "encoding/hex" - "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" @@ -116,14 +115,6 @@ type SetCandidateOffData struct { PubKey types.Pubkey `json:"pub_key"` } -func (data SetCandidateOffData) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - PubKey string `json:"pub_key"` - }{ - PubKey: data.PubKey.String(), - }) -} - func (data SetCandidateOffData) GetPubKey() types.Pubkey { return data.PubKey } diff --git a/core/transaction/switch_candidate_status_test.go b/core/transaction/switch_candidate_status_test.go index f0c221206..45611b3bb 100644 --- a/core/transaction/switch_candidate_status_test.go +++ b/core/transaction/switch_candidate_status_test.go @@ -1,6 +1,7 @@ package transaction import ( + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/state/candidates" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" @@ -30,7 +31,6 @@ func TestSwitchCandidateStatusTx(t *testing.T) { } encodedData, err := rlp.EncodeToBytes(data) - if err != nil { t.Fatal(err) } @@ -50,13 +50,11 @@ func TestSwitchCandidateStatusTx(t *testing.T) { } encodedTx, err := rlp.EncodeToBytes(tx) - if err != nil { t.Fatal(err) } response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) - if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) } @@ -77,3 +75,159 @@ func TestSwitchCandidateStatusTx(t *testing.T) { t.Fatalf("Status has not changed") } } + +func TestSetCandidateOffTx(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pubkey := types.Pubkey{} + rand.Read(pubkey[:]) + + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + + data := SetCandidateOffData{ + PubKey: pubkey, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSetCandidateOffline, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != 0 { + t.Fatalf("Response code is not 0. Error %s", response.Log) + } + + targetBalance, _ := big.NewInt(0).SetString("999999900000000000000000", 10) + balance := cState.Accounts.GetBalance(addr, coin) + if balance.Cmp(targetBalance) != 0 { + t.Fatalf("Target %s balance is not correct. Expected %s, got %s", coin, targetBalance, balance) + } + + candidate := cState.Candidates.GetCandidate(pubkey) + + if candidate == nil { + t.Fatalf("Candidate not found") + } + + if candidate.Status != candidates.CandidateStatusOffline { + t.Fatalf("Status has not changed") + } +} + +func TestSwitchCandidateStatusTxToNonExistenCandidate(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pubkey := types.Pubkey{} + rand.Read(pubkey[:]) + + data := SetCandidateOnData{ + PubKey: pubkey, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSetCandidateOnline, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CandidateNotFound { + t.Fatalf("Response code is not %d. Error %s", code.CandidateNotFound, response.Log) + } +} + +func TestSwitchCandidateStatusTxToCandidateOwnership(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + addr2 := types.Address{0} + coin := types.GetBaseCoinID() + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pubkey := types.Pubkey{} + rand.Read(pubkey[:]) + + cState.Candidates.Create(addr2, addr2, addr2, pubkey, 10) + + data := SetCandidateOnData{ + PubKey: pubkey, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSetCandidateOnline, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.IsNotOwnerOfCandidate { + t.Fatalf("Response code is not %d. Error %s", code.IsNotOwnerOfCandidate, response.Log) + } +} From b9000d232836bd6f82d0b21465e68515e2302af2 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 1 Sep 2020 14:02:36 +0300 Subject: [PATCH 185/426] tx tests --- core/transaction/declare_candidacy_test.go | 311 ++++++++ core/transaction/redeem_check_test.go | 781 +++++++++++++++++++++ core/transaction/unbond_test.go | 316 +++++++++ 3 files changed, 1408 insertions(+) diff --git a/core/transaction/declare_candidacy_test.go b/core/transaction/declare_candidacy_test.go index 81215792f..9d21d2018 100644 --- a/core/transaction/declare_candidacy_test.go +++ b/core/transaction/declare_candidacy_test.go @@ -2,6 +2,7 @@ package transaction import ( "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/state/candidates" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/core/validators" @@ -259,5 +260,315 @@ func TestDeclareCandidacyTxWithBlockPybKey(t *testing.T) { if candidate.ControlAddress == addr { t.Fatalf("ControlAddress has changed") } +} + +func TestDeclareCandidacyToNonExistenCoin(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + + coin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pkey, _ := crypto.GenerateKey() + publicKeyBytes := crypto.FromECDSAPub(&pkey.PublicKey)[:32] + var publicKey types.Pubkey + copy(publicKey[:], publicKeyBytes) + + commission := uint(10) + + data := DeclareCandidacyData{ + Address: addr, + PubKey: publicKey, + Commission: commission, + Coin: 5, + Stake: helpers.BipToPip(big.NewInt(100)), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeDeclareCandidacy, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinNotExists { + t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) + } +} + +func TestDeclareCandidacyToExistenCandidate(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + + coin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pkey, _ := crypto.GenerateKey() + publicKeyBytes := crypto.FromECDSAPub(&pkey.PublicKey)[:32] + var publicKey types.Pubkey + copy(publicKey[:], publicKeyBytes) + + cState.Candidates.Create(addr, addr, addr, publicKey, uint(10)) + + commission := uint(10) + + data := DeclareCandidacyData{ + Address: addr, + PubKey: publicKey, + Commission: commission, + Coin: coin, + Stake: helpers.BipToPip(big.NewInt(100)), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeDeclareCandidacy, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CandidateExists { + t.Fatalf("Response code is not %d. Error %s", code.CandidateExists, response.Log) + } +} + +func TestDeclareCandidacyToDecodeError(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + + coin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pkey, _ := crypto.GenerateKey() + publicKeyBytes := crypto.FromECDSAPub(&pkey.PublicKey)[:32] + var publicKey types.Pubkey + copy(publicKey[:], publicKeyBytes) + commission := uint(10) + + data := DeclareCandidacyData{ + Address: addr, + PubKey: publicKey, + Commission: commission, + Coin: 5, + Stake: nil, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeDeclareCandidacy, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + response := data.Run(&tx, state.NewCheckState(cState), nil, 0) + if response.Code != code.DecodeError { + t.Fatalf("Response code is not %d. Error %s", code.DecodeError, response.Log) + } +} + +func TestDeclareCandidacyToWrongCommission(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + + coin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pkey, _ := crypto.GenerateKey() + publicKeyBytes := crypto.FromECDSAPub(&pkey.PublicKey)[:32] + var publicKey types.Pubkey + copy(publicKey[:], publicKeyBytes) + + data := DeclareCandidacyData{ + Address: addr, + PubKey: publicKey, + Commission: maxCommission + 1, + Coin: coin, + Stake: helpers.BipToPip(big.NewInt(100)), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeDeclareCandidacy, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.WrongCommission { + t.Fatalf("Response code is not %d. Error %s", code.WrongCommission, response.Log) + } +} + +func TestDeclareCandidacyToInsufficientFunds(t *testing.T) { + cState := getState() + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + stake := big.NewInt(1e18) + + pkey, _ := crypto.GenerateKey() + publicKeyBytes := crypto.FromECDSAPub(&pkey.PublicKey)[:32] + var publicKey types.Pubkey + copy(publicKey[:], publicKeyBytes) + + data := DeclareCandidacyData{ + Address: addr, + PubKey: publicKey, + Commission: uint(10), + Coin: coin, + Stake: stake, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeDeclareCandidacy, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } + + cState.Accounts.AddBalance(addr, coin, stake) + cState.Commit() + + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } + + cState.Accounts.SetBalance(addr, coin, new(big.Int).Mul(big.NewInt(1e18), big.NewInt(10))) + cState.Commit() + + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } } diff --git a/core/transaction/redeem_check_test.go b/core/transaction/redeem_check_test.go index d1039e6dc..1dcb39ebb 100644 --- a/core/transaction/redeem_check_test.go +++ b/core/transaction/redeem_check_test.go @@ -3,6 +3,8 @@ package transaction import ( "crypto/sha256" c "github.com/MinterTeam/minter-go-node/core/check" + "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/crypto/sha3" @@ -116,3 +118,782 @@ func TestRedeemCheckTx(t *testing.T) { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", coin, checkValue, balance) } } + +func TestRedeemCheckTxToDecodeError(t *testing.T) { + cState := getState() + coin := types.GetBaseCoinID() + + senderPrivateKey, _ := crypto.GenerateKey() + senderAddr := crypto.PubkeyToAddress(senderPrivateKey.PublicKey) + cState.Accounts.AddBalance(senderAddr, coin, helpers.BipToPip(big.NewInt(1000000))) + + receiverPrivateKey, _ := crypto.GenerateKey() + receiverAddr := crypto.PubkeyToAddress(receiverPrivateKey.PublicKey) + + passphrase := "password" + passphraseHash := sha256.Sum256([]byte(passphrase)) + passphrasePk, err := crypto.ToECDSA(passphraseHash[:]) + + if err != nil { + t.Fatal(err) + } + + checkValue := helpers.BipToPip(big.NewInt(10)) + + check := c.Check{ + Nonce: []byte{1, 2, 3}, + ChainID: types.CurrentChainID, + DueBlock: 1, + Coin: coin, + Value: checkValue, + GasCoin: types.GetBaseCoinID(), + } + + lock, err := crypto.Sign(check.HashWithoutLock().Bytes(), passphrasePk) + + if err != nil { + t.Fatal(err) + } + + check.Lock = big.NewInt(0).SetBytes(lock) + + err = check.Sign(senderPrivateKey) + + if err != nil { + t.Fatal(err) + } + + var senderAddressHash types.Hash + hw := sha3.NewKeccak256() + _ = rlp.Encode(hw, []interface{}{ + receiverAddr, + }) + hw.Sum(senderAddressHash[:0]) + + sig, err := crypto.Sign(senderAddressHash.Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + proof := [65]byte{} + copy(proof[:], sig) + + data := RedeemCheckData{ + Proof: proof, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeRedeemCheck, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(receiverPrivateKey); err != nil { + t.Fatal(err) + } + + response := data.BasicCheck(&tx, state.NewCheckState(cState)) + if response.Code != code.DecodeError { + t.Fatalf("Response code is not %d. Error %s", code.DecodeError, response.Log) + } + + data.RawCheck = []byte{0} + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx.Data = encodedData + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + txResponse := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if txResponse.Code != code.DecodeError { + t.Fatalf("Response code is not %d. Error %s", code.DecodeError, response.Log) + } +} + +func TestRedeemCheckTxToHighGasPrice(t *testing.T) { + cState := getState() + coin := types.GetBaseCoinID() + + senderPrivateKey, _ := crypto.GenerateKey() + senderAddr := crypto.PubkeyToAddress(senderPrivateKey.PublicKey) + cState.Accounts.AddBalance(senderAddr, coin, helpers.BipToPip(big.NewInt(1000000))) + + receiverPrivateKey, _ := crypto.GenerateKey() + receiverAddr := crypto.PubkeyToAddress(receiverPrivateKey.PublicKey) + + passphrase := "password" + passphraseHash := sha256.Sum256([]byte(passphrase)) + passphrasePk, err := crypto.ToECDSA(passphraseHash[:]) + + if err != nil { + t.Fatal(err) + } + + checkValue := helpers.BipToPip(big.NewInt(10)) + + check := c.Check{ + Nonce: []byte{1, 2, 3}, + ChainID: types.CurrentChainID, + DueBlock: 1, + Coin: coin, + Value: checkValue, + GasCoin: types.GetBaseCoinID(), + } + + lock, err := crypto.Sign(check.HashWithoutLock().Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + check.Lock = big.NewInt(0).SetBytes(lock) + + err = check.Sign(senderPrivateKey) + if err != nil { + t.Fatal(err) + } + + rawCheck, _ := rlp.EncodeToBytes(check) + + var senderAddressHash types.Hash + hw := sha3.NewKeccak256() + _ = rlp.Encode(hw, []interface{}{ + receiverAddr, + }) + hw.Sum(senderAddressHash[:0]) + + sig, err := crypto.Sign(senderAddressHash.Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + proof := [65]byte{} + copy(proof[:], sig) + + data := RedeemCheckData{ + RawCheck: rawCheck, + Proof: proof, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 2, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeRedeemCheck, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(receiverPrivateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.TooHighGasPrice { + t.Fatalf("Response code is not %d. Error %s", code.TooHighGasPrice, response.Log) + } +} + +func TestRedeemCheckTxToWrongChainID(t *testing.T) { + cState := getState() + coin := types.GetBaseCoinID() + + senderPrivateKey, _ := crypto.GenerateKey() + senderAddr := crypto.PubkeyToAddress(senderPrivateKey.PublicKey) + cState.Accounts.AddBalance(senderAddr, coin, helpers.BipToPip(big.NewInt(1000000))) + + receiverPrivateKey, _ := crypto.GenerateKey() + receiverAddr := crypto.PubkeyToAddress(receiverPrivateKey.PublicKey) + + passphrase := "password" + passphraseHash := sha256.Sum256([]byte(passphrase)) + passphrasePk, err := crypto.ToECDSA(passphraseHash[:]) + + if err != nil { + t.Fatal(err) + } + + checkValue := helpers.BipToPip(big.NewInt(10)) + + check := c.Check{ + Nonce: []byte{1, 2, 3}, + ChainID: types.ChainTestnet, + DueBlock: 1, + Coin: coin, + Value: checkValue, + GasCoin: types.GetBaseCoinID(), + } + + lock, err := crypto.Sign(check.HashWithoutLock().Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + check.Lock = big.NewInt(0).SetBytes(lock) + + err = check.Sign(senderPrivateKey) + if err != nil { + t.Fatal(err) + } + + rawCheck, _ := rlp.EncodeToBytes(check) + + var senderAddressHash types.Hash + hw := sha3.NewKeccak256() + _ = rlp.Encode(hw, []interface{}{ + receiverAddr, + }) + hw.Sum(senderAddressHash[:0]) + + sig, err := crypto.Sign(senderAddressHash.Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + proof := [65]byte{} + copy(proof[:], sig) + + data := RedeemCheckData{ + RawCheck: rawCheck, + Proof: proof, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeRedeemCheck, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(receiverPrivateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.WrongChainID { + t.Fatalf("Response code is not %d. Error %s", code.WrongChainID, response.Log) + } +} + +func TestRedeemCheckTxToNonceLength(t *testing.T) { + cState := getState() + coin := types.GetBaseCoinID() + + senderPrivateKey, _ := crypto.GenerateKey() + senderAddr := crypto.PubkeyToAddress(senderPrivateKey.PublicKey) + cState.Accounts.AddBalance(senderAddr, coin, helpers.BipToPip(big.NewInt(1000000))) + + receiverPrivateKey, _ := crypto.GenerateKey() + receiverAddr := crypto.PubkeyToAddress(receiverPrivateKey.PublicKey) + + passphrase := "password" + passphraseHash := sha256.Sum256([]byte(passphrase)) + passphrasePk, err := crypto.ToECDSA(passphraseHash[:]) + + if err != nil { + t.Fatal(err) + } + + checkValue := helpers.BipToPip(big.NewInt(10)) + + check := c.Check{ + Nonce: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, + ChainID: types.CurrentChainID, + DueBlock: 1, + Coin: coin, + Value: checkValue, + GasCoin: types.GetBaseCoinID(), + } + + lock, err := crypto.Sign(check.HashWithoutLock().Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + check.Lock = big.NewInt(0).SetBytes(lock) + + err = check.Sign(senderPrivateKey) + if err != nil { + t.Fatal(err) + } + + rawCheck, _ := rlp.EncodeToBytes(check) + + var senderAddressHash types.Hash + hw := sha3.NewKeccak256() + _ = rlp.Encode(hw, []interface{}{ + receiverAddr, + }) + hw.Sum(senderAddressHash[:0]) + + sig, err := crypto.Sign(senderAddressHash.Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + proof := [65]byte{} + copy(proof[:], sig) + + data := RedeemCheckData{ + RawCheck: rawCheck, + Proof: proof, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeRedeemCheck, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(receiverPrivateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.TooLongNonce { + t.Fatalf("Response code is not %d. Error %s", code.TooLongNonce, response.Log) + } +} + +func TestRedeemCheckTxToCheckData(t *testing.T) { + cState := getState() + coin := types.GetBaseCoinID() + + senderPrivateKey, _ := crypto.GenerateKey() + senderAddr := crypto.PubkeyToAddress(senderPrivateKey.PublicKey) + cState.Accounts.AddBalance(senderAddr, coin, helpers.BipToPip(big.NewInt(1000000))) + + receiverPrivateKey, _ := crypto.GenerateKey() + receiverAddr := crypto.PubkeyToAddress(receiverPrivateKey.PublicKey) + + passphrase := "password" + passphraseHash := sha256.Sum256([]byte(passphrase)) + passphrasePk, err := crypto.ToECDSA(passphraseHash[:]) + + if err != nil { + t.Fatal(err) + } + + checkValue := helpers.BipToPip(big.NewInt(10)) + + check := c.Check{ + Nonce: []byte{1, 2, 3}, + ChainID: types.CurrentChainID, + DueBlock: 1, + Coin: 5, + Value: checkValue, + GasCoin: types.GetBaseCoinID(), + } + + lock, err := crypto.Sign(check.HashWithoutLock().Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + check.Lock = big.NewInt(0).SetBytes(lock) + + err = check.Sign(senderPrivateKey) + if err != nil { + t.Fatal(err) + } + + rawCheck, _ := rlp.EncodeToBytes(check) + + var senderAddressHash types.Hash + hw := sha3.NewKeccak256() + _ = rlp.Encode(hw, []interface{}{ + receiverAddr, + }) + hw.Sum(senderAddressHash[:0]) + + sig, err := crypto.Sign(senderAddressHash.Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + proof := [65]byte{} + copy(proof[:], sig) + + data := RedeemCheckData{ + RawCheck: rawCheck, + Proof: proof, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeRedeemCheck, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(receiverPrivateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinNotExists { + t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) + } + + check.Coin = coin + check.GasCoin = 5 + lock, err = crypto.Sign(check.HashWithoutLock().Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + check.Lock = big.NewInt(0).SetBytes(lock) + err = check.Sign(senderPrivateKey) + if err != nil { + t.Fatal(err) + } + + rawCheck, _ = rlp.EncodeToBytes(check) + data = RedeemCheckData{ + RawCheck: rawCheck, + Proof: proof, + } + + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx.Data = encodedData + if err := tx.Sign(receiverPrivateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinNotExists { + t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) + } + + check.GasCoin = coin + lock, err = crypto.Sign(check.HashWithoutLock().Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + check.Lock = big.NewInt(0).SetBytes(lock) + err = check.Sign(senderPrivateKey) + if err != nil { + t.Fatal(err) + } + + rawCheck, _ = rlp.EncodeToBytes(check) + data.RawCheck = rawCheck + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + customCoin := createTestCoin(cState) + tx.GasCoin = customCoin + tx.Data = encodedData + if err := tx.Sign(receiverPrivateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.WrongGasCoin { + t.Fatalf("Response code is not %d. Error %s", code.WrongGasCoin, response.Log) + } + + check.DueBlock = 1 + lock, err = crypto.Sign(check.HashWithoutLock().Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + check.Lock = big.NewInt(0).SetBytes(lock) + err = check.Sign(senderPrivateKey) + if err != nil { + t.Fatal(err) + } + + rawCheck, _ = rlp.EncodeToBytes(check) + data.RawCheck = rawCheck + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx.GasCoin = coin + tx.Data = encodedData + if err := tx.Sign(receiverPrivateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 100, &sync.Map{}, 0) + if response.Code != code.CheckExpired { + t.Fatalf("Response code is not %d. Error %s", code.CheckExpired, response.Log) + } +} + +func TestRedeemCheckTxToUsed(t *testing.T) { + cState := getState() + coin := types.GetBaseCoinID() + + senderPrivateKey, _ := crypto.GenerateKey() + senderAddr := crypto.PubkeyToAddress(senderPrivateKey.PublicKey) + cState.Accounts.AddBalance(senderAddr, coin, helpers.BipToPip(big.NewInt(1000000))) + + receiverPrivateKey, _ := crypto.GenerateKey() + receiverAddr := crypto.PubkeyToAddress(receiverPrivateKey.PublicKey) + + passphrase := "password" + passphraseHash := sha256.Sum256([]byte(passphrase)) + passphrasePk, err := crypto.ToECDSA(passphraseHash[:]) + + if err != nil { + t.Fatal(err) + } + + checkValue := helpers.BipToPip(big.NewInt(10)) + + check := c.Check{ + Nonce: []byte{1, 2, 3}, + ChainID: types.CurrentChainID, + DueBlock: 1, + Coin: coin, + Value: checkValue, + GasCoin: types.GetBaseCoinID(), + } + + lock, err := crypto.Sign(check.HashWithoutLock().Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + check.Lock = big.NewInt(0).SetBytes(lock) + + err = check.Sign(senderPrivateKey) + if err != nil { + t.Fatal(err) + } + + rawCheck, _ := rlp.EncodeToBytes(check) + + cState.Checks.UseCheck(&check) + + var senderAddressHash types.Hash + hw := sha3.NewKeccak256() + _ = rlp.Encode(hw, []interface{}{ + receiverAddr, + }) + hw.Sum(senderAddressHash[:0]) + + sig, err := crypto.Sign(senderAddressHash.Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + proof := [65]byte{} + copy(proof[:], sig) + + data := RedeemCheckData{ + RawCheck: rawCheck, + Proof: proof, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeRedeemCheck, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(receiverPrivateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CheckUsed { + t.Fatalf("Response code is not %d. Error %s", code.CheckUsed, response.Log) + } +} + +func TestRedeemCheckTxToInsufficientFunds(t *testing.T) { + cState := getState() + coin := types.GetBaseCoinID() + + senderPrivateKey, _ := crypto.GenerateKey() + + receiverPrivateKey, _ := crypto.GenerateKey() + receiverAddr := crypto.PubkeyToAddress(receiverPrivateKey.PublicKey) + + passphrase := "password" + passphraseHash := sha256.Sum256([]byte(passphrase)) + passphrasePk, err := crypto.ToECDSA(passphraseHash[:]) + + if err != nil { + t.Fatal(err) + } + + checkValue := helpers.BipToPip(big.NewInt(10)) + + check := c.Check{ + Nonce: []byte{1, 2, 3}, + ChainID: types.CurrentChainID, + DueBlock: 1, + Coin: coin, + Value: checkValue, + GasCoin: types.GetBaseCoinID(), + } + + lock, err := crypto.Sign(check.HashWithoutLock().Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + check.Lock = big.NewInt(0).SetBytes(lock) + + err = check.Sign(senderPrivateKey) + if err != nil { + t.Fatal(err) + } + + rawCheck, _ := rlp.EncodeToBytes(check) + + var senderAddressHash types.Hash + hw := sha3.NewKeccak256() + _ = rlp.Encode(hw, []interface{}{ + receiverAddr, + }) + hw.Sum(senderAddressHash[:0]) + + sig, err := crypto.Sign(senderAddressHash.Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + proof := [65]byte{} + copy(proof[:], sig) + + data := RedeemCheckData{ + RawCheck: rawCheck, + Proof: proof, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeRedeemCheck, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(receiverPrivateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} diff --git a/core/transaction/unbond_test.go b/core/transaction/unbond_test.go index cb6b032b5..2adc1c091 100644 --- a/core/transaction/unbond_test.go +++ b/core/transaction/unbond_test.go @@ -1,6 +1,8 @@ package transaction import ( + "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/state/candidates" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" @@ -220,3 +222,317 @@ func TestUnbondTxWithWatchlist(t *testing.T) { t.Fatalf("Waitlist is not correct") } } + +func TestUnbondTxToDecodeError(t *testing.T) { + cState := getState() + + pubkey := createTestCandidate(cState) + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + value := helpers.BipToPip(big.NewInt(100)) + cState.Candidates.Delegate(addr, pubkey, coin, value, big.NewInt(0)) + + cState.Candidates.RecalculateStakes(109000) + + data := UnbondData{ + PubKey: pubkey, + Coin: coin, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeUnbond, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + response := data.Run(&tx, state.NewCheckState(cState), nil, 1) + if response.Code != code.DecodeError { + t.Fatalf("Response code is not %d. Error %s", code.DecodeError, response.Log) + } +} + +func TestUnbondTxToNotExistenCoin(t *testing.T) { + cState := getState() + pubkey := createTestCandidate(cState) + privateKey, _ := crypto.GenerateKey() + coin := types.GetBaseCoinID() + value := helpers.BipToPip(big.NewInt(100)) + + data := UnbondData{ + PubKey: pubkey, + Coin: 5, + Value: value, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeUnbond, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinNotExists { + t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) + } +} + +func TestUnbondTxToNotExistenCandidate(t *testing.T) { + cState := getState() + pubkey := types.Pubkey{0} + privateKey, _ := crypto.GenerateKey() + coin := types.GetBaseCoinID() + value := helpers.BipToPip(big.NewInt(100)) + + data := UnbondData{ + PubKey: pubkey, + Coin: coin, + Value: value, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeUnbond, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CandidateNotFound { + t.Fatalf("Response code is not %d. Error %s", code.CandidateNotFound, response.Log) + } +} + +func TestUnbondTxToNotExistenStake(t *testing.T) { + cState := getState() + pubkey := createTestCandidate(cState) + privateKey, _ := crypto.GenerateKey() + coin := types.GetBaseCoinID() + value := helpers.BipToPip(big.NewInt(100)) + + data := UnbondData{ + PubKey: pubkey, + Coin: coin, + Value: value, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeUnbond, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.StakeNotFound { + t.Fatalf("Response code is not %d. Error %s", code.StakeNotFound, response.Log) + } +} + +func TestUnbondTxToInsufficientStake(t *testing.T) { + cState := getState() + pubkey := createTestCandidate(cState) + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + value := helpers.BipToPip(big.NewInt(100)) + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + cState.Candidates.Delegate(addr, pubkey, coin, value, big.NewInt(0)) + cState.Candidates.RecalculateStakes(109000) + + data := UnbondData{ + PubKey: pubkey, + Coin: coin, + Value: helpers.BipToPip(big.NewInt(1000)), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeUnbond, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientStake { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientStake, response.Log) + } +} + +func TestUnbondTxToInsufficientFunds(t *testing.T) { + cState := getState() + pubkey := createTestCandidate(cState) + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + value := helpers.BipToPip(big.NewInt(100)) + + cState.Candidates.Delegate(addr, pubkey, coin, value, big.NewInt(0)) + cState.Candidates.RecalculateStakes(109000) + + data := UnbondData{ + PubKey: pubkey, + Coin: coin, + Value: value, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeUnbond, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} + +func TestUnbondTxToInsufficientAmountAtWaitlist(t *testing.T) { + cState := getState() + pubkey := createTestCandidate(cState) + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + value := helpers.BipToPip(big.NewInt(100)) + + cState.Waitlist.AddWaitList(addr, pubkey, coin, value) + + data := UnbondData{ + PubKey: pubkey, + Coin: coin, + Value: helpers.BipToPip(big.NewInt(1000)), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeUnbond, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientWaitList { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientWaitList, response.Log) + } +} From 4db855e576f4f93b815452a8b35b5dff2acc0323 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 1 Sep 2020 23:06:44 +0300 Subject: [PATCH 186/426] fix --- api/v2/service/estimate_tx_commission.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v2/service/estimate_tx_commission.go b/api/v2/service/estimate_tx_commission.go index 5d6360ac1..e5ebd1e41 100644 --- a/api/v2/service/estimate_tx_commission.go +++ b/api/v2/service/estimate_tx_commission.go @@ -34,7 +34,7 @@ func (s *Service) EstimateTxCommission(ctx context.Context, req *pb.EstimateTxCo return commissionCoinForData(data, cState) } - if !strings.HasPrefix(strings.Title(req.GetTx()), "Mt") { + if !strings.HasPrefix(strings.Title(req.GetTx()), "0x") { return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "invalid transaction") } From 81716774e91e80d55b12a331bcc301ccee630d75 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 2 Sep 2020 09:16:01 +0300 Subject: [PATCH 187/426] set testnet flag --- core/types/constants.go | 2 +- version/version.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/types/constants.go b/core/types/constants.go index b1f1767d4..5f8dbc997 100644 --- a/core/types/constants.go +++ b/core/types/constants.go @@ -6,7 +6,7 @@ const ( ChainTestnet = 0x02 ChainMainnet = 0x01 - CurrentChainID = ChainMainnet + CurrentChainID = ChainTestnet ) var ( diff --git a/version/version.go b/version/version.go index ae573008b..65e0e51b7 100755 --- a/version/version.go +++ b/version/version.go @@ -11,7 +11,7 @@ const ( var ( // Must be a string because scripts like dist.sh read this file. - Version = "1.2.0" + Version = "1.2.0-testnet" // GitCommit is the current HEAD set using ldflags. GitCommit string From 38ac71f275239a597f6f3debfb51ea650005f0d1 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 2 Sep 2020 11:09:52 +0300 Subject: [PATCH 188/426] fix api --- api/estimate_coin_sell_all.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/estimate_coin_sell_all.go b/api/estimate_coin_sell_all.go index cbf26c6ae..892c07668 100644 --- a/api/estimate_coin_sell_all.go +++ b/api/estimate_coin_sell_all.go @@ -13,7 +13,7 @@ type EstimateCoinSellAllResponse struct { WillGet string `json:"will_get"` } -func EstimateCoinSellAll(coinIdToSell uint32, coinIdToBuy uint32, valueToSell *big.Int, gasPrice uint64, height int) (*EstimateCoinSellAllResponse, +func EstimateCoinSellAll(coinIdToSell uint64, coinIdToBuy uint64, valueToSell *big.Int, gasPrice uint64, height int) (*EstimateCoinSellAllResponse, error) { cState, err := GetStateForHeight(height) if err != nil { From 26d1504b693d80ff7592228d923a5d0c4cd5df84 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 2 Sep 2020 11:10:14 +0300 Subject: [PATCH 189/426] fix api --- api/estimate_coin_buy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/estimate_coin_buy.go b/api/estimate_coin_buy.go index 347fa2532..4e244ba78 100644 --- a/api/estimate_coin_buy.go +++ b/api/estimate_coin_buy.go @@ -15,7 +15,7 @@ type EstimateCoinBuyResponse struct { Commission string `json:"commission"` } -func EstimateCoinBuy(coinIdToSell uint32, coinIdToBuy uint32, valueToBuy *big.Int, height int) (*EstimateCoinBuyResponse, error) { +func EstimateCoinBuy(coinIdToSell uint64, coinIdToBuy uint64, valueToBuy *big.Int, height int) (*EstimateCoinBuyResponse, error) { cState, err := GetStateForHeight(height) if err != nil { return nil, err From 999c782487b8dad60ac6b716b969e9effb1ee48d Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 2 Sep 2020 14:59:06 +0300 Subject: [PATCH 190/426] test gas coin reserver underflow --- core/transaction/change_coin_owner_test.go | 47 +++++ core/transaction/create_coin_test.go | 161 ++++++++++++++++++ core/transaction/create_multisig_test.go | 51 ++++++ core/transaction/declare_candidacy_test.go | 54 ++++++ core/transaction/delegate_test.go | 46 +++++ core/transaction/edit_candidate_test.go | 59 +++++++ core/transaction/edit_multisig_owners_test.go | 54 ++++++ core/transaction/multisend_test.go | 54 ++++++ core/transaction/recreate_coin_test.go | 111 ++++++++++++ core/transaction/send_test.go | 49 ++++++ core/transaction/set_halt_block_test.go | 55 ++++++ .../switch_candidate_status_test.go | 94 ++++++++++ core/transaction/unbond_test.go | 50 ++++++ 13 files changed, 885 insertions(+) diff --git a/core/transaction/change_coin_owner_test.go b/core/transaction/change_coin_owner_test.go index a35b0d4a7..a80e024ff 100644 --- a/core/transaction/change_coin_owner_test.go +++ b/core/transaction/change_coin_owner_test.go @@ -157,6 +157,53 @@ func TestChangeOwnerTxWithInsufficientFunds(t *testing.T) { } } +func TestChangeCoinOwnerTxToGasCoinReserveUnderflow(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + + newOwnerPrivateKey, _ := crypto.GenerateKey() + newOwner := crypto.PubkeyToAddress(newOwnerPrivateKey.PublicKey) + + customCoin := createTestCoinWithOwner(cState, addr) + cState.Coins.SubReserve(customCoin, helpers.BipToPip(big.NewInt(90000))) + + data := ChangeCoinOwnerData{ + Symbol: types.StrToCoinSymbol("TEST"), + NewOwner: newOwner, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: customCoin, + Type: TypeChangeCoinOwner, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 500000, &sync.Map{}, 0) + if response.Code != code.CoinReserveUnderflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) + } +} + func makeTestChangeOwnerTx(data ChangeCoinOwnerData, privateKey *ecdsa.PrivateKey) ([]byte, error) { encodedData, err := rlp.EncodeToBytes(data) if err != nil { diff --git a/core/transaction/create_coin_test.go b/core/transaction/create_coin_test.go index eba8bcfa0..e8979bf8f 100644 --- a/core/transaction/create_coin_test.go +++ b/core/transaction/create_coin_test.go @@ -575,3 +575,164 @@ func TestCreateCoinWithInsufficientFundsForGas(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } } + +func TestCreateCoinTxToGasCoinReserveUnderflow(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + + customCoin := createTestCoin(cState) + cState.Coins.SubReserve(customCoin, helpers.BipToPip(big.NewInt(90000))) + + toCreate := types.StrToCoinSymbol("ABCDEF") + reserve := helpers.BipToPip(big.NewInt(10000)) + crr := uint(50) + name := "My Test Coin" + + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + cState.Accounts.AddBalance(addr, customCoin, helpers.BipToPip(big.NewInt(105))) + cState.Accounts.AddBalance(addr, types.GetBaseCoinID(), helpers.BipToPip(big.NewInt(10000))) + cState.Commit() + + data := CreateCoinData{ + Name: name, + Symbol: toCreate, + InitialAmount: helpers.BipToPip(big.NewInt(10)), + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: helpers.BipToPip(big.NewInt(100)), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: customCoin, + Type: TypeCreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveUnderflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) + } +} + +func TestCreateCoinToInsufficientFundsForGasCoin(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + + toCreate := types.StrToCoinSymbol("ABCDEF") + reserve := helpers.BipToPip(big.NewInt(10000)) + crr := uint(50) + name := "My Test Coin" + + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + cState.Accounts.AddBalance(addr, types.GetBaseCoinID(), helpers.BipToPip(big.NewInt(10000))) + + data := CreateCoinData{ + Name: name, + Symbol: toCreate, + InitialAmount: helpers.BipToPip(big.NewInt(10)), + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: helpers.BipToPip(big.NewInt(100)), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeCreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} + +func TestCreateCoinToInsufficientFundsForInitialReserve(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + + toCreate := types.StrToCoinSymbol("ABCDEF") + reserve := helpers.BipToPip(big.NewInt(11000)) + crr := uint(50) + name := "My Test Coin" + + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + cState.Accounts.AddBalance(addr, types.GetBaseCoinID(), helpers.BipToPip(big.NewInt(10000))) + + data := CreateCoinData{ + Name: name, + Symbol: toCreate, + InitialAmount: helpers.BipToPip(big.NewInt(10)), + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: helpers.BipToPip(big.NewInt(100)), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeCreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} diff --git a/core/transaction/create_multisig_test.go b/core/transaction/create_multisig_test.go index f7f90c9ae..2f2766131 100644 --- a/core/transaction/create_multisig_test.go +++ b/core/transaction/create_multisig_test.go @@ -522,3 +522,54 @@ func TestCreateMultisigOwnersTxToInsufficientFunds(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } } + +func TestCreateMultisigTxToGasCoinReserveUnderflow(t *testing.T) { + cState := getState() + + privateKey1, _ := crypto.GenerateKey() + addr1 := crypto.PubkeyToAddress(privateKey1.PublicKey) + privateKey2, _ := crypto.GenerateKey() + addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) + privateKey3, _ := crypto.GenerateKey() + addr3 := crypto.PubkeyToAddress(privateKey3.PublicKey) + + customCoin := createTestCoin(cState) + cState.Coins.SubReserve(customCoin, helpers.BipToPip(big.NewInt(90000))) + + cState.Accounts.AddBalance(addr3, types.GetBaseCoinID(), helpers.BipToPip(big.NewInt(1000000))) + + data := CreateMultisigData{ + Threshold: 3, + Weights: []uint{1, 2, 3}, + Addresses: []types.Address{addr1, addr2, addr3}, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: customCoin, + Type: TypeCreateMultisig, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey3); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveUnderflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) + } +} diff --git a/core/transaction/declare_candidacy_test.go b/core/transaction/declare_candidacy_test.go index 9d21d2018..37068d3f0 100644 --- a/core/transaction/declare_candidacy_test.go +++ b/core/transaction/declare_candidacy_test.go @@ -572,3 +572,57 @@ func TestDeclareCandidacyToInsufficientFunds(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } } + +func TestDeclareCandidacyTxToGasCoinReserveUnderflow(t *testing.T) { + cState := getState() + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := createTestCoin(cState) + stake := big.NewInt(1e18) + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) + cState.Commit() + + pkey, _ := crypto.GenerateKey() + publicKeyBytes := crypto.FromECDSAPub(&pkey.PublicKey)[:32] + var publicKey types.Pubkey + copy(publicKey[:], publicKeyBytes) + + data := DeclareCandidacyData{ + Address: addr, + PubKey: publicKey, + Commission: uint(10), + Coin: coin, + Stake: stake, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeDeclareCandidacy, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveUnderflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) + } +} diff --git a/core/transaction/delegate_test.go b/core/transaction/delegate_test.go index 75114d07c..3ce666959 100644 --- a/core/transaction/delegate_test.go +++ b/core/transaction/delegate_test.go @@ -446,3 +446,49 @@ func TestDelegateTxToInsufficientFunds(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } } + +func TestDelegateTxToGasCoinReserveUnderflow(t *testing.T) { + cState := getState() + + pubkey := createTestCandidate(cState) + privateKey, _ := crypto.GenerateKey() + value := big.NewInt(1) + + coin := createTestCoin(cState) + cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) + + data := DelegateData{ + PubKey: pubkey, + Coin: coin, + Value: value, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeDelegate, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveUnderflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) + } +} diff --git a/core/transaction/edit_candidate_test.go b/core/transaction/edit_candidate_test.go index 77feeaa2c..8e1327f7a 100644 --- a/core/transaction/edit_candidate_test.go +++ b/core/transaction/edit_candidate_test.go @@ -461,3 +461,62 @@ func TestEditCandidateTxToNewPublicKeyInBlockList(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.PublicKeyInBlockList, response.Log) } } + +func TestEditCandidateTxToGasCoinReserveUnderflow(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := createTestCoin(cState) + cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + pubkey2 := types.Pubkey{1} + + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + + newRewardAddress := types.Address{1} + newOwnerAddress := types.Address{2} + newControlAddress := types.Address{3} + + data := EditCandidateData{ + PubKey: pubkey, + NewPubKey: &pubkey2, + RewardAddress: newRewardAddress, + OwnerAddress: newOwnerAddress, + ControlAddress: newControlAddress, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditCandidate, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveUnderflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) + } +} diff --git a/core/transaction/edit_multisig_owners_test.go b/core/transaction/edit_multisig_owners_test.go index 89985b73e..710c3ba66 100644 --- a/core/transaction/edit_multisig_owners_test.go +++ b/core/transaction/edit_multisig_owners_test.go @@ -401,3 +401,57 @@ func TestEditMultisigOwnersTxToInsufficientFunds(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } } + +func TestEditMultisigOwnersTxToGasCoinReserveUnderflow(t *testing.T) { + cState := getState() + + addr := types.Address{0} + privateKey1, _ := crypto.GenerateKey() + addr1 := crypto.PubkeyToAddress(privateKey1.PublicKey) + privateKey2, _ := crypto.GenerateKey() + addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) + privateKey3, _ := crypto.GenerateKey() + addr3 := crypto.PubkeyToAddress(privateKey3.PublicKey) + + coin := createTestCoin(cState) + cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) + + cState.Accounts.CreateMultisig([]uint{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + + data := EditMultisigOwnersData{ + Threshold: 3, + Weights: []uint{1, 2, 3}, + Addresses: []types.Address{addr1, addr2, addr3}, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditMultisigOwner, + Data: encodedData, + SignatureType: SigTypeMulti, + } + + tx.SetMultisigAddress(addr) + + if err := tx.Sign(privateKey3); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveUnderflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) + } +} diff --git a/core/transaction/multisend_test.go b/core/transaction/multisend_test.go index 7a7199523..ad6f0ceb5 100644 --- a/core/transaction/multisend_test.go +++ b/core/transaction/multisend_test.go @@ -300,3 +300,57 @@ func TestMultisendToInsufficientReserve(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) } } + +func TestMultisendTxToGasCoinReserveUnderflow(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := createTestCoin(cState) + + cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + cState.Commit() + + value := helpers.BipToPip(big.NewInt(10)) + to := types.Address([20]byte{1}) + + data := MultisendData{ + List: []MultisendDataItem{ + { + Coin: coin, + To: to, + Value: value, + }, + }, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + GasCoin: coin, + ChainID: types.CurrentChainID, + Type: TypeMultisend, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveUnderflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) + } +} diff --git a/core/transaction/recreate_coin_test.go b/core/transaction/recreate_coin_test.go index f0a0b05df..cea5841e1 100644 --- a/core/transaction/recreate_coin_test.go +++ b/core/transaction/recreate_coin_test.go @@ -491,6 +491,117 @@ func TestRecreateCoinWithInsufficientFundsForGas(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + cState.Accounts.SetBalance(addr, types.GetBaseCoinID(), data.InitialReserve) + cState.Commit() + + tx.GasCoin = types.GetBaseCoinID() + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} + +func TestRecreateCoinToInsufficientFundsForInitialReserve(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + createTestCoinWithOwner(cState, crypto.PubkeyToAddress(privateKey.PublicKey)) + + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + cState.Accounts.SetBalance(addr, types.GetBaseCoinID(), helpers.BipToPip(big.NewInt(10000))) + cState.Commit() + + toCreate := types.StrToCoinSymbol("TEST") + reserve := helpers.BipToPip(big.NewInt(100000)) + crr := uint(50) + name := "My Test Coin" + + data := RecreateCoinData{ + Name: name, + Symbol: toCreate, + InitialAmount: helpers.BipToPip(big.NewInt(10)), + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: helpers.BipToPip(big.NewInt(100)), + } + + encodedTx, err := makeTestRecreateCoinTx(data, privateKey) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} + +func TestRecreateCoinToGasCoinReserveUnderflow(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + coin := createTestCoinWithOwner(cState, crypto.PubkeyToAddress(privateKey.PublicKey)) + + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + + cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(105))) + cState.Accounts.AddBalance(addr, types.GetBaseCoinID(), helpers.BipToPip(big.NewInt(10000))) + cState.Commit() + + toCreate := types.StrToCoinSymbol("TEST") + reserve := helpers.BipToPip(big.NewInt(100000)) + crr := uint(50) + name := "My Test Coin" + + data := RecreateCoinData{ + Name: name, + Symbol: toCreate, + InitialAmount: helpers.BipToPip(big.NewInt(10)), + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: helpers.BipToPip(big.NewInt(100)), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeRecreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveUnderflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) + } } func makeTestRecreateCoinTx(data RecreateCoinData, privateKey *ecdsa.PrivateKey) ([]byte, error) { diff --git a/core/transaction/send_test.go b/core/transaction/send_test.go index 8a5d7e0dc..72108a47e 100644 --- a/core/transaction/send_test.go +++ b/core/transaction/send_test.go @@ -312,3 +312,52 @@ func TestSendTxWithCustomCoin(t *testing.T) { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", to.String(), targetTestBalance, testBalance) } } + +func TestSendTxToGasCoinReserveUnderflow(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := createTestCoin(cState) + + cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + value := helpers.BipToPip(big.NewInt(10)) + to := types.Address([20]byte{1}) + + data := SendData{ + Coin: coin, + To: to, + Value: value, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSend, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveUnderflow { + t.Fatalf("Response code is not %d. Error: %s", code.CoinReserveUnderflow, response.Log) + } +} diff --git a/core/transaction/set_halt_block_test.go b/core/transaction/set_halt_block_test.go index a88121599..17d601be8 100644 --- a/core/transaction/set_halt_block_test.go +++ b/core/transaction/set_halt_block_test.go @@ -315,3 +315,58 @@ func TestSetHaltBlockTxToInsufficientFunds(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } } + +func TestSetHaltBlockTxToGasCoinReserveUnderflow(t *testing.T) { + cState, err := state.NewState(500000, db.NewMemDB(), nil, 1, 1) + if err != nil { + t.Fatalf("Cannot load state. Error %s", err) + } + + haltHeight := 500000 + uint64(100) + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + + coin := createTestCoin(cState) + cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) + cState.Commit() + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + + data := SetHaltBlockData{ + PubKey: pubkey, + Height: haltHeight, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSetHaltBlock, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 500000, &sync.Map{}, 0) + if response.Code != code.CoinReserveUnderflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) + } +} diff --git a/core/transaction/switch_candidate_status_test.go b/core/transaction/switch_candidate_status_test.go index 45611b3bb..0fc482333 100644 --- a/core/transaction/switch_candidate_status_test.go +++ b/core/transaction/switch_candidate_status_test.go @@ -231,3 +231,97 @@ func TestSwitchCandidateStatusTxToCandidateOwnership(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.IsNotOwnerOfCandidate, response.Log) } } + +func TestSwitchCandidateStatusToGasCoinReserveUnderflow(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + + coin := createTestCoin(cState) + cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pubkey := types.Pubkey{} + rand.Read(pubkey[:]) + + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + + data := SetCandidateOnData{ + PubKey: pubkey, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSetCandidateOnline, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveUnderflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) + } +} + +func TestSwitchCandidateStatusToInsufficientFundsForGas(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + pubkey := types.Pubkey{} + rand.Read(pubkey[:]) + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + + data := SetCandidateOnData{ + PubKey: pubkey, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSetCandidateOnline, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} diff --git a/core/transaction/unbond_test.go b/core/transaction/unbond_test.go index 2adc1c091..4c64fb6dc 100644 --- a/core/transaction/unbond_test.go +++ b/core/transaction/unbond_test.go @@ -536,3 +536,53 @@ func TestUnbondTxToInsufficientAmountAtWaitlist(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.InsufficientWaitList, response.Log) } } + +func TestUnbondTxToGasCoinReserveUnderflow(t *testing.T) { + cState := getState() + pubkey := createTestCandidate(cState) + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + value := helpers.BipToPip(big.NewInt(100)) + + cState.Candidates.Delegate(addr, pubkey, coin, value, big.NewInt(0)) + cState.Candidates.RecalculateStakes(109000) + + data := UnbondData{ + PubKey: pubkey, + Coin: coin, + Value: value, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + gasCoin := createTestCoin(cState) + cState.Coins.SubReserve(gasCoin, helpers.BipToPip(big.NewInt(90000))) + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: gasCoin, + Type: TypeUnbond, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveUnderflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) + } +} From dec2304ef5bd351b76199ed33908d74fbc4bd426 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 3 Sep 2020 09:48:31 +0300 Subject: [PATCH 191/426] remove check for coin insufficient reserve --- core/transaction/change_coin_owner.go | 12 ----------- core/transaction/create_coin.go | 12 ----------- core/transaction/create_multisig.go | 12 ----------- core/transaction/declare_candidacy.go | 12 ----------- core/transaction/delegate.go | 12 ----------- core/transaction/edit_candidate.go | 12 ----------- core/transaction/edit_multisig_owners.go | 12 ----------- core/transaction/multisend.go | 12 ----------- core/transaction/recreate_coin.go | 12 ----------- core/transaction/send.go | 13 ----------- core/transaction/set_halt_block.go | 12 ----------- core/transaction/switch_candidate_status.go | 24 --------------------- core/transaction/unbond.go | 12 ----------- 13 files changed, 169 deletions(-) diff --git a/core/transaction/change_coin_owner.go b/core/transaction/change_coin_owner.go index de3eb1bfe..8f0da97ad 100644 --- a/core/transaction/change_coin_owner.go +++ b/core/transaction/change_coin_owner.go @@ -71,18 +71,6 @@ func (data ChangeCoinOwnerData) Run(tx *Transaction, context state.Interface, re return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Gas coin reserve balance is not sufficient for transaction. Has: %s %s, required %s %s", gasCoin.Reserve().String(), types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), - Info: EncodeError(map[string]string{ - "has_value": gasCoin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index d20338b18..f567f6f17 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -127,18 +127,6 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP return *errResp } - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Gas coin reserve balance is not sufficient for transaction. Has: %s %s, required %s %s", coin.Reserve().String(), types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), - Info: EncodeError(map[string]string{ - "has_value": coin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), - }), - } - } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index 96add517f..7a95432b1 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -94,18 +94,6 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "has_reserve": gasCoin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": gasCoin.GetFullSymbol(), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index 1de880d2e..8c1a213a9 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -118,18 +118,6 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "has_reserve": gasCoin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": gasCoin.CName, - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index 0dd0697dd..5add3b71a 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -93,18 +93,6 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "has_reserve": gasCoin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": gasCoin.GetFullSymbol(), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index 58b965f36..2b93fdd3e 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -77,18 +77,6 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "has_reserve": gasCoin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": gasCoin.GetFullSymbol(), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/edit_multisig_owners.go b/core/transaction/edit_multisig_owners.go index a6751654a..9b1410abc 100644 --- a/core/transaction/edit_multisig_owners.go +++ b/core/transaction/edit_multisig_owners.go @@ -120,18 +120,6 @@ func (data EditMultisigOwnersData) Run(tx *Transaction, context state.Interface, return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "has_reserve": gasCoin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": gasCoin.GetFullSymbol(), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/multisend.go b/core/transaction/multisend.go index 770a73a0e..c9e772fab 100644 --- a/core/transaction/multisend.go +++ b/core/transaction/multisend.go @@ -79,18 +79,6 @@ func (data MultisendData) Run(tx *Transaction, context state.Interface, rewardPo return *errResp } - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "has_reserve": coin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": coin.CName, - }), - } - } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index d0708be77..c3eca4d57 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -113,18 +113,6 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Gas coin reserve balance is not sufficient for transaction. Has: %s %s, required %s %s", gasCoin.Reserve().String(), types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), - Info: EncodeError(map[string]string{ - "has_value": gasCoin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "gas_coin": gasCoin.GetFullSymbol(), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/send.go b/core/transaction/send.go index 42417cb01..d35df68b3 100644 --- a/core/transaction/send.go +++ b/core/transaction/send.go @@ -38,19 +38,6 @@ func (data SendData) TotalSpend(tx *Transaction, context *state.CheckState) (Tot return nil, nil, nil, errResp } - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return nil, nil, nil, &Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", - coin.Reserve().String(), - commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "has": coin.Reserve().String(), - "required": commissionInBaseCoin.String(), - }), - } - } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) conversions = append(conversions, Conversion{ FromCoin: tx.GasCoin, diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index 9f29b5c68..fb20967b7 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -81,18 +81,6 @@ func (data SetHaltBlockData) Run(tx *Transaction, context state.Interface, rewar return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "has_reserve": gasCoin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": gasCoin.GetFullSymbol(), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index c2c1f18c6..486777244 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -58,18 +58,6 @@ func (data SetCandidateOnData) Run(tx *Transaction, context state.Interface, rew return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "has_reserve": gasCoin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": gasCoin.GetFullSymbol(), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } @@ -152,18 +140,6 @@ func (data SetCandidateOffData) Run(tx *Transaction, context state.Interface, re if !tx.GasCoin.IsBaseCoin() { coin := checkState.Coins().GetCoin(tx.GasCoin) - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "has_reserve": coin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": coin.CName, - }), - } - } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 0d6e413df..f6f2402df 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -121,18 +121,6 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "has_reserve": gasCoin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": gasCoin.GetFullSymbol(), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } From 15d75ecb86d82557bfa75e7a7ce79ae41de34de0 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Thu, 3 Sep 2020 11:37:39 +0300 Subject: [PATCH 192/426] Add changelog --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebdc07c54..81fecd723 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## 1.2.0 + +- [core] Added ControlAddress for Candidate +- [core] Added changing candidate’s public key functionality +- [core] Coins now identified by ID, not by symbols +- [core] Added RecreateCoin tx +- [core] Added ChangeCoinOwner tx +- [core] Limit validators slots to 64 +- [core] Add EditMultisigOwnersData tx +- [core] Add PriceVoteData tx +- [core] Stake value calculation changes + ## 1.1.8 BUG FIXES From 8a50ba0c2945102fece7e8d5b8fab8601bcffac4 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Thu, 3 Sep 2020 11:37:53 +0300 Subject: [PATCH 193/426] Update go mod --- go.mod | 8 +++++--- go.sum | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6239f2a87..be4c6a1c0 100644 --- a/go.mod +++ b/go.mod @@ -32,10 +32,12 @@ require ( github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 github.com/urfave/cli/v2 v2.0.0 gitlab.com/tslocum/cview v1.4.7 - golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 - golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e - golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 + golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect + golang.org/x/net v0.0.0-20200822124328-c89045814202 + golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 golang.org/x/sys v0.0.0-20200523222454-059865788121 + golang.org/x/tools v0.0.0-20200903005429-2364a5e8fdcf // indirect google.golang.org/grpc v1.31.0 google.golang.org/protobuf v1.25.0 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 diff --git a/go.sum b/go.sum index c076aaf0c..ea36531fc 100644 --- a/go.sum +++ b/go.sum @@ -482,6 +482,7 @@ github.com/urfave/cli/v2 v2.0.0 h1:+HU9SCbu8GnEUFtIBfuUNXN39ofWViIEJIp6SURMpCg= github.com/urfave/cli/v2 v2.0.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= gitlab.com/tslocum/cbind v0.1.1 h1:JXXtxMWHgWLvoF+QkrvcNvOQ59juy7OE1RhT7hZfdt0= gitlab.com/tslocum/cbind v0.1.1/go.mod h1:rX7vkl0pUSg/yy427MmD1FZAf99S7WwpUlxF/qTpPqk= gitlab.com/tslocum/cview v1.4.7 h1:8HkA2iwk9008FKDTbi6L0KkHoj2mFbgUW73DHw9iG1U= @@ -515,14 +516,20 @@ golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 h1:DOmugCavvUtnUD114C1Wh+ golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88= golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -546,6 +553,7 @@ golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 h1:2mqDk8w/o6UmeUCu5Qiq2y7iM golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -557,6 +565,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEha golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -605,11 +614,17 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114 h1:DnSr2mCsxyCE6ZgIkmcWUQY2R5cH/6wL7eIxEmQOMSE= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200903005429-2364a5e8fdcf h1:cOiNYCV+8M1y9/TPI56oDaaBFwU0kWzlJ45x74iFaJY= +golang.org/x/tools v0.0.0-20200903005429-2364a5e8fdcf/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= From 509073dde91fb2680144c9739ecb730a56443092 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Thu, 3 Sep 2020 11:56:20 +0300 Subject: [PATCH 194/426] Fix linter errors on appdb --- core/appdb/appdb.go | 41 ++++++++++++++++++++++++++++++----------- go.sum | 1 + 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/core/appdb/appdb.go b/core/appdb/appdb.go index 57f700628..a764a86b9 100644 --- a/core/appdb/appdb.go +++ b/core/appdb/appdb.go @@ -24,14 +24,19 @@ const ( dbName = "app" ) +// AppDB is responsible for storing basic information about app state on disk type AppDB struct { db db.DB } +// Close closes db connection, panics on error func (appDB *AppDB) Close() { - appDB.db.Close() + if err := appDB.db.Close(); err != nil { + panic(err) + } } +// GetLastBlockHash returns latest block hash stored on disk func (appDB *AppDB) GetLastBlockHash() []byte { var hash [32]byte @@ -44,12 +49,14 @@ func (appDB *AppDB) GetLastBlockHash() []byte { return hash[:] } +// SetLastBlockHash stores given block hash on disk, panics on error func (appDB *AppDB) SetLastBlockHash(hash []byte) { if err := appDB.db.Set([]byte(hashPath), hash); err != nil { panic(err) } } +// GetLastHeight returns latest block height stored on disk func (appDB *AppDB) GetLastHeight() uint64 { result, err := appDB.db.Get([]byte(heightPath)) if err != nil { @@ -64,6 +71,7 @@ func (appDB *AppDB) GetLastHeight() uint64 { return height } +// SetLastHeight stores given block height on disk, panics on error func (appDB *AppDB) SetLastHeight(height uint64) { h := make([]byte, 8) binary.BigEndian.PutUint64(h, height) @@ -72,12 +80,16 @@ func (appDB *AppDB) SetLastHeight(height uint64) { } } +// SetStartHeight stores given block height on disk as start height, panics on error func (appDB *AppDB) SetStartHeight(height uint64) { h := make([]byte, 8) binary.BigEndian.PutUint64(h, height) - appDB.db.Set([]byte(startHeightPath), h) + if err := appDB.db.Set([]byte(startHeightPath), h); err != nil { + panic(err) + } } +// GetStartHeight returns start height stored on disk func (appDB *AppDB) GetStartHeight() uint64 { result, err := appDB.db.Get([]byte(startHeightPath)) if err != nil { @@ -92,6 +104,7 @@ func (appDB *AppDB) GetStartHeight() uint64 { return height } +// GetValidators returns list of latest validators stored on dist func (appDB *AppDB) GetValidators() types.ValidatorUpdates { result, err := appDB.db.Get([]byte(validatorsPath)) if err != nil { @@ -105,7 +118,6 @@ func (appDB *AppDB) GetValidators() types.ValidatorUpdates { var vals types.ValidatorUpdates err = cdc.UnmarshalBinaryBare(result, &vals) - if err != nil { panic(err) } @@ -113,45 +125,49 @@ func (appDB *AppDB) GetValidators() types.ValidatorUpdates { return vals } +// SaveValidators stores given validators list on disk, panics on error func (appDB *AppDB) SaveValidators(vals types.ValidatorUpdates) { data, err := cdc.MarshalBinaryBare(vals) - if err != nil { panic(err) } - appDB.db.Set([]byte(validatorsPath), data) + if err := appDB.db.Set([]byte(validatorsPath), data); err != nil { + panic(err) + } } -type LastBlocksTimeDelta struct { +type lastBlocksTimeDelta struct { Height uint64 Delta int } +// GetLastBlocksTimeDelta returns delta of time between latest blocks func (appDB *AppDB) GetLastBlocksTimeDelta(height uint64) (int, error) { result, err := appDB.db.Get([]byte(blockTimeDeltaPath)) if err != nil { panic(err) } if result == nil { - return 0, errors.New("no info about LastBlocksTimeDelta is available") + return 0, errors.New("no info about lastBlocksTimeDelta is available") } - data := LastBlocksTimeDelta{} + data := lastBlocksTimeDelta{} err = cdc.UnmarshalBinaryBare(result, &data) if err != nil { panic(err) } if data.Height != height { - return 0, errors.New("no info about LastBlocksTimeDelta is available") + return 0, errors.New("no info about lastBlocksTimeDelta is available") } return data.Delta, nil } +// SetLastBlocksTimeDelta stores delta of time between latest blocks func (appDB *AppDB) SetLastBlocksTimeDelta(height uint64, delta int) { - data, err := cdc.MarshalBinaryBare(LastBlocksTimeDelta{ + data, err := cdc.MarshalBinaryBare(lastBlocksTimeDelta{ Height: height, Delta: delta, }) @@ -160,9 +176,12 @@ func (appDB *AppDB) SetLastBlocksTimeDelta(height uint64, delta int) { panic(err) } - appDB.db.Set([]byte(blockTimeDeltaPath), data) + if err := appDB.db.Set([]byte(blockTimeDeltaPath), data); err != nil { + panic(err) + } } +// NewAppDB creates AppDB instance with given config func NewAppDB(cfg *config.Config) *AppDB { return &AppDB{ db: db.NewDB(dbName, db.BackendType(cfg.DBBackend), utils.GetMinterHome()+"/data"), diff --git a/go.sum b/go.sum index ea36531fc..564002110 100644 --- a/go.sum +++ b/go.sum @@ -553,6 +553,7 @@ golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 h1:2mqDk8w/o6UmeUCu5Qiq2y7iM golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= From 9213cc744b723ea567273f20437abb7b3df85a95 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Thu, 3 Sep 2020 13:00:41 +0300 Subject: [PATCH 195/426] Fix linter errors on check --- core/check/check.go | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/core/check/check.go b/core/check/check.go index 59d94fcc9..2eaedc81d 100644 --- a/core/check/check.go +++ b/core/check/check.go @@ -13,9 +13,21 @@ import ( ) var ( + // ErrInvalidSig represents error on given v, r, s values ErrInvalidSig = errors.New("invalid transaction v, r, s values") ) +// Check is like an ordinary bank check. +// Each user of network can issue check with any amount of coins and pass it to another person. +// Receiver will be able to cash a check from arbitrary account. +// +// Nonce - unique "id" of the check. +// Coin Symbol - symbol of coin. +// Value - amount of coins. +// GasCoin - symbol of a coin to pay fee. +// DueBlock - defines last block height in which the check can be used. +// Lock - secret to prevent hijacking. +// V, R, S - signature of issuer. type Check struct { Nonce []byte ChainID types.ChainID @@ -29,10 +41,12 @@ type Check struct { S *big.Int } +// Sender returns sender's address of a Check, recovered from signature func (check *Check) Sender() (types.Address, error) { return recoverPlain(check.Hash(), check.R, check.S, check.V) } +// LockPubKey returns bytes of public key, which is used for proving check's recipient rights func (check *Check) LockPubKey() ([]byte, error) { sig := check.Lock.Bytes() @@ -53,6 +67,7 @@ func (check *Check) LockPubKey() ([]byte, error) { return pub, nil } +// HashWithoutLock returns a types.Hash to be used in process of signing and checking Lock func (check *Check) HashWithoutLock() types.Hash { return rlpHash([]interface{}{ check.Nonce, @@ -64,6 +79,7 @@ func (check *Check) HashWithoutLock() types.Hash { }) } +// Hash returns a types.Hash to be used in process of signing a Check by sender func (check *Check) Hash() types.Hash { return rlpHash([]interface{}{ check.Nonce, @@ -76,6 +92,7 @@ func (check *Check) Hash() types.Hash { }) } +// Sign signs the check with given private key, returns error func (check *Check) Sign(prv *ecdsa.PrivateKey) error { h := check.Hash() sig, err := crypto.Sign(h[:], prv) @@ -83,12 +100,12 @@ func (check *Check) Sign(prv *ecdsa.PrivateKey) error { return err } - check.SetSignature(sig) + check.setSignature(sig) return nil } -func (check *Check) SetSignature(sig []byte) { +func (check *Check) setSignature(sig []byte) { check.R = new(big.Int).SetBytes(sig[:32]) check.S = new(big.Int).SetBytes(sig[32:64]) check.V = new(big.Int).SetBytes([]byte{sig[64] + 27}) @@ -101,6 +118,7 @@ func (check *Check) String() string { check.DueBlock, check.Value.String(), check.Coin.String()) } +// DecodeFromBytes decodes check from bytes func DecodeFromBytes(buf []byte) (*Check, error) { var check Check err := rlp.Decode(bytes.NewReader(buf), &check) From 3caa90b4504e3f4d77ef06b40f7a4f499fb51ead Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Thu, 3 Sep 2020 13:02:09 +0300 Subject: [PATCH 196/426] Fix linter errors on codes --- core/code/code.go | 1 + 1 file changed, 1 insertion(+) diff --git a/core/code/code.go b/core/code/code.go index 0b4e86ef8..96354ae2c 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -1,5 +1,6 @@ package code +// Codes for transaction checks and delivers responses const ( // general OK uint32 = 0 From a71963348d32d67023c4bf65cb6852fbc29e3815 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Thu, 3 Sep 2020 13:13:06 +0300 Subject: [PATCH 197/426] Fix linter errors --- core/dao/dao.go | 10 +++------- core/developers/developers.go | 10 +++------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/core/dao/dao.go b/core/dao/dao.go index 6d722a3ba..8134a503c 100644 --- a/core/dao/dao.go +++ b/core/dao/dao.go @@ -1,15 +1,11 @@ package dao import ( - "github.com/MinterTeam/minter-go-node/core/state/accounts" "github.com/MinterTeam/minter-go-node/core/types" ) +// Commission which is subtracted from rewards and being send to DAO Address var ( - Address = (&accounts.Multisig{ - Threshold: 2, - Weights: []uint{1, 1, 1}, - Addresses: []types.Address{types.HexToAddress("Mxed2f3dbe7a25f928df95ae8f207ed8079578daf3"), types.HexToAddress("Mx91980bf6391eb6946f43df559fd1e56952f9cde7"), types.HexToAddress("Mx375bc810e0fd19dcf0da43556b50ba6825ba11b8")}, - }).Address() - Commission = 10 + Address = types.HexToAddress("Mx7f0fc21d932f38ca9444f61703174569066cfa50") + Commission = 10 // in % ) diff --git a/core/developers/developers.go b/core/developers/developers.go index 434d6047c..104d53c70 100644 --- a/core/developers/developers.go +++ b/core/developers/developers.go @@ -1,15 +1,11 @@ package developers import ( - "github.com/MinterTeam/minter-go-node/core/state/accounts" "github.com/MinterTeam/minter-go-node/core/types" ) +// Commission which is subtracted from rewards and being send to Developers Address var ( - Address = (&accounts.Multisig{ - Threshold: 2, - Weights: []uint{1, 1, 1}, - Addresses: []types.Address{types.HexToAddress("Mx22df0f98c1b421974fb0c64440258aaffd4e96d8"), types.HexToAddress("Mxf8821646818a873e3efac40cc2c13f96e3515aa1"), types.HexToAddress("Mx90a82ed6fd69cdd125474ce9349a8e34fb4f5ffe")}, - }).Address() - Commission = 10 + Address = types.HexToAddress("Mx688568d9d70c57e71d0b9de6480afb0d317f885c") + Commission = 10 // in % ) From c0228dc0eebb27137aa3c85478499cecdbcefdc3 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 3 Sep 2020 13:21:43 +0300 Subject: [PATCH 198/426] handle http errors --- api/v2/service/estimate_coin_buy.go | 25 +++++++--- api/v2/service/estimate_coin_sell.go | 22 ++++----- api/v2/service/estimate_coin_sell_all.go | 25 ++++++---- api/v2/service/estimate_tx_commission.go | 2 +- api/v2/service/send_transaction.go | 25 +++++----- api/v2/v2.go | 63 +++++++++++++++++++++++- core/transaction/buy_coin.go | 4 ++ core/transaction/create_multisig.go | 19 +++++-- core/transaction/declare_candidacy.go | 19 ++++++- core/transaction/delegate.go | 23 +++++++-- core/transaction/edit_candidate.go | 12 ++++- core/transaction/edit_multisig_owners.go | 24 +++++++-- core/transaction/recreate_coin.go | 47 +++++++++++++++--- core/transaction/redeem_check.go | 47 +++++++++++++++--- core/transaction/sell_all_coin.go | 14 ++++++ core/transaction/sell_coin.go | 19 ++++++- core/transaction/send.go | 10 +++- core/transaction/transaction.go | 3 ++ go.mod | 1 + go.sum | 6 +++ 20 files changed, 342 insertions(+), 68 deletions(-) diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index 3c3676e69..4cf19e8c5 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -25,16 +25,28 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe coinToSell := types.CoinID(req.CoinIdToSell) coinToBuy := types.CoinID(req.CoinIdToBuy) - if coinToSell == coinToBuy { - return new(pb.EstimateCoinBuyResponse), status.Error(codes.FailedPrecondition, "\"From\" coin equals to \"to\" coin") - } - if !cState.Coins().Exists(coinToSell) { - return new(pb.EstimateCoinBuyResponse), status.Error(codes.FailedPrecondition, "Coin to sell not exists") + return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.InvalidArgument, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ + "code": "404", + "coin_id_to_sell": coinToSell.String(), + })) } if !cState.Coins().Exists(coinToBuy) { - return new(pb.EstimateCoinBuyResponse), status.Error(codes.FailedPrecondition, "Coin to buy not exists") + return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.InvalidArgument, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ + "code": "404", + "coin_id_to_buy": coinToBuy.String(), + })) + } + + if coinToSell == coinToBuy { + return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), transaction.EncodeError(map[string]string{ + "code": "400", + "coin_id_to_sell": coinToSell.String(), + "coin_to_sell": cState.Coins().GetCoin(coinToSell).Symbol().String(), + "coin_id_to_buy": coinToBuy.String(), + "coin_to_buy": cState.Coins().GetCoin(coinToBuy).Symbol().String(), + })) } commissionInBaseCoin := big.NewInt(commissions.ConvertTx) @@ -48,6 +60,7 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe if coinFrom.Reserve().Cmp(commissionInBaseCoin) < 0 { return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coinFrom.Reserve().String(), commissionInBaseCoin.String())), transaction.EncodeError(map[string]string{ + "code": "400", "has": coinFrom.Reserve().String(), "required": commissionInBaseCoin.String(), })) diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index 98a16c27d..070750e9a 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -25,28 +25,28 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell coinToSell := types.CoinID(req.CoinIdToSell) coinToBuy := types.CoinID(req.CoinIdToBuy) - if coinToSell == coinToBuy { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), transaction.EncodeError(map[string]string{ - "coin_id_to_sell": coinToSell.String(), - "coin_to_sell": cState.Coins().GetCoin(coinToSell).Symbol().String(), - "coin_id_to_buy": coinToBuy.String(), - "coin_to_buy": cState.Coins().GetCoin(coinToBuy).Symbol().String(), - })) - } - if !cState.Coins().Exists(coinToSell) { return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ + "code": "404", "coin_id_to_sell": coinToSell.String(), - "coin_to_sell": cState.Coins().GetCoin(coinToSell).Symbol().String(), })) } if !cState.Coins().Exists(coinToBuy) { return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ + "code": "404", "coin_id_to_buy": coinToBuy.String(), - "coin_to_buy": cState.Coins().GetCoin(coinToBuy).Symbol().String(), })) + } + if coinToSell == coinToBuy { + return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), transaction.EncodeError(map[string]string{ + "code": "400", + "coin_id_to_sell": coinToSell.String(), + "coin_to_sell": cState.Coins().GetCoin(coinToSell).Symbol().String(), + "coin_id_to_buy": coinToBuy.String(), + "coin_to_buy": cState.Coins().GetCoin(coinToBuy).Symbol().String(), + })) } commissionInBaseCoin := big.NewInt(commissions.ConvertTx) diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index 553ecfdf2..1304fd22f 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -28,27 +28,32 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS coinToSell := types.CoinID(req.CoinIdToSell) coinToBuy := types.CoinID(req.CoinIdToBuy) - valueToSell, ok := big.NewInt(0).SetString(req.ValueToSell, 10) //todo: mb delete? + valueToSell, ok := big.NewInt(0).SetString(req.ValueToSell, 10) if !ok { return new(pb.EstimateCoinSellAllResponse), status.Error(codes.InvalidArgument, "Value to sell not specified") } - if coinToSell == coinToBuy { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), transaction.EncodeError(map[string]string{ - "coin_to_sell": coinToSell.String(), - "coin_to_buy": coinToBuy.String(), - })) - } - if !cState.Coins().Exists(coinToSell) { return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.InvalidArgument, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ - "coin_to_sell": coinToSell.String(), + "code": "404", + "coin_id_to_sell": coinToSell.String(), })) } if !cState.Coins().Exists(coinToBuy) { return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.InvalidArgument, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ - "coin_to_buy": coinToBuy.String(), + "code": "404", + "coin_id_to_buy": coinToBuy.String(), + })) + } + + if coinToSell == coinToBuy { + return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), transaction.EncodeError(map[string]string{ + "code": "400", + "coin_id_to_sell": coinToSell.String(), + "coin_to_sell": cState.Coins().GetCoin(coinToSell).Symbol().String(), + "coin_id_to_buy": coinToBuy.String(), + "coin_to_buy": cState.Coins().GetCoin(coinToBuy).Symbol().String(), })) } diff --git a/api/v2/service/estimate_tx_commission.go b/api/v2/service/estimate_tx_commission.go index e5ebd1e41..020f28aed 100644 --- a/api/v2/service/estimate_tx_commission.go +++ b/api/v2/service/estimate_tx_commission.go @@ -45,7 +45,7 @@ func (s *Service) EstimateTxCommission(ctx context.Context, req *pb.EstimateTxCo decodedTx, err := transaction.TxDecoder.DecodeFromBytesWithoutSig(decodeString) if err != nil { - return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "Cannot decode transaction") + return new(pb.EstimateTxCommissionResponse), status.Errorf(codes.InvalidArgument, "Cannot decode transaction: %s", err.Error()) } commissionInBaseCoin := decodedTx.CommissionInBaseCoin() diff --git a/api/v2/service/send_transaction.go b/api/v2/service/send_transaction.go index fc93dea95..98fa261ae 100644 --- a/api/v2/service/send_transaction.go +++ b/api/v2/service/send_transaction.go @@ -12,23 +12,21 @@ import ( "github.com/tendermint/tendermint/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "strings" ) func (s *Service) SendTransaction(ctx context.Context, req *pb.SendTransactionRequest) (*pb.SendTransactionResponse, error) { - if len(req.Tx) < 3 { - return new(pb.SendTransactionResponse), status.Error(codes.InvalidArgument, "invalid tx") + if !strings.HasPrefix(strings.Title(req.GetTx()), "0x") { + return new(pb.SendTransactionResponse), status.Error(codes.InvalidArgument, "invalid transaction") } decodeString, err := hex.DecodeString(req.Tx[2:]) if err != nil { return new(pb.SendTransactionResponse), status.Error(codes.InvalidArgument, err.Error()) } - result, err := s.broadcastTxSync(decodeString, ctx /*timeout*/) - if err != nil { - if _, ok := status.FromError(err); ok { - return new(pb.SendTransactionResponse), err - } - return new(pb.SendTransactionResponse), status.Error(codes.FailedPrecondition, err.Error()) + result, statusErr := s.broadcastTxSync(decodeString, ctx /*timeout*/) + if statusErr != nil { + return new(pb.SendTransactionResponse), statusErr.Err() } switch result.Code { @@ -51,13 +49,16 @@ type ResultBroadcastTx struct { Hash bytes.HexBytes `json:"hash"` } -func (s *Service) broadcastTxSync(tx types.Tx, ctx context.Context) (*ResultBroadcastTx, error) { +func (s *Service) broadcastTxSync(tx types.Tx, ctx context.Context) (*ResultBroadcastTx, *status.Status) { resCh := make(chan *abci.Response, 1) err := s.tmNode.Mempool().CheckTx(tx, func(res *abci.Response) { resCh <- res }, mempool.TxInfo{}) if err != nil { - return nil, err + if err.Error() == mempool.ErrTxInCache.Error() { + return nil, status.New(codes.AlreadyExists, err.Error()) + } + return nil, status.New(codes.FailedPrecondition, err.Error()) } select { @@ -72,9 +73,9 @@ func (s *Service) broadcastTxSync(tx types.Tx, ctx context.Context) (*ResultBroa }, nil case <-ctx.Done(): if ctx.Err() != context.DeadlineExceeded { - return nil, status.New(codes.Canceled, ctx.Err().Error()).Err() + return nil, status.New(codes.Canceled, ctx.Err().Error()) } - return nil, status.New(codes.DeadlineExceeded, ctx.Err().Error()).Err() + return nil, status.New(codes.DeadlineExceeded, ctx.Err().Error()) } } diff --git a/api/v2/v2.go b/api/v2/v2.go index fac2ec5a5..fb491a400 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -2,6 +2,7 @@ package v2 import ( "context" + "encoding/json" "github.com/MinterTeam/minter-go-node/api/v2/service" gw "github.com/MinterTeam/node-grpc-gateway/api_pb" _ "github.com/MinterTeam/node-grpc-gateway/statik" @@ -14,6 +15,10 @@ import ( "github.com/tmc/grpc-websocket-proxy/wsproxy" "golang.org/x/sync/errgroup" "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/status" + _struct "google.golang.org/protobuf/types/known/structpb" "mime" "net" "net/http" @@ -40,7 +45,7 @@ func Run(srv *service.Service, addrGRPC, addrApi string, traceLog bool) error { ), ) runtime.DefaultContextTimeout = 10 * time.Second - + runtime.GlobalHTTPErrorHandler = httpError gw.RegisterApiServiceServer(grpcServer, srv) grpc_prometheus.Register(grpcServer) @@ -123,3 +128,59 @@ func contextWithTimeoutInterceptor(timeout time.Duration) func(ctx context.Conte return handler(withTimeout, req) } } + +func parseStatus(s *status.Status) (string, map[string]interface{}) { + codeString := "400" + var data map[string]interface{} + details := s.Details() + if len(details) != 0 { + detail, ok := details[0].(*_struct.Struct) + if !ok { + return codeString, data + } + + data = detail.AsMap() + + code, ok := detail.GetFields()["code"] + if ok { + codeString = code.GetStringValue() + } + } + return codeString, data +} + +func httpError(ctx context.Context, mux *runtime.ServeMux, marshaler runtime.Marshaler, w http.ResponseWriter, r *http.Request, err error) { + const fallback = `{"error": "failed to marshal error message"}` + type errorHTTPResponse struct { + Error interface{} `json:"error"` + } + + contentType := marshaler.ContentType() + w.Header().Set("Content-Type", contentType) + + s, ok := status.FromError(err) + if !ok { + s = status.New(codes.Unknown, err.Error()) + } + st := runtime.HTTPStatusFromCode(s.Code()) + w.WriteHeader(st) + + codeString, data := parseStatus(s) + + jErr := json.NewEncoder(w).Encode(errorHTTPResponse{ + Error: struct { + Code string `json:"code"` + Message string `json:"message"` + Data map[string]interface{} `json:"data"` + }{ + Code: codeString, + Message: s.Message(), + Data: data, + }, + }) + + if jErr != nil { + grpclog.Infof("Failed to write response: %v", err) + w.Write([]byte(fallback)) + } +} diff --git a/core/transaction/buy_coin.go b/core/transaction/buy_coin.go index 1bf51814f..2fe9701ac 100644 --- a/core/transaction/buy_coin.go +++ b/core/transaction/buy_coin.go @@ -10,6 +10,7 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" "math/big" + "strconv" ) type BuyCoinData struct { @@ -58,6 +59,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( "You wanted to sell maximum %s, but currently you need to spend %s to complete tx", data.MaximumValueToSell.String(), value.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.MaximumValueToSellReached)), "maximum_value_to_sell": data.MaximumValueToSell.String(), "needed_spend_value": value.String(), }), @@ -82,6 +84,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( commissionInBaseCoin.String(), types.GetBaseCoin()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coin.Reserve().String(), "required_value": commissionInBaseCoin.String(), "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), @@ -125,6 +128,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( "You wanted to sell maximum %s, but currently you need to spend %s to complete tx", data.MaximumValueToSell.String(), value.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.MaximumValueToSellReached)), "maximum_value_to_sell": data.MaximumValueToSell.String(), "needed_spend_value": value.String(), }), diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index 96add517f..2f257ea45 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -11,6 +11,7 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" "math/big" + "strconv" ) type CreateMultisigData struct { @@ -24,7 +25,10 @@ func (data CreateMultisigData) BasicCheck(tx *Transaction, context *state.CheckS if lenWeights > 32 { return &Response{ Code: code.TooLargeOwnersList, - Log: "Owners list is limited to 32 items"} + Log: "Owners list is limited to 32 items", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.TooLargeOwnersList)), + })} } lenAddresses := len(data.Addresses) @@ -33,6 +37,7 @@ func (data CreateMultisigData) BasicCheck(tx *Transaction, context *state.CheckS Code: code.IncorrectWeights, Log: fmt.Sprintf("Incorrect multisig weights"), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.IncorrectWeights)), "count_weights": fmt.Sprintf("%d", lenWeights), "count_addresses": fmt.Sprintf("%d", lenAddresses), }), @@ -43,7 +48,9 @@ func (data CreateMultisigData) BasicCheck(tx *Transaction, context *state.CheckS if weight > 1023 { return &Response{ Code: code.IncorrectWeights, - Log: "Incorrect multisig weights"} + Log: "Incorrect multisig weights", Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.IncorrectWeights)), + })} } } @@ -52,7 +59,10 @@ func (data CreateMultisigData) BasicCheck(tx *Transaction, context *state.CheckS if usedAddresses[address] { return &Response{ Code: code.DuplicatedAddresses, - Log: "Duplicated multisig addresses"} + Log: "Duplicated multisig addresses", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.DuplicatedAddresses)), + })} } usedAddresses[address] = true @@ -99,6 +109,7 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_reserve": gasCoin.Reserve().String(), "commission": commissionInBaseCoin.String(), "gas_coin": gasCoin.GetFullSymbol(), @@ -114,6 +125,7 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), "gas_coin": gasCoin.GetFullSymbol(), @@ -128,6 +140,7 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew Code: code.MultisigExists, Log: fmt.Sprintf("Multisig %s already exists", msigAddress.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.MultisigExists)), "multisig_address": msigAddress.String(), }), } diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index 1de880d2e..d8faee4b7 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -11,6 +11,7 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" "math/big" + "strconv" ) const minCommission = 0 @@ -28,7 +29,10 @@ func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.Chec if data.Stake == nil { return &Response{ Code: code.DecodeError, - Log: "Incorrect tx data"} + Log: "Incorrect tx data", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.DecodeError)), + })} } if !context.Coins().Exists(data.Coin) { @@ -36,6 +40,7 @@ func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.Chec Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Coin), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), "coin": fmt.Sprintf("%s", data.Coin), }), } @@ -46,6 +51,7 @@ func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.Chec Code: code.CandidateExists, Log: fmt.Sprintf("Candidate with such public key (%s) already exists", data.PubKey.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CandidateExists)), "public_key": data.PubKey.String(), }), } @@ -56,6 +62,7 @@ func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.Chec Code: code.PublicKeyInBlockList, Log: fmt.Sprintf("Candidate with such public key (%s) exists in block list", data.PubKey.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.PublicKeyInBlockList)), "public_key": data.PubKey.String(), }), } @@ -66,6 +73,7 @@ func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.Chec Code: code.WrongCommission, Log: fmt.Sprintf("Commission should be between 0 and 100"), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.WrongCommission)), "got_commission": fmt.Sprintf("%d", data.Commission), }), } @@ -102,7 +110,10 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r if checkState.Candidates().Count() >= maxCandidatesCount && !checkState.Candidates().IsNewCandidateStakeSufficient(data.Coin, data.Stake, maxCandidatesCount) { return Response{ Code: code.TooLowStake, - Log: fmt.Sprintf("Given stake is too low")} + Log: fmt.Sprintf("Given stake is too low"), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.TooLowStake)), + })} } commissionInBaseCoin := big.NewInt(0).Mul(big.NewInt(int64(tx.GasPrice)), big.NewInt(tx.Gas())) @@ -123,6 +134,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_reserve": gasCoin.Reserve().String(), "commission": commissionInBaseCoin.String(), "gas_coin": gasCoin.CName, @@ -138,6 +150,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), data.Stake, coin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": data.Stake.String(), "coin": coin.GetFullSymbol(), @@ -150,6 +163,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), "gas_coin": gasCoin.GetFullSymbol(), @@ -167,6 +181,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": totalTxCost.String(), "gas_coin": gasCoin.GetFullSymbol(), diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index ebdad638f..fe62cabe6 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -11,6 +11,7 @@ import ( "github.com/MinterTeam/minter-go-node/hexutil" "github.com/tendermint/tendermint/libs/kv" "math/big" + "strconv" ) type DelegateData struct { @@ -23,19 +24,28 @@ func (data DelegateData) BasicCheck(tx *Transaction, context *state.CheckState) if data.Value == nil { return &Response{ Code: code.DecodeError, - Log: "Incorrect tx data"} + Log: "Incorrect tx data", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.DecodeError)), + })} } if !context.Coins().Exists(tx.GasCoin) { return &Response{ Code: code.CoinNotExists, - Log: fmt.Sprintf("Coin %s not exists", tx.GasCoin)} + Log: fmt.Sprintf("Coin %s not exists", tx.GasCoin), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), + })} } if data.Value.Cmp(types.Big0) < 1 { return &Response{ Code: code.StakeShouldBePositive, - Log: fmt.Sprintf("Stake should be positive")} + Log: fmt.Sprintf("Stake should be positive"), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.StakeShouldBePositive)), + })} } if !context.Candidates().Exists(data.PubKey) { @@ -43,6 +53,7 @@ func (data DelegateData) BasicCheck(tx *Transaction, context *state.CheckState) Code: code.CandidateNotFound, Log: fmt.Sprintf("Candidate with such public key not found"), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CandidateNotFound)), "pub_key": data.PubKey.String(), }), } @@ -52,7 +63,11 @@ func (data DelegateData) BasicCheck(tx *Transaction, context *state.CheckState) if !context.Candidates().IsDelegatorStakeSufficient(sender, data.PubKey, data.Coin, data.Value) { return &Response{ Code: code.TooLowStake, - Log: fmt.Sprintf("Stake is too low")} + Log: fmt.Sprintf("Stake is too low"), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.TooLowStake)), + "pub_key": data.PubKey.String(), + })} } return nil diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index 58b965f36..072aa9841 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -10,6 +10,7 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" "math/big" + "strconv" ) type CandidateTx interface { @@ -60,6 +61,7 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa Code: code.NewPublicKeyIsBad, Log: fmt.Sprintf("Current public key (%s) equals new public key (%s)", data.PubKey.String(), data.NewPubKey.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.NewPublicKeyIsBad)), "public_key": data.PubKey.String(), "new_public_key": data.NewPubKey.String(), }), @@ -82,6 +84,7 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_reserve": gasCoin.Reserve().String(), "commission": commissionInBaseCoin.String(), "gas_coin": gasCoin.GetFullSymbol(), @@ -97,6 +100,7 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), "gas_coin": gasCoin.GetFullSymbol(), @@ -109,6 +113,7 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa Code: code.PublicKeyInBlockList, Log: fmt.Sprintf("Public key (%s) exists in block list", data.NewPubKey.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.PublicKeyInBlockList)), "new_public_key": data.NewPubKey.String(), }), } @@ -147,6 +152,7 @@ func checkCandidateOwnership(data CandidateTx, tx *Transaction, context *state.C Code: code.CandidateNotFound, Log: fmt.Sprintf("Candidate with such public key (%s) not found", data.GetPubKey().String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CandidateNotFound)), "public_key": data.GetPubKey().String(), }), } @@ -157,7 +163,11 @@ func checkCandidateOwnership(data CandidateTx, tx *Transaction, context *state.C if owner != sender { return &Response{ Code: code.IsNotOwnerOfCandidate, - Log: fmt.Sprintf("Sender is not an owner of a candidate")} + Log: fmt.Sprintf("Sender is not an owner of a candidate"), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.IsNotOwnerOfCandidate)), + }), + } } return nil diff --git a/core/transaction/edit_multisig_owners.go b/core/transaction/edit_multisig_owners.go index a6751654a..221954b22 100644 --- a/core/transaction/edit_multisig_owners.go +++ b/core/transaction/edit_multisig_owners.go @@ -10,6 +10,7 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" "math/big" + "strconv" ) type EditMultisigOwnersData struct { @@ -26,6 +27,7 @@ func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.Ch Code: code.MultisigNotExists, Log: "Multisig does not exists", Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.MultisigNotExists)), "multisig_address": sender.String(), }), } @@ -35,7 +37,11 @@ func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.Ch if lenWeights > 32 { return &Response{ Code: code.TooLargeOwnersList, - Log: fmt.Sprintf("Owners list is limited to 32 items")} + Log: fmt.Sprintf("Owners list is limited to 32 items"), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.TooLargeOwnersList)), + }), + } } lenAddresses := len(data.Addresses) @@ -44,6 +50,7 @@ func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.Ch Code: code.IncorrectWeights, Log: fmt.Sprintf("Incorrect multisig weights"), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.IncorrectWeights)), "count_weights": fmt.Sprintf("%d", lenWeights), "count_addresses": fmt.Sprintf("%d", lenAddresses), }), @@ -54,7 +61,11 @@ func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.Ch if weight > 1023 { return &Response{ Code: code.IncorrectWeights, - Log: "Incorrect multisig weights"} + Log: "Incorrect multisig weights", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.IncorrectWeights)), + }), + } } } @@ -63,7 +74,11 @@ func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.Ch if usedAddresses[address] { return &Response{ Code: code.DuplicatedAddresses, - Log: fmt.Sprintf("Duplicated multisig addresses")} + Log: fmt.Sprintf("Duplicated multisig addresses"), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.DuplicatedAddresses)), + }), + } } usedAddresses[address] = true @@ -78,6 +93,7 @@ func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.Ch Code: code.IncorrectWeights, Log: "Incorrect multisig weights", Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.IncorrectWeights)), "total_weight": fmt.Sprintf("%d", totalWeight), "threshold": fmt.Sprintf("%d", data.Threshold), }), @@ -125,6 +141,7 @@ func (data EditMultisigOwnersData) Run(tx *Transaction, context state.Interface, Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_reserve": gasCoin.Reserve().String(), "commission": commissionInBaseCoin.String(), "gas_coin": gasCoin.GetFullSymbol(), @@ -140,6 +157,7 @@ func (data EditMultisigOwnersData) Run(tx *Transaction, context state.Interface, Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), "gas_coin": gasCoin.GetFullSymbol(), diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index d0708be77..1d04d7cc7 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -10,6 +10,7 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" "math/big" + "strconv" ) type RecreateCoinData struct { @@ -25,37 +26,61 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta if data.InitialReserve == nil || data.InitialAmount == nil || data.MaxSupply == nil { return &Response{ Code: code.DecodeError, - Log: "Incorrect tx data"} + Log: "Incorrect tx data", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.DecodeError)), + }), + } } if len(data.Name) > maxCoinNameBytes { return &Response{ Code: code.InvalidCoinName, - Log: fmt.Sprintf("Coin name is invalid. Allowed up to %d bytes.", maxCoinNameBytes)} + Log: fmt.Sprintf("Coin name is invalid. Allowed up to %d bytes.", maxCoinNameBytes), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InvalidCoinName)), + }), + } } if data.ConstantReserveRatio < 10 || data.ConstantReserveRatio > 100 { return &Response{ Code: code.WrongCrr, - Log: fmt.Sprintf("Constant Reserve Ratio should be between 10 and 100")} + Log: fmt.Sprintf("Constant Reserve Ratio should be between 10 and 100"), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.WrongCrr)), + }), + } } if data.InitialAmount.Cmp(minCoinSupply) == -1 || data.InitialAmount.Cmp(data.MaxSupply) == 1 { return &Response{ Code: code.WrongCoinSupply, - Log: fmt.Sprintf("Coin supply should be between %s and %s", minCoinSupply.String(), data.MaxSupply.String())} + Log: fmt.Sprintf("Coin supply should be between %s and %s", minCoinSupply.String(), data.MaxSupply.String()), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.WrongCoinSupply)), + }), + } } if data.MaxSupply.Cmp(maxCoinSupply) == 1 { return &Response{ Code: code.WrongCoinSupply, - Log: fmt.Sprintf("Max coin supply should be less than %s", maxCoinSupply)} + Log: fmt.Sprintf("Max coin supply should be less than %s", maxCoinSupply), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.WrongCoinSupply)), + }), + } } if data.InitialReserve.Cmp(minCoinReserve) == -1 { return &Response{ Code: code.WrongCoinSupply, - Log: fmt.Sprintf("Coin reserve should be greater than or equal to %s", minCoinReserve.String())} + Log: fmt.Sprintf("Coin reserve should be greater than or equal to %s", minCoinReserve.String()), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.WrongCoinSupply)), + }), + } } sender, _ := tx.Sender() @@ -65,6 +90,9 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Symbol), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), + }), } } @@ -73,6 +101,9 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta return &Response{ Code: code.IsNotOwnerOfCoin, Log: "Sender is not owner of coin", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.IsNotOwnerOfCoin)), + }), } } @@ -118,6 +149,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Gas coin reserve balance is not sufficient for transaction. Has: %s %s, required %s %s", gasCoin.Reserve().String(), types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": gasCoin.Reserve().String(), "required_value": commissionInBaseCoin.String(), "gas_coin": gasCoin.GetFullSymbol(), @@ -135,6 +167,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), "gas_coin": gasCoin.GetFullSymbol(), @@ -147,6 +180,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), data.InitialReserve.String(), types.GetBaseCoin()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_reserve": data.InitialReserve.String(), "base_coin": fmt.Sprintf("%s", types.GetBaseCoin()), @@ -166,6 +200,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": totalTxCost.String(), "gas_coin": gasCoin.GetFullSymbol(), diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index 07a28d8c1..65862aa39 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -15,6 +15,7 @@ import ( "github.com/MinterTeam/minter-go-node/rlp" "github.com/tendermint/tendermint/libs/kv" "math/big" + "strconv" ) type RedeemCheckData struct { @@ -26,14 +27,20 @@ func (data RedeemCheckData) BasicCheck(tx *Transaction, context *state.CheckStat if data.RawCheck == nil { return &Response{ Code: code.DecodeError, - Log: "Incorrect tx data"} + Log: "Incorrect tx data", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.DecodeError)), + })} } // fixed potential problem with making too high commission for sender if tx.GasPrice != 1 { return &Response{ Code: code.TooHighGasPrice, - Log: fmt.Sprintf("Gas price for check is limited to 1")} + Log: fmt.Sprintf("Gas price for check is limited to 1"), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.TooHighGasPrice)), + })} } return nil @@ -66,6 +73,9 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.DecodeError, Log: err.Error(), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.DecodeError)), + }), } } @@ -74,6 +84,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward Code: code.WrongChainID, Log: "Wrong chain id", Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.WrongChainID)), "current_chain_id": fmt.Sprintf("%d", types.CurrentChainID), "got_chain_id": fmt.Sprintf("%d", decodedCheck.ChainID), }), @@ -84,6 +95,9 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.TooLongNonce, Log: "Nonce is too big. Should be up to 16 bytes.", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.TooLongNonce)), + }), } } @@ -92,7 +106,10 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward if err != nil { return Response{ Code: code.DecodeError, - Log: err.Error()} + Log: err.Error(), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.DecodeError)), + })} } if !checkState.Coins().Exists(decodedCheck.Coin) { @@ -100,6 +117,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward Code: code.CoinNotExists, Log: fmt.Sprintf("Coin not exists"), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), "coin": fmt.Sprintf("%s", decodedCheck.Coin), }), } @@ -110,6 +128,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward Code: code.CoinNotExists, Log: fmt.Sprintf("Gas coin not exists"), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), "gas_coin": fmt.Sprintf("%s", decodedCheck.GasCoin), }), } @@ -120,6 +139,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward Code: code.WrongGasCoin, Log: fmt.Sprintf("Gas coin for redeem check transaction can only be %s", decodedCheck.GasCoin), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.WrongGasCoin)), "gas_coin": fmt.Sprintf("%s", decodedCheck.GasCoin), }), } @@ -129,7 +149,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.CheckExpired, Log: fmt.Sprintf("Check expired"), - Info: EncodeError(map[string]string{ + Info: EncodeError(map[string]string{"code": strconv.Itoa(int(code.CheckExpired)), "due_block": fmt.Sprintf("%d", decodedCheck.DueBlock), "current_block": fmt.Sprintf("%d", currentBlock), }), @@ -139,7 +159,11 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward if checkState.Checks().IsCheckUsed(decodedCheck) { return Response{ Code: code.CheckUsed, - Log: fmt.Sprintf("Check already redeemed")} + Log: fmt.Sprintf("Check already redeemed"), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CheckUsed)), + }), + } } lockPublicKey, err := decodedCheck.LockPubKey() @@ -148,6 +172,9 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.DecodeError, Log: err.Error(), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.DecodeError)), + }), } } @@ -164,13 +191,18 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.DecodeError, Log: err.Error(), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.DecodeError)), + }), } } if !bytes.Equal(lockPublicKey, pub) { return Response{ Code: code.CheckInvalidLock, - Log: "Invalid proof", + Log: "Invalid proof", Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CheckInvalidLock)), + }), } } @@ -196,6 +228,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", decodedCheck.Coin, checkSender.String(), totalTxCost.String(), coin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": checkSender.String(), "coin": coin.GetFullSymbol(), "total_tx_cost": totalTxCost.String(), @@ -208,6 +241,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", checkSender.String(), decodedCheck.Coin, decodedCheck.Value.String(), coin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": checkSender.String(), "coin": coin.GetFullSymbol(), "value": decodedCheck.Value.String(), @@ -220,6 +254,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", checkSender.String(), decodedCheck.GasCoin, commission.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "gas_coin": gasCoin.GetFullSymbol(), "commission": commission.String(), diff --git a/core/transaction/sell_all_coin.go b/core/transaction/sell_all_coin.go index 180e146d6..d29899543 100644 --- a/core/transaction/sell_all_coin.go +++ b/core/transaction/sell_all_coin.go @@ -10,6 +10,7 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" "math/big" + "strconv" ) type SellAllCoinData struct { @@ -43,6 +44,7 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat Code: code.MinimumValueToBuyReached, Log: fmt.Sprintf("You wanted to get minimum %s, but currently you will get %s", data.MinimumValueToBuy.String(), value.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), "minimum_value_to_buy": data.MinimumValueToBuy.String(), "coin": value.String(), }), @@ -70,6 +72,7 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat Code: code.MinimumValueToBuyReached, Log: fmt.Sprintf("You wanted to get minimum %s, but currently you will get %s", data.MinimumValueToBuy.String(), ret.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), "minimum_value_to_buy": data.MinimumValueToBuy.String(), "will_get_value": ret.String(), }), @@ -80,6 +83,9 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat return nil, nil, nil, &Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account"), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), + }), } } @@ -103,6 +109,9 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat return nil, nil, nil, &Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account"), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), + }), } } @@ -114,6 +123,7 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat Code: code.MinimumValueToBuyReached, Log: fmt.Sprintf("You wanted to get minimum %s, but currently you will get %s", data.MinimumValueToBuy.String(), value.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), "minimum_value_to_buy": data.MinimumValueToBuy.String(), "will_get_value": value.String(), }), @@ -143,6 +153,7 @@ func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.CheckStat Code: code.CrossConvert, Log: fmt.Sprintf("\"From\" coin equals to \"to\" coin"), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CrossConvert)), "coin_to_sell": fmt.Sprintf("%s", data.CoinToSell), "coin_to_buy": fmt.Sprintf("%s", data.CoinToBuy), }), @@ -154,6 +165,7 @@ func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.CheckStat Code: code.CoinNotExists, Log: fmt.Sprintf("Coin to sell not exists"), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), "coin_to_sell": fmt.Sprintf("%s", data.CoinToSell), }), } @@ -164,6 +176,7 @@ func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.CheckStat Code: code.CoinNotExists, Log: fmt.Sprintf("Coin to buy not exists"), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), "coin_to_buy": fmt.Sprintf("%s", data.CoinToBuy), }), } @@ -211,6 +224,7 @@ func (data SellAllCoinData) Run(tx *Transaction, context state.Interface, reward ts.Value.String(), coin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": ts.Value.String(), "coin": coin.GetFullSymbol(), diff --git a/core/transaction/sell_coin.go b/core/transaction/sell_coin.go index 7992a0a16..8d08d4429 100644 --- a/core/transaction/sell_coin.go +++ b/core/transaction/sell_coin.go @@ -10,6 +10,7 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" "math/big" + "strconv" ) type SellCoinData struct { @@ -36,6 +37,9 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) return nil, nil, nil, &Response{ Code: code.MinimumValueToBuyReached, Log: fmt.Sprintf("You wanted to get minimum %s, but currently you will get %s", data.MinimumValueToBuy.String(), value.String()), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), + }), } } @@ -79,6 +83,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) Code: code.MinimumValueToBuyReached, Log: fmt.Sprintf("You wanted to get minimum %s, but currently you will get %s", data.MinimumValueToBuy.String(), value.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), "minimum_value_to_buy": data.MinimumValueToBuy.String(), "value_to_buy": value.String(), }), @@ -106,6 +111,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) commissionInBaseCoin.String(), types.GetBaseCoin()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coin.Reserve().String(), "required_value": commissionInBaseCoin.String(), "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), @@ -157,6 +163,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) commissionInBaseCoin.String(), types.GetBaseCoin()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has": coinFrom.Reserve().String(), "required": commissionInBaseCoin.String(), "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), @@ -182,6 +189,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) Code: code.MinimumValueToBuyReached, Log: fmt.Sprintf("You wanted to get minimum %s, but currently you will get %s", data.MinimumValueToBuy.String(), value.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), "minimum_value_to_buy": data.MinimumValueToBuy.String(), "get_value": value.String(), }), @@ -239,6 +247,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) commissionInBaseCoin.String(), types.GetBaseCoin()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coin.Reserve().String(), "required_value": commissionInBaseCoin.String(), "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), @@ -265,7 +274,11 @@ func (data SellCoinData) BasicCheck(tx *Transaction, context *state.CheckState) if data.ValueToSell == nil { return &Response{ Code: code.DecodeError, - Log: "Incorrect tx data"} + Log: "Incorrect tx data", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CrossConvert)), + }), + } } if data.CoinToSell == data.CoinToBuy { @@ -273,6 +286,7 @@ func (data SellCoinData) BasicCheck(tx *Transaction, context *state.CheckState) Code: code.CrossConvert, Log: fmt.Sprintf("\"From\" coin equals to \"to\" coin"), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CrossConvert)), "coin_to_sell": fmt.Sprintf("%s", data.CoinToSell), "coin_to_buy": fmt.Sprintf("%s", data.CoinToBuy), }), @@ -284,6 +298,7 @@ func (data SellCoinData) BasicCheck(tx *Transaction, context *state.CheckState) Code: code.CoinNotExists, Log: fmt.Sprintf("Coin not exists"), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), "coin_to_sell": fmt.Sprintf("%s", data.CoinToSell), }), } @@ -294,6 +309,7 @@ func (data SellCoinData) BasicCheck(tx *Transaction, context *state.CheckState) Code: code.CoinNotExists, Log: fmt.Sprintf("Coin not exists"), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), "coin_to_buy": fmt.Sprintf("%s", data.CoinToBuy), }), } @@ -341,6 +357,7 @@ func (data SellCoinData) Run(tx *Transaction, context state.Interface, rewardPoo coin.GetFullSymbol(), ), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": ts.Value.String(), "coin": coin.GetFullSymbol(), diff --git a/core/transaction/send.go b/core/transaction/send.go index 42417cb01..8830f2c92 100644 --- a/core/transaction/send.go +++ b/core/transaction/send.go @@ -10,6 +10,7 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" "math/big" + "strconv" ) type SendData struct { @@ -45,6 +46,7 @@ func (data SendData) TotalSpend(tx *Transaction, context *state.CheckState) (Tot coin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has": coin.Reserve().String(), "required": commissionInBaseCoin.String(), }), @@ -70,7 +72,11 @@ func (data SendData) BasicCheck(tx *Transaction, context *state.CheckState) *Res if data.Value == nil { return &Response{ Code: code.DecodeError, - Log: "Incorrect tx data"} + Log: "Incorrect tx data", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), + }), + } } if !context.Coins().Exists(data.Coin) { @@ -78,6 +84,7 @@ func (data SendData) BasicCheck(tx *Transaction, context *state.CheckState) *Res Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Coin), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), "coin": fmt.Sprintf("%s", data.Coin), }), } @@ -125,6 +132,7 @@ func (data SendData) Run(tx *Transaction, context state.Interface, rewardPool *b ts.Value.String(), coin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": ts.Value.String(), "coin": coin.GetFullSymbol(), diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index f35f551dc..e0649c289 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -13,6 +13,7 @@ import ( "github.com/MinterTeam/minter-go-node/crypto/sha3" "github.com/MinterTeam/minter-go-node/rlp" "math/big" + "strconv" ) type TxType byte @@ -304,6 +305,7 @@ func CheckForCoinSupplyOverflow(current *big.Int, delta *big.Int, max *big.Int) Code: code.CoinSupplyOverflow, Log: "coin supply overflow", Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinSupplyOverflow)), "current": total.String(), "delta": delta.String(), "max": max.String(), @@ -323,6 +325,7 @@ func CheckReserveUnderflow(m *coins.Model, delta *big.Int) *Response { Code: code.CoinReserveUnderflow, Log: fmt.Sprintf("coin %s reserve is too small (%s, required at least %s)", m.GetFullSymbol(), m.Reserve().String(), min.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveUnderflow)), "coin": m.Symbol().String(), "coin_reserve": m.Reserve().String(), "min_coin_reserve": min.String(), diff --git a/go.mod b/go.mod index 6239f2a87..a1dc4db5d 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,7 @@ require ( github.com/tendermint/iavl v0.14.0 github.com/tendermint/tendermint v0.33.8 github.com/tendermint/tm-db v0.5.1 + github.com/tidwall/gjson v1.6.1 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 github.com/urfave/cli/v2 v2.0.0 gitlab.com/tslocum/cview v1.4.7 diff --git a/go.sum b/go.sum index c076aaf0c..ddc4d4e0c 100644 --- a/go.sum +++ b/go.sum @@ -471,6 +471,12 @@ github.com/tendermint/tendermint v0.33.8 h1:Xxu4QhpqcomSE0iQDw1MqLgfsa8fqtPtWFJK github.com/tendermint/tendermint v0.33.8/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM= github.com/tendermint/tm-db v0.5.1 h1:H9HDq8UEA7Eeg13kdYckkgwwkQLBnJGgX4PgLJRhieY= github.com/tendermint/tm-db v0.5.1/go.mod h1:g92zWjHpCYlEvQXvy9M168Su8V1IBEeawpXVVBaK4f4= +github.com/tidwall/gjson v1.6.1 h1:LRbvNuNuvAiISWg6gxLEFuCe72UKy5hDqhxW/8183ws= +github.com/tidwall/gjson v1.6.1/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0= +github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc= +github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= +github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU= +github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= From 5041a4cee7ad08bc21a5b4d1027f95fdbcddc233 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Thu, 3 Sep 2020 13:24:02 +0300 Subject: [PATCH 199/426] Fix linter errors --- core/events/store.go | 2 ++ core/minter/minter.go | 75 +++++++++++++++++++++++++------------------ 2 files changed, 46 insertions(+), 31 deletions(-) diff --git a/core/events/store.go b/core/events/store.go index 6d6949547..6cdb61906 100644 --- a/core/events/store.go +++ b/core/events/store.go @@ -7,6 +7,7 @@ import ( "sync" ) +// IEventsDB is an interface of Events type IEventsDB interface { AddEvent(height uint32, event Event) LoadEvents(height uint32) Events @@ -30,6 +31,7 @@ type pendingEvents struct { items Events } +// NewEventsStore creates new events store in given DB func NewEventsStore(db db.DB) IEventsDB { codec := amino.NewCodec() codec.RegisterInterface((*Event)(nil), nil) diff --git a/core/minter/minter.go b/core/minter/minter.go index 1302cabf7..fa3489239 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -38,24 +38,26 @@ import ( "time" ) +// Statuses of validators const ( - // Global validator's statuses ValidatorPresent = 1 ValidatorAbsent = 2 +) - BlockMaxBytes = 10000000 - - DefaultMaxGas = 100000 - MinMaxGas = 5000 - - VotingPowerConsensus = 2. / 3. +// Block params +const ( + blockMaxBytes = 10000000 + defaultMaxGas = 100000 + minMaxGas = 5000 ) +const votingPowerConsensus = 2. / 3. + var ( blockchain *Blockchain ) -// Main structure of Minter Blockchain +// Blockchain is a main structure of Minter type Blockchain struct { abciTypes.BaseApplication @@ -82,7 +84,7 @@ type Blockchain struct { cfg *config.Config } -// Creates Minter Blockchain instance, should be only called once +// NewMinterBlockchain creates Minter Blockchain instance, should be only called once func NewMinterBlockchain(cfg *config.Config) *Blockchain { var err error @@ -124,7 +126,7 @@ func NewMinterBlockchain(cfg *config.Config) *Blockchain { return blockchain } -// Initialize blockchain with validators and other info. Only called once. +// InitChain initialize blockchain with validators and other info. Only called once. func (app *Blockchain) InitChain(req abciTypes.RequestInitChain) abciTypes.ResponseInitChain { var genesisState types.AppState if err := amino.UnmarshalJSON(req.AppStateBytes, &genesisState); err != nil { @@ -165,7 +167,7 @@ func (app *Blockchain) InitChain(req abciTypes.RequestInitChain) abciTypes.Respo } } -// Signals the beginning of a block. +// BeginBlock signals the beginning of a block. func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.ResponseBeginBlock { height := uint64(req.Header.Height) @@ -242,7 +244,7 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res return abciTypes.ResponseBeginBlock{} } -// Signals the end of a block, returns changes to the validator set +// EndBlock signals the end of a block, returns changes to the validator set func (app *Blockchain) EndBlock(req abciTypes.RequestEndBlock) abciTypes.ResponseEndBlock { height := uint64(req.Height) @@ -376,14 +378,14 @@ func (app *Blockchain) EndBlock(req abciTypes.RequestEndBlock) abciTypes.Respons ValidatorUpdates: updates, ConsensusParamUpdates: &abciTypes.ConsensusParams{ Block: &abciTypes.BlockParams{ - MaxBytes: BlockMaxBytes, + MaxBytes: blockMaxBytes, MaxGas: int64(app.stateDeliver.App.GetMaxGas()), }, }, } } -// Return application info. Used for synchronization between Tendermint and Minter +// Info return application info. Used for synchronization between Tendermint and Minter func (app *Blockchain) Info(req abciTypes.RequestInfo) (resInfo abciTypes.ResponseInfo) { return abciTypes.ResponseInfo{ Version: version.Version, @@ -393,7 +395,7 @@ func (app *Blockchain) Info(req abciTypes.RequestInfo) (resInfo abciTypes.Respon } } -// Deliver a tx for full processing +// DeliverTx deliver a tx for full processing func (app *Blockchain) DeliverTx(req abciTypes.RequestDeliverTx) abciTypes.ResponseDeliverTx { response := transaction.RunTx(app.stateDeliver, req.Tx, app.rewards, app.height, &sync.Map{}, 0) @@ -413,7 +415,7 @@ func (app *Blockchain) DeliverTx(req abciTypes.RequestDeliverTx) abciTypes.Respo } } -// Validate a tx for the mempool +// CheckTx validates a tx for the mempool func (app *Blockchain) CheckTx(req abciTypes.RequestCheckTx) abciTypes.ResponseCheckTx { response := transaction.RunTx(app.stateCheck, req.Tx, nil, app.height, app.currentMempool, app.MinGasPrice()) @@ -467,23 +469,25 @@ func (app *Blockchain) Commit() abciTypes.ResponseCommit { } } -// Unused method, required by Tendermint +// Query Unused method, required by Tendermint func (app *Blockchain) Query(reqQuery abciTypes.RequestQuery) abciTypes.ResponseQuery { return abciTypes.ResponseQuery{} } -// Unused method, required by Tendermint +// SetOption Unused method, required by Tendermint func (app *Blockchain) SetOption(req abciTypes.RequestSetOption) abciTypes.ResponseSetOption { return abciTypes.ResponseSetOption{} } -// Gracefully stopping Minter Blockchain instance +// Stop gracefully stopping Minter Blockchain instance func (app *Blockchain) Stop() { app.appDB.Close() - app.stateDB.Close() + if err := app.stateDB.Close(); err != nil { + panic(err) + } } -// Get immutable state of Minter Blockchain +// CurrentState returns immutable state of Minter Blockchain func (app *Blockchain) CurrentState() *state.CheckState { app.lock.RLock() defer app.lock.RUnlock() @@ -491,7 +495,7 @@ func (app *Blockchain) CurrentState() *state.CheckState { return app.stateCheck } -// Get immutable state of Minter Blockchain for given height +// GetStateForHeight returns immutable state of Minter Blockchain for given height func (app *Blockchain) GetStateForHeight(height uint64) (*state.CheckState, error) { if height > 0 { s, err := state.NewCheckStateAtHeight(height, app.stateDB) @@ -503,6 +507,7 @@ func (app *Blockchain) GetStateForHeight(height uint64) (*state.CheckState, erro return blockchain.CurrentState(), nil } +// MissedBlocks returns aggregated info about block which has no signature of given validator func (app *Blockchain) MissedBlocks(pubKey string, height uint64) (missedBlocks string, missedBlocksCount int, err error) { if !strings.HasPrefix(pubKey, "Mp") { return "", 0, status.Error(codes.InvalidArgument, "public key don't has prefix 'Mp'") @@ -531,17 +536,17 @@ func (app *Blockchain) MissedBlocks(pubKey string, height uint64) (missedBlocks } -// Get current height of Minter Blockchain +// Height returns current height of Minter Blockchain func (app *Blockchain) Height() uint64 { return atomic.LoadUint64(&app.height) } -// Set Tendermint node +// SetTmNode sets Tendermint node func (app *Blockchain) SetTmNode(node *tmNode.Node) { app.tmNode = node } -// Get minimal acceptable gas price +// MinGasPrice returns minimal acceptable gas price func (app *Blockchain) MinGasPrice() uint32 { mempoolSize := app.tmNode.Mempool().Size() @@ -598,10 +603,12 @@ func (app *Blockchain) updateBlocksTimeDelta(height uint64, count int64) { app.appDB.SetLastBlocksTimeDelta(height, delta) } +// SetBlocksTimeDelta sets current blocks time delta func (app *Blockchain) SetBlocksTimeDelta(height uint64, value int) { app.appDB.SetLastBlocksTimeDelta(height, value) } +// GetBlocksTimeDelta returns current blocks time delta func (app *Blockchain) GetBlocksTimeDelta(height, count uint64) (int, error) { return app.appDB.GetLastBlocksTimeDelta(height) } @@ -612,7 +619,7 @@ func (app *Blockchain) calcMaxGas(height uint64) uint64 { // skip first 20 blocks if height <= 20 { - return DefaultMaxGas + return defaultMaxGas } // get current max gas @@ -626,31 +633,35 @@ func (app *Blockchain) calcMaxGas(height uint64) uint64 { } // check if max gas is too high - if newMaxGas > DefaultMaxGas { - newMaxGas = DefaultMaxGas + if newMaxGas > defaultMaxGas { + newMaxGas = defaultMaxGas } // check if max gas is too low - if newMaxGas < MinMaxGas { - newMaxGas = MinMaxGas + if newMaxGas < minMaxGas { + newMaxGas = minMaxGas } return newMaxGas } +// GetEventsDB returns current EventsDB func (app *Blockchain) GetEventsDB() eventsdb.IEventsDB { return app.eventsDB } +// SetStatisticData used for collection statistics about blockchain operations func (app *Blockchain) SetStatisticData(statisticData *statistics.Data) *statistics.Data { app.statisticData = statisticData return app.statisticData } +// StatisticData used for collection statistics about blockchain operations func (app *Blockchain) StatisticData() *statistics.Data { return app.statisticData } +// GetValidatorStatus returns given validator's status func (app *Blockchain) GetValidatorStatus(address types.TmAddress) int8 { app.lock.RLock() defer app.lock.RUnlock() @@ -658,6 +669,7 @@ func (app *Blockchain) GetValidatorStatus(address types.TmAddress) int8 { return app.validatorsStatuses[address] } +// MaxPeerHeight returns max height of connected peers func (app *Blockchain) MaxPeerHeight() int64 { var max int64 for _, peer := range app.tmNode.Switch().Peers().List() { @@ -669,6 +681,7 @@ func (app *Blockchain) MaxPeerHeight() int64 { return max } +// DeleteStateVersions deletes states in given range func (app *Blockchain) DeleteStateVersions(from, to int64) error { app.lock.RLock() defer app.lock.RUnlock() @@ -725,7 +738,7 @@ func (app *Blockchain) isApplicationHalted(height uint64) bool { new(big.Float).SetInt(totalPower), ) - if votingResult.Cmp(big.NewFloat(VotingPowerConsensus)) == 1 { + if votingResult.Cmp(big.NewFloat(votingPowerConsensus)) == 1 { return true } } From dae38e15264297db0619ba845c863f9ad3664f6c Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Thu, 3 Sep 2020 13:26:07 +0300 Subject: [PATCH 200/426] Fix linter errors --- core/rewards/rewards.go | 6 ++++-- core/validators/validators.go | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/core/rewards/rewards.go b/core/rewards/rewards.go index 4773a3698..ddc09530b 100644 --- a/core/rewards/rewards.go +++ b/core/rewards/rewards.go @@ -11,8 +11,9 @@ const firstReward = 333 const lastReward = 68 var startHeight uint64 = 0 -var BeforeGenesis = big.NewInt(0) +var beforeGenesis = big.NewInt(0) +// GetRewardForBlock returns reward for creation of given block. If there is no reward - returns 0. func GetRewardForBlock(blockHeight uint64) *big.Int { blockHeight += startHeight @@ -34,9 +35,10 @@ func GetRewardForBlock(blockHeight uint64) *big.Int { return helpers.BipToPip(reward) } +// SetStartHeight sets base height for rewards calculations func SetStartHeight(sHeight uint64) { for i := uint64(1); i <= sHeight; i++ { - BeforeGenesis.Add(BeforeGenesis, GetRewardForBlock(i)) + beforeGenesis.Add(beforeGenesis, GetRewardForBlock(i)) } startHeight = sHeight diff --git a/core/validators/validators.go b/core/validators/validators.go index 974b27baa..f7e254646 100644 --- a/core/validators/validators.go +++ b/core/validators/validators.go @@ -1,9 +1,11 @@ package validators +// GetValidatorsCountForBlock returns available validators slots for given height func GetValidatorsCountForBlock(block uint64) int { return 64 } +// GetCandidatesCountForBlock returns available candidates slots for given height func GetCandidatesCountForBlock(block uint64) int { return 192 } From f03ea247cb873d67e53c6bc0afbbb44b26932d64 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 3 Sep 2020 13:29:47 +0300 Subject: [PATCH 201/426] errors code --- api/v2/v2.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/v2/v2.go b/api/v2/v2.go index fb491a400..3cec1cc00 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -23,6 +23,7 @@ import ( "net" "net/http" "os" + "strconv" "strings" "time" ) @@ -130,7 +131,7 @@ func contextWithTimeoutInterceptor(timeout time.Duration) func(ctx context.Conte } func parseStatus(s *status.Status) (string, map[string]interface{}) { - codeString := "400" + codeString := strconv.Itoa(int(s.Code())) var data map[string]interface{} details := s.Details() if len(details) != 0 { From 683df6a1676cf47df9e0df6b51d801859fcb2db3 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Thu, 3 Sep 2020 13:37:27 +0300 Subject: [PATCH 202/426] Update dist script --- scripts/dist.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/dist.sh b/scripts/dist.sh index bd934464a..3507930af 100644 --- a/scripts/dist.sh +++ b/scripts/dist.sh @@ -51,17 +51,17 @@ for PLATFORM in $(find ./build/pkg -mindepth 1 -maxdepth 1 -type d); do popd >/dev/null 2>&1 done -# Add "minter" and $VERSION prefix to package name. +# Add "minter" and $VERSION, $GIT_COMMIT prefix to package name. rm -rf ./build/dist mkdir -p ./build/dist for FILENAME in $(find ./build/pkg -mindepth 1 -maxdepth 1 -type f); do FILENAME=$(basename "$FILENAME") - cp "./build/pkg/${FILENAME}" "./build/dist/minter_${VERSION}_${FILENAME}" + cp "./build/pkg/${FILENAME}" "./build/dist/minter_${VERSION}_${GIT_COMMIT}_${FILENAME}" done # Make the checksums. pushd ./build/dist -shasum -a256 ./* > "./minter_${VERSION}_SHA256SUMS" +shasum -a256 ./* > "./minter_${VERSION}_${GIT_COMMIT}_SHA256SUMS" popd # Done From 501a7c30462869003860b3c27d3445fa190174f2 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 3 Sep 2020 22:45:31 +0300 Subject: [PATCH 203/426] errors code fix --- api/v2/v2.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v2/v2.go b/api/v2/v2.go index 3cec1cc00..337b4a09f 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -131,7 +131,7 @@ func contextWithTimeoutInterceptor(timeout time.Duration) func(ctx context.Conte } func parseStatus(s *status.Status) (string, map[string]interface{}) { - codeString := strconv.Itoa(int(s.Code())) + codeString := strconv.Itoa(runtime.HTTPStatusFromCode(s.Code())) var data map[string]interface{} details := s.Details() if len(details) != 0 { From 4619af5c331c000a9bdae892c469360b50413f13 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 3 Sep 2020 23:02:00 +0300 Subject: [PATCH 204/426] errors code fix --- core/transaction/unbond.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 0d6e413df..5e908d784 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -11,6 +11,7 @@ import ( "github.com/MinterTeam/minter-go-node/hexutil" "github.com/tendermint/tendermint/libs/kv" "math/big" + "strconv" ) const unbondPeriod = 518400 @@ -33,6 +34,7 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Coin), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), "coin": fmt.Sprintf("%s", data.Coin), }), } @@ -43,6 +45,7 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R "unbound_value": data.Value.String(), } if !context.Candidates().Exists(data.PubKey) { + errorInfo["code"] = strconv.Itoa(int(code.CandidateNotFound)) return &Response{ Code: code.CandidateNotFound, Log: fmt.Sprintf("Candidate with such public key not found"), @@ -58,6 +61,7 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R return nil } errorInfo["waitlist_value"] = waitlist.Value.String() + errorInfo["code"] = strconv.Itoa(int(code.InsufficientWaitList)) return &Response{ Code: code.InsufficientWaitList, Log: fmt.Sprintf("Insufficient amount at waitlist for sender account"), @@ -68,6 +72,7 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R stake := context.Candidates().GetStakeValueOfAddress(data.PubKey, sender, data.Coin) if stake == nil { + errorInfo["code"] = strconv.Itoa(int(code.StakeNotFound)) return &Response{ Code: code.StakeNotFound, Log: fmt.Sprintf("Stake of current user not found"), @@ -77,6 +82,7 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R if stake.Cmp(data.Value) < 0 { errorInfo["stake_value"] = stake.String() + errorInfo["code"] = strconv.Itoa(int(code.InsufficientStake)) return &Response{ Code: code.InsufficientStake, Log: fmt.Sprintf("Insufficient stake for sender account"), @@ -126,6 +132,7 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_reserve": gasCoin.Reserve().String(), "commission": commissionInBaseCoin.String(), "gas_coin": gasCoin.GetFullSymbol(), @@ -141,6 +148,7 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), "gas_coin": gasCoin.GetFullSymbol(), From 152a05372251ddd3d7548f167db0e019c00e9b69 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 3 Sep 2020 23:08:03 +0300 Subject: [PATCH 205/426] errors code fix --- core/transaction/buy_coin.go | 22 ++++++++++++++++++++-- core/transaction/delegate.go | 3 +++ core/transaction/redeem_check.go | 3 ++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/core/transaction/buy_coin.go b/core/transaction/buy_coin.go index 2fe9701ac..8f6a40248 100644 --- a/core/transaction/buy_coin.go +++ b/core/transaction/buy_coin.go @@ -158,6 +158,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( baseCoinNeeded.String(), types.GetBaseCoin()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coinFrom.Reserve().String(), "required_value": commissionInBaseCoin.String(), "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), @@ -183,6 +184,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( commissionInBaseCoin.String(), types.GetBaseCoin()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coinTo.Reserve().String(), "required_value": commissionInBaseCoin.String(), "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), @@ -209,6 +211,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( Log: fmt.Sprintf("You wanted to sell maximum %s, but currently you need to spend %s to complete tx", data.MaximumValueToSell.String(), value.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.MaximumValueToSellReached)), "maximum_value_to_sell": data.MaximumValueToSell.String(), "needed_spend_value": value.String(), }), @@ -233,6 +236,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( commissionInBaseCoin.String(), types.GetBaseCoin()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coinFrom.Reserve().String(), "required_value": commissionInBaseCoin.String(), "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), @@ -256,6 +260,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( Code: code.MaximumValueToSellReached, Log: fmt.Sprintf("You wanted to sell maximum %s, but currently you need to spend %s to complete tx", data.MaximumValueToSell.String(), totalValue.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.MaximumValueToSellReached)), "maximum_value_to_sell": data.MaximumValueToSell.String(), "needed_spend_value": value.String(), }), @@ -289,6 +294,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( commissionInBaseCoin.String(), types.GetBaseCoin()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coin.Reserve().String(), "required_value": commissionInBaseCoin.String(), "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), @@ -315,13 +321,22 @@ func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.CheckState) * if data.ValueToBuy == nil { return &Response{ Code: code.DecodeError, - Log: "Incorrect tx data"} + Log: "Incorrect tx data", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.DecodeError)), + }), + } + } if data.CoinToSell == data.CoinToBuy { return &Response{ Code: code.CrossConvert, - Log: fmt.Sprintf("\"From\" coin equals to \"to\" coin")} + Log: fmt.Sprintf("\"From\" coin equals to \"to\" coin"), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CrossConvert)), + }), + } } if !context.Coins().Exists(data.CoinToSell) { @@ -329,6 +344,7 @@ func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.CheckState) * Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.CoinToSell), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), "coin_to_sell": fmt.Sprintf("%s", data.CoinToSell), }), } @@ -339,6 +355,7 @@ func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.CheckState) * Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.CoinToBuy), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), "coin_to_buy": fmt.Sprintf("%s", data.CoinToBuy), }), } @@ -377,6 +394,7 @@ func (data BuyCoinData) Run(tx *Transaction, context state.Interface, rewardPool ts.Value.String(), coin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": ts.Value.String(), "coin": coin.GetFullSymbol(), diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index fe62cabe6..9c6284839 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -113,6 +113,7 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_reserve": gasCoin.Reserve().String(), "commission": commissionInBaseCoin.String(), "gas_coin": gasCoin.GetFullSymbol(), @@ -128,6 +129,7 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), "gas_coin": gasCoin.GetFullSymbol(), @@ -140,6 +142,7 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), data.Value, coin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": data.Value.String(), "coin": coin.GetFullSymbol(), diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index 65862aa39..6ebf0c34f 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -149,7 +149,8 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.CheckExpired, Log: fmt.Sprintf("Check expired"), - Info: EncodeError(map[string]string{"code": strconv.Itoa(int(code.CheckExpired)), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CheckExpired)), "due_block": fmt.Sprintf("%d", decodedCheck.DueBlock), "current_block": fmt.Sprintf("%d", currentBlock), }), From f0b8d682533167c649a1e1c85ca3076b29a73810 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 4 Sep 2020 00:22:19 +0300 Subject: [PATCH 206/426] detail error rename --- core/transaction/buy_coin.go | 2 +- core/transaction/change_coin_owner.go | 4 +++- core/transaction/create_coin.go | 4 +++- core/transaction/create_multisig.go | 8 ++++---- core/transaction/declare_candidacy.go | 8 ++++---- core/transaction/delegate.go | 8 ++++---- core/transaction/edit_candidate.go | 8 ++++---- core/transaction/edit_multisig_owners.go | 8 ++++---- core/transaction/multisend.go | 8 +++++--- core/transaction/price_vote.go | 6 +++--- core/transaction/recreate_coin.go | 2 +- core/transaction/sell_coin.go | 12 ++++++------ core/transaction/send.go | 7 ++++--- core/transaction/set_halt_block.go | 7 ++++--- core/transaction/switch_candidate_status.go | 12 ++++++------ core/transaction/unbond.go | 8 ++++---- 16 files changed, 60 insertions(+), 52 deletions(-) diff --git a/core/transaction/buy_coin.go b/core/transaction/buy_coin.go index 8f6a40248..b8270bb1a 100644 --- a/core/transaction/buy_coin.go +++ b/core/transaction/buy_coin.go @@ -87,7 +87,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } diff --git a/core/transaction/change_coin_owner.go b/core/transaction/change_coin_owner.go index de3eb1bfe..a2b5f2b21 100644 --- a/core/transaction/change_coin_owner.go +++ b/core/transaction/change_coin_owner.go @@ -10,6 +10,7 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" "math/big" + "strconv" ) type ChangeCoinOwnerData struct { @@ -76,9 +77,10 @@ func (data ChangeCoinOwnerData) Run(tx *Transaction, context state.Interface, re Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Gas coin reserve balance is not sufficient for transaction. Has: %s %s, required %s %s", gasCoin.Reserve().String(), types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": gasCoin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index d20338b18..f101a5a6b 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -11,6 +11,7 @@ import ( "github.com/tendermint/tendermint/libs/kv" "math/big" "regexp" + "strconv" ) const maxCoinNameBytes = 64 @@ -132,9 +133,10 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Gas coin reserve balance is not sufficient for transaction. Has: %s %s, required %s %s", coin.Reserve().String(), types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index 2f257ea45..138081c12 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -109,10 +109,10 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_reserve": gasCoin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), + "has_reserve": gasCoin.Reserve().String(), + "required_value": commissionInBaseCoin.String(), + "coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index d8faee4b7..35de93241 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -134,10 +134,10 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_reserve": gasCoin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": gasCoin.CName, + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), + "has_reserve": gasCoin.Reserve().String(), + "required_value": commissionInBaseCoin.String(), + "coin": gasCoin.CName, }), } } diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index 9c6284839..6a6c3d022 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -113,10 +113,10 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_reserve": gasCoin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), + "has_reserve": gasCoin.Reserve().String(), + "required_value": commissionInBaseCoin.String(), + "coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index 072aa9841..68f6ac0ff 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -84,10 +84,10 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_reserve": gasCoin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), + "has_reserve": gasCoin.Reserve().String(), + "required_value": commissionInBaseCoin.String(), + "coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/edit_multisig_owners.go b/core/transaction/edit_multisig_owners.go index 221954b22..829d759a5 100644 --- a/core/transaction/edit_multisig_owners.go +++ b/core/transaction/edit_multisig_owners.go @@ -141,10 +141,10 @@ func (data EditMultisigOwnersData) Run(tx *Transaction, context state.Interface, Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_reserve": gasCoin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), + "has_reserve": gasCoin.Reserve().String(), + "required_value": commissionInBaseCoin.String(), + "coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/multisend.go b/core/transaction/multisend.go index 8e7ca4fec..ef4128c87 100644 --- a/core/transaction/multisend.go +++ b/core/transaction/multisend.go @@ -12,6 +12,7 @@ import ( "github.com/tendermint/tendermint/libs/kv" "math/big" "sort" + "strconv" "strings" ) @@ -97,9 +98,10 @@ func (data MultisendData) Run(tx *Transaction, context state.Interface, rewardPo Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "has_reserve": coin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": coin.CName, + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), + "has_value": coin.Reserve().String(), + "required_value": commissionInBaseCoin.String(), + "coin": coin.CName, }), } } diff --git a/core/transaction/price_vote.go b/core/transaction/price_vote.go index ace4c4455..a1eb3c13e 100644 --- a/core/transaction/price_vote.go +++ b/core/transaction/price_vote.go @@ -57,9 +57,9 @@ func (data PriceVoteData) Run(tx *Transaction, context state.Interface, rewardPo Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "has_reserve": gasCoin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "has_reserve": gasCoin.Reserve().String(), + "required_value": commissionInBaseCoin.String(), + "coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 1d04d7cc7..9a753bf5b 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -152,7 +152,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": gasCoin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/sell_coin.go b/core/transaction/sell_coin.go index 8d08d4429..7638de78b 100644 --- a/core/transaction/sell_coin.go +++ b/core/transaction/sell_coin.go @@ -114,7 +114,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } @@ -163,10 +163,10 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) commissionInBaseCoin.String(), types.GetBaseCoin()), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has": coinFrom.Reserve().String(), - "required": commissionInBaseCoin.String(), - "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), + "has_value": coinFrom.Reserve().String(), + "required_value": commissionInBaseCoin.String(), + "coin": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } @@ -250,7 +250,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } diff --git a/core/transaction/send.go b/core/transaction/send.go index 8830f2c92..00b8c6774 100644 --- a/core/transaction/send.go +++ b/core/transaction/send.go @@ -46,9 +46,10 @@ func (data SendData) TotalSpend(tx *Transaction, context *state.CheckState) (Tot coin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has": coin.Reserve().String(), - "required": commissionInBaseCoin.String(), + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), + "has_value": coin.Reserve().String(), + "required_value": commissionInBaseCoin.String(), + "coin": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index 9f29b5c68..dcbbfa316 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -86,9 +86,10 @@ func (data SetHaltBlockData) Run(tx *Transaction, context state.Interface, rewar Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "has_reserve": gasCoin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), + "has_value": gasCoin.Reserve().String(), + "required_value": commissionInBaseCoin.String(), + "coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index e86d02a8b..1c36864ca 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -64,9 +64,9 @@ func (data SetCandidateOnData) Run(tx *Transaction, context state.Interface, rew Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "has_reserve": gasCoin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "has_value": gasCoin.Reserve().String(), + "required_value": commissionInBaseCoin.String(), + "coin": gasCoin.GetFullSymbol(), }), } } @@ -166,9 +166,9 @@ func (data SetCandidateOffData) Run(tx *Transaction, context state.Interface, re Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "has_reserve": coin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": coin.CName, + "has_value": coin.Reserve().String(), + "required_value": commissionInBaseCoin.String(), + "coin": coin.CName, }), } } diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 5e908d784..9b530959a 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -132,10 +132,10 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_reserve": gasCoin.Reserve().String(), - "commission": commissionInBaseCoin.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), + "has_value": gasCoin.Reserve().String(), + "required_value": commissionInBaseCoin.String(), + "coin": gasCoin.GetFullSymbol(), }), } } From 635cd99dccf49f3261be6e1a906794210807e88e Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 4 Sep 2020 00:32:56 +0300 Subject: [PATCH 207/426] detail error rename --- core/transaction/change_coin_owner.go | 3 +- core/transaction/create_coin.go | 36 ++++++++++++++++----- core/transaction/create_multisig.go | 4 +-- core/transaction/declare_candidacy.go | 4 +-- core/transaction/delegate.go | 5 +-- core/transaction/edit_candidate.go | 2 +- core/transaction/edit_multisig_owners.go | 2 +- core/transaction/multisend.go | 2 ++ core/transaction/price_vote.go | 4 ++- core/transaction/recreate_coin.go | 6 ++-- core/transaction/redeem_check.go | 24 +++++++------- core/transaction/sell_all_coin.go | 10 ++++-- core/transaction/set_halt_block.go | 5 ++- core/transaction/switch_candidate_status.go | 7 ++-- core/transaction/unbond.go | 2 +- 15 files changed, 77 insertions(+), 39 deletions(-) diff --git a/core/transaction/change_coin_owner.go b/core/transaction/change_coin_owner.go index a2b5f2b21..bfe0a31a7 100644 --- a/core/transaction/change_coin_owner.go +++ b/core/transaction/change_coin_owner.go @@ -95,9 +95,10 @@ func (data ChangeCoinOwnerData) Run(tx *Transaction, context state.Interface, re Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index f101a5a6b..ff8607871 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -54,31 +54,48 @@ func (data CreateCoinData) BasicCheck(tx *Transaction, context *state.CheckState if context.Coins().ExistsBySymbol(data.Symbol) { return &Response{ Code: code.CoinAlreadyExists, - Log: fmt.Sprintf("Coin already exists")} + Log: fmt.Sprintf("Coin already exists"), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinAlreadyExists)), + }), + } + } if data.ConstantReserveRatio < 10 || data.ConstantReserveRatio > 100 { return &Response{ Code: code.WrongCrr, - Log: fmt.Sprintf("Constant Reserve Ratio should be between 10 and 100")} + Log: fmt.Sprintf("Constant Reserve Ratio should be between 10 and 100"), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.WrongCrr)), + })} } if data.InitialAmount.Cmp(minCoinSupply) == -1 || data.InitialAmount.Cmp(data.MaxSupply) == 1 { return &Response{ Code: code.WrongCoinSupply, - Log: fmt.Sprintf("Coin supply should be between %s and %s", minCoinSupply.String(), data.MaxSupply.String())} + Log: fmt.Sprintf("Coin supply should be between %s and %s", minCoinSupply.String(), data.MaxSupply.String()), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.WrongCoinSupply)), + })} } if data.MaxSupply.Cmp(maxCoinSupply) == 1 { return &Response{ Code: code.WrongCoinSupply, - Log: fmt.Sprintf("Max coin supply should be less than %s", maxCoinSupply)} + Log: fmt.Sprintf("Max coin supply should be less than %s", maxCoinSupply), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.WrongCoinSupply)), + })} } if data.InitialReserve.Cmp(minCoinReserve) == -1 { return &Response{ Code: code.WrongCoinSupply, - Log: fmt.Sprintf("Coin reserve should be greater than or equal to %s", minCoinReserve.String())} + Log: fmt.Sprintf("Coin reserve should be greater than or equal to %s", minCoinReserve.String()), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.WrongCoinSupply)), + })} } return nil @@ -151,9 +168,10 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "coin": gasCoin.GetFullSymbol(), }), } } @@ -163,9 +181,10 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), data.InitialReserve.String(), types.GetBaseCoin()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_reserve": data.InitialReserve.String(), - "base_coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } @@ -182,9 +201,10 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": totalTxCost.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index 138081c12..b593bc0b5 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -110,7 +110,7 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_reserve": gasCoin.Reserve().String(), + "has_value": gasCoin.Reserve().String(), "required_value": commissionInBaseCoin.String(), "coin": gasCoin.GetFullSymbol(), }), @@ -128,7 +128,7 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index 35de93241..cdf6ad413 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -166,7 +166,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "coin": gasCoin.GetFullSymbol(), }), } } @@ -184,7 +184,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": totalTxCost.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index 6a6c3d022..36ec72d1e 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -132,7 +132,7 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "coin": gasCoin.GetFullSymbol(), }), } } @@ -160,9 +160,10 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": totalTxCost.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index 68f6ac0ff..a5da0705b 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -103,7 +103,7 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/edit_multisig_owners.go b/core/transaction/edit_multisig_owners.go index 829d759a5..7443856f5 100644 --- a/core/transaction/edit_multisig_owners.go +++ b/core/transaction/edit_multisig_owners.go @@ -160,7 +160,7 @@ func (data EditMultisigOwnersData) Run(tx *Transaction, context state.Interface, "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/multisend.go b/core/transaction/multisend.go index ef4128c87..4616f3d04 100644 --- a/core/transaction/multisend.go +++ b/core/transaction/multisend.go @@ -170,6 +170,7 @@ func checkBalances(context *state.CheckState, sender types.Address, items []Mult Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), value, coinData.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": fmt.Sprintf("%d", value), "coin": coinData.GetFullSymbol(), @@ -188,6 +189,7 @@ func checkCoins(context *state.CheckState, items []MultisendDataItem) *Response Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", item.Coin), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), "coin": fmt.Sprintf("%s", item.Coin), }), } diff --git a/core/transaction/price_vote.go b/core/transaction/price_vote.go index a1eb3c13e..abb212890 100644 --- a/core/transaction/price_vote.go +++ b/core/transaction/price_vote.go @@ -9,6 +9,7 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" "math/big" + "strconv" ) type PriceVoteData struct { @@ -72,9 +73,10 @@ func (data PriceVoteData) Run(tx *Transaction, context state.Interface, rewardPo Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 9a753bf5b..950397da6 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -170,7 +170,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "coin": gasCoin.GetFullSymbol(), }), } } @@ -183,7 +183,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_reserve": data.InitialReserve.String(), - "base_coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } @@ -203,7 +203,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": totalTxCost.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index 6ebf0c34f..9617b8f05 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -229,10 +229,10 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", decodedCheck.Coin, checkSender.String(), totalTxCost.String(), coin.GetFullSymbol()), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": checkSender.String(), - "coin": coin.GetFullSymbol(), - "total_tx_cost": totalTxCost.String(), + "code": strconv.Itoa(int(code.InsufficientFunds)), + "sender": checkSender.String(), + "coin": coin.GetFullSymbol(), + "needed_value": totalTxCost.String(), }), } } @@ -242,10 +242,10 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", checkSender.String(), decodedCheck.Coin, decodedCheck.Value.String(), coin.GetFullSymbol()), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": checkSender.String(), - "coin": coin.GetFullSymbol(), - "value": decodedCheck.Value.String(), + "code": strconv.Itoa(int(code.InsufficientFunds)), + "sender": checkSender.String(), + "coin": coin.GetFullSymbol(), + "needed_value": decodedCheck.Value.String(), }), } } @@ -255,10 +255,10 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", checkSender.String(), decodedCheck.GasCoin, commission.String(), gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "gas_coin": gasCoin.GetFullSymbol(), - "commission": commission.String(), + "code": strconv.Itoa(int(code.InsufficientFunds)), + "sender": sender.String(), + "coin": gasCoin.GetFullSymbol(), + "needed_value": commission.String(), }), } } diff --git a/core/transaction/sell_all_coin.go b/core/transaction/sell_all_coin.go index d29899543..c156970df 100644 --- a/core/transaction/sell_all_coin.go +++ b/core/transaction/sell_all_coin.go @@ -84,7 +84,10 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account"), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), + "code": strconv.Itoa(int(code.InsufficientFunds)), + "sender": sender.String(), + "coin": coin.GetFullSymbol(), + "needed_value": commissionInBaseCoin.String(), }), } } @@ -110,7 +113,10 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account"), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), + "code": strconv.Itoa(int(code.InsufficientFunds)), + "sender": sender.String(), + "coin": coinFrom.GetFullSymbol(), + "needed_value": commissionInBaseCoin.String(), }), } } diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index dcbbfa316..4d1c88319 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -29,6 +29,7 @@ func (data SetHaltBlockData) BasicCheck(tx *Transaction, context *state.CheckSta Code: code.CandidateNotFound, Log: fmt.Sprintf("Candidate with such public key not found"), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CandidateNotFound)), "pub_key": data.PubKey.String(), }), } @@ -65,6 +66,7 @@ func (data SetHaltBlockData) Run(tx *Transaction, context state.Interface, rewar Code: code.WrongHaltHeight, Log: fmt.Sprintf("Halt height should be equal or bigger than current: %d", currentBlock), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.WrongHaltHeight)), "height": strconv.FormatUint(data.Height, 10), }), } @@ -104,9 +106,10 @@ func (data SetHaltBlockData) Run(tx *Transaction, context state.Interface, rewar Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "coin": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index 1c36864ca..fa7f3880f 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -11,6 +11,7 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" "math/big" + "strconv" ) type SetCandidateOnData struct { @@ -81,9 +82,10 @@ func (data SetCandidateOnData) Run(tx *Transaction, context state.Interface, rew Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "coin": gasCoin.GetFullSymbol(), }), } } @@ -181,9 +183,10 @@ func (data SetCandidateOffData) Run(tx *Transaction, context state.Interface, re Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, tx.GasCoin), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": fmt.Sprintf("%s", tx.GasCoin), + "coin": fmt.Sprintf("%s", tx.GasCoin), }), } } diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 9b530959a..12a79087e 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -151,7 +151,7 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "gas_coin": gasCoin.GetFullSymbol(), + "coin": gasCoin.GetFullSymbol(), }), } } From 9ead5803cafe7978e20c2491315fbe7c682d68a5 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 4 Sep 2020 13:46:13 +0300 Subject: [PATCH 208/426] handle errors --- api/v2/v2.go | 28 +++++++++------------ core/transaction/buy_coin.go | 18 ++++++------- core/transaction/change_coin_owner.go | 9 ++++++- core/transaction/create_coin.go | 8 +++--- core/transaction/create_multisig.go | 4 +-- core/transaction/declare_candidacy.go | 12 ++++----- core/transaction/delegate.go | 11 ++++---- core/transaction/edit_candidate.go | 4 +-- core/transaction/edit_multisig_owners.go | 4 +-- core/transaction/executor.go | 9 ++++++- core/transaction/multisend.go | 8 +++--- core/transaction/price_vote.go | 2 +- core/transaction/recreate_coin.go | 11 ++++---- core/transaction/redeem_check.go | 18 ++++++------- core/transaction/sell_all_coin.go | 14 +++++------ core/transaction/sell_coin.go | 16 ++++++------ core/transaction/send.go | 10 ++++---- core/transaction/set_halt_block.go | 2 +- core/transaction/switch_candidate_status.go | 4 +-- core/transaction/unbond.go | 12 ++++----- go.mod | 2 +- go.sum | 4 +-- 22 files changed, 111 insertions(+), 99 deletions(-) diff --git a/api/v2/v2.go b/api/v2/v2.go index 337b4a09f..c968f508a 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -3,6 +3,7 @@ package v2 import ( "context" "encoding/json" + "fmt" "github.com/MinterTeam/minter-go-node/api/v2/service" gw "github.com/MinterTeam/node-grpc-gateway/api_pb" _ "github.com/MinterTeam/node-grpc-gateway/statik" @@ -130,31 +131,30 @@ func contextWithTimeoutInterceptor(timeout time.Duration) func(ctx context.Conte } } -func parseStatus(s *status.Status) (string, map[string]interface{}) { +func parseStatus(s *status.Status) (string, map[string]string) { codeString := strconv.Itoa(runtime.HTTPStatusFromCode(s.Code())) - var data map[string]interface{} + dataString := map[string]string{} details := s.Details() if len(details) != 0 { detail, ok := details[0].(*_struct.Struct) if !ok { - return codeString, data + return codeString, dataString } - data = detail.AsMap() - + data := detail.AsMap() + for k, v := range data { + dataString[k] = fmt.Sprintf("%s", v) + } code, ok := detail.GetFields()["code"] if ok { codeString = code.GetStringValue() } } - return codeString, data + return codeString, dataString } func httpError(ctx context.Context, mux *runtime.ServeMux, marshaler runtime.Marshaler, w http.ResponseWriter, r *http.Request, err error) { - const fallback = `{"error": "failed to marshal error message"}` - type errorHTTPResponse struct { - Error interface{} `json:"error"` - } + const fallback = `{"error": {"code": "500", "message": "failed to marshal error message"}}` contentType := marshaler.ContentType() w.Header().Set("Content-Type", contentType) @@ -168,12 +168,8 @@ func httpError(ctx context.Context, mux *runtime.ServeMux, marshaler runtime.Mar codeString, data := parseStatus(s) - jErr := json.NewEncoder(w).Encode(errorHTTPResponse{ - Error: struct { - Code string `json:"code"` - Message string `json:"message"` - Data map[string]interface{} `json:"data"` - }{ + jErr := json.NewEncoder(w).Encode(gw.ErrorBody{ + Error: &gw.ErrorBody_Error{ Code: codeString, Message: s.Message(), Data: data, diff --git a/core/transaction/buy_coin.go b/core/transaction/buy_coin.go index b8270bb1a..1c47968c9 100644 --- a/core/transaction/buy_coin.go +++ b/core/transaction/buy_coin.go @@ -161,7 +161,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coinFrom.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } @@ -187,7 +187,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coinTo.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } @@ -239,7 +239,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coinFrom.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } @@ -297,7 +297,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "gas_coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } @@ -344,8 +344,8 @@ func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.CheckState) * Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.CoinToSell), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_to_sell": fmt.Sprintf("%s", data.CoinToSell), + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": fmt.Sprintf("%s", data.CoinToSell.String()), }), } } @@ -355,8 +355,8 @@ func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.CheckState) * Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.CoinToBuy), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_to_buy": fmt.Sprintf("%s", data.CoinToBuy), + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": fmt.Sprintf("%s", data.CoinToBuy.String()), }), } } @@ -397,7 +397,7 @@ func (data BuyCoinData) Run(tx *Transaction, context state.Interface, rewardPool "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": ts.Value.String(), - "coin": coin.GetFullSymbol(), + "coin_symbol": coin.GetFullSymbol(), }), } } diff --git a/core/transaction/change_coin_owner.go b/core/transaction/change_coin_owner.go index bfe0a31a7..bc7239d28 100644 --- a/core/transaction/change_coin_owner.go +++ b/core/transaction/change_coin_owner.go @@ -26,6 +26,10 @@ func (data ChangeCoinOwnerData) BasicCheck(tx *Transaction, context *state.Check return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Symbol), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_symbol": data.Symbol.String(), + }), } } @@ -33,6 +37,9 @@ func (data ChangeCoinOwnerData) BasicCheck(tx *Transaction, context *state.Check return &Response{ Code: code.IsNotOwnerOfCoin, Log: "Sender is not owner of coin", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.IsNotOwnerOfCoin)), + }), } } @@ -98,7 +105,7 @@ func (data ChangeCoinOwnerData) Run(tx *Transaction, context state.Interface, re "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index ff8607871..c208b3b36 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -153,7 +153,7 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin_symbol": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } @@ -171,7 +171,7 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } @@ -184,7 +184,7 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_reserve": data.InitialReserve.String(), - "coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin_symbol": fmt.Sprintf("%s", types.GetBaseCoin().String()), }), } } @@ -204,7 +204,7 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": totalTxCost.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index b593bc0b5..6d61bdbab 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -112,7 +112,7 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": gasCoin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } @@ -128,7 +128,7 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index cdf6ad413..4891b8b1e 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -40,8 +40,8 @@ func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.Chec Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Coin), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin": fmt.Sprintf("%s", data.Coin), + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": fmt.Sprintf("%s", data.Coin.String()), }), } } @@ -137,7 +137,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_reserve": gasCoin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "coin": gasCoin.CName, + "coin_symbol": gasCoin.GetFullSymbol(), }), } } @@ -153,7 +153,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": data.Stake.String(), - "coin": coin.GetFullSymbol(), + "coin_symbol": coin.GetFullSymbol(), }), } } @@ -166,7 +166,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } @@ -184,7 +184,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": totalTxCost.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index 36ec72d1e..9b0e05712 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -35,7 +35,8 @@ func (data DelegateData) BasicCheck(tx *Transaction, context *state.CheckState) Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", tx.GasCoin), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": fmt.Sprintf("%s", tx.GasCoin.String()), })} } @@ -116,7 +117,7 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_reserve": gasCoin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } @@ -132,7 +133,7 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } @@ -145,7 +146,7 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": data.Value.String(), - "coin": coin.GetFullSymbol(), + "coin_symbol": coin.GetFullSymbol(), }), } } @@ -163,7 +164,7 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": totalTxCost.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index a5da0705b..8d66d77e6 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -87,7 +87,7 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_reserve": gasCoin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } @@ -103,7 +103,7 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/edit_multisig_owners.go b/core/transaction/edit_multisig_owners.go index 7443856f5..269b13323 100644 --- a/core/transaction/edit_multisig_owners.go +++ b/core/transaction/edit_multisig_owners.go @@ -144,7 +144,7 @@ func (data EditMultisigOwnersData) Run(tx *Transaction, context state.Interface, "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_reserve": gasCoin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } @@ -160,7 +160,7 @@ func (data EditMultisigOwnersData) Run(tx *Transaction, context state.Interface, "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/executor.go b/core/transaction/executor.go index e99444b36..4e13fcba0 100644 --- a/core/transaction/executor.go +++ b/core/transaction/executor.go @@ -8,6 +8,7 @@ import ( "github.com/MinterTeam/minter-go-node/core/types" "github.com/tendermint/tendermint/libs/kv" "math/big" + "strconv" "sync" ) @@ -46,6 +47,7 @@ func RunTx(context state.Interface, Code: code.TxTooLarge, Log: fmt.Sprintf("TX length is over %d bytes", maxTxLength), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.TxTooLarge)), "max_tx_length": fmt.Sprintf("%d", maxTxLength), "got_tx_length": fmt.Sprintf("%d", lenRawTx), }), @@ -57,6 +59,9 @@ func RunTx(context state.Interface, return Response{ Code: code.DecodeError, Log: err.Error(), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.DecodeError)), + }), } } @@ -65,6 +70,7 @@ func RunTx(context state.Interface, Code: code.WrongChainID, Log: "Wrong chain id", Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.WrongChainID)), "current_chain_id": fmt.Sprintf("%d", types.CurrentChainID), "got_chain_id": fmt.Sprintf("%d", tx.ChainID), }), @@ -82,7 +88,8 @@ func RunTx(context state.Interface, Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", tx.GasCoin), Info: EncodeError(map[string]string{ - "gas_coin": fmt.Sprintf("%d", tx.GasCoin), + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": tx.GasCoin.String(), }), } } diff --git a/core/transaction/multisend.go b/core/transaction/multisend.go index 4616f3d04..2549c1709 100644 --- a/core/transaction/multisend.go +++ b/core/transaction/multisend.go @@ -101,7 +101,7 @@ func (data MultisendData) Run(tx *Transaction, context state.Interface, rewardPo "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "coin": coin.CName, + "coin_symbol": coin.CName, }), } } @@ -173,7 +173,7 @@ func checkBalances(context *state.CheckState, sender types.Address, items []Mult "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": fmt.Sprintf("%d", value), - "coin": coinData.GetFullSymbol(), + "coin_symbol": coinData.GetFullSymbol(), }), } } @@ -189,8 +189,8 @@ func checkCoins(context *state.CheckState, items []MultisendDataItem) *Response Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", item.Coin), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin": fmt.Sprintf("%s", item.Coin), + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": fmt.Sprintf("%s", item.Coin.String()), }), } } diff --git a/core/transaction/price_vote.go b/core/transaction/price_vote.go index abb212890..f8bcd079f 100644 --- a/core/transaction/price_vote.go +++ b/core/transaction/price_vote.go @@ -76,7 +76,7 @@ func (data PriceVoteData) Run(tx *Transaction, context state.Interface, rewardPo "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 950397da6..90f3408ff 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -91,7 +91,8 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Symbol), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_symbol": fmt.Sprintf("%s", data.Symbol.String()), }), } } @@ -152,7 +153,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": gasCoin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } @@ -170,7 +171,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } @@ -183,7 +184,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_reserve": data.InitialReserve.String(), - "coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin_symbol": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } @@ -203,7 +204,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": totalTxCost.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index 9617b8f05..fe6fae669 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -117,8 +117,8 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward Code: code.CoinNotExists, Log: fmt.Sprintf("Coin not exists"), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin": fmt.Sprintf("%s", decodedCheck.Coin), + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": fmt.Sprintf("%s", decodedCheck.Coin.String()), }), } } @@ -128,8 +128,8 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward Code: code.CoinNotExists, Log: fmt.Sprintf("Gas coin not exists"), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "gas_coin": fmt.Sprintf("%s", decodedCheck.GasCoin), + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": fmt.Sprintf("%s", decodedCheck.GasCoin.String()), }), } } @@ -139,8 +139,8 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward Code: code.WrongGasCoin, Log: fmt.Sprintf("Gas coin for redeem check transaction can only be %s", decodedCheck.GasCoin), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongGasCoin)), - "gas_coin": fmt.Sprintf("%s", decodedCheck.GasCoin), + "code": strconv.Itoa(int(code.WrongGasCoin)), + "coin": fmt.Sprintf("%s", decodedCheck.GasCoin), }), } } @@ -231,7 +231,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward Info: EncodeError(map[string]string{ "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": checkSender.String(), - "coin": coin.GetFullSymbol(), + "coin_symbol": coin.GetFullSymbol(), "needed_value": totalTxCost.String(), }), } @@ -244,7 +244,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward Info: EncodeError(map[string]string{ "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": checkSender.String(), - "coin": coin.GetFullSymbol(), + "coin_symbol": coin.GetFullSymbol(), "needed_value": decodedCheck.Value.String(), }), } @@ -257,7 +257,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward Info: EncodeError(map[string]string{ "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), "needed_value": commission.String(), }), } diff --git a/core/transaction/sell_all_coin.go b/core/transaction/sell_all_coin.go index c156970df..e147eb016 100644 --- a/core/transaction/sell_all_coin.go +++ b/core/transaction/sell_all_coin.go @@ -86,7 +86,7 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat Info: EncodeError(map[string]string{ "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), - "coin": coin.GetFullSymbol(), + "coin_symbol": coin.GetFullSymbol(), "needed_value": commissionInBaseCoin.String(), }), } @@ -115,7 +115,7 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat Info: EncodeError(map[string]string{ "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), - "coin": coinFrom.GetFullSymbol(), + "coin_symbol": coinFrom.GetFullSymbol(), "needed_value": commissionInBaseCoin.String(), }), } @@ -171,8 +171,8 @@ func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.CheckStat Code: code.CoinNotExists, Log: fmt.Sprintf("Coin to sell not exists"), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_to_sell": fmt.Sprintf("%s", data.CoinToSell), + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": fmt.Sprintf("%s", data.CoinToSell.String()), }), } } @@ -182,8 +182,8 @@ func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.CheckStat Code: code.CoinNotExists, Log: fmt.Sprintf("Coin to buy not exists"), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_to_buy": fmt.Sprintf("%s", data.CoinToBuy), + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": fmt.Sprintf("%s", data.CoinToBuy.String()), }), } } @@ -233,7 +233,7 @@ func (data SellAllCoinData) Run(tx *Transaction, context state.Interface, reward "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": ts.Value.String(), - "coin": coin.GetFullSymbol(), + "coin_symbol": coin.GetFullSymbol(), }), } } diff --git a/core/transaction/sell_coin.go b/core/transaction/sell_coin.go index 7638de78b..00f6dab1c 100644 --- a/core/transaction/sell_coin.go +++ b/core/transaction/sell_coin.go @@ -114,7 +114,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin_symbol": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } @@ -166,7 +166,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coinFrom.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin_symbol": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } @@ -250,7 +250,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin_symbol": fmt.Sprintf("%s", types.GetBaseCoin()), }), } } @@ -298,8 +298,8 @@ func (data SellCoinData) BasicCheck(tx *Transaction, context *state.CheckState) Code: code.CoinNotExists, Log: fmt.Sprintf("Coin not exists"), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_to_sell": fmt.Sprintf("%s", data.CoinToSell), + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": fmt.Sprintf("%s", data.CoinToSell.String()), }), } } @@ -309,8 +309,8 @@ func (data SellCoinData) BasicCheck(tx *Transaction, context *state.CheckState) Code: code.CoinNotExists, Log: fmt.Sprintf("Coin not exists"), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_to_buy": fmt.Sprintf("%s", data.CoinToBuy), + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": fmt.Sprintf("%s", data.CoinToBuy.String()), }), } } @@ -360,7 +360,7 @@ func (data SellCoinData) Run(tx *Transaction, context state.Interface, rewardPoo "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": ts.Value.String(), - "coin": coin.GetFullSymbol(), + "coin_symbol": coin.GetFullSymbol(), }), } } diff --git a/core/transaction/send.go b/core/transaction/send.go index 00b8c6774..4a4d7d39a 100644 --- a/core/transaction/send.go +++ b/core/transaction/send.go @@ -49,7 +49,7 @@ func (data SendData) TotalSpend(tx *Transaction, context *state.CheckState) (Tot "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "coin": fmt.Sprintf("%s", types.GetBaseCoin()), + "coin_symbol": fmt.Sprintf("%s", types.GetBaseCoin().String()), }), } } @@ -75,7 +75,7 @@ func (data SendData) BasicCheck(tx *Transaction, context *state.CheckState) *Res Code: code.DecodeError, Log: "Incorrect tx data", Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), + "code": strconv.Itoa(int(code.DecodeError)), }), } } @@ -85,8 +85,8 @@ func (data SendData) BasicCheck(tx *Transaction, context *state.CheckState) *Res Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Coin), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin": fmt.Sprintf("%s", data.Coin), + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": fmt.Sprintf("%s", data.Coin.String()), }), } } @@ -136,7 +136,7 @@ func (data SendData) Run(tx *Transaction, context state.Interface, rewardPool *b "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": ts.Value.String(), - "coin": coin.GetFullSymbol(), + "coin_symbol": coin.GetFullSymbol(), }), } } diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index 4d1c88319..050a027ca 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -109,7 +109,7 @@ func (data SetHaltBlockData) Run(tx *Transaction, context state.Interface, rewar "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index fa7f3880f..429c800b3 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -85,7 +85,7 @@ func (data SetCandidateOnData) Run(tx *Transaction, context state.Interface, rew "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } @@ -186,7 +186,7 @@ func (data SetCandidateOffData) Run(tx *Transaction, context state.Interface, re "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "coin": fmt.Sprintf("%s", tx.GasCoin), + "coin_symbol": fmt.Sprintf("%s", tx.GasCoin), }), } } diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 12a79087e..049ac3a66 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -34,15 +34,14 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Coin), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin": fmt.Sprintf("%s", data.Coin), + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": fmt.Sprintf("%s", data.Coin.String()), }), } } errorInfo := map[string]string{ - "pub_key": data.PubKey.String(), - "unbound_value": data.Value.String(), + "pub_key": data.PubKey.String(), } if !context.Candidates().Exists(data.PubKey) { errorInfo["code"] = strconv.Itoa(int(code.CandidateNotFound)) @@ -53,6 +52,7 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R } } + errorInfo["unbound_value"] = data.Value.String() sender, _ := tx.Sender() if waitlist := context.Watchlist().Get(sender, data.PubKey, data.Coin); waitlist != nil { @@ -135,7 +135,7 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": gasCoin.Reserve().String(), "required_value": commissionInBaseCoin.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } @@ -151,7 +151,7 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool "code": strconv.Itoa(int(code.InsufficientFunds)), "sender": sender.String(), "needed_value": commission.String(), - "coin": gasCoin.GetFullSymbol(), + "coin_symbol": gasCoin.GetFullSymbol(), }), } } diff --git a/go.mod b/go.mod index ff521e509..1376a6dfd 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200827131141-8b2620700577 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200904103900-937c375d23da github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 2564a8bf2..98b4fa8ee 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200827131141-8b2620700577 h1:QFPT9LYNLLub4i3VdP7ipeoRMEELpfWSWoX7wbd+3GM= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200827131141-8b2620700577/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200904103900-937c375d23da h1:sefY3XEsIS0WEJ1xbg767JOllabybtVm4G8pwJ0aRGQ= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200904103900-937c375d23da/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 173ead448c733a1b681a0792ec5e1ea9455a1868 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 4 Sep 2020 13:48:32 +0300 Subject: [PATCH 209/426] api --- api/v2/service/estimate_tx_commission.go | 74 ------------------------ 1 file changed, 74 deletions(-) diff --git a/api/v2/service/estimate_tx_commission.go b/api/v2/service/estimate_tx_commission.go index 020f28aed..8c9dc9e3c 100644 --- a/api/v2/service/estimate_tx_commission.go +++ b/api/v2/service/estimate_tx_commission.go @@ -4,10 +4,7 @@ import ( "context" "encoding/hex" "fmt" - "github.com/MinterTeam/minter-go-node/core/commissions" - "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/transaction" - "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" @@ -25,15 +22,6 @@ func (s *Service) EstimateTxCommission(ctx context.Context, req *pb.EstimateTxCo cState.RLock() defer cState.RUnlock() - if req.GetTx() == "" { - data := req.GetData() - if data == nil { - return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "invalid tx and data") - } - - return commissionCoinForData(data, cState) - } - if !strings.HasPrefix(strings.Title(req.GetTx()), "0x") { return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "invalid transaction") } @@ -70,65 +58,3 @@ func (s *Service) EstimateTxCommission(ctx context.Context, req *pb.EstimateTxCo Commission: commission.String(), }, nil } - -func commissionCoinForData(data *pb.EstimateTxCommissionRequest_TransactionData, cState *state.CheckState) (*pb.EstimateTxCommissionResponse, error) { - var commissionInBaseCoin *big.Int - switch data.Type { - case pb.EstimateTxCommissionRequest_TransactionData_Send: - commissionInBaseCoin = big.NewInt(commissions.SendTx) - case pb.EstimateTxCommissionRequest_TransactionData_SellAllCoin, - pb.EstimateTxCommissionRequest_TransactionData_SellCoin, - pb.EstimateTxCommissionRequest_TransactionData_BuyCoin: - commissionInBaseCoin = big.NewInt(commissions.ConvertTx) - case pb.EstimateTxCommissionRequest_TransactionData_DeclareCandidacy: - commissionInBaseCoin = big.NewInt(commissions.DeclareCandidacyTx) - case pb.EstimateTxCommissionRequest_TransactionData_Delegate: - commissionInBaseCoin = big.NewInt(commissions.DelegateTx) - case pb.EstimateTxCommissionRequest_TransactionData_Unbond: - commissionInBaseCoin = big.NewInt(commissions.UnbondTx) - case pb.EstimateTxCommissionRequest_TransactionData_SetCandidateOffline, - pb.EstimateTxCommissionRequest_TransactionData_SetCandidateOnline: - commissionInBaseCoin = big.NewInt(commissions.ToggleCandidateStatus) - case pb.EstimateTxCommissionRequest_TransactionData_EditCandidate: - commissionInBaseCoin = big.NewInt(commissions.EditCandidate) - case pb.EstimateTxCommissionRequest_TransactionData_RedeemCheck: - commissionInBaseCoin = big.NewInt(commissions.RedeemCheckTx) - case pb.EstimateTxCommissionRequest_TransactionData_CreateMultisig: - commissionInBaseCoin = big.NewInt(commissions.CreateMultisig) - case pb.EstimateTxCommissionRequest_TransactionData_Multisend: - if data.Mtxs <= 0 { - return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "Set number of transactions for multisend (mtxs)") - } - commissionInBaseCoin = big.NewInt(commissions.MultisendDelta*(data.Mtxs-1) + 10) - default: - return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "Set correct transaction type for tx") - } - - lenPayload := len(data.Payload) - if lenPayload > 1024 { - return new(pb.EstimateTxCommissionResponse), status.Errorf(codes.InvalidArgument, "Transaction payload length is over %d bytes", 1024) - } - - totalCommissionInBaseCoin := new(big.Int).Mul(big.NewInt(0).Add(commissionInBaseCoin, big.NewInt(int64(lenPayload))), transaction.CommissionMultiplier) - - if types.CoinID(data.GasCoinId).IsBaseCoin() { - return &pb.EstimateTxCommissionResponse{ - Commission: totalCommissionInBaseCoin.String(), - }, nil - } - - coin := cState.Coins().GetCoin(types.CoinID(data.GasCoinId)) - - if coin == nil { - return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "Gas Coin not found") - } - - if totalCommissionInBaseCoin.Cmp(coin.Reserve()) == 1 { - return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "Not enough coin reserve for pay comission") - } - - return &pb.EstimateTxCommissionResponse{ - Commission: formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), totalCommissionInBaseCoin).String(), - }, nil - -} From 07e135bf14b9a9506ca6f3bf5ffad5883f1abea4 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 4 Sep 2020 13:54:41 +0300 Subject: [PATCH 210/426] api --- api/v2/service/estimate_tx_commission.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/api/v2/service/estimate_tx_commission.go b/api/v2/service/estimate_tx_commission.go index 8c9dc9e3c..e920e11d5 100644 --- a/api/v2/service/estimate_tx_commission.go +++ b/api/v2/service/estimate_tx_commission.go @@ -4,12 +4,14 @@ import ( "context" "encoding/hex" "fmt" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/formula" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "math/big" + "strconv" "strings" ) @@ -45,9 +47,10 @@ func (s *Service) EstimateTxCommission(ctx context.Context, req *pb.EstimateTxCo if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { return new(pb.EstimateTxCommissionResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String())), transaction.EncodeError(map[string]string{ - "commission_in_base_coin": commissionInBaseCoin.String(), - "value_has": coin.Reserve().String(), - "value_required": commissionInBaseCoin.String(), + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), + "coin": coin.GetFullSymbol(), + "value_has": coin.Reserve().String(), + "value_required": commissionInBaseCoin.String(), })) } From d5f17782dd8ff07dfc1584300d48f9bbc39b5c55 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 4 Sep 2020 14:06:08 +0300 Subject: [PATCH 211/426] fix status code 400 -> 404 --- api/v2/service/estimate_coin_buy.go | 4 ++-- api/v2/service/estimate_coin_sell.go | 4 ++-- api/v2/service/estimate_coin_sell_all.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index 4cf19e8c5..c8c993bf9 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -26,14 +26,14 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe coinToBuy := types.CoinID(req.CoinIdToBuy) if !cState.Coins().Exists(coinToSell) { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.InvalidArgument, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ + return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ "code": "404", "coin_id_to_sell": coinToSell.String(), })) } if !cState.Coins().Exists(coinToBuy) { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.InvalidArgument, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ + return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ "code": "404", "coin_id_to_buy": coinToBuy.String(), })) diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index 070750e9a..0705bcfb2 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -26,14 +26,14 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell coinToBuy := types.CoinID(req.CoinIdToBuy) if !cState.Coins().Exists(coinToSell) { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ + return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ "code": "404", "coin_id_to_sell": coinToSell.String(), })) } if !cState.Coins().Exists(coinToBuy) { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ + return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ "code": "404", "coin_id_to_buy": coinToBuy.String(), })) diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index 1304fd22f..a20816643 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -34,14 +34,14 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS } if !cState.Coins().Exists(coinToSell) { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.InvalidArgument, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ + return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ "code": "404", "coin_id_to_sell": coinToSell.String(), })) } if !cState.Coins().Exists(coinToBuy) { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.InvalidArgument, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ + return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ "code": "404", "coin_id_to_buy": coinToBuy.String(), })) From 7e092e87a96942a4ce5acbe11ce54c22065dae45 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 4 Sep 2020 14:24:00 +0300 Subject: [PATCH 212/426] delete code from data error --- api/v2/v2.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api/v2/v2.go b/api/v2/v2.go index c968f508a..f18fc3395 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -167,6 +167,9 @@ func httpError(ctx context.Context, mux *runtime.ServeMux, marshaler runtime.Mar w.WriteHeader(st) codeString, data := parseStatus(s) + if _, ok := data["code"]; ok { + delete(data, "code") + } jErr := json.NewEncoder(w).Encode(gw.ErrorBody{ Error: &gw.ErrorBody_Error{ From ec0ed93d4140627ec38c1272ba33541d640444db Mon Sep 17 00:00:00 2001 From: klim0v Date: Sat, 5 Sep 2020 00:49:48 +0300 Subject: [PATCH 213/426] delete code from data error --- api/v2/v2.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/api/v2/v2.go b/api/v2/v2.go index f18fc3395..0d9c6faf5 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -167,9 +167,7 @@ func httpError(ctx context.Context, mux *runtime.ServeMux, marshaler runtime.Mar w.WriteHeader(st) codeString, data := parseStatus(s) - if _, ok := data["code"]; ok { - delete(data, "code") - } + delete(data, "code") jErr := json.NewEncoder(w).Encode(gw.ErrorBody{ Error: &gw.ErrorBody_Error{ From 120bf7de107f180cf60f1665aabb1ae5f762ed7e Mon Sep 17 00:00:00 2001 From: klim0v Date: Sat, 5 Sep 2020 01:17:02 +0300 Subject: [PATCH 214/426] add code in error --- api/v2/service/coin_info.go | 4 +-- core/transaction/create_coin.go | 18 ++++++++++--- core/transaction/executor.go | 28 ++++++++++++++++++--- core/transaction/switch_candidate_status.go | 9 ++++++- core/transaction/unbond.go | 6 ++++- 5 files changed, 55 insertions(+), 10 deletions(-) diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index 012618399..089e918e8 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -21,7 +21,7 @@ func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.Co coin := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.Symbol), 0) if coin == nil { - return new(pb.CoinInfoResponse), status.Error(codes.FailedPrecondition, "Coin not found") + return new(pb.CoinInfoResponse), status.Error(codes.NotFound, "Coin not found") } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { @@ -59,7 +59,7 @@ func (s *Service) CoinInfoById(ctx context.Context, req *pb.CoinIdRequest) (*pb. coin := cState.Coins().GetCoin(types.CoinID(req.Id)) if coin == nil { - return new(pb.CoinInfoResponse), status.Error(codes.FailedPrecondition, "Coin not found") + return new(pb.CoinInfoResponse), status.Error(codes.NotFound, "Coin not found") } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index c208b3b36..0568e9c42 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -36,19 +36,31 @@ func (data CreateCoinData) BasicCheck(tx *Transaction, context *state.CheckState if data.InitialReserve == nil || data.InitialAmount == nil || data.MaxSupply == nil { return &Response{ Code: code.DecodeError, - Log: "Incorrect tx data"} + Log: "Incorrect tx data", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.DecodeError)), + }), + } } if len(data.Name) > maxCoinNameBytes { return &Response{ Code: code.InvalidCoinName, - Log: fmt.Sprintf("Coin name is invalid. Allowed up to %d bytes.", maxCoinNameBytes)} + Log: fmt.Sprintf("Coin name is invalid. Allowed up to %d bytes.", maxCoinNameBytes), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InvalidCoinName)), + }), + } } if match, _ := regexp.MatchString(allowedCoinSymbols, data.Symbol.String()); !match { return &Response{ Code: code.InvalidCoinSymbol, - Log: fmt.Sprintf("Invalid coin symbol. Should be %s", allowedCoinSymbols)} + Log: fmt.Sprintf("Invalid coin symbol. Should be %s", allowedCoinSymbols), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InvalidCoinSymbol)), + }), + } } if context.Coins().ExistsBySymbol(data.Symbol) { diff --git a/core/transaction/executor.go b/core/transaction/executor.go index 4e13fcba0..13c245278 100644 --- a/core/transaction/executor.go +++ b/core/transaction/executor.go @@ -99,6 +99,7 @@ func RunTx(context state.Interface, Code: code.TooLowGasPrice, Log: fmt.Sprintf("Gas price of tx is too low to be included in mempool. Expected %d", minGasPrice), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.TooLowGasPrice)), "min_gas_price": fmt.Sprintf("%d", minGasPrice), "got_gas_price": fmt.Sprintf("%d", tx.GasPrice), }), @@ -111,6 +112,7 @@ func RunTx(context state.Interface, Code: code.TxPayloadTooLarge, Log: fmt.Sprintf("TX payload length is over %d bytes", maxPayloadLength), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.TxPayloadTooLarge)), "max_payload_length": fmt.Sprintf("%d", maxPayloadLength), "got_payload_length": fmt.Sprintf("%d", lenPayload), }), @@ -123,6 +125,7 @@ func RunTx(context state.Interface, Code: code.TxServiceDataTooLarge, Log: fmt.Sprintf("TX service data length is over %d bytes", maxServiceDataLength), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.TxServiceDataTooLarge)), "max_service_data_length": fmt.Sprintf("%d", maxServiceDataLength), "got_service_data_length": fmt.Sprintf("%d", lenServiceData), }), @@ -134,6 +137,9 @@ func RunTx(context state.Interface, return Response{ Code: code.DecodeError, Log: err.Error(), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.DecodeError)), + }), } } @@ -143,6 +149,7 @@ func RunTx(context state.Interface, Code: code.TxFromSenderAlreadyInMempool, Log: fmt.Sprintf("Tx from %s already exists in mempool", sender.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.TxFromSenderAlreadyInMempool)), "sender": sender.String(), }), } @@ -161,6 +168,7 @@ func RunTx(context state.Interface, Code: code.MultisigNotExists, Log: "Multisig does not exists", Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.MultisigNotExists)), "multisig_address": tx.multisig.Multisig.String(), }), } @@ -171,7 +179,11 @@ func RunTx(context state.Interface, if len(tx.multisig.Signatures) > 32 || len(multisigData.Weights) < len(tx.multisig.Signatures) { return Response{ Code: code.IncorrectMultiSignature, - Log: "Incorrect multi-signature"} + Log: "Incorrect multi-signature", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.IncorrectMultiSignature)), + }), + } } txHash := tx.Hash() @@ -184,13 +196,21 @@ func RunTx(context state.Interface, if err != nil { return Response{ Code: code.IncorrectMultiSignature, - Log: "Incorrect multi-signature"} + Log: "Incorrect multi-signature", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.IncorrectMultiSignature)), + }), + } } if usedAccounts[signer] { return Response{ Code: code.IncorrectMultiSignature, - Log: "Incorrect multi-signature"} + Log: "Incorrect multi-signature", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.IncorrectMultiSignature)), + }), + } } usedAccounts[signer] = true @@ -202,6 +222,7 @@ func RunTx(context state.Interface, Code: code.IncorrectMultiSignature, Log: fmt.Sprintf("Not enough multisig votes. Needed %d, has %d", multisigData.Threshold, totalWeight), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.IncorrectMultiSignature)), "needed_votes": fmt.Sprintf("%d", multisigData.Threshold), "got_votes": fmt.Sprintf("%d", totalWeight), }), @@ -215,6 +236,7 @@ func RunTx(context state.Interface, Code: code.WrongNonce, Log: fmt.Sprintf("Unexpected nonce. Expected: %d, got %d.", expectedNonce, tx.Nonce), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.WrongNonce)), "expected_nonce": fmt.Sprintf("%d", expectedNonce), "got_nonce": fmt.Sprintf("%d", tx.Nonce), }), diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index 429c800b3..e13491141 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -65,6 +65,7 @@ func (data SetCandidateOnData) Run(tx *Transaction, context state.Interface, rew Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": gasCoin.Reserve().String(), "required_value": commissionInBaseCoin.String(), "coin": gasCoin.GetFullSymbol(), @@ -168,6 +169,7 @@ func (data SetCandidateOffData) Run(tx *Transaction, context state.Interface, re Code: code.CoinReserveNotSufficient, Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), "has_value": coin.Reserve().String(), "required_value": commissionInBaseCoin.String(), "coin": coin.CName, @@ -222,6 +224,7 @@ func checkCandidateControl(data CandidateTx, tx *Transaction, context *state.Che Code: code.CandidateNotFound, Log: fmt.Sprintf("Candidate with such public key (%s) not found", data.GetPubKey().String()), Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CandidateNotFound)), "public_key": data.GetPubKey().String(), }), } @@ -235,7 +238,11 @@ func checkCandidateControl(data CandidateTx, tx *Transaction, context *state.Che default: return &Response{ Code: code.IsNotOwnerOfCandidate, - Log: fmt.Sprintf("Sender is not an owner of a candidate")} + Log: fmt.Sprintf("Sender is not an owner of a candidate"), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.IsNotOwnerOfCandidate)), + }), + } } return nil diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 049ac3a66..5136fd1e3 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -26,7 +26,11 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R if data.Value == nil { return &Response{ Code: code.DecodeError, - Log: "Incorrect tx data"} + Log: "Incorrect tx data", + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.DecodeError)), + }), + } } if !context.Coins().Exists(data.Coin) { From 3b5af2760b077ce676628b253f20f10915d462df Mon Sep 17 00:00:00 2001 From: klim0v Date: Sat, 5 Sep 2020 01:39:41 +0300 Subject: [PATCH 215/426] update estimate_coins --- api/v2/service/estimate_coin_buy.go | 51 ++++++++++++++++++------ api/v2/service/estimate_coin_sell.go | 51 ++++++++++++++++++------ api/v2/service/estimate_coin_sell_all.go | 50 +++++++++++++++++------ go.mod | 2 +- go.sum | 4 +- 5 files changed, 117 insertions(+), 41 deletions(-) diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index c8c993bf9..03a569b9c 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -3,6 +3,7 @@ package service import ( "context" "fmt" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/core/types" @@ -11,6 +12,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "math/big" + "strconv" ) func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRequest) (*pb.EstimateCoinBuyResponse, error) { @@ -22,21 +24,44 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe cState.RLock() defer cState.RUnlock() - coinToSell := types.CoinID(req.CoinIdToSell) - coinToBuy := types.CoinID(req.CoinIdToBuy) - - if !cState.Coins().Exists(coinToSell) { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ - "code": "404", - "coin_id_to_sell": coinToSell.String(), - })) + var coinToBuy types.CoinID + if req.GetCoinToBuy() != "" { + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), 0) + if symbol == nil { + return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_symbol": req.GetCoinToBuy(), + })) + } + coinToBuy = symbol.ID() + } else { + coinToBuy = types.CoinID(req.GetCoinIdToBuy()) + if !cState.Coins().Exists(coinToBuy) { + return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": coinToBuy.String(), + })) + } } - if !cState.Coins().Exists(coinToBuy) { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ - "code": "404", - "coin_id_to_buy": coinToBuy.String(), - })) + var coinToSell types.CoinID + if req.GetCoinToSell() != "" { + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), 0) + if symbol == nil { + return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_symbol": req.GetCoinToSell(), + })) + } + coinToSell = symbol.ID() + } else { + coinToSell = types.CoinID(req.GetCoinIdToSell()) + if !cState.Coins().Exists(coinToSell) { + return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": coinToSell.String(), + })) + } } if coinToSell == coinToBuy { diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index 0705bcfb2..ba071665e 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -3,6 +3,7 @@ package service import ( "context" "fmt" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/core/types" @@ -11,6 +12,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "math/big" + "strconv" ) func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSellRequest) (*pb.EstimateCoinSellResponse, error) { @@ -22,21 +24,44 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell cState.RLock() defer cState.RUnlock() - coinToSell := types.CoinID(req.CoinIdToSell) - coinToBuy := types.CoinID(req.CoinIdToBuy) - - if !cState.Coins().Exists(coinToSell) { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ - "code": "404", - "coin_id_to_sell": coinToSell.String(), - })) + var coinToBuy types.CoinID + if req.GetCoinToBuy() != "" { + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), 0) + if symbol == nil { + return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_symbol": req.GetCoinToBuy(), + })) + } + coinToBuy = symbol.ID() + } else { + coinToBuy = types.CoinID(req.GetCoinIdToBuy()) + if !cState.Coins().Exists(coinToBuy) { + return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ + "code": "404", + "coin_id": coinToBuy.String(), + })) + } } - if !cState.Coins().Exists(coinToBuy) { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ - "code": "404", - "coin_id_to_buy": coinToBuy.String(), - })) + var coinToSell types.CoinID + if req.GetCoinToSell() != "" { + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), 0) + if symbol == nil { + return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_symbol": req.GetCoinToSell(), + })) + } + coinToSell = symbol.ID() + } else { + coinToSell = types.CoinID(req.GetCoinIdToSell()) + if !cState.Coins().Exists(coinToSell) { + return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ + "code": "404", + "coin_id": coinToSell.String(), + })) + } } if coinToSell == coinToBuy { diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index a20816643..eb19b1de0 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -2,6 +2,7 @@ package service import ( "context" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/core/types" @@ -10,6 +11,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "math/big" + "strconv" ) func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinSellAllRequest) (*pb.EstimateCoinSellAllResponse, error) { @@ -26,25 +28,49 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS gasPrice = 1 } - coinToSell := types.CoinID(req.CoinIdToSell) - coinToBuy := types.CoinID(req.CoinIdToBuy) valueToSell, ok := big.NewInt(0).SetString(req.ValueToSell, 10) if !ok { return new(pb.EstimateCoinSellAllResponse), status.Error(codes.InvalidArgument, "Value to sell not specified") } - if !cState.Coins().Exists(coinToSell) { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ - "code": "404", - "coin_id_to_sell": coinToSell.String(), - })) + var coinToBuy types.CoinID + if req.GetCoinToBuy() != "" { + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), 0) + if symbol == nil { + return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_symbol": req.GetCoinToBuy(), + })) + } + coinToBuy = symbol.ID() + } else { + coinToBuy = types.CoinID(req.GetCoinIdToBuy()) + if !cState.Coins().Exists(coinToBuy) { + return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": coinToBuy.String(), + })) + } } - if !cState.Coins().Exists(coinToBuy) { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ - "code": "404", - "coin_id_to_buy": coinToBuy.String(), - })) + var coinToSell types.CoinID + if req.GetCoinToSell() != "" { + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), 0) + if symbol == nil { + return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_symbol": req.GetCoinToSell(), + })) + } + coinToSell = symbol.ID() + } else { + coinToSell = types.CoinID(req.GetCoinIdToSell()) + if !cState.Coins().Exists(coinToSell) { + return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": coinToSell.String(), + })) + } } if coinToSell == coinToBuy { diff --git a/go.mod b/go.mod index 1376a6dfd..ce6f08e0d 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200904103900-937c375d23da + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200904221942-ac3acb43c093 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 98b4fa8ee..dbcb71243 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200904103900-937c375d23da h1:sefY3XEsIS0WEJ1xbg767JOllabybtVm4G8pwJ0aRGQ= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200904103900-937c375d23da/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200904221942-ac3acb43c093 h1:cWbZIOVb2/Z4MbQN8V46ilAupkpH2G5WOdPFI2TR8q0= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200904221942-ac3acb43c093/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 2deb539ea668a16a5eee9b2f6aae1d7d244a7752 Mon Sep 17 00:00:00 2001 From: klim0v Date: Sat, 5 Sep 2020 01:58:35 +0300 Subject: [PATCH 216/426] update coin_info errors --- api/v2/service/coin_info.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index 089e918e8..f5f54d166 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -3,11 +3,14 @@ package service import ( "context" "fmt" + "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/core/types" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "github.com/golang/protobuf/ptypes/wrappers" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "strconv" ) func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.CoinInfoResponse, error) { @@ -21,7 +24,10 @@ func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.Co coin := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.Symbol), 0) if coin == nil { - return new(pb.CoinInfoResponse), status.Error(codes.NotFound, "Coin not found") + return new(pb.CoinInfoResponse), s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_symbol": req.Symbol, + })) } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { @@ -59,7 +65,10 @@ func (s *Service) CoinInfoById(ctx context.Context, req *pb.CoinIdRequest) (*pb. coin := cState.Coins().GetCoin(types.CoinID(req.Id)) if coin == nil { - return new(pb.CoinInfoResponse), status.Error(codes.NotFound, "Coin not found") + return new(pb.CoinInfoResponse), s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": strconv.Itoa(int(req.Id)), + })) } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { From 9b542da71dbab2102a20fc3b334266038517a53e Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Mon, 7 Sep 2020 12:19:23 +0300 Subject: [PATCH 217/426] Fixes --- core/state/candidates/candidates.go | 93 +++++++++++++++++++++-------- core/state/candidates/model.go | 54 ++++++----------- core/state/candidates_test.go | 4 +- go.mod | 2 +- 4 files changed, 90 insertions(+), 63 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 4f073540e..31c764103 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -17,13 +17,16 @@ import ( "sync" ) +// Common constants const ( CandidateStatusOffline = 0x01 CandidateStatusOnline = 0x02 UnbondPeriod = 518400 MaxDelegatorsPerCandidate = 1000 +) +const ( mainPrefix = 'c' pubKeyIDPrefix = mainPrefix + 'p' blockListPrefix = mainPrefix + 'b' @@ -37,6 +40,7 @@ var ( minValidatorBipStake = big.NewInt(1000) ) +// RCandidates interface represents Candidates state type RCandidates interface { Export(state *types.AppState) Exists(pubkey types.Pubkey) bool @@ -53,9 +57,10 @@ type RCandidates interface { GetCandidate(pubkey types.Pubkey) *Candidate LoadStakes() GetCandidates() []*Candidate - GetStakes(pubkey types.Pubkey) []*Stake + GetStakes(pubkey types.Pubkey) []*stake } +// Candidates struct is a store of Candidates state type Candidates struct { list map[uint32]*Candidate @@ -71,6 +76,7 @@ type Candidates struct { loaded bool } +// NewCandidates returns newly created Candidates state with a given bus and iavl func NewCandidates(bus *bus.Bus, iavl tree.MTree) (*Candidates, error) { candidates := &Candidates{iavl: iavl, bus: bus} candidates.bus.SetCandidates(NewBus(candidates)) @@ -78,6 +84,7 @@ func NewCandidates(bus *bus.Bus, iavl tree.MTree) (*Candidates, error) { return candidates, nil } +// Commit writes changes to iavl, may return an error func (c *Candidates) Commit() error { keys := c.getOrderedCandidates() @@ -115,12 +122,12 @@ func (c *Candidates) Commit() error { sort.SliceStable(pubIDs, func(i, j int) bool { return pubIDs[i].ID < pubIDs[j].ID }) - pubIdData, err := rlp.EncodeToBytes(pubIDs) + pubIDData, err := rlp.EncodeToBytes(pubIDs) if err != nil { panic(fmt.Sprintf("failed to encode candidates public key with ID: %s", err)) } - c.iavl.Set([]byte{pubKeyIDPrefix}, pubIdData) + c.iavl.Set([]byte{pubKeyIDPrefix}, pubIDData) var blockList []types.Pubkey for pubKey := range c.blockList { @@ -193,6 +200,9 @@ func (c *Candidates) Commit() error { return nil } +// GetNewCandidates returns list of candidates that can be the new validators +// Skips offline candidates and candidates with stake less than minValidatorBipStake +// Result is sorted by candidates stakes and limited to valCount func (c *Candidates) GetNewCandidates(valCount int) []Candidate { var result []Candidate @@ -220,6 +230,7 @@ func (c *Candidates) GetNewCandidates(valCount int) []Candidate { return result } +// Create creates a new candidate with given params and adds it to state func (c *Candidates) Create(ownerAddress, rewardAddress, controlAddress types.Address, pubkey types.Pubkey, commission uint) { candidate := &Candidate{ ID: c.getOrNewID(pubkey), @@ -230,7 +241,7 @@ func (c *Candidates) Create(ownerAddress, rewardAddress, controlAddress types.Ad Commission: commission, Status: CandidateStatusOffline, totalBipStake: big.NewInt(0), - stakes: [MaxDelegatorsPerCandidate]*Stake{}, + stakes: [MaxDelegatorsPerCandidate]*stake{}, isDirty: true, isTotalStakeDirty: true, } @@ -239,11 +250,16 @@ func (c *Candidates) Create(ownerAddress, rewardAddress, controlAddress types.Ad c.setToMap(pubkey, candidate) } +// CreateWithID creates a new candidate with given params and adds it to state +// CreateWithID uses given ID to be associated with public key of a candidate func (c *Candidates) CreateWithID(ownerAddress, rewardAddress, controlAddress types.Address, pubkey types.Pubkey, commission uint, id uint32) { c.setPubKeyID(pubkey, id) c.Create(ownerAddress, rewardAddress, controlAddress, pubkey, commission) } +// PunishByzantineCandidate finds candidate with given tmAddress and punishes it: +// 1. Subs 5% of each stake of a candidate +// 2. Unbond each stake of a candidate func (c *Candidates) PunishByzantineCandidate(height uint64, tmAddress types.TmAddress) { candidate := c.GetCandidateByTendermintAddress(tmAddress) stakes := c.GetStakes(candidate.PubKey) @@ -282,6 +298,7 @@ func (c *Candidates) PunishByzantineCandidate(height uint64, tmAddress types.TmA } } +// GetCandidateByTendermintAddress finds and returns candidate with given tendermint-address func (c *Candidates) GetCandidateByTendermintAddress(address types.TmAddress) *Candidate { candidates := c.GetCandidates() for _, candidate := range candidates { @@ -293,11 +310,14 @@ func (c *Candidates) GetCandidateByTendermintAddress(address types.TmAddress) *C return nil } +// RecalculateStakes recalculate stakes of all candidates: +// 1. Updates bip-value of each stake +// 2. Applies updates func (c *Candidates) RecalculateStakes(height uint64) { - c.recalculateStakesNew(height) + c.recalculateStakes(height) } -func (c *Candidates) recalculateStakesNew(height uint64) { +func (c *Candidates) recalculateStakes(height uint64) { coinsCache := newCoinsCache() for _, pubkey := range c.getOrderedCandidates() { @@ -353,7 +373,7 @@ func (c *Candidates) recalculateStakesNew(height uint64) { c.stakeKick(stakes[index].Owner, stakes[index].Value, stakes[index].Coin, candidate.PubKey, height) } - candidate.SetStakeAtIndex(index, update, true) + candidate.setStakeAtIndex(index, update, true) } candidate.clearUpdates() @@ -382,6 +402,7 @@ func (c *Candidates) stakeKick(owner types.Address, value *big.Int, coin types.C c.bus.Checker().AddCoin(coin, big.NewInt(0).Neg(value)) } +// Exists returns wherever a candidate with given public key exists func (c *Candidates) Exists(pubkey types.Pubkey) bool { c.lock.RLock() defer c.lock.RUnlock() @@ -397,6 +418,7 @@ func (c *Candidates) existPubKey(pubKey types.Pubkey) bool { return exists } +// IsBlockedPubKey returns if given public key is blacklisted func (c *Candidates) IsBlockedPubKey(pubkey types.Pubkey) bool { return c.isBlocked(pubkey) } @@ -409,6 +431,7 @@ func (c *Candidates) isBlocked(pubKey types.Pubkey) bool { return exists } +// Count returns current amount of candidates func (c *Candidates) Count() int { c.lock.RLock() defer c.lock.RUnlock() @@ -416,6 +439,7 @@ func (c *Candidates) Count() int { return len(c.list) } +// IsNewCandidateStakeSufficient determines if given stake is sufficient to create new candidate func (c *Candidates) IsNewCandidateStakeSufficient(coin types.CoinID, stake *big.Int, limit int) bool { c.lock.RLock() defer c.lock.RUnlock() @@ -440,10 +464,12 @@ func (c *Candidates) IsNewCandidateStakeSufficient(coin types.CoinID, stake *big return false } +// GetCandidate returns candidate by a public key func (c *Candidates) GetCandidate(pubkey types.Pubkey) *Candidate { return c.getFromMap(pubkey) } +// IsDelegatorStakeSufficient determines if given stake is sufficient to add it to a candidate func (c *Candidates) IsDelegatorStakeSufficient(address types.Address, pubkey types.Pubkey, coin types.CoinID, amount *big.Int) bool { stakes := c.GetStakes(pubkey) if len(stakes) < MaxDelegatorsPerCandidate { @@ -460,8 +486,9 @@ func (c *Candidates) IsDelegatorStakeSufficient(address types.Address, pubkey ty return false } +// Delegate adds a stake to a candidate func (c *Candidates) Delegate(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int, bipValue *big.Int) { - stake := &Stake{ + stake := &stake{ Owner: address, Coin: coin, Value: big.NewInt(0).Set(value), @@ -469,12 +496,12 @@ func (c *Candidates) Delegate(address types.Address, pubkey types.Pubkey, coin t } candidate := c.GetCandidate(pubkey) - candidate.addUpdate(stake) c.bus.Checker().AddCoin(coin, value) } +// Edit edits a candidate func (c *Candidates) Edit(pubkey types.Pubkey, rewardAddress types.Address, ownerAddress types.Address, controlAddress types.Address) { candidate := c.getFromMap(pubkey) candidate.setOwner(ownerAddress) @@ -482,20 +509,24 @@ func (c *Candidates) Edit(pubkey types.Pubkey, rewardAddress types.Address, owne candidate.setControl(controlAddress) } +// SetOnline sets candidate status to CandidateStatusOnline func (c *Candidates) SetOnline(pubkey types.Pubkey) { c.getFromMap(pubkey).setStatus(CandidateStatusOnline) } +// SetOffline sets candidate status to CandidateStatusOffline func (c *Candidates) SetOffline(pubkey types.Pubkey) { c.getFromMap(pubkey).setStatus(CandidateStatusOffline) } +// SubStake subs given value from delegator's stake func (c *Candidates) SubStake(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { stake := c.GetStakeOfAddress(pubkey, address, coin) stake.subValue(value) c.bus.Checker().AddCoin(coin, big.NewInt(0).Neg(value)) } +// GetCandidates returns a list of all candidates func (c *Candidates) GetCandidates() []*Candidate { var candidates []*Candidate for _, pubkey := range c.getOrderedCandidates() { @@ -505,6 +536,7 @@ func (c *Candidates) GetCandidates() []*Candidate { return candidates } +// GetTotalStake calculates and returns total stake of a candidate func (c *Candidates) GetTotalStake(pubkey types.Pubkey) *big.Int { candidate := c.getFromMap(pubkey) if candidate.totalBipStake == nil { @@ -523,10 +555,11 @@ func (c *Candidates) GetTotalStake(pubkey types.Pubkey) *big.Int { return candidate.totalBipStake } -func (c *Candidates) GetStakes(pubkey types.Pubkey) []*Stake { +// GetStakes returns list of stakes of candidate with given public key +func (c *Candidates) GetStakes(pubkey types.Pubkey) []*stake { candidate := c.GetCandidate(pubkey) - var stakes []*Stake + var stakes []*stake for i := 0; i < MaxDelegatorsPerCandidate; i++ { stake := candidate.stakes[i] if stake == nil { @@ -538,11 +571,8 @@ func (c *Candidates) GetStakes(pubkey types.Pubkey) []*Stake { return stakes } -func (c *Candidates) StakesCount(pubkey types.Pubkey) int { - return c.GetCandidate(pubkey).stakesCount -} - -func (c *Candidates) GetStakeOfAddress(pubkey types.Pubkey, address types.Address, coin types.CoinID) *Stake { +// GetStakeOfAddress returns stake of address in given candidate and in given coin +func (c *Candidates) GetStakeOfAddress(pubkey types.Pubkey, address types.Address, coin types.CoinID) *stake { candidate := c.GetCandidate(pubkey) for _, stake := range candidate.stakes { if stake == nil { @@ -557,6 +587,7 @@ func (c *Candidates) GetStakeOfAddress(pubkey types.Pubkey, address types.Addres return nil } +// GetStakeValueOfAddress returns stake VALUE of address in given candidate and in given coin func (c *Candidates) GetStakeValueOfAddress(pubkey types.Pubkey, address types.Address, coin types.CoinID) *big.Int { stake := c.GetStakeOfAddress(pubkey, address, coin) if stake == nil { @@ -566,15 +597,17 @@ func (c *Candidates) GetStakeValueOfAddress(pubkey types.Pubkey, address types.A return stake.Value } +// GetCandidateOwner returns candidate's owner address func (c *Candidates) GetCandidateOwner(pubkey types.Pubkey) types.Address { return c.getFromMap(pubkey).OwnerAddress } +// GetCandidateControl returns candidate's control address func (c *Candidates) GetCandidateControl(pubkey types.Pubkey) types.Address { return c.getFromMap(pubkey).ControlAddress } -// Load only list candidates (for read) +// LoadCandidates Loads only list of candidates (for read) func (c *Candidates) LoadCandidates() { if c.checkAndSetLoaded() { return @@ -583,7 +616,7 @@ func (c *Candidates) LoadCandidates() { _ = c.loadCandidatesList() } -// Load full info about candidates (for edit) +// LoadCandidatesDeliver Loads full info about candidates (for edit) func (c *Candidates) LoadCandidatesDeliver() { if c.checkAndSetLoaded() { return @@ -670,6 +703,7 @@ func (c *Candidates) checkAndSetLoaded() bool { return false } +// LoadStakes loads all stakes of candidates func (c *Candidates) LoadStakes() { for pubkey := range c.pubKeyIDs { c.LoadStakesOfCandidate(pubkey) @@ -722,11 +756,13 @@ func (c *Candidates) calculateBipValue(coinID types.CoinID, amount *big.Int, inc return big.NewInt(0).Div(big.NewInt(0).Mul(big.NewInt(0).Sub(coin.Reserve, saleReturn), amount), totalDelegatedValue) } +// Punish punished a candidate with given tendermint-address +// 1. Subs 1% from each stake +// 2. Calculate and return new total stake func (c *Candidates) Punish(height uint64, address types.TmAddress) *big.Int { totalStake := big.NewInt(0) candidate := c.GetCandidateByTendermintAddress(address) - stakes := c.GetStakes(candidate.PubKey) for _, stake := range stakes { newValue := big.NewInt(0).Set(stake.Value) @@ -764,12 +800,13 @@ func (c *Candidates) Punish(height uint64, address types.TmAddress) *big.Int { return totalStake } +// SetStakes Sets stakes and updates of a candidate. Used in Import. func (c *Candidates) SetStakes(pubkey types.Pubkey, stakes []types.Stake, updates []types.Stake) { candidate := c.GetCandidate(pubkey) candidate.stakesCount = len(stakes) for _, u := range updates { - candidate.addUpdate(&Stake{ + candidate.addUpdate(&stake{ Owner: u.Owner, Coin: u.Coin, Value: helpers.StringToBigInt(u.Value), @@ -782,7 +819,7 @@ func (c *Candidates) SetStakes(pubkey types.Pubkey, stakes []types.Stake, update count = MaxDelegatorsPerCandidate for _, u := range stakes[1000:] { - candidate.addUpdate(&Stake{ + candidate.addUpdate(&stake{ Owner: u.Owner, Coin: u.Coin, Value: helpers.StringToBigInt(u.Value), @@ -792,7 +829,7 @@ func (c *Candidates) SetStakes(pubkey types.Pubkey, stakes []types.Stake, update } for i, s := range stakes[:count] { - candidate.stakes[i] = &Stake{ + candidate.stakes[i] = &stake{ Owner: s.Owner, Coin: s.Coin, Value: helpers.StringToBigInt(s.Value), @@ -807,6 +844,7 @@ func (c *Candidates) SetStakes(pubkey types.Pubkey, stakes []types.Stake, update } } +// Export exports all data to the given state func (c *Candidates) Export(state *types.AppState) { c.LoadCandidatesDeliver() c.LoadStakes() @@ -910,10 +948,12 @@ func (c *Candidates) setPubKeyIDs(list map[types.Pubkey]uint32) { c.pubKeyIDs = list } +// SetTotalStake sets candidate's total bip stake. Used in Import. func (c *Candidates) SetTotalStake(pubkey types.Pubkey, stake *big.Int) { c.GetCandidate(pubkey).setTotalBipStake(stake) } +// LoadStakesOfCandidate loads stakes of given candidate from disk func (c *Candidates) LoadStakesOfCandidate(pubkey types.Pubkey) { candidate := c.GetCandidate(pubkey) @@ -930,12 +970,12 @@ func (c *Candidates) LoadStakesOfCandidate(pubkey types.Pubkey) { continue } - stake := &Stake{} + stake := &stake{} if err := rlp.DecodeBytes(enc, stake); err != nil { panic(fmt.Sprintf("failed to decode stake: %s", err)) } - candidate.SetStakeAtIndex(index, stake, false) + candidate.setStakeAtIndex(index, stake, false) stakesCount++ } @@ -950,7 +990,7 @@ func (c *Candidates) LoadStakesOfCandidate(pubkey types.Pubkey) { if len(enc) == 0 { candidate.updates = nil } else { - var updates []*Stake + var updates []*stake if err := rlp.DecodeBytes(enc, &updates); err != nil { panic(fmt.Sprintf("failed to decode updated: %s", err)) } @@ -980,6 +1020,7 @@ func (c *Candidates) LoadStakesOfCandidate(pubkey types.Pubkey) { c.setToMap(candidate.PubKey, candidate) } +// ChangePubKey change public key of a candidate from old to new func (c *Candidates) ChangePubKey(old types.Pubkey, new types.Pubkey) { if c.isBlocked(new) { panic("Candidate with such public key (" + new.String() + ") exists in block list") @@ -1013,6 +1054,7 @@ func (c *Candidates) id(pubKey types.Pubkey) uint32 { return c.pubKeyIDs[pubKey] } +// ID returns an id of candidate by it's public key func (c *Candidates) ID(pubKey types.Pubkey) uint32 { c.lock.RLock() defer c.lock.RUnlock() @@ -1049,6 +1091,7 @@ func (c *Candidates) setBlockPubKey(p types.Pubkey) { c.isDirty = true } +// AddToBlockPubKey blacklists given publickey func (c *Candidates) AddToBlockPubKey(p types.Pubkey) { c.setBlockPubKey(p) } diff --git a/core/state/candidates/model.go b/core/state/candidates/model.go index 257691818..28c0ec3d7 100644 --- a/core/state/candidates/model.go +++ b/core/state/candidates/model.go @@ -13,6 +13,7 @@ type pubkeyID struct { ID uint32 } +// Candidate represents candidate object which is stored on disk type Candidate struct { PubKey types.Pubkey RewardAddress types.Address @@ -24,8 +25,8 @@ type Candidate struct { totalBipStake *big.Int stakesCount int - stakes [MaxDelegatorsPerCandidate]*Stake - updates []*Stake + stakes [MaxDelegatorsPerCandidate]*stake + updates []*stake tmAddress *types.TmAddress isDirty bool @@ -60,7 +61,7 @@ func (candidate *Candidate) setControl(address types.Address) { candidate.ControlAddress = address } -func (candidate *Candidate) addUpdate(stake *Stake) { +func (candidate *Candidate) addUpdate(stake *stake) { candidate.isUpdatesDirty = true stake.markDirty = func(i int) { candidate.isUpdatesDirty = true @@ -84,6 +85,7 @@ func (candidate *Candidate) setTotalBipStake(totalBipValue *big.Int) { candidate.totalBipStake.Set(totalBipValue) } +// GetTmAddress returns tendermint-address of a candidate func (candidate *Candidate) GetTmAddress() types.TmAddress { return *candidate.tmAddress } @@ -99,8 +101,9 @@ func (candidate *Candidate) setTmAddress() { candidate.tmAddress = &address } -func (candidate *Candidate) GetFilteredUpdates() []*Stake { - var updates []*Stake +// GetFilteredUpdates returns updates which is > 0 in their value + merge similar updates +func (candidate *Candidate) GetFilteredUpdates() []*stake { + var updates []*stake for _, update := range candidate.updates { // skip updates with 0 stakes if update.Value.Cmp(big.NewInt(0)) != 1 { @@ -125,8 +128,9 @@ func (candidate *Candidate) GetFilteredUpdates() []*Stake { return updates } +// FilterUpdates filters candidate updates: remove 0-valued updates and merge similar ones func (candidate *Candidate) FilterUpdates() { - var updates []*Stake + var updates []*stake for _, update := range candidate.updates { // skip updates with 0 stakes if update.Value.Cmp(big.NewInt(0)) != 1 { @@ -156,21 +160,12 @@ func (candidate *Candidate) FilterUpdates() { candidate.isUpdatesDirty = true } -func (candidate *Candidate) updateStakesCount() { - count := 0 - for _, stake := range candidate.stakes { - if stake != nil { - count++ - } - } - candidate.stakesCount = count -} - +// GetTotalBipStake returns total stake value of a candidate func (candidate *Candidate) GetTotalBipStake() *big.Int { return big.NewInt(0).Set(candidate.totalBipStake) } -func (candidate *Candidate) SetStakeAtIndex(index int, stake *Stake, isDirty bool) { +func (candidate *Candidate) setStakeAtIndex(index int, stake *stake, isDirty bool) { stake.markDirty = func(i int) { candidate.dirtyStakes[i] = true } @@ -183,7 +178,7 @@ func (candidate *Candidate) SetStakeAtIndex(index int, stake *Stake, isDirty boo } } -type Stake struct { +type stake struct { Owner types.Address Coin types.CoinID Value *big.Int @@ -193,17 +188,17 @@ type Stake struct { markDirty func(int) } -func (stake *Stake) addValue(value *big.Int) { +func (stake *stake) addValue(value *big.Int) { stake.markDirty(stake.index) stake.Value.Add(stake.Value, value) } -func (stake *Stake) subValue(value *big.Int) { +func (stake *stake) subValue(value *big.Int) { stake.markDirty(stake.index) stake.Value.Sub(stake.Value, value) } -func (stake *Stake) setBipValue(value *big.Int) { +func (stake *stake) setBipValue(value *big.Int) { if stake.BipValue.Cmp(value) != 0 { stake.markDirty(stake.index) } @@ -211,24 +206,11 @@ func (stake *Stake) setBipValue(value *big.Int) { stake.BipValue.Set(value) } -func (stake *Stake) setNewOwner(coin types.CoinID, owner types.Address) { - stake.Coin = coin - stake.Owner = owner - stake.BipValue = big.NewInt(0) - stake.Value = big.NewInt(0) - stake.markDirty(stake.index) -} - -func (stake *Stake) setValue(ret *big.Int) { +func (stake *stake) setValue(ret *big.Int) { stake.markDirty(stake.index) stake.Value.Set(ret) } -func (stake *Stake) setCoin(coin types.CoinID) { - stake.markDirty(stake.index) - stake.Coin = coin -} - type coinsCache struct { list map[types.CoinID]*coinsCacheItem } @@ -253,7 +235,7 @@ func (c *coinsCache) Exists(id types.CoinID) bool { } func (c *coinsCache) Get(id types.CoinID) (saleReturn *big.Int, totalAmount *big.Int) { - return c.list[id].totalAmount, c.list[id].totalAmount + return big.NewInt(0).Set(c.list[id].totalAmount), big.NewInt(0).Set(c.list[id].totalAmount) } func (c *coinsCache) Set(id types.CoinID, saleReturn *big.Int, totalAmount *big.Int) { diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index a48159700..0353232fb 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -419,7 +419,9 @@ func TestDelegationAfterUnbond(t *testing.T) { st.Candidates.SubStake(addr, pubkey, coin, amount) st.Candidates.RecalculateStakes(height) - st.Candidates.Commit() + if err := st.Candidates.Commit(); err != nil { + panic(err) + } } // delegate diff --git a/go.mod b/go.mod index ce6f08e0d..72292ac41 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/MinterTeam/minter-go-node -go 1.13 +go 1.15 require ( github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200904221942-ac3acb43c093 From 716360e20ad181f04c61f168dea378aaa79f7f93 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Mon, 7 Sep 2020 12:28:00 +0300 Subject: [PATCH 218/426] fix --- core/transaction/create_coin.go | 7 ++++--- core/transaction/create_multisig.go | 5 +++-- core/transaction/declare_candidacy.go | 5 +++-- core/transaction/delegate.go | 5 +++-- core/transaction/edit_candidate.go | 8 +++----- core/transaction/edit_multisig_owners.go | 5 +++-- core/transaction/multisend.go | 9 +++++---- core/transaction/recreate_coin.go | 5 +++-- core/transaction/send.go | 5 +++-- core/transaction/switch_candidate_status.go | 5 +++-- core/transaction/unbond.go | 5 +++-- 11 files changed, 36 insertions(+), 28 deletions(-) diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index 0568e9c42..87756ba12 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -3,15 +3,16 @@ package transaction import ( "encoding/hex" "fmt" + "math/big" + "regexp" + "strconv" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/MinterTeam/minter-go-node/helpers" "github.com/tendermint/tendermint/libs/kv" - "math/big" - "regexp" - "strconv" ) const maxCoinNameBytes = 64 diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index 6d61bdbab..01bedc9eb 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -3,6 +3,9 @@ package transaction import ( "encoding/hex" "fmt" + "math/big" + "strconv" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" @@ -10,8 +13,6 @@ import ( "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" - "math/big" - "strconv" ) type CreateMultisigData struct { diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index 4891b8b1e..c5c3912df 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -3,6 +3,9 @@ package transaction import ( "encoding/hex" "fmt" + "math/big" + "strconv" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" @@ -10,8 +13,6 @@ import ( "github.com/MinterTeam/minter-go-node/core/validators" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" - "math/big" - "strconv" ) const minCommission = 0 diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index 9b0e05712..cef8d4c93 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -3,6 +3,9 @@ package transaction import ( "encoding/hex" "fmt" + "math/big" + "strconv" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" @@ -10,8 +13,6 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/MinterTeam/minter-go-node/hexutil" "github.com/tendermint/tendermint/libs/kv" - "math/big" - "strconv" ) type DelegateData struct { diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index 03fddcc9c..af2e0928b 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -3,14 +3,15 @@ package transaction import ( "encoding/hex" "fmt" + "math/big" + "strconv" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" - "math/big" - "strconv" ) type CandidateTx interface { @@ -79,8 +80,6 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa return *errResp } -<<<<<<< HEAD -======= if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { return Response{ Code: code.CoinReserveNotSufficient, @@ -94,7 +93,6 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa } } ->>>>>>> alpha/v1.2 commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/edit_multisig_owners.go b/core/transaction/edit_multisig_owners.go index 269b13323..7e9cdab2c 100644 --- a/core/transaction/edit_multisig_owners.go +++ b/core/transaction/edit_multisig_owners.go @@ -3,14 +3,15 @@ package transaction import ( "encoding/hex" "fmt" + "math/big" + "strconv" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" - "math/big" - "strconv" ) type EditMultisigOwnersData struct { diff --git a/core/transaction/multisend.go b/core/transaction/multisend.go index 2549c1709..5d05754c0 100644 --- a/core/transaction/multisend.go +++ b/core/transaction/multisend.go @@ -4,16 +4,17 @@ import ( "encoding/hex" "encoding/json" "fmt" + "math/big" + "sort" + "strconv" + "strings" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" - "math/big" - "sort" - "strconv" - "strings" ) type MultisendData struct { diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 90f3408ff..3e23f908a 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -3,14 +3,15 @@ package transaction import ( "encoding/hex" "fmt" + "math/big" + "strconv" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" - "math/big" - "strconv" ) type RecreateCoinData struct { diff --git a/core/transaction/send.go b/core/transaction/send.go index 4a4d7d39a..3221211ac 100644 --- a/core/transaction/send.go +++ b/core/transaction/send.go @@ -3,14 +3,15 @@ package transaction import ( "encoding/hex" "fmt" + "math/big" + "strconv" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" - "math/big" - "strconv" ) type SendData struct { diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index e13491141..6585dfe33 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -4,14 +4,15 @@ import ( "encoding/hex" "encoding/json" "fmt" + "math/big" + "strconv" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" - "math/big" - "strconv" ) type SetCandidateOnData struct { diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 5136fd1e3..fbdcbe856 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -3,6 +3,9 @@ package transaction import ( "encoding/hex" "fmt" + "math/big" + "strconv" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" @@ -10,8 +13,6 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/MinterTeam/minter-go-node/hexutil" "github.com/tendermint/tendermint/libs/kv" - "math/big" - "strconv" ) const unbondPeriod = 518400 From 56bac594986bb1e64a26bd5b3e76ddda79760b8c Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Mon, 7 Sep 2020 12:34:01 +0300 Subject: [PATCH 219/426] remove unused check --- core/transaction/create_coin.go | 13 ------------ core/transaction/create_multisig.go | 13 ------------ core/transaction/declare_candidacy.go | 13 ------------ core/transaction/delegate.go | 23 +++++++++------------ core/transaction/edit_candidate.go | 13 ------------ core/transaction/edit_multisig_owners.go | 13 ------------ core/transaction/multisend.go | 13 ------------ core/transaction/price_vote.go | 12 ----------- core/transaction/recreate_coin.go | 13 ------------ core/transaction/send.go | 15 -------------- core/transaction/switch_candidate_status.go | 13 ------------ core/transaction/unbond.go | 13 ------------ 12 files changed, 10 insertions(+), 157 deletions(-) diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index 87756ba12..81c890470 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -158,19 +158,6 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP return *errResp } - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Gas coin reserve balance is not sufficient for transaction. Has: %s %s, required %s %s", coin.Reserve().String(), types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_value": coin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin_symbol": fmt.Sprintf("%s", types.GetBaseCoin()), - }), - } - } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index 01bedc9eb..9cf574095 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -105,19 +105,6 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_value": gasCoin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index c5c3912df..6db53dd42 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -130,19 +130,6 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_reserve": gasCoin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index cef8d4c93..efc58c57d 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -41,6 +41,16 @@ func (data DelegateData) BasicCheck(tx *Transaction, context *state.CheckState) })} } + if !context.Coins().Exists(data.Coin) { + return &Response{ + Code: code.CoinNotExists, + Log: fmt.Sprintf("Coin %s not exists", data.Coin), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.CoinNotExists)), + "coin_id": fmt.Sprintf("%s", data.Coin.String()), + })} + } + if data.Value.Cmp(types.Big0) < 1 { return &Response{ Code: code.StakeShouldBePositive, @@ -110,19 +120,6 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_reserve": gasCoin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index af2e0928b..03a5ef203 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -80,19 +80,6 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_reserve": gasCoin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/edit_multisig_owners.go b/core/transaction/edit_multisig_owners.go index 7e9cdab2c..79224a93c 100644 --- a/core/transaction/edit_multisig_owners.go +++ b/core/transaction/edit_multisig_owners.go @@ -137,19 +137,6 @@ func (data EditMultisigOwnersData) Run(tx *Transaction, context state.Interface, return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_reserve": gasCoin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/multisend.go b/core/transaction/multisend.go index 5d05754c0..17b66fe8c 100644 --- a/core/transaction/multisend.go +++ b/core/transaction/multisend.go @@ -94,19 +94,6 @@ func (data MultisendData) Run(tx *Transaction, context state.Interface, rewardPo return *errResp } - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_value": coin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin_symbol": coin.CName, - }), - } - } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/price_vote.go b/core/transaction/price_vote.go index e7e09bcca..81b7444eb 100644 --- a/core/transaction/price_vote.go +++ b/core/transaction/price_vote.go @@ -54,18 +54,6 @@ func (data PriceVoteData) Run(tx *Transaction, context state.Interface, rewardPo return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "has_reserve": gasCoin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin": gasCoin.GetFullSymbol(), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 3e23f908a..6fc8f66fd 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -146,19 +146,6 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Gas coin reserve balance is not sufficient for transaction. Has: %s %s, required %s %s", gasCoin.Reserve().String(), types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_value": gasCoin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/send.go b/core/transaction/send.go index 3221211ac..ebb5fb502 100644 --- a/core/transaction/send.go +++ b/core/transaction/send.go @@ -40,21 +40,6 @@ func (data SendData) TotalSpend(tx *Transaction, context *state.CheckState) (Tot return nil, nil, nil, errResp } - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return nil, nil, nil, &Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", - coin.Reserve().String(), - commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_value": coin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin_symbol": fmt.Sprintf("%s", types.GetBaseCoin().String()), - }), - } - } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) conversions = append(conversions, Conversion{ FromCoin: tx.GasCoin, diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index 6585dfe33..2156f9251 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -61,19 +61,6 @@ func (data SetCandidateOnData) Run(tx *Transaction, context state.Interface, rew return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_value": gasCoin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin": gasCoin.GetFullSymbol(), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index fbdcbe856..35dbda087 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -132,19 +132,6 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool return *errResp } - if gasCoin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", gasCoin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_value": gasCoin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), - } - } - commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } From d5e9628c10494bdf54454e2d11fb57817042190a Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 7 Sep 2020 15:16:06 +0300 Subject: [PATCH 220/426] refactoring --- api/v2/service/address.go | 13 ++++++----- api/v2/service/addresses.go | 5 ++-- api/v2/service/block.go | 1 + api/v2/service/candidate.go | 1 + api/v2/service/candidates.go | 1 + api/v2/service/coin_info.go | 2 ++ api/v2/service/estimate_coin_buy.go | 1 + api/v2/service/estimate_coin_sell.go | 1 + api/v2/service/estimate_coin_sell_all.go | 1 + api/v2/service/estimate_tx_commission.go | 1 + api/v2/service/events.go | 1 + api/v2/service/frozen.go | 1 + api/v2/service/gas.go | 2 ++ api/v2/service/genesis.go | 1 + api/v2/service/halts.go | 1 + api/v2/service/missed_blocks.go | 1 + api/v2/service/net_info.go | 7 +++++- api/v2/service/send_transaction.go | 1 + api/v2/service/service.go | 12 ++++++++++ api/v2/service/status.go | 7 +++++- api/v2/service/transaction.go | 11 +-------- api/v2/service/transactions.go | 1 + api/v2/service/unconfirmed_txs.go | 1 + api/v2/service/validators.go | 1 + api/v2/service/waitlist.go | 1 + api/v2/service/ws.go | 1 + api/v2/v2.go | 29 +++++++++++++----------- cli/cli_pb/manager.pb.go | 27 +++++++++++++++------- cli/cli_pb/manager.proto | 1 + cli/service/server_test.go | 4 +++- cli/service/service.go | 17 +++++++++++--- cmd/minter/cmd/node.go | 2 +- go.mod | 2 +- go.sum | 4 ++-- 34 files changed, 114 insertions(+), 49 deletions(-) diff --git a/api/v2/service/address.go b/api/v2/service/address.go index c0ec81cdf..26c93b368 100644 --- a/api/v2/service/address.go +++ b/api/v2/service/address.go @@ -14,11 +14,12 @@ import ( "strings" ) -type UserStake struct { +type stakeUser struct { Value *big.Int BipValue *big.Int } +// Returns coins list, balance and transaction count of an address. func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.AddressResponse, error) { if !strings.HasPrefix(strings.Title(req.Address), "Mx") { return new(pb.AddressResponse), status.Error(codes.InvalidArgument, "invalid address") @@ -69,14 +70,14 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr } if req.Delegated { - var userDelegatedStakesGroupByCoin = map[types.CoinID]*UserStake{} + var userDelegatedStakesGroupByCoin = map[types.CoinID]*stakeUser{} allCandidates := cState.Candidates().GetCandidates() for _, candidate := range allCandidates { userStakes := userStakes(candidate.PubKey, address, cState) for coin, userStake := range userStakes { stake, ok := userDelegatedStakesGroupByCoin[coin] if !ok { - stake = &UserStake{ + stake = &stakeUser{ Value: big.NewInt(0), BipValue: big.NewInt(0), } @@ -160,8 +161,8 @@ func customCoinBipBalance(coinToSell types.CoinID, valueToSell *big.Int, cState return formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), basecoinValue) } -func userStakes(c types.Pubkey, address types.Address, state *state.CheckState) map[types.CoinID]*UserStake { - var userStakes = map[types.CoinID]*UserStake{} +func userStakes(c types.Pubkey, address types.Address, state *state.CheckState) map[types.CoinID]*stakeUser { + var userStakes = map[types.CoinID]*stakeUser{} stakes := state.Candidates().GetStakes(c) @@ -169,7 +170,7 @@ func userStakes(c types.Pubkey, address types.Address, state *state.CheckState) if stake.Owner != address { continue } - userStakes[stake.Coin] = &UserStake{ + userStakes[stake.Coin] = &stakeUser{ Value: stake.Value, BipValue: stake.BipValue, } diff --git a/api/v2/service/addresses.go b/api/v2/service/addresses.go index ca2acd95e..019882dbe 100644 --- a/api/v2/service/addresses.go +++ b/api/v2/service/addresses.go @@ -11,6 +11,7 @@ import ( "math/big" ) +// Returns list of addresses. func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb.AddressesResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { @@ -70,14 +71,14 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. } if req.Delegated { - var userDelegatedStakesGroupByCoin = map[types.CoinID]*UserStake{} + var userDelegatedStakesGroupByCoin = map[types.CoinID]*stakeUser{} allCandidates := cState.Candidates().GetCandidates() for _, candidate := range allCandidates { userStakes := userStakes(candidate.PubKey, address, cState) for coin, userStake := range userStakes { stake, ok := userDelegatedStakesGroupByCoin[coin] if !ok { - stake = &UserStake{ + stake = &stakeUser{ Value: big.NewInt(0), BipValue: big.NewInt(0), } diff --git a/api/v2/service/block.go b/api/v2/service/block.go index 776b92559..b684bbed7 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -18,6 +18,7 @@ import ( "time" ) +// Returns block data at given height. func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockResponse, error) { height := int64(req.Height) block, err := s.client.Block(&height) diff --git a/api/v2/service/candidate.go b/api/v2/service/candidate.go index 71f2623bf..3e731fc0d 100644 --- a/api/v2/service/candidate.go +++ b/api/v2/service/candidate.go @@ -13,6 +13,7 @@ import ( "math/big" ) +// Returns candidate’s info by provided public_key. It will respond with 404 code if candidate is not found. func (s *Service) Candidate(ctx context.Context, req *pb.CandidateRequest) (*pb.CandidateResponse, error) { if len(req.PublicKey) < 3 { return new(pb.CandidateResponse), status.Error(codes.InvalidArgument, "invalid public_key") diff --git a/api/v2/service/candidates.go b/api/v2/service/candidates.go index 91d5a88c3..8528ebdb8 100644 --- a/api/v2/service/candidates.go +++ b/api/v2/service/candidates.go @@ -7,6 +7,7 @@ import ( "google.golang.org/grpc/status" ) +// Returns list of candidates. func (s *Service) Candidates(ctx context.Context, req *pb.CandidatesRequest) (*pb.CandidatesResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index f5f54d166..a31d22a1a 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -13,6 +13,7 @@ import ( "strconv" ) +// Returns information about coin symbol. func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.CoinInfoResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { @@ -54,6 +55,7 @@ func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.Co }, nil } +// Returns information about coin ID. func (s *Service) CoinInfoById(ctx context.Context, req *pb.CoinIdRequest) (*pb.CoinInfoResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index 03a569b9c..331e5a843 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -15,6 +15,7 @@ import ( "strconv" ) +// Return estimate of buy coin transaction. func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRequest) (*pb.EstimateCoinBuyResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index ba071665e..2d1799fc2 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -15,6 +15,7 @@ import ( "strconv" ) +// Return estimate of sell coin transaction. func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSellRequest) (*pb.EstimateCoinSellResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index eb19b1de0..442c8e3f8 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -14,6 +14,7 @@ import ( "strconv" ) +// Return estimate of sell all coin transaction. func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinSellAllRequest) (*pb.EstimateCoinSellAllResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { diff --git a/api/v2/service/estimate_tx_commission.go b/api/v2/service/estimate_tx_commission.go index e920e11d5..4506fa43a 100644 --- a/api/v2/service/estimate_tx_commission.go +++ b/api/v2/service/estimate_tx_commission.go @@ -15,6 +15,7 @@ import ( "strings" ) +// Return estimate of transaction. func (s *Service) EstimateTxCommission(ctx context.Context, req *pb.EstimateTxCommissionRequest) (*pb.EstimateTxCommissionResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { diff --git a/api/v2/service/events.go b/api/v2/service/events.go index b00c4d4bf..1a2722cf4 100644 --- a/api/v2/service/events.go +++ b/api/v2/service/events.go @@ -9,6 +9,7 @@ import ( "google.golang.org/grpc/status" ) +// Returns events at given height. func (s *Service) Events(ctx context.Context, req *pb.EventsRequest) (*pb.EventsResponse, error) { height := uint32(req.Height) events := s.blockchain.GetEventsDB().LoadEvents(height) diff --git a/api/v2/service/frozen.go b/api/v2/service/frozen.go index 263362538..0ca379144 100644 --- a/api/v2/service/frozen.go +++ b/api/v2/service/frozen.go @@ -11,6 +11,7 @@ import ( "strings" ) +// Returns frozen balance. func (s *Service) Frozen(ctx context.Context, req *pb.FrozenRequest) (*pb.FrozenResponse, error) { if !strings.HasPrefix(strings.Title(req.Address), "Mx") { return new(pb.FrozenResponse), status.Error(codes.InvalidArgument, "invalid address") diff --git a/api/v2/service/gas.go b/api/v2/service/gas.go index 5af9edc62..a9510bc4e 100644 --- a/api/v2/service/gas.go +++ b/api/v2/service/gas.go @@ -9,12 +9,14 @@ import ( "google.golang.org/grpc/status" ) +// Returns current min gas price. func (s *Service) MinGasPrice(context.Context, *empty.Empty) (*pb.MinGasPriceResponse, error) { return &pb.MinGasPriceResponse{ MinGasPrice: fmt.Sprintf("%d", s.blockchain.MinGasPrice()), }, nil } +// Returns current max gas. func (s *Service) MaxGas(ctx context.Context, req *pb.MaxGasRequest) (*pb.MaxGasResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { diff --git a/api/v2/service/genesis.go b/api/v2/service/genesis.go index b125b9078..3ed3ec048 100644 --- a/api/v2/service/genesis.go +++ b/api/v2/service/genesis.go @@ -10,6 +10,7 @@ import ( "time" ) +// Returns genesis file. func (s *Service) Genesis(ctx context.Context, _ *empty.Empty) (*pb.GenesisResponse, error) { result, err := s.client.Genesis() if err != nil { diff --git a/api/v2/service/halts.go b/api/v2/service/halts.go index 91a40a429..1c3706bbb 100644 --- a/api/v2/service/halts.go +++ b/api/v2/service/halts.go @@ -7,6 +7,7 @@ import ( "google.golang.org/grpc/status" ) +// Returns func (s *Service) Halts(_ context.Context, req *pb.HaltsRequest) (*pb.HaltsResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { diff --git a/api/v2/service/missed_blocks.go b/api/v2/service/missed_blocks.go index b6b7fc64e..9b4a4d3df 100644 --- a/api/v2/service/missed_blocks.go +++ b/api/v2/service/missed_blocks.go @@ -6,6 +6,7 @@ import ( pb "github.com/MinterTeam/node-grpc-gateway/api_pb" ) +// Returns missed blocks by validator public key. func (s *Service) MissedBlocks(ctx context.Context, req *pb.MissedBlocksRequest) (*pb.MissedBlocksResponse, error) { blocks, count, err := s.blockchain.MissedBlocks(req.PublicKey, req.Height) if err != nil { diff --git a/api/v2/service/net_info.go b/api/v2/service/net_info.go index 92372f90f..17aaf7875 100644 --- a/api/v2/service/net_info.go +++ b/api/v2/service/net_info.go @@ -5,11 +5,14 @@ import ( "fmt" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "github.com/golang/protobuf/ptypes/empty" + "github.com/tendermint/tendermint/evidence" + types2 "github.com/tendermint/tendermint/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "time" ) +// Returns network info. func (s *Service) NetInfo(ctx context.Context, _ *empty.Empty) (*pb.NetInfoResponse, error) { result, err := s.client.NetInfo() if err != nil { @@ -18,7 +21,8 @@ func (s *Service) NetInfo(ctx context.Context, _ *empty.Empty) (*pb.NetInfoRespo var peers []*pb.NetInfoResponse_Peer for _, peer := range result.Peers { - + peerTM := s.tmNode.Switch().Peers().Get(peer.NodeInfo.ID()) + currentHeight := peerTM.Get(types2.PeerStateKey).(evidence.PeerState).GetHeight() if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { return new(pb.NetInfoResponse), timeoutStatus.Err() } @@ -35,6 +39,7 @@ func (s *Service) NetInfo(ctx context.Context, _ *empty.Empty) (*pb.NetInfoRespo } peers = append(peers, &pb.NetInfoResponse_Peer{ + LatestBlockHeight: fmt.Sprintf("%d", currentHeight), NodeInfo: &pb.NodeInfo{ ProtocolVersion: &pb.NodeInfo_ProtocolVersion{ P2P: fmt.Sprintf("%d", peer.NodeInfo.ProtocolVersion.P2P), diff --git a/api/v2/service/send_transaction.go b/api/v2/service/send_transaction.go index 98fa261ae..131fbfd6e 100644 --- a/api/v2/service/send_transaction.go +++ b/api/v2/service/send_transaction.go @@ -15,6 +15,7 @@ import ( "strings" ) +// Returns the result of sending signed tx. To ensure that transaction was successfully committed to the blockchain, you need to find the transaction by the hash and ensure that the status code equals to 0. func (s *Service) SendTransaction(ctx context.Context, req *pb.SendTransactionRequest) (*pb.SendTransactionResponse, error) { if !strings.HasPrefix(strings.Title(req.GetTx()), "0x") { return new(pb.SendTransactionResponse), status.Error(codes.InvalidArgument, "invalid transaction") diff --git a/api/v2/service/service.go b/api/v2/service/service.go index 429a49a1c..735d515b8 100644 --- a/api/v2/service/service.go +++ b/api/v2/service/service.go @@ -4,6 +4,7 @@ import ( "context" "github.com/MinterTeam/minter-go-node/config" "github.com/MinterTeam/minter-go-node/core/minter" + _struct "github.com/golang/protobuf/ptypes/struct" "github.com/tendermint/go-amino" tmNode "github.com/tendermint/tendermint/node" rpc "github.com/tendermint/tendermint/rpc/client/local" @@ -12,6 +13,7 @@ import ( "time" ) +// gRPC implementation ApiServiceServer type Service struct { cdc *amino.Codec blockchain *minter.Blockchain @@ -52,6 +54,16 @@ func (s *Service) createError(statusErr *status.Status, data string) error { return withDetails.Err() } +func encodeToStruct(b []byte) (*_struct.Struct, error) { + dataStruct := &_struct.Struct{} + if err := dataStruct.UnmarshalJSON(b); err != nil { + return nil, err + } + + return dataStruct, nil +} + +// TimeoutDuration gRPC func (s *Service) TimeoutDuration() time.Duration { return s.minterCfg.APIv2TimeoutDuration } diff --git a/api/v2/service/status.go b/api/v2/service/status.go index d8aadcac7..ac55d04e5 100644 --- a/api/v2/service/status.go +++ b/api/v2/service/status.go @@ -10,12 +10,17 @@ import ( "time" ) +// Returns current min gas price. func (s *Service) Status(context.Context, *empty.Empty) (*pb.StatusResponse, error) { result, err := s.client.Status() if err != nil { return new(pb.StatusResponse), status.Error(codes.Internal, err.Error()) } + cState := s.blockchain.CurrentState() + cState.RLock() + defer cState.RUnlock() + return &pb.StatusResponse{ Version: s.version, LatestBlockHash: fmt.Sprintf("%X", result.SyncInfo.LatestBlockHash), @@ -23,7 +28,7 @@ func (s *Service) Status(context.Context, *empty.Empty) (*pb.StatusResponse, err LatestBlockHeight: fmt.Sprintf("%d", result.SyncInfo.LatestBlockHeight), LatestBlockTime: result.SyncInfo.LatestBlockTime.Format(time.RFC3339Nano), KeepLastStates: fmt.Sprintf("%d", s.minterCfg.BaseConfig.KeepLastStates), - TotalSlashed: s.blockchain.CurrentState().App().GetTotalSlashed().String(), + TotalSlashed: cState.App().GetTotalSlashed().String(), CatchingUp: result.SyncInfo.CatchingUp, PublicKey: fmt.Sprintf("Mp%x", result.ValidatorInfo.PubKey.Bytes()[5:]), NodeId: string(result.NodeInfo.ID()), diff --git a/api/v2/service/transaction.go b/api/v2/service/transaction.go index 98363a103..63de7b910 100644 --- a/api/v2/service/transaction.go +++ b/api/v2/service/transaction.go @@ -6,12 +6,12 @@ import ( "fmt" "github.com/MinterTeam/minter-go-node/core/transaction" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" - _struct "github.com/golang/protobuf/ptypes/struct" tmbytes "github.com/tendermint/tendermint/libs/bytes" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) +// Returns transaction info. func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) (*pb.TransactionResponse, error) { if len(req.Hash) < 3 { return new(pb.TransactionResponse), status.Error(codes.InvalidArgument, "invalid hash") @@ -68,12 +68,3 @@ func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) ( Log: tx.TxResult.Log, }, nil } - -func encodeToStruct(b []byte) (*_struct.Struct, error) { - dataStruct := &_struct.Struct{} - if err := dataStruct.UnmarshalJSON(b); err != nil { - return nil, err - } - - return dataStruct, nil -} diff --git a/api/v2/service/transactions.go b/api/v2/service/transactions.go index 46fbebe56..2ebf787d1 100644 --- a/api/v2/service/transactions.go +++ b/api/v2/service/transactions.go @@ -10,6 +10,7 @@ import ( "google.golang.org/grpc/status" ) +// Return transactions by query. func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) (*pb.TransactionsResponse, error) { page := int(req.Page) if page == 0 { diff --git a/api/v2/service/unconfirmed_txs.go b/api/v2/service/unconfirmed_txs.go index 93d25d2c0..e99e515bb 100644 --- a/api/v2/service/unconfirmed_txs.go +++ b/api/v2/service/unconfirmed_txs.go @@ -8,6 +8,7 @@ import ( "google.golang.org/grpc/status" ) +// Returns unconfirmed transactions. func (s *Service) UnconfirmedTxs(ctx context.Context, req *pb.UnconfirmedTxsRequest) (*pb.UnconfirmedTxsResponse, error) { txs, err := s.client.UnconfirmedTxs(int(req.Limit)) if err != nil { diff --git a/api/v2/service/validators.go b/api/v2/service/validators.go index 1569d1748..50ba76092 100644 --- a/api/v2/service/validators.go +++ b/api/v2/service/validators.go @@ -9,6 +9,7 @@ import ( "google.golang.org/grpc/status" ) +// Returns list of active validators. func (s *Service) Validators(ctx context.Context, req *pb.ValidatorsRequest) (*pb.ValidatorsResponse, error) { height := int64(req.Height) if height == 0 { diff --git a/api/v2/service/waitlist.go b/api/v2/service/waitlist.go index 00da30e74..92a5564e5 100644 --- a/api/v2/service/waitlist.go +++ b/api/v2/service/waitlist.go @@ -10,6 +10,7 @@ import ( "strings" ) +// Returns the list of address stakes in waitlist. func (s *Service) WaitList(ctx context.Context, req *pb.WaitListRequest) (*pb.WaitListResponse, error) { if !strings.HasPrefix(strings.Title(req.Address), "Mx") { return new(pb.WaitListResponse), status.Error(codes.InvalidArgument, "invalid address") diff --git a/api/v2/service/ws.go b/api/v2/service/ws.go index 401ec0756..35aba1bc3 100644 --- a/api/v2/service/ws.go +++ b/api/v2/service/ws.go @@ -16,6 +16,7 @@ const ( SubscribeTimeout = 5 * time.Second ) +// Returns a subscription for events by query. func (s *Service) Subscribe(request *pb.SubscribeRequest, stream pb.ApiService_SubscribeServer) error { if s.client.NumClients() >= s.minterCfg.RPC.MaxSubscriptionClients { diff --git a/api/v2/v2.go b/api/v2/v2.go index 0d9c6faf5..7bfe88e8c 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -29,6 +29,7 @@ import ( "time" ) +// Start gRPC and API v2 func Run(srv *service.Service, addrGRPC, addrApi string, traceLog bool) error { lis, err := net.Listen("tcp", addrGRPC) if err != nil { @@ -135,20 +136,22 @@ func parseStatus(s *status.Status) (string, map[string]string) { codeString := strconv.Itoa(runtime.HTTPStatusFromCode(s.Code())) dataString := map[string]string{} details := s.Details() - if len(details) != 0 { - detail, ok := details[0].(*_struct.Struct) - if !ok { - return codeString, dataString - } + if len(details) == 0 { + return codeString, dataString + } - data := detail.AsMap() - for k, v := range data { - dataString[k] = fmt.Sprintf("%s", v) - } - code, ok := detail.GetFields()["code"] - if ok { - codeString = code.GetStringValue() - } + detail, ok := details[0].(*_struct.Struct) + if !ok { + return codeString, dataString + } + + data := detail.AsMap() + for k, v := range data { + dataString[k] = fmt.Sprintf("%s", v) + } + code, ok := detail.GetFields()["code"] + if ok { + codeString = code.GetStringValue() } return codeString, dataString } diff --git a/cli/cli_pb/manager.pb.go b/cli/cli_pb/manager.pb.go index 01b2f22a6..4e470927b 100644 --- a/cli/cli_pb/manager.pb.go +++ b/cli/cli_pb/manager.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.24.0 -// protoc v3.12.1 +// protoc-gen-go v1.25.0 +// protoc v3.13.0 // source: manager.proto package cli_pb @@ -799,10 +799,11 @@ type NetInfoResponse_Peer struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - NodeInfo *NodeInfo `protobuf:"bytes,4,opt,name=node_info,json=nodeInfo,proto3" json:"node_info,omitempty"` - IsOutbound bool `protobuf:"varint,1,opt,name=is_outbound,json=isOutbound,proto3" json:"is_outbound,omitempty"` - ConnectionStatus *NetInfoResponse_Peer_ConnectionStatus `protobuf:"bytes,2,opt,name=connection_status,json=connectionStatus,proto3" json:"connection_status,omitempty"` - RemoteIp string `protobuf:"bytes,3,opt,name=remote_ip,json=remoteIp,proto3" json:"remote_ip,omitempty"` + LatestBlockHeight int64 `protobuf:"varint,5,opt,name=latest_block_height,json=latestBlockHeight,proto3" json:"latest_block_height,omitempty"` + NodeInfo *NodeInfo `protobuf:"bytes,4,opt,name=node_info,json=nodeInfo,proto3" json:"node_info,omitempty"` + IsOutbound bool `protobuf:"varint,1,opt,name=is_outbound,json=isOutbound,proto3" json:"is_outbound,omitempty"` + ConnectionStatus *NetInfoResponse_Peer_ConnectionStatus `protobuf:"bytes,2,opt,name=connection_status,json=connectionStatus,proto3" json:"connection_status,omitempty"` + RemoteIp string `protobuf:"bytes,3,opt,name=remote_ip,json=remoteIp,proto3" json:"remote_ip,omitempty"` } func (x *NetInfoResponse_Peer) Reset() { @@ -837,6 +838,13 @@ func (*NetInfoResponse_Peer) Descriptor() ([]byte, []int) { return file_manager_proto_rawDescGZIP(), []int{1, 0} } +func (x *NetInfoResponse_Peer) GetLatestBlockHeight() int64 { + if x != nil { + return x.LatestBlockHeight + } + return 0 +} + func (x *NetInfoResponse_Peer) GetNodeInfo() *NodeInfo { if x != nil { return x.NodeInfo @@ -1193,7 +1201,7 @@ var file_manager_proto_rawDesc = []byte{ 0x0a, 0x08, 0x74, 0x78, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x78, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x70, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x72, 0x70, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xaa, 0x09, 0x0a, 0x0f, 0x4e, + 0x72, 0x70, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xda, 0x09, 0x0a, 0x0f, 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x1c, 0x0a, 0x09, @@ -1203,7 +1211,10 @@ var file_manager_proto_rawDesc = []byte{ 0x65, 0x72, 0x73, 0x12, 0x32, 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, - 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x1a, 0x8d, 0x08, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, + 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x1a, 0xbd, 0x08, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, + 0x12, 0x2e, 0x0a, 0x13, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6c, + 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2d, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, diff --git a/cli/cli_pb/manager.proto b/cli/cli_pb/manager.proto index 6c74ecd86..78bbbddb5 100644 --- a/cli/cli_pb/manager.proto +++ b/cli/cli_pb/manager.proto @@ -35,6 +35,7 @@ message NetInfoResponse { int64 n_peers = 2; message Peer { + int64 latest_block_height = 5; NodeInfo node_info = 4; diff --git a/cli/service/server_test.go b/cli/service/server_test.go index 2f4e47999..3086e3c2e 100644 --- a/cli/service/server_test.go +++ b/cli/service/server_test.go @@ -4,6 +4,7 @@ import ( "context" "github.com/MinterTeam/minter-go-node/config" "github.com/MinterTeam/minter-go-node/core/minter" + tmNode "github.com/tendermint/tendermint/node" rpc "github.com/tendermint/tendermint/rpc/client/local" "io/ioutil" "path/filepath" @@ -15,13 +16,14 @@ func TestStartCLIServer(t *testing.T) { var ( blockchain *minter.Blockchain tmRPC *rpc.Local + tmNode *tmNode.Node cfg *config.Config ) ctx, cancel := context.WithCancel(context.Background()) socketPath, _ := filepath.Abs(filepath.Join(".", "file.sock")) _ = ioutil.WriteFile(socketPath, []byte("address already in use"), 0644) go func() { - err := StartCLIServer(socketPath, NewManager(blockchain, tmRPC, cfg), ctx) + err := StartCLIServer(socketPath, NewManager(blockchain, tmRPC, tmNode, cfg), ctx) if err != nil { t.Log(err) } diff --git a/cli/service/service.go b/cli/service/service.go index ddcc0aa05..ebb586873 100644 --- a/cli/service/service.go +++ b/cli/service/service.go @@ -10,7 +10,10 @@ import ( "github.com/MinterTeam/minter-go-node/version" "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/empty" + "github.com/tendermint/tendermint/evidence" + tmNode "github.com/tendermint/tendermint/node" rpc "github.com/tendermint/tendermint/rpc/client/local" + types2 "github.com/tendermint/tendermint/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "runtime" @@ -20,11 +23,12 @@ import ( type Manager struct { blockchain *minter.Blockchain tmRPC *rpc.Local + tmNode *tmNode.Node cfg *config.Config } -func NewManager(blockchain *minter.Blockchain, tmRPC *rpc.Local, cfg *config.Config) pb.ManagerServiceServer { - return &Manager{blockchain: blockchain, tmRPC: tmRPC, cfg: cfg} +func NewManager(blockchain *minter.Blockchain, tmRPC *rpc.Local, tmNode *tmNode.Node, cfg *config.Config) pb.ManagerServiceServer { + return &Manager{blockchain: blockchain, tmRPC: tmRPC, tmNode: tmNode, cfg: cfg} } func (m *Manager) Dashboard(_ *empty.Empty, stream pb.ManagerService_DashboardServer) error { @@ -42,7 +46,11 @@ func (m *Manager) Dashboard(_ *empty.Empty, stream pb.ManagerService_DashboardSe averageTimeBlock := statisticData.GetAverageBlockProcessingTime() timePerBlock := statisticData.GetTimePerBlock() maxPeersHeight := m.blockchain.MaxPeerHeight() - maxPeersHeight = maxPeersHeight - 1 + if maxPeersHeight == 0 { + maxPeersHeight = info.Height + } else { + maxPeersHeight = maxPeersHeight - 1 + } protoTime, _ := ptypes.TimestampProto(info.HeaderTimestamp) var mem runtime.MemStats runtime.ReadMemStats(&mem) @@ -146,7 +154,10 @@ func (m *Manager) NetInfo(context.Context, *empty.Empty) (*pb.NetInfoResponse, e RecentlySent: channel.RecentlySent, }) } + peerTM := m.tmNode.Switch().Peers().Get(peer.NodeInfo.ID()) + currentHeight := peerTM.Get(types2.PeerStateKey).(evidence.PeerState).GetHeight() peers = append(peers, &pb.NetInfoResponse_Peer{ + LatestBlockHeight: currentHeight, NodeInfo: &pb.NodeInfo{ ProtocolVersion: &pb.NodeInfo_ProtocolVersion{ P2P: uint64(peer.NodeInfo.ProtocolVersion.P2P), diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index d1202dc57..67810ae9f 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -130,7 +130,7 @@ func runNode(cmd *cobra.Command) error { } go func() { - err := service.StartCLIServer(utils.GetMinterHome()+"/manager.sock", service.NewManager(app, client, cfg), cmd.Context()) + err := service.StartCLIServer(utils.GetMinterHome()+"/manager.sock", service.NewManager(app, client, node, cfg), cmd.Context()) if err != nil { panic(err) } diff --git a/go.mod b/go.mod index ce6f08e0d..da33f0196 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.13 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200904221942-ac3acb43c093 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200907121318-9d4f607d1405 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index dbcb71243..f15ad080c 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200904221942-ac3acb43c093 h1:cWbZIOVb2/Z4MbQN8V46ilAupkpH2G5WOdPFI2TR8q0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200904221942-ac3acb43c093/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200907121318-9d4f607d1405 h1:dWIaHK1Wk3xp720CA90ZfVI7n9YuHZvwNDWxOEbikUM= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200907121318-9d4f607d1405/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From bfd17f660cbf6cbb3ee4bf5fddc9ef9cebac0848 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 7 Sep 2020 16:17:30 +0300 Subject: [PATCH 221/426] add --testnet flag --- cmd/minter/cmd/node.go | 7 +++++++ cmd/minter/main.go | 1 + core/types/constants.go | 14 ++++++++++---- version/version.go | 2 +- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index 67810ae9f..2dffd57d5 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -10,6 +10,7 @@ import ( "github.com/MinterTeam/minter-go-node/config" "github.com/MinterTeam/minter-go-node/core/minter" "github.com/MinterTeam/minter-go-node/core/statistics" + minterTypes "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/log" "github.com/MinterTeam/minter-go-node/version" "github.com/spf13/cobra" @@ -64,6 +65,12 @@ func runNode(cmd *cobra.Command) error { } } + isTestnet, _ := cmd.Flags().GetBool("testnet") + if isTestnet { + minterTypes.CurrentChainID = minterTypes.ChainTestnet + version.Version += "-testnet" + } + pprofOn, err := cmd.Flags().GetBool("pprof") if err != nil { return err diff --git a/cmd/minter/main.go b/cmd/minter/main.go index fcae7166f..c22163dab 100644 --- a/cmd/minter/main.go +++ b/cmd/minter/main.go @@ -31,6 +31,7 @@ func main() { rootCmd.PersistentFlags().StringVar(&utils.MinterHome, "home-dir", "", "base dir (default is $HOME/.minter)") rootCmd.PersistentFlags().StringVar(&utils.MinterConfig, "config", "", "path to config (default is $(home-dir)/config/config.toml)") + rootCmd.PersistentFlags().Bool("testnet", false, "use \"true\" for testnet, mainnet is default") rootCmd.PersistentFlags().Bool("pprof", false, "enable pprof") rootCmd.PersistentFlags().String("pprof-addr", "0.0.0.0:6060", "pprof listen addr") diff --git a/core/types/constants.go b/core/types/constants.go index 5f8dbc997..e4272bd87 100644 --- a/core/types/constants.go +++ b/core/types/constants.go @@ -1,23 +1,29 @@ package types +// ChainID is ID of the network (1 - mainnet, 2 - testnet) type ChainID byte const ( - ChainTestnet = 0x02 - ChainMainnet = 0x01 - - CurrentChainID = ChainTestnet + // ChainMainnet is mainnet chain ID of the network + ChainMainnet ChainID = 0x01 + // ChainTestnet is mainnet chain ID of the network + ChainTestnet ChainID = 0x02 ) +// CurrentChainID is current ChainID of the network +var CurrentChainID = ChainMainnet + var ( coinTestnet = StrToCoinSymbol("MNT") coinMainnet = StrToCoinSymbol("BIP") ) +// GetBaseCoin returns the coin symbol of the current ChainID func GetBaseCoin() CoinSymbol { return getBaseCoin(CurrentChainID) } +// GetBaseCoinID returns ID of base coin func GetBaseCoinID() CoinID { return BasecoinID } diff --git a/version/version.go b/version/version.go index 65e0e51b7..ae573008b 100755 --- a/version/version.go +++ b/version/version.go @@ -11,7 +11,7 @@ const ( var ( // Must be a string because scripts like dist.sh read this file. - Version = "1.2.0-testnet" + Version = "1.2.0" // GitCommit is the current HEAD set using ldflags. GitCommit string From 29029b8d9d83db992d908f07d47f27a0e878a05e Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 8 Sep 2020 12:09:42 +0300 Subject: [PATCH 222/426] tests for buy coin tx --- core/transaction/buy_coin_test.go | 263 +++++++++++++++++++++++++++++- 1 file changed, 256 insertions(+), 7 deletions(-) diff --git a/core/transaction/buy_coin_test.go b/core/transaction/buy_coin_test.go index 91a5cf10b..bd8eeced4 100644 --- a/core/transaction/buy_coin_test.go +++ b/core/transaction/buy_coin_test.go @@ -2,6 +2,13 @@ package transaction import ( "crypto/ecdsa" + "log" + "math/big" + "math/rand" + "sync" + "testing" + "time" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" @@ -10,13 +17,7 @@ import ( "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/rlp" "github.com/tendermint/go-amino" - "github.com/tendermint/tm-db" - "log" - "math/big" - "math/rand" - "sync" - "testing" - "time" + db "github.com/tendermint/tm-db" ) var ( @@ -1060,6 +1061,254 @@ func TestBuyCoinTxCustomToCustomCustom2Commission(t *testing.T) { } } +func TestBuyCoinTxToCoinSupplyOverflow(t *testing.T) { + cState := getState() + privateKey, addr := getAccount() + coinToBuyID, sellCoinID := createTestCoin(cState), types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, sellCoinID, helpers.BipToPip(big.NewInt(5000000))) + + tx := createBuyCoinTx(sellCoinID, coinToBuyID, sellCoinID, helpers.BipToPip(big.NewInt(1000001)), 1) + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinSupplyOverflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinSupplyOverflow, response.Log) + } +} + +func TestBuyCoinTxToMaximumValueToSellReached(t *testing.T) { + cState := getState() + privateKey, addr := getAccount() + coinToBuyID, sellCoinID := createTestCoin(cState), types.GetBaseCoinID() + + valueToSell := big.NewInt(2e18) + cState.Accounts.AddBalance(addr, sellCoinID, valueToSell) + + data := BuyCoinData{ + CoinToBuy: coinToBuyID, + ValueToBuy: valueToSell, + CoinToSell: sellCoinID, + MaximumValueToSell: big.NewInt(1e18), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + panic(err) + } + + tx := &Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: sellCoinID, + Type: TypeBuyCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + decodedData: data, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.MaximumValueToSellReached { + t.Fatalf("Response code is not %d. Error %s", code.MaximumValueToSellReached, response.Log) + } + + cState.Accounts.AddBalance(addr, coinToBuyID, helpers.BipToPip(big.NewInt(100000))) + + data.CoinToBuy = sellCoinID + data.CoinToSell = coinToBuyID + data.MaximumValueToSell = big.NewInt(1) + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + panic(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.MaximumValueToSellReached { + t.Fatalf("Response code is not %d. Error %s", code.MaximumValueToSellReached, response.Log) + } + + cState.Coins.Create( + cState.App.GetNextCoinID(), + types.StrToCoinSymbol("TEST9"), + "TEST COIN", + helpers.BipToPip(big.NewInt(100000)), + 10, + helpers.BipToPip(big.NewInt(100000)), + helpers.BipToPip(big.NewInt(1000000)), + nil, + ) + + coinToSellID := cState.App.GetNextCoinID() + cState.App.SetCoinsCount(coinToSellID.Uint32()) + + data.CoinToBuy = coinToBuyID + data.CoinToSell = coinToSellID + data.MaximumValueToSell = big.NewInt(1) + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + panic(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.MaximumValueToSellReached { + t.Fatalf("Response code is not %d. Error %s", code.MaximumValueToSellReached, response.Log) + } + + data.MaximumValueToSell = big.NewInt(2000360064812986923) + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + panic(err) + } + + tx.Data = encodedData + tx.GasCoin = data.CoinToSell + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.MaximumValueToSellReached { + t.Fatalf("Response code is not %d. Error %s", code.MaximumValueToSellReached, response.Log) + } +} + +func TestBuyCoinTxToCoinReserveNotSufficient(t *testing.T) { + cState := getState() + privateKey, addr := getAccount() + coinToBuyID := createTestCoin(cState) + + cState.Coins.Create( + cState.App.GetNextCoinID(), + types.StrToCoinSymbol("TEST9"), + "TEST COIN", + helpers.BipToPip(big.NewInt(100000)), + 10, + helpers.BipToPip(big.NewInt(100000)), + helpers.BipToPip(big.NewInt(1000000)), + nil, + ) + + coinToSellID := cState.App.GetNextCoinID() + cState.App.SetCoinsCount(coinToSellID.Uint32()) + + cState.Accounts.AddBalance(addr, coinToSellID, helpers.BipToPip(big.NewInt(5000000))) + + tx := createBuyCoinTx(coinToSellID, coinToBuyID, coinToBuyID, helpers.BipToPip(big.NewInt(10000)), 1) + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveNotSufficient { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveNotSufficient, response.Log) + } + + // gas coin == coin to buy + + cState.Coins.SubReserve(tx.GasCoin, helpers.BipToPip(big.NewInt(100000))) + + tx = createBuyCoinTx(coinToSellID, coinToBuyID, coinToBuyID, helpers.BipToPip(big.NewInt(1)), 1) + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveNotSufficient { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveNotSufficient, response.Log) + } + + // gas coin == coin to sell + + cState.Coins.AddReserve(coinToBuyID, helpers.BipToPip(big.NewInt(11))) + cState.Coins.SubReserve(coinToBuyID, big.NewInt(9e17)) + + tx = createBuyCoinTx(coinToBuyID, coinToSellID, coinToBuyID, helpers.BipToPip(big.NewInt(1)), 1) + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveNotSufficient { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveNotSufficient, response.Log) + } + + // gas coin == coin to buy + // sell coin == base coin + + tx = createBuyCoinTx(types.GetBaseCoinID(), coinToBuyID, coinToBuyID, big.NewInt(1), 1) + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + tx.GasPrice = 5000 + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveNotSufficient { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveNotSufficient, response.Log) + } +} + func createBuyCoinTx(sellCoin, buyCoin, gasCoin types.CoinID, valueToBuy *big.Int, nonce uint64) *Transaction { maxValToSell, _ := big.NewInt(0).SetString("100000000000000000000000000000", 10) data := BuyCoinData{ From 0d84dac7b058b8055b239cf444ea1e0ded53fd63 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 8 Sep 2020 13:18:15 +0300 Subject: [PATCH 223/426] tests for sell coin tx --- core/transaction/buy_coin_test.go | 6 +- core/transaction/sell_coin_test.go | 334 ++++++++++++++++++++++++++++- 2 files changed, 334 insertions(+), 6 deletions(-) diff --git a/core/transaction/buy_coin_test.go b/core/transaction/buy_coin_test.go index bd8eeced4..0d0922be0 100644 --- a/core/transaction/buy_coin_test.go +++ b/core/transaction/buy_coin_test.go @@ -1089,12 +1089,12 @@ func TestBuyCoinTxToMaximumValueToSellReached(t *testing.T) { privateKey, addr := getAccount() coinToBuyID, sellCoinID := createTestCoin(cState), types.GetBaseCoinID() - valueToSell := big.NewInt(2e18) - cState.Accounts.AddBalance(addr, sellCoinID, valueToSell) + valueToBuy := big.NewInt(2e18) + cState.Accounts.AddBalance(addr, sellCoinID, valueToBuy) data := BuyCoinData{ CoinToBuy: coinToBuyID, - ValueToBuy: valueToSell, + ValueToBuy: valueToBuy, CoinToSell: sellCoinID, MaximumValueToSell: big.NewInt(1e18), } diff --git a/core/transaction/sell_coin_test.go b/core/transaction/sell_coin_test.go index 922e9e377..0df5e019e 100644 --- a/core/transaction/sell_coin_test.go +++ b/core/transaction/sell_coin_test.go @@ -1,15 +1,16 @@ package transaction import ( + "math/big" + "sync" + "testing" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/formula" "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/rlp" - "math/big" - "sync" - "testing" ) func TestSellCoinTx(t *testing.T) { @@ -610,6 +611,333 @@ func TestSellCoinTxCustomToCustomCustom2Commission(t *testing.T) { } } +func TestSellCoinTxToCoinSupplyOverflow(t *testing.T) { + cState := getState() + privateKey, addr := getAccount() + coinToBuyID, sellCoinID := createTestCoin(cState), types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, sellCoinID, helpers.BipToPip(big.NewInt(100))) + + coinToBuy := cState.Coins.GetCoin(coinToBuyID) + coinToBuy.CMaxSupply = big.NewInt(1) + + tx := createSellCoinTx(sellCoinID, coinToBuyID, sellCoinID, helpers.BipToPip(big.NewInt(90)), 1) + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinSupplyOverflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinSupplyOverflow, response.Log) + } + + // custom buy and sell coins + + cState.Coins.Create( + cState.App.GetNextCoinID(), + types.StrToCoinSymbol("TEST9"), + "TEST COIN", + helpers.BipToPip(big.NewInt(100000)), + 10, + helpers.BipToPip(big.NewInt(100000)), + helpers.BipToPip(big.NewInt(1000000)), + nil, + ) + + coinToSellID := cState.App.GetNextCoinID() + cState.App.SetCoinsCount(coinToSellID.Uint32()) + + tx = createSellCoinTx(coinToSellID, coinToBuyID, coinToSellID, helpers.BipToPip(big.NewInt(90)), 1) + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinSupplyOverflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinSupplyOverflow, response.Log) + } +} + +func TestSellCoinTxToMinimumValueToBuyReached(t *testing.T) { + cState := getState() + privateKey, addr := getAccount() + coinToBuyID, sellCoinID := createTestCoin(cState), types.GetBaseCoinID() + + valueToSell := big.NewInt(2e18) + cState.Accounts.AddBalance(addr, sellCoinID, helpers.BipToPip(big.NewInt(2))) + + data := SellCoinData{ + CoinToBuy: coinToBuyID, + ValueToSell: valueToSell, + CoinToSell: sellCoinID, + MinimumValueToBuy: big.NewInt(9e18), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + panic(err) + } + + tx := &Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: sellCoinID, + Type: TypeSellCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + decodedData: data, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.MinimumValueToBuyReached { + t.Fatalf("Response code is not %d. Error %s", code.MinimumValueToBuyReached, response.Log) + } + + // coin to buy == base coin + + cState.Accounts.AddBalance(addr, coinToBuyID, helpers.BipToPip(big.NewInt(100000))) + + data.CoinToBuy = sellCoinID + data.CoinToSell = coinToBuyID + data.MinimumValueToBuy = big.NewInt(9e18) + data.ValueToSell = big.NewInt(1) + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + panic(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.MinimumValueToBuyReached { + t.Fatalf("Response code is not %d. Error %s", code.MinimumValueToBuyReached, response.Log) + } + + // custom buy and sell coins + + cState.Coins.Create( + cState.App.GetNextCoinID(), + types.StrToCoinSymbol("TEST9"), + "TEST COIN", + helpers.BipToPip(big.NewInt(100000)), + 10, + helpers.BipToPip(big.NewInt(100000)), + helpers.BipToPip(big.NewInt(1000000)), + nil, + ) + + coinToSellID := cState.App.GetNextCoinID() + cState.App.SetCoinsCount(coinToSellID.Uint32()) + + data.CoinToBuy = coinToBuyID + data.CoinToSell = coinToSellID + data.MinimumValueToBuy = big.NewInt(9e18) + data.ValueToSell = big.NewInt(1) + + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + panic(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.MinimumValueToBuyReached { + t.Fatalf("Response code is not %d. Error %s", code.MinimumValueToBuyReached, response.Log) + } +} + +func TestSellCoinTxToCoinReserveNotSufficient(t *testing.T) { + cState := getState() + privateKey, addr := getAccount() + coinToBuyID, coinToSellID := createTestCoin(cState), types.GetBaseCoinID() + + cState.Coins.Create( + cState.App.GetNextCoinID(), + types.StrToCoinSymbol("TEST9"), + "TEST COIN", + helpers.BipToPip(big.NewInt(100000)), + 10, + helpers.BipToPip(big.NewInt(100000)), + helpers.BipToPip(big.NewInt(1000000)), + nil, + ) + + customCoinToSellID := cState.App.GetNextCoinID() + cState.App.SetCoinsCount(customCoinToSellID.Uint32()) + + cState.Accounts.AddBalance(addr, coinToSellID, helpers.BipToPip(big.NewInt(5000000))) + + tx := createSellCoinTx(coinToBuyID, coinToSellID, coinToBuyID, helpers.BipToPip(big.NewInt(100000)), 1) + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveNotSufficient { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveNotSufficient, response.Log) + } + + // gas coin == coin to sell + + cState.Coins.SubReserve(coinToBuyID, helpers.BipToPip(big.NewInt(100000))) + + tx = createSellCoinTx(coinToBuyID, customCoinToSellID, coinToBuyID, helpers.BipToPip(big.NewInt(1)), 1) + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveNotSufficient { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveNotSufficient, response.Log) + } +} + +func TestSellCoinTxInsufficientFunds(t *testing.T) { + cState := getState() + + coinToBuyID, coinToSellID := createTestCoin(cState), types.GetBaseCoinID() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1))) + + tx := createSellCoinTx(coinToSellID, coinToBuyID, coinToSellID, helpers.BipToPip(big.NewInt(1000)), 1) + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} + +func TestSellCoinTxEqualCoins(t *testing.T) { + cState := getState() + coinID := createTestCoin(cState) + privateKey, _ := crypto.GenerateKey() + + tx := createSellCoinTx(coinID, coinID, coinID, big.NewInt(1), 1) + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CrossConvert { + t.Fatalf("Response code is not %d. Error %s", code.CrossConvert, response.Log) + } +} + +func TestSellCoinTxToNonExistenCoins(t *testing.T) { + cState := getState() + coinID := createTestCoin(cState) + privateKey, _ := crypto.GenerateKey() + + tx := createSellCoinTx(5, coinID, coinID, big.NewInt(1), 1) + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinNotExists { + t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) + } + + tx = createSellCoinTx(coinID, 5, coinID, big.NewInt(1), 1) + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinNotExists { + t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) + } + + tx = createSellCoinTx(coinID, types.GetBaseCoinID(), 5, big.NewInt(1), 1) + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinNotExists { + t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) + } +} + func createSellCoinTx(sellCoin, buyCoin, gasCoin types.CoinID, valueToSell *big.Int, nonce uint64) *Transaction { data := SellCoinData{ CoinToSell: sellCoin, From fe2675decfdf0eb4e0dbdb95bfa0c4b73505eed5 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 8 Sep 2020 14:04:27 +0300 Subject: [PATCH 224/426] refactor and tests --- api/api.go | 7 +- api/estimate_coin_buy.go | 54 +- api/estimate_coin_sell.go | 51 +- api/estimate_coin_sell_all.go | 39 +- api/v2/service/waitlist.go | 2 +- api/waitlist.go | 2 +- core/state/candidates/candidate_test.go | 845 ++++++++++++++++++++++++ core/state/candidates/candidates.go | 17 +- core/state/candidates/coins_cache.go | 46 ++ core/state/candidates/model.go | 40 -- core/state/coins/coins.go | 6 +- core/state/state.go | 11 +- core/state/waitlist/waitlist.go | 21 + core/transaction/redeem_check_test.go | 2 +- core/transaction/unbond.go | 2 +- core/types/appstate.go | 8 + 16 files changed, 1020 insertions(+), 133 deletions(-) create mode 100644 core/state/candidates/candidate_test.go create mode 100644 core/state/candidates/coins_cache.go diff --git a/api/api.go b/api/api.go index aff3d8481..66e58fa03 100644 --- a/api/api.go +++ b/api/api.go @@ -44,9 +44,9 @@ var Routes = map[string]*rpcserver.RPCFunc{ "events": rpcserver.NewRPCFunc(Events, "height"), "net_info": rpcserver.NewRPCFunc(NetInfo, ""), "coin_info": rpcserver.NewRPCFunc(CoinInfo, "symbol,id,height"), - "estimate_coin_sell": rpcserver.NewRPCFunc(EstimateCoinSell, "coin_id_to_sell,coin_id_to_buy,value_to_sell,height"), - "estimate_coin_sell_all": rpcserver.NewRPCFunc(EstimateCoinSellAll, "coin_id_to_sell,coin_id_to_buy,value_to_sell,gas_price,height"), - "estimate_coin_buy": rpcserver.NewRPCFunc(EstimateCoinBuy, "coin_id_to_sell,coin_id_to_buy,value_to_buy,height"), + "estimate_coin_sell": rpcserver.NewRPCFunc(EstimateCoinSell, "coin_to_sell,coin_to_buy,value_to_sell,height"), + "estimate_coin_sell_all": rpcserver.NewRPCFunc(EstimateCoinSellAll, "coin_to_sell,coin_to_buy,value_to_sell,gas_price,height"), + "estimate_coin_buy": rpcserver.NewRPCFunc(EstimateCoinBuy, "coin_to_sell,coin_to_buy,value_to_buy,height"), "estimate_tx_commission": rpcserver.NewRPCFunc(EstimateTxCommission, "tx,height"), "unconfirmed_txs": rpcserver.NewRPCFunc(UnconfirmedTxs, "limit"), "max_gas": rpcserver.NewRPCFunc(MaxGas, "height"), @@ -66,6 +66,7 @@ func responseTime(b *minter.Blockchain) func(f func(http.ResponseWriter, *http.R } } +// RunAPI start func RunAPI(b *minter.Blockchain, tmRPC *rpc.Local, cfg *config.Config, logger log.Logger) { minterCfg = cfg diff --git a/api/estimate_coin_buy.go b/api/estimate_coin_buy.go index 4e244ba78..9440d4348 100644 --- a/api/estimate_coin_buy.go +++ b/api/estimate_coin_buy.go @@ -10,12 +10,14 @@ import ( "math/big" ) +// EstimateCoinBuyResponse is estimate of buy coin transaction type EstimateCoinBuyResponse struct { WillPay string `json:"will_pay"` Commission string `json:"commission"` } -func EstimateCoinBuy(coinIdToSell uint64, coinIdToBuy uint64, valueToBuy *big.Int, height int) (*EstimateCoinBuyResponse, error) { +// EstimateCoinBuy returns is estimate of buy coin transaction +func EstimateCoinBuy(coinToSell, coinToBuy string, valueToBuy *big.Int, height int) (*EstimateCoinBuyResponse, error) { cState, err := GetStateForHeight(height) if err != nil { return nil, err @@ -24,56 +26,46 @@ func EstimateCoinBuy(coinIdToSell uint64, coinIdToBuy uint64, valueToBuy *big.In cState.RLock() defer cState.RUnlock() - sellCoinID := types.CoinID(coinIdToSell) - buyCoinID := types.CoinID(coinIdToBuy) - - var result *big.Int - - if sellCoinID == buyCoinID { - return nil, rpctypes.RPCError{Code: 400, Message: "\"From\" coin equals to \"to\" coin"} - } - - if !cState.Coins().Exists(sellCoinID) { + coinFrom := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToSell), 0) + if coinFrom == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to sell not exists"} } - if !cState.Coins().Exists(buyCoinID) { + coinTo := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToBuy), 0) + if coinTo == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to buy not exists"} } + if coinFrom.ID() == coinTo.ID() { + return nil, rpctypes.RPCError{Code: 400, Message: "\"From\" coin equals to \"to\" coin"} + } + commissionInBaseCoin := big.NewInt(commissions.ConvertTx) commissionInBaseCoin.Mul(commissionInBaseCoin, transaction.CommissionMultiplier) commission := big.NewInt(0).Set(commissionInBaseCoin) - if !sellCoinID.IsBaseCoin() { - coin := cState.Coins().GetCoin(sellCoinID) - - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { + if !coinFrom.ID().IsBaseCoin() { + if coinFrom.Reserve().Cmp(commissionInBaseCoin) < 0 { return nil, rpctypes.RPCError{Code: 400, Message: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", - coin.Reserve().String(), commissionInBaseCoin.String())} + coinFrom.Reserve().String(), commissionInBaseCoin.String())} } - - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + commission = formula.CalculateSaleAmount(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), commissionInBaseCoin) } - switch { - case sellCoinID.IsBaseCoin(): - coin := cState.Coins().GetCoin(buyCoinID) - result = formula.CalculatePurchaseAmount(coin.Volume(), coin.Reserve(), coin.Crr(), valueToBuy) - case buyCoinID.IsBaseCoin(): - coin := cState.Coins().GetCoin(sellCoinID) + var result *big.Int - if coin.Reserve().Cmp(valueToBuy) < 0 { + switch { + case coinTo.ID().IsBaseCoin(): + result = formula.CalculatePurchaseAmount(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), valueToBuy) + case coinFrom.ID().IsBaseCoin(): + if coinFrom.Reserve().Cmp(valueToBuy) < 0 { return nil, rpctypes.RPCError{Code: 400, Message: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", - coin.Reserve().String(), valueToBuy.String())} + coinFrom.Reserve().String(), valueToBuy.String())} } - result = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), valueToBuy) + result = formula.CalculateSaleAmount(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToBuy) default: - coinFrom := cState.Coins().GetCoin(sellCoinID) - coinTo := cState.Coins().GetCoin(buyCoinID) baseCoinNeeded := formula.CalculatePurchaseAmount(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), valueToBuy) - if coinFrom.Reserve().Cmp(baseCoinNeeded) < 0 { return nil, rpctypes.RPCError{Code: 400, Message: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coinFrom.Reserve().String(), baseCoinNeeded.String())} diff --git a/api/estimate_coin_sell.go b/api/estimate_coin_sell.go index eaf73cbbd..b5d298c48 100644 --- a/api/estimate_coin_sell.go +++ b/api/estimate_coin_sell.go @@ -10,12 +10,14 @@ import ( "math/big" ) +// EstimateCoinSellResponse is estimate of sell coin transaction type EstimateCoinSellResponse struct { WillGet string `json:"will_get"` Commission string `json:"commission"` } -func EstimateCoinSell(coinIdToSell uint64, coinIdToBuy uint64, valueToSell *big.Int, height int) (*EstimateCoinSellResponse, error) { +// EstimateCoinSell returns estimate of sell coin transaction +func EstimateCoinSell(coinToSell, coinToBuy string, valueToSell *big.Int, height int) (*EstimateCoinSellResponse, error) { cState, err := GetStateForHeight(height) if err != nil { return nil, err @@ -24,53 +26,46 @@ func EstimateCoinSell(coinIdToSell uint64, coinIdToBuy uint64, valueToSell *big. cState.RLock() defer cState.RUnlock() - sellCoinID := types.CoinID(coinIdToSell) - buyCoinID := types.CoinID(coinIdToBuy) - - var result *big.Int - - if sellCoinID == buyCoinID { - return nil, rpctypes.RPCError{Code: 400, Message: "\"From\" coin equals to \"to\" coin"} - } - - if !cState.Coins().Exists(sellCoinID) { + coinFrom := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToSell), 0) + if coinFrom == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to sell not exists"} } - if !cState.Coins().Exists(buyCoinID) { + coinTo := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToBuy), 0) + if coinTo == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to buy not exists"} } + if coinFrom.ID() == coinTo.ID() { + return nil, rpctypes.RPCError{Code: 400, Message: "\"From\" coin equals to \"to\" coin"} + } + + var result *big.Int + commissionInBaseCoin := big.NewInt(commissions.ConvertTx) commissionInBaseCoin.Mul(commissionInBaseCoin, transaction.CommissionMultiplier) commission := big.NewInt(0).Set(commissionInBaseCoin) - if !sellCoinID.IsBaseCoin() { - coin := cState.Coins().GetCoin(sellCoinID) - - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { + if !coinFrom.ID().IsBaseCoin() { + if coinFrom.Reserve().Cmp(commissionInBaseCoin) < 0 { return nil, rpctypes.RPCError{Code: 400, Message: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", - coin.Reserve().String(), commissionInBaseCoin.String())} + coinFrom.Reserve().String(), commissionInBaseCoin.String())} } - if coin.Volume().Cmp(valueToSell) < 0 { + if coinFrom.Volume().Cmp(valueToSell) < 0 { return nil, rpctypes.RPCError{Code: 400, Message: fmt.Sprintf("Coin volume is not sufficient for transaction. Has: %s, required %s", - coin.Volume().String(), valueToSell.String())} + coinFrom.Volume().String(), valueToSell.String())} } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + commission = formula.CalculateSaleAmount(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), commissionInBaseCoin) } switch { - case sellCoinID.IsBaseCoin(): - coin := cState.Coins().GetCoin(buyCoinID) - result = formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) - case buyCoinID.IsBaseCoin(): - coin := cState.Coins().GetCoin(sellCoinID) - result = formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) + case coinFrom.ID().IsBaseCoin(): + result = formula.CalculatePurchaseReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) + case coinTo.ID().IsBaseCoin(): + result = formula.CalculateSaleReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), valueToSell) default: - coinFrom := cState.Coins().GetCoin(sellCoinID) - coinTo := cState.Coins().GetCoin(buyCoinID) basecoinValue := formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) result = formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), basecoinValue) } diff --git a/api/estimate_coin_sell_all.go b/api/estimate_coin_sell_all.go index 892c07668..03f0ff443 100644 --- a/api/estimate_coin_sell_all.go +++ b/api/estimate_coin_sell_all.go @@ -9,11 +9,13 @@ import ( "math/big" ) +// EstimateCoinSellAllResponse is estimate of sell all coin transaction type EstimateCoinSellAllResponse struct { WillGet string `json:"will_get"` } -func EstimateCoinSellAll(coinIdToSell uint64, coinIdToBuy uint64, valueToSell *big.Int, gasPrice uint64, height int) (*EstimateCoinSellAllResponse, +// EstimateCoinSellAll returns estimate of sell all coin transaction +func EstimateCoinSellAll(coinToSell, coinToBuy string, valueToSell *big.Int, gasPrice uint64, height int) (*EstimateCoinSellAllResponse, error) { cState, err := GetStateForHeight(height) if err != nil { @@ -27,50 +29,43 @@ func EstimateCoinSellAll(coinIdToSell uint64, coinIdToBuy uint64, valueToSell *b gasPrice = 1 } - sellCoinID := types.CoinID(coinIdToSell) - buyCoinID := types.CoinID(coinIdToBuy) - - var result *big.Int - - if sellCoinID == buyCoinID { - return nil, rpctypes.RPCError{Code: 400, Message: "\"From\" coin equals to \"to\" coin"} - } - - if !cState.Coins().Exists(sellCoinID) { + coinFrom := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToSell), 0) + if coinFrom == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to sell not exists"} } - if !cState.Coins().Exists(buyCoinID) { + coinTo := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToBuy), 0) + if coinTo == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to buy not exists"} } + if coinFrom.ID() == coinTo.ID() { + return nil, rpctypes.RPCError{Code: 400, Message: "\"From\" coin equals to \"to\" coin"} + } + commissionInBaseCoin := big.NewInt(commissions.ConvertTx) commissionInBaseCoin.Mul(commissionInBaseCoin, transaction.CommissionMultiplier) commission := big.NewInt(0).Set(commissionInBaseCoin) - switch { - case sellCoinID.IsBaseCoin(): - coin := cState.Coins().GetCoin(buyCoinID) + var result *big.Int + switch { + case coinFrom.ID().IsBaseCoin(): valueToSell.Sub(valueToSell, commission) if valueToSell.Cmp(big.NewInt(0)) != 1 { return nil, rpctypes.RPCError{Code: 400, Message: "Not enough coins to pay commission"} } - result = formula.CalculatePurchaseReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) - case buyCoinID.IsBaseCoin(): - coin := cState.Coins().GetCoin(sellCoinID) - result = formula.CalculateSaleReturn(coin.Volume(), coin.Reserve(), coin.Crr(), valueToSell) + result = formula.CalculatePurchaseReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) + case coinTo.ID().IsBaseCoin(): + result = formula.CalculateSaleReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), valueToSell) result.Sub(result, commission) if result.Cmp(big.NewInt(0)) != 1 { return nil, rpctypes.RPCError{Code: 400, Message: "Not enough coins to pay commission"} } default: - coinFrom := cState.Coins().GetCoin(sellCoinID) - coinTo := cState.Coins().GetCoin(buyCoinID) basecoinValue := formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) - basecoinValue.Sub(basecoinValue, commission) if basecoinValue.Cmp(big.NewInt(0)) != 1 { return nil, rpctypes.RPCError{Code: 400, Message: "Not enough coins to pay commission"} diff --git a/api/v2/service/waitlist.go b/api/v2/service/waitlist.go index 92a5564e5..19be0acec 100644 --- a/api/v2/service/waitlist.go +++ b/api/v2/service/waitlist.go @@ -42,7 +42,7 @@ func (s *Service) WaitList(ctx context.Context, req *pb.WaitListRequest) (*pb.Wa } response := new(pb.WaitListResponse) - items := cState.Watchlist().GetByAddressAndPubKey(address, publickKey) + items := cState.WaitList().GetByAddressAndPubKey(address, publickKey) response.List = make([]*pb.WaitListResponse_Wait, 0, len(items)) for _, item := range items { if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { diff --git a/api/waitlist.go b/api/waitlist.go index 6e9f492d9..d89bdc0a4 100644 --- a/api/waitlist.go +++ b/api/waitlist.go @@ -23,7 +23,7 @@ func Waitlist(pubkey types.Pubkey, address types.Address, height int) (*Waitlist defer cState.RUnlock() response := new(WaitlistResponse) - items := cState.Watchlist().GetByAddressAndPubKey(address, pubkey) + items := cState.WaitList().GetByAddressAndPubKey(address, pubkey) response.List = make([]*Wait, 0, len(items)) for _, item := range items { response.List = append(response.List, &Wait{ diff --git a/core/state/candidates/candidate_test.go b/core/state/candidates/candidate_test.go new file mode 100644 index 000000000..1eb3f9b76 --- /dev/null +++ b/core/state/candidates/candidate_test.go @@ -0,0 +1,845 @@ +package candidates + +import ( + "encoding/json" + "fmt" + eventsdb "github.com/MinterTeam/minter-go-node/core/events" + "github.com/MinterTeam/minter-go-node/core/state/accounts" + "github.com/MinterTeam/minter-go-node/core/state/bus" + "github.com/MinterTeam/minter-go-node/core/state/checker" + "github.com/MinterTeam/minter-go-node/core/state/coins" + "github.com/MinterTeam/minter-go-node/core/state/waitlist" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/helpers" + "github.com/MinterTeam/minter-go-node/tree" + db "github.com/tendermint/tm-db" + "math/big" + "strconv" + "testing" +) + +func TestCandidates_Commit_createOneCandidate(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + candidates, err := NewCandidates(bus.NewBus(), mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err := mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 1 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "FCF3853839873D3EC344016C04A5E75166F51063745670DF5D561C060E7F45A1" { + t.Fatalf("hash %X", hash) + } + + if !candidates.Exists([32]byte{4}) { + t.Fatal("candidate not found by pub_key") + } +} + +func TestCandidates_Commit_createThreeCandidates(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + candidates, err := NewCandidates(bus.NewBus(), mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + candidates.Create([20]byte{11}, [20]byte{21}, [20]byte{31}, [32]byte{41}, 10) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err := mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 1 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "D7A17D41EAE39D61D3F85BC3311DA1FE306E885FF03024D0173F23E3739E719B" { + t.Fatalf("hash %X", hash) + } + + candidates.Create([20]byte{1, 1}, [20]byte{2, 2}, [20]byte{3, 3}, [32]byte{4, 4}, 10) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 2 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "01E34A08A0CF18403B8C3708FA773A4D0B152635F321085CE7B68F04FD520A9A" { + t.Fatalf("hash %X", hash) + } +} + +func TestCandidates_Commit_changePubKeyAndCheckBlockList(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + candidates, err := NewCandidates(bus.NewBus(), mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + candidates.Create([20]byte{11}, [20]byte{21}, [20]byte{31}, [32]byte{41}, 10) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err := mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 1 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "D7A17D41EAE39D61D3F85BC3311DA1FE306E885FF03024D0173F23E3739E719B" { + t.Fatalf("hash %X", hash) + } + + candidates.ChangePubKey([32]byte{4}, [32]byte{5}) + candidates.ChangePubKey([32]byte{41}, [32]byte{6}) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 2 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "C0DC396CF17399CF3E05EAFFD29D94A99698633C9160D46C469D5F6575DC66E0" { + t.Fatalf("hash %X", hash) + } + + if !candidates.IsBlockedPubKey([32]byte{4}) { + t.Fatal("pub_key is not blocked") + } +} +func TestCandidates_Commit_addBlockList(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + candidates, err := NewCandidates(bus.NewBus(), mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.AddToBlockPubKey([32]byte{4}) + + if !candidates.IsBlockedPubKey([32]byte{4}) { + t.Fatal("pub_key is not blocked") + } +} + +func TestCandidates_Commit_withStakeAndUpdate(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + candidates, err := NewCandidates(bus.NewBus(), mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err := mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 1 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "FCF3853839873D3EC344016C04A5E75166F51063745670DF5D561C060E7F45A1" { + t.Fatalf("hash %X", hash) + } + + candidates.SetStakes([32]byte{4}, []types.Stake{ + { + Owner: [20]byte{1}, + Coin: 0, + Value: "100", + BipValue: "100", + }, + }, []types.Stake{ + { + Owner: [20]byte{2}, + Coin: 0, + Value: "100", + BipValue: "100", + }, + }) + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 2 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "2D206158AA79C3BDAA019C61FEAD47BB9B6170C445EE7B36E935AC954765E99F" { + t.Fatalf("hash %X", hash) + } +} + +func TestCandidates_Commit_withStakesMoreMaxDelegatorsPerCandidate(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + candidates, err := NewCandidates(bus.NewBus(), mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err := mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 1 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "FCF3853839873D3EC344016C04A5E75166F51063745670DF5D561C060E7F45A1" { + t.Fatalf("hash %X", hash) + } + + var stakes []types.Stake + for i := 0; i < 1010; i++ { + value := strconv.Itoa(i + 2000) + stakes = append(stakes, types.Stake{ + Owner: types.StringToAddress(strconv.Itoa(i)), + Coin: 0, + Value: value, + BipValue: value, + }) + } + candidates.SetStakes([32]byte{4}, stakes, []types.Stake{ + { + Owner: [20]byte{2}, + Coin: 0, + Value: "100", + BipValue: "100", + }, + }) + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 2 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "51022ED08FD976D0305B3BD8CB90C0139CDC4970CD9548237DF358ECD54BA6D1" { + t.Fatalf("hash %X", hash) + } +} + +func TestCandidates_Commit_edit(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + candidates, err := NewCandidates(bus.NewBus(), mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err := mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 1 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "FCF3853839873D3EC344016C04A5E75166F51063745670DF5D561C060E7F45A1" { + t.Fatalf("hash %X", hash) + } + + candidates.Edit([32]byte{4}, [20]byte{1, 1}, [20]byte{2, 2}, [20]byte{3, 3}) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 2 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "482BE887F2E18DC1BB829BD6AFE8887CE4EC74D4DC485DB1355D78093EAB6B35" { + t.Fatalf("hash %X", hash) + } + + if candidates.GetCandidateControl([32]byte{4}) != [20]byte{3, 3} { + t.Fatal("control address is not change") + } + + if candidates.GetCandidateOwner([32]byte{4}) != [20]byte{2, 2} { + t.Fatal("owner address is not change") + } + +} + +func TestCandidates_Commit_createOneCandidateWithID(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + candidates, err := NewCandidates(bus.NewBus(), mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.CreateWithID([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10, 1) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err := mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 1 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "FCF3853839873D3EC344016C04A5E75166F51063745670DF5D561C060E7F45A1" { + t.Fatalf("hash %X", hash) + } + + id := candidates.ID([32]byte{4}) + if id != 1 { + t.Fatalf("ID %d", id) + } +} + +func TestCandidates_Commit_Delegate(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + candidates, err := NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err := mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 1 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "FCF3853839873D3EC344016C04A5E75166F51063745670DF5D561C060E7F45A1" { + t.Fatalf("hash %X", hash) + } + + candidates.Delegate([20]byte{1, 1}, [32]byte{4}, 0, big.NewInt(10000000), big.NewInt(10000000)) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 2 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "43FE25EB54D52C6516521FB0F951E87359040A9E8DAA23BDC27C6EC5DFBC10EF" { + t.Fatalf("hash %X", hash) + } +} + +func TestCandidates_Commit_setOnline(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + candidates, err := NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err := mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 1 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "FCF3853839873D3EC344016C04A5E75166F51063745670DF5D561C060E7F45A1" { + t.Fatalf("hash %X", hash) + } + + candidates.SetOnline([32]byte{4}) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 2 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "B7CDFAE03E151CA2CD105295E101D4BD00F64CD55D2D8E1AD853853C623BEC23" { + t.Fatalf("hash %X", hash) + } +} + +func TestCandidates_Commit_setOffline(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + candidates, err := NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err := mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 1 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "FCF3853839873D3EC344016C04A5E75166F51063745670DF5D561C060E7F45A1" { + t.Fatalf("hash %X", hash) + } + + candidates.SetOffline([32]byte{4}) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 2 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "17D06535CC123FDF2DA9B97D272E683EC143CEEC73C143D151D0311388E82CBC" { + t.Fatalf("hash %X", hash) + } +} + +func TestCandidates_Count(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + candidates, err := NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + candidates.Create([20]byte{1, 1}, [20]byte{2, 2}, [20]byte{3, 3}, [32]byte{4, 4}, 20) + candidates.Create([20]byte{1, 1, 1}, [20]byte{2, 2, 2}, [20]byte{3, 3, 3}, [32]byte{4, 4, 4}, 30) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err := mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 1 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "25F7EF5A007B3D8A5FB4DCE32F9DBC28C2AE6848B893986E3055BC3045E8F00F" { + t.Fatalf("hash %X", hash) + } + + count := candidates.Count() + if count != 3 { + t.Fatalf("coun %d", count) + } +} + +func TestCandidates_GetTotalStake_fromModelAndFromDB(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + wl, err := waitlist.NewWaitList(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetEvents(eventsdb.NewEventsStore(db.NewMemDB())) + b.SetWaitList(waitlist.NewBus(wl)) + accs, err := accounts.NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetAccounts(accounts.NewBus(accs)) + b.SetChecker(checker.NewChecker(b)) + candidates, err := NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err := mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 1 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "FCF3853839873D3EC344016C04A5E75166F51063745670DF5D561C060E7F45A1" { + t.Fatalf("hash %X", hash) + } + + var stakes []types.Stake + for i := 0; i < 1010; i++ { + value := strconv.Itoa(i + 2000) + stakes = append(stakes, types.Stake{ + Owner: types.StringToAddress(strconv.Itoa(i)), + Coin: 0, + Value: value, + BipValue: value, + }) + } + candidates.SetStakes([32]byte{4}, stakes, []types.Stake{ + { + Owner: [20]byte{2}, + Coin: 0, + Value: "100", + BipValue: "100", + }, + }) + + candidates.RecalculateStakes(1) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 2 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "5DDA783086104DCC15B5825F0C2BD559EA813A3024AEB8E8A3D336A24676887B" { + t.Fatalf("hash %X", hash) + } + + totalStake := candidates.GetTotalStake([32]byte{4}) + totalStakeString := totalStake.String() + if totalStakeString != "2509500" { + t.Fatalf("total stake %s", totalStakeString) + } + + candidates, err = NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + candidates.LoadCandidates() + totalStake = candidates.GetTotalStake([32]byte{4}) + totalStakeString = totalStake.String() + if totalStakeString != "2509500" { + t.Fatalf("total stake %s", totalStakeString) + } +} + +func TestCandidates_GetTotalStake_forCustomCoins(t *testing.T) { + + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + wl, err := waitlist.NewWaitList(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetEvents(eventsdb.NewEventsStore(db.NewMemDB())) + b.SetWaitList(waitlist.NewBus(wl)) + accs, err := accounts.NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetAccounts(accounts.NewBus(accs)) + b.SetChecker(checker.NewChecker(b)) + candidates, err := NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + coinsState, err := coins.NewCoins(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + coinsState.Create(1, + types.StrToCoinSymbol("AAA"), + "AAACOIN", + helpers.BipToPip(big.NewInt(10)), + 10, + helpers.BipToPip(big.NewInt(10000)), + big.NewInt(0).Exp(big.NewInt(10), big.NewInt(10+18), nil), + nil) + + err = coinsState.Commit() + if err != nil { + t.Fatal(err) + } + + symbol := coinsState.GetCoinBySymbol(types.StrToCoinSymbol("AAA"), 0) + if symbol == nil { + t.Fatal("coin not found") + } + + var stakes []types.Stake + for i := 0; i < 50; i++ { + value := strconv.Itoa(i + 2000) + stakes = append(stakes, types.Stake{ + Owner: types.StringToAddress(strconv.Itoa(i)), + Coin: symbol.ID(), + Value: value, + BipValue: "0", + }) + } + candidates.SetStakes([32]byte{4}, stakes, nil) + + candidates.RecalculateStakes(1) + + candidates.LoadCandidates() + totalStake := candidates.GetTotalStake([32]byte{4}) + totalStakeString := totalStake.String() + if totalStakeString != "9802420350703877401368" { + t.Fatalf("total stake %s", totalStakeString) + } +} + +func TestCandidates_Export(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + candidates, err := NewCandidates(bus.NewBus(), mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + candidates.AddToBlockPubKey([32]byte{10}) + candidates.SetStakes([32]byte{4}, []types.Stake{ + { + Owner: [20]byte{1}, + Coin: 0, + Value: "100", + BipValue: "100", + }, + }, []types.Stake{ + { + Owner: [20]byte{2}, + Coin: 0, + Value: "100", + BipValue: "100", + }, + }) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + state := new(types.AppState) + candidates.Export(state) + + bytes, err := json.Marshal(state.Candidates) + if err != nil { + t.Fatal(err) + } + + if string(bytes) != "[{\"id\":1,\"reward_address\":\"Mx0200000000000000000000000000000000000000\",\"owner_address\":\"Mx0100000000000000000000000000000000000000\",\"control_address\":\"Mx0300000000000000000000000000000000000000\",\"total_bip_stake\":\"0\",\"public_key\":\"Mp0400000000000000000000000000000000000000000000000000000000000000\",\"commission\":10,\"stakes\":[{\"owner\":\"Mx0100000000000000000000000000000000000000\",\"coin\":0,\"value\":\"100\",\"bip_value\":\"100\"}],\"updates\":[{\"owner\":\"Mx0200000000000000000000000000000000000000\",\"coin\":0,\"value\":\"100\",\"bip_value\":\"100\"}],\"status\":1}]" { + t.Fatal("not equal JSON") + } + + bytes, err = json.Marshal(state.BlockListCandidates) + if err != nil { + t.Fatal(err) + } + + if string(bytes) != "[\"Mp0a00000000000000000000000000000000000000000000000000000000000000\"]" { + t.Fatal("not equal JSON") + } +} + +func TestCandidates_bus(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + candidates, err := NewCandidates(bus.NewBus(), mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + candidates.SetStakes([32]byte{4}, []types.Stake{ + { + Owner: [20]byte{1}, + Coin: 0, + Value: "100", + BipValue: "100", + }, + }, []types.Stake{ + { + Owner: [20]byte{2}, + Coin: 0, + Value: "100", + BipValue: "100", + }, + }) + + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + stakes := candidates.bus.Candidates().GetStakes([32]byte{4}) + if len(stakes) != 1 { + t.Fatalf("stakes count %d", len(stakes)) + } + + if stakes[0].Owner != [20]byte{1} { + t.Fatal("owner is invalid") + } +} + +func TestCandidates_GetCandidateByTendermintAddress(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + candidates, err := NewCandidates(bus.NewBus(), mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + + candidate := candidates.GetCandidate([32]byte{4}) + if candidate == nil { + t.Fatal("candidate not found") + } + + candidateByTmAddr := candidates.GetCandidateByTendermintAddress(*candidate.tmAddress) + if candidate.ID != candidateByTmAddr.ID { + t.Fatal("candidate ID != candidateByTmAddr.ID") + } +} diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 31c764103..6745b3ae2 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -233,7 +233,7 @@ func (c *Candidates) GetNewCandidates(valCount int) []Candidate { // Create creates a new candidate with given params and adds it to state func (c *Candidates) Create(ownerAddress, rewardAddress, controlAddress types.Address, pubkey types.Pubkey, commission uint) { candidate := &Candidate{ - ID: c.getOrNewID(pubkey), + ID: 0, PubKey: pubkey, RewardAddress: rewardAddress, OwnerAddress: ownerAddress, @@ -1059,7 +1059,20 @@ func (c *Candidates) ID(pubKey types.Pubkey) uint32 { c.lock.RLock() defer c.lock.RUnlock() - return c.pubKeyIDs[pubKey] + return c.id(pubKey) +} + +// PubKey returns a public key of candidate by it's ID +func (c *Candidates) PubKey(id uint32) types.Pubkey { + c.lock.RLock() + defer c.lock.RUnlock() + + candidate, ok := c.list[id] + if !ok { + panic(fmt.Sprintf("candidate by ID %d not found", id)) + } + + return candidate.PubKey } func (c *Candidates) setPubKeyID(pubkey types.Pubkey, u uint32) { diff --git a/core/state/candidates/coins_cache.go b/core/state/candidates/coins_cache.go new file mode 100644 index 000000000..fbf45c23d --- /dev/null +++ b/core/state/candidates/coins_cache.go @@ -0,0 +1,46 @@ +package candidates + +import ( + "github.com/MinterTeam/minter-go-node/core/types" + "math/big" +) + +type coinsCache struct { + list map[types.CoinID]*coinsCacheItem +} + +func newCoinsCache() *coinsCache { + return &coinsCache{list: map[types.CoinID]*coinsCacheItem{}} +} + +type coinsCacheItem struct { + saleReturn *big.Int + totalAmount *big.Int +} + +func (c *coinsCache) Exists(id types.CoinID) bool { + if c == nil { + return false + } + + _, exists := c.list[id] + + return exists +} + +func (c *coinsCache) Get(id types.CoinID) (saleReturn *big.Int, totalAmount *big.Int) { + return big.NewInt(0).Set(c.list[id].totalAmount), big.NewInt(0).Set(c.list[id].totalAmount) +} + +func (c *coinsCache) Set(id types.CoinID, saleReturn *big.Int, totalAmount *big.Int) { + if c == nil { + return + } + + if c.list[id] == nil { + c.list[id] = &coinsCacheItem{} + } + + c.list[id].totalAmount = totalAmount + c.list[id].saleReturn = saleReturn +} diff --git a/core/state/candidates/model.go b/core/state/candidates/model.go index 28c0ec3d7..44f593559 100644 --- a/core/state/candidates/model.go +++ b/core/state/candidates/model.go @@ -210,43 +210,3 @@ func (stake *stake) setValue(ret *big.Int) { stake.markDirty(stake.index) stake.Value.Set(ret) } - -type coinsCache struct { - list map[types.CoinID]*coinsCacheItem -} - -func newCoinsCache() *coinsCache { - return &coinsCache{list: map[types.CoinID]*coinsCacheItem{}} -} - -type coinsCacheItem struct { - saleReturn *big.Int - totalAmount *big.Int -} - -func (c *coinsCache) Exists(id types.CoinID) bool { - if c == nil { - return false - } - - _, exists := c.list[id] - - return exists -} - -func (c *coinsCache) Get(id types.CoinID) (saleReturn *big.Int, totalAmount *big.Int) { - return big.NewInt(0).Set(c.list[id].totalAmount), big.NewInt(0).Set(c.list[id].totalAmount) -} - -func (c *coinsCache) Set(id types.CoinID, saleReturn *big.Int, totalAmount *big.Int) { - if c == nil { - return - } - - if c.list[id] == nil { - c.list[id] = &coinsCacheItem{} - } - - c.list[id].totalAmount = totalAmount - c.list[id].saleReturn = saleReturn -} diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index c205aa96a..342844c09 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/MinterTeam/minter-go-node/core/state/bus" "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/rlp" "github.com/MinterTeam/minter-go-node/tree" "math/big" @@ -259,8 +260,9 @@ func (c *Coins) get(id types.CoinID) *Model { if id.IsBaseCoin() { // TODO: refactor return &Model{ - id: types.GetBaseCoinID(), - CSymbol: types.GetBaseCoin(), + id: types.GetBaseCoinID(), + CSymbol: types.GetBaseCoin(), + CMaxSupply: helpers.BipToPip(big.NewInt(10000000000)), info: &Info{ Volume: big.NewInt(0), Reserve: big.NewInt(0), diff --git a/core/state/state.go b/core/state/state.go index f70cd960d..9c0c9ea06 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -87,7 +87,7 @@ func (cs *CheckState) Coins() coins.RCoins { func (cs *CheckState) Checks() checks.RChecks { return cs.state.Checks } -func (cs *CheckState) Watchlist() waitlist.RWaitList { +func (cs *CheckState) WaitList() waitlist.RWaitList { return cs.state.Waitlist } func (cs *CheckState) Tree() tree.ReadOnlyTree { @@ -332,6 +332,14 @@ func (s *State) Import(state types.AppState) error { s.Candidates.SetStakes(c.PubKey, c.Stakes, c.Updates) } + for _, w := range state.Waitlist { + value, ok := big.NewInt(0).SetString(w.Value, 10) + if !ok { + panic(fmt.Sprintf("Cannot decode %s into big.Int", w.Value)) + } + s.Waitlist.AddWaitList(w.Owner, s.Candidates.PubKey(w.CandidateID), w.Coin, value) + } + for _, hashString := range state.UsedChecks { bytes, _ := hex.DecodeString(string(hashString)) var hash types.Hash @@ -356,6 +364,7 @@ func (s *State) Export(height uint64) types.AppState { state.App().Export(appState, height) state.Validators().Export(appState) state.Candidates().Export(appState) + state.WaitList().Export(appState) state.FrozenFunds().Export(appState, height) state.Accounts().Export(appState) state.Coins().Export(appState) diff --git a/core/state/waitlist/waitlist.go b/core/state/waitlist/waitlist.go index 19e14621c..4c9288360 100644 --- a/core/state/waitlist/waitlist.go +++ b/core/state/waitlist/waitlist.go @@ -19,6 +19,7 @@ type RWaitList interface { Get(address types.Address, pubkey types.Pubkey, coin types.CoinID) *Item GetByAddress(address types.Address) *Model GetByAddressAndPubKey(address types.Address, pubkey types.Pubkey) []Item + Export(state *types.AppState) } type WaitList struct { @@ -43,6 +44,26 @@ func NewWaitList(stateBus *bus.Bus, iavl tree.MTree) (*WaitList, error) { return waitlist, nil } +func (wl *WaitList) Export(state *types.AppState) { + var waitlist []*Model + for _, model := range wl.list { + waitlist = append(waitlist, model) + } + sort.Slice(waitlist, func(i, j int) bool { + return waitlist[i].address.Compare(waitlist[j].address) > 0 + }) + for _, model := range waitlist { + for _, item := range model.List { + state.Waitlist = append(state.Waitlist, types.Waitlist{ + CandidateID: item.CandidateId, + Owner: model.address, + Coin: item.Coin, + Value: item.Value.String(), + }) + } + } +} + func (wl *WaitList) Commit() error { dirty := wl.getOrderedDirty() for _, address := range dirty { diff --git a/core/transaction/redeem_check_test.go b/core/transaction/redeem_check_test.go index 77f9cd602..17a4f6281 100644 --- a/core/transaction/redeem_check_test.go +++ b/core/transaction/redeem_check_test.go @@ -391,7 +391,7 @@ func TestRedeemCheckTxToWrongChainID(t *testing.T) { tx := Transaction{ Nonce: 1, GasPrice: 1, - ChainID: types.CurrentChainID, + ChainID: types.ChainTestnet, GasCoin: coin, Type: TypeRedeemCheck, Data: encodedData, diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 35dbda087..d9f557b6f 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -60,7 +60,7 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R errorInfo["unbound_value"] = data.Value.String() sender, _ := tx.Sender() - if waitlist := context.Watchlist().Get(sender, data.PubKey, data.Coin); waitlist != nil { + if waitlist := context.WaitList().Get(sender, data.PubKey, data.Coin); waitlist != nil { value := big.NewInt(0).Sub(data.Value, waitlist.Value) if value.Sign() < 1 { return nil diff --git a/core/types/appstate.go b/core/types/appstate.go index 416cfaa27..8ef627ca1 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -13,6 +13,7 @@ type AppState struct { Validators []Validator `json:"validators,omitempty"` Candidates []Candidate `json:"candidates,omitempty"` BlockListCandidates []Pubkey `json:"block_list_candidates,omitempty"` + Waitlist []Waitlist `json:"waitlist,omitempty"` Accounts []Account `json:"accounts,omitempty"` Coins []Coin `json:"coins,omitempty"` FrozenFunds []FrozenFund `json:"frozen_funds,omitempty"` @@ -229,6 +230,13 @@ type Stake struct { BipValue string `json:"bip_value"` } +type Waitlist struct { + CandidateID uint32 `json:"candidate_id"` + Owner Address `json:"owner"` + Coin CoinID `json:"coin"` + Value string `json:"value"` +} + type Coin struct { ID CoinID `json:"id"` Name string `json:"name"` From 66a9762108bfecd8a6b8a4a96e0e55626ec0bcd8 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 8 Sep 2020 14:14:49 +0300 Subject: [PATCH 225/426] refactor and tests --- api/estimate_coin_buy.go | 4 ++-- api/estimate_coin_sell.go | 4 ++-- api/estimate_coin_sell_all.go | 4 ++-- core/events/store_test.go | 24 ++++++++++++++++++++---- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/api/estimate_coin_buy.go b/api/estimate_coin_buy.go index 9440d4348..b43cdd602 100644 --- a/api/estimate_coin_buy.go +++ b/api/estimate_coin_buy.go @@ -10,13 +10,13 @@ import ( "math/big" ) -// EstimateCoinBuyResponse is estimate of buy coin transaction +// EstimateCoinBuyResponse returns an estimate of buy coin transaction type EstimateCoinBuyResponse struct { WillPay string `json:"will_pay"` Commission string `json:"commission"` } -// EstimateCoinBuy returns is estimate of buy coin transaction +// EstimateCoinBuy returns an estimate of buy coin transaction func EstimateCoinBuy(coinToSell, coinToBuy string, valueToBuy *big.Int, height int) (*EstimateCoinBuyResponse, error) { cState, err := GetStateForHeight(height) if err != nil { diff --git a/api/estimate_coin_sell.go b/api/estimate_coin_sell.go index b5d298c48..ac4296e7e 100644 --- a/api/estimate_coin_sell.go +++ b/api/estimate_coin_sell.go @@ -10,13 +10,13 @@ import ( "math/big" ) -// EstimateCoinSellResponse is estimate of sell coin transaction +// EstimateCoinSellResponse returns an estimate of sell coin transaction type EstimateCoinSellResponse struct { WillGet string `json:"will_get"` Commission string `json:"commission"` } -// EstimateCoinSell returns estimate of sell coin transaction +// EstimateCoinSell returns an estimate of sell coin transaction func EstimateCoinSell(coinToSell, coinToBuy string, valueToSell *big.Int, height int) (*EstimateCoinSellResponse, error) { cState, err := GetStateForHeight(height) if err != nil { diff --git a/api/estimate_coin_sell_all.go b/api/estimate_coin_sell_all.go index 03f0ff443..513e1ef5b 100644 --- a/api/estimate_coin_sell_all.go +++ b/api/estimate_coin_sell_all.go @@ -9,12 +9,12 @@ import ( "math/big" ) -// EstimateCoinSellAllResponse is estimate of sell all coin transaction +// EstimateCoinSellAllResponse returns an of sell all coin transaction type EstimateCoinSellAllResponse struct { WillGet string `json:"will_get"` } -// EstimateCoinSellAll returns estimate of sell all coin transaction +// EstimateCoinSellAll returns an estimate of sell all coin transaction func EstimateCoinSellAll(coinToSell, coinToBuy string, valueToSell *big.Int, gasPrice uint64, height int) (*EstimateCoinSellAllResponse, error) { cState, err := GetStateForHeight(height) diff --git a/core/events/store_test.go b/core/events/store_test.go index 049a0368c..076023153 100644 --- a/core/events/store_test.go +++ b/core/events/store_test.go @@ -56,9 +56,25 @@ func TestIEventsDB(t *testing.T) { } loadEvents := store.LoadEvents(12) - for _, v := range loadEvents { - t.Logf("%+v", v) - t.Logf("%+v", v.(*RewardEvent).Amount) - t.Logf("%+v", v.(*RewardEvent).Address.String()) + + if len(loadEvents) != 2 { + t.Fatal("count of events not equal 2") + } + + if loadEvents[0].(*RewardEvent).Amount != "111497225000000000000" { + t.Fatal("invalid Amount") + } + + if loadEvents[0].(*RewardEvent).Address.String() != "Mx04bea23efb744dc93b4fda4c20bf4a21c6e195f1" { + t.Fatal("invalid Address") } + + if loadEvents[1].(*RewardEvent).Amount != "891977800000000000000" { + t.Fatal("invalid Amount") + } + + if loadEvents[1].(*RewardEvent).Address.String() != "Mx18467bbb64a8edf890201d526c35957d82be3d95" { + t.Fatal("invalid Address") + } + } From 44ce34acb943275934e190b6c732d6a8bf9e952a Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 8 Sep 2020 14:46:49 +0300 Subject: [PATCH 226/426] linter --- api/block.go | 5 +++-- api/transaction.go | 1 + api/transactions.go | 1 + core/transaction/encoder/encoder.go | 1 + core/transaction/encoder/resources.go | 3 ++- core/transaction/transaction.go | 5 +++-- 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/api/block.go b/api/block.go index ae09b53f1..e5e677cf0 100644 --- a/api/block.go +++ b/api/block.go @@ -5,14 +5,15 @@ import ( "encoding/hex" "encoding/json" "fmt" + "time" + "github.com/MinterTeam/minter-go-node/core/rewards" "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/core/transaction/encoder" "github.com/MinterTeam/minter-go-node/core/types" - "github.com/MinterTeam/minter-go-node/rpc/lib/types" + rpctypes "github.com/MinterTeam/minter-go-node/rpc/lib/types" core_types "github.com/tendermint/tendermint/rpc/core/types" tmTypes "github.com/tendermint/tendermint/types" - "time" ) type BlockResponse struct { diff --git a/api/transaction.go b/api/transaction.go index 1541ea41e..913ad534e 100644 --- a/api/transaction.go +++ b/api/transaction.go @@ -2,6 +2,7 @@ package api import ( "encoding/json" + "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/core/transaction/encoder" ) diff --git a/api/transactions.go b/api/transactions.go index 31d461d2a..b0943c3ed 100644 --- a/api/transactions.go +++ b/api/transactions.go @@ -2,6 +2,7 @@ package api import ( "encoding/json" + "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/core/transaction/encoder" core_types "github.com/tendermint/tendermint/rpc/core/types" diff --git a/core/transaction/encoder/encoder.go b/core/transaction/encoder/encoder.go index b0b175a6c..3a75a3ec6 100644 --- a/core/transaction/encoder/encoder.go +++ b/core/transaction/encoder/encoder.go @@ -3,6 +3,7 @@ package encoder import ( "encoding/json" "fmt" + "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/transaction" rpctypes "github.com/MinterTeam/minter-go-node/rpc/lib/types" diff --git a/core/transaction/encoder/resources.go b/core/transaction/encoder/resources.go index e9e3ab4cb..59024c9b8 100644 --- a/core/transaction/encoder/resources.go +++ b/core/transaction/encoder/resources.go @@ -2,10 +2,11 @@ package encoder import ( "encoding/base64" + "strconv" + "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/core/types" - "strconv" ) type TxDataResource interface { diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index e0649c289..1afbf8af5 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -4,6 +4,9 @@ import ( "crypto/ecdsa" "errors" "fmt" + "math/big" + "strconv" + "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" @@ -12,8 +15,6 @@ import ( "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/crypto/sha3" "github.com/MinterTeam/minter-go-node/rlp" - "math/big" - "strconv" ) type TxType byte From 7ffd5c13beccfeb84bbd04f026ee9ba2c2d92331 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 8 Sep 2020 17:03:57 +0300 Subject: [PATCH 227/426] refactor and tests --- core/state/candidates/candidate_test.go | 680 +++++++++++++++++------- core/state/candidates/candidates.go | 6 +- core/state/candidates/model.go | 28 +- 3 files changed, 492 insertions(+), 222 deletions(-) diff --git a/core/state/candidates/candidate_test.go b/core/state/candidates/candidate_test.go index 1eb3f9b76..b8fdb1e3e 100644 --- a/core/state/candidates/candidate_test.go +++ b/core/state/candidates/candidate_test.go @@ -5,6 +5,7 @@ import ( "fmt" eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/state/accounts" + "github.com/MinterTeam/minter-go-node/core/state/app" "github.com/MinterTeam/minter-go-node/core/state/bus" "github.com/MinterTeam/minter-go-node/core/state/checker" "github.com/MinterTeam/minter-go-node/core/state/coins" @@ -32,21 +33,13 @@ func TestCandidates_Commit_createOneCandidate(t *testing.T) { t.Fatal(err) } - hash, version, err := mutableTree.SaveVersion() - if err != nil { - t.Fatal(err) - } - - if version != 1 { - t.Fatalf("version %d", version) - } - - if fmt.Sprintf("%X", hash) != "FCF3853839873D3EC344016C04A5E75166F51063745670DF5D561C060E7F45A1" { - t.Fatalf("hash %X", hash) + candidate := candidates.GetCandidate([32]byte{4}) + if candidate == nil { + t.Fatal("candidate not found") } - if !candidates.Exists([32]byte{4}) { - t.Fatal("candidate not found by pub_key") + if candidates.PubKey(candidate.ID) != [32]byte{4} { + t.Fatal("candidate error ID or PubKey") } } @@ -227,70 +220,6 @@ func TestCandidates_Commit_withStakeAndUpdate(t *testing.T) { } } -func TestCandidates_Commit_withStakesMoreMaxDelegatorsPerCandidate(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) - candidates, err := NewCandidates(bus.NewBus(), mutableTree) - if err != nil { - t.Fatal(err) - } - - candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) - - err = candidates.Commit() - if err != nil { - t.Fatal(err) - } - - hash, version, err := mutableTree.SaveVersion() - if err != nil { - t.Fatal(err) - } - - if version != 1 { - t.Fatalf("version %d", version) - } - - if fmt.Sprintf("%X", hash) != "FCF3853839873D3EC344016C04A5E75166F51063745670DF5D561C060E7F45A1" { - t.Fatalf("hash %X", hash) - } - - var stakes []types.Stake - for i := 0; i < 1010; i++ { - value := strconv.Itoa(i + 2000) - stakes = append(stakes, types.Stake{ - Owner: types.StringToAddress(strconv.Itoa(i)), - Coin: 0, - Value: value, - BipValue: value, - }) - } - candidates.SetStakes([32]byte{4}, stakes, []types.Stake{ - { - Owner: [20]byte{2}, - Coin: 0, - Value: "100", - BipValue: "100", - }, - }) - err = candidates.Commit() - if err != nil { - t.Fatal(err) - } - - hash, version, err = mutableTree.SaveVersion() - if err != nil { - t.Fatal(err) - } - - if version != 2 { - t.Fatalf("version %d", version) - } - - if fmt.Sprintf("%X", hash) != "51022ED08FD976D0305B3BD8CB90C0139CDC4970CD9548237DF358ECD54BA6D1" { - t.Fatalf("hash %X", hash) - } -} - func TestCandidates_Commit_edit(t *testing.T) { mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) candidates, err := NewCandidates(bus.NewBus(), mutableTree) @@ -431,7 +360,7 @@ func TestCandidates_Commit_Delegate(t *testing.T) { } } -func TestCandidates_Commit_setOnline(t *testing.T) { +func TestCandidates_SetOnlineAndBusSetOffline(t *testing.T) { mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) @@ -447,87 +376,18 @@ func TestCandidates_Commit_setOnline(t *testing.T) { t.Fatal(err) } - hash, version, err := mutableTree.SaveVersion() - if err != nil { - t.Fatal(err) - } - - if version != 1 { - t.Fatalf("version %d", version) - } - - if fmt.Sprintf("%X", hash) != "FCF3853839873D3EC344016C04A5E75166F51063745670DF5D561C060E7F45A1" { - t.Fatalf("hash %X", hash) - } - candidates.SetOnline([32]byte{4}) - err = candidates.Commit() - if err != nil { - t.Fatal(err) - } - - hash, version, err = mutableTree.SaveVersion() - if err != nil { - t.Fatal(err) - } - - if version != 2 { - t.Fatalf("version %d", version) - } - - if fmt.Sprintf("%X", hash) != "B7CDFAE03E151CA2CD105295E101D4BD00F64CD55D2D8E1AD853853C623BEC23" { - t.Fatalf("hash %X", hash) - } -} - -func TestCandidates_Commit_setOffline(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) - b := bus.NewBus() - b.SetChecker(checker.NewChecker(b)) - candidates, err := NewCandidates(b, mutableTree) - if err != nil { - t.Fatal(err) - } - - candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) - - err = candidates.Commit() - if err != nil { - t.Fatal(err) - } - - hash, version, err := mutableTree.SaveVersion() - if err != nil { - t.Fatal(err) - } - - if version != 1 { - t.Fatalf("version %d", version) - } - - if fmt.Sprintf("%X", hash) != "FCF3853839873D3EC344016C04A5E75166F51063745670DF5D561C060E7F45A1" { - t.Fatalf("hash %X", hash) - } - - candidates.SetOffline([32]byte{4}) - - err = candidates.Commit() - if err != nil { - t.Fatal(err) - } - - hash, version, err = mutableTree.SaveVersion() - if err != nil { - t.Fatal(err) + candidate := candidates.GetCandidate([32]byte{4}) + if candidate == nil { + t.Fatal("candidate not found") } - - if version != 2 { - t.Fatalf("version %d", version) + if candidate.Status != CandidateStatusOnline { + t.Fatal("candidate not change status to online") } - - if fmt.Sprintf("%X", hash) != "17D06535CC123FDF2DA9B97D272E683EC143CEEC73C143D151D0311388E82CBC" { - t.Fatalf("hash %X", hash) + candidates.bus.Candidates().SetOffline([32]byte{4}) + if candidate.Status != CandidateStatusOffline { + t.Fatal("candidate not change status to offline") } } @@ -575,8 +435,8 @@ func TestCandidates_GetTotalStake_fromModelAndFromDB(t *testing.T) { if err != nil { t.Fatal(err) } - b.SetEvents(eventsdb.NewEventsStore(db.NewMemDB())) b.SetWaitList(waitlist.NewBus(wl)) + b.SetEvents(eventsdb.NewEventsStore(db.NewMemDB())) accs, err := accounts.NewAccounts(b, mutableTree) if err != nil { t.Fatal(err) @@ -590,24 +450,6 @@ func TestCandidates_GetTotalStake_fromModelAndFromDB(t *testing.T) { candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) - err = candidates.Commit() - if err != nil { - t.Fatal(err) - } - - hash, version, err := mutableTree.SaveVersion() - if err != nil { - t.Fatal(err) - } - - if version != 1 { - t.Fatalf("version %d", version) - } - - if fmt.Sprintf("%X", hash) != "FCF3853839873D3EC344016C04A5E75166F51063745670DF5D561C060E7F45A1" { - t.Fatalf("hash %X", hash) - } - var stakes []types.Stake for i := 0; i < 1010; i++ { value := strconv.Itoa(i + 2000) @@ -625,31 +467,24 @@ func TestCandidates_GetTotalStake_fromModelAndFromDB(t *testing.T) { Value: "100", BipValue: "100", }, + { + Owner: types.StringToAddress("1"), + Coin: 0, + Value: "100", + BipValue: "100", + }, }) - candidates.RecalculateStakes(1) + candidates.RecalculateStakes(0) err = candidates.Commit() if err != nil { t.Fatal(err) } - hash, version, err = mutableTree.SaveVersion() - if err != nil { - t.Fatal(err) - } - - if version != 2 { - t.Fatalf("version %d", version) - } - - if fmt.Sprintf("%X", hash) != "5DDA783086104DCC15B5825F0C2BD559EA813A3024AEB8E8A3D336A24676887B" { - t.Fatalf("hash %X", hash) - } - totalStake := candidates.GetTotalStake([32]byte{4}) totalStakeString := totalStake.String() - if totalStakeString != "2509500" { + if totalStakeString != "2509591" { t.Fatalf("total stake %s", totalStakeString) } @@ -658,9 +493,10 @@ func TestCandidates_GetTotalStake_fromModelAndFromDB(t *testing.T) { t.Fatal(err) } candidates.LoadCandidates() + candidates.GetCandidate([32]byte{4}).totalBipStake = nil totalStake = candidates.GetTotalStake([32]byte{4}) totalStakeString = totalStake.String() - if totalStakeString != "2509500" { + if totalStakeString != "2509591" { t.Fatalf("total stake %s", totalStakeString) } } @@ -723,7 +559,7 @@ func TestCandidates_GetTotalStake_forCustomCoins(t *testing.T) { } candidates.SetStakes([32]byte{4}, stakes, nil) - candidates.RecalculateStakes(1) + candidates.RecalculateStakes(0) candidates.LoadCandidates() totalStake := candidates.GetTotalStake([32]byte{4}) @@ -757,7 +593,7 @@ func TestCandidates_Export(t *testing.T) { BipValue: "100", }, }) - + candidates.recalculateStakes(0) err = candidates.Commit() if err != nil { t.Fatal(err) @@ -771,7 +607,8 @@ func TestCandidates_Export(t *testing.T) { t.Fatal(err) } - if string(bytes) != "[{\"id\":1,\"reward_address\":\"Mx0200000000000000000000000000000000000000\",\"owner_address\":\"Mx0100000000000000000000000000000000000000\",\"control_address\":\"Mx0300000000000000000000000000000000000000\",\"total_bip_stake\":\"0\",\"public_key\":\"Mp0400000000000000000000000000000000000000000000000000000000000000\",\"commission\":10,\"stakes\":[{\"owner\":\"Mx0100000000000000000000000000000000000000\",\"coin\":0,\"value\":\"100\",\"bip_value\":\"100\"}],\"updates\":[{\"owner\":\"Mx0200000000000000000000000000000000000000\",\"coin\":0,\"value\":\"100\",\"bip_value\":\"100\"}],\"status\":1}]" { + if string(bytes) != "[{\"id\":1,\"reward_address\":\"Mx0200000000000000000000000000000000000000\",\"owner_address\":\"Mx0100000000000000000000000000000000000000\",\"control_address\":\"Mx0300000000000000000000000000000000000000\",\"total_bip_stake\":\"200\",\"public_key\":\"Mp0400000000000000000000000000000000000000000000000000000000000000\",\"commission\":10,\"stakes\":[{\"owner\":\"Mx0100000000000000000000000000000000000000\",\"coin\":0,\"value\":\"100\",\"bip_value\":\"100\"},{\"owner\":\"Mx0200000000000000000000000000000000000000\",\"coin\":0,\"value\":\"100\",\"bip_value\":\"100\"}],\"updates\":[],\"status\":1}]" { + t.Log(string(bytes)) t.Fatal("not equal JSON") } @@ -785,7 +622,7 @@ func TestCandidates_Export(t *testing.T) { } } -func TestCandidates_bus(t *testing.T) { +func TestCandidates_busGetStakes(t *testing.T) { mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) candidates, err := NewCandidates(bus.NewBus(), mutableTree) if err != nil { @@ -838,8 +675,461 @@ func TestCandidates_GetCandidateByTendermintAddress(t *testing.T) { t.Fatal("candidate not found") } - candidateByTmAddr := candidates.GetCandidateByTendermintAddress(*candidate.tmAddress) + candidateByTmAddr := candidates.GetCandidateByTendermintAddress(candidate.GetTmAddress()) if candidate.ID != candidateByTmAddr.ID { t.Fatal("candidate ID != candidateByTmAddr.ID") } } +func TestCandidates_busGetCandidateByTendermintAddress(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + candidates, err := NewCandidates(bus.NewBus(), mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + + candidate := candidates.GetCandidate([32]byte{4}) + if candidate == nil { + t.Fatal("candidate not found") + } + + candidateByTmAddr := candidates.bus.Candidates().GetCandidateByTendermintAddress(candidate.GetTmAddress()) + if candidate.ID != candidateByTmAddr.ID { + t.Fatal("candidate ID != candidateByTmAddr.ID") + } +} + +func TestCandidates_Punish(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + wl, err := waitlist.NewWaitList(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetEvents(eventsdb.NewEventsStore(db.NewMemDB())) + b.SetWaitList(waitlist.NewBus(wl)) + accs, err := accounts.NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetAccounts(accounts.NewBus(accs)) + appBus, err := app.NewApp(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetApp(appBus) + b.SetChecker(checker.NewChecker(b)) + candidates, err := NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + coinsState, err := coins.NewCoins(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + coinsState.Create(1, + types.StrToCoinSymbol("AAA"), + "AAACOIN", + helpers.BipToPip(big.NewInt(10)), + 10, + helpers.BipToPip(big.NewInt(10000)), + big.NewInt(0).Exp(big.NewInt(10), big.NewInt(10+18), nil), + nil) + + err = coinsState.Commit() + if err != nil { + t.Fatal(err) + } + + symbol := coinsState.GetCoinBySymbol(types.StrToCoinSymbol("AAA"), 0) + if symbol == nil { + t.Fatal("coin not found") + } + + candidates.SetStakes([32]byte{4}, []types.Stake{ + { + Owner: [20]byte{1}, + Coin: 0, + Value: "100", + BipValue: "100", + }, + { + Owner: [20]byte{1}, + Coin: symbol.ID(), + Value: "100", + BipValue: "0", + }, + }, nil) + + candidates.RecalculateStakes(1) + candidate := candidates.GetCandidate([32]byte{4}) + if candidate == nil { + t.Fatal("candidate not found") + } + candidates.bus.Candidates().Punish(0, candidate.GetTmAddress()) + + if candidate.stakesCount != 2 { + t.Fatalf("stakes count %d", candidate.stakesCount) + } + + if candidate.stakes[0].Value.String() != "99" { + t.Fatalf("stakes[0] == %s", candidate.stakes[0].Value.String()) + } +} + +type fr struct { + unbounds []*big.Int +} + +func (fr *fr) AddFrozenFund(_ uint64, _ types.Address, _ types.Pubkey, _ types.CoinID, value *big.Int) { + fr.unbounds = append(fr.unbounds, value) +} +func TestCandidates_PunishByzantineCandidate(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + frozenfunds := &fr{} + b.SetFrozenFunds(frozenfunds) + wl, err := waitlist.NewWaitList(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetEvents(eventsdb.NewEventsStore(db.NewMemDB())) + b.SetWaitList(waitlist.NewBus(wl)) + accs, err := accounts.NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetAccounts(accounts.NewBus(accs)) + appBus, err := app.NewApp(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetApp(appBus) + b.SetChecker(checker.NewChecker(b)) + candidates, err := NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + coinsState, err := coins.NewCoins(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + coinsState.Create(1, + types.StrToCoinSymbol("AAA"), + "AAACOIN", + helpers.BipToPip(big.NewInt(10)), + 10, + helpers.BipToPip(big.NewInt(10000)), + big.NewInt(0).Exp(big.NewInt(10), big.NewInt(10+18), nil), + nil) + + err = coinsState.Commit() + if err != nil { + t.Fatal(err) + } + + symbol := coinsState.GetCoinBySymbol(types.StrToCoinSymbol("AAA"), 0) + if symbol == nil { + t.Fatal("coin not found") + } + + candidates.SetStakes([32]byte{4}, []types.Stake{ + { + Owner: [20]byte{1}, + Coin: 0, + Value: "100", + BipValue: "100", + }, + { + Owner: [20]byte{1}, + Coin: symbol.ID(), + Value: "100", + BipValue: "0", + }, + }, nil) + + candidates.RecalculateStakes(1) + + candidate := candidates.GetCandidate([32]byte{4}) + if candidate == nil { + t.Fatal("candidate not found") + } + candidates.PunishByzantineCandidate(0, candidate.GetTmAddress()) + + if candidates.GetStakeValueOfAddress([32]byte{4}, [20]byte{1}, symbol.ID()).String() != "0" { + t.Error("stake[0] not unbound") + } + if candidates.GetStakeValueOfAddress([32]byte{4}, [20]byte{1}, 0).String() != "0" { + t.Error("stake[1] not unbound") + } + + if len(frozenfunds.unbounds) != 2 { + t.Fatalf("count unbounds == %d", len(frozenfunds.unbounds)) + } + + if frozenfunds.unbounds[0].String() != "95" { + t.Fatalf("frozenfunds.unbounds[0] == %s", frozenfunds.unbounds[0].String()) + } + if frozenfunds.unbounds[1].String() != "95" { + t.Fatalf("frozenfunds.unbounds[1] == %s", frozenfunds.unbounds[1].String()) + } +} + +func TestCandidates_SubStake(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + candidates, err := NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + candidates.SetStakes([32]byte{4}, []types.Stake{ + { + Owner: [20]byte{1}, + Coin: 0, + Value: "100", + BipValue: "100", + }, + }, nil) + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + candidates.SubStake([20]byte{1}, [32]byte{4}, 0, big.NewInt(10)) + stake := candidates.GetStakeOfAddress([32]byte{4}, [20]byte{1}, 0) + if stake == nil { + t.Fatal("stake not found") + } + + if stake.Value.String() != "90" { + t.Fatal("sub stake error") + } +} + +func TestCandidates_IsNewCandidateStakeSufficient(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + candidates, err := NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + candidates.SetStakes([32]byte{4}, []types.Stake{ + { + Owner: [20]byte{1}, + Coin: 0, + Value: "100", + BipValue: "100", + }, + }, nil) + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + // todo: validators.GetCandidatesCountForBlock(1) + if !candidates.IsNewCandidateStakeSufficient(0, big.NewInt(1000), 1) { + t.Log("is not new candidate stake sufficient") + } +} + +func TestCandidates_IsDelegatorStakeSufficient(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + wl, err := waitlist.NewWaitList(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetWaitList(waitlist.NewBus(wl)) + b.SetChecker(checker.NewChecker(b)) + accs, err := accounts.NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetAccounts(accounts.NewBus(accs)) + b.SetEvents(eventsdb.NewEventsStore(db.NewMemDB())) + candidates, err := NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + + var stakes []types.Stake + for i := 0; i < 1010; i++ { + value := strconv.Itoa(i + 2000) + stakes = append(stakes, types.Stake{ + Owner: types.StringToAddress(strconv.Itoa(i)), + Coin: 0, + Value: value, + BipValue: value, + }) + } + candidates.SetStakes([32]byte{4}, stakes, []types.Stake{ + { + Owner: [20]byte{2}, + Coin: 0, + Value: "100", + BipValue: "100", + }, + }) + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + candidates.SetStakes([32]byte{4}, []types.Stake{ + { + Owner: types.StringToAddress("10000"), + Coin: 0, + Value: "10000", + BipValue: "10000", + }, + }, nil) + + candidates.recalculateStakes(0) + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + if candidates.IsDelegatorStakeSufficient([20]byte{1}, [32]byte{4}, 0, big.NewInt(10)) { + t.Fatal("is not delegator stake sufficient") + } +} +func TestCandidates_IsDelegatorStakeSufficient_false(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + candidates, err := NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + candidates.SetStakes([32]byte{4}, []types.Stake{ + { + Owner: [20]byte{1}, + Coin: 0, + Value: "100", + BipValue: "100", + }, + }, nil) + + candidates.recalculateStakes(0) + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + if !candidates.IsDelegatorStakeSufficient([20]byte{1}, [32]byte{4}, 0, big.NewInt(10)) { + t.Fatal("is delegator stake sufficient") + } +} + +func TestCandidates_GetNewCandidates(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + candidates, err := NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + candidates.SetStakes([32]byte{4}, []types.Stake{ + { + Owner: [20]byte{1}, + Coin: 0, + Value: "1000000000000000", + BipValue: "1000000000000000", + }, + }, nil) + candidates.SetOnline([32]byte{4}) + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{5}, 10) + candidates.SetStakes([32]byte{5}, []types.Stake{ + { + Owner: [20]byte{1}, + Coin: 0, + Value: "1000000000000000", + BipValue: "1000000000000000", + }, + }, nil) + candidates.SetOnline([32]byte{5}) + + candidates.RecalculateStakes(1) + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + newCandidates := candidates.GetNewCandidates(2) + if len(newCandidates) != 2 { + t.Fatal("error count of new candidates") + } +} + +func TestCandidate_GetFilteredUpdates(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + candidates, err := NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + candidates.SetStakes([32]byte{4}, []types.Stake{ + { + Owner: [20]byte{1}, + Coin: 0, + Value: "100", + BipValue: "100", + }, + }, []types.Stake{ + { + Owner: [20]byte{1}, + Coin: 0, + Value: "100", + BipValue: "100", + }, + { + Owner: [20]byte{1}, + Coin: 0, + Value: "100", + BipValue: "100", + }, + }) + err = candidates.Commit() + if err != nil { + t.Fatal(err) + } + + candidate := candidates.GetCandidate([32]byte{4}) + if candidate == nil { + t.Fatal("candidate not found") + } + + candidate.FilterUpdates() + + if len(candidate.updates) != 1 { + t.Fatal("updates not merged") + } + + if candidate.updates[0].Value.String() != "200" { + t.Fatal("error merge updates") + } +} diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 6745b3ae2..e91dbec9e 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -311,7 +311,7 @@ func (c *Candidates) GetCandidateByTendermintAddress(address types.TmAddress) *C } // RecalculateStakes recalculate stakes of all candidates: -// 1. Updates bip-value of each stake +// 1. Updates bip-unbounds of each stake // 2. Applies updates func (c *Candidates) RecalculateStakes(height uint64) { c.recalculateStakes(height) @@ -519,7 +519,7 @@ func (c *Candidates) SetOffline(pubkey types.Pubkey) { c.getFromMap(pubkey).setStatus(CandidateStatusOffline) } -// SubStake subs given value from delegator's stake +// SubStake subs given unbounds from delegator's stake func (c *Candidates) SubStake(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { stake := c.GetStakeOfAddress(pubkey, address, coin) stake.subValue(value) @@ -541,7 +541,7 @@ func (c *Candidates) GetTotalStake(pubkey types.Pubkey) *big.Int { candidate := c.getFromMap(pubkey) if candidate.totalBipStake == nil { path := []byte{mainPrefix} - path = append(path, pubkey[:]...) + path = append(path, candidate.idBytes()...) path = append(path, totalStakePrefix) _, enc := c.iavl.Get(path) if len(enc) == 0 { diff --git a/core/state/candidates/model.go b/core/state/candidates/model.go index 44f593559..aac97147e 100644 --- a/core/state/candidates/model.go +++ b/core/state/candidates/model.go @@ -101,8 +101,8 @@ func (candidate *Candidate) setTmAddress() { candidate.tmAddress = &address } -// GetFilteredUpdates returns updates which is > 0 in their value + merge similar updates -func (candidate *Candidate) GetFilteredUpdates() []*stake { +// getFilteredUpdates returns updates which is > 0 in their unbounds + merge similar updates +func (candidate *Candidate) getFilteredUpdates() []*stake { var updates []*stake for _, update := range candidate.updates { // skip updates with 0 stakes @@ -130,27 +130,7 @@ func (candidate *Candidate) GetFilteredUpdates() []*stake { // FilterUpdates filters candidate updates: remove 0-valued updates and merge similar ones func (candidate *Candidate) FilterUpdates() { - var updates []*stake - for _, update := range candidate.updates { - // skip updates with 0 stakes - if update.Value.Cmp(big.NewInt(0)) != 1 { - continue - } - - // merge updates - merged := false - for _, u := range updates { - if u.Coin == update.Coin && u.Owner == update.Owner { - u.Value.Add(u.Value, update.Value) - merged = true - break - } - } - - if !merged { - updates = append(updates, update) - } - } + updates := candidate.getFilteredUpdates() sort.SliceStable(updates, func(i, j int) bool { return updates[i].BipValue.Cmp(updates[j].BipValue) == 1 @@ -160,7 +140,7 @@ func (candidate *Candidate) FilterUpdates() { candidate.isUpdatesDirty = true } -// GetTotalBipStake returns total stake value of a candidate +// GetTotalBipStake returns total stake unbounds of a candidate func (candidate *Candidate) GetTotalBipStake() *big.Int { return big.NewInt(0).Set(candidate.totalBipStake) } From bcc53e2b0482f8fa72574d61ca097c808aa81fe1 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Tue, 8 Sep 2020 17:08:33 +0300 Subject: [PATCH 228/426] Move state unlock --- core/minter/minter.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index fa3489239..464ede06f 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -456,14 +456,14 @@ func (app *Blockchain) Commit() abciTypes.ResponseCommit { app.appDB.SetLastBlockHash(hash) app.appDB.SetLastHeight(app.height) + app.stateDeliver.Unlock() + // Resetting check state to be consistent with current height app.resetCheckState() // Clear mempool app.currentMempool = &sync.Map{} - app.stateDeliver.Unlock() - return abciTypes.ResponseCommit{ Data: hash, } From 62b09f9497d5adb249b88af5682c7eac68520552 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 8 Sep 2020 19:01:52 +0300 Subject: [PATCH 229/426] fix uses GetCoinBySymbol --- api/estimate_coin_buy.go | 4 ++-- api/estimate_coin_sell.go | 4 ++-- api/estimate_coin_sell_all.go | 4 ++-- api/v2/service/coin_info.go | 2 +- api/v2/service/estimate_coin_buy.go | 4 ++-- api/v2/service/estimate_coin_sell.go | 4 ++-- api/v2/service/estimate_coin_sell_all.go | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/api/estimate_coin_buy.go b/api/estimate_coin_buy.go index b43cdd602..6ffcd869f 100644 --- a/api/estimate_coin_buy.go +++ b/api/estimate_coin_buy.go @@ -26,12 +26,12 @@ func EstimateCoinBuy(coinToSell, coinToBuy string, valueToBuy *big.Int, height i cState.RLock() defer cState.RUnlock() - coinFrom := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToSell), 0) + coinFrom := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToSell), types.GetVersionFromSymbol(coinToSell)) if coinFrom == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to sell not exists"} } - coinTo := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToBuy), 0) + coinTo := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToBuy), types.GetVersionFromSymbol(coinToBuy)) if coinTo == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to buy not exists"} } diff --git a/api/estimate_coin_sell.go b/api/estimate_coin_sell.go index ac4296e7e..2709617b9 100644 --- a/api/estimate_coin_sell.go +++ b/api/estimate_coin_sell.go @@ -26,12 +26,12 @@ func EstimateCoinSell(coinToSell, coinToBuy string, valueToSell *big.Int, height cState.RLock() defer cState.RUnlock() - coinFrom := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToSell), 0) + coinFrom := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToSell), types.GetVersionFromSymbol(coinToSell)) if coinFrom == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to sell not exists"} } - coinTo := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToBuy), 0) + coinTo := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToBuy), types.GetVersionFromSymbol(coinToBuy)) if coinTo == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to buy not exists"} } diff --git a/api/estimate_coin_sell_all.go b/api/estimate_coin_sell_all.go index 513e1ef5b..3316b22bd 100644 --- a/api/estimate_coin_sell_all.go +++ b/api/estimate_coin_sell_all.go @@ -29,12 +29,12 @@ func EstimateCoinSellAll(coinToSell, coinToBuy string, valueToSell *big.Int, gas gasPrice = 1 } - coinFrom := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToSell), 0) + coinFrom := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToSell), types.GetVersionFromSymbol(coinToSell)) if coinFrom == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to sell not exists"} } - coinTo := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToBuy), 0) + coinTo := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToBuy), types.GetVersionFromSymbol(coinToBuy)) if coinTo == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to buy not exists"} } diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index c82dd96ec..0bad62686 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -24,7 +24,7 @@ func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.Co cState.RLock() defer cState.RUnlock() - coin := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.Symbol), 0) + coin := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.Symbol), types.GetVersionFromSymbol(req.Symbol)) if coin == nil { return new(pb.CoinInfoResponse), s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(map[string]string{ "code": strconv.Itoa(int(code.CoinNotExists)), diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index b6e6634ca..0353beeb0 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -28,7 +28,7 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe var coinToBuy types.CoinID if req.GetCoinToBuy() != "" { - symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), 0) + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), types.GetVersionFromSymbol(req.GetCoinToBuy())) if symbol == nil { return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ "code": strconv.Itoa(int(code.CoinNotExists)), @@ -48,7 +48,7 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe var coinToSell types.CoinID if req.GetCoinToSell() != "" { - symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), 0) + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), types.GetVersionFromSymbol(req.GetCoinToSell())) if symbol == nil { return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ "code": strconv.Itoa(int(code.CoinNotExists)), diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index eee095b7f..4fd9c9bfa 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -28,7 +28,7 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell var coinToBuy types.CoinID if req.GetCoinToBuy() != "" { - symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), 0) + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), types.GetVersionFromSymbol(req.GetCoinToBuy())) if symbol == nil { return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ "code": strconv.Itoa(int(code.CoinNotExists)), @@ -48,7 +48,7 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell var coinToSell types.CoinID if req.GetCoinToSell() != "" { - symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), 0) + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), types.GetVersionFromSymbol(req.GetCoinToSell())) if symbol == nil { return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ "code": strconv.Itoa(int(code.CoinNotExists)), diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index f567813d6..4969a389f 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -37,7 +37,7 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS var coinToBuy types.CoinID if req.GetCoinToBuy() != "" { - symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), 0) + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), types.GetVersionFromSymbol(req.GetCoinToBuy())) if symbol == nil { return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ "code": strconv.Itoa(int(code.CoinNotExists)), @@ -57,7 +57,7 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS var coinToSell types.CoinID if req.GetCoinToSell() != "" { - symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), 0) + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), types.GetVersionFromSymbol(req.GetCoinToSell())) if symbol == nil { return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ "code": strconv.Itoa(int(code.CoinNotExists)), From caaf1fdf6f38a4f5795dd77426965201417b233e Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 9 Sep 2020 11:09:44 +0300 Subject: [PATCH 230/426] add tests --- core/transaction/price_vote_test.go | 121 +++++++++ core/transaction/sell_all_coin_test.go | 240 ++++++++++++++++++ core/transaction/switch_candidate_status.go | 23 +- .../switch_candidate_status_test.go | 65 +++++ 4 files changed, 429 insertions(+), 20 deletions(-) create mode 100644 core/transaction/price_vote_test.go diff --git a/core/transaction/price_vote_test.go b/core/transaction/price_vote_test.go new file mode 100644 index 000000000..2dc4d6137 --- /dev/null +++ b/core/transaction/price_vote_test.go @@ -0,0 +1,121 @@ +package transaction + +import ( + "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/helpers" + "github.com/MinterTeam/minter-go-node/rlp" + "math/big" + "sync" + "testing" +) + +func TestPriceVoteTx(t *testing.T) { + cState := getState() + privateKey, addr := getAccount() + + cState.Accounts.AddBalance(addr, types.GetBaseCoinID(), big.NewInt(1e18)) + + data := PriceVoteData{Price: 1} + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypePriceVote, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != 0 { + t.Fatalf("Response code is not 0. Error: %s", response.Log) + } +} + +func TestPriceVoteTxToInsufficientFunds(t *testing.T) { + cState := getState() + privateKey, _ := getAccount() + + data := PriceVoteData{Price: 1} + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypePriceVote, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error: %s", code.InsufficientFunds, response.Log) + } +} + +func TestPriceVoteTxToCoinReserveUnderflow(t *testing.T) { + cState := getState() + customCoin := createTestCoin(cState) + privateKey, _ := getAccount() + + cState.Coins.SubReserve(customCoin, helpers.BipToPip(big.NewInt(90000))) + + data := PriceVoteData{Price: 1} + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: customCoin, + Type: TypePriceVote, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveUnderflow { + t.Fatalf("Response code is not %d. Error: %s", code.CoinReserveUnderflow, response.Log) + } +} diff --git a/core/transaction/sell_all_coin_test.go b/core/transaction/sell_all_coin_test.go index 0048a73eb..9208694ff 100644 --- a/core/transaction/sell_all_coin_test.go +++ b/core/transaction/sell_all_coin_test.go @@ -278,4 +278,244 @@ func TestSellAllCoinTxWithInsufficientFunds(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + cState.Coins.Create( + cState.App.GetNextCoinID(), + types.StrToCoinSymbol("TEST9"), + "TEST COIN", + helpers.BipToPip(big.NewInt(100000)), + 10, + helpers.BipToPip(big.NewInt(100000)), + helpers.BipToPip(big.NewInt(1000000)), + nil, + ) + + coinToSellID := cState.App.GetNextCoinID() + cState.App.SetCoinsCount(coinToSellID.Uint32()) + + cState.Accounts.AddBalance(addr, coinToSellID, big.NewInt(1)) + + data.CoinToBuy = coinID + data.CoinToSell = coinToSellID + data.MinimumValueToBuy = big.NewInt(9e18) + + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + panic(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} + +func TestSellAllCoinTxToCoinSupplyOverflow(t *testing.T) { + cState := getState() + privateKey, addr := getAccount() + coinToBuyID, sellCoinID := createTestCoin(cState), types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, sellCoinID, helpers.BipToPip(big.NewInt(100))) + + coinToBuy := cState.Coins.GetCoin(coinToBuyID) + coinToBuy.CMaxSupply = big.NewInt(1) + + data := SellAllCoinData{ + CoinToSell: sellCoinID, + CoinToBuy: coinToBuyID, + MinimumValueToBuy: big.NewInt(0), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: data.CoinToSell, + Type: TypeSellAllCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinSupplyOverflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinSupplyOverflow, response.Log) + } + + // custom buy and sell coins + + cState.Coins.Create( + cState.App.GetNextCoinID(), + types.StrToCoinSymbol("TEST9"), + "TEST COIN", + helpers.BipToPip(big.NewInt(100000)), + 10, + helpers.BipToPip(big.NewInt(100000)), + helpers.BipToPip(big.NewInt(1000000)), + nil, + ) + + coinToSellID := cState.App.GetNextCoinID() + cState.App.SetCoinsCount(coinToSellID.Uint32()) + + cState.Accounts.AddBalance(addr, coinToSellID, helpers.BipToPip(big.NewInt(90))) + + data.CoinToBuy = coinToBuyID + data.CoinToSell = coinToSellID + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx.GasCoin = coinToSellID + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinSupplyOverflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinSupplyOverflow, response.Log) + } +} + +func TestSellAllCoinTxToMinimumValueToBuyReached(t *testing.T) { + cState := getState() + privateKey, addr := getAccount() + coinToBuyID, sellCoinID := createTestCoin(cState), types.GetBaseCoinID() + + cState.Accounts.AddBalance(addr, sellCoinID, helpers.BipToPip(big.NewInt(2))) + + data := SellAllCoinData{ + CoinToBuy: coinToBuyID, + CoinToSell: sellCoinID, + MinimumValueToBuy: big.NewInt(9e18), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + panic(err) + } + + tx := &Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: sellCoinID, + Type: TypeSellAllCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + decodedData: data, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.MinimumValueToBuyReached { + t.Fatalf("Response code is not %d. Error %s", code.MinimumValueToBuyReached, response.Log) + } + + // coin to buy == base coin + + cState.Accounts.AddBalance(addr, coinToBuyID, big.NewInt(1)) + + data.CoinToBuy = sellCoinID + data.CoinToSell = coinToBuyID + data.MinimumValueToBuy = big.NewInt(9e18) + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + panic(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.MinimumValueToBuyReached { + t.Fatalf("Response code is not %d. Error %s", code.MinimumValueToBuyReached, response.Log) + } + + // custom buy and sell coins + + cState.Coins.Create( + cState.App.GetNextCoinID(), + types.StrToCoinSymbol("TEST9"), + "TEST COIN", + helpers.BipToPip(big.NewInt(100000)), + 10, + helpers.BipToPip(big.NewInt(100000)), + helpers.BipToPip(big.NewInt(1000000)), + nil, + ) + + coinToSellID := cState.App.GetNextCoinID() + cState.App.SetCoinsCount(coinToSellID.Uint32()) + + cState.Accounts.AddBalance(addr, coinToSellID, big.NewInt(1e17)) + + data.CoinToBuy = coinToBuyID + data.CoinToSell = coinToSellID + data.MinimumValueToBuy = big.NewInt(9e18) + + encodedData, err = rlp.EncodeToBytes(data) + if err != nil { + panic(err) + } + + tx.Data = encodedData + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.MinimumValueToBuyReached { + t.Fatalf("Response code is not %d. Error %s", code.MinimumValueToBuyReached, response.Log) + } } diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index 2156f9251..49d21c126 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -2,7 +2,6 @@ package transaction import ( "encoding/hex" - "encoding/json" "fmt" "math/big" "strconv" @@ -107,14 +106,6 @@ type SetCandidateOffData struct { PubKey types.Pubkey `json:"pub_key"` } -func (data SetCandidateOffData) MarshalJSON() ([]byte, error) { - return json.Marshal(struct { - PubKey string `json:"pub_key"` - }{ - PubKey: data.PubKey.String(), - }) -} - func (data SetCandidateOffData) GetPubKey() types.Pubkey { return data.PubKey } @@ -152,17 +143,9 @@ func (data SetCandidateOffData) Run(tx *Transaction, context state.Interface, re if !tx.GasCoin.IsBaseCoin() { coin := checkState.Coins().GetCoin(tx.GasCoin) - if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return Response{ - Code: code.CoinReserveNotSufficient, - Log: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_value": coin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin": coin.CName, - }), - } + errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) + if errResp != nil { + return *errResp } commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) diff --git a/core/transaction/switch_candidate_status_test.go b/core/transaction/switch_candidate_status_test.go index 3349ce78d..0b68f4427 100644 --- a/core/transaction/switch_candidate_status_test.go +++ b/core/transaction/switch_candidate_status_test.go @@ -325,4 +325,69 @@ func TestSwitchCandidateStatusToInsufficientFundsForGas(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + cState.Candidates.SetOnline(pubkey) + + tx.Type = TypeSetCandidateOffline + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} + +func TestSwitchCandidateStatusToCoinReserveUnderflow(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := createTestCoin(cState) + + pubkey := types.Pubkey{} + rand.Read(pubkey[:]) + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + cState.Candidates.SetOnline(pubkey) + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(100000))) + + data := SetCandidateOffData{ + PubKey: pubkey, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSetCandidateOffline, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveUnderflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) + } } From 036864cdcf91132e2dd70f7ed9cc2844841333fa Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 9 Sep 2020 11:16:47 +0300 Subject: [PATCH 231/426] redeem check tx test --- core/transaction/redeem_check_test.go | 97 ++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 2 deletions(-) diff --git a/core/transaction/redeem_check_test.go b/core/transaction/redeem_check_test.go index 17a4f6281..fc4869f0b 100644 --- a/core/transaction/redeem_check_test.go +++ b/core/transaction/redeem_check_test.go @@ -342,7 +342,7 @@ func TestRedeemCheckTxToWrongChainID(t *testing.T) { check := c.Check{ Nonce: []byte{1, 2, 3}, - ChainID: types.ChainMainnet, + ChainID: types.ChainTestnet, DueBlock: 1, Coin: coin, Value: checkValue, @@ -391,7 +391,7 @@ func TestRedeemCheckTxToWrongChainID(t *testing.T) { tx := Transaction{ Nonce: 1, GasPrice: 1, - ChainID: types.ChainTestnet, + ChainID: types.CurrentChainID, GasCoin: coin, Type: TypeRedeemCheck, Data: encodedData, @@ -898,3 +898,96 @@ func TestRedeemCheckTxToInsufficientFunds(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } } + +func TestRedeemCheckTxToCoinReserveUnderflow(t *testing.T) { + cState := getState() + coin := createTestCoin(cState) + cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) + + senderPrivateKey, _ := crypto.GenerateKey() + + receiverPrivateKey, _ := crypto.GenerateKey() + receiverAddr := crypto.PubkeyToAddress(receiverPrivateKey.PublicKey) + + passphrase := "password" + passphraseHash := sha256.Sum256([]byte(passphrase)) + passphrasePk, err := crypto.ToECDSA(passphraseHash[:]) + + if err != nil { + t.Fatal(err) + } + + checkValue := helpers.BipToPip(big.NewInt(10)) + + check := c.Check{ + Nonce: []byte{1, 2, 3}, + ChainID: types.CurrentChainID, + DueBlock: 1, + Coin: coin, + Value: checkValue, + GasCoin: coin, + } + + lock, err := crypto.Sign(check.HashWithoutLock().Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + check.Lock = big.NewInt(0).SetBytes(lock) + + err = check.Sign(senderPrivateKey) + if err != nil { + t.Fatal(err) + } + + rawCheck, _ := rlp.EncodeToBytes(check) + + var senderAddressHash types.Hash + hw := sha3.NewKeccak256() + _ = rlp.Encode(hw, []interface{}{ + receiverAddr, + }) + hw.Sum(senderAddressHash[:0]) + + sig, err := crypto.Sign(senderAddressHash.Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + proof := [65]byte{} + copy(proof[:], sig) + + data := RedeemCheckData{ + RawCheck: rawCheck, + Proof: proof, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeRedeemCheck, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(receiverPrivateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveUnderflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) + } +} From 33f5e808ab1fafcd626d572d17282fe1896c0691 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 9 Sep 2020 11:36:45 +0300 Subject: [PATCH 232/426] tests --- core/transaction/decoder_test.go | 120 +++++++++++++++++ core/transaction/redeem_check_test.go | 186 ++++++++++++++++++++++++++ 2 files changed, 306 insertions(+) create mode 100644 core/transaction/decoder_test.go diff --git a/core/transaction/decoder_test.go b/core/transaction/decoder_test.go new file mode 100644 index 000000000..15eb56ff2 --- /dev/null +++ b/core/transaction/decoder_test.go @@ -0,0 +1,120 @@ +package transaction + +import ( + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/rlp" + "math/big" + "testing" +) + +func TestDecodeFromBytesToInvalidSignature(t *testing.T) { + data := SendData{Coin: 0, To: types.Address{0}, Value: big.NewInt(0)} + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeSend, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + _, err = TxDecoder.DecodeFromBytes(encodedTx) + if err == nil { + t.Fatal("Expected the invalid signature error") + } +} + +func TestDecodeSigToInvalidMultiSignature(t *testing.T) { + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeSend, + Data: nil, + SignatureType: SigTypeMulti, + } + + _, err := DecodeSig(&tx) + if err == nil { + t.Fatal("Expected the invalid signature error") + } +} + +func TestDecodeSigToInvalidSingleSignature(t *testing.T) { + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeSend, + Data: nil, + SignatureType: SigTypeSingle, + } + + _, err := DecodeSig(&tx) + if err == nil { + t.Fatal("Expected the invalid signature error") + } +} + +func TestDecodeSigToUnknownSignatureType(t *testing.T) { + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeSend, + Data: nil, + SignatureType: 0x03, + } + + _, err := DecodeSig(&tx) + if err == nil { + t.Fatal("Expected unknown signature type error") + } +} + +func TestDecodeFromBytesWithoutSigToInvalidData(t *testing.T) { + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: 0x20, + Data: nil, + SignatureType: SigTypeSingle, + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + _, err = TxDecoder.DecodeFromBytesWithoutSig(encodedTx) + if err == nil { + t.Fatal("Expected tx type is not registered error") + } + + tx.Type = TypeSend + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + _, err = TxDecoder.DecodeFromBytesWithoutSig(encodedTx) + if err == nil { + t.Fatal("Expected invalid data error") + } +} diff --git a/core/transaction/redeem_check_test.go b/core/transaction/redeem_check_test.go index fc4869f0b..f18f8e6cb 100644 --- a/core/transaction/redeem_check_test.go +++ b/core/transaction/redeem_check_test.go @@ -991,3 +991,189 @@ func TestRedeemCheckTxToCoinReserveUnderflow(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } } + +func TestRedeemCheckTxToInsufficientFundsForCheckCoin(t *testing.T) { + cState := getState() + coin := createTestCoin(cState) + + senderPrivateKey, _ := crypto.GenerateKey() + + receiverPrivateKey, _ := crypto.GenerateKey() + receiverAddr := crypto.PubkeyToAddress(receiverPrivateKey.PublicKey) + + passphrase := "password" + passphraseHash := sha256.Sum256([]byte(passphrase)) + passphrasePk, err := crypto.ToECDSA(passphraseHash[:]) + + if err != nil { + t.Fatal(err) + } + + checkValue := helpers.BipToPip(big.NewInt(10)) + + check := c.Check{ + Nonce: []byte{1, 2, 3}, + ChainID: types.CurrentChainID, + DueBlock: 1, + Coin: coin, + Value: checkValue, + GasCoin: types.GetBaseCoinID(), + } + + lock, err := crypto.Sign(check.HashWithoutLock().Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + check.Lock = big.NewInt(0).SetBytes(lock) + + err = check.Sign(senderPrivateKey) + if err != nil { + t.Fatal(err) + } + + rawCheck, _ := rlp.EncodeToBytes(check) + + var senderAddressHash types.Hash + hw := sha3.NewKeccak256() + _ = rlp.Encode(hw, []interface{}{ + receiverAddr, + }) + hw.Sum(senderAddressHash[:0]) + + sig, err := crypto.Sign(senderAddressHash.Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + proof := [65]byte{} + copy(proof[:], sig) + + data := RedeemCheckData{ + RawCheck: rawCheck, + Proof: proof, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeRedeemCheck, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(receiverPrivateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} + +func TestRedeemCheckTxToInsufficientFundsForCheckGasCoin(t *testing.T) { + cState := getState() + coin := createTestCoin(cState) + + senderPrivateKey, senderAddr := getAccount() + + receiverPrivateKey, _ := crypto.GenerateKey() + receiverAddr := crypto.PubkeyToAddress(receiverPrivateKey.PublicKey) + + passphrase := "password" + passphraseHash := sha256.Sum256([]byte(passphrase)) + passphrasePk, err := crypto.ToECDSA(passphraseHash[:]) + + cState.Accounts.AddBalance(senderAddr, coin, helpers.BipToPip(big.NewInt(100))) + + if err != nil { + t.Fatal(err) + } + + checkValue := helpers.BipToPip(big.NewInt(10)) + + check := c.Check{ + Nonce: []byte{1, 2, 3}, + ChainID: types.CurrentChainID, + DueBlock: 1, + Coin: coin, + Value: checkValue, + GasCoin: types.GetBaseCoinID(), + } + + lock, err := crypto.Sign(check.HashWithoutLock().Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + check.Lock = big.NewInt(0).SetBytes(lock) + + err = check.Sign(senderPrivateKey) + if err != nil { + t.Fatal(err) + } + + rawCheck, _ := rlp.EncodeToBytes(check) + + var senderAddressHash types.Hash + hw := sha3.NewKeccak256() + _ = rlp.Encode(hw, []interface{}{ + receiverAddr, + }) + hw.Sum(senderAddressHash[:0]) + + sig, err := crypto.Sign(senderAddressHash.Bytes(), passphrasePk) + if err != nil { + t.Fatal(err) + } + + proof := [65]byte{} + copy(proof[:], sig) + + data := RedeemCheckData{ + RawCheck: rawCheck, + Proof: proof, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: TypeRedeemCheck, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(receiverPrivateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} From bdc0aaa902a377bfc41cbb3f45fc3ae14b9214c5 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 9 Sep 2020 11:40:20 +0300 Subject: [PATCH 233/426] fix coin info api --- core/state/coins/coins.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index 342844c09..c8fd05539 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -129,6 +129,10 @@ func (c *Coins) ExistsBySymbol(symbol types.CoinSymbol) bool { } func (c *Coins) GetCoinBySymbol(symbol types.CoinSymbol, version types.CoinVersion) *Model { + if symbol.IsBaseCoin() { + return c.get(types.GetBaseCoinID()) + } + coins := c.getBySymbol(symbol) if len(coins) == 0 { return nil From 4a92c6eee539e3a79d6ab6dce5388c05a540f5a4 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 9 Sep 2020 12:56:38 +0300 Subject: [PATCH 234/426] Update resources: fix linter errors and remove multisig address from editMultisigOwners tx --- core/transaction/encoder/resources.go | 85 ++++++++++++++------------- 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/core/transaction/encoder/resources.go b/core/transaction/encoder/resources.go index 59024c9b8..b93275ca9 100644 --- a/core/transaction/encoder/resources.go +++ b/core/transaction/encoder/resources.go @@ -9,23 +9,25 @@ import ( "github.com/MinterTeam/minter-go-node/core/types" ) +// TxDataResource is an interface for preparing JSON representation of TxData type TxDataResource interface { Transform(txData interface{}, context *state.CheckState) TxDataResource } +// CoinResource is a JSON representation of a coin type CoinResource struct { ID uint32 `json:"id"` Symbol string `json:"symbol"` } -// TxType 0x01 - +// SendDataResource is JSON representation of TxType 0x01 type SendDataResource struct { Coin CoinResource `json:"coin"` To string `json:"to"` Value string `json:"value"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (SendDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.SendData) coin := context.Coins().GetCoin(data.Coin) @@ -37,8 +39,7 @@ func (SendDataResource) Transform(txData interface{}, context *state.CheckState) } } -// TxType 0x02 - +// SellCoinDataResource is JSON representation of TxType 0x02 type SellCoinDataResource struct { CoinToSell CoinResource `json:"coin_to_sell"` ValueToSell string `json:"value_to_sell"` @@ -46,6 +47,7 @@ type SellCoinDataResource struct { MinimumValueToBuy string `json:"minimum_value_to_buy"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (SellCoinDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.SellCoinData) buyCoin := context.Coins().GetCoin(data.CoinToBuy) @@ -59,14 +61,14 @@ func (SellCoinDataResource) Transform(txData interface{}, context *state.CheckSt } } -// TxType 0x03 - +// SellAllCoinDataResource is JSON representation of TxType 0x03 type SellAllCoinDataResource struct { CoinToSell CoinResource `json:"coin_to_sell"` CoinToBuy CoinResource `json:"coin_to_buy"` MinimumValueToBuy string `json:"minimum_value_to_buy"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (SellAllCoinDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.SellAllCoinData) buyCoin := context.Coins().GetCoin(data.CoinToBuy) @@ -79,8 +81,7 @@ func (SellAllCoinDataResource) Transform(txData interface{}, context *state.Chec } } -// TxType 0x04 - +// BuyCoinDataResource is JSON representation of TxType 0x04 type BuyCoinDataResource struct { CoinToBuy CoinResource `json:"coin_to_buy"` ValueToBuy string `json:"value_to_buy"` @@ -88,6 +89,7 @@ type BuyCoinDataResource struct { MaximumValueToSell string `json:"maximum_value_to_sell"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (BuyCoinDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.BuyCoinData) buyCoin := context.Coins().GetCoin(data.CoinToBuy) @@ -101,8 +103,7 @@ func (BuyCoinDataResource) Transform(txData interface{}, context *state.CheckSta } } -// TxType 0x05 - +// CreateCoinDataResource is JSON representation of TxType 0x05 type CreateCoinDataResource struct { Name string `json:"name"` Symbol string `json:"symbol"` @@ -112,6 +113,7 @@ type CreateCoinDataResource struct { MaxSupply string `json:"max_supply"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (CreateCoinDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.CreateCoinData) @@ -125,8 +127,7 @@ func (CreateCoinDataResource) Transform(txData interface{}, context *state.Check } } -// TxType 0x06 - +// DeclareCandidacyDataResource is JSON representation of TxType 0x06 type DeclareCandidacyDataResource struct { Address string `json:"address"` PubKey string `json:"pub_key"` @@ -135,6 +136,7 @@ type DeclareCandidacyDataResource struct { Stake string `json:"stake"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (DeclareCandidacyDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.DeclareCandidacyData) coin := context.Coins().GetCoin(data.Coin) @@ -148,14 +150,14 @@ func (DeclareCandidacyDataResource) Transform(txData interface{}, context *state } } -// TxType 0x07 - +// DelegateDataResource is JSON representation of TxType 0x07 type DelegateDataResource struct { PubKey string `json:"pub_key"` Coin CoinResource `json:"coin"` Value string `json:"value"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (DelegateDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.DelegateData) coin := context.Coins().GetCoin(data.Coin) @@ -167,14 +169,14 @@ func (DelegateDataResource) Transform(txData interface{}, context *state.CheckSt } } -// TxType 0x08 - +// UnbondDataResource is JSON representation of TxType 0x08 type UnbondDataResource struct { PubKey string `json:"pub_key"` Coin CoinResource `json:"coin"` Value string `json:"value"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (UnbondDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.UnbondData) coin := context.Coins().GetCoin(data.Coin) @@ -186,13 +188,13 @@ func (UnbondDataResource) Transform(txData interface{}, context *state.CheckStat } } -// TxType 0x09 - +// RedeemCheckDataResource is JSON representation of TxType 0x09 type RedeemCheckDataResource struct { RawCheck string `json:"raw_check"` Proof string `json:"proof"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (RedeemCheckDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.RedeemCheckData) @@ -202,36 +204,36 @@ func (RedeemCheckDataResource) Transform(txData interface{}, context *state.Chec } } -// TxType 0x0A - +// SetCandidateOnDataResource is JSON representation of TxType 0x0A type SetCandidateOnDataResource struct { PubKey string `json:"pub_key"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (SetCandidateOnDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.SetCandidateOnData) return SetCandidateOnDataResource{data.PubKey.String()} } -// TxType 0x0B - +// SetCandidateOffDataResource is JSON representation of TxType 0x0B type SetCandidateOffDataResource struct { PubKey string `json:"pub_key"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (SetCandidateOffDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.SetCandidateOffData) return SetCandidateOffDataResource{data.PubKey.String()} } -// TxType 0x0C - +// CreateMultisigDataResource is JSON representation of TxType 0x0C type CreateMultisigDataResource struct { Threshold string `json:"threshold"` Weights []string `json:"weights"` Addresses []types.Address `json:"addresses"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (CreateMultisigDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.CreateMultisigData) @@ -247,12 +249,12 @@ func (CreateMultisigDataResource) Transform(txData interface{}, context *state.C } } -// TxType 0x0D - +// MultiSendDataResource is JSON representation of TxType 0x0D type MultiSendDataResource struct { List []SendDataResource `json:"list"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (resource MultiSendDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.MultisendData) @@ -269,8 +271,7 @@ func (resource MultiSendDataResource) Transform(txData interface{}, context *sta return resource } -// TxType 0x0E - +// EditCandidateDataResource is JSON representation of TxType 0x0E type EditCandidateDataResource struct { PubKey string `json:"pub_key"` NewPubKey *string `json:"new_pub_key"` @@ -279,6 +280,7 @@ type EditCandidateDataResource struct { ControlAddress string `json:"control_address"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (EditCandidateDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.EditCandidateData) var newPubKeyStr *string @@ -295,13 +297,13 @@ func (EditCandidateDataResource) Transform(txData interface{}, context *state.Ch } } -// TxType 0x0F - +// SetHaltBlockDataResource is JSON representation of TxType 0x0F type SetHaltBlockDataResource struct { PubKey string `json:"pub_key"` Height string `json:"height"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (SetHaltBlockDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.SetHaltBlockData) @@ -311,8 +313,7 @@ func (SetHaltBlockDataResource) Transform(txData interface{}, context *state.Che } } -// TxType 0x10 - +// RecreateCoinDataResource is JSON representation of TxType 0x10 type RecreateCoinDataResource struct { Name string `json:"name"` Symbol types.CoinSymbol `json:"symbol"` @@ -322,6 +323,7 @@ type RecreateCoinDataResource struct { MaxSupply string `json:"max_supply"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (RecreateCoinDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.RecreateCoinData) @@ -335,13 +337,13 @@ func (RecreateCoinDataResource) Transform(txData interface{}, context *state.Che } } -// TxType 0x11 - +// ChangeCoinOwnerDataResource is JSON representation of TxType 0x11 type ChangeCoinOwnerDataResource struct { Symbol types.CoinSymbol `json:"symbol"` NewOwner types.Address `json:"new_owner"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (ChangeCoinOwnerDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.ChangeCoinOwnerData) @@ -351,15 +353,14 @@ func (ChangeCoinOwnerDataResource) Transform(txData interface{}, context *state. } } -// TxType 0x12 - +// EditMultisigOwnersResource is JSON representation of TxType 0x12 type EditMultisigOwnersResource struct { - MultisigAddress types.Address `json:"multisig_address"` - Threshold string `json:"threshold"` - Weights []string `json:"weights"` - Addresses []types.Address `json:"addresses"` + Threshold string `json:"threshold"` + Weights []string `json:"weights"` + Addresses []types.Address `json:"addresses"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (EditMultisigOwnersResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.EditMultisigOwnersData) @@ -376,12 +377,12 @@ func (EditMultisigOwnersResource) Transform(txData interface{}, context *state.C return resource } -// TxType 0x13 - +// PriceVoteResource is JSON representation of TxType 0x13 type PriceVoteResource struct { Price uint32 `json:"price"` } +// Transform returns TxDataResource from given txData. Used for JSON encoder. func (PriceVoteResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.PriceVoteData) From f2538a9a707daa24ce75ee9273d9b67432dad488 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 9 Sep 2020 13:18:56 +0300 Subject: [PATCH 235/426] Fix linter errors --- config/config.go | 7 ++++++- formula/formula.go | 18 ++++++++++-------- helpers/helpers.go | 3 +++ hexutil/hexutil.go | 1 + log/log.go | 1 + upgrades/blocks.go | 22 +++++++++++----------- version/version.go | 6 +----- 7 files changed, 33 insertions(+), 25 deletions(-) diff --git a/config/config.go b/config/config.go index 9e00a7623..b142ce6ae 100644 --- a/config/config.go +++ b/config/config.go @@ -34,6 +34,7 @@ var ( defaultNodeKeyPath = filepath.Join(defaultConfigDir, defaultNodeKeyName) ) +// DefaultConfig returns config with predefined values func DefaultConfig() *Config { cfg := defaultConfig() @@ -74,6 +75,7 @@ func DefaultConfig() *Config { return cfg } +// GetConfig returns DefaultConfig with some changes func GetConfig() *Config { cfg := DefaultConfig() @@ -132,6 +134,7 @@ func (cfg *Config) SetRoot(root string) *Config { return cfg } +// GetTmConfig composes and returns config for Tendermint engine based on given Minter config func GetTmConfig(cfg *Config) *tmConfig.Config { return &tmConfig.Config{ BaseConfig: tmConfig.BaseConfig{ @@ -279,6 +282,7 @@ func DefaultBaseConfig() BaseConfig { } } +// ChainID returns the id of a chain func (cfg BaseConfig) ChainID() string { return cfg.chainID } @@ -288,7 +292,7 @@ func (cfg BaseConfig) GenesisFile() string { return rootify(cfg.Genesis, cfg.RootDir) } -// PrivValidatorFile returns the full path to the priv_validator.json file +// PrivValidatorStateFile returns the full path to the priv_validator_state.json file func (cfg BaseConfig) PrivValidatorStateFile() string { return rootify(cfg.PrivValidatorState, cfg.RootDir) } @@ -298,6 +302,7 @@ func (cfg BaseConfig) NodeKeyFile() string { return rootify(cfg.NodeKey, cfg.RootDir) } +// PrivValidatorKeyFile returns the full path to the priv_validator.json file func (cfg BaseConfig) PrivValidatorKeyFile() string { return rootify(cfg.PrivValidatorKey, cfg.RootDir) } diff --git a/formula/formula.go b/formula/formula.go index 404ea0251..a703e1dd3 100644 --- a/formula/formula.go +++ b/formula/formula.go @@ -10,10 +10,7 @@ const ( precision = 100 ) -func newFloat(x float64) *big.Float { - return big.NewFloat(x).SetPrec(precision) -} - +// CalculatePurchaseReturn calculates amount of coin that user will receive by depositing given amount of BIP // Return = supply * ((1 + deposit / reserve) ^ (crr / 100) - 1) func CalculatePurchaseReturn(supply *big.Int, reserve *big.Int, crr uint, deposit *big.Int) *big.Int { if deposit.Cmp(types.Big0) == 0 { @@ -41,8 +38,8 @@ func CalculatePurchaseReturn(supply *big.Int, reserve *big.Int, crr uint, deposi return result } -// reversed function CalculatePurchaseReturn -// deposit = reserve * (((wantReceive + supply) / supply)^(100/c) - 1) +// CalculatePurchaseAmount is the reversed version of function CalculatePurchaseReturn +// Deposit = reserve * (((wantReceive + supply) / supply)^(100/c) - 1) func CalculatePurchaseAmount(supply *big.Int, reserve *big.Int, crr uint, wantReceive *big.Int) *big.Int { if wantReceive.Cmp(types.Big0) == 0 { return big.NewInt(0) @@ -69,6 +66,7 @@ func CalculatePurchaseAmount(supply *big.Int, reserve *big.Int, crr uint, wantRe return result } +// CalculateSaleReturn returns amount of BIP user will receive by depositing given amount of coins // Return = reserve * (1 - (1 - sellAmount / supply) ^ (100 / crr)) func CalculateSaleReturn(supply *big.Int, reserve *big.Int, crr uint, sellAmount *big.Int) *big.Int { // special case for 0 sell amount @@ -103,8 +101,8 @@ func CalculateSaleReturn(supply *big.Int, reserve *big.Int, crr uint, sellAmount return result } -// reversed function CalculateSaleReturn -// -(-1 + (-(wantReceive - reserve)/reserve)^(1/crr)) * supply +// CalculateSaleAmount is the reversed version of function CalculateSaleReturn +// Deposit = -(-1 + (-(wantReceive - reserve)/reserve)^(1/crr)) * supply func CalculateSaleAmount(supply *big.Int, reserve *big.Int, crr uint, wantReceive *big.Int) *big.Int { if wantReceive.Cmp(types.Big0) == 0 { return big.NewInt(0) @@ -133,3 +131,7 @@ func CalculateSaleAmount(supply *big.Int, reserve *big.Int, crr uint, wantReceiv return result } + +func newFloat(x float64) *big.Float { + return big.NewFloat(x).SetPrec(precision) +} diff --git a/helpers/helpers.go b/helpers/helpers.go index 61e23ad86..06d95f54b 100644 --- a/helpers/helpers.go +++ b/helpers/helpers.go @@ -5,6 +5,7 @@ import ( "math/big" ) +// BipToPip converts BIP to PIP (multiplies input by 1e18) func BipToPip(bip *big.Int) *big.Int { p := big.NewInt(10) p.Exp(p, big.NewInt(18), nil) @@ -13,6 +14,7 @@ func BipToPip(bip *big.Int) *big.Int { return p } +// StringToBigInt converts string to BigInt, panics on empty strings and errors func StringToBigInt(s string) *big.Int { if s == "" { panic("string is empty") @@ -26,6 +28,7 @@ func StringToBigInt(s string) *big.Int { return b } +// IsValidBigInt verifies that string is a valid int func IsValidBigInt(s string) bool { if s == "" { return false diff --git a/hexutil/hexutil.go b/hexutil/hexutil.go index bd1f0e9b5..b92397c68 100644 --- a/hexutil/hexutil.go +++ b/hexutil/hexutil.go @@ -39,6 +39,7 @@ import ( const uintBits = 32 << (uint64(^uint(0)) >> 63) +// Error set var ( ErrEmptyString = &decError{"empty hex string"} ErrSyntax = &decError{"invalid hex string"} diff --git a/log/log.go b/log/log.go index 5535e8f07..b5bd9410f 100644 --- a/log/log.go +++ b/log/log.go @@ -8,6 +8,7 @@ import ( "os" ) +// NewLogger returns a logger based on given config func NewLogger(cfg *config.Config) log.Logger { var dest io.Writer = os.Stdout diff --git a/upgrades/blocks.go b/upgrades/blocks.go index ab69c57dc..6aad29a9b 100644 --- a/upgrades/blocks.go +++ b/upgrades/blocks.go @@ -1,13 +1,13 @@ package upgrades -func IsUpgradeBlock(height uint64) bool { - upgradeBlocks := []uint64{} // fill this - - for _, block := range upgradeBlocks { - if height == block { - return true - } - } - - return false -} +//func IsUpgradeBlock(height uint64) bool { +// upgradeBlocks := []uint64{} // fill this +// +// for _, block := range upgradeBlocks { +// if height == block { +// return true +// } +// } +// +// return false +//} diff --git a/version/version.go b/version/version.go index ae573008b..4b4e95d98 100755 --- a/version/version.go +++ b/version/version.go @@ -2,15 +2,11 @@ package version // Version components const ( - Maj = "1" - Min = "2" - Fix = "0" - AppVer = 7 ) var ( - // Must be a string because scripts like dist.sh read this file. + // Version must be a string because scripts like dist.sh read this file. Version = "1.2.0" // GitCommit is the current HEAD set using ldflags. From 1bd8d13b98b5a15544c89bf4c23ef7f24a7f47db Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 9 Sep 2020 15:09:35 +0300 Subject: [PATCH 236/426] Fix linter errors --- rlp/decode.go | 1 + tree/tree.go | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/rlp/decode.go b/rlp/decode.go index 5676bed6d..8eaab8bdd 100644 --- a/rlp/decode.go +++ b/rlp/decode.go @@ -28,6 +28,7 @@ import ( "strings" ) +// Set of Errors var ( // EOL is returned when the end of the current list // has been reached during streaming. diff --git a/tree/tree.go b/tree/tree.go index 9fd68f5b5..d59fab804 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -6,6 +6,7 @@ import ( "sync" ) +// ReadOnlyTree used for CheckState: API and CheckTx calls. Immutable. type ReadOnlyTree interface { Get(key []byte) (index int64, value []byte) Version() int64 @@ -13,6 +14,7 @@ type ReadOnlyTree interface { Iterate(fn func(key []byte, value []byte) bool) (stopped bool) } +// MTree mutable tree, used for txs delivery type MTree interface { ReadOnlyTree KeepLastHeight() int64 @@ -30,6 +32,7 @@ type MTree interface { GlobalUnlock() } +// NewMutableTree creates and returns new MutableTree using given db. Panics on error. // If you want to get read-only state, you should use height = 0 and LazyLoadVersion (version), see NewImmutableTree func NewMutableTree(height uint64, db dbm.DB, cacheSize int) MTree { tree, err := iavl.NewMutableTree(db, cacheSize) @@ -201,11 +204,13 @@ func (t *mutableTree) AvailableVersions() []int { return t.tree.AvailableVersions() } +// ImmutableTree used for CheckState: API and CheckTx calls. type ImmutableTree struct { tree *iavl.ImmutableTree } -//Warning: returns the MTree interface, but you should only use ReadOnlyTree +// NewImmutableTree returns MTree from given db at given height +// Warning: returns the MTree interface, but you should only use ReadOnlyTree func NewImmutableTree(height uint64, db dbm.DB) MTree { tree := NewMutableTree(0, db, 1024) _, err := tree.LazyLoadVersion(int64(height)) @@ -215,18 +220,25 @@ func NewImmutableTree(height uint64, db dbm.DB) MTree { return tree } +// Iterate iterates over all keys of the tree, in order. The keys and values must not be modified, +// since they may point to data stored within IAVL. func (t *ImmutableTree) Iterate(fn func(key []byte, value []byte) bool) (stopped bool) { return t.tree.Iterate(fn) } +// Hash returns the root hash. func (t *ImmutableTree) Hash() []byte { return t.tree.Hash() } +// Version returns the version of the tree. func (t *ImmutableTree) Version() int64 { return t.tree.Version() } +// Get returns the index and value of the specified key if it exists, or nil and the next index +// otherwise. The returned value must not be modified, since it may point to data stored within +// IAVL. func (t *ImmutableTree) Get(key []byte) (index int64, value []byte) { return t.tree.Get(key) } From 9de484e2bc1e9edc0fb8f037db64d35a6ff5ec39 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 9 Sep 2020 15:31:05 +0300 Subject: [PATCH 237/426] fixs --- core/state/accounts/accounts.go | 1 + core/state/candidates/candidates.go | 2 +- core/state/candidates/model.go | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/state/accounts/accounts.go b/core/state/accounts/accounts.go index ed2c68212..e3c991627 100644 --- a/core/state/accounts/accounts.go +++ b/core/state/accounts/accounts.go @@ -207,6 +207,7 @@ func (a *Accounts) CreateMultisig(weights []uint, addresses []types.Address, thr coins: []types.CoinID{}, balances: map[types.CoinID]*big.Int{}, markDirty: a.markDirty, + isNew: true, dirtyBalances: map[types.CoinID]struct{}{}, } } diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index e91dbec9e..41f8054a2 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -519,7 +519,7 @@ func (c *Candidates) SetOffline(pubkey types.Pubkey) { c.getFromMap(pubkey).setStatus(CandidateStatusOffline) } -// SubStake subs given unbounds from delegator's stake +// SubStake subs given value from delegator's stake func (c *Candidates) SubStake(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { stake := c.GetStakeOfAddress(pubkey, address, coin) stake.subValue(value) diff --git a/core/state/candidates/model.go b/core/state/candidates/model.go index aac97147e..aa68d2488 100644 --- a/core/state/candidates/model.go +++ b/core/state/candidates/model.go @@ -101,7 +101,7 @@ func (candidate *Candidate) setTmAddress() { candidate.tmAddress = &address } -// getFilteredUpdates returns updates which is > 0 in their unbounds + merge similar updates +// getFilteredUpdates returns updates which is > 0 in their value + merge similar updates func (candidate *Candidate) getFilteredUpdates() []*stake { var updates []*stake for _, update := range candidate.updates { @@ -140,7 +140,7 @@ func (candidate *Candidate) FilterUpdates() { candidate.isUpdatesDirty = true } -// GetTotalBipStake returns total stake unbounds of a candidate +// GetTotalBipStake returns total stake value of a candidate func (candidate *Candidate) GetTotalBipStake() *big.Int { return big.NewInt(0).Set(candidate.totalBipStake) } From f00b7cc2ab5c6691db60ab196c3c6e8b19f11bb8 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 9 Sep 2020 16:33:22 +0300 Subject: [PATCH 238/426] fix grpc genesis response --- api/v2/service/genesis.go | 2 +- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/v2/service/genesis.go b/api/v2/service/genesis.go index 3ed3ec048..0c3e4c557 100644 --- a/api/v2/service/genesis.go +++ b/api/v2/service/genesis.go @@ -44,7 +44,7 @@ func (s *Service) Genesis(ctx context.Context, _ *empty.Empty) (*pb.GenesisRespo MaxAgeDuration: fmt.Sprintf("%d", result.Genesis.ConsensusParams.Evidence.MaxAgeDuration), }, Validator: &pb.GenesisResponse_ConsensusParams_Validator{ - PublicKeyTypes: result.Genesis.ConsensusParams.Validator.PubKeyTypes, + PubKeyTypes: result.Genesis.ConsensusParams.Validator.PubKeyTypes, }, }, AppHash: result.Genesis.AppHash.String(), diff --git a/go.mod b/go.mod index 8bef82fe4..60d6b8920 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200907121318-9d4f607d1405 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200909133144-ed943599e38f github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index f15ad080c..0cd281201 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200907121318-9d4f607d1405 h1:dWIaHK1Wk3xp720CA90ZfVI7n9YuHZvwNDWxOEbikUM= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200907121318-9d4f607d1405/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200909133144-ed943599e38f h1:FcJkxj26psCS6MLJXKkR2Kjaay5wBkMrpIqjoALJTAE= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200909133144-ed943599e38f/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 8470ab224c2c6276199007b00c78da439814fb97 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 10 Sep 2020 10:48:47 +0300 Subject: [PATCH 239/426] halts tests --- core/state/halts/halts.go | 38 ++++++++++----- core/state/halts/halts_test.go | 87 ++++++++++++++++++++++++++++++++++ core/state/state.go | 1 + core/state/state_test.go | 23 +++++++++ 4 files changed, 137 insertions(+), 12 deletions(-) create mode 100644 core/state/halts/halts_test.go diff --git a/core/state/halts/halts.go b/core/state/halts/halts.go index d5999d085..ba12a4e89 100644 --- a/core/state/halts/halts.go +++ b/core/state/halts/halts.go @@ -14,6 +14,7 @@ import ( const mainPrefix = byte('h') type RHalts interface { + Export(state *types.AppState) GetHaltBlocks(height uint64) *Model } @@ -47,15 +48,21 @@ func (hb *HaltBlocks) Commit() error { hb.lock.Lock() delete(hb.dirty, height) + delete(hb.list, height) hb.lock.Unlock() - data, err := rlp.EncodeToBytes(haltBlock) - if err != nil { - return fmt.Errorf("can't encode object at %d: %v", height, err) - } - path := getPath(height) - hb.iavl.Set(path, data) + + if haltBlock.deleted { + hb.iavl.Remove(path) + } else { + data, err := rlp.EncodeToBytes(haltBlock) + if err != nil { + return fmt.Errorf("can't encode object at %d: %v", height, err) + } + + hb.iavl.Set(path, data) + } } return nil @@ -131,20 +138,27 @@ func (hb *HaltBlocks) Delete(height uint64) { haltBlock.delete() } -func (hb *HaltBlocks) Export(state *types.AppState, height uint64) { - for i := height; i <= height; i++ { - halts := hb.get(i) +func (hb *HaltBlocks) Export(state *types.AppState) { + hb.iavl.Iterate(func(key []byte, value []byte) bool { + if key[0] != mainPrefix { + return false + } + + height := binary.LittleEndian.Uint64(key[1:]) + halts := hb.get(height) if halts == nil { - continue + return false } for _, haltBlock := range halts.List { state.HaltBlocks = append(state.HaltBlocks, types.HaltBlock{ - Height: i, + Height: height, CandidateKey: haltBlock.Pubkey, }) } - } + + return false + }) } func (hb *HaltBlocks) getFromMap(height uint64) *Model { diff --git a/core/state/halts/halts_test.go b/core/state/halts/halts_test.go new file mode 100644 index 000000000..0847cc339 --- /dev/null +++ b/core/state/halts/halts_test.go @@ -0,0 +1,87 @@ +package halts + +import ( + "github.com/MinterTeam/minter-go-node/core/state/bus" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/tree" + db "github.com/tendermint/tm-db" + "testing" +) + +func TestHaltsToDeleteModel(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + h, err := NewHalts(bus.NewBus(), mutableTree) + if err != nil { + t.Fatal(err) + } + + pubkey, height := types.Pubkey{0}, uint64(10) + + h.AddHaltBlock(height, pubkey) + if err := h.Commit(); err != nil { + t.Fatal(err) + } + + _, _, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if h.GetHaltBlocks(height) == nil { + t.Fatal("Halts not found") + } + + h.Delete(height) + if err := h.Commit(); err != nil { + t.Fatal(err) + } + + _, _, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if h.GetHaltBlocks(height) != nil { + t.Fatal("Halts not deleted") + } +} + +func TestBusToAddHaltBlock(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + h, err := NewHalts(bus.NewBus(), mutableTree) + if err != nil { + t.Fatal(err) + } + + pubkey, height := types.Pubkey{0}, uint64(10) + + hbBus := Bus{halts: h} + hbBus.AddHaltBlock(height, pubkey) + + if err := h.Commit(); err != nil { + t.Fatal(err) + } + + _, _, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + halt := h.GetHaltBlocks(height) + if halt == nil { + t.Fatal("Halts not found") + } + + if len(halt.List) != 1 { + t.Fatalf("Incorrect amount of halts: %d. Expected: 1", len(halt.List)) + } + + if halt.Height() != height { + t.Fatalf("Invalid height %d. Expected %d", halt.Height(), height) + } + + hbPubKey := halt.List[0].Pubkey + if hbPubKey != pubkey { + t.Fatalf("Invalid public key %s. Expected %s", hbPubKey.String(), pubkey.String()) + } +} diff --git a/core/state/state.go b/core/state/state.go index 9c0c9ea06..70183296a 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -369,6 +369,7 @@ func (s *State) Export(height uint64) types.AppState { state.Accounts().Export(appState) state.Coins().Export(appState) state.Checks().Export(appState) + state.Halts().Export(appState) return *appState } diff --git a/core/state/state_test.go b/core/state/state_test.go index 62d749130..5c9301df9 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -90,6 +90,10 @@ func TestStateExport(t *testing.T) { state.Checks.UseCheck(newCheck) + state.Halts.AddHaltBlock(height, types.Pubkey{0}) + state.Halts.AddHaltBlock(height+1, types.Pubkey{1}) + state.Halts.AddHaltBlock(height+2, types.Pubkey{2}) + _, err = state.Commit() if err != nil { log.Panicf("Cannot commit state: %s", err) @@ -247,4 +251,23 @@ func TestStateExport(t *testing.T) { newStateCandidate2.Commission != 30 { t.Fatal("Wrong new state candidate data") } + + if len(newState.HaltBlocks) != 3 { + t.Fatalf("Invalid amount of halts: %d. Expected 3", len(newState.HaltBlocks)) + } + + pubkey := types.Pubkey{0} + if newState.HaltBlocks[0].Height != height && newState.HaltBlocks[0].CandidateKey != pubkey { + t.Fatal("Wrong new state halt blocks") + } + + pubkey = types.Pubkey{1} + if newState.HaltBlocks[1].Height != height+1 && newState.HaltBlocks[1].CandidateKey != pubkey { + t.Fatal("Wrong new state halt blocks") + } + + pubkey = types.Pubkey{2} + if newState.HaltBlocks[2].Height != height+2 && newState.HaltBlocks[2].CandidateKey != pubkey { + t.Fatal("Wrong new state halt blocks") + } } From ee377667d0666ddf9f1c660701ff64aebd30f3f4 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 10 Sep 2020 11:49:04 +0300 Subject: [PATCH 240/426] fixes and refactor --- api/v2/service/address.go | 2 +- api/v2/service/addresses.go | 2 +- api/v2/service/block.go | 2 +- api/v2/service/candidate.go | 2 +- api/v2/service/candidates.go | 2 +- api/v2/service/coin_info.go | 2 +- api/v2/service/estimate_coin_buy.go | 2 +- api/v2/service/estimate_coin_sell.go | 2 +- api/v2/service/estimate_coin_sell_all.go | 2 +- api/v2/service/estimate_tx_commission.go | 2 +- api/v2/service/events.go | 2 +- api/v2/service/frozen.go | 2 +- api/v2/service/gas.go | 4 ++-- api/v2/service/genesis.go | 2 +- api/v2/service/halts.go | 2 +- api/v2/service/missed_blocks.go | 2 +- api/v2/service/net_info.go | 16 +++++++++------ api/v2/service/send_transaction.go | 2 +- api/v2/service/service.go | 1 + api/v2/service/status.go | 2 +- api/v2/service/transaction.go | 2 +- api/v2/service/transactions.go | 2 +- api/v2/service/unconfirmed_txs.go | 2 +- api/v2/service/validators.go | 2 +- api/v2/service/waitlist.go | 2 +- api/v2/service/ws.go | 2 +- cli/cli_pb/manager.pb.go | 3 +++ cli/cli_pb/manager.proto | 1 + cli/service/client.go | 8 ++++++-- cli/service/server.go | 11 +++++++++- cli/service/server_test.go | 4 +--- cli/service/service.go | 13 ++++-------- cmd/minter/cmd/node.go | 2 +- core/minter/minter.go | 26 ++++++++++++++++++++++-- go.mod | 2 +- go.sum | 4 ++-- 36 files changed, 89 insertions(+), 52 deletions(-) diff --git a/api/v2/service/address.go b/api/v2/service/address.go index 26c93b368..9a677f1a1 100644 --- a/api/v2/service/address.go +++ b/api/v2/service/address.go @@ -19,7 +19,7 @@ type stakeUser struct { BipValue *big.Int } -// Returns coins list, balance and transaction count of an address. +// Address returns coins list, balance and transaction count of an address. func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.AddressResponse, error) { if !strings.HasPrefix(strings.Title(req.Address), "Mx") { return new(pb.AddressResponse), status.Error(codes.InvalidArgument, "invalid address") diff --git a/api/v2/service/addresses.go b/api/v2/service/addresses.go index 019882dbe..f6caa4162 100644 --- a/api/v2/service/addresses.go +++ b/api/v2/service/addresses.go @@ -11,7 +11,7 @@ import ( "math/big" ) -// Returns list of addresses. +// Addresses returns list of addresses. func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb.AddressesResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { diff --git a/api/v2/service/block.go b/api/v2/service/block.go index b684bbed7..f77451e4a 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -18,7 +18,7 @@ import ( "time" ) -// Returns block data at given height. +// Block returns block data at given height. func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockResponse, error) { height := int64(req.Height) block, err := s.client.Block(&height) diff --git a/api/v2/service/candidate.go b/api/v2/service/candidate.go index 3e731fc0d..fcb01f04e 100644 --- a/api/v2/service/candidate.go +++ b/api/v2/service/candidate.go @@ -13,7 +13,7 @@ import ( "math/big" ) -// Returns candidate’s info by provided public_key. It will respond with 404 code if candidate is not found. +// Candidate returns candidate’s info by provided public_key. It will respond with 404 code if candidate is not found. func (s *Service) Candidate(ctx context.Context, req *pb.CandidateRequest) (*pb.CandidateResponse, error) { if len(req.PublicKey) < 3 { return new(pb.CandidateResponse), status.Error(codes.InvalidArgument, "invalid public_key") diff --git a/api/v2/service/candidates.go b/api/v2/service/candidates.go index 8528ebdb8..bcf0313e6 100644 --- a/api/v2/service/candidates.go +++ b/api/v2/service/candidates.go @@ -7,7 +7,7 @@ import ( "google.golang.org/grpc/status" ) -// Returns list of candidates. +// Candidates returns list of candidates. func (s *Service) Candidates(ctx context.Context, req *pb.CandidatesRequest) (*pb.CandidatesResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index 0bad62686..c126f6631 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -14,7 +14,7 @@ import ( "google.golang.org/grpc/status" ) -// Returns information about coin symbol. +// CoinInfo returns information about coin symbol. func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.CoinInfoResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index 0353beeb0..9271a8a31 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -16,7 +16,7 @@ import ( "google.golang.org/grpc/status" ) -// Return estimate of buy coin transaction. +// EstimateCoinBuy return estimate of buy coin transaction. func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRequest) (*pb.EstimateCoinBuyResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index 4fd9c9bfa..df0d3fb32 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -16,7 +16,7 @@ import ( "google.golang.org/grpc/status" ) -// Return estimate of sell coin transaction. +// EstimateCoinSell return estimate of sell coin transaction. func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSellRequest) (*pb.EstimateCoinSellResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index 4969a389f..8d8b7da10 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -15,7 +15,7 @@ import ( "google.golang.org/grpc/status" ) -// Return estimate of sell all coin transaction. +// EstimateCoinSellAll return estimate of sell all coin transaction. func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinSellAllRequest) (*pb.EstimateCoinSellAllResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { diff --git a/api/v2/service/estimate_tx_commission.go b/api/v2/service/estimate_tx_commission.go index 2a165808c..13ee9911f 100644 --- a/api/v2/service/estimate_tx_commission.go +++ b/api/v2/service/estimate_tx_commission.go @@ -16,7 +16,7 @@ import ( "google.golang.org/grpc/status" ) -// Return estimate of transaction. +// EstimateTxCommission return estimate of transaction. func (s *Service) EstimateTxCommission(ctx context.Context, req *pb.EstimateTxCommissionRequest) (*pb.EstimateTxCommissionResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { diff --git a/api/v2/service/events.go b/api/v2/service/events.go index 1a2722cf4..04fec7405 100644 --- a/api/v2/service/events.go +++ b/api/v2/service/events.go @@ -9,7 +9,7 @@ import ( "google.golang.org/grpc/status" ) -// Returns events at given height. +// Events returns events at given height. func (s *Service) Events(ctx context.Context, req *pb.EventsRequest) (*pb.EventsResponse, error) { height := uint32(req.Height) events := s.blockchain.GetEventsDB().LoadEvents(height) diff --git a/api/v2/service/frozen.go b/api/v2/service/frozen.go index 0ca379144..3c6ad368f 100644 --- a/api/v2/service/frozen.go +++ b/api/v2/service/frozen.go @@ -11,7 +11,7 @@ import ( "strings" ) -// Returns frozen balance. +// Frozen returns frozen balance. func (s *Service) Frozen(ctx context.Context, req *pb.FrozenRequest) (*pb.FrozenResponse, error) { if !strings.HasPrefix(strings.Title(req.Address), "Mx") { return new(pb.FrozenResponse), status.Error(codes.InvalidArgument, "invalid address") diff --git a/api/v2/service/gas.go b/api/v2/service/gas.go index a9510bc4e..e93b5196d 100644 --- a/api/v2/service/gas.go +++ b/api/v2/service/gas.go @@ -9,14 +9,14 @@ import ( "google.golang.org/grpc/status" ) -// Returns current min gas price. +// MinGasPrice returns current min gas price. func (s *Service) MinGasPrice(context.Context, *empty.Empty) (*pb.MinGasPriceResponse, error) { return &pb.MinGasPriceResponse{ MinGasPrice: fmt.Sprintf("%d", s.blockchain.MinGasPrice()), }, nil } -// Returns current max gas. +// MaxGas returns current max gas. func (s *Service) MaxGas(ctx context.Context, req *pb.MaxGasRequest) (*pb.MaxGasResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { diff --git a/api/v2/service/genesis.go b/api/v2/service/genesis.go index 0c3e4c557..7fab9fad7 100644 --- a/api/v2/service/genesis.go +++ b/api/v2/service/genesis.go @@ -10,7 +10,7 @@ import ( "time" ) -// Returns genesis file. +// Genesis returns genesis file. func (s *Service) Genesis(ctx context.Context, _ *empty.Empty) (*pb.GenesisResponse, error) { result, err := s.client.Genesis() if err != nil { diff --git a/api/v2/service/halts.go b/api/v2/service/halts.go index 1c3706bbb..7045ac916 100644 --- a/api/v2/service/halts.go +++ b/api/v2/service/halts.go @@ -7,7 +7,7 @@ import ( "google.golang.org/grpc/status" ) -// Returns +// Halts returns votes func (s *Service) Halts(_ context.Context, req *pb.HaltsRequest) (*pb.HaltsResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { diff --git a/api/v2/service/missed_blocks.go b/api/v2/service/missed_blocks.go index 9b4a4d3df..029d9096d 100644 --- a/api/v2/service/missed_blocks.go +++ b/api/v2/service/missed_blocks.go @@ -6,7 +6,7 @@ import ( pb "github.com/MinterTeam/node-grpc-gateway/api_pb" ) -// Returns missed blocks by validator public key. +// MissedBlocks returns missed blocks by validator public key. func (s *Service) MissedBlocks(ctx context.Context, req *pb.MissedBlocksRequest) (*pb.MissedBlocksResponse, error) { blocks, count, err := s.blockchain.MissedBlocks(req.PublicKey, req.Height) if err != nil { diff --git a/api/v2/service/net_info.go b/api/v2/service/net_info.go index 17aaf7875..5ec299f46 100644 --- a/api/v2/service/net_info.go +++ b/api/v2/service/net_info.go @@ -5,14 +5,13 @@ import ( "fmt" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "github.com/golang/protobuf/ptypes/empty" - "github.com/tendermint/tendermint/evidence" - types2 "github.com/tendermint/tendermint/types" + "github.com/golang/protobuf/ptypes/wrappers" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "time" ) -// Returns network info. +// NetInfo returns network info. func (s *Service) NetInfo(ctx context.Context, _ *empty.Empty) (*pb.NetInfoResponse, error) { result, err := s.client.NetInfo() if err != nil { @@ -21,8 +20,13 @@ func (s *Service) NetInfo(ctx context.Context, _ *empty.Empty) (*pb.NetInfoRespo var peers []*pb.NetInfoResponse_Peer for _, peer := range result.Peers { - peerTM := s.tmNode.Switch().Peers().Get(peer.NodeInfo.ID()) - currentHeight := peerTM.Get(types2.PeerStateKey).(evidence.PeerState).GetHeight() + + var currentHeight *wrappers.StringValue + peerHeight := s.blockchain.PeerHeight(peer.NodeInfo.ID()) + if peerHeight != 0 { + currentHeight = &wrappers.StringValue{Value: fmt.Sprintf("%d", peerHeight)} + } + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { return new(pb.NetInfoResponse), timeoutStatus.Err() } @@ -39,7 +43,7 @@ func (s *Service) NetInfo(ctx context.Context, _ *empty.Empty) (*pb.NetInfoRespo } peers = append(peers, &pb.NetInfoResponse_Peer{ - LatestBlockHeight: fmt.Sprintf("%d", currentHeight), + LatestBlockHeight: currentHeight, NodeInfo: &pb.NodeInfo{ ProtocolVersion: &pb.NodeInfo_ProtocolVersion{ P2P: fmt.Sprintf("%d", peer.NodeInfo.ProtocolVersion.P2P), diff --git a/api/v2/service/send_transaction.go b/api/v2/service/send_transaction.go index 131fbfd6e..922e8ec3d 100644 --- a/api/v2/service/send_transaction.go +++ b/api/v2/service/send_transaction.go @@ -15,7 +15,7 @@ import ( "strings" ) -// Returns the result of sending signed tx. To ensure that transaction was successfully committed to the blockchain, you need to find the transaction by the hash and ensure that the status code equals to 0. +// SendTransaction returns the result of sending signed tx. To ensure that transaction was successfully committed to the blockchain, you need to find the transaction by the hash and ensure that the status code equals to 0. func (s *Service) SendTransaction(ctx context.Context, req *pb.SendTransactionRequest) (*pb.SendTransactionResponse, error) { if !strings.HasPrefix(strings.Title(req.GetTx()), "0x") { return new(pb.SendTransactionResponse), status.Error(codes.InvalidArgument, "invalid transaction") diff --git a/api/v2/service/service.go b/api/v2/service/service.go index 735d515b8..83373a60c 100644 --- a/api/v2/service/service.go +++ b/api/v2/service/service.go @@ -23,6 +23,7 @@ type Service struct { version string } +// NewService create gRPC implementation func NewService(cdc *amino.Codec, blockchain *minter.Blockchain, client *rpc.Local, node *tmNode.Node, minterCfg *config.Config, version string) *Service { return &Service{ cdc: cdc, diff --git a/api/v2/service/status.go b/api/v2/service/status.go index ac55d04e5..6e47691f1 100644 --- a/api/v2/service/status.go +++ b/api/v2/service/status.go @@ -10,7 +10,7 @@ import ( "time" ) -// Returns current min gas price. +// Status returns current min gas price. func (s *Service) Status(context.Context, *empty.Empty) (*pb.StatusResponse, error) { result, err := s.client.Status() if err != nil { diff --git a/api/v2/service/transaction.go b/api/v2/service/transaction.go index 63de7b910..be645272a 100644 --- a/api/v2/service/transaction.go +++ b/api/v2/service/transaction.go @@ -11,7 +11,7 @@ import ( "google.golang.org/grpc/status" ) -// Returns transaction info. +// Transaction returns transaction info. func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) (*pb.TransactionResponse, error) { if len(req.Hash) < 3 { return new(pb.TransactionResponse), status.Error(codes.InvalidArgument, "invalid hash") diff --git a/api/v2/service/transactions.go b/api/v2/service/transactions.go index 2ebf787d1..16bedf1a3 100644 --- a/api/v2/service/transactions.go +++ b/api/v2/service/transactions.go @@ -10,7 +10,7 @@ import ( "google.golang.org/grpc/status" ) -// Return transactions by query. +// Transactions return transactions by query. func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) (*pb.TransactionsResponse, error) { page := int(req.Page) if page == 0 { diff --git a/api/v2/service/unconfirmed_txs.go b/api/v2/service/unconfirmed_txs.go index e99e515bb..a0e37d84c 100644 --- a/api/v2/service/unconfirmed_txs.go +++ b/api/v2/service/unconfirmed_txs.go @@ -8,7 +8,7 @@ import ( "google.golang.org/grpc/status" ) -// Returns unconfirmed transactions. +// UnconfirmedTxs returns unconfirmed transactions. func (s *Service) UnconfirmedTxs(ctx context.Context, req *pb.UnconfirmedTxsRequest) (*pb.UnconfirmedTxsResponse, error) { txs, err := s.client.UnconfirmedTxs(int(req.Limit)) if err != nil { diff --git a/api/v2/service/validators.go b/api/v2/service/validators.go index 50ba76092..619128aa5 100644 --- a/api/v2/service/validators.go +++ b/api/v2/service/validators.go @@ -9,7 +9,7 @@ import ( "google.golang.org/grpc/status" ) -// Returns list of active validators. +// Validators returns list of active validators. func (s *Service) Validators(ctx context.Context, req *pb.ValidatorsRequest) (*pb.ValidatorsResponse, error) { height := int64(req.Height) if height == 0 { diff --git a/api/v2/service/waitlist.go b/api/v2/service/waitlist.go index 19be0acec..e798a851e 100644 --- a/api/v2/service/waitlist.go +++ b/api/v2/service/waitlist.go @@ -10,7 +10,7 @@ import ( "strings" ) -// Returns the list of address stakes in waitlist. +// WaitList returns the list of address stakes in waitlist. func (s *Service) WaitList(ctx context.Context, req *pb.WaitListRequest) (*pb.WaitListResponse, error) { if !strings.HasPrefix(strings.Title(req.Address), "Mx") { return new(pb.WaitListResponse), status.Error(codes.InvalidArgument, "invalid address") diff --git a/api/v2/service/ws.go b/api/v2/service/ws.go index 35aba1bc3..4a19ee765 100644 --- a/api/v2/service/ws.go +++ b/api/v2/service/ws.go @@ -16,7 +16,7 @@ const ( SubscribeTimeout = 5 * time.Second ) -// Returns a subscription for events by query. +// Subscribe returns a subscription for events by query. func (s *Service) Subscribe(request *pb.SubscribeRequest, stream pb.ApiService_SubscribeServer) error { if s.client.NumClients() >= s.minterCfg.RPC.MaxSubscriptionClients { diff --git a/cli/cli_pb/manager.pb.go b/cli/cli_pb/manager.pb.go index 4e470927b..d8f618af2 100644 --- a/cli/cli_pb/manager.pb.go +++ b/cli/cli_pb/manager.pb.go @@ -11,6 +11,7 @@ import ( proto "github.com/golang/protobuf/proto" empty "github.com/golang/protobuf/ptypes/empty" timestamp "github.com/golang/protobuf/ptypes/timestamp" + _ "github.com/golang/protobuf/ptypes/wrappers" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" @@ -1174,6 +1175,8 @@ var file_manager_proto_rawDesc = []byte{ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb2, 0x03, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4b, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, diff --git a/cli/cli_pb/manager.proto b/cli/cli_pb/manager.proto index 78bbbddb5..60457539b 100644 --- a/cli/cli_pb/manager.proto +++ b/cli/cli_pb/manager.proto @@ -4,6 +4,7 @@ package cli_pb; option go_package = ".;cli_pb"; import "google/protobuf/empty.proto"; import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; message NodeInfo { diff --git a/cli/service/client.go b/cli/service/client.go index 4c9796cc7..2fce090dd 100644 --- a/cli/service/client.go +++ b/cli/service/client.go @@ -10,6 +10,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/empty" + grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry" "github.com/marcusolsson/tui-go" "github.com/urfave/cli/v2" "gitlab.com/tslocum/cview" @@ -108,7 +109,10 @@ func (mc *ManagerConsole) Cli(ctx context.Context) { } func NewCLI(socketPath string) (*ManagerConsole, error) { - cc, err := grpc.Dial("passthrough:///unix:///"+socketPath, grpc.WithInsecure()) + cc, err := grpc.Dial("passthrough:///unix:///"+socketPath, + grpc.WithStreamInterceptor(grpc_retry.StreamClientInterceptor()), + grpc.WithUnaryInterceptor(grpc_retry.UnaryClientInterceptor()), + grpc.WithInsecure()) if err != nil { return nil, err } @@ -164,7 +168,7 @@ func NewCLI(socketPath string) (*ManagerConsole, error) { { Name: "dashboard", Aliases: []string{"db"}, - Usage: "Show dashboard", //todo + Usage: "Show dashboard", Action: dashboardCMD(client), }, { diff --git a/cli/service/server.go b/cli/service/server.go index a46da701f..3ccac407d 100644 --- a/cli/service/server.go +++ b/cli/service/server.go @@ -3,6 +3,8 @@ package service import ( "context" pb "github.com/MinterTeam/minter-go-node/cli/cli_pb" + grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" + grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" "google.golang.org/grpc" "net" "os" @@ -18,7 +20,14 @@ func StartCLIServer(socketPath string, manager pb.ManagerServiceServer, ctx cont return err } - server := grpc.NewServer() + server := grpc.NewServer( + grpc_middleware.WithStreamServerChain( + grpc_recovery.StreamServerInterceptor(), + ), + grpc_middleware.WithUnaryServerChain( + grpc_recovery.UnaryServerInterceptor(), + ), + ) pb.RegisterManagerServiceServer(server, manager) diff --git a/cli/service/server_test.go b/cli/service/server_test.go index 3086e3c2e..2f4e47999 100644 --- a/cli/service/server_test.go +++ b/cli/service/server_test.go @@ -4,7 +4,6 @@ import ( "context" "github.com/MinterTeam/minter-go-node/config" "github.com/MinterTeam/minter-go-node/core/minter" - tmNode "github.com/tendermint/tendermint/node" rpc "github.com/tendermint/tendermint/rpc/client/local" "io/ioutil" "path/filepath" @@ -16,14 +15,13 @@ func TestStartCLIServer(t *testing.T) { var ( blockchain *minter.Blockchain tmRPC *rpc.Local - tmNode *tmNode.Node cfg *config.Config ) ctx, cancel := context.WithCancel(context.Background()) socketPath, _ := filepath.Abs(filepath.Join(".", "file.sock")) _ = ioutil.WriteFile(socketPath, []byte("address already in use"), 0644) go func() { - err := StartCLIServer(socketPath, NewManager(blockchain, tmRPC, tmNode, cfg), ctx) + err := StartCLIServer(socketPath, NewManager(blockchain, tmRPC, cfg), ctx) if err != nil { t.Log(err) } diff --git a/cli/service/service.go b/cli/service/service.go index ebb586873..775a9a515 100644 --- a/cli/service/service.go +++ b/cli/service/service.go @@ -10,10 +10,7 @@ import ( "github.com/MinterTeam/minter-go-node/version" "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/empty" - "github.com/tendermint/tendermint/evidence" - tmNode "github.com/tendermint/tendermint/node" rpc "github.com/tendermint/tendermint/rpc/client/local" - types2 "github.com/tendermint/tendermint/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "runtime" @@ -23,12 +20,11 @@ import ( type Manager struct { blockchain *minter.Blockchain tmRPC *rpc.Local - tmNode *tmNode.Node cfg *config.Config } -func NewManager(blockchain *minter.Blockchain, tmRPC *rpc.Local, tmNode *tmNode.Node, cfg *config.Config) pb.ManagerServiceServer { - return &Manager{blockchain: blockchain, tmRPC: tmRPC, tmNode: tmNode, cfg: cfg} +func NewManager(blockchain *minter.Blockchain, tmRPC *rpc.Local, cfg *config.Config) pb.ManagerServiceServer { + return &Manager{blockchain: blockchain, tmRPC: tmRPC, cfg: cfg} } func (m *Manager) Dashboard(_ *empty.Empty, stream pb.ManagerService_DashboardServer) error { @@ -154,10 +150,9 @@ func (m *Manager) NetInfo(context.Context, *empty.Empty) (*pb.NetInfoResponse, e RecentlySent: channel.RecentlySent, }) } - peerTM := m.tmNode.Switch().Peers().Get(peer.NodeInfo.ID()) - currentHeight := peerTM.Get(types2.PeerStateKey).(evidence.PeerState).GetHeight() + peerHeight := m.blockchain.PeerHeight(peer.NodeInfo.ID()) peers = append(peers, &pb.NetInfoResponse_Peer{ - LatestBlockHeight: currentHeight, + LatestBlockHeight: peerHeight, NodeInfo: &pb.NodeInfo{ ProtocolVersion: &pb.NodeInfo_ProtocolVersion{ P2P: uint64(peer.NodeInfo.ProtocolVersion.P2P), diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index 2dffd57d5..e175f68b0 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -137,7 +137,7 @@ func runNode(cmd *cobra.Command) error { } go func() { - err := service.StartCLIServer(utils.GetMinterHome()+"/manager.sock", service.NewManager(app, client, node, cfg), cmd.Context()) + err := service.StartCLIServer(utils.GetMinterHome()+"/manager.sock", service.NewManager(app, client, cfg), cmd.Context()) if err != nil { panic(err) } diff --git a/core/minter/minter.go b/core/minter/minter.go index 464ede06f..63285e4b1 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -16,7 +16,6 @@ import ( "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/core/validators" "github.com/MinterTeam/minter-go-node/helpers" - "github.com/MinterTeam/minter-go-node/version" "github.com/syndtr/goleveldb/leveldb/filter" "github.com/syndtr/goleveldb/leveldb/opt" @@ -26,7 +25,9 @@ import ( cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" "github.com/tendermint/tendermint/evidence" tmNode "github.com/tendermint/tendermint/node" + "github.com/tendermint/tendermint/p2p" types2 "github.com/tendermint/tendermint/types" + typesT "github.com/tendermint/tendermint/types" "github.com/tendermint/tm-db" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -673,7 +674,11 @@ func (app *Blockchain) GetValidatorStatus(address types.TmAddress) int8 { func (app *Blockchain) MaxPeerHeight() int64 { var max int64 for _, peer := range app.tmNode.Switch().Peers().List() { - height := peer.Get(types2.PeerStateKey).(evidence.PeerState).GetHeight() + peerState, ok := peer.Get(typesT.PeerStateKey).(evidence.PeerState) + if !ok { + continue + } + height := peerState.GetHeight() if height > max { max = height } @@ -681,6 +686,23 @@ func (app *Blockchain) MaxPeerHeight() int64 { return max } +// PeerHeight returns height of peer by ID. If peer is fast_syncing, height equal 0 +func (app *Blockchain) PeerHeight(id p2p.ID) int64 { + peerTM := app.tmNode.Switch().Peers().Get(id) + if peerTM == nil { + return 0 + } + ps := peerTM.Get(typesT.PeerStateKey) + if ps == nil { + return 0 + } + peerState, ok := ps.(evidence.PeerState) + if !ok { + return 0 + } + return peerState.GetHeight() +} + // DeleteStateVersions deletes states in given range func (app *Blockchain) DeleteStateVersions(from, to int64) error { app.lock.RLock() diff --git a/go.mod b/go.mod index 60d6b8920..3e043ceda 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200909133144-ed943599e38f + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200910081617-1c9f3b1d580c github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 0cd281201..7c1d77c14 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200909133144-ed943599e38f h1:FcJkxj26psCS6MLJXKkR2Kjaay5wBkMrpIqjoALJTAE= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200909133144-ed943599e38f/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200910081617-1c9f3b1d580c h1:yxVaVM+pMyakNvcXABbjGnQmZzTXguR03c1uOxDgKNY= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200910081617-1c9f3b1d580c/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 959ded3c862ecdb134cabcf9a63502f0c7299f35 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Thu, 10 Sep 2020 11:51:32 +0300 Subject: [PATCH 241/426] Fix linter errors --- core/types/bitarray.go | 2 +- core/types/types.go | 128 +++++++++++++++++++++++++++------------ core/types/types_test.go | 2 +- tests/helpers.go | 11 ++++ 4 files changed, 103 insertions(+), 40 deletions(-) diff --git a/core/types/bitarray.go b/core/types/bitarray.go index 5cc54cc32..1b6fd35d9 100644 --- a/core/types/bitarray.go +++ b/core/types/bitarray.go @@ -189,6 +189,6 @@ func (bA *BitArray) UnmarshalJSON(bz []byte) error { bA2.SetIndex(i, true) } } - *bA = *bA2 + *bA = *bA2 //nolint:govet return nil } diff --git a/core/types/types.go b/core/types/types.go index 43d9944f4..12d7c0157 100644 --- a/core/types/types.go +++ b/core/types/types.go @@ -13,12 +13,18 @@ import ( "strings" ) +// Types lengths const ( - HashLength = 32 - AddressLength = 20 - PubKeyLength = 32 - CoinSymbolLength = 10 - BasecoinID = 0 + HashLength = 32 + AddressLength = 20 + PubKeyLength = 32 + CoinSymbolLength = 10 + TendermintAddressLength = 20 +) + +const ( + // BasecoinID is an ID of a base coin + BasecoinID = 0 ) var ( @@ -29,20 +35,33 @@ var ( // Hash represents the 32 byte Keccak256 hash of arbitrary data. type Hash [HashLength]byte +// BytesToHash converts given byte slice to Hash func BytesToHash(b []byte) Hash { var h Hash h.SetBytes(b) return h } + +// StringToHash converts given string to Hash func StringToHash(s string) Hash { return BytesToHash([]byte(s)) } -func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) } -func HexToHash(s string) Hash { return BytesToHash(FromHex(s, "Mh")) } -// Get the string representation of the underlying hash -func (h Hash) Str() string { return string(h[:]) } +// BigToHash converts given big.Int to Hash +func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) } + +// HexToHash converts given hex string to Hash +func HexToHash(s string) Hash { return BytesToHash(FromHex(s, "Mh")) } + +// Str returns the string representation of the underlying hash +func (h Hash) Str() string { return string(h[:]) } + +// Bytes returns the bytes representation of the underlying hash func (h Hash) Bytes() []byte { return h[:] } + +// Big returns the big.Int representation of the underlying hash func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } -func (h Hash) Hex() string { return hexutil.Encode(h[:]) } + +// Hex returns the hex-string representation of the underlying hash +func (h Hash) Hex() string { return hexutil.Encode(h[:]) } // TerminalString implements log.TerminalStringer, formatting a string for console // output during logging. @@ -77,7 +96,7 @@ func (h Hash) MarshalText() ([]byte, error) { return hexutil.Bytes(h[:]).MarshalText() } -// Sets the hash to the value of b. If b is larger than len(h), 'b' will be cropped (from the left). +// SetBytes Sets the hash to the value of b. If b is larger than len(h), 'b' will be cropped (from the left). func (h *Hash) SetBytes(b []byte) { if len(b) > len(h) { b = b[len(b)-HashLength:] @@ -86,10 +105,10 @@ func (h *Hash) SetBytes(b []byte) { copy(h[HashLength-len(b):], b) } -// Set string `s` to h. If s is larger than len(h) s will be cropped (from left) to fit. +// SetString sets string `s` to h. If s is larger than len(h) s will be cropped (from left) to fit. func (h *Hash) SetString(s string) { h.SetBytes([]byte(s)) } -// Sets h to other +// Set h to other func (h *Hash) Set(other Hash) { for i, v := range other { h[i] = v @@ -105,6 +124,7 @@ func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value { return reflect.ValueOf(h) } +// EmptyHash checks if given Hash is empty func EmptyHash(h Hash) bool { return h == Hash{} } @@ -124,11 +144,15 @@ func (h UnprefixedHash) MarshalText() ([]byte, error) { /////////// Coin +// CoinSymbol represents the 10 byte coin symbol. type CoinSymbol [CoinSymbolLength]byte func (c CoinSymbol) String() string { return string(bytes.Trim(c[:], "\x00")) } -func (c CoinSymbol) Bytes() []byte { return c[:] } +// Bytes returns the bytes representation of the underlying CoinSymbol +func (c CoinSymbol) Bytes() []byte { return c[:] } + +// MarshalJSON encodes coin to json func (c CoinSymbol) MarshalJSON() ([]byte, error) { buffer := bytes.NewBufferString("\"") @@ -138,25 +162,31 @@ func (c CoinSymbol) MarshalJSON() ([]byte, error) { return buffer.Bytes(), nil } +// UnmarshalJSON parses a coinSymbol from json func (c *CoinSymbol) UnmarshalJSON(input []byte) error { *c = StrToCoinSymbol(string(input[1 : len(input)-1])) return nil } +// Compare compares coin symbols. +// The result will be 0 if a==b, -1 if a < b, and +1 if a > b. func (c CoinSymbol) Compare(c2 CoinSymbol) int { return bytes.Compare(c.Bytes(), c2.Bytes()) } +// IsBaseCoin checks if coin is a base coin func (c CoinSymbol) IsBaseCoin() bool { return c.Compare(GetBaseCoin()) == 0 } +// StrToCoinSymbol converts given string to a coin symbol func StrToCoinSymbol(s string) CoinSymbol { var symbol CoinSymbol - copy(symbol[:], []byte(s)) + copy(symbol[:], s) return symbol } +// GetVersionFromSymbol returns coin version extracted from symbol func GetVersionFromSymbol(s string) CoinVersion { parts := strings.Split(s, "-") if len(parts) == 1 { @@ -167,8 +197,10 @@ func GetVersionFromSymbol(s string) CoinVersion { return CoinVersion(v) } +// CoinID represents coin id type CoinID uint32 +// IsBaseCoin checks if func (c CoinID) IsBaseCoin() bool { return c == GetBaseCoinID() } @@ -177,34 +209,46 @@ func (c CoinID) String() string { return strconv.Itoa(int(c)) } +// Bytes returns LittleEndian encoded bytes of coin id func (c CoinID) Bytes() []byte { b := make([]byte, 4) binary.LittleEndian.PutUint32(b, c.Uint32()) return b } +// Uint32 returns coin id as uint32 func (c CoinID) Uint32() uint32 { return uint32(c) } +// BytesToCoinID converts bytes to coin id. Expects LittleEndian encoding. func BytesToCoinID(bytes []byte) CoinID { return CoinID(binary.LittleEndian.Uint32(bytes)) } +// CoinVersion represents coin version info type CoinVersion = uint16 /////////// Address +// Address represents 20-byte address in Minter Blockchain type Address [AddressLength]byte +// BytesToAddress converts given byte slice to Address func BytesToAddress(b []byte) Address { var a Address a.SetBytes(b) return a } + +// StringToAddress converts given string to Address func StringToAddress(s string) Address { return BytesToAddress([]byte(s)) } -func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) } -func HexToAddress(s string) Address { return BytesToAddress(FromHex(s, "Mx")) } + +// BigToAddress converts given big.Int to Address +func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) } + +// HexToAddress converts given hex string to Address +func HexToAddress(s string) Address { return BytesToAddress(FromHex(s, "Mx")) } // IsHexAddress verifies whether a string can represent a valid hex-encoded // Minter address or not. @@ -215,12 +259,19 @@ func IsHexAddress(s string) bool { return len(s) == 2*AddressLength && isHex(s) } -// Get the string representation of the underlying address -func (a Address) Str() string { return string(a[:]) } +// Str returns the string representation of the underlying address +func (a Address) Str() string { return string(a[:]) } + +// Bytes returns the byte representation of the underlying address func (a Address) Bytes() []byte { return a[:] } + +// Big returns the big.Int representation of the underlying address func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) } -func (a Address) Hash() Hash { return BytesToHash(a[:]) } +// Hash returns the Hash representation of the underlying address +func (a Address) Hash() Hash { return BytesToHash(a[:]) } + +// Hex returns the hex-string representation of the underlying address func (a Address) Hex() string { return "Mx" + hex.EncodeToString(a[:]) } @@ -236,7 +287,7 @@ func (a Address) Format(s fmt.State, c rune) { fmt.Fprintf(s, "%"+string(c), a[:]) } -// Sets the address to the value of b. If b is larger than len(a) it will panic +// SetBytes Sets the address to the value of b. If b is larger than len(a) it will panic func (a *Address) SetBytes(b []byte) { if len(b) > len(a) { b = b[len(b)-AddressLength:] @@ -244,10 +295,10 @@ func (a *Address) SetBytes(b []byte) { copy(a[AddressLength-len(b):], b) } -// Set string `s` to a. If s is larger than len(a) it will panic +// SetString set string `s` to a. If s is larger than len(a) it will panic func (a *Address) SetString(s string) { a.SetBytes([]byte(s)) } -// Sets a to other +// Set Sets a to other func (a *Address) Set(other Address) { for i, v := range other { a[i] = v @@ -264,11 +315,13 @@ func (a *Address) UnmarshalText(input []byte) error { return hexutil.UnmarshalFixedText("Address", input, a[:]) } +// Unmarshal parses a hash from byte slice. func (a *Address) Unmarshal(input []byte) error { copy(a[:], input) return nil } +// MarshalJSON marshals given address to json format. func (a Address) MarshalJSON() ([]byte, error) { return []byte(fmt.Sprintf("\"%s\"", a.String())), nil } @@ -278,33 +331,26 @@ func (a *Address) UnmarshalJSON(input []byte) error { return hexutil.UnmarshalFixedJSON(addressT, input, a[:]) } +// Compare compares addresses. +// The result will be 0 if a==b, -1 if a < b, and +1 if a > b. func (a *Address) Compare(a2 Address) int { return bytes.Compare(a.Bytes(), a2.Bytes()) } -// UnprefixedHash allows marshaling an Address without 0x prefix. -type UnprefixedAddress Address - -// UnmarshalText decodes the address from hex. The 0x prefix is optional. -func (a *UnprefixedAddress) UnmarshalText(input []byte) error { - return hexutil.UnmarshalFixedUnprefixedText("UnprefixedAddress", input, a[:]) -} - -// MarshalText encodes the address as hex. -func (a UnprefixedAddress) MarshalText() ([]byte, error) { - return []byte(hex.EncodeToString(a[:])), nil -} - -type Pubkey [32]byte +// Pubkey represents 32 byte public key of a validator +type Pubkey [PubKeyLength]byte +// HexToPubkey decodes given string into Pubkey func HexToPubkey(s string) Pubkey { return BytesToPubkey(FromHex(s, "Mp")) } +// BytesToPubkey decodes given bytes into Pubkey func BytesToPubkey(b []byte) Pubkey { var p Pubkey p.SetBytes(b) return p } +// SetBytes sets given bytes as public key func (p *Pubkey) SetBytes(b []byte) { if len(b) > len(p) { b = b[len(b)-PubKeyLength:] @@ -312,20 +358,24 @@ func (p *Pubkey) SetBytes(b []byte) { copy(p[PubKeyLength-len(b):], b) } +// Bytes returns underlying bytes func (p Pubkey) Bytes() []byte { return p[:] } func (p Pubkey) String() string { return fmt.Sprintf("Mp%x", p[:]) } +// MarshalText encodes Pubkey from to text. func (p Pubkey) MarshalText() ([]byte, error) { return []byte(p.String()), nil } +// MarshalJSON encodes Pubkey from to json format. func (p Pubkey) MarshalJSON() ([]byte, error) { return []byte(fmt.Sprintf("\"%s\"", p.String())), nil } +// UnmarshalJSON decodes Pubkey from json format. func (p *Pubkey) UnmarshalJSON(input []byte) error { b, err := hex.DecodeString(string(input)[3 : len(input)-1]) copy(p[:], b) @@ -333,8 +383,10 @@ func (p *Pubkey) UnmarshalJSON(input []byte) error { return err } +// Equals checks if public keys are equal func (p Pubkey) Equals(p2 Pubkey) bool { return p == p2 } -type TmAddress [20]byte +// TmAddress represents Tendermint address +type TmAddress [TendermintAddressLength]byte diff --git a/core/types/types_test.go b/core/types/types_test.go index a743d6b18..5a9c9156b 100644 --- a/core/types/types_test.go +++ b/core/types/types_test.go @@ -221,7 +221,7 @@ func TestAppState(t *testing.T) { panic(err) } - if bytes.Compare(b1, b2) != 0 { + if !bytes.Equal(b1, b2) { t.Errorf("Bytes are not the same") } } diff --git a/tests/helpers.go b/tests/helpers.go index 2e6c87fac..59007e0e8 100644 --- a/tests/helpers.go +++ b/tests/helpers.go @@ -16,6 +16,8 @@ import ( "time" ) +// CreateApp creates and returns new Blockchain instance +// Recreates $HOME/.minter_test dir func CreateApp(state types.AppState) *minter.Blockchain { utils.MinterHome = os.ExpandEnv(filepath.Join("$HOME", ".minter_test")) _ = os.RemoveAll(utils.MinterHome) @@ -42,10 +44,12 @@ func CreateApp(state types.AppState) *minter.Blockchain { return app } +// SendCommit sends Commit message to given Blockchain instance func SendCommit(app *minter.Blockchain) tmTypes.ResponseCommit { return app.Commit() } +// SendBeginBlock sends BeginBlock message to given Blockchain instance func SendBeginBlock(app *minter.Blockchain) tmTypes.ResponseBeginBlock { return app.BeginBlock(tmTypes.RequestBeginBlock{ Hash: nil, @@ -73,12 +77,15 @@ func SendBeginBlock(app *minter.Blockchain) tmTypes.ResponseBeginBlock { }) } +// SendEndBlock sends EndBlock message to given Blockchain instance func SendEndBlock(app *minter.Blockchain) tmTypes.ResponseEndBlock { return app.EndBlock(tmTypes.RequestEndBlock{ Height: 0, }) } +// CreateTx composes and returns Tx with given params. +// Nonce, chain id, gas price, gas coin and signature type fields are auto-filled. func CreateTx(app *minter.Blockchain, address types.Address, txType transaction.TxType, data interface{}) transaction.Transaction { nonce := app.CurrentState().Accounts().GetNonce(address) + 1 bData, err := rlp.EncodeToBytes(data) @@ -99,12 +106,14 @@ func CreateTx(app *minter.Blockchain, address types.Address, txType transaction. return tx } +// SendTx sends DeliverTx message to given Blockchain instance func SendTx(app *minter.Blockchain, bytes []byte) tmTypes.ResponseDeliverTx { return app.DeliverTx(tmTypes.RequestDeliverTx{ Tx: bytes, }) } +// SignTx returns bytes of signed with given pk transaction func SignTx(pk *ecdsa.PrivateKey, tx transaction.Transaction) []byte { err := tx.Sign(pk) if err != nil { @@ -116,12 +125,14 @@ func SignTx(pk *ecdsa.PrivateKey, tx transaction.Transaction) []byte { return b } +// CreateAddress returns random address and corresponding private key func CreateAddress() (types.Address, *ecdsa.PrivateKey) { pk, _ := crypto.GenerateKey() return crypto.PubkeyToAddress(pk.PublicKey), pk } +// DefaultAppState returns new AppState with some predefined values func DefaultAppState() types.AppState { return types.AppState{ Note: "", From f7eb1ee92b6c3449c25082318071896cbd0377d9 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Thu, 10 Sep 2020 14:25:22 +0300 Subject: [PATCH 242/426] Remove redundant db write --- core/state/candidates/candidates.go | 2 +- core/state/candidates/model.go | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 41f8054a2..afa95d53e 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -311,7 +311,7 @@ func (c *Candidates) GetCandidateByTendermintAddress(address types.TmAddress) *C } // RecalculateStakes recalculate stakes of all candidates: -// 1. Updates bip-unbounds of each stake +// 1. Updates bip-values of each stake // 2. Applies updates func (c *Candidates) RecalculateStakes(height uint64) { c.recalculateStakes(height) diff --git a/core/state/candidates/model.go b/core/state/candidates/model.go index aa68d2488..b8c2f214b 100644 --- a/core/state/candidates/model.go +++ b/core/state/candidates/model.go @@ -130,6 +130,10 @@ func (candidate *Candidate) getFilteredUpdates() []*stake { // FilterUpdates filters candidate updates: remove 0-valued updates and merge similar ones func (candidate *Candidate) FilterUpdates() { + if len(candidate.updates) == 0 { + return + } + updates := candidate.getFilteredUpdates() sort.SliceStable(updates, func(i, j int) bool { From 07d79ce0aef4220a1772a105e1781f6fed96a44c Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 10 Sep 2020 14:35:04 +0300 Subject: [PATCH 243/426] accounts_test.go and refactor --- core/state/accounts/accounts.go | 11 - core/state/accounts/accounts_test.go | 382 ++++++++++++++++++++++++ core/state/accounts/bus.go | 4 - core/state/accounts/model.go | 13 - core/state/bus/accounts.go | 1 - core/state/candidates/candidate_test.go | 5 +- 6 files changed, 384 insertions(+), 32 deletions(-) create mode 100644 core/state/accounts/accounts_test.go diff --git a/core/state/accounts/accounts.go b/core/state/accounts/accounts.go index e3c991627..9e9aac3f2 100644 --- a/core/state/accounts/accounts.go +++ b/core/state/accounts/accounts.go @@ -5,7 +5,6 @@ import ( "fmt" "github.com/MinterTeam/minter-go-node/core/state/bus" "github.com/MinterTeam/minter-go-node/core/types" - "github.com/MinterTeam/minter-go-node/formula" "github.com/MinterTeam/minter-go-node/rlp" "github.com/MinterTeam/minter-go-node/tree" @@ -315,16 +314,6 @@ func (a *Accounts) GetBalances(address types.Address) []Balance { return balances } -func (a *Accounts) DeleteCoin(address types.Address, id types.CoinID) { - balance := a.GetBalance(address, id) - coin := a.bus.Coins().GetCoin(id) - - ret := formula.CalculateSaleReturn(coin.Volume, coin.Reserve, 100, balance) - - a.AddBalance(address, types.GetBaseCoinID(), ret) - a.SetBalance(address, id, big.NewInt(0)) -} - func (a *Accounts) markDirty(addr types.Address) { a.dirty[addr] = struct{}{} } diff --git a/core/state/accounts/accounts_test.go b/core/state/accounts/accounts_test.go new file mode 100644 index 000000000..b445adcf6 --- /dev/null +++ b/core/state/accounts/accounts_test.go @@ -0,0 +1,382 @@ +package accounts + +import ( + "encoding/json" + "fmt" + "github.com/MinterTeam/minter-go-node/core/state/bus" + "github.com/MinterTeam/minter-go-node/core/state/checker" + "github.com/MinterTeam/minter-go-node/core/state/coins" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/helpers" + "github.com/MinterTeam/minter-go-node/tree" + db "github.com/tendermint/tm-db" + "math/big" + "testing" +) + +func TestAccounts_CreateMultisig(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + accounts, err := NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + multisigAddr := accounts.CreateMultisig([]uint{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, 2, 0, [20]byte{4}) + + account := accounts.GetAccount(multisigAddr) + if account == nil { + t.Fatal("account is nil") + } + + if !account.IsMultisig() { + t.Fatal("account is not multisig") + } + + multisig := account.Multisig() + if multisig.GetWeight([20]byte{1, 1, 2, 3, 4, 5}) != 0 { + t.Fatal("address weight not equal 0") + } + if multisig.GetWeight([20]byte{1}) != 1 { + t.Fatal("address weight not equal 1") + } + if multisig.GetWeight([20]byte{2}) != 1 { + t.Fatal("address weight not equal 1") + } + if multisig.GetWeight([20]byte{3}) != 2 { + t.Fatal("address weight not equal 2") + } + if multisig.Threshold != 2 { + t.Fatal("threshold not equal 2") + } +} + +func TestAccounts_SetNonce(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + accounts, err := NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + accounts.SetNonce([20]byte{4}, 5) + if accounts.GetNonce([20]byte{4}) != 5 { + t.Fatal("nonce not equal 5") + } +} + +func TestAccounts_SetBalance(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + accounts, err := NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + accounts.SetBalance([20]byte{4}, 0, big.NewInt(1000)) + account := accounts.GetAccount([20]byte{4}) + if account == nil { + t.Fatal("account is nil") + } + if account.getBalance(0).String() != "1000" { + t.Fatal("balance of coin ID '0' not equal 1000") + } +} + +func TestAccounts_SetBalance_fromDB(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + accounts, err := NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + accounts.SetBalance([20]byte{4}, 0, big.NewInt(1000)) + err = accounts.Commit() + if err != nil { + t.Fatal(err) + } + accounts, err = NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + if accounts.GetBalance([20]byte{4}, 0).String() != "1000" { + t.Fatal("balance of coin ID '0' not equal 1000") + } +} + +func TestAccounts_SetBalance_0(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + accounts, err := NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + accounts.SetBalance([20]byte{4}, 0, big.NewInt(100)) + accounts.SetBalance([20]byte{4}, 0, big.NewInt(0)) + accounts.SetBalance([20]byte{4}, 1, big.NewInt(0)) + account := accounts.GetAccount([20]byte{4}) + if account == nil { + t.Fatal("account is nil") + } + if accounts.GetBalance([20]byte{4}, 0).String() != "0" { + t.Fatal("balance of coin ID '0' is not 0") + } + if accounts.GetBalance([20]byte{4}, 1).String() != "0" { + t.Fatal("balance of coin ID '1' is not 0") + } +} + +func TestAccounts_GetBalances(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + busCoins, err := coins.NewCoins(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetCoins(coins.NewBus(busCoins)) + accounts, err := NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + accounts.SetBalance([20]byte{4}, 0, big.NewInt(1000)) + + coinsState, err := coins.NewCoins(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + coinsState.Create(1, + types.StrToCoinSymbol("AAA"), + "AAACOIN", + helpers.BipToPip(big.NewInt(10)), + 10, + helpers.BipToPip(big.NewInt(10000)), + big.NewInt(0).Exp(big.NewInt(10), big.NewInt(10+18), nil), + nil) + + err = coinsState.Commit() + if err != nil { + t.Fatal(err) + } + + symbol := coinsState.GetCoinBySymbol(types.StrToCoinSymbol("AAA"), 0) + if symbol == nil { + t.Fatal("coin not found") + } + + accounts.SetBalance([20]byte{4}, symbol.ID(), big.NewInt(1001)) + + balances := accounts.GetBalances([20]byte{4}) + if len(balances) != 2 { + t.Fatal("count of coin on balance not equal 2") + } + if balances[0].Value.String() != "1000" { + t.Fatal("balance of coin ID '0' not equal 1000") + } + if balances[1].Value.String() != "1001" { + t.Log(balances[1].Value.String()) + t.Fatal("balance of coin 'AAA' not equal 1001") + } +} + +func TestAccounts_ExistsMultisig(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + accounts, err := NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + msigAddress := CreateMultisigAddress([20]byte{4}, 12) + if accounts.ExistsMultisig(msigAddress) { + t.Fatal("multisig address is busy") + } + + accounts.SetBalance(msigAddress, 0, big.NewInt(1)) + if accounts.ExistsMultisig(msigAddress) { + t.Fatal("multisig address is busy") + } + + accounts.SetNonce(msigAddress, 1) + if !accounts.ExistsMultisig(msigAddress) { + t.Fatal("multisig address is not busy") + } + + accounts.SetNonce(msigAddress, 0) + + _ = accounts.CreateMultisig([]uint{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, 2, 0, msigAddress) + + if !accounts.ExistsMultisig(msigAddress) { + t.Fatal("multisig address is free") + } +} + +func TestAccounts_AddBalance_bus(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + accounts, err := NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + accounts.SetBalance([20]byte{4}, 0, big.NewInt(1000)) + + accounts.bus.Accounts().AddBalance([20]byte{4}, 0, big.NewInt(1000)) + + if accounts.GetBalance([20]byte{4}, 0).String() != "2000" { + t.Fatal("balance of coin ID '0' not equal 2000") + } +} + +func TestAccounts_SubBalance(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + accounts, err := NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + accounts.SetBalance([20]byte{4}, 0, big.NewInt(1000)) + + accounts.SubBalance([20]byte{4}, 0, big.NewInt(500)) + + account := accounts.GetAccount([20]byte{4}) + if account == nil { + t.Fatal("account is nil") + } + if account.getBalance(0).String() != "500" { + t.Fatal("balance of coin ID '0' not equal 500") + } +} + +func TestAccounts_EditMultisig(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + accounts, err := NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + msigAddress := CreateMultisigAddress([20]byte{4}, 12) + + _ = accounts.CreateMultisig([]uint{3, 3, 6}, []types.Address{[20]byte{1, 1}, [20]byte{2, 3}, [20]byte{3, 3}}, 6, 0, msigAddress) + _ = accounts.EditMultisig(2, []uint{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, msigAddress) + + account := accounts.GetAccount(msigAddress) + if account == nil { + t.Fatal("account is nil") + } + + if !account.IsMultisig() { + t.Fatal("account is not multisig") + } + + multisig := account.Multisig() + if multisig.GetWeight([20]byte{1}) != 1 { + t.Fatal("address weight not equal 1") + } + if multisig.GetWeight([20]byte{2}) != 1 { + t.Fatal("address weight not equal 1") + } + if multisig.GetWeight([20]byte{3}) != 2 { + t.Fatal("address weight not equal 2") + } + if multisig.Threshold != 2 { + t.Fatal("threshold not equal 2") + } +} + +func TestAccounts_Commit(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + accounts, err := NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + accounts.SetBalance([20]byte{4}, 0, big.NewInt(1000)) + + err = accounts.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err := mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if version != 1 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "8DAE826A26BD8A994B690BD6587A7852B3A75586A1A7162B97479A0D618774EF" { + t.Fatalf("hash %X", hash) + } +} + +func TestAccounts_Export(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + busCoins, err := coins.NewCoins(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetCoins(coins.NewBus(busCoins)) + b.SetChecker(checker.NewChecker(b)) + accounts, err := NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + accounts.SetBalance([20]byte{4}, 0, big.NewInt(1000)) + + coinsState, err := coins.NewCoins(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + coinsState.Create(1, + types.StrToCoinSymbol("AAA"), + "AAACOIN", + helpers.BipToPip(big.NewInt(10)), + 10, + helpers.BipToPip(big.NewInt(10000)), + big.NewInt(0).Exp(big.NewInt(10), big.NewInt(10+18), nil), + nil) + + err = coinsState.Commit() + if err != nil { + t.Fatal(err) + } + + symbol := coinsState.GetCoinBySymbol(types.StrToCoinSymbol("AAA"), 0) + if symbol == nil { + t.Fatal("coin not found") + } + + accounts.SetBalance([20]byte{4}, symbol.ID(), big.NewInt(1001)) + _ = accounts.CreateMultisig([]uint{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, 2, 0, [20]byte{4}) + + err = accounts.Commit() + if err != nil { + t.Fatal(err) + } + + state := new(types.AppState) + accounts.Export(state) + + bytes, err := json.Marshal(state.Accounts) + if err != nil { + t.Fatal(err) + } + + if string(bytes) != "[{\"address\":\"Mx0400000000000000000000000000000000000000\",\"balance\":[{\"coin\":1,\"value\":\"1001\"},{\"coin\":0,\"value\":\"1000\"}],\"nonce\":0,\"multisig_data\":{\"weights\":[1,1,2],\"threshold\":2,\"addresses\":[\"Mx0100000000000000000000000000000000000000\",\"Mx0200000000000000000000000000000000000000\",\"Mx0300000000000000000000000000000000000000\"]}}]" { + t.Fatal("not equal JSON") + } +} diff --git a/core/state/accounts/bus.go b/core/state/accounts/bus.go index 1062bf201..9f758f675 100644 --- a/core/state/accounts/bus.go +++ b/core/state/accounts/bus.go @@ -13,10 +13,6 @@ func NewBus(accounts *Accounts) *Bus { return &Bus{accounts: accounts} } -func (b *Bus) DeleteCoin(address types.Address, coin types.CoinID) { - b.accounts.DeleteCoin(address, coin) -} - func (b *Bus) AddBalance(address types.Address, coin types.CoinID, value *big.Int) { b.accounts.AddBalance(address, coin, value) } diff --git a/core/state/accounts/model.go b/core/state/accounts/model.go index c4472a5b3..45fd20867 100644 --- a/core/state/accounts/model.go +++ b/core/state/accounts/model.go @@ -32,19 +32,6 @@ type Multisig struct { Addresses []types.Address } -// Deprecated. Don't use. Use CreateMultisigAddress(owner types.Address, nonce uint64) -func (m *Multisig) Address() types.Address { - b, err := rlp.EncodeToBytes(m) - if err != nil { - panic(err) - } - - var addr types.Address - copy(addr[:], crypto.Keccak256(b)[12:]) - - return addr -} - func CreateMultisigAddress(owner types.Address, nonce uint64) types.Address { b, err := rlp.EncodeToBytes(&struct { Owner types.Address diff --git a/core/state/bus/accounts.go b/core/state/bus/accounts.go index 5fd807a45..f584503e8 100644 --- a/core/state/bus/accounts.go +++ b/core/state/bus/accounts.go @@ -6,6 +6,5 @@ import ( ) type Accounts interface { - DeleteCoin(types.Address, types.CoinID) AddBalance(types.Address, types.CoinID, *big.Int) } diff --git a/core/state/candidates/candidate_test.go b/core/state/candidates/candidate_test.go index b8fdb1e3e..4fe446e0b 100644 --- a/core/state/candidates/candidate_test.go +++ b/core/state/candidates/candidate_test.go @@ -19,7 +19,7 @@ import ( "testing" ) -func TestCandidates_Commit_createOneCandidate(t *testing.T) { +func TestCandidates_Create_oneCandidate(t *testing.T) { mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) candidates, err := NewCandidates(bus.NewBus(), mutableTree) if err != nil { @@ -145,7 +145,7 @@ func TestCandidates_Commit_changePubKeyAndCheckBlockList(t *testing.T) { t.Fatal("pub_key is not blocked") } } -func TestCandidates_Commit_addBlockList(t *testing.T) { +func TestCandidates_AddToBlockPubKey(t *testing.T) { mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) candidates, err := NewCandidates(bus.NewBus(), mutableTree) if err != nil { @@ -608,7 +608,6 @@ func TestCandidates_Export(t *testing.T) { } if string(bytes) != "[{\"id\":1,\"reward_address\":\"Mx0200000000000000000000000000000000000000\",\"owner_address\":\"Mx0100000000000000000000000000000000000000\",\"control_address\":\"Mx0300000000000000000000000000000000000000\",\"total_bip_stake\":\"200\",\"public_key\":\"Mp0400000000000000000000000000000000000000000000000000000000000000\",\"commission\":10,\"stakes\":[{\"owner\":\"Mx0100000000000000000000000000000000000000\",\"coin\":0,\"value\":\"100\",\"bip_value\":\"100\"},{\"owner\":\"Mx0200000000000000000000000000000000000000\",\"coin\":0,\"value\":\"100\",\"bip_value\":\"100\"}],\"updates\":[],\"status\":1}]" { - t.Log(string(bytes)) t.Fatal("not equal JSON") } From 70043de762a4d589086e5a7b9a8338cd83d3a09b Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 10 Sep 2020 15:00:55 +0300 Subject: [PATCH 244/426] tests --- core/state/candidates_test.go | 4 + core/state/frozenfunds/frozen_funds.go | 22 +++- core/state/frozenfunds/frozen_funds_test.go | 115 ++++++++++++++++++++ core/state/halts/halts.go | 5 +- core/state/halts/halts_test.go | 2 +- core/state/state_test.go | 6 +- 6 files changed, 143 insertions(+), 11 deletions(-) create mode 100644 core/state/frozenfunds/frozen_funds_test.go diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index 0353232fb..a32a9e210 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -264,12 +264,16 @@ func TestDoubleSignPenalty(t *testing.T) { st.Candidates.RecalculateStakes(height) + st.FrozenFunds.AddFund(1, addr, pubkey, coin, amount) + var pk ed25519.PubKeyEd25519 copy(pk[:], pubkey[:]) var tmAddr types.TmAddress copy(tmAddr[:], pk.Address().Bytes()) + st.Validators.PunishByzantineValidator(tmAddr) + st.FrozenFunds.PunishFrozenFundsWithAddress(1, 1+candidates.UnbondPeriod, tmAddr) st.Candidates.PunishByzantineCandidate(1, tmAddr) stake := st.Candidates.GetStakeValueOfAddress(pubkey, addr, coin) diff --git a/core/state/frozenfunds/frozen_funds.go b/core/state/frozenfunds/frozen_funds.go index 1eb5641a8..37d03976e 100644 --- a/core/state/frozenfunds/frozen_funds.go +++ b/core/state/frozenfunds/frozen_funds.go @@ -46,15 +46,25 @@ func (f *FrozenFunds) Commit() error { f.lock.Lock() delete(f.dirty, height) + delete(f.list, height) f.lock.Unlock() - data, err := rlp.EncodeToBytes(ff) - if err != nil { - return fmt.Errorf("can't encode object at %d: %v", height, err) - } - path := getPath(height) - f.iavl.Set(path, data) + + if ff.deleted { + f.lock.Lock() + delete(f.list, height) + f.lock.Unlock() + + f.iavl.Remove(path) + } else { + data, err := rlp.EncodeToBytes(ff) + if err != nil { + return fmt.Errorf("can't encode object at %d: %v", height, err) + } + + f.iavl.Set(path, data) + } } return nil diff --git a/core/state/frozenfunds/frozen_funds_test.go b/core/state/frozenfunds/frozen_funds_test.go new file mode 100644 index 000000000..5442fe58c --- /dev/null +++ b/core/state/frozenfunds/frozen_funds_test.go @@ -0,0 +1,115 @@ +package frozenfunds + +import ( + "github.com/MinterTeam/minter-go-node/core/state/bus" + "github.com/MinterTeam/minter-go-node/core/state/checker" + "github.com/MinterTeam/minter-go-node/core/state/coins" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/tree" + db "github.com/tendermint/tm-db" + "math/big" + "testing" +) + +func TestFrozenFundsToAddModel(t *testing.T) { + b, mutableTree := bus.NewBus(), tree.NewMutableTree(0, db.NewMemDB(), 1024) + ff, err := NewFrozenFunds(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + b.SetChecker(checker.NewChecker(b)) + coinsState, err := coins.NewCoins(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + b.SetCoins(coins.NewBus(coinsState)) + + height, addr, pubkey, coin, val := uint64(1), types.Address{0}, types.Pubkey{0}, types.GetBaseCoinID(), big.NewInt(1e18) + + ff.AddFund(height, addr, pubkey, coin, val) + if err := ff.Commit(); err != nil { + t.Fatal(err) + } + + _, _, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + funds := ff.GetFrozenFunds(height) + if funds == nil { + t.Fatal("Funds not found") + } + + if len(funds.List) != 1 { + t.Fatal("Incorrect amount of funds") + } + + if funds.Height() != height { + t.Fatal("Invalid funds data") + } + + f := funds.List[0] + if !pubkey.Equals(*f.CandidateKey) || f.Value.Cmp(val) != 0 || f.Address.Compare(addr) != 0 || f.Coin != coin { + t.Fatal("Invalid funds data") + } +} + +func TestFrozenFundsToDeleteModel(t *testing.T) { + b, mutableTree := bus.NewBus(), tree.NewMutableTree(0, db.NewMemDB(), 1024) + ff, err := NewFrozenFunds(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + b.SetChecker(checker.NewChecker(b)) + coinsState, err := coins.NewCoins(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + b.SetCoins(coins.NewBus(coinsState)) + + height, addr, pubkey, coin, val := uint64(1), types.Address{0}, types.Pubkey{0}, types.GetBaseCoinID(), big.NewInt(1e18) + + ff.AddFund(height, addr, pubkey, coin, val) + if err := ff.Commit(); err != nil { + t.Fatal(err) + } + + _, _, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if funds := ff.GetFrozenFunds(height); funds == nil { + t.Fatal("Funds not found") + } + + ff.Delete(height) + + if err := ff.Commit(); err != nil { + t.Fatal(err) + } + + _, _, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + if funds := ff.GetFrozenFunds(height); funds != nil { + t.Fatal("Funds not deleted") + } +} + +func TestFrozenFundsToDeleteNotExistenFund(t *testing.T) { + b, mutableTree := bus.NewBus(), tree.NewMutableTree(0, db.NewMemDB(), 1024) + ff, err := NewFrozenFunds(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + ff.Delete(0) +} diff --git a/core/state/halts/halts.go b/core/state/halts/halts.go index ba12a4e89..4439ec062 100644 --- a/core/state/halts/halts.go +++ b/core/state/halts/halts.go @@ -48,12 +48,15 @@ func (hb *HaltBlocks) Commit() error { hb.lock.Lock() delete(hb.dirty, height) - delete(hb.list, height) hb.lock.Unlock() path := getPath(height) if haltBlock.deleted { + hb.lock.Lock() + delete(hb.list, height) + hb.lock.Unlock() + hb.iavl.Remove(path) } else { data, err := rlp.EncodeToBytes(haltBlock) diff --git a/core/state/halts/halts_test.go b/core/state/halts/halts_test.go index 0847cc339..1ef49dd0a 100644 --- a/core/state/halts/halts_test.go +++ b/core/state/halts/halts_test.go @@ -81,7 +81,7 @@ func TestBusToAddHaltBlock(t *testing.T) { } hbPubKey := halt.List[0].Pubkey - if hbPubKey != pubkey { + if !hbPubKey.Equals(pubkey) { t.Fatalf("Invalid public key %s. Expected %s", hbPubKey.String(), pubkey.String()) } } diff --git a/core/state/state_test.go b/core/state/state_test.go index 5c9301df9..47f544b6f 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -257,17 +257,17 @@ func TestStateExport(t *testing.T) { } pubkey := types.Pubkey{0} - if newState.HaltBlocks[0].Height != height && newState.HaltBlocks[0].CandidateKey != pubkey { + if newState.HaltBlocks[0].Height != height || !newState.HaltBlocks[0].CandidateKey.Equals(pubkey) { t.Fatal("Wrong new state halt blocks") } pubkey = types.Pubkey{1} - if newState.HaltBlocks[1].Height != height+1 && newState.HaltBlocks[1].CandidateKey != pubkey { + if newState.HaltBlocks[1].Height != height+1 || !newState.HaltBlocks[1].CandidateKey.Equals(pubkey) { t.Fatal("Wrong new state halt blocks") } pubkey = types.Pubkey{2} - if newState.HaltBlocks[2].Height != height+2 && newState.HaltBlocks[2].CandidateKey != pubkey { + if newState.HaltBlocks[2].Height != height+2 || !newState.HaltBlocks[2].CandidateKey.Equals(pubkey) { t.Fatal("Wrong new state halt blocks") } } From e2875a12d440df457bf2c7d1a1ae5d14709d4815 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 10 Sep 2020 15:20:29 +0300 Subject: [PATCH 245/426] remove unused code --- core/state/waitlist/model.go | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/core/state/waitlist/model.go b/core/state/waitlist/model.go index 1d08ac13a..0ddc7be37 100644 --- a/core/state/waitlist/model.go +++ b/core/state/waitlist/model.go @@ -25,15 +25,3 @@ func (m *Model) AddToList(candidateId uint32, coin types.CoinID, value *big.Int) Value: value, }) } - -func (m *Model) GetValue(candidateId uint32, coin types.CoinID) *big.Int { - value := big.NewInt(0) - - for _, item := range m.List { - if item.CandidateId == candidateId && item.Coin == coin { - value.Add(value, item.Value) - } - } - - return value -} From 4d3d97dd5bd6835a4cb521aa07c235e313356d26 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 10 Sep 2020 16:26:19 +0300 Subject: [PATCH 246/426] waitlist tests --- core/state/waitlist/waitlist_test.go | 54 ++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 core/state/waitlist/waitlist_test.go diff --git a/core/state/waitlist/waitlist_test.go b/core/state/waitlist/waitlist_test.go new file mode 100644 index 000000000..345dc899f --- /dev/null +++ b/core/state/waitlist/waitlist_test.go @@ -0,0 +1,54 @@ +package waitlist + +import ( + "github.com/MinterTeam/minter-go-node/core/state/bus" + "github.com/MinterTeam/minter-go-node/core/state/candidates" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/tree" + db "github.com/tendermint/tm-db" + "math/big" + "testing" +) + +func TestWaitListToGetByAddressAndPubKey(t *testing.T) { + b := bus.NewBus() + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + + wl, err := NewWaitList(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + candidatesState, err := candidates.NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + addr, pubkey, coin, val := types.Address{0}, types.Pubkey{0}, types.GetBaseCoinID(), big.NewInt(1e18) + + candidatesState.Create(addr, addr, addr, pubkey, 10) + + wl.AddWaitList(addr, pubkey, coin, val) + if err := wl.Commit(); err != nil { + t.Fatal(err) + } + + _, _, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + items := wl.GetByAddressAndPubKey(addr, pubkey) + if len(items) != 1 { + t.Fatal("Incorrect amount of items in waitlist") + } + + if items[0].Value.Cmp(val) != 0 || items[0].Coin != coin { + t.Fatal("Invalid waitlist data") + } + + model := wl.GetByAddress(addr) + if len(model.List) != 1 { + t.Fatal("Incorrect amount of items in waitlist") + } +} From 951c984c109483243ebdf46990d4a91d90be3494 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 10 Sep 2020 16:32:18 +0300 Subject: [PATCH 247/426] fix waitlist export --- core/state/state_test.go | 18 +++++++++++++++ core/state/waitlist/waitlist.go | 40 +++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/core/state/state_test.go b/core/state/state_test.go index 47f544b6f..a80fcaaa2 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -94,6 +94,12 @@ func TestStateExport(t *testing.T) { state.Halts.AddHaltBlock(height+1, types.Pubkey{1}) state.Halts.AddHaltBlock(height+2, types.Pubkey{2}) + wlAddr1 := types.StringToAddress("1") + wlAddr2 := types.StringToAddress("2") + + state.Waitlist.AddWaitList(wlAddr1, candidatePubKey1, coinTestID, big.NewInt(1e18)) + state.Waitlist.AddWaitList(wlAddr2, candidatePubKey2, coinTest2ID, big.NewInt(2e18)) + _, err = state.Commit() if err != nil { log.Panicf("Cannot commit state: %s", err) @@ -270,4 +276,16 @@ func TestStateExport(t *testing.T) { if newState.HaltBlocks[2].Height != height+2 || !newState.HaltBlocks[2].CandidateKey.Equals(pubkey) { t.Fatal("Wrong new state halt blocks") } + + if len(newState.Waitlist) != 2 { + t.Fatalf("Invalid amount of waitlist: %d. Expected 2", len(newState.Waitlist)) + } + + if newState.Waitlist[0].Coin != coinTest2ID || newState.Waitlist[0].Value != big.NewInt(2e18).String() || newState.Waitlist[0].Owner.Compare(wlAddr2) != 0 { + t.Fatal("Invalid waitlist data") + } + + if newState.Waitlist[1].Coin != coinTestID || newState.Waitlist[1].Value != big.NewInt(1e18).String() || newState.Waitlist[1].Owner.Compare(wlAddr1) != 0 { + t.Fatal("Invalid waitlist data") + } } diff --git a/core/state/waitlist/waitlist.go b/core/state/waitlist/waitlist.go index 4c9288360..55f0b2352 100644 --- a/core/state/waitlist/waitlist.go +++ b/core/state/waitlist/waitlist.go @@ -45,23 +45,29 @@ func NewWaitList(stateBus *bus.Bus, iavl tree.MTree) (*WaitList, error) { } func (wl *WaitList) Export(state *types.AppState) { - var waitlist []*Model - for _, model := range wl.list { - waitlist = append(waitlist, model) - } - sort.Slice(waitlist, func(i, j int) bool { - return waitlist[i].address.Compare(waitlist[j].address) > 0 - }) - for _, model := range waitlist { - for _, item := range model.List { - state.Waitlist = append(state.Waitlist, types.Waitlist{ - CandidateID: item.CandidateId, - Owner: model.address, - Coin: item.Coin, - Value: item.Value.String(), - }) + wl.iavl.Iterate(func(key []byte, value []byte) bool { + if key[0] == mainPrefix { + address := types.BytesToAddress(key[1:]) + + model := wl.GetByAddress(address) + if model != nil && len(model.List) != 0 { + for _, w := range model.List { + state.Waitlist = append(state.Waitlist, types.Waitlist{ + CandidateID: w.CandidateId, + Owner: address, + Coin: w.Coin, + Value: w.Value.String(), + }) + } + } } - } + + return false + }) + + sort.SliceStable(state.Waitlist, func(i, j int) bool { + return bytes.Compare(state.Waitlist[i].Owner.Bytes(), state.Waitlist[j].Owner.Bytes()) == 1 + }) } func (wl *WaitList) Commit() error { @@ -120,7 +126,7 @@ func (wl *WaitList) GetByAddressAndPubKey(address types.Address, pubkey types.Pu log.Panicf("Candidate not found: %s", pubkey.String()) } - items := make([]Item, 0, len(waitlist.List)) + items := make([]Item, len(waitlist.List)) for i, item := range waitlist.List { if item.CandidateId == candidate.ID { items[i] = item From 4631ffe312340804bb7622c22360642c5d1bd41d Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 10 Sep 2020 16:39:43 +0300 Subject: [PATCH 248/426] move legacy --- core/state/state.go | 10 +++++----- {core/state/legacy => legacy}/accounts/accounts.go | 0 {core/state/legacy => legacy}/accounts/model.go | 0 {core/state/legacy => legacy}/app/app.go | 0 {core/state/legacy => legacy}/app/model.go | 0 {core/state/legacy => legacy}/candidates/candidates.go | 0 {core/state/legacy => legacy}/candidates/model.go | 0 {core/state/legacy => legacy}/coins/coins.go | 0 {core/state/legacy => legacy}/coins/model.go | 0 .../legacy => legacy}/frozenfunds/frozen_funds.go | 0 {core/state/legacy => legacy}/frozenfunds/model.go | 0 11 files changed, 5 insertions(+), 5 deletions(-) rename {core/state/legacy => legacy}/accounts/accounts.go (100%) rename {core/state/legacy => legacy}/accounts/model.go (100%) rename {core/state/legacy => legacy}/app/app.go (100%) rename {core/state/legacy => legacy}/app/model.go (100%) rename {core/state/legacy => legacy}/candidates/candidates.go (100%) rename {core/state/legacy => legacy}/candidates/model.go (100%) rename {core/state/legacy => legacy}/coins/coins.go (100%) rename {core/state/legacy => legacy}/coins/model.go (100%) rename {core/state/legacy => legacy}/frozenfunds/frozen_funds.go (100%) rename {core/state/legacy => legacy}/frozenfunds/model.go (100%) diff --git a/core/state/state.go b/core/state/state.go index 70183296a..20a173bc3 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -13,15 +13,15 @@ import ( "github.com/MinterTeam/minter-go-node/core/state/coins" "github.com/MinterTeam/minter-go-node/core/state/frozenfunds" "github.com/MinterTeam/minter-go-node/core/state/halts" - legacyAccounts "github.com/MinterTeam/minter-go-node/core/state/legacy/accounts" - legacyApp "github.com/MinterTeam/minter-go-node/core/state/legacy/app" - legacyCandidates "github.com/MinterTeam/minter-go-node/core/state/legacy/candidates" - legacyCoins "github.com/MinterTeam/minter-go-node/core/state/legacy/coins" - legacyFrozenfunds "github.com/MinterTeam/minter-go-node/core/state/legacy/frozenfunds" "github.com/MinterTeam/minter-go-node/core/state/validators" "github.com/MinterTeam/minter-go-node/core/state/waitlist" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/helpers" + legacyAccounts "github.com/MinterTeam/minter-go-node/legacy/accounts" + legacyApp "github.com/MinterTeam/minter-go-node/legacy/app" + legacyCandidates "github.com/MinterTeam/minter-go-node/legacy/candidates" + legacyCoins "github.com/MinterTeam/minter-go-node/legacy/coins" + legacyFrozenfunds "github.com/MinterTeam/minter-go-node/legacy/frozenfunds" "github.com/MinterTeam/minter-go-node/tree" db "github.com/tendermint/tm-db" "log" diff --git a/core/state/legacy/accounts/accounts.go b/legacy/accounts/accounts.go similarity index 100% rename from core/state/legacy/accounts/accounts.go rename to legacy/accounts/accounts.go diff --git a/core/state/legacy/accounts/model.go b/legacy/accounts/model.go similarity index 100% rename from core/state/legacy/accounts/model.go rename to legacy/accounts/model.go diff --git a/core/state/legacy/app/app.go b/legacy/app/app.go similarity index 100% rename from core/state/legacy/app/app.go rename to legacy/app/app.go diff --git a/core/state/legacy/app/model.go b/legacy/app/model.go similarity index 100% rename from core/state/legacy/app/model.go rename to legacy/app/model.go diff --git a/core/state/legacy/candidates/candidates.go b/legacy/candidates/candidates.go similarity index 100% rename from core/state/legacy/candidates/candidates.go rename to legacy/candidates/candidates.go diff --git a/core/state/legacy/candidates/model.go b/legacy/candidates/model.go similarity index 100% rename from core/state/legacy/candidates/model.go rename to legacy/candidates/model.go diff --git a/core/state/legacy/coins/coins.go b/legacy/coins/coins.go similarity index 100% rename from core/state/legacy/coins/coins.go rename to legacy/coins/coins.go diff --git a/core/state/legacy/coins/model.go b/legacy/coins/model.go similarity index 100% rename from core/state/legacy/coins/model.go rename to legacy/coins/model.go diff --git a/core/state/legacy/frozenfunds/frozen_funds.go b/legacy/frozenfunds/frozen_funds.go similarity index 100% rename from core/state/legacy/frozenfunds/frozen_funds.go rename to legacy/frozenfunds/frozen_funds.go diff --git a/core/state/legacy/frozenfunds/model.go b/legacy/frozenfunds/model.go similarity index 100% rename from core/state/legacy/frozenfunds/model.go rename to legacy/frozenfunds/model.go From 41b4814ecf8bd7169d018ab8650f8c471267576c Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 11 Sep 2020 14:45:19 +0300 Subject: [PATCH 249/426] tests --- core/state/candidates/bus.go | 5 + core/state/candidates/candidates.go | 4 +- core/state/validators/model.go | 3 + core/state/validators/validators.go | 32 +- core/state/validators/validators_test.go | 459 +++++++++++++++++++++++ go.mod | 2 +- go.sum | 4 +- 7 files changed, 486 insertions(+), 23 deletions(-) create mode 100644 core/state/validators/validators_test.go diff --git a/core/state/candidates/bus.go b/core/state/candidates/bus.go index 362a95195..8585a099a 100644 --- a/core/state/candidates/bus.go +++ b/core/state/candidates/bus.go @@ -14,6 +14,7 @@ func NewBus(candidates *Candidates) *Bus { return &Bus{candidates: candidates} } +// GetStakes returns list of stakes of candidate with given public key func (b *Bus) GetStakes(pubkey types.Pubkey) []bus.Stake { stakes := b.candidates.GetStakes(pubkey) var result []bus.Stake @@ -30,10 +31,12 @@ func (b *Bus) GetStakes(pubkey types.Pubkey) []bus.Stake { return result } +// Punish punished a candidate with given tendermint-address func (b *Bus) Punish(height uint64, address types.TmAddress) *big.Int { return b.candidates.Punish(height, address) } +// GetCandidate returns candidate by a public key func (b *Bus) GetCandidate(pubkey types.Pubkey) *bus.Candidate { candidate := b.candidates.GetCandidate(pubkey) if candidate == nil { @@ -51,10 +54,12 @@ func (b *Bus) GetCandidate(pubkey types.Pubkey) *bus.Candidate { } } +// SetOffline sets candidate status to CandidateStatusOffline func (b *Bus) SetOffline(pubkey types.Pubkey) { b.candidates.SetOffline(pubkey) } +// GetCandidateByTendermintAddress finds and returns candidate with given tendermint-address func (b *Bus) GetCandidateByTendermintAddress(tmAddress types.TmAddress) *bus.Candidate { candidate := b.candidates.GetCandidateByTendermintAddress(tmAddress) if candidate == nil { diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 41f8054a2..48fcd117d 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -607,7 +607,7 @@ func (c *Candidates) GetCandidateControl(pubkey types.Pubkey) types.Address { return c.getFromMap(pubkey).ControlAddress } -// LoadCandidates Loads only list of candidates (for read) +// LoadCandidates loads only list of candidates (for read) func (c *Candidates) LoadCandidates() { if c.checkAndSetLoaded() { return @@ -616,7 +616,7 @@ func (c *Candidates) LoadCandidates() { _ = c.loadCandidatesList() } -// LoadCandidatesDeliver Loads full info about candidates (for edit) +// LoadCandidatesDeliver loads full info about candidates (for edit) func (c *Candidates) LoadCandidatesDeliver() { if c.checkAndSetLoaded() { return diff --git a/core/state/validators/model.go b/core/state/validators/model.go index abaa5723e..a057db532 100644 --- a/core/state/validators/model.go +++ b/core/state/validators/model.go @@ -55,14 +55,17 @@ func (v *Validator) GetAccumReward() *big.Int { return big.NewInt(0).Set(v.accumReward) } +// GetAddress returns tendermint-address of a validator func (v *Validator) GetAddress() types.TmAddress { return v.tmAddress } +// GetTotalBipStake returns total bip stake func (v *Validator) GetTotalBipStake() *big.Int { return big.NewInt(0).Set(v.totalStake) } +// SetTotalBipStake sets total bip stake func (v *Validator) SetTotalBipStake(value *big.Int) { if v.totalStake.Cmp(value) != 0 { v.isTotalStakeDirty = true diff --git a/core/state/validators/validators.go b/core/state/validators/validators.go index c035165d5..1452cd61a 100644 --- a/core/state/validators/validators.go +++ b/core/state/validators/validators.go @@ -25,6 +25,7 @@ const ( ValidatorMaxAbsentTimes = 12 ) +// Validators struct is a store of Validators state type Validators struct { list []*Validator loaded bool @@ -33,6 +34,7 @@ type Validators struct { bus *bus.Bus } +// RValidators interface represents Validator state type RValidators interface { GetValidators() []*Validator Export(state *types.AppState) @@ -41,28 +43,14 @@ type RValidators interface { GetByTmAddress(address types.TmAddress) *Validator } -func NewReadValidators(bus *bus.Bus, iavl tree.MTree) (RValidators, error) { - validators := &Validators{iavl: iavl, bus: bus} - - return validators, nil -} - -type RWValidators interface { - RValidators - Commit() error - SetValidatorPresent(height uint64, address types.TmAddress) - SetValidatorAbsent(height uint64, address types.TmAddress) - PunishByzantineValidator(tmAddress [20]byte) - PayRewards(height uint64) - SetNewValidators(candidates []candidates.Candidate) -} - +// NewValidators returns newly created Validators state with a given bus and iavl func NewValidators(bus *bus.Bus, iavl tree.MTree) (*Validators, error) { validators := &Validators{iavl: iavl, bus: bus} return validators, nil } +// Commit writes changes to iavl, may return an error func (v *Validators) Commit() error { if v.hasDirtyValidators() { data, err := rlp.EncodeToBytes(v.list) @@ -118,6 +106,7 @@ func (v *Validators) SetValidatorAbsent(height uint64, address types.TmAddress) } } +// GetValidators returns list of validators func (v *Validators) GetValidators() []*Validator { return v.list } @@ -138,7 +127,6 @@ func (v *Validators) SetNewValidators(candidates []candidates.Candidate) { } newVals = append(newVals, &Validator{ - PubKey: candidate.PubKey, AbsentTimes: absentTimes, totalStake: candidate.GetTotalBipStake(), @@ -151,9 +139,12 @@ func (v *Validators) SetNewValidators(candidates []candidates.Candidate) { }) } - v.list = newVals + v.SetValidators(newVals) } +// PunishByzantineValidator find validator with given tmAddress and punishes it: +// 1. Set total stake 0 +// 2. Drop validator func (v *Validators) PunishByzantineValidator(tmAddress [20]byte) { validator := v.GetByTmAddress(tmAddress) if validator != nil { @@ -163,6 +154,7 @@ func (v *Validators) PunishByzantineValidator(tmAddress [20]byte) { } } +// Create creates a new validator with given params and adds it to state func (v *Validators) Create(pubkey types.Pubkey, stake *big.Int) { val := &Validator{ PubKey: pubkey, @@ -266,6 +258,7 @@ func (v *Validators) PayRewards(height uint64) { } } +// GetByTmAddress finds and returns validator with given tendermint-address func (v *Validators) GetByTmAddress(address types.TmAddress) *Validator { for _, val := range v.list { if val.tmAddress == address { @@ -276,6 +269,7 @@ func (v *Validators) GetByTmAddress(address types.TmAddress) *Validator { return nil } +// GetByPublicKey finds and returns validator func (v *Validators) GetByPublicKey(pubKey types.Pubkey) *Validator { for _, val := range v.list { if val.PubKey == pubKey { @@ -286,6 +280,7 @@ func (v *Validators) GetByPublicKey(pubKey types.Pubkey) *Validator { return nil } +// LoadValidators loads only list of validators (for read) func (v *Validators) LoadValidators() { if v.loaded { return @@ -359,6 +354,7 @@ func (v *Validators) SetValidators(vals []*Validator) { v.list = vals } +// Export exports all data to the given state func (v *Validators) Export(state *types.AppState) { v.LoadValidators() diff --git a/core/state/validators/validators_test.go b/core/state/validators/validators_test.go new file mode 100644 index 000000000..2e00bfc3b --- /dev/null +++ b/core/state/validators/validators_test.go @@ -0,0 +1,459 @@ +package validators + +import ( + "encoding/json" + "fmt" + "github.com/MinterTeam/minter-go-node/core/dao" + "github.com/MinterTeam/minter-go-node/core/developers" + eventsdb "github.com/MinterTeam/minter-go-node/core/events" + "github.com/MinterTeam/minter-go-node/core/state/accounts" + "github.com/MinterTeam/minter-go-node/core/state/app" + "github.com/MinterTeam/minter-go-node/core/state/bus" + "github.com/MinterTeam/minter-go-node/core/state/candidates" + "github.com/MinterTeam/minter-go-node/core/state/checker" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/tree" + db "github.com/tendermint/tm-db" + "math/big" + "testing" +) + +func TestValidators_GetValidators(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + + validators, err := NewValidators(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + validators.Create([32]byte{1}, big.NewInt(1000000)) + validators.Create([32]byte{2}, big.NewInt(2000000)) + getValidators := validators.GetValidators() + if len(getValidators) != 2 { + t.Fatal("count of validators not equal 2") + } + if getValidators[0].PubKey != [32]byte{1} { + t.Fatal("validator public_key invalid") + } + if getValidators[0].totalStake.String() != "1000000" { + t.Fatal("validator total_stake invalid") + } + if getValidators[1].PubKey != [32]byte{2} { + t.Fatal("validator public_key invalid") + } + if getValidators[1].totalStake.String() != "2000000" { + t.Fatal("validator total_stake invalid") + } +} + +func TestValidators_GetByPublicKey(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + + validators, err := NewValidators(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + validators.Create([32]byte{1}, big.NewInt(1000000)) + validator := validators.GetByPublicKey([32]byte{1}) + if validator == nil { + t.Fatal("validator not found") + } + if validator.PubKey != [32]byte{1} { + t.Fatal("validator public_key invalid") + } + if validator.totalStake.String() != "1000000" { + t.Fatal("validator total_stake invalid") + } +} + +func TestValidators_GetByTmAddress(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + + validators, err := NewValidators(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + validators.Create([32]byte{1}, big.NewInt(1000000)) + validator := validators.GetByPublicKey([32]byte{1}) + if validator == nil { + t.Fatal("validator not found") + } + vldtr := validators.GetByTmAddress(validator.tmAddress) + + if vldtr.PubKey != [32]byte{1} { + t.Fatal("validator public_key invalid") + } + if vldtr.totalStake.String() != "1000000" { + t.Fatal("validator total_stake invalid") + } +} + +func TestValidators_PunishByzantineValidator(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + + validators, err := NewValidators(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + validators.Create([32]byte{1}, big.NewInt(1000000)) + validator := validators.GetByPublicKey([32]byte{1}) + if validator == nil { + t.Fatal("validator not found") + } + + validators.PunishByzantineValidator(validator.tmAddress) + + if validator.totalStake.String() != "0" { + t.Fatal("validator total_stake invalid") + } +} + +func TestValidators_LoadValidators(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + validators, err := NewValidators(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + newValidator := NewValidator( + [32]byte{1}, + types.NewBitArray(ValidatorMaxAbsentWindow), + big.NewInt(1000000), + big.NewInt(0), + true, + true, + true, + b) + newValidator.AddAccumReward(big.NewInt(10)) + validators.SetValidators([]*Validator{newValidator}) + + validators.Create([32]byte{2}, big.NewInt(2000000)) + + err = validators.Commit() + if err != nil { + t.Fatal(err) + } + + validators, err = NewValidators(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + validators.LoadValidators() + + getValidators := validators.GetValidators() + if len(getValidators) != 2 { + t.Fatal("count of validators not equal 2") + } + if getValidators[0].PubKey != [32]byte{1} { + t.Fatal("validator public_key invalid") + } + if getValidators[0].totalStake.String() != "1000000" { + t.Fatal("validator total_stake invalid") + } + if getValidators[1].PubKey != [32]byte{2} { + t.Fatal("validator public_key invalid") + } + if getValidators[1].totalStake.String() != "2000000" { + t.Fatal("validator total_stake invalid") + } +} + +func TestValidators_SetValidators(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + + validators, err := NewValidators(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + newValidator := NewValidator( + [32]byte{1}, + types.NewBitArray(ValidatorMaxAbsentWindow), + big.NewInt(1000000), + big.NewInt(0), + true, + true, + true, + b) + validators.SetValidators([]*Validator{newValidator}) + + validator := validators.GetByPublicKey([32]byte{1}) + if validator == nil { + t.Fatal("validator not found") + } + if validator.PubKey != [32]byte{1} { + t.Fatal("validator public_key invalid") + } + if validator.totalStake.String() != "1000000" { + t.Fatal("validator total_stake invalid") + } +} + +func TestValidators_PayRewards(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + accs, err := accounts.NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetAccounts(accounts.NewBus(accs)) + b.SetChecker(checker.NewChecker(b)) + b.SetEvents(eventsdb.NewEventsStore(db.NewMemDB())) + appBus, err := app.NewApp(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetApp(appBus) + validators, err := NewValidators(b, mutableTree) + if err != nil { + t.Fatal(err) + } + newValidator := NewValidator( + [32]byte{4}, + types.NewBitArray(ValidatorMaxAbsentWindow), + big.NewInt(1000000), + big.NewInt(10), + true, + true, + true, + b) + validators.SetValidators([]*Validator{newValidator}) + validator := validators.GetByPublicKey([32]byte{4}) + if validator == nil { + t.Fatal("validator not found") + } + validator.AddAccumReward(big.NewInt(90)) + candidatesS, err := candidates.NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + candidatesS.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + candidatesS.SetOnline([32]byte{4}) + candidatesS.SetStakes([32]byte{4}, []types.Stake{ + { + Owner: [20]byte{1}, + Coin: 0, + Value: "10000", + BipValue: "10000", + }, + }, nil) + candidatesS.RecalculateStakes(0) + validators.SetNewValidators(candidatesS.GetNewCandidates(1)) + + validators.PayRewards(0) + + if accs.GetBalance([20]byte{1}, 0).String() != "72" { + t.Fatal("delegate did not receive the award") + } + if accs.GetBalance([20]byte{2}, 0).String() != "8" { + t.Fatal("rewards_address did not receive the award") + } + + if accs.GetBalance(dao.Address, 0).String() != "10" { + t.Fatal("dao_address did not receive the award") + } + if accs.GetBalance(developers.Address, 0).String() != "10" { + t.Fatal("developers_address did not receive the award") + } +} + +func TestValidators_SetValidatorAbsent(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + accs, err := accounts.NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetAccounts(accounts.NewBus(accs)) + b.SetChecker(checker.NewChecker(b)) + b.SetEvents(eventsdb.NewEventsStore(db.NewMemDB())) + appBus, err := app.NewApp(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetApp(appBus) + validators, err := NewValidators(b, mutableTree) + if err != nil { + t.Fatal(err) + } + newValidator := NewValidator( + [32]byte{4}, + types.NewBitArray(ValidatorMaxAbsentWindow), + big.NewInt(1000000), + big.NewInt(100), + true, + true, + true, + b) + validators.SetValidators([]*Validator{newValidator}) + + candidatesS, err := candidates.NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + candidatesS.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + candidatesS.SetOnline([32]byte{4}) + candidatesS.SetStakes([32]byte{4}, []types.Stake{ + { + Owner: [20]byte{1}, + Coin: 0, + Value: "10000", + BipValue: "10000", + }, + }, nil) + candidatesS.RecalculateStakes(0) + validators.SetNewValidators(candidatesS.GetNewCandidates(1)) + + validator := validators.GetByPublicKey([32]byte{4}) + if validator == nil { + t.Fatal("validator not found") + } + for i := uint64(0); i < ValidatorMaxAbsentTimes+1; i++ { + validators.SetValidatorAbsent(i, validator.tmAddress) + } + if !validator.IsToDrop() { + t.Fatal("validator not drop") + } +} +func TestValidators_SetValidatorPresent(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + + validators, err := NewValidators(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + validators.Create([32]byte{4}, big.NewInt(1000000)) + + validator := validators.GetByPublicKey([32]byte{4}) + if validator == nil { + t.Fatal("validator not found") + } + + validators.SetValidatorAbsent(0, validator.tmAddress) + + if validator.AbsentTimes.String() != "BA{24:x_______________________}" { + t.Fatal("validator has not absent") + } + + validators.SetValidatorPresent(0, validator.tmAddress) + + if validator.AbsentTimes.String() != "BA{24:________________________}" { + t.Fatal("validator has absent") + } +} + +func TestValidators_SetToDrop(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + + validators, err := NewValidators(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + validators.Create([32]byte{4}, big.NewInt(1000000)) + + validator := validators.GetByPublicKey([32]byte{4}) + if validator == nil { + t.Fatal("validator not found") + } + + if validator.toDrop { + t.Fatal("default validator set to drop") + } + validators.SetToDrop([32]byte{4}) + if !validator.toDrop { + t.Fatal("validator not set to drop") + } +} + +func TestValidators_Export(t *testing.T) { + mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + accs, err := accounts.NewAccounts(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetAccounts(accounts.NewBus(accs)) + b.SetChecker(checker.NewChecker(b)) + b.SetEvents(eventsdb.NewEventsStore(db.NewMemDB())) + appBus, err := app.NewApp(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetApp(appBus) + validators, err := NewValidators(b, mutableTree) + if err != nil { + t.Fatal(err) + } + newValidator := NewValidator( + [32]byte{4}, + types.NewBitArray(ValidatorMaxAbsentWindow), + big.NewInt(1000000), + big.NewInt(100), + true, + true, + true, + b) + validators.SetValidators([]*Validator{newValidator}) + + candidatesS, err := candidates.NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + candidatesS.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) + candidatesS.SetOnline([32]byte{4}) + candidatesS.SetStakes([32]byte{4}, []types.Stake{ + { + Owner: [20]byte{1}, + Coin: 0, + Value: "10000", + BipValue: "10000", + }, + }, nil) + candidatesS.RecalculateStakes(0) + validators.SetNewValidators(candidatesS.GetNewCandidates(1)) + + err = validators.Commit() + if err != nil { + t.Fatal(err) + } + + hash, version, err := mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + if version != 1 { + t.Fatalf("version %d", version) + } + + if fmt.Sprintf("%X", hash) != "9387AD1250A4943193BCB44AFF1F4EBFEC626B53FD5A980181AFD7E03079862E" { + t.Fatalf("hash %X", hash) + } + + state := new(types.AppState) + validators.Export(state) + + bytes, err := json.Marshal(state.Validators) + if err != nil { + t.Fatal(err) + } + + if string(bytes) != "[{\"total_bip_stake\":\"10000\",\"public_key\":\"Mp0400000000000000000000000000000000000000000000000000000000000000\",\"accum_reward\":\"100\",\"absent_times\":\"________________________\"}]" { + t.Log(string(bytes)) + t.Fatal("not equal JSON") + } +} diff --git a/go.mod b/go.mod index 3e043ceda..bfd36490c 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200910081617-1c9f3b1d580c + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200910155433-6fd6860b50b9 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 7c1d77c14..89cc337ca 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200910081617-1c9f3b1d580c h1:yxVaVM+pMyakNvcXABbjGnQmZzTXguR03c1uOxDgKNY= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200910081617-1c9f3b1d580c/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200910155433-6fd6860b50b9 h1:n1tgrQ0mvnOl94BTuVpLUvxT4br1CtlgrRmnP2DjOjI= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200910155433-6fd6860b50b9/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 22cbe1874329cb46454da159907f3131d2d72944 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 14 Sep 2020 10:59:53 +0300 Subject: [PATCH 250/426] refactor cli --- cli/cli_pb/manager.pb.go | 407 ++++++++++++++++++++------------------- cli/cli_pb/manager.proto | 47 ++--- cli/service/service.go | 10 +- 3 files changed, 230 insertions(+), 234 deletions(-) diff --git a/cli/cli_pb/manager.pb.go b/cli/cli_pb/manager.pb.go index d8f618af2..a49bfac53 100644 --- a/cli/cli_pb/manager.pb.go +++ b/cli/cli_pb/manager.pb.go @@ -192,10 +192,10 @@ type NetInfoResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Listening bool `protobuf:"varint,4,opt,name=listening,proto3" json:"listening,omitempty"` - Listeners []string `protobuf:"bytes,1,rep,name=listeners,proto3" json:"listeners,omitempty"` - NPeers int64 `protobuf:"varint,2,opt,name=n_peers,json=nPeers,proto3" json:"n_peers,omitempty"` - Peers []*NetInfoResponse_Peer `protobuf:"bytes,3,rep,name=peers,proto3" json:"peers,omitempty"` + Listening bool `protobuf:"varint,4,opt,name=listening,proto3" json:"listening,omitempty"` + Listeners []string `protobuf:"bytes,1,rep,name=listeners,proto3" json:"listeners,omitempty"` + CountPeers int64 `protobuf:"varint,2,opt,name=count_peers,json=countPeers,proto3" json:"count_peers,omitempty"` + Peers []*NetInfoResponse_Peer `protobuf:"bytes,3,rep,name=peers,proto3" json:"peers,omitempty"` } func (x *NetInfoResponse) Reset() { @@ -244,9 +244,9 @@ func (x *NetInfoResponse) GetListeners() []string { return nil } -func (x *NetInfoResponse) GetNPeers() int64 { +func (x *NetInfoResponse) GetCountPeers() int64 { if x != nil { - return x.NPeers + return x.CountPeers } return 0 } @@ -879,10 +879,10 @@ type NetInfoResponse_Peer_ConnectionStatus struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Duration int64 `protobuf:"varint,4,opt,name=Duration,proto3" json:"Duration,omitempty"` + Duration int64 `protobuf:"varint,4,opt,name=duration,proto3" json:"duration,omitempty"` SendMonitor *NetInfoResponse_Peer_ConnectionStatus_Monitor `protobuf:"bytes,1,opt,name=SendMonitor,proto3" json:"SendMonitor,omitempty"` RecvMonitor *NetInfoResponse_Peer_ConnectionStatus_Monitor `protobuf:"bytes,2,opt,name=RecvMonitor,proto3" json:"RecvMonitor,omitempty"` - Channels []*NetInfoResponse_Peer_ConnectionStatus_Channel `protobuf:"bytes,3,rep,name=Channels,proto3" json:"Channels,omitempty"` + Channels []*NetInfoResponse_Peer_ConnectionStatus_Channel `protobuf:"bytes,3,rep,name=channels,proto3" json:"channels,omitempty"` } func (x *NetInfoResponse_Peer_ConnectionStatus) Reset() { @@ -950,19 +950,19 @@ type NetInfoResponse_Peer_ConnectionStatus_Monitor struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Active bool `protobuf:"varint,13,opt,name=Active,proto3" json:"Active,omitempty"` - Start string `protobuf:"bytes,1,opt,name=Start,proto3" json:"Start,omitempty"` - Duration int64 `protobuf:"varint,2,opt,name=Duration,proto3" json:"Duration,omitempty"` - Idle int64 `protobuf:"varint,3,opt,name=Idle,proto3" json:"Idle,omitempty"` - Bytes int64 `protobuf:"varint,4,opt,name=Bytes,proto3" json:"Bytes,omitempty"` - Samples int64 `protobuf:"varint,5,opt,name=Samples,proto3" json:"Samples,omitempty"` - InstRate int64 `protobuf:"varint,6,opt,name=InstRate,proto3" json:"InstRate,omitempty"` - CurRate int64 `protobuf:"varint,7,opt,name=CurRate,proto3" json:"CurRate,omitempty"` - AvgRate int64 `protobuf:"varint,8,opt,name=AvgRate,proto3" json:"AvgRate,omitempty"` - PeakRate int64 `protobuf:"varint,9,opt,name=PeakRate,proto3" json:"PeakRate,omitempty"` - BytesRem int64 `protobuf:"varint,10,opt,name=BytesRem,proto3" json:"BytesRem,omitempty"` - TimeRem int64 `protobuf:"varint,11,opt,name=TimeRem,proto3" json:"TimeRem,omitempty"` - Progress uint32 `protobuf:"varint,12,opt,name=Progress,proto3" json:"Progress,omitempty"` + Active bool `protobuf:"varint,13,opt,name=active,proto3" json:"active,omitempty"` + Start string `protobuf:"bytes,1,opt,name=start,proto3" json:"start,omitempty"` + Duration int64 `protobuf:"varint,2,opt,name=duration,proto3" json:"duration,omitempty"` + Idle int64 `protobuf:"varint,3,opt,name=idle,proto3" json:"idle,omitempty"` + Bytes int64 `protobuf:"varint,4,opt,name=bytes,proto3" json:"bytes,omitempty"` + Samples int64 `protobuf:"varint,5,opt,name=samples,proto3" json:"samples,omitempty"` + InstRate int64 `protobuf:"varint,6,opt,name=inst_rate,json=instRate,proto3" json:"inst_rate,omitempty"` + CurRate int64 `protobuf:"varint,7,opt,name=cur_rate,json=curRate,proto3" json:"cur_rate,omitempty"` + AvgRate int64 `protobuf:"varint,8,opt,name=avg_rate,json=avgRate,proto3" json:"avg_rate,omitempty"` + PeakRate int64 `protobuf:"varint,9,opt,name=peak_rate,json=peakRate,proto3" json:"peak_rate,omitempty"` + BytesRem int64 `protobuf:"varint,10,opt,name=bytes_rem,json=bytesRem,proto3" json:"bytes_rem,omitempty"` + TimeRem int64 `protobuf:"varint,11,opt,name=time_rem,json=timeRem,proto3" json:"time_rem,omitempty"` + Progress uint32 `protobuf:"varint,12,opt,name=progress,proto3" json:"progress,omitempty"` } func (x *NetInfoResponse_Peer_ConnectionStatus_Monitor) Reset() { @@ -1093,11 +1093,11 @@ type NetInfoResponse_Peer_ConnectionStatus_Channel struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ID int32 `protobuf:"varint,5,opt,name=ID,proto3" json:"ID,omitempty"` - SendQueueCapacity int64 `protobuf:"varint,1,opt,name=SendQueueCapacity,proto3" json:"SendQueueCapacity,omitempty"` - SendQueueSize int64 `protobuf:"varint,2,opt,name=SendQueueSize,proto3" json:"SendQueueSize,omitempty"` - Priority int64 `protobuf:"varint,3,opt,name=Priority,proto3" json:"Priority,omitempty"` - RecentlySent int64 `protobuf:"varint,4,opt,name=RecentlySent,proto3" json:"RecentlySent,omitempty"` + Id int32 `protobuf:"varint,5,opt,name=id,proto3" json:"id,omitempty"` + SendQueueCapacity int64 `protobuf:"varint,1,opt,name=send_queue_capacity,json=sendQueueCapacity,proto3" json:"send_queue_capacity,omitempty"` + SendQueueSize int64 `protobuf:"varint,2,opt,name=send_queue_size,json=sendQueueSize,proto3" json:"send_queue_size,omitempty"` + Priority int64 `protobuf:"varint,3,opt,name=priority,proto3" json:"priority,omitempty"` + RecentlySent int64 `protobuf:"varint,4,opt,name=recently_sent,json=recentlySent,proto3" json:"recently_sent,omitempty"` } func (x *NetInfoResponse_Peer_ConnectionStatus_Channel) Reset() { @@ -1132,9 +1132,9 @@ func (*NetInfoResponse_Peer_ConnectionStatus_Channel) Descriptor() ([]byte, []in return file_manager_proto_rawDescGZIP(), []int{1, 0, 0, 1} } -func (x *NetInfoResponse_Peer_ConnectionStatus_Channel) GetID() int32 { +func (x *NetInfoResponse_Peer_ConnectionStatus_Channel) GetId() int32 { if x != nil { - return x.ID + return x.Id } return 0 } @@ -1204,185 +1204,186 @@ var file_manager_proto_rawDesc = []byte{ 0x0a, 0x08, 0x74, 0x78, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x78, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x70, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x72, 0x70, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xda, 0x09, 0x0a, 0x0f, 0x4e, + 0x72, 0x70, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xed, 0x09, 0x0a, 0x0f, 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x5f, - 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x50, 0x65, - 0x65, 0x72, 0x73, 0x12, 0x32, 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, - 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x1a, 0xbd, 0x08, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, - 0x12, 0x2e, 0x0a, 0x13, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6c, - 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x12, 0x2d, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, - 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, - 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, - 0x12, 0x5a, 0x0a, 0x11, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6c, - 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x09, - 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x49, 0x70, 0x1a, 0xbb, 0x06, 0x0a, 0x10, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, - 0x0a, 0x08, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x08, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x57, 0x0a, 0x0b, 0x53, 0x65, - 0x6e, 0x64, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x35, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x2e, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x4d, - 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x6f, 0x6e, 0x69, - 0x74, 0x6f, 0x72, 0x12, 0x57, 0x0a, 0x0b, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x6f, 0x6e, 0x69, 0x74, - 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, - 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, - 0x0b, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x12, 0x51, 0x0a, 0x08, - 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, - 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x43, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x08, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x1a, - 0xd5, 0x02, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x41, - 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x41, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x44, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x44, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x49, 0x64, 0x6c, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x04, 0x49, 0x64, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x42, 0x79, 0x74, - 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, - 0x18, 0x0a, 0x07, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x07, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x49, 0x6e, 0x73, - 0x74, 0x52, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x49, 0x6e, 0x73, - 0x74, 0x52, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x43, 0x75, 0x72, 0x52, 0x61, 0x74, 0x65, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x43, 0x75, 0x72, 0x52, 0x61, 0x74, 0x65, 0x12, - 0x18, 0x0a, 0x07, 0x41, 0x76, 0x67, 0x52, 0x61, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x07, 0x41, 0x76, 0x67, 0x52, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x65, 0x61, - 0x6b, 0x52, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x50, 0x65, 0x61, - 0x6b, 0x52, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x42, 0x79, 0x74, 0x65, 0x73, 0x52, 0x65, - 0x6d, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x42, 0x79, 0x74, 0x65, 0x73, 0x52, 0x65, - 0x6d, 0x12, 0x18, 0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x65, 0x6d, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x65, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x50, - 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x50, - 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x1a, 0xad, 0x01, 0x0a, 0x07, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x02, 0x49, 0x44, 0x12, 0x2c, 0x0a, 0x11, 0x53, 0x65, 0x6e, 0x64, 0x51, 0x75, 0x65, 0x75, 0x65, - 0x43, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, - 0x53, 0x65, 0x6e, 0x64, 0x51, 0x75, 0x65, 0x75, 0x65, 0x43, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, - 0x79, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x6e, 0x64, 0x51, 0x75, 0x65, 0x75, 0x65, 0x53, 0x69, - 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x53, 0x65, 0x6e, 0x64, 0x51, 0x75, - 0x65, 0x75, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x69, 0x6f, 0x72, - 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x50, 0x72, 0x69, 0x6f, 0x72, - 0x69, 0x74, 0x79, 0x12, 0x22, 0x0a, 0x0c, 0x52, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x53, - 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x52, 0x65, 0x63, 0x65, 0x6e, - 0x74, 0x6c, 0x79, 0x53, 0x65, 0x6e, 0x74, 0x22, 0xdd, 0x02, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, - 0x12, 0x26, 0x0a, 0x0f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x70, 0x70, 0x5f, 0x68, - 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x61, 0x74, 0x65, 0x73, - 0x74, 0x41, 0x70, 0x70, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2e, 0x0a, 0x13, 0x6c, 0x61, 0x74, 0x65, + 0x09, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0a, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x32, 0x0a, 0x05, 0x70, + 0x65, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6c, 0x69, + 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x1a, + 0xc8, 0x08, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x13, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x74, 0x65, - 0x73, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x54, 0x69, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x6c, 0x61, 0x73, - 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, - 0x6b, 0x65, 0x65, 0x70, 0x4c, 0x61, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1f, - 0x0a, 0x0b, 0x63, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x70, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0a, 0x63, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x55, 0x70, 0x12, - 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x17, - 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x22, 0x52, 0x0a, 0x12, 0x50, 0x72, 0x75, 0x6e, 0x65, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, - 0x0b, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0a, 0x66, 0x72, 0x6f, 0x6d, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1b, - 0x0a, 0x09, 0x74, 0x6f, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x08, 0x74, 0x6f, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x4b, 0x0a, 0x0f, 0x44, - 0x65, 0x61, 0x6c, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, - 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x65, 0x72, 0x73, - 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x70, 0x65, - 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x8c, 0x05, 0x0a, 0x11, 0x44, 0x61, 0x73, - 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, - 0x0a, 0x0d, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x48, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1a, 0x0a, - 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x65, 0x6d, - 0x6f, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x0b, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, 0x11, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, - 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, - 0x70, 0x65, 0x65, 0x72, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x50, 0x65, 0x65, 0x72, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x65, 0x65, 0x72, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x39, 0x0a, 0x19, 0x61, 0x76, 0x67, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, - 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x61, 0x76, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x50, 0x72, - 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, - 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x50, 0x65, 0x72, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x69, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x69, 0x73, 0x73, 0x65, - 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x6f, 0x74, 0x69, 0x6e, - 0x67, 0x5f, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x76, - 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, - 0x61, 0x6b, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x6b, 0x65, - 0x12, 0x54, 0x0a, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x63, 0x6c, 0x69, - 0x5f, 0x70, 0x62, 0x2e, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x4f, 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0e, 0x0a, 0x0a, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x68, 0x61, - 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x72, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x66, 0x66, - 0x6c, 0x69, 0x6e, 0x65, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x4e, 0x6f, 0x74, 0x44, 0x65, 0x63, - 0x6c, 0x61, 0x72, 0x65, 0x64, 0x10, 0x03, 0x22, 0x45, 0x0a, 0x13, 0x50, 0x72, 0x75, 0x6e, 0x65, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, - 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, - 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x32, 0xcf, - 0x02, 0x0a, 0x0e, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x38, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x4e, - 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x17, - 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x50, 0x72, 0x75, 0x6e, 0x65, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, - 0x50, 0x72, 0x75, 0x6e, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x50, 0x72, 0x75, 0x6e, - 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, - 0x01, 0x12, 0x3b, 0x0a, 0x08, 0x44, 0x65, 0x61, 0x6c, 0x50, 0x65, 0x65, 0x72, 0x12, 0x17, 0x2e, - 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x61, 0x6c, 0x50, 0x65, 0x65, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x40, - 0x0a, 0x09, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x44, 0x61, 0x73, - 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, - 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x3b, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2d, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, + 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x6c, + 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6e, + 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x6f, 0x75, + 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, + 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x5a, 0x0a, 0x11, 0x63, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x65, 0x65, + 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x69, + 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x49, + 0x70, 0x1a, 0xc6, 0x06, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x57, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, + 0x2e, 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x50, 0x65, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x0b, + 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x12, 0x57, 0x0a, 0x0b, 0x52, + 0x65, 0x63, 0x76, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x35, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x2e, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, + 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x0b, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x6f, 0x6e, + 0x69, 0x74, 0x6f, 0x72, 0x12, 0x51, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, + 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x50, 0x65, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x08, 0x63, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x1a, 0xdb, 0x02, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x69, + 0x74, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, 0x0d, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, + 0x04, 0x69, 0x64, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x69, 0x64, 0x6c, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, + 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x12, 0x19, + 0x0a, 0x08, 0x63, 0x75, 0x72, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x07, 0x63, 0x75, 0x72, 0x52, 0x61, 0x74, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x76, 0x67, + 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x61, 0x76, 0x67, + 0x52, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x65, 0x61, 0x6b, 0x5f, 0x72, 0x61, 0x74, + 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x70, 0x65, 0x61, 0x6b, 0x52, 0x61, 0x74, + 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x6d, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x62, 0x79, 0x74, 0x65, 0x73, 0x52, 0x65, 0x6d, 0x12, 0x19, + 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x6d, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x52, 0x65, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, + 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, 0x72, 0x6f, + 0x67, 0x72, 0x65, 0x73, 0x73, 0x1a, 0xb2, 0x01, 0x0a, 0x07, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, + 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, + 0x73, 0x65, 0x6e, 0x64, 0x51, 0x75, 0x65, 0x75, 0x65, 0x43, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, + 0x79, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, + 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x73, 0x65, 0x6e, 0x64, + 0x51, 0x75, 0x65, 0x75, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x69, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x70, 0x72, 0x69, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x6c, + 0x79, 0x5f, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x65, + 0x63, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x53, 0x65, 0x6e, 0x74, 0x22, 0xdd, 0x02, 0x0a, 0x0e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x74, 0x65, 0x73, + 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, + 0x61, 0x73, 0x68, 0x12, 0x26, 0x0a, 0x0f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x70, + 0x70, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x61, + 0x74, 0x65, 0x73, 0x74, 0x41, 0x70, 0x70, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2e, 0x0a, 0x13, 0x6c, + 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x6c, + 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x6b, 0x65, 0x65, 0x70, 0x5f, + 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x6b, 0x65, 0x65, 0x70, 0x4c, 0x61, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x70, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x63, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, + 0x55, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, + 0x79, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x22, 0x52, 0x0a, 0x12, 0x50, 0x72, + 0x75, 0x6e, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x66, 0x72, 0x6f, 0x6d, 0x48, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x74, 0x6f, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x4b, + 0x0a, 0x0f, 0x44, 0x65, 0x61, 0x6c, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x70, + 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0a, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x8c, 0x05, 0x0a, 0x11, + 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, + 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, + 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x2a, 0x0a, 0x11, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x75, 0x62, + 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x0f, 0x6d, + 0x61, 0x78, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x50, 0x65, 0x65, 0x72, 0x48, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x65, 0x65, 0x72, 0x73, 0x5f, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x73, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x19, 0x61, 0x76, 0x67, 0x5f, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x69, 0x6d, + 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x61, 0x76, 0x67, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x54, 0x69, 0x6d, 0x65, 0x12, + 0x24, 0x0a, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x50, 0x65, 0x72, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x69, 0x73, 0x73, 0x65, 0x64, 0x5f, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x69, + 0x73, 0x73, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x6f, + 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x76, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x12, 0x14, 0x0a, + 0x05, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, + 0x61, 0x6b, 0x65, 0x12, 0x54, 0x0a, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, + 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x4f, 0x0a, 0x0f, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0e, 0x0a, 0x0a, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, + 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x72, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, + 0x4f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x4e, 0x6f, 0x74, + 0x44, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x65, 0x64, 0x10, 0x03, 0x22, 0x45, 0x0a, 0x13, 0x50, 0x72, + 0x75, 0x6e, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x74, 0x32, 0xcf, 0x02, 0x0a, 0x0e, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x38, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, + 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x1a, 0x17, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x74, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x50, 0x72, + 0x75, 0x6e, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6c, 0x69, 0x5f, + 0x70, 0x62, 0x2e, 0x50, 0x72, 0x75, 0x6e, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x50, + 0x72, 0x75, 0x6e, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x30, 0x01, 0x12, 0x3b, 0x0a, 0x08, 0x44, 0x65, 0x61, 0x6c, 0x50, 0x65, 0x65, 0x72, + 0x12, 0x17, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x61, 0x6c, 0x50, 0x65, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x40, 0x0a, 0x09, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x12, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x2e, + 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x30, 0x01, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x3b, 0x63, 0x6c, 0x69, 0x5f, 0x70, 0x62, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1427,7 +1428,7 @@ var file_manager_proto_depIdxs = []int32{ 11, // 6: cli_pb.NetInfoResponse.Peer.connection_status:type_name -> cli_pb.NetInfoResponse.Peer.ConnectionStatus 12, // 7: cli_pb.NetInfoResponse.Peer.ConnectionStatus.SendMonitor:type_name -> cli_pb.NetInfoResponse.Peer.ConnectionStatus.Monitor 12, // 8: cli_pb.NetInfoResponse.Peer.ConnectionStatus.RecvMonitor:type_name -> cli_pb.NetInfoResponse.Peer.ConnectionStatus.Monitor - 13, // 9: cli_pb.NetInfoResponse.Peer.ConnectionStatus.Channels:type_name -> cli_pb.NetInfoResponse.Peer.ConnectionStatus.Channel + 13, // 9: cli_pb.NetInfoResponse.Peer.ConnectionStatus.channels:type_name -> cli_pb.NetInfoResponse.Peer.ConnectionStatus.Channel 15, // 10: cli_pb.ManagerService.Status:input_type -> google.protobuf.Empty 15, // 11: cli_pb.ManagerService.NetInfo:input_type -> google.protobuf.Empty 4, // 12: cli_pb.ManagerService.PruneBlocks:input_type -> cli_pb.PruneBlocksRequest diff --git a/cli/cli_pb/manager.proto b/cli/cli_pb/manager.proto index 60457539b..1a9187a71 100644 --- a/cli/cli_pb/manager.proto +++ b/cli/cli_pb/manager.proto @@ -33,7 +33,7 @@ message NodeInfo { message NetInfoResponse { bool listening = 4; repeated string listeners = 1; - int64 n_peers = 2; + int64 count_peers = 2; message Peer { int64 latest_block_height = 5; @@ -43,37 +43,32 @@ message NetInfoResponse { bool is_outbound = 1; message ConnectionStatus { - int64 Duration = 4; - + int64 duration = 4; message Monitor { - bool Active = 13; - string Start = 1; - int64 Duration = 2; - int64 Idle = 3; - int64 Bytes = 4; - int64 Samples = 5; - int64 InstRate = 6; - int64 CurRate = 7; - int64 AvgRate = 8; - int64 PeakRate = 9; - int64 BytesRem = 10; - int64 TimeRem = 11; - uint32 Progress = 12; + bool active = 13; + string start = 1; + int64 duration = 2; + int64 idle = 3; + int64 bytes = 4; + int64 samples = 5; + int64 inst_rate = 6; + int64 cur_rate = 7; + int64 avg_rate = 8; + int64 peak_rate = 9; + int64 bytes_rem = 10; + int64 time_rem = 11; + uint32 progress = 12; } - Monitor SendMonitor = 1; - Monitor RecvMonitor = 2; - message Channel { - int32 ID = 5; - int64 SendQueueCapacity = 1; - int64 SendQueueSize = 2; - int64 Priority = 3; - int64 RecentlySent = 4; + int32 id = 5; + int64 send_queue_capacity = 1; + int64 send_queue_size = 2; + int64 priority = 3; + int64 recently_sent = 4; } - - repeated Channel Channels = 3; + repeated Channel channels = 3; } ConnectionStatus connection_status = 2; diff --git a/cli/service/service.go b/cli/service/service.go index 775a9a515..d2da69cdf 100644 --- a/cli/service/service.go +++ b/cli/service/service.go @@ -143,7 +143,7 @@ func (m *Manager) NetInfo(context.Context, *empty.Empty) (*pb.NetInfoResponse, e channels := make([]*pb.NetInfoResponse_Peer_ConnectionStatus_Channel, 0, len(peer.ConnectionStatus.Channels)) for _, channel := range peer.ConnectionStatus.Channels { channels = append(channels, &pb.NetInfoResponse_Peer_ConnectionStatus_Channel{ - ID: int32(channel.ID), + Id: int32(channel.ID), SendQueueCapacity: int64(channel.SendQueueCapacity), SendQueueSize: int64(channel.SendQueueSize), Priority: int64(channel.Priority), @@ -210,10 +210,10 @@ func (m *Manager) NetInfo(context.Context, *empty.Empty) (*pb.NetInfoResponse, e } response := &pb.NetInfoResponse{ - Listening: resultNetInfo.Listening, - Listeners: resultNetInfo.Listeners, - NPeers: int64(resultNetInfo.NPeers), - Peers: peers, + Listening: resultNetInfo.Listening, + Listeners: resultNetInfo.Listeners, + CountPeers: int64(resultNetInfo.NPeers), + Peers: peers, } return response, nil From 737515981941b3d0f74bbce51ca00897936343ac Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 14 Sep 2020 11:49:56 +0300 Subject: [PATCH 251/426] refactor transactions --- api/v2/service/data_encoder.go | 18 +-- core/commissions/commissions.go | 3 +- core/transaction/decoder.go | 3 +- core/transaction/edit_candidate.go | 27 ---- core/transaction/edit_candidate_public_key.go | 126 ++++++++++++++++++ ...hange_coin_owner.go => edit_coin_owner.go} | 16 +-- ..._owner_test.go => edit_coin_owner_test.go} | 16 +-- core/transaction/encoder/encoder.go | 39 +++--- core/transaction/encoder/resources.go | 32 +++-- core/transaction/executor.go | 2 +- core/transaction/transaction.go | 39 +++--- go.mod | 2 +- go.sum | 4 +- 13 files changed, 220 insertions(+), 107 deletions(-) create mode 100644 core/transaction/edit_candidate_public_key.go rename core/transaction/{change_coin_owner.go => edit_coin_owner.go} (85%) rename core/transaction/{change_coin_owner_test.go => edit_coin_owner_test.go} (94%) diff --git a/api/v2/service/data_encoder.go b/api/v2/service/data_encoder.go index 9e18ebd48..b9745eabb 100644 --- a/api/v2/service/data_encoder.go +++ b/api/v2/service/data_encoder.go @@ -9,7 +9,6 @@ import ( "github.com/golang/protobuf/ptypes/any" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" - "google.golang.org/protobuf/types/known/wrapperspb" "strconv" ) @@ -30,9 +29,9 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { }, MaximumValueToSell: d.MaximumValueToSell.String(), } - case *transaction.ChangeCoinOwnerData: - d := data.(*transaction.ChangeCoinOwnerData) - m = &pb.ChangeCoinOwnerData{ + case *transaction.EditCoinOwnerData: + d := data.(*transaction.EditCoinOwnerData) + m = &pb.EditCoinOwnerData{ Symbol: d.Symbol.String(), NewOwner: d.NewOwner.String(), } @@ -85,17 +84,18 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { } case *transaction.EditCandidateData: d := data.(*transaction.EditCandidateData) - var newPubKey *wrapperspb.StringValue - if d.NewPubKey != nil { - newPubKey = wrapperspb.String(d.NewPubKey.String()) - } m = &pb.EditCandidateData{ PubKey: d.PubKey.String(), - NewPubKey: newPubKey, RewardAddress: d.RewardAddress.String(), OwnerAddress: d.OwnerAddress.String(), ControlAddress: d.ControlAddress.String(), } + case *transaction.EditCandidatePublicKeyData: + d := data.(*transaction.EditCandidatePublicKeyData) + m = &pb.EditCandidatePublicKeyData{ + PubKey: d.PubKey.String(), + NewPubKey: d.NewPubKey.String(), + } case *transaction.EditMultisigOwnersData: d := data.(*transaction.EditMultisigOwnersData) weights := make([]string, 0, len(d.Weights)) diff --git a/core/commissions/commissions.go b/core/commissions/commissions.go index 1c451a557..5598d46a6 100644 --- a/core/commissions/commissions.go +++ b/core/commissions/commissions.go @@ -12,11 +12,12 @@ const ( PayloadByte int64 = 2 ToggleCandidateStatus int64 = 100 EditCandidate int64 = 10000 + EditCandidatePublicKey int64 = 10000 MultisendDelta int64 = 5 RedeemCheckTx = SendTx * 3 SetHaltBlock int64 = 1000 RecreateCoin int64 = 10000000 - ChangeOwner int64 = 10000000 + EditOwner int64 = 10000000 EditMultisigOwnersData int64 = 1000 PriceVoteData int64 = 10 ) diff --git a/core/transaction/decoder.go b/core/transaction/decoder.go index 81bdecb22..47ecd2254 100644 --- a/core/transaction/decoder.go +++ b/core/transaction/decoder.go @@ -28,9 +28,10 @@ func init() { TxDecoder.RegisterType(TypeEditCandidate, EditCandidateData{}) TxDecoder.RegisterType(TypeSetHaltBlock, SetHaltBlockData{}) TxDecoder.RegisterType(TypeRecreateCoin, RecreateCoinData{}) - TxDecoder.RegisterType(TypeChangeCoinOwner, ChangeCoinOwnerData{}) + TxDecoder.RegisterType(TypeEditCoinOwner, EditCoinOwnerData{}) TxDecoder.RegisterType(TypeEditMultisigOwner, EditMultisigOwnersData{}) TxDecoder.RegisterType(TypePriceVote, PriceVoteData{}) + TxDecoder.RegisterType(TypeEditCandidatePublicKey, EditCandidatePublicKeyData{}) } type Decoder struct { diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index 03a5ef203..e79551398 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -20,7 +20,6 @@ type CandidateTx interface { type EditCandidateData struct { PubKey types.Pubkey - NewPubKey *types.Pubkey `rlp:"nil"` RewardAddress types.Address OwnerAddress types.Address ControlAddress types.Address @@ -57,18 +56,6 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa return *response } - if data.NewPubKey != nil && data.PubKey == *data.NewPubKey { - return Response{ - Code: code.NewPublicKeyIsBad, - Log: fmt.Sprintf("Current public key (%s) equals new public key (%s)", data.PubKey.String(), data.NewPubKey.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.NewPublicKeyIsBad)), - "public_key": data.PubKey.String(), - "new_public_key": data.NewPubKey.String(), - }), - } - } - commissionInBaseCoin := tx.CommissionInBaseCoin() commission := big.NewInt(0).Set(commissionInBaseCoin) @@ -96,17 +83,6 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa } } - if data.NewPubKey != nil && checkState.Candidates().IsBlockedPubKey(*data.NewPubKey) { - return Response{ - Code: code.PublicKeyInBlockList, - Log: fmt.Sprintf("Public key (%s) exists in block list", data.NewPubKey.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.PublicKeyInBlockList)), - "new_public_key": data.NewPubKey.String(), - }), - } - } - if deliverState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) @@ -115,9 +91,6 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) deliverState.Candidates.Edit(data.PubKey, data.RewardAddress, data.OwnerAddress, data.ControlAddress) - if data.NewPubKey != nil { - deliverState.Candidates.ChangePubKey(data.PubKey, *data.NewPubKey) - } deliverState.Accounts.SetNonce(sender, tx.Nonce) } diff --git a/core/transaction/edit_candidate_public_key.go b/core/transaction/edit_candidate_public_key.go new file mode 100644 index 000000000..bc20fa708 --- /dev/null +++ b/core/transaction/edit_candidate_public_key.go @@ -0,0 +1,126 @@ +package transaction + +import ( + "encoding/hex" + "fmt" + "math/big" + "strconv" + + "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/commissions" + "github.com/MinterTeam/minter-go-node/core/state" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/formula" + "github.com/tendermint/tendermint/libs/kv" +) + +type EditCandidatePublicKeyData struct { + PubKey types.Pubkey + NewPubKey types.Pubkey +} + +func (data EditCandidatePublicKeyData) GetPubKey() types.Pubkey { + return data.PubKey +} + +func (data EditCandidatePublicKeyData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { + return checkCandidateOwnership(data, tx, context) +} + +func (data EditCandidatePublicKeyData) String() string { + return fmt.Sprintf("EDIT CANDIDATE PUB KEY old: %x, new: %x", + data.PubKey, data.NewPubKey) +} + +func (data EditCandidatePublicKeyData) Gas() int64 { + return commissions.EditCandidatePublicKey +} + +func (data EditCandidatePublicKeyData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { + sender, _ := tx.Sender() + + var checkState *state.CheckState + var isCheck bool + if checkState, isCheck = context.(*state.CheckState); !isCheck { + checkState = state.NewCheckState(context.(*state.State)) + } + + response := data.BasicCheck(tx, checkState) + if response != nil { + return *response + } + + if data.PubKey == data.NewPubKey { + return Response{ + Code: code.NewPublicKeyIsBad, + Log: fmt.Sprintf("Current public key (%s) equals new public key (%s)", data.PubKey.String(), data.NewPubKey.String()), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.NewPublicKeyIsBad)), + "public_key": data.PubKey.String(), + "new_public_key": data.NewPubKey.String(), + }), + } + } + + commissionInBaseCoin := tx.CommissionInBaseCoin() + commission := big.NewInt(0).Set(commissionInBaseCoin) + + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) + + if !tx.GasCoin.IsBaseCoin() { + errResp := CheckReserveUnderflow(gasCoin, commissionInBaseCoin) + if errResp != nil { + return *errResp + } + + commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) + } + + if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { + return Response{ + Code: code.InsufficientFunds, + Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.InsufficientFunds)), + "sender": sender.String(), + "needed_value": commission.String(), + "coin_symbol": gasCoin.GetFullSymbol(), + }), + } + } + + if checkState.Candidates().IsBlockedPubKey(data.NewPubKey) { + return Response{ + Code: code.PublicKeyInBlockList, + Log: fmt.Sprintf("Public key (%s) exists in block list", data.NewPubKey.String()), + Info: EncodeError(map[string]string{ + "code": strconv.Itoa(int(code.PublicKeyInBlockList)), + "new_public_key": data.NewPubKey.String(), + }), + } + } + + if deliverState, ok := context.(*state.State); ok { + rewardPool.Add(rewardPool, commissionInBaseCoin) + + deliverState.Coins.SubReserve(tx.GasCoin, commissionInBaseCoin) + deliverState.Coins.SubVolume(tx.GasCoin, commission) + + deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) + deliverState.Candidates.ChangePubKey(data.PubKey, data.NewPubKey) + + deliverState.Accounts.SetNonce(sender, tx.Nonce) + } + + tags := kv.Pairs{ + kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeEditCandidatePublicKey)}))}, + kv.Pair{Key: []byte("tx.from"), Value: []byte(hex.EncodeToString(sender[:]))}, + } + + return Response{ + Code: code.OK, + GasUsed: tx.Gas(), + GasWanted: tx.Gas(), + Tags: tags, + } +} diff --git a/core/transaction/change_coin_owner.go b/core/transaction/edit_coin_owner.go similarity index 85% rename from core/transaction/change_coin_owner.go rename to core/transaction/edit_coin_owner.go index d35e85f48..3289ef40a 100644 --- a/core/transaction/change_coin_owner.go +++ b/core/transaction/edit_coin_owner.go @@ -14,12 +14,12 @@ import ( "github.com/tendermint/tendermint/libs/kv" ) -type ChangeCoinOwnerData struct { +type EditCoinOwnerData struct { Symbol types.CoinSymbol NewOwner types.Address } -func (data ChangeCoinOwnerData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { +func (data EditCoinOwnerData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { sender, _ := tx.Sender() info := context.Coins().GetSymbolInfo(data.Symbol) @@ -47,15 +47,15 @@ func (data ChangeCoinOwnerData) BasicCheck(tx *Transaction, context *state.Check return nil } -func (data ChangeCoinOwnerData) String() string { - return fmt.Sprintf("CHANGE OWNER COIN symbol:%s new owner:%s", data.Symbol.String(), data.NewOwner.String()) +func (data EditCoinOwnerData) String() string { + return fmt.Sprintf("EDIT OWNER COIN symbol:%s new owner:%s", data.Symbol.String(), data.NewOwner.String()) } -func (data ChangeCoinOwnerData) Gas() int64 { - return commissions.ChangeOwner +func (data EditCoinOwnerData) Gas() int64 { + return commissions.EditOwner } -func (data ChangeCoinOwnerData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { +func (data EditCoinOwnerData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { sender, _ := tx.Sender() var checkState *state.CheckState @@ -108,7 +108,7 @@ func (data ChangeCoinOwnerData) Run(tx *Transaction, context state.Interface, re } tags := kv.Pairs{ - kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeChangeCoinOwner)}))}, + kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeEditCoinOwner)}))}, kv.Pair{Key: []byte("tx.from"), Value: []byte(hex.EncodeToString(sender[:]))}, kv.Pair{Key: []byte("tx.coin"), Value: []byte(data.Symbol.String())}, } diff --git a/core/transaction/change_coin_owner_test.go b/core/transaction/edit_coin_owner_test.go similarity index 94% rename from core/transaction/change_coin_owner_test.go rename to core/transaction/edit_coin_owner_test.go index 35806a07f..3984262e4 100644 --- a/core/transaction/change_coin_owner_test.go +++ b/core/transaction/edit_coin_owner_test.go @@ -34,7 +34,7 @@ func TestChangeOwnerTx(t *testing.T) { gasCoin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, gasCoin, helpers.BipToPip(big.NewInt(10000))) - data := ChangeCoinOwnerData{ + data := EditCoinOwnerData{ Symbol: getTestCoinSymbol(), NewOwner: newOwner, } @@ -83,7 +83,7 @@ func TestChangeOwnerTxWithWrongOwner(t *testing.T) { createTestCoinWithOwner(cState, newOwner) - data := ChangeCoinOwnerData{ + data := EditCoinOwnerData{ Symbol: getTestCoinSymbol(), NewOwner: newOwner, } @@ -113,7 +113,7 @@ func TestChangeOwnerTxWithWrongSymbol(t *testing.T) { createTestCoinWithOwner(cState, addr) - data := ChangeCoinOwnerData{ + data := EditCoinOwnerData{ Symbol: types.StrToCoinSymbol("UNKNOWN"), NewOwner: newOwner, } @@ -143,7 +143,7 @@ func TestChangeOwnerTxWithInsufficientFunds(t *testing.T) { createTestCoinWithOwner(cState, addr) - data := ChangeCoinOwnerData{ + data := EditCoinOwnerData{ Symbol: getTestCoinSymbol(), NewOwner: newOwner, } @@ -171,7 +171,7 @@ func TestChangeCoinOwnerTxToGasCoinReserveUnderflow(t *testing.T) { customCoin := createTestCoinWithOwner(cState, addr) cState.Coins.SubReserve(customCoin, helpers.BipToPip(big.NewInt(90000))) - data := ChangeCoinOwnerData{ + data := EditCoinOwnerData{ Symbol: types.StrToCoinSymbol("TEST"), NewOwner: newOwner, } @@ -186,7 +186,7 @@ func TestChangeCoinOwnerTxToGasCoinReserveUnderflow(t *testing.T) { GasPrice: 1, ChainID: types.CurrentChainID, GasCoin: customCoin, - Type: TypeChangeCoinOwner, + Type: TypeEditCoinOwner, Data: encodedData, SignatureType: SigTypeSingle, } @@ -206,7 +206,7 @@ func TestChangeCoinOwnerTxToGasCoinReserveUnderflow(t *testing.T) { } } -func makeTestChangeOwnerTx(data ChangeCoinOwnerData, privateKey *ecdsa.PrivateKey) ([]byte, error) { +func makeTestChangeOwnerTx(data EditCoinOwnerData, privateKey *ecdsa.PrivateKey) ([]byte, error) { encodedData, err := rlp.EncodeToBytes(data) if err != nil { return nil, err @@ -217,7 +217,7 @@ func makeTestChangeOwnerTx(data ChangeCoinOwnerData, privateKey *ecdsa.PrivateKe GasPrice: 1, ChainID: types.CurrentChainID, GasCoin: types.GetBaseCoinID(), - Type: TypeChangeCoinOwner, + Type: TypeEditCoinOwner, Data: encodedData, SignatureType: SigTypeSingle, } diff --git a/core/transaction/encoder/encoder.go b/core/transaction/encoder/encoder.go index 3a75a3ec6..bb719212f 100644 --- a/core/transaction/encoder/encoder.go +++ b/core/transaction/encoder/encoder.go @@ -34,25 +34,26 @@ type TransactionResponse struct { } var resourcesConfig = map[transaction.TxType]TxDataResource{ - transaction.TypeSend: new(SendDataResource), - transaction.TypeSellCoin: new(SellCoinDataResource), - transaction.TypeSellAllCoin: new(SellAllCoinDataResource), - transaction.TypeBuyCoin: new(BuyCoinDataResource), - transaction.TypeCreateCoin: new(CreateCoinDataResource), - transaction.TypeDeclareCandidacy: new(DeclareCandidacyDataResource), - transaction.TypeDelegate: new(DelegateDataResource), - transaction.TypeUnbond: new(UnbondDataResource), - transaction.TypeRedeemCheck: new(RedeemCheckDataResource), - transaction.TypeSetCandidateOnline: new(SetCandidateOnDataResource), - transaction.TypeSetCandidateOffline: new(SetCandidateOffDataResource), - transaction.TypeCreateMultisig: new(CreateMultisigDataResource), - transaction.TypeMultisend: new(MultiSendDataResource), - transaction.TypeEditCandidate: new(EditCandidateDataResource), - transaction.TypeSetHaltBlock: new(SetHaltBlockDataResource), - transaction.TypeRecreateCoin: new(RecreateCoinDataResource), - transaction.TypeChangeCoinOwner: new(ChangeCoinOwnerDataResource), - transaction.TypeEditMultisigOwner: new(EditMultisigOwnersResource), - transaction.TypePriceVote: new(PriceVoteResource), + transaction.TypeSend: new(SendDataResource), + transaction.TypeSellCoin: new(SellCoinDataResource), + transaction.TypeSellAllCoin: new(SellAllCoinDataResource), + transaction.TypeBuyCoin: new(BuyCoinDataResource), + transaction.TypeCreateCoin: new(CreateCoinDataResource), + transaction.TypeDeclareCandidacy: new(DeclareCandidacyDataResource), + transaction.TypeDelegate: new(DelegateDataResource), + transaction.TypeUnbond: new(UnbondDataResource), + transaction.TypeRedeemCheck: new(RedeemCheckDataResource), + transaction.TypeSetCandidateOnline: new(SetCandidateOnDataResource), + transaction.TypeSetCandidateOffline: new(SetCandidateOffDataResource), + transaction.TypeCreateMultisig: new(CreateMultisigDataResource), + transaction.TypeMultisend: new(MultiSendDataResource), + transaction.TypeEditCandidate: new(EditCandidateDataResource), + transaction.TypeSetHaltBlock: new(SetHaltBlockDataResource), + transaction.TypeRecreateCoin: new(RecreateCoinDataResource), + transaction.TypeEditCoinOwner: new(EditCoinOwnerDataResource), + transaction.TypeEditMultisigOwner: new(EditMultisigOwnersResource), + transaction.TypePriceVote: new(PriceVoteResource), + transaction.TypeEditCandidatePublicKey: new(EditCandidatePublicKeyResource), } func NewTxEncoderJSON(context *state.CheckState) *TxEncoderJSON { diff --git a/core/transaction/encoder/resources.go b/core/transaction/encoder/resources.go index b93275ca9..539b1ec27 100644 --- a/core/transaction/encoder/resources.go +++ b/core/transaction/encoder/resources.go @@ -283,14 +283,8 @@ type EditCandidateDataResource struct { // Transform returns TxDataResource from given txData. Used for JSON encoder. func (EditCandidateDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { data := txData.(*transaction.EditCandidateData) - var newPubKeyStr *string - if data.NewPubKey != nil { - s := data.NewPubKey.String() - newPubKeyStr = &s - } return EditCandidateDataResource{ PubKey: data.PubKey.String(), - NewPubKey: newPubKeyStr, RewardAddress: data.RewardAddress.String(), OwnerAddress: data.OwnerAddress.String(), ControlAddress: data.ControlAddress.String(), @@ -337,17 +331,17 @@ func (RecreateCoinDataResource) Transform(txData interface{}, context *state.Che } } -// ChangeCoinOwnerDataResource is JSON representation of TxType 0x11 -type ChangeCoinOwnerDataResource struct { +// EditCoinOwnerDataResource is JSON representation of TxType 0x11 +type EditCoinOwnerDataResource struct { Symbol types.CoinSymbol `json:"symbol"` NewOwner types.Address `json:"new_owner"` } // Transform returns TxDataResource from given txData. Used for JSON encoder. -func (ChangeCoinOwnerDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { - data := txData.(*transaction.ChangeCoinOwnerData) +func (EditCoinOwnerDataResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { + data := txData.(*transaction.EditCoinOwnerData) - return ChangeCoinOwnerDataResource{ + return EditCoinOwnerDataResource{ Symbol: data.Symbol, NewOwner: data.NewOwner, } @@ -390,3 +384,19 @@ func (PriceVoteResource) Transform(txData interface{}, context *state.CheckState Price: uint32(data.Price), } } + +// EditCandidatePublicKeyResource is JSON representation of TxType 0x14 +type EditCandidatePublicKeyResource struct { + PubKey string `json:"pub_key"` + NewPubKey string `json:"new_pub_key"` +} + +// Transform returns TxDataResource from given txData. Used for JSON encoder. +func (EditCandidatePublicKeyResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { + data := txData.(*transaction.EditCandidatePublicKeyData) + + return EditCandidatePublicKeyResource{ + PubKey: data.PubKey.String(), + NewPubKey: data.NewPubKey.String(), + } +} diff --git a/core/transaction/executor.go b/core/transaction/executor.go index b7fddc5a8..530ccfc8a 100644 --- a/core/transaction/executor.go +++ b/core/transaction/executor.go @@ -257,7 +257,7 @@ func RunTx(context state.Interface, response.GasWanted = coinGas } - if tx.Type == TypeChangeCoinOwner { + if tx.Type == TypeEditCoinOwner { response.GasUsed = coinGas response.GasWanted = coinGas } diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index 1afbf8af5..edeb71bb2 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -21,25 +21,26 @@ type TxType byte type SigType byte const ( - TypeSend TxType = 0x01 - TypeSellCoin TxType = 0x02 - TypeSellAllCoin TxType = 0x03 - TypeBuyCoin TxType = 0x04 - TypeCreateCoin TxType = 0x05 - TypeDeclareCandidacy TxType = 0x06 - TypeDelegate TxType = 0x07 - TypeUnbond TxType = 0x08 - TypeRedeemCheck TxType = 0x09 - TypeSetCandidateOnline TxType = 0x0A - TypeSetCandidateOffline TxType = 0x0B - TypeCreateMultisig TxType = 0x0C - TypeMultisend TxType = 0x0D - TypeEditCandidate TxType = 0x0E - TypeSetHaltBlock TxType = 0x0F - TypeRecreateCoin TxType = 0x10 - TypeChangeCoinOwner TxType = 0x11 - TypeEditMultisigOwner TxType = 0x12 - TypePriceVote TxType = 0x13 + TypeSend TxType = 0x01 + TypeSellCoin TxType = 0x02 + TypeSellAllCoin TxType = 0x03 + TypeBuyCoin TxType = 0x04 + TypeCreateCoin TxType = 0x05 + TypeDeclareCandidacy TxType = 0x06 + TypeDelegate TxType = 0x07 + TypeUnbond TxType = 0x08 + TypeRedeemCheck TxType = 0x09 + TypeSetCandidateOnline TxType = 0x0A + TypeSetCandidateOffline TxType = 0x0B + TypeCreateMultisig TxType = 0x0C + TypeMultisend TxType = 0x0D + TypeEditCandidate TxType = 0x0E + TypeSetHaltBlock TxType = 0x0F + TypeRecreateCoin TxType = 0x10 + TypeEditCoinOwner TxType = 0x11 + TypeEditMultisigOwner TxType = 0x12 + TypePriceVote TxType = 0x13 + TypeEditCandidatePublicKey TxType = 0x14 SigTypeSingle SigType = 0x01 SigTypeMulti SigType = 0x02 diff --git a/go.mod b/go.mod index bfd36490c..4b636350f 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200910155433-6fd6860b50b9 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200914084650-1886df946f7a github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 89cc337ca..b09370ad4 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200910155433-6fd6860b50b9 h1:n1tgrQ0mvnOl94BTuVpLUvxT4br1CtlgrRmnP2DjOjI= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200910155433-6fd6860b50b9/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200914084650-1886df946f7a h1:VnbpxZI8gat0tUv1ZF1Si5QqmiDiQbDsfAv47rEOm7A= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200914084650-1886df946f7a/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 6fd0098b50e6f7e745de92e0be71167d9f466519 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Mon, 14 Sep 2020 12:00:25 +0300 Subject: [PATCH 252/426] Fix multisig test --- core/transaction/create_multisig_test.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/core/transaction/create_multisig_test.go b/core/transaction/create_multisig_test.go index 840ce2a67..7f1ce78c0 100644 --- a/core/transaction/create_multisig_test.go +++ b/core/transaction/create_multisig_test.go @@ -134,11 +134,7 @@ func TestCreateMultisigFromExistingAccountTx(t *testing.T) { Addresses: addresses, } - msigAddr := (&accounts.Multisig{ - Threshold: data.Threshold, - Weights: data.Weights, - Addresses: data.Addresses, - }).Address() + msigAddr := accounts.CreateMultisigAddress(addr, 1) initialBalance := big.NewInt(10) cState.Accounts.AddBalance(msigAddr, types.GetBaseCoinID(), initialBalance) From d6d309ac9e91b46ce1b4ea1be53cb429f2ffca8e Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Mon, 14 Sep 2020 12:01:16 +0300 Subject: [PATCH 253/426] Update edit candidate test --- core/transaction/edit_candidate_test.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/core/transaction/edit_candidate_test.go b/core/transaction/edit_candidate_test.go index 1498ad71f..e38de7e10 100644 --- a/core/transaction/edit_candidate_test.go +++ b/core/transaction/edit_candidate_test.go @@ -115,10 +115,8 @@ func TestEditCandidateNewPubKeyTx(t *testing.T) { newOwnerAddress := types.Address{2} newControlAddress := types.Address{3} - p := types.Pubkey(newpubkey) data := EditCandidateData{ PubKey: pubkey, - NewPubKey: &p, RewardAddress: newRewardAddress, OwnerAddress: newOwnerAddress, ControlAddress: newControlAddress, @@ -310,11 +308,9 @@ func TestEditCandidateTxToNewPublicKey(t *testing.T) { newRewardAddress := types.Address{1} newOwnerAddress := types.Address{2} newControlAddress := types.Address{3} - newPubKey := types.Pubkey(pubkey) data := EditCandidateData{ PubKey: pubkey, - NewPubKey: &newPubKey, RewardAddress: newRewardAddress, OwnerAddress: newOwnerAddress, ControlAddress: newControlAddress, @@ -427,7 +423,6 @@ func TestEditCandidateTxToNewPublicKeyInBlockList(t *testing.T) { data := EditCandidateData{ PubKey: pubkey, - NewPubKey: &pubkey2, RewardAddress: newRewardAddress, OwnerAddress: newOwnerAddress, ControlAddress: newControlAddress, @@ -475,8 +470,6 @@ func TestEditCandidateTxToGasCoinReserveUnderflow(t *testing.T) { pubkey := [32]byte{} rand.Read(pubkey[:]) - pubkey2 := types.Pubkey{1} - cState.Candidates.Create(addr, addr, addr, pubkey, 10) cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) @@ -486,7 +479,6 @@ func TestEditCandidateTxToGasCoinReserveUnderflow(t *testing.T) { data := EditCandidateData{ PubKey: pubkey, - NewPubKey: &pubkey2, RewardAddress: newRewardAddress, OwnerAddress: newOwnerAddress, ControlAddress: newControlAddress, From af5474f97f04fd59e7dea0a0aac807f44dbea56c Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Mon, 14 Sep 2020 12:22:48 +0300 Subject: [PATCH 254/426] fix tests --- .../edit_candidate_public_key_test.go | 378 ++++++++++++++++++ core/transaction/edit_candidate_test.go | 201 ---------- core/transaction/edit_coin_owner_test.go | 20 +- 3 files changed, 388 insertions(+), 211 deletions(-) create mode 100644 core/transaction/edit_candidate_public_key_test.go diff --git a/core/transaction/edit_candidate_public_key_test.go b/core/transaction/edit_candidate_public_key_test.go new file mode 100644 index 000000000..f53f6cc0e --- /dev/null +++ b/core/transaction/edit_candidate_public_key_test.go @@ -0,0 +1,378 @@ +package transaction + +import ( + "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/crypto" + "github.com/MinterTeam/minter-go-node/helpers" + "github.com/MinterTeam/minter-go-node/rlp" + "math/big" + "math/rand" + "sync" + "testing" +) + +func TestEditCandidateNewPublicKeyTx(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + newpubkey := [32]byte{} + rand.Read(newpubkey[:]) + + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + + data := EditCandidatePublicKeyData{ + PubKey: pubkey, + NewPubKey: newpubkey, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditCandidatePublicKey, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != 0 { + t.Fatalf("Response code is not 0. Error %s", response.Log) + } + + targetBalance, _ := big.NewInt(0).SetString("999990000000000000000000", 10) + balance := cState.Accounts.GetBalance(addr, coin) + if balance.Cmp(targetBalance) != 0 { + t.Fatalf("Target %s balance is not correct. Expected %s, got %s", coin, targetBalance, balance) + } + + if cState.Candidates.GetCandidate(pubkey) != nil { + t.Fatalf("Candidate found with old pub key") + } + + candidate := cState.Candidates.GetCandidate(newpubkey) + if candidate == nil { + t.Fatalf("Candidate not found") + } + + if !candidate.PubKey.Equals(newpubkey) { + t.Fatalf("Public key has not changed") + } +} + +func TestEditCandidatePublicKeyTxToNewPublicKey(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + + data := EditCandidatePublicKeyData{ + PubKey: pubkey, + NewPubKey: pubkey, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditCandidatePublicKey, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.NewPublicKeyIsBad { + t.Fatalf("Response code is not %d. Error %s", code.NewPublicKeyIsBad, response.Log) + } +} + +func TestEditCandidatePublicKeyTxToNewPublicKeyInBlockList(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + pubkey2 := types.Pubkey{1} + + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + cState.Candidates.AddToBlockPubKey(pubkey2) + + data := EditCandidatePublicKeyData{ + PubKey: pubkey, + NewPubKey: pubkey2, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditCandidatePublicKey, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.PublicKeyInBlockList { + t.Fatalf("Response code is not %d. Error %s", code.PublicKeyInBlockList, response.Log) + } +} + +func TestEditCandidatePublicKeyTxToInsufficientFunds(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + + data := EditCandidatePublicKeyData{ + PubKey: pubkey, + NewPubKey: types.Pubkey{5}, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditCandidatePublicKey, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.InsufficientFunds { + t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) + } +} + +func TestEditCandidatePublicKeyTxToGasCoinReserveUnderflow(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := createTestCoin(cState) + cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + + data := EditCandidatePublicKeyData{ + PubKey: pubkey, + NewPubKey: types.Pubkey{5}, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditCandidatePublicKey, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinReserveUnderflow { + t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) + } +} + +func TestEditCandidatePublicKeyToNotExistenCandidate(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + data := EditCandidatePublicKeyData{ + PubKey: pubkey, + NewPubKey: types.Pubkey{5}, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditCandidatePublicKey, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CandidateNotFound { + t.Fatalf("Response code is not %d. Error %s", code.CandidateNotFound, response.Log) + } +} + +func TestEditCandidatePublicKeyTxToCandidateOwnership(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + addr2 := types.Address{0} + coin := types.GetBaseCoinID() + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + cState.Candidates.Create(addr2, addr2, addr2, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + + data := EditCandidatePublicKeyData{ + PubKey: pubkey, + NewPubKey: types.Pubkey{5}, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditCandidatePublicKey, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.IsNotOwnerOfCandidate { + t.Fatalf("Response code is not %d. Error %s", code.IsNotOwnerOfCandidate, response.Log) + } +} diff --git a/core/transaction/edit_candidate_test.go b/core/transaction/edit_candidate_test.go index e38de7e10..09989f6c1 100644 --- a/core/transaction/edit_candidate_test.go +++ b/core/transaction/edit_candidate_test.go @@ -95,94 +95,6 @@ func TestEditCandidateTx(t *testing.T) { } } -func TestEditCandidateNewPubKeyTx(t *testing.T) { - cState := getState() - - privateKey, _ := crypto.GenerateKey() - addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoinID() - cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) - - pubkey := [32]byte{} - rand.Read(pubkey[:]) - newpubkey := [32]byte{} - rand.Read(newpubkey[:]) - - cState.Candidates.Create(addr, addr, addr, pubkey, 10) - cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) - - newRewardAddress := types.Address{1} - newOwnerAddress := types.Address{2} - newControlAddress := types.Address{3} - - data := EditCandidateData{ - PubKey: pubkey, - RewardAddress: newRewardAddress, - OwnerAddress: newOwnerAddress, - ControlAddress: newControlAddress, - } - - encodedData, err := rlp.EncodeToBytes(data) - - if err != nil { - t.Fatal(err) - } - - tx := Transaction{ - Nonce: 1, - GasPrice: 1, - ChainID: types.CurrentChainID, - GasCoin: coin, - Type: TypeEditCandidate, - Data: encodedData, - SignatureType: SigTypeSingle, - } - - if err := tx.Sign(privateKey); err != nil { - t.Fatal(err) - } - - encodedTx, err := rlp.EncodeToBytes(tx) - - if err != nil { - t.Fatal(err) - } - - response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) - - if response.Code != 0 { - t.Fatalf("Response code is not 0. Error %s", response.Log) - } - - targetBalance, _ := big.NewInt(0).SetString("999990000000000000000000", 10) - balance := cState.Accounts.GetBalance(addr, coin) - if balance.Cmp(targetBalance) != 0 { - t.Fatalf("Target %s balance is not correct. Expected %s, got %s", coin, targetBalance, balance) - } - - if cState.Candidates.GetCandidate(pubkey) != nil { - t.Fatalf("Candidate found with old pub key") - } - - candidate := cState.Candidates.GetCandidate(newpubkey) - - if candidate == nil { - t.Fatalf("Candidate not found") - } - - if candidate.OwnerAddress != newOwnerAddress { - t.Fatalf("OwnerAddress has not changed") - } - - if candidate.RewardAddress != newRewardAddress { - t.Fatalf("RewardAddress has not changed") - } - - if candidate.ControlAddress != newControlAddress { - t.Fatalf("ControlAddress has not changed") - } -} - func TestEditCandidateTxToNonExistenCandidate(t *testing.T) { cState := getState() @@ -291,61 +203,6 @@ func TestEditCandidateTxToCandidateOwnership(t *testing.T) { } } -func TestEditCandidateTxToNewPublicKey(t *testing.T) { - cState := getState() - - privateKey, _ := crypto.GenerateKey() - addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoinID() - cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) - - pubkey := [32]byte{} - rand.Read(pubkey[:]) - - cState.Candidates.Create(addr, addr, addr, pubkey, 10) - cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) - - newRewardAddress := types.Address{1} - newOwnerAddress := types.Address{2} - newControlAddress := types.Address{3} - - data := EditCandidateData{ - PubKey: pubkey, - RewardAddress: newRewardAddress, - OwnerAddress: newOwnerAddress, - ControlAddress: newControlAddress, - } - - encodedData, err := rlp.EncodeToBytes(data) - if err != nil { - t.Fatal(err) - } - - tx := Transaction{ - Nonce: 1, - GasPrice: 1, - ChainID: types.CurrentChainID, - GasCoin: coin, - Type: TypeEditCandidate, - Data: encodedData, - SignatureType: SigTypeSingle, - } - - if err := tx.Sign(privateKey); err != nil { - t.Fatal(err) - } - - encodedTx, err := rlp.EncodeToBytes(tx) - if err != nil { - t.Fatal(err) - } - - response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) - if response.Code != code.NewPublicKeyIsBad { - t.Fatalf("Response code is not %d. Error %s", code.NewPublicKeyIsBad, response.Log) - } -} - func TestEditCandidateTxToInsufficientFunds(t *testing.T) { cState := getState() @@ -400,64 +257,6 @@ func TestEditCandidateTxToInsufficientFunds(t *testing.T) { } } -func TestEditCandidateTxToNewPublicKeyInBlockList(t *testing.T) { - cState := getState() - - privateKey, _ := crypto.GenerateKey() - addr := crypto.PubkeyToAddress(privateKey.PublicKey) - coin := types.GetBaseCoinID() - cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) - - pubkey := [32]byte{} - rand.Read(pubkey[:]) - - pubkey2 := types.Pubkey{1} - - cState.Candidates.Create(addr, addr, addr, pubkey, 10) - cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) - cState.Candidates.AddToBlockPubKey(pubkey2) - - newRewardAddress := types.Address{1} - newOwnerAddress := types.Address{2} - newControlAddress := types.Address{3} - - data := EditCandidateData{ - PubKey: pubkey, - RewardAddress: newRewardAddress, - OwnerAddress: newOwnerAddress, - ControlAddress: newControlAddress, - } - - encodedData, err := rlp.EncodeToBytes(data) - if err != nil { - t.Fatal(err) - } - - tx := Transaction{ - Nonce: 1, - GasPrice: 1, - ChainID: types.CurrentChainID, - GasCoin: coin, - Type: TypeEditCandidate, - Data: encodedData, - SignatureType: SigTypeSingle, - } - - if err := tx.Sign(privateKey); err != nil { - t.Fatal(err) - } - - encodedTx, err := rlp.EncodeToBytes(tx) - if err != nil { - t.Fatal(err) - } - - response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) - if response.Code != code.PublicKeyInBlockList { - t.Fatalf("Response code is not %d. Error %s", code.PublicKeyInBlockList, response.Log) - } -} - func TestEditCandidateTxToGasCoinReserveUnderflow(t *testing.T) { cState := getState() diff --git a/core/transaction/edit_coin_owner_test.go b/core/transaction/edit_coin_owner_test.go index 3984262e4..cfd59fb51 100644 --- a/core/transaction/edit_coin_owner_test.go +++ b/core/transaction/edit_coin_owner_test.go @@ -17,7 +17,7 @@ import ( db "github.com/tendermint/tm-db" ) -func TestChangeOwnerTx(t *testing.T) { +func TestEditOwnerTx(t *testing.T) { cState, err := state.NewState(0, db.NewMemDB(), nil, 1, 1) if err != nil { t.Fatalf("Cannot load state. Error %s", err) @@ -39,7 +39,7 @@ func TestChangeOwnerTx(t *testing.T) { NewOwner: newOwner, } - tx, err := makeTestChangeOwnerTx(data, privateKey) + tx, err := makeTestEditOwnerTx(data, privateKey) if err != nil { t.Fatal(err) } @@ -70,7 +70,7 @@ func TestChangeOwnerTx(t *testing.T) { } } -func TestChangeOwnerTxWithWrongOwner(t *testing.T) { +func TestEditOwnerTxWithWrongOwner(t *testing.T) { cState, err := state.NewState(0, db.NewMemDB(), nil, 1, 1) if err != nil { t.Fatalf("Cannot load state. Error %s", err) @@ -88,7 +88,7 @@ func TestChangeOwnerTxWithWrongOwner(t *testing.T) { NewOwner: newOwner, } - tx, err := makeTestChangeOwnerTx(data, privateKey) + tx, err := makeTestEditOwnerTx(data, privateKey) if err != nil { t.Fatal(err) } @@ -99,7 +99,7 @@ func TestChangeOwnerTxWithWrongOwner(t *testing.T) { } } -func TestChangeOwnerTxWithWrongSymbol(t *testing.T) { +func TestEditOwnerTxWithWrongSymbol(t *testing.T) { cState, err := state.NewState(0, db.NewMemDB(), nil, 1, 1) if err != nil { t.Fatalf("Cannot load state. Error %s", err) @@ -118,7 +118,7 @@ func TestChangeOwnerTxWithWrongSymbol(t *testing.T) { NewOwner: newOwner, } - tx, err := makeTestChangeOwnerTx(data, privateKey) + tx, err := makeTestEditOwnerTx(data, privateKey) if err != nil { t.Fatal(err) } @@ -129,7 +129,7 @@ func TestChangeOwnerTxWithWrongSymbol(t *testing.T) { } } -func TestChangeOwnerTxWithInsufficientFunds(t *testing.T) { +func TestEditCOwnerTxWithInsufficientFunds(t *testing.T) { cState, err := state.NewState(0, db.NewMemDB(), nil, 1, 1) if err != nil { t.Fatalf("Cannot load state. Error %s", err) @@ -148,7 +148,7 @@ func TestChangeOwnerTxWithInsufficientFunds(t *testing.T) { NewOwner: newOwner, } - tx, err := makeTestChangeOwnerTx(data, privateKey) + tx, err := makeTestEditOwnerTx(data, privateKey) if err != nil { t.Fatal(err) } @@ -159,7 +159,7 @@ func TestChangeOwnerTxWithInsufficientFunds(t *testing.T) { } } -func TestChangeCoinOwnerTxToGasCoinReserveUnderflow(t *testing.T) { +func TestEditCoinOwnerTxToGasCoinReserveUnderflow(t *testing.T) { cState := getState() privateKey, _ := crypto.GenerateKey() @@ -206,7 +206,7 @@ func TestChangeCoinOwnerTxToGasCoinReserveUnderflow(t *testing.T) { } } -func makeTestChangeOwnerTx(data EditCoinOwnerData, privateKey *ecdsa.PrivateKey) ([]byte, error) { +func makeTestEditOwnerTx(data EditCoinOwnerData, privateKey *ecdsa.PrivateKey) ([]byte, error) { encodedData, err := rlp.EncodeToBytes(data) if err != nil { return nil, err From bb9a9629b3e5c477d79e19a289aaa225cdeac43e Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Mon, 14 Sep 2020 12:30:45 +0300 Subject: [PATCH 255/426] fix --- core/transaction/encoder/resources.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/core/transaction/encoder/resources.go b/core/transaction/encoder/resources.go index 539b1ec27..9e6ea3453 100644 --- a/core/transaction/encoder/resources.go +++ b/core/transaction/encoder/resources.go @@ -273,11 +273,10 @@ func (resource MultiSendDataResource) Transform(txData interface{}, context *sta // EditCandidateDataResource is JSON representation of TxType 0x0E type EditCandidateDataResource struct { - PubKey string `json:"pub_key"` - NewPubKey *string `json:"new_pub_key"` - RewardAddress string `json:"reward_address"` - OwnerAddress string `json:"owner_address"` - ControlAddress string `json:"control_address"` + PubKey string `json:"pub_key"` + RewardAddress string `json:"reward_address"` + OwnerAddress string `json:"owner_address"` + ControlAddress string `json:"control_address"` } // Transform returns TxDataResource from given txData. Used for JSON encoder. From c3c2e41913126a5551802e735c726abf92976bd1 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Mon, 14 Sep 2020 12:32:23 +0300 Subject: [PATCH 256/426] Refactor --- cmd/minter/cmd/node.go | 162 +++++++++++++++++++++++------------------ cmd/minter/cmd/root.go | 4 + 2 files changed, 97 insertions(+), 69 deletions(-) diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index e175f68b0..58840a7b3 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -2,9 +2,9 @@ package cmd import ( "fmt" - api_v1 "github.com/MinterTeam/minter-go-node/api" - api_v2 "github.com/MinterTeam/minter-go-node/api/v2" - service_api "github.com/MinterTeam/minter-go-node/api/v2/service" + apiV1 "github.com/MinterTeam/minter-go-node/api" + apiV2 "github.com/MinterTeam/minter-go-node/api/v2" + serviceApi "github.com/MinterTeam/minter-go-node/api/v2/service" "github.com/MinterTeam/minter-go-node/cli/service" "github.com/MinterTeam/minter-go-node/cmd/utils" "github.com/MinterTeam/minter-go-node/config" @@ -17,8 +17,8 @@ import ( "github.com/tendermint/go-amino" "github.com/tendermint/tendermint/abci/types" tmCfg "github.com/tendermint/tendermint/config" - tmlog "github.com/tendermint/tendermint/libs/log" - tmos "github.com/tendermint/tendermint/libs/os" + tmLog "github.com/tendermint/tendermint/libs/log" + tmOS "github.com/tendermint/tendermint/libs/os" tmNode "github.com/tendermint/tendermint/node" "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/privval" @@ -28,14 +28,13 @@ import ( tmTypes "github.com/tendermint/tendermint/types" "io" "net/http" - _ "net/http/pprof" + _ "net/http/pprof" // nolint: gosec // securely exposed on separate, optional port "net/url" "os" "syscall" ) -const RequiredOpenFilesLimit = 10000 - +// RunNode is the command that allows the CLI to start a node. var RunNode = &cobra.Command{ Use: "node", Short: "Run the Minter node", @@ -48,21 +47,13 @@ func runNode(cmd *cobra.Command) error { logger := log.NewLogger(cfg) // check open files limits - { - var rLimit syscall.Rlimit - err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit) - if err != nil { - panic(err) - } + if err := checkRlimits(); err != nil { + panic(err) + } - required := RequiredOpenFilesLimit + uint64(cfg.StateMemAvailable) - if rLimit.Cur < required { - rLimit.Cur = required - err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit) - if err != nil { - panic(fmt.Errorf("cannot set RLIMIT_NOFILE to %d", rLimit.Cur)) - } - } + // ensure /config and /tmdata dirs + if err := ensureDirs(); err != nil { + return err } isTestnet, _ := cmd.Flags().GetBool("testnet") @@ -77,35 +68,13 @@ func runNode(cmd *cobra.Command) error { } if pprofOn { - pprofAddr, err := cmd.Flags().GetString("pprof-addr") - if err != nil { + if err := enablePprof(cmd, logger); err != nil { return err } - - pprofMux := http.DefaultServeMux - http.DefaultServeMux = http.NewServeMux() - go func() { - logger.Error((&http.Server{ - Addr: pprofAddr, - Handler: pprofMux, - }).ListenAndServe().Error()) - }() } tmConfig := config.GetTmConfig(cfg) - if err := tmos.EnsureDir(utils.GetMinterHome()+"/config", 0777); err != nil { - return err - } - - if err := tmos.EnsureDir(utils.GetMinterHome()+"/tmdata", 0777); err != nil { - return err - } - - if cfg.KeepLastStates < 1 { - panic("keep_last_states field should be greater than 0") - } - app := minter.NewMinterBlockchain(cfg) // update BlocksTimeDelta in case it was corrupted @@ -113,50 +82,106 @@ func runNode(cmd *cobra.Command) error { // start TM node node := startTendermintNode(app, tmConfig, logger) - client := rpc.New(node) - app.SetTmNode(node) if !cfg.ValidatorMode { - go func(srv *service_api.Service) { - grpcUrl, err := url.Parse(cfg.GRPCListenAddress) - if err != nil { - logger.Error("Failed to parse gRPC address", err) - } - apiV2url, err := url.Parse(cfg.APIv2ListenAddress) - if err != nil { - logger.Error("Failed to parse API v2 address", err) - } - traceLog := os.Getenv("API_V2_LOG_LEVEL") == "trace" - logger.Error("Failed to start Api V2 in both gRPC and RESTful", - api_v2.Run(srv, grpcUrl.Host, apiV2url.Host, traceLog)) - }(service_api.NewService(amino.NewCodec(), app, client, node, cfg, version.Version)) - - go api_v1.RunAPI(app, client, cfg, logger) + runAPI(logger, app, client, node) } + runCLI(cmd, app, client) + + if cfg.Instrumentation.Prometheus { + go app.SetStatisticData(statistics.New()).Statistic(cmd.Context()) + } + + <-cmd.Context().Done() + + defer app.Stop() + if err := node.Stop(); err != nil { + return err + } + + return nil +} + +func runCLI(cmd *cobra.Command, app *minter.Blockchain, client *rpc.Local) { go func() { err := service.StartCLIServer(utils.GetMinterHome()+"/manager.sock", service.NewManager(app, client, cfg), cmd.Context()) if err != nil { panic(err) } }() +} - if cfg.Instrumentation.Prometheus { - go app.SetStatisticData(statistics.New()).Statistic(cmd.Context()) +func runAPI(logger tmLog.Logger, app *minter.Blockchain, client *rpc.Local, node *tmNode.Node) { + go func(srv *serviceApi.Service) { + grpcURL, err := url.Parse(cfg.GRPCListenAddress) + if err != nil { + logger.Error("Failed to parse gRPC address", err) + } + apiV2url, err := url.Parse(cfg.APIv2ListenAddress) + if err != nil { + logger.Error("Failed to parse API v2 address", err) + } + traceLog := os.Getenv("API_V2_LOG_LEVEL") == "trace" + logger.Error("Failed to start Api V2 in both gRPC and RESTful", + apiV2.Run(srv, grpcURL.Host, apiV2url.Host, traceLog)) + }(serviceApi.NewService(amino.NewCodec(), app, client, node, cfg, version.Version)) + + go apiV1.RunAPI(app, client, cfg, logger) +} + +func enablePprof(cmd *cobra.Command, logger tmLog.Logger) error { + pprofAddr, err := cmd.Flags().GetString("pprof-addr") + if err != nil { + return err } - <-cmd.Context().Done() + pprofMux := http.DefaultServeMux + http.DefaultServeMux = http.NewServeMux() + go func() { + logger.Error((&http.Server{ + Addr: pprofAddr, + Handler: pprofMux, + }).ListenAndServe().Error()) + }() + return nil +} - defer app.Stop() - if err := node.Stop(); err != nil { +func ensureDirs() error { + if err := tmOS.EnsureDir(utils.GetMinterHome()+"/config", 0777); err != nil { + return err + } + + if err := tmOS.EnsureDir(utils.GetMinterHome()+"/tmdata", 0777); err != nil { return err } return nil } +func checkRlimits() error { + const RequiredOpenFilesLimit = 10000 + + var rLimit syscall.Rlimit + err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit) + if err != nil { + return err + } + + required := RequiredOpenFilesLimit + uint64(cfg.StateMemAvailable) + if rLimit.Cur < required { + rLimit.Cur = required + err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit) + if err != nil { + return fmt.Errorf("cannot set RLIMIT_NOFILE to %d", rLimit.Cur) + } + } + + return nil +} + func updateBlocksTimeDelta(app *minter.Blockchain, config *tmCfg.Config) { blockStoreDB, err := tmNode.DefaultDBProvider(&tmNode.DBContext{ID: "blockstore", Config: config}) if err != nil { @@ -176,7 +201,7 @@ func updateBlocksTimeDelta(app *minter.Blockchain, config *tmCfg.Config) { blockStoreDB.Close() } -func startTendermintNode(app types.Application, cfg *tmCfg.Config, logger tmlog.Logger) *tmNode.Node { +func startTendermintNode(app types.Application, cfg *tmCfg.Config, logger tmLog.Logger) *tmNode.Node { nodeKey, err := p2p.LoadOrGenNodeKey(cfg.NodeKeyFile()) if err != nil { panic(err) @@ -223,7 +248,6 @@ func getGenesis() (doc *tmTypes.GenesisDoc, e error) { } func downloadFile(filepath string, url string) error { - // Get the data resp, err := http.Get(url) if err != nil { diff --git a/cmd/minter/cmd/root.go b/cmd/minter/cmd/root.go index 1f72e3e5e..91825387f 100644 --- a/cmd/minter/cmd/root.go +++ b/cmd/minter/cmd/root.go @@ -24,5 +24,9 @@ var RootCmd = &cobra.Command{ if err := v.Unmarshal(cfg); err != nil { panic(err) } + + if cfg.KeepLastStates < 1 { + panic("keep_last_states field should be greater than 0") + } }, } From 5870c0c34e4576feaec4a9b9c7cab81ade921f75 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Mon, 14 Sep 2020 13:15:18 +0300 Subject: [PATCH 257/426] Refactor --- api/v2/service/missed_blocks.go | 33 ++++++++++++++++++++++++++++++++- core/minter/minter.go | 32 -------------------------------- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/api/v2/service/missed_blocks.go b/api/v2/service/missed_blocks.go index 029d9096d..4d10ede96 100644 --- a/api/v2/service/missed_blocks.go +++ b/api/v2/service/missed_blocks.go @@ -3,15 +3,46 @@ package service import ( "context" "fmt" + "github.com/MinterTeam/minter-go-node/core/types" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "strings" ) // MissedBlocks returns missed blocks by validator public key. func (s *Service) MissedBlocks(ctx context.Context, req *pb.MissedBlocksRequest) (*pb.MissedBlocksResponse, error) { - blocks, count, err := s.blockchain.MissedBlocks(req.PublicKey, req.Height) + blocks, count, err := missedBlocks(s, req.Height, req.PublicKey) if err != nil { return new(pb.MissedBlocksResponse), err } return &pb.MissedBlocksResponse{MissedBlocks: blocks, MissedBlocksCount: fmt.Sprintf("%d", count)}, nil } + +func missedBlocks(s *Service, height uint64, pubKey string) (missedBlocks string, missedBlocksCount int, err error) { + if !strings.HasPrefix(pubKey, "Mp") { + return "", 0, status.Error(codes.InvalidArgument, "public key don't has prefix 'Mp'") + } + + cState, err := s.blockchain.GetStateForHeight(height) + if err != nil { + return "", 0, status.Error(codes.NotFound, err.Error()) + } + + if height != 0 { + cState.Lock() + cState.Validators().LoadValidators() + cState.Unlock() + } + + cState.RLock() + defer cState.RUnlock() + + val := cState.Validators().GetByPublicKey(types.HexToPubkey(pubKey)) + if val == nil { + return "", 0, status.Error(codes.NotFound, "Validator not found") + } + + return val.AbsentTimes.String(), val.CountAbsentTimes(), nil +} diff --git a/core/minter/minter.go b/core/minter/minter.go index 63285e4b1..177058c67 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -29,11 +29,8 @@ import ( types2 "github.com/tendermint/tendermint/types" typesT "github.com/tendermint/tendermint/types" "github.com/tendermint/tm-db" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" "math/big" "sort" - "strings" "sync" "sync/atomic" "time" @@ -508,35 +505,6 @@ func (app *Blockchain) GetStateForHeight(height uint64) (*state.CheckState, erro return blockchain.CurrentState(), nil } -// MissedBlocks returns aggregated info about block which has no signature of given validator -func (app *Blockchain) MissedBlocks(pubKey string, height uint64) (missedBlocks string, missedBlocksCount int, err error) { - if !strings.HasPrefix(pubKey, "Mp") { - return "", 0, status.Error(codes.InvalidArgument, "public key don't has prefix 'Mp'") - } - - cState, err := blockchain.GetStateForHeight(height) - if err != nil { - return "", 0, status.Error(codes.NotFound, err.Error()) - } - - if height != 0 { - cState.Lock() - cState.Validators().LoadValidators() - cState.Unlock() - } - - cState.RLock() - defer cState.RUnlock() - - val := cState.Validators().GetByPublicKey(types.HexToPubkey(pubKey)) - if val == nil { - return "", 0, status.Error(codes.NotFound, "Validator not found") - } - - return val.AbsentTimes.String(), val.CountAbsentTimes(), nil - -} - // Height returns current height of Minter Blockchain func (app *Blockchain) Height() uint64 { return atomic.LoadUint64(&app.height) From 045ec88eec3a7b08874b1bf47a08523b7aa5278b Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Mon, 14 Sep 2020 13:24:21 +0300 Subject: [PATCH 258/426] Add todos --- core/minter/minter.go | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index 177058c67..29d16940d 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -639,6 +639,7 @@ func (app *Blockchain) GetValidatorStatus(address types.TmAddress) int8 { } // MaxPeerHeight returns max height of connected peers +// TODO: move outside Blockchain struct func (app *Blockchain) MaxPeerHeight() int64 { var max int64 for _, peer := range app.tmNode.Switch().Peers().List() { @@ -655,6 +656,7 @@ func (app *Blockchain) MaxPeerHeight() int64 { } // PeerHeight returns height of peer by ID. If peer is fast_syncing, height equal 0 +// TODO: move outside Blockchain struct func (app *Blockchain) PeerHeight(id p2p.ID) int64 { peerTM := app.tmNode.Switch().Peers().Get(id) if peerTM == nil { @@ -682,18 +684,6 @@ func (app *Blockchain) DeleteStateVersions(from, to int64) error { return app.stateDeliver.Tree().DeleteVersionsIfExists(from, to) } -func getDbOpts(memLimit int) *opt.Options { - if memLimit < 1024 { - panic(fmt.Sprintf("Not enough memory given to StateDB. Expected >1024M, given %d", memLimit)) - } - return &opt.Options{ - OpenFilesCacheCapacity: memLimit, - BlockCacheCapacity: memLimit / 2 * opt.MiB, - WriteBuffer: memLimit / 4 * opt.MiB, // Two of these are used internally - Filter: filter.NewBloomFilter(10), - } -} - func (app *Blockchain) isApplicationHalted(height uint64) bool { if app.haltHeight > 0 && height >= app.haltHeight { return true @@ -735,3 +725,15 @@ func (app *Blockchain) isApplicationHalted(height uint64) bool { return false } + +func getDbOpts(memLimit int) *opt.Options { + if memLimit < 1024 { + panic(fmt.Sprintf("Not enough memory given to StateDB. Expected >1024M, given %d", memLimit)) + } + return &opt.Options{ + OpenFilesCacheCapacity: memLimit, + BlockCacheCapacity: memLimit / 2 * opt.MiB, + WriteBuffer: memLimit / 4 * opt.MiB, // Two of these are used internally + Filter: filter.NewBloomFilter(10), + } +} From 296dd87bc9d8b5678bbf4fdfdc1767ea7d9c7807 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Mon, 14 Sep 2020 14:19:33 +0300 Subject: [PATCH 259/426] Add tests --- helpers/helpers_test.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 helpers/helpers_test.go diff --git a/helpers/helpers_test.go b/helpers/helpers_test.go new file mode 100644 index 000000000..7353c6658 --- /dev/null +++ b/helpers/helpers_test.go @@ -0,0 +1,19 @@ +package helpers + +import "testing" + +func TestIsValidBigInt(t *testing.T) { + cases := map[string]bool{ + "": false, + "1": true, + "1s": false, + "-1": false, + "123437456298465928764598276349587623948756928764958762934569": true, + } + + for str, result := range cases { + if IsValidBigInt(str) != result { + t.Fail() + } + } +} From 2638710cbf960f077666ad7b57903237192e3a62 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 15 Sep 2020 13:51:53 +0300 Subject: [PATCH 260/426] fix --- core/state/candidates/candidates.go | 2 +- core/state/candidates/model.go | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 26c9d0f55..1f96f6914 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -1026,7 +1026,7 @@ func (c *Candidates) ChangePubKey(old types.Pubkey, new types.Pubkey) { panic("Candidate with such public key (" + new.String() + ") exists in block list") } - c.getFromMap(old).PubKey = new + c.getFromMap(old).setPublicKey(new) c.setBlockPubKey(old) c.setPubKeyID(new, c.pubKeyIDs[old]) delete(c.pubKeyIDs, old) diff --git a/core/state/candidates/model.go b/core/state/candidates/model.go index b8c2f214b..ff7f97c82 100644 --- a/core/state/candidates/model.go +++ b/core/state/candidates/model.go @@ -61,6 +61,11 @@ func (candidate *Candidate) setControl(address types.Address) { candidate.ControlAddress = address } +func (candidate *Candidate) setPublicKey(pubKey types.Pubkey) { + candidate.isDirty = true + candidate.PubKey = pubKey +} + func (candidate *Candidate) addUpdate(stake *stake) { candidate.isUpdatesDirty = true stake.markDirty = func(i int) { From 5462479e20bf6f331d738d4974f1ab5040399c0a Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 15 Sep 2020 02:02:08 +0300 Subject: [PATCH 261/426] wip: errors models and refactor api --- api/v2/service/coin_info.go | 10 +- api/v2/service/estimate_coin_buy.go | 42 ++-- api/v2/service/estimate_coin_sell.go | 50 ++--- api/v2/service/estimate_coin_sell_all.go | 41 ++-- api/v2/service/estimate_tx_commission.go | 18 +- api/v2/service/net_info.go | 21 +- cli/service/server_test.go | 4 +- cli/service/service.go | 44 +++- cmd/minter/cmd/node.go | 6 +- core/code/code.go | 203 ++++++++++++++++++ core/minter/minter.go | 38 ---- core/transaction/buy_coin.go | 91 ++++---- core/transaction/create_coin.go | 68 +++--- core/transaction/create_multisig.go | 7 +- core/transaction/declare_candidacy.go | 31 +-- core/transaction/delegate.go | 38 +--- core/transaction/edit_candidate.go | 7 +- core/transaction/edit_candidate_public_key.go | 7 +- core/transaction/edit_coin_owner.go | 12 +- core/transaction/edit_multisig_owners.go | 7 +- core/transaction/executor.go | 56 +---- core/transaction/multisend.go | 21 +- core/transaction/price_vote.go | 13 +- core/transaction/recreate_coin.go | 34 +-- core/transaction/redeem_check.go | 64 ++---- core/transaction/sell_all_coin.go | 43 ++-- core/transaction/sell_coin.go | 74 +++---- core/transaction/send.go | 20 +- core/transaction/set_halt_block.go | 7 +- core/transaction/switch_candidate_status.go | 27 +-- core/transaction/transaction.go | 30 +-- core/transaction/unbond.go | 16 +- 32 files changed, 534 insertions(+), 616 deletions(-) diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index c126f6631..655d2fbd4 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -26,10 +26,7 @@ func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.Co coin := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.Symbol), types.GetVersionFromSymbol(req.Symbol)) if coin == nil { - return new(pb.CoinInfoResponse), s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_symbol": req.Symbol, - })) + return new(pb.CoinInfoResponse), s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(code.NewCoinNotExists(req.Symbol, ""))) } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { @@ -68,10 +65,7 @@ func (s *Service) CoinInfoById(ctx context.Context, req *pb.CoinIdRequest) (*pb. coin := cState.Coins().GetCoin(types.CoinID(req.Id)) if coin == nil { - return new(pb.CoinInfoResponse), s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": strconv.Itoa(int(req.Id)), - })) + return new(pb.CoinInfoResponse), s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(transaction.EncodeError(code.NewCoinNotExists("", strconv.Itoa(int(req.Id)))))) } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index 9271a8a31..ef95a0a41 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -3,9 +3,6 @@ package service import ( "context" "fmt" - "math/big" - "strconv" - "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/transaction" @@ -14,6 +11,7 @@ import ( pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "math/big" ) // EstimateCoinBuy return estimate of buy coin transaction. @@ -30,19 +28,13 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe if req.GetCoinToBuy() != "" { symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), types.GetVersionFromSymbol(req.GetCoinToBuy())) if symbol == nil { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_symbol": req.GetCoinToBuy(), - })) + return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToBuy(), ""))) } coinToBuy = symbol.ID() } else { coinToBuy = types.CoinID(req.GetCoinIdToBuy()) if !cState.Coins().Exists(coinToBuy) { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": coinToBuy.String(), - })) + return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(code.NewCoinNotExists("", coinToBuy.String()))) } } @@ -50,19 +42,13 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe if req.GetCoinToSell() != "" { symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), types.GetVersionFromSymbol(req.GetCoinToSell())) if symbol == nil { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_symbol": req.GetCoinToSell(), - })) + return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToSell(), ""))) } coinToSell = symbol.ID() } else { coinToSell = types.CoinID(req.GetCoinIdToSell()) if !cState.Coins().Exists(coinToSell) { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": coinToSell.String(), - })) + return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists("", coinToSell.String()))) } } @@ -85,12 +71,16 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe if !coinToSell.IsBaseCoin() { if coinFrom.Reserve().Cmp(commissionInBaseCoin) < 0 { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", - coinFrom.Reserve().String(), commissionInBaseCoin.String())), transaction.EncodeError(map[string]string{ - "code": "400", - "has": coinFrom.Reserve().String(), - "required": commissionInBaseCoin.String(), - })) + return new(pb.EstimateCoinBuyResponse), s.createError( + status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", + coinFrom.Reserve().String(), commissionInBaseCoin.String())), + transaction.EncodeError(code.NewCoinReserveNotSufficient( + coinFrom.GetFullSymbol(), + coinFrom.ID().String(), + coinFrom.Reserve().String(), + commissionInBaseCoin.String(), + )), + ) } commission = formula.CalculateSaleAmount(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), commissionInBaseCoin) @@ -110,7 +100,7 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe } if !coinToBuy.IsBaseCoin() { - if errResp := transaction.CheckForCoinSupplyOverflow(coinTo.Volume(), value, coinTo.MaxSupply()); errResp != nil { + if errResp := transaction.CheckForCoinSupplyOverflow(coinTo, value); errResp != nil { return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } value = formula.CalculateSaleAmount(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), value) diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index df0d3fb32..41c8cd6c2 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -3,9 +3,6 @@ package service import ( "context" "fmt" - "math/big" - "strconv" - "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/transaction" @@ -14,6 +11,7 @@ import ( pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "math/big" ) // EstimateCoinSell return estimate of sell coin transaction. @@ -30,19 +28,13 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell if req.GetCoinToBuy() != "" { symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), types.GetVersionFromSymbol(req.GetCoinToBuy())) if symbol == nil { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_symbol": req.GetCoinToBuy(), - })) + return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToBuy(), ""))) } coinToBuy = symbol.ID() } else { coinToBuy = types.CoinID(req.GetCoinIdToBuy()) if !cState.Coins().Exists(coinToBuy) { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ - "code": "404", - "coin_id": coinToBuy.String(), - })) + return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(code.NewCoinNotExists("", coinToBuy.String()))) } } @@ -50,19 +42,13 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell if req.GetCoinToSell() != "" { symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), types.GetVersionFromSymbol(req.GetCoinToSell())) if symbol == nil { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_symbol": req.GetCoinToSell(), - })) + return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToSell(), ""))) } coinToSell = symbol.ID() } else { coinToSell = types.CoinID(req.GetCoinIdToSell()) if !cState.Coins().Exists(coinToSell) { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ - "code": "404", - "coin_id": coinToSell.String(), - })) + return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists("", coinToSell.String()))) } } @@ -88,21 +74,17 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell coinTo := cState.Coins().GetCoin(coinToBuy) if !coinToSell.IsBaseCoin() { - - if coinFrom.Volume().Cmp(valueToSell) < 0 { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin volume balance is not sufficient for transaction. Has: %s, required %s", - coinFrom.Volume().String(), valueToSell.String())), transaction.EncodeError(map[string]string{ - "volume_has": coinFrom.Volume().String(), - "volume_required": valueToSell.String(), - })) - } - if coinFrom.Reserve().Cmp(commissionInBaseCoin) < 0 { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", - coinFrom.Reserve().String(), commissionInBaseCoin.String())), transaction.EncodeError(map[string]string{ - "reserve_has": coinFrom.Reserve().String(), - "reserve_required": commissionInBaseCoin.String(), - })) + return new(pb.EstimateCoinSellResponse), s.createError( + status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", + coinFrom.Reserve().String(), commissionInBaseCoin.String())), + transaction.EncodeError(code.NewCoinReserveNotSufficient( + coinFrom.GetFullSymbol(), + coinFrom.ID().String(), + coinFrom.Reserve().String(), + commissionInBaseCoin.String(), + )), + ) } commission = formula.CalculateSaleAmount(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), commissionInBaseCoin) @@ -117,7 +99,7 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell } if !coinToBuy.IsBaseCoin() { - if errResp := transaction.CheckForCoinSupplyOverflow(coinTo.Volume(), value, coinTo.MaxSupply()); errResp != nil { + if errResp := transaction.CheckForCoinSupplyOverflow(coinTo, value); errResp != nil { return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } value = formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), value) diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index 8d8b7da10..443bec7b7 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -2,9 +2,7 @@ package service import ( "context" - "math/big" - "strconv" - + "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/transaction" @@ -13,6 +11,7 @@ import ( pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "math/big" ) // EstimateCoinSellAll return estimate of sell all coin transaction. @@ -39,19 +38,13 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS if req.GetCoinToBuy() != "" { symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), types.GetVersionFromSymbol(req.GetCoinToBuy())) if symbol == nil { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_symbol": req.GetCoinToBuy(), - })) + return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToBuy(), ""))) } coinToBuy = symbol.ID() } else { coinToBuy = types.CoinID(req.GetCoinIdToBuy()) if !cState.Coins().Exists(coinToBuy) { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": coinToBuy.String(), - })) + return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(transaction.EncodeError(code.NewCoinNotExists("", coinToBuy.String())))) } } @@ -59,19 +52,14 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS if req.GetCoinToSell() != "" { symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), types.GetVersionFromSymbol(req.GetCoinToSell())) if symbol == nil { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_symbol": req.GetCoinToSell(), - })) + return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToSell(), ""))) } coinToSell = symbol.ID() } else { coinToSell = types.CoinID(req.GetCoinIdToSell()) if !cState.Coins().Exists(coinToSell) { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": coinToSell.String(), - })) + return new(pb.EstimateCoinSellAllResponse), + s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists("", coinToSell.String()))) } } @@ -93,6 +81,19 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS value := valueToSell if !coinToSell.IsBaseCoin() { + if coinFrom.Reserve().Cmp(commissionInBaseCoin) < 0 { + return new(pb.EstimateCoinSellAllResponse), s.createError( + status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", + coinFrom.Reserve().String(), commissionInBaseCoin.String())), + transaction.EncodeError(code.NewCoinReserveNotSufficient( + coinFrom.GetFullSymbol(), + coinFrom.ID().String(), + coinFrom.Reserve().String(), + commissionInBaseCoin.String(), + )), + ) + } + value = formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) if errResp := transaction.CheckReserveUnderflow(coinFrom, value); errResp != nil { return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) @@ -100,7 +101,7 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS } if !coinToBuy.IsBaseCoin() { - if errResp := transaction.CheckForCoinSupplyOverflow(coinTo.Volume(), value, coinTo.MaxSupply()); errResp != nil { + if errResp := transaction.CheckForCoinSupplyOverflow(coinTo, value); errResp != nil { return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } value = formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), value) diff --git a/api/v2/service/estimate_tx_commission.go b/api/v2/service/estimate_tx_commission.go index 13ee9911f..096b5af97 100644 --- a/api/v2/service/estimate_tx_commission.go +++ b/api/v2/service/estimate_tx_commission.go @@ -5,7 +5,6 @@ import ( "encoding/hex" "fmt" "math/big" - "strconv" "strings" "github.com/MinterTeam/minter-go-node/core/code" @@ -47,13 +46,16 @@ func (s *Service) EstimateTxCommission(ctx context.Context, req *pb.EstimateTxCo coin := cState.Coins().GetCoin(decodedTx.GasCoin) if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return new(pb.EstimateTxCommissionResponse), s.createError(status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", - coin.Reserve().String(), commissionInBaseCoin.String())), transaction.EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "coin": coin.GetFullSymbol(), - "value_has": coin.Reserve().String(), - "value_required": commissionInBaseCoin.String(), - })) + return new(pb.EstimateTxCommissionResponse), s.createError( + status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", + coin.Reserve().String(), commissionInBaseCoin.String())), + transaction.EncodeError(code.NewCoinReserveNotSufficient( + coin.GetFullSymbol(), + coin.ID().String(), + coin.Reserve().String(), + commissionInBaseCoin.String(), + )), + ) } commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) diff --git a/api/v2/service/net_info.go b/api/v2/service/net_info.go index 5ec299f46..d46316c2f 100644 --- a/api/v2/service/net_info.go +++ b/api/v2/service/net_info.go @@ -6,6 +6,9 @@ import ( pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "github.com/golang/protobuf/ptypes/empty" "github.com/golang/protobuf/ptypes/wrappers" + "github.com/tendermint/tendermint/evidence" + "github.com/tendermint/tendermint/p2p" + typesTM "github.com/tendermint/tendermint/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "time" @@ -22,7 +25,7 @@ func (s *Service) NetInfo(ctx context.Context, _ *empty.Empty) (*pb.NetInfoRespo for _, peer := range result.Peers { var currentHeight *wrappers.StringValue - peerHeight := s.blockchain.PeerHeight(peer.NodeInfo.ID()) + peerHeight := peerHeight(s.tmNode.Switch(), peer.NodeInfo.ID()) if peerHeight != 0 { currentHeight = &wrappers.StringValue{Value: fmt.Sprintf("%d", peerHeight)} } @@ -93,3 +96,19 @@ func (s *Service) NetInfo(ctx context.Context, _ *empty.Empty) (*pb.NetInfoRespo Peers: peers, }, nil } + +func peerHeight(sw *p2p.Switch, id p2p.ID) int64 { + peerTM := sw.Peers().Get(id) + if peerTM == nil { + return 0 + } + ps := peerTM.Get(typesTM.PeerStateKey) + if ps == nil { + return 0 + } + peerState, ok := ps.(evidence.PeerState) + if !ok { + return 0 + } + return peerState.GetHeight() +} diff --git a/cli/service/server_test.go b/cli/service/server_test.go index 2f4e47999..63881da4d 100644 --- a/cli/service/server_test.go +++ b/cli/service/server_test.go @@ -4,6 +4,7 @@ import ( "context" "github.com/MinterTeam/minter-go-node/config" "github.com/MinterTeam/minter-go-node/core/minter" + "github.com/tendermint/tendermint/node" rpc "github.com/tendermint/tendermint/rpc/client/local" "io/ioutil" "path/filepath" @@ -15,13 +16,14 @@ func TestStartCLIServer(t *testing.T) { var ( blockchain *minter.Blockchain tmRPC *rpc.Local + tmNode *node.Node cfg *config.Config ) ctx, cancel := context.WithCancel(context.Background()) socketPath, _ := filepath.Abs(filepath.Join(".", "file.sock")) _ = ioutil.WriteFile(socketPath, []byte("address already in use"), 0644) go func() { - err := StartCLIServer(socketPath, NewManager(blockchain, tmRPC, cfg), ctx) + err := StartCLIServer(socketPath, NewManager(blockchain, tmRPC, tmNode, cfg), ctx) if err != nil { t.Log(err) } diff --git a/cli/service/service.go b/cli/service/service.go index d2da69cdf..aceb1192f 100644 --- a/cli/service/service.go +++ b/cli/service/service.go @@ -10,7 +10,11 @@ import ( "github.com/MinterTeam/minter-go-node/version" "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/empty" + "github.com/tendermint/tendermint/evidence" + tmNode "github.com/tendermint/tendermint/node" + "github.com/tendermint/tendermint/p2p" rpc "github.com/tendermint/tendermint/rpc/client/local" + typesTM "github.com/tendermint/tendermint/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "runtime" @@ -20,11 +24,12 @@ import ( type Manager struct { blockchain *minter.Blockchain tmRPC *rpc.Local + tmNode *tmNode.Node cfg *config.Config } -func NewManager(blockchain *minter.Blockchain, tmRPC *rpc.Local, cfg *config.Config) pb.ManagerServiceServer { - return &Manager{blockchain: blockchain, tmRPC: tmRPC, cfg: cfg} +func NewManager(blockchain *minter.Blockchain, tmRPC *rpc.Local, tmNode *tmNode.Node, cfg *config.Config) pb.ManagerServiceServer { + return &Manager{blockchain: blockchain, tmRPC: tmRPC, tmNode: tmNode, cfg: cfg} } func (m *Manager) Dashboard(_ *empty.Empty, stream pb.ManagerService_DashboardServer) error { @@ -41,7 +46,7 @@ func (m *Manager) Dashboard(_ *empty.Empty, stream pb.ManagerService_DashboardSe info := statisticData.GetLastBlockInfo() averageTimeBlock := statisticData.GetAverageBlockProcessingTime() timePerBlock := statisticData.GetTimePerBlock() - maxPeersHeight := m.blockchain.MaxPeerHeight() + maxPeersHeight := maxPeerHeight(m.tmNode.Switch()) if maxPeersHeight == 0 { maxPeersHeight = info.Height } else { @@ -150,7 +155,7 @@ func (m *Manager) NetInfo(context.Context, *empty.Empty) (*pb.NetInfoResponse, e RecentlySent: channel.RecentlySent, }) } - peerHeight := m.blockchain.PeerHeight(peer.NodeInfo.ID()) + peerHeight := peerHeight(m.tmNode.Switch(), peer.NodeInfo.ID()) peers = append(peers, &pb.NetInfoResponse_Peer{ LatestBlockHeight: peerHeight, NodeInfo: &pb.NodeInfo{ @@ -275,3 +280,34 @@ func (m *Manager) DealPeer(_ context.Context, req *pb.DealPeerRequest) (*empty.E } return res, nil } + +func maxPeerHeight(sw *p2p.Switch) int64 { + var max int64 + for _, peer := range sw.Peers().List() { + peerState, ok := peer.Get(typesTM.PeerStateKey).(evidence.PeerState) + if !ok { + continue + } + height := peerState.GetHeight() + if height > max { + max = height + } + } + return max +} + +func peerHeight(sw *p2p.Switch, id p2p.ID) int64 { + peerTM := sw.Peers().Get(id) + if peerTM == nil { + return 0 + } + ps := peerTM.Get(typesTM.PeerStateKey) + if ps == nil { + return 0 + } + peerState, ok := ps.(evidence.PeerState) + if !ok { + return 0 + } + return peerState.GetHeight() +} diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index 58840a7b3..5c69ee958 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -89,7 +89,7 @@ func runNode(cmd *cobra.Command) error { runAPI(logger, app, client, node) } - runCLI(cmd, app, client) + runCLI(cmd, app, client, node) if cfg.Instrumentation.Prometheus { go app.SetStatisticData(statistics.New()).Statistic(cmd.Context()) @@ -105,9 +105,9 @@ func runNode(cmd *cobra.Command) error { return nil } -func runCLI(cmd *cobra.Command, app *minter.Blockchain, client *rpc.Local) { +func runCLI(cmd *cobra.Command, app *minter.Blockchain, client *rpc.Local, tmNode *tmNode.Node) { go func() { - err := service.StartCLIServer(utils.GetMinterHome()+"/manager.sock", service.NewManager(app, client, cfg), cmd.Context()) + err := service.StartCLIServer(utils.GetMinterHome()+"/manager.sock", service.NewManager(app, client, tmNode, cfg), cmd.Context()) if err != nil { panic(err) } diff --git a/core/code/code.go b/core/code/code.go index 96354ae2c..bd933e5c9 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -1,5 +1,9 @@ package code +import ( + "strconv" +) + // Codes for transaction checks and delivers responses const ( // general @@ -65,3 +69,202 @@ const ( TooLargeOwnersList uint32 = 605 DuplicatedAddresses uint32 = 606 ) + +type wrongNonce struct { + Code string `json:"code,omitempty"` + ExpectedNonce string `json:"expected_nonce,omitempty"` + GotNonce string `json:"got_nonce,omitempty"` +} + +func NewWrongNonce(expectedNonce string, gotNonce string) *wrongNonce { + return &wrongNonce{Code: strconv.Itoa(int(WrongNonce)), ExpectedNonce: expectedNonce, GotNonce: gotNonce} +} + +type coinNotExists struct { + Code string `json:"code,omitempty"` + CoinSymbol string `json:"coin_symbol,omitempty"` + CoinId string `json:"coin_id,omitempty"` +} + +func NewCoinNotExists(coinSymbol string, coinId string) *coinNotExists { + return &coinNotExists{Code: strconv.Itoa(int(CoinNotExists)), CoinSymbol: coinSymbol, CoinId: coinId} +} + +type coinReserveNotSufficient struct { + Code string `json:"code,omitempty"` + CoinSymbol string `json:"coin_symbol,omitempty"` + CoinId string `json:"coin_id,omitempty"` + HasBipValue string `json:"has_bip_value,omitempty"` + RequiredBipValue string `json:"required_bip_value,omitempty"` +} + +func NewCoinReserveNotSufficient(coinSymbol string, coinId string, hasBipValue string, requiredBipValue string) *coinReserveNotSufficient { + return &coinReserveNotSufficient{Code: strconv.Itoa(int(CoinReserveNotSufficient)), CoinSymbol: coinSymbol, CoinId: coinId, HasBipValue: hasBipValue, RequiredBipValue: requiredBipValue} +} + +type txTooLarge struct { + Code string `json:"code,omitempty"` + MaxTxLength string `json:"max_tx_length,omitempty"` + GotTxLength string `json:"got_tx_length,omitempty"` +} + +func NewTxTooLarge(maxTxLength string, gotTxLength string) *txTooLarge { + return &txTooLarge{Code: strconv.Itoa(int(TxTooLarge)), MaxTxLength: maxTxLength, GotTxLength: gotTxLength} +} + +type decodeError struct { + Code string `json:"code,omitempty"` +} + +func NewDecodeError() *decodeError { + return &decodeError{Code: strconv.Itoa(int(DecodeError))} +} + +type insufficientFunds struct { + Code string `json:"code,omitempty"` + Sender string `json:"sender,omitempty"` + NeededBipValue string `json:"needed_bip_value,omitempty"` + CoinSymbol string `json:"coin_symbol,omitempty"` + CoinId string `json:"coin_id,omitempty"` +} + +func NewInsufficientFunds(sender string, neededBipValue string, coinSymbol string, coinId string) *insufficientFunds { + return &insufficientFunds{Code: strconv.Itoa(int(InsufficientFunds)), Sender: sender, NeededBipValue: neededBipValue, CoinSymbol: coinSymbol, CoinId: coinId} +} + +type txPayloadTooLarge struct { + Code string `json:"code,omitempty"` + MaxPayloadLength string `json:"max_payload_length,omitempty"` + GotPayloadLength string `json:"got_payload_length,omitempty"` +} + +func NewTxPayloadTooLarge(maxPayloadLength string, gotPayloadLength string) *txPayloadTooLarge { + return &txPayloadTooLarge{Code: strconv.Itoa(int(TxPayloadTooLarge)), MaxPayloadLength: maxPayloadLength, GotPayloadLength: gotPayloadLength} +} + +type txServiceDataTooLarge struct { + Code string `json:"code,omitempty"` + MaxServiceDataLength string `json:"max_service_data_length,omitempty"` + GotServiceDataLength string `json:"got_service_data_length,omitempty"` +} + +func NewTxServiceDataTooLarge(maxServiceDataLength string, gotServiceDataLength string) *txServiceDataTooLarge { + return &txServiceDataTooLarge{Code: strconv.Itoa(int(TxServiceDataTooLarge)), MaxServiceDataLength: maxServiceDataLength, GotServiceDataLength: gotServiceDataLength} +} + +type invalidMultisendData struct { + Code string `json:"code,omitempty"` + MinQuantity string `json:"min_quantity,omitempty"` + MaxQuantity string `json:"max_quantity,omitempty"` + GotQuantity string `json:"got_quantity,omitempty"` +} + +func NewInvalidMultisendData(minQuantity string, maxQuantity string, gotQuantity string) *invalidMultisendData { + return &invalidMultisendData{Code: strconv.Itoa(int(InvalidMultisendData)), MinQuantity: minQuantity, MaxQuantity: maxQuantity, GotQuantity: gotQuantity} +} + +type coinSupplyOverflow struct { + Code string `json:"code,omitempty"` + Delta string `json:"delta,omitempty"` + CoinSupply string `json:"coin_supply,omitempty"` + CurrentSupply string `json:"current_supply,omitempty"` + MaxCoinSupply string `json:"max_coin_supply,omitempty"` + CoinSymbol string `json:"coin_symbol,omitempty"` + CoinId string `json:"coin_id,omitempty"` +} + +func NewCoinSupplyOverflow(delta string, coinSupply string, currentSupply string, maxCoinSupply string, coinSymbol string, coinId string) *coinSupplyOverflow { + return &coinSupplyOverflow{Code: strconv.Itoa(int(CoinSupplyOverflow)), Delta: delta, CoinSupply: coinSupply, CurrentSupply: currentSupply, MaxCoinSupply: maxCoinSupply, CoinSymbol: coinSymbol, CoinId: coinId} +} + +type txFromSenderAlreadyInMempool struct { + Code string `json:"code,omitempty"` + Sender string `json:"sender,omitempty"` +} + +func NewTxFromSenderAlreadyInMempool(sender string, itoa string) *txFromSenderAlreadyInMempool { + return &txFromSenderAlreadyInMempool{Code: strconv.Itoa(int(TxFromSenderAlreadyInMempool)), Sender: sender} +} + +type tooLowGasPrice struct { + Code string `json:"code,omitempty"` + MinGasPrice string `json:"min_gas_price,omitempty"` + GotGasPrice string `json:"got_gas_price,omitempty"` +} + +func NewTooLowGasPrice(minGasPrice string, gotGasPrice string) *tooLowGasPrice { + return &tooLowGasPrice{Code: strconv.Itoa(int(TooLowGasPrice)), MinGasPrice: minGasPrice, GotGasPrice: gotGasPrice} +} + +type wrongChainID struct { + Code string `json:"code,omitempty"` + CurrentChainId string `json:"current_chain_id,omitempty"` + GotChainId string `json:"got_chain_id,omitempty"` +} + +func NewWrongChainID(currentChainId string, gotChainId string) *wrongChainID { + return &wrongChainID{Code: strconv.Itoa(int(WrongChainID)), CurrentChainId: currentChainId, GotChainId: gotChainId} +} + +type coinReserveUnderflow struct { + Code string `json:"code,omitempty"` + Delta string `json:"delta,omitempty"` + CoinReserve string `json:"coin_reserve,omitempty"` + CurrentReserve string `json:"current_reserve,omitempty"` + MinCoinReserve string `json:"min_coin_reserve,omitempty"` + CoinSymbol string `json:"coin_symbol,omitempty"` + CoinId string `json:"coin_id,omitempty"` +} + +func NewCoinReserveUnderflow(delta string, coinReserve string, currentReserve string, minCoinReserve string, coinSymbol string, coinId string) *coinReserveUnderflow { + return &coinReserveUnderflow{Code: strconv.Itoa(int(CoinReserveUnderflow)), Delta: delta, CoinReserve: coinReserve, CurrentReserve: currentReserve, MinCoinReserve: minCoinReserve, CoinSymbol: coinSymbol, CoinId: coinId} +} + +type coinAlreadyExists struct { + Code string `json:"code,omitempty"` + CoinSymbol string `json:"coin_symbol,omitempty"` + CoinId string `json:"coin_id,omitempty"` +} + +func NewCoinAlreadyExists(coinSymbol string, coinId string) *coinAlreadyExists { + return &coinAlreadyExists{Code: strconv.Itoa(int(CoinAlreadyExists)), CoinSymbol: coinSymbol, CoinId: coinId} +} + +type invalidCoinSymbol struct { + Code string `json:"code,omitempty"` + Pattern string `json:"pattern,omitempty"` + CoinSymbol string `json:"coin_symbol,omitempty"` +} + +func NewInvalidCoinSymbol(pattern string, coinSymbol string) *invalidCoinSymbol { + return &invalidCoinSymbol{Code: strconv.Itoa(int(InvalidCoinSymbol)), Pattern: pattern, CoinSymbol: coinSymbol} +} + +type invalidCoinName struct { + Code string `json:"code,omitempty"` + MaxBytes string `json:"max_bytes,omitempty"` + GotBytes string `json:"got_bytes,omitempty"` +} + +func NewInvalidCoinName(maxBytes string, gotBytes string) *invalidCoinName { + return &invalidCoinName{Code: strconv.Itoa(int(InvalidCoinName)), MaxBytes: maxBytes, GotBytes: gotBytes} +} + +// todo +type wrongCoinSupply struct { + Code string `json:"code,omitempty"` + MaxBytes string `json:"max_bytes,omitempty"` + GotBytes string `json:"got_bytes,omitempty"` +} + +func NewWrongCoinSupply(maxBytes string, gotBytes string) *wrongCoinSupply { + return &wrongCoinSupply{Code: strconv.Itoa(int(WrongCoinSupply)), MaxBytes: maxBytes, GotBytes: gotBytes} +} + +type tooHighGasPrice struct { + Code string `json:"code,omitempty"` +} + +func NewTooHighGasPrice() *tooHighGasPrice { + return &tooHighGasPrice{Code: strconv.Itoa(int(TooHighGasPrice))} +} diff --git a/core/minter/minter.go b/core/minter/minter.go index 29d16940d..425f73ba1 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -23,11 +23,8 @@ import ( abciTypes "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto/ed25519" cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" - "github.com/tendermint/tendermint/evidence" tmNode "github.com/tendermint/tendermint/node" - "github.com/tendermint/tendermint/p2p" types2 "github.com/tendermint/tendermint/types" - typesT "github.com/tendermint/tendermint/types" "github.com/tendermint/tm-db" "math/big" "sort" @@ -638,41 +635,6 @@ func (app *Blockchain) GetValidatorStatus(address types.TmAddress) int8 { return app.validatorsStatuses[address] } -// MaxPeerHeight returns max height of connected peers -// TODO: move outside Blockchain struct -func (app *Blockchain) MaxPeerHeight() int64 { - var max int64 - for _, peer := range app.tmNode.Switch().Peers().List() { - peerState, ok := peer.Get(typesT.PeerStateKey).(evidence.PeerState) - if !ok { - continue - } - height := peerState.GetHeight() - if height > max { - max = height - } - } - return max -} - -// PeerHeight returns height of peer by ID. If peer is fast_syncing, height equal 0 -// TODO: move outside Blockchain struct -func (app *Blockchain) PeerHeight(id p2p.ID) int64 { - peerTM := app.tmNode.Switch().Peers().Get(id) - if peerTM == nil { - return 0 - } - ps := peerTM.Get(typesT.PeerStateKey) - if ps == nil { - return 0 - } - peerState, ok := ps.(evidence.PeerState) - if !ok { - return 0 - } - return peerState.GetHeight() -} - // DeleteStateVersions deletes states in given range func (app *Blockchain) DeleteStateVersions(from, to int64) error { app.lock.RLock() diff --git a/core/transaction/buy_coin.go b/core/transaction/buy_coin.go index 449bd76a0..152b38ae3 100644 --- a/core/transaction/buy_coin.go +++ b/core/transaction/buy_coin.go @@ -41,7 +41,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( if !data.CoinToBuy.IsBaseCoin() { coin := context.Coins().GetCoin(data.CoinToBuy) - if errResp := CheckForCoinSupplyOverflow(coin.Volume(), data.ValueToBuy, coin.MaxSupply()); errResp != nil { + if errResp := CheckForCoinSupplyOverflow(coin, data.ValueToBuy); errResp != nil { return nil, nil, nil, errResp } } @@ -61,6 +61,8 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( data.MaximumValueToSell.String(), value.String()), Info: EncodeError(map[string]string{ "code": strconv.Itoa(int(code.MaximumValueToSellReached)), + "coin_symbol": coin.GetFullSymbol(), + "coin_id": coin.ID().String(), "maximum_value_to_sell": data.MaximumValueToSell.String(), "needed_spend_value": value.String(), }), @@ -84,12 +86,12 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_value": coin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin": fmt.Sprintf("%s", types.GetBaseCoin()), - }), + Info: EncodeError(code.NewCoinReserveNotSufficient( + coin.GetFullSymbol(), + coin.ID().String(), + coin.Reserve().String(), + commissionInBaseCoin.String(), + )), } } @@ -130,6 +132,8 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( data.MaximumValueToSell.String(), value.String()), Info: EncodeError(map[string]string{ "code": strconv.Itoa(int(code.MaximumValueToSellReached)), + "coin_symbol": coin.GetFullSymbol(), + "coin_id": coin.ID().String(), "maximum_value_to_sell": data.MaximumValueToSell.String(), "needed_spend_value": value.String(), }), @@ -158,12 +162,12 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( types.GetBaseCoin(), baseCoinNeeded.String(), types.GetBaseCoin()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_value": coinFrom.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin": fmt.Sprintf("%s", types.GetBaseCoin()), - }), + Info: EncodeError(code.NewCoinReserveNotSufficient( + coinFrom.GetFullSymbol(), + coinFrom.ID().String(), + coinFrom.Reserve().String(), + commissionInBaseCoin.String(), + )), } } @@ -184,12 +188,12 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_value": coinTo.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin": fmt.Sprintf("%s", types.GetBaseCoin()), - }), + Info: EncodeError(code.NewCoinReserveNotSufficient( + coinTo.GetFullSymbol(), + coinTo.ID().String(), + coinTo.Reserve().String(), + commissionInBaseCoin.String(), + )), } } @@ -213,6 +217,8 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( data.MaximumValueToSell.String(), value.String()), Info: EncodeError(map[string]string{ "code": strconv.Itoa(int(code.MaximumValueToSellReached)), + "coin_symbol": coinFrom.GetFullSymbol(), + "coin_id": coinFrom.ID().String(), "maximum_value_to_sell": data.MaximumValueToSell.String(), "needed_spend_value": value.String(), }), @@ -236,12 +242,12 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_value": coinFrom.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin": fmt.Sprintf("%s", types.GetBaseCoin()), - }), + Info: EncodeError(code.NewCoinReserveNotSufficient( + coinFrom.GetFullSymbol(), + coinFrom.ID().String(), + coinFrom.Reserve().String(), + commissionInBaseCoin.String(), + )), } } @@ -262,6 +268,8 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( Log: fmt.Sprintf("You wanted to sell maximum %s, but currently you need to spend %s to complete tx", data.MaximumValueToSell.String(), totalValue.String()), Info: EncodeError(map[string]string{ "code": strconv.Itoa(int(code.MaximumValueToSellReached)), + "coin_symbol": coinFrom.GetFullSymbol(), + "coin_id": coinFrom.ID().String(), "maximum_value_to_sell": data.MaximumValueToSell.String(), "needed_spend_value": value.String(), }), @@ -294,12 +302,12 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_value": coin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin": fmt.Sprintf("%s", types.GetBaseCoin()), - }), + Info: EncodeError(code.NewCoinReserveNotSufficient( + coin.GetFullSymbol(), + coin.ID().String(), + coin.Reserve().String(), + commissionInBaseCoin.String(), + )), } } @@ -323,9 +331,7 @@ func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.CheckState) * return &Response{ Code: code.DecodeError, Log: "Incorrect tx data", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.DecodeError)), - }), + Info: EncodeError(code.NewDecodeError()), } } @@ -344,10 +350,7 @@ func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.CheckState) * return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.CoinToSell), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": fmt.Sprintf("%s", data.CoinToSell.String()), - }), + Info: EncodeError(code.NewCoinNotExists("", data.CoinToSell.String())), } } @@ -355,10 +358,7 @@ func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.CheckState) * return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.CoinToBuy), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": fmt.Sprintf("%s", data.CoinToBuy.String()), - }), + Info: EncodeError(code.NewCoinNotExists("", data.CoinToBuy.String())), } } @@ -394,12 +394,7 @@ func (data BuyCoinData) Run(tx *Transaction, context state.Interface, rewardPool sender.String(), ts.Value.String(), coin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": ts.Value.String(), - "coin_symbol": coin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), ts.Value.String(), coin.GetFullSymbol(), coin.ID().String())), } } } diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index 81c890470..34e58b028 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -19,9 +19,10 @@ const maxCoinNameBytes = 64 const allowedCoinSymbols = "^[A-Z0-9]{3,10}$" var ( - minCoinSupply = helpers.BipToPip(big.NewInt(1)) - minCoinReserve = helpers.BipToPip(big.NewInt(10000)) - maxCoinSupply = big.NewInt(0).Exp(big.NewInt(10), big.NewInt(15+18), nil) + minCoinSupply = helpers.BipToPip(big.NewInt(1)) + minCoinReserve = helpers.BipToPip(big.NewInt(10000)) + maxCoinSupply = big.NewInt(0).Exp(big.NewInt(10), big.NewInt(15+18), nil) + allowedCoinSymbolsRegexpCompile, _ = regexp.Compile(allowedCoinSymbols) ) type CreateCoinData struct { @@ -38,9 +39,7 @@ func (data CreateCoinData) BasicCheck(tx *Transaction, context *state.CheckState return &Response{ Code: code.DecodeError, Log: "Incorrect tx data", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.DecodeError)), - }), + Info: EncodeError(code.NewDecodeError()), } } @@ -48,19 +47,15 @@ func (data CreateCoinData) BasicCheck(tx *Transaction, context *state.CheckState return &Response{ Code: code.InvalidCoinName, Log: fmt.Sprintf("Coin name is invalid. Allowed up to %d bytes.", maxCoinNameBytes), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InvalidCoinName)), - }), + Info: EncodeError(code.NewInvalidCoinName(strconv.Itoa(maxCoinNameBytes), strconv.Itoa(len(data.Name)))), } } - if match, _ := regexp.MatchString(allowedCoinSymbols, data.Symbol.String()); !match { + if match := allowedCoinSymbolsRegexpCompile.MatchString(data.Symbol.String()); !match { return &Response{ Code: code.InvalidCoinSymbol, Log: fmt.Sprintf("Invalid coin symbol. Should be %s", allowedCoinSymbols), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InvalidCoinSymbol)), - }), + Info: EncodeError(code.NewInvalidCoinSymbol(allowedCoinSymbols, data.Symbol.String())), } } @@ -68,11 +63,8 @@ func (data CreateCoinData) BasicCheck(tx *Transaction, context *state.CheckState return &Response{ Code: code.CoinAlreadyExists, Log: fmt.Sprintf("Coin already exists"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinAlreadyExists)), - }), + Info: EncodeError(code.NewCoinAlreadyExists(types.StrToCoinSymbol(data.Symbol.String()).String(), context.Coins().GetCoinBySymbol(data.Symbol, 0).ID().String())), } - } if data.ConstantReserveRatio < 10 || data.ConstantReserveRatio > 100 { @@ -84,21 +76,26 @@ func (data CreateCoinData) BasicCheck(tx *Transaction, context *state.CheckState })} } - if data.InitialAmount.Cmp(minCoinSupply) == -1 || data.InitialAmount.Cmp(data.MaxSupply) == 1 { + if data.MaxSupply.Cmp(maxCoinSupply) == 1 { return &Response{ Code: code.WrongCoinSupply, - Log: fmt.Sprintf("Coin supply should be between %s and %s", minCoinSupply.String(), data.MaxSupply.String()), + Log: fmt.Sprintf("Max coin supply should be less than %s", maxCoinSupply), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongCoinSupply)), + "code": strconv.Itoa(int(code.WrongCoinSupply)), + "max_coin_supply": maxCoinSupply.String(), + "current_coin_supply": data.MaxSupply.String(), })} } - if data.MaxSupply.Cmp(maxCoinSupply) == 1 { + if data.InitialAmount.Cmp(minCoinSupply) == -1 || data.InitialAmount.Cmp(data.MaxSupply) == 1 { return &Response{ Code: code.WrongCoinSupply, - Log: fmt.Sprintf("Max coin supply should be less than %s", maxCoinSupply), + Log: fmt.Sprintf("Coin supply should be between %s and %s", minCoinSupply.String(), data.MaxSupply.String()), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongCoinSupply)), + "code": strconv.Itoa(int(code.WrongCoinSupply)), + "min_initial_amount": minCoinSupply.String(), + "current_initial_amount": data.InitialAmount.String(), + "max_initial_amount": data.MaxSupply.String(), })} } @@ -107,7 +104,9 @@ func (data CreateCoinData) BasicCheck(tx *Transaction, context *state.CheckState Code: code.WrongCoinSupply, Log: fmt.Sprintf("Coin reserve should be greater than or equal to %s", minCoinReserve.String()), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongCoinSupply)), + "code": strconv.Itoa(int(code.WrongCoinSupply)), + "min_initial_reserve": minCoinReserve.String(), + "current_initial_reserve": data.InitialReserve.String(), })} } @@ -167,12 +166,7 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": commission.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), commission.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } @@ -180,12 +174,7 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), data.InitialReserve.String(), types.GetBaseCoin()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_reserve": data.InitialReserve.String(), - "coin_symbol": fmt.Sprintf("%s", types.GetBaseCoin().String()), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), data.InitialReserve.String(), types.GetBaseCoin().String(), types.GetBaseCoinID().String())), } } @@ -200,12 +189,7 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": totalTxCost.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), totalTxCost.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } } diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index 9cf574095..9515ef021 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -112,12 +112,7 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": commission.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), commission.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index 6db53dd42..e3111b463 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -31,19 +31,15 @@ func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.Chec return &Response{ Code: code.DecodeError, Log: "Incorrect tx data", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.DecodeError)), - })} + Info: EncodeError(code.NewDecodeError()), + } } if !context.Coins().Exists(data.Coin) { return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Coin), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": fmt.Sprintf("%s", data.Coin.String()), - }), + Info: EncodeError(code.NewCoinNotExists("", data.Coin.String())), } } @@ -137,12 +133,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), data.Stake, coin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": data.Stake.String(), - "coin_symbol": coin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), data.Stake.String(), coin.GetFullSymbol(), coin.ID().String())), } } @@ -150,12 +141,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": commission.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), commission.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } @@ -168,12 +154,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": totalTxCost.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), totalTxCost.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } } diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index efc58c57d..6f42e7d04 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -26,29 +26,24 @@ func (data DelegateData) BasicCheck(tx *Transaction, context *state.CheckState) return &Response{ Code: code.DecodeError, Log: "Incorrect tx data", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.DecodeError)), - })} + Info: EncodeError(code.NewDecodeError()), + } } if !context.Coins().Exists(tx.GasCoin) { return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", tx.GasCoin), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": fmt.Sprintf("%s", tx.GasCoin.String()), - })} + Info: EncodeError(code.NewCoinNotExists("", tx.GasCoin.String())), + } } if !context.Coins().Exists(data.Coin) { return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Coin), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": fmt.Sprintf("%s", data.Coin.String()), - })} + Info: EncodeError(code.NewCoinNotExists("", data.Coin.String())), + } } if data.Value.Cmp(types.Big0) < 1 { @@ -127,12 +122,7 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": commission.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), commission.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } @@ -140,12 +130,7 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), data.Value, coin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": data.Value.String(), - "coin_symbol": coin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), data.Value.String(), coin.GetFullSymbol(), coin.ID().String())), } } @@ -158,12 +143,7 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": totalTxCost.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), totalTxCost.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } } diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index e79551398..efc8505b6 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -74,12 +74,7 @@ func (data EditCandidateData) Run(tx *Transaction, context state.Interface, rewa return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": commission.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), commission.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } diff --git a/core/transaction/edit_candidate_public_key.go b/core/transaction/edit_candidate_public_key.go index bc20fa708..d1a614274 100644 --- a/core/transaction/edit_candidate_public_key.go +++ b/core/transaction/edit_candidate_public_key.go @@ -80,12 +80,7 @@ func (data EditCandidatePublicKeyData) Run(tx *Transaction, context state.Interf return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": commission.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), commission.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } diff --git a/core/transaction/edit_coin_owner.go b/core/transaction/edit_coin_owner.go index 3289ef40a..849acb550 100644 --- a/core/transaction/edit_coin_owner.go +++ b/core/transaction/edit_coin_owner.go @@ -27,10 +27,7 @@ func (data EditCoinOwnerData) BasicCheck(tx *Transaction, context *state.CheckSt return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Symbol), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_symbol": data.Symbol.String(), - }), + Info: EncodeError(code.NewCoinNotExists(data.Symbol.String(), "")), } } @@ -89,12 +86,7 @@ func (data EditCoinOwnerData) Run(tx *Transaction, context state.Interface, rewa return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": commission.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), commission.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } diff --git a/core/transaction/edit_multisig_owners.go b/core/transaction/edit_multisig_owners.go index 79224a93c..d87b20f1d 100644 --- a/core/transaction/edit_multisig_owners.go +++ b/core/transaction/edit_multisig_owners.go @@ -144,12 +144,7 @@ func (data EditMultisigOwnersData) Run(tx *Transaction, context state.Interface, return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": commission.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), commission.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } diff --git a/core/transaction/executor.go b/core/transaction/executor.go index 530ccfc8a..1465629be 100644 --- a/core/transaction/executor.go +++ b/core/transaction/executor.go @@ -47,11 +47,7 @@ func RunTx(context state.Interface, return Response{ Code: code.TxTooLarge, Log: fmt.Sprintf("TX length is over %d bytes", maxTxLength), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.TxTooLarge)), - "max_tx_length": fmt.Sprintf("%d", maxTxLength), - "got_tx_length": fmt.Sprintf("%d", lenRawTx), - }), + Info: EncodeError(code.NewTxTooLarge(fmt.Sprintf("%d", maxTxLength), fmt.Sprintf("%d", lenRawTx))), } } @@ -60,9 +56,7 @@ func RunTx(context state.Interface, return Response{ Code: code.DecodeError, Log: err.Error(), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.DecodeError)), - }), + Info: EncodeError(code.NewDecodeError()), } } @@ -70,11 +64,7 @@ func RunTx(context state.Interface, return Response{ Code: code.WrongChainID, Log: "Wrong chain id", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongChainID)), - "current_chain_id": fmt.Sprintf("%d", types.CurrentChainID), - "got_chain_id": fmt.Sprintf("%d", tx.ChainID), - }), + Info: EncodeError(code.NewWrongChainID(fmt.Sprintf("%d", types.CurrentChainID), fmt.Sprintf("%d", tx.ChainID))), } } @@ -88,10 +78,7 @@ func RunTx(context state.Interface, return Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", tx.GasCoin), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": tx.GasCoin.String(), - }), + Info: EncodeError(code.NewCoinNotExists("", tx.GasCoin.String())), } } @@ -99,11 +86,7 @@ func RunTx(context state.Interface, return Response{ Code: code.TooLowGasPrice, Log: fmt.Sprintf("Gas price of tx is too low to be included in mempool. Expected %d", minGasPrice), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.TooLowGasPrice)), - "min_gas_price": fmt.Sprintf("%d", minGasPrice), - "got_gas_price": fmt.Sprintf("%d", tx.GasPrice), - }), + Info: EncodeError(code.NewTooLowGasPrice(fmt.Sprintf("%d", minGasPrice), fmt.Sprintf("%d", tx.GasPrice))), } } @@ -112,11 +95,7 @@ func RunTx(context state.Interface, return Response{ Code: code.TxPayloadTooLarge, Log: fmt.Sprintf("TX payload length is over %d bytes", maxPayloadLength), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.TxPayloadTooLarge)), - "max_payload_length": fmt.Sprintf("%d", maxPayloadLength), - "got_payload_length": fmt.Sprintf("%d", lenPayload), - }), + Info: EncodeError(code.NewTxPayloadTooLarge(fmt.Sprintf("%d", maxPayloadLength), fmt.Sprintf("%d", lenPayload))), } } @@ -125,11 +104,7 @@ func RunTx(context state.Interface, return Response{ Code: code.TxServiceDataTooLarge, Log: fmt.Sprintf("TX service data length is over %d bytes", maxServiceDataLength), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.TxServiceDataTooLarge)), - "max_service_data_length": fmt.Sprintf("%d", maxServiceDataLength), - "got_service_data_length": fmt.Sprintf("%d", lenServiceData), - }), + Info: EncodeError(code.NewTxServiceDataTooLarge(fmt.Sprintf("%d", maxServiceDataLength), fmt.Sprintf("%d", lenServiceData))), } } @@ -138,9 +113,7 @@ func RunTx(context state.Interface, return Response{ Code: code.DecodeError, Log: err.Error(), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.DecodeError)), - }), + Info: EncodeError(code.NewDecodeError()), } } @@ -149,10 +122,7 @@ func RunTx(context state.Interface, return Response{ Code: code.TxFromSenderAlreadyInMempool, Log: fmt.Sprintf("Tx from %s already exists in mempool", sender.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.TxFromSenderAlreadyInMempool)), - "sender": sender.String(), - }), + Info: EncodeError(code.NewTxFromSenderAlreadyInMempool(sender.String(), strconv.Itoa(int(currentBlock)))), } } @@ -236,11 +206,7 @@ func RunTx(context state.Interface, return Response{ Code: code.WrongNonce, Log: fmt.Sprintf("Unexpected nonce. Expected: %d, got %d.", expectedNonce, tx.Nonce), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongNonce)), - "expected_nonce": fmt.Sprintf("%d", expectedNonce), - "got_nonce": fmt.Sprintf("%d", tx.Nonce), - }), + Info: EncodeError(code.NewWrongNonce(fmt.Sprintf("%d", expectedNonce), fmt.Sprintf("%d", tx.Nonce))), } } @@ -270,7 +236,7 @@ func RunTx(context state.Interface, return response } -func EncodeError(data map[string]string) string { +func EncodeError(data interface{}) string { marshal, err := json.Marshal(data) if err != nil { panic(err) diff --git a/core/transaction/multisend.go b/core/transaction/multisend.go index 17b66fe8c..2f7c425ef 100644 --- a/core/transaction/multisend.go +++ b/core/transaction/multisend.go @@ -6,7 +6,6 @@ import ( "fmt" "math/big" "sort" - "strconv" "strings" "github.com/MinterTeam/minter-go-node/core/code" @@ -27,13 +26,7 @@ func (data MultisendData) BasicCheck(tx *Transaction, context *state.CheckState) return &Response{ Code: code.InvalidMultisendData, Log: "List length must be between 1 and 100", - Info: EncodeError(map[string]string{ - "code": fmt.Sprintf("%d", code.InvalidMultisendData), - "description": "invalid_multisend_data", - "min_quantity": "1", - "max_quantity": "100", - "got_quantity": fmt.Sprintf("%d", quantity), - }), + Info: EncodeError(code.NewInvalidMultisendData("1", "100", fmt.Sprintf("%d", quantity))), } } @@ -157,12 +150,7 @@ func checkBalances(context *state.CheckState, sender types.Address, items []Mult return &Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), value, coinData.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": fmt.Sprintf("%d", value), - "coin_symbol": coinData.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), value.String(), coinData.GetFullSymbol(), coinData.ID().String())), } } } @@ -176,10 +164,7 @@ func checkCoins(context *state.CheckState, items []MultisendDataItem) *Response return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", item.Coin), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": fmt.Sprintf("%s", item.Coin.String()), - }), + Info: EncodeError(code.NewCoinNotExists("", item.Coin.String())), } } } diff --git a/core/transaction/price_vote.go b/core/transaction/price_vote.go index 81b7444eb..4b354ae30 100644 --- a/core/transaction/price_vote.go +++ b/core/transaction/price_vote.go @@ -3,14 +3,12 @@ package transaction import ( "encoding/hex" "fmt" - "math/big" - "strconv" - "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" + "math/big" ) type PriceVoteData struct { @@ -61,12 +59,7 @@ func (data PriceVoteData) Run(tx *Transaction, context state.Interface, rewardPo return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": commission.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), commission.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } @@ -78,8 +71,6 @@ func (data PriceVoteData) Run(tx *Transaction, context state.Interface, rewardPo deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) deliverState.Accounts.SetNonce(sender, tx.Nonce) - - //todo } tags := kv.Pairs{ diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 6fc8f66fd..ca951b41a 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -28,9 +28,7 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta return &Response{ Code: code.DecodeError, Log: "Incorrect tx data", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.DecodeError)), - }), + Info: EncodeError(code.NewDecodeError()), } } @@ -38,9 +36,7 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta return &Response{ Code: code.InvalidCoinName, Log: fmt.Sprintf("Coin name is invalid. Allowed up to %d bytes.", maxCoinNameBytes), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InvalidCoinName)), - }), + Info: EncodeError(code.NewInvalidCoinName(strconv.Itoa(maxCoinNameBytes), strconv.Itoa(len(data.Name)))), } } @@ -91,10 +87,7 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Symbol), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_symbol": fmt.Sprintf("%s", data.Symbol.String()), - }), + Info: EncodeError(code.NewCoinNotExists(data.Symbol.String(), "")), } } @@ -155,12 +148,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission.String(), gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": commission.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), commission.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } @@ -168,12 +156,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), data.InitialReserve.String(), types.GetBaseCoin()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_reserve": data.InitialReserve.String(), - "coin_symbol": fmt.Sprintf("%s", types.GetBaseCoin()), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), data.InitialReserve.String(), types.GetBaseCoin().String(), types.GetBaseCoinID().String())), } } @@ -188,12 +171,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), totalTxCost.String(), gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": totalTxCost.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), totalTxCost.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } } diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index 171b52bcd..58db52eeb 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -29,9 +29,8 @@ func (data RedeemCheckData) BasicCheck(tx *Transaction, context *state.CheckStat return &Response{ Code: code.DecodeError, Log: "Incorrect tx data", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.DecodeError)), - })} + Info: EncodeError(code.NewDecodeError()), + } } // fixed potential problem with making too high commission for sender @@ -39,9 +38,8 @@ func (data RedeemCheckData) BasicCheck(tx *Transaction, context *state.CheckStat return &Response{ Code: code.TooHighGasPrice, Log: fmt.Sprintf("Gas price for check is limited to 1"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.TooHighGasPrice)), - })} + Info: EncodeError(code.NewTooHighGasPrice()), + } } return nil @@ -74,9 +72,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.DecodeError, Log: err.Error(), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.DecodeError)), - }), + Info: EncodeError(code.NewDecodeError()), } } @@ -84,11 +80,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.WrongChainID, Log: "Wrong chain id", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongChainID)), - "current_chain_id": fmt.Sprintf("%d", types.CurrentChainID), - "got_chain_id": fmt.Sprintf("%d", decodedCheck.ChainID), - }), + Info: EncodeError(code.NewWrongChainID(fmt.Sprintf("%d", types.CurrentChainID), fmt.Sprintf("%d", tx.ChainID))), } } @@ -108,19 +100,15 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.DecodeError, Log: err.Error(), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.DecodeError)), - })} + Info: EncodeError(code.NewDecodeError()), + } } if !checkState.Coins().Exists(decodedCheck.Coin) { return Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin not exists"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": fmt.Sprintf("%s", decodedCheck.Coin.String()), - }), + Info: EncodeError(code.NewCoinNotExists("", decodedCheck.Coin.String())), } } @@ -128,10 +116,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Gas coin not exists"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": fmt.Sprintf("%s", decodedCheck.GasCoin.String()), - }), + Info: EncodeError(code.NewCoinNotExists("", decodedCheck.GasCoin.String())), } } @@ -174,9 +159,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.DecodeError, Log: err.Error(), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.DecodeError)), - }), + Info: EncodeError(code.NewDecodeError()), } } @@ -193,9 +176,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.DecodeError, Log: err.Error(), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.DecodeError)), - }), + Info: EncodeError(code.NewDecodeError()), } } @@ -229,12 +210,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", decodedCheck.Coin, checkSender.String(), totalTxCost.String(), coin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": checkSender.String(), - "coin_symbol": coin.GetFullSymbol(), - "needed_value": totalTxCost.String(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), totalTxCost.String(), coin.GetFullSymbol(), coin.ID().String())), } } } else { @@ -242,12 +218,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", checkSender.String(), decodedCheck.Coin, decodedCheck.Value.String(), coin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": checkSender.String(), - "coin_symbol": coin.GetFullSymbol(), - "needed_value": decodedCheck.Value.String(), - }), + Info: EncodeError(code.NewInsufficientFunds(checkSender.String(), decodedCheck.Value.String(), coin.GetFullSymbol(), coin.ID().String())), } } @@ -255,12 +226,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for check issuer account: %s %s. Wanted %s %s", checkSender.String(), decodedCheck.GasCoin, commission.String(), gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - "needed_value": commission.String(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), commission.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } } diff --git a/core/transaction/sell_all_coin.go b/core/transaction/sell_all_coin.go index a4786e551..6e506d325 100644 --- a/core/transaction/sell_all_coin.go +++ b/core/transaction/sell_all_coin.go @@ -47,12 +47,14 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat Info: EncodeError(map[string]string{ "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), "minimum_value_to_buy": data.MinimumValueToBuy.String(), - "coin": value.String(), + "will_get_value": value.String(), + "coin_symbol": coin.GetFullSymbol(), + "coin_id": coin.ID().String(), }), } } - if errResp := CheckForCoinSupplyOverflow(coin.Volume(), value, coin.MaxSupply()); errResp != nil { + if errResp := CheckForCoinSupplyOverflow(coin, value); errResp != nil { return nil, nil, nil, errResp } @@ -76,6 +78,8 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), "minimum_value_to_buy": data.MinimumValueToBuy.String(), "will_get_value": ret.String(), + "coin_symbol": coin.GetFullSymbol(), + "coin_id": coin.ID().String(), }), } } @@ -84,12 +88,7 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat return nil, nil, nil, &Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "coin_symbol": coin.GetFullSymbol(), - "needed_value": commissionInBaseCoin.String(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), commissionInBaseCoin.String(), coin.GetFullSymbol(), coin.ID().String())), } } @@ -113,12 +112,7 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat return nil, nil, nil, &Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "coin_symbol": coinFrom.GetFullSymbol(), - "needed_value": commissionInBaseCoin.String(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), commissionInBaseCoin.String(), coinFrom.GetFullSymbol(), coinFrom.ID().String())), } } @@ -133,11 +127,13 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), "minimum_value_to_buy": data.MinimumValueToBuy.String(), "will_get_value": value.String(), + "coin_symbol": coinTo.GetFullSymbol(), + "coin_id": coinTo.ID().String(), }), } } - if errResp := CheckForCoinSupplyOverflow(coinTo.Volume(), value, coinTo.MaxSupply()); errResp != nil { + if errResp := CheckForCoinSupplyOverflow(coinTo, value); errResp != nil { return nil, nil, nil, errResp } @@ -171,10 +167,7 @@ func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.CheckStat return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin to sell not exists"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": fmt.Sprintf("%s", data.CoinToSell.String()), - }), + Info: EncodeError(code.NewCoinNotExists("", data.CoinToSell.String())), } } @@ -182,10 +175,7 @@ func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.CheckStat return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin to buy not exists"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": fmt.Sprintf("%s", data.CoinToBuy.String()), - }), + Info: EncodeError(code.NewCoinNotExists("", data.CoinToBuy.String())), } } @@ -230,12 +220,7 @@ func (data SellAllCoinData) Run(tx *Transaction, context state.Interface, reward sender.String(), ts.Value.String(), coin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": ts.Value.String(), - "coin_symbol": coin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), ts.Value.String(), coin.GetFullSymbol(), coin.ID().String())), } } } diff --git a/core/transaction/sell_coin.go b/core/transaction/sell_coin.go index b3c85742c..403ca2716 100644 --- a/core/transaction/sell_coin.go +++ b/core/transaction/sell_coin.go @@ -39,7 +39,11 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) Code: code.MinimumValueToBuyReached, Log: fmt.Sprintf("You wanted to get minimum %s, but currently you will get %s", data.MinimumValueToBuy.String(), value.String()), Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), + "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), + "minimum_value_to_buy": data.MinimumValueToBuy.String(), + "will_get_value": value.String(), + "coin_symbol": coin.GetFullSymbol(), + "coin_id": coin.ID().String(), }), } } @@ -64,7 +68,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) }) } - if errResp := CheckForCoinSupplyOverflow(coin.Volume(), value, coin.MaxSupply()); errResp != nil { + if errResp := CheckForCoinSupplyOverflow(coin, value); errResp != nil { return nil, nil, nil, errResp } @@ -86,7 +90,9 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) Info: EncodeError(map[string]string{ "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), "minimum_value_to_buy": data.MinimumValueToBuy.String(), - "value_to_buy": value.String(), + "will_get_value": value.String(), + "coin_symbol": coin.GetFullSymbol(), + "coin_id": coin.ID().String(), }), } } @@ -111,12 +117,12 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_value": coin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin_symbol": fmt.Sprintf("%s", types.GetBaseCoin()), - }), + Info: EncodeError(code.NewCoinReserveNotSufficient( + coin.GetFullSymbol(), + coin.ID().String(), + coin.Reserve().String(), + commissionInBaseCoin.String(), + )), } } @@ -163,12 +169,12 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_value": coinFrom.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin_symbol": fmt.Sprintf("%s", types.GetBaseCoin()), - }), + Info: EncodeError(code.NewCoinReserveNotSufficient( + coinFrom.GetFullSymbol(), + coinFrom.ID().String(), + coinFrom.Reserve().String(), + commissionInBaseCoin.String(), + )), } } @@ -192,7 +198,9 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) Info: EncodeError(map[string]string{ "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), "minimum_value_to_buy": data.MinimumValueToBuy.String(), - "get_value": value.String(), + "will_get_value": value.String(), + "coin_symbol": coinTo.GetFullSymbol(), + "coin_id": coinTo.ID().String(), }), } } @@ -217,7 +225,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) }) } - if errResp := CheckForCoinSupplyOverflow(coinTo.Volume(), value, coinTo.MaxSupply()); errResp != nil { + if errResp := CheckForCoinSupplyOverflow(coinTo, value); errResp != nil { return nil, nil, nil, errResp } @@ -247,12 +255,12 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) types.GetBaseCoin(), commissionInBaseCoin.String(), types.GetBaseCoin()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveNotSufficient)), - "has_value": coin.Reserve().String(), - "required_value": commissionInBaseCoin.String(), - "coin_symbol": fmt.Sprintf("%s", types.GetBaseCoin()), - }), + Info: EncodeError(code.NewCoinReserveNotSufficient( + coin.GetFullSymbol(), + coin.ID().String(), + coin.Reserve().String(), + commissionInBaseCoin.String(), + )), } } @@ -298,10 +306,7 @@ func (data SellCoinData) BasicCheck(tx *Transaction, context *state.CheckState) return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin not exists"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": fmt.Sprintf("%s", data.CoinToSell.String()), - }), + Info: EncodeError(code.NewCoinNotExists("", data.CoinToSell.String())), } } @@ -309,10 +314,7 @@ func (data SellCoinData) BasicCheck(tx *Transaction, context *state.CheckState) return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin not exists"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": fmt.Sprintf("%s", data.CoinToBuy.String()), - }), + Info: EncodeError(code.NewCoinNotExists("", data.CoinToBuy.String())), } } @@ -355,14 +357,8 @@ func (data SellCoinData) Run(tx *Transaction, context state.Interface, rewardPoo Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s.", sender.String(), ts.Value.String(), - coin.GetFullSymbol(), - ), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": ts.Value.String(), - "coin_symbol": coin.GetFullSymbol(), - }), + coin.GetFullSymbol()), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), ts.Value.String(), coin.GetFullSymbol(), coin.ID().String())), } } } diff --git a/core/transaction/send.go b/core/transaction/send.go index ebb5fb502..4bd87e330 100644 --- a/core/transaction/send.go +++ b/core/transaction/send.go @@ -3,15 +3,13 @@ package transaction import ( "encoding/hex" "fmt" - "math/big" - "strconv" - "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" + "math/big" ) type SendData struct { @@ -60,9 +58,7 @@ func (data SendData) BasicCheck(tx *Transaction, context *state.CheckState) *Res return &Response{ Code: code.DecodeError, Log: "Incorrect tx data", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.DecodeError)), - }), + Info: EncodeError(code.NewDecodeError()), } } @@ -70,10 +66,7 @@ func (data SendData) BasicCheck(tx *Transaction, context *state.CheckState) *Res return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Coin), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": fmt.Sprintf("%s", data.Coin.String()), - }), + Info: EncodeError(code.NewCoinNotExists("", data.Coin.String())), } } @@ -118,12 +111,7 @@ func (data SendData) Run(tx *Transaction, context state.Interface, rewardPool *b sender.String(), ts.Value.String(), coin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": ts.Value.String(), - "coin_symbol": coin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), ts.Value.String(), coin.GetFullSymbol(), coin.ID().String())), } } } diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index 5007a724e..b7d5cdb47 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -93,12 +93,7 @@ func (data SetHaltBlockData) Run(tx *Transaction, context state.Interface, rewar return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": commission.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), commission.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index 49d21c126..fac13d23a 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -52,9 +52,9 @@ func (data SetCandidateOnData) Run(tx *Transaction, context state.Interface, rew commissionInBaseCoin := tx.CommissionInBaseCoin() commission := big.NewInt(0).Set(commissionInBaseCoin) - if !tx.GasCoin.IsBaseCoin() { - gasCoin := checkState.Coins().GetCoin(tx.GasCoin) + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) + if !tx.GasCoin.IsBaseCoin() { errResp := CheckReserveUnderflow(gasCoin, commissionInBaseCoin) if errResp != nil { return *errResp @@ -64,17 +64,10 @@ func (data SetCandidateOnData) Run(tx *Transaction, context state.Interface, rew } if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { - gasCoin := checkState.Coins().GetCoin(tx.GasCoin) - return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": commission.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), commission.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } @@ -140,27 +133,21 @@ func (data SetCandidateOffData) Run(tx *Transaction, context state.Interface, re commissionInBaseCoin := tx.CommissionInBaseCoin() commission := big.NewInt(0).Set(commissionInBaseCoin) + gasCoin := checkState.Coins().GetCoin(tx.GasCoin) if !tx.GasCoin.IsBaseCoin() { - coin := checkState.Coins().GetCoin(tx.GasCoin) - - errResp := CheckReserveUnderflow(coin, commissionInBaseCoin) + errResp := CheckReserveUnderflow(gasCoin, commissionInBaseCoin) if errResp != nil { return *errResp } - commission = formula.CalculateSaleAmount(coin.Volume(), coin.Reserve(), coin.Crr(), commissionInBaseCoin) + commission = formula.CalculateSaleAmount(gasCoin.Volume(), gasCoin.Reserve(), gasCoin.Crr(), commissionInBaseCoin) } if checkState.Accounts().GetBalance(sender, tx.GasCoin).Cmp(commission) < 0 { return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, tx.GasCoin), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": commission.String(), - "coin_symbol": fmt.Sprintf("%s", tx.GasCoin), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), commission.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index edeb71bb2..e78fb52e3 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -4,9 +4,6 @@ import ( "crypto/ecdsa" "errors" "fmt" - "math/big" - "strconv" - "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" @@ -15,6 +12,7 @@ import ( "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/crypto/sha3" "github.com/MinterTeam/minter-go-node/rlp" + "math/big" ) type TxType byte @@ -298,40 +296,30 @@ func rlpHash(x interface{}) (h types.Hash) { return h } -func CheckForCoinSupplyOverflow(current *big.Int, delta *big.Int, max *big.Int) *Response { - total := big.NewInt(0).Set(current) +func CheckForCoinSupplyOverflow(coin *coins.Model, delta *big.Int) *Response { + total := big.NewInt(0).Set(coin.Volume()) total.Add(total, delta) - if total.Cmp(max) != -1 { + if total.Cmp(coin.MaxSupply()) != -1 { return &Response{ Code: code.CoinSupplyOverflow, Log: "coin supply overflow", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinSupplyOverflow)), - "current": total.String(), - "delta": delta.String(), - "max": max.String(), - }), + Info: EncodeError(code.NewCoinSupplyOverflow(delta.String(), coin.Volume().String(), total.String(), coin.MaxSupply().String(), coin.GetFullSymbol(), coin.ID().String())), } } return nil } -func CheckReserveUnderflow(m *coins.Model, delta *big.Int) *Response { - total := big.NewInt(0).Sub(m.Reserve(), delta) +func CheckReserveUnderflow(coin *coins.Model, delta *big.Int) *Response { + total := big.NewInt(0).Sub(coin.Reserve(), delta) if total.Cmp(minCoinReserve) == -1 { min := big.NewInt(0).Add(minCoinReserve, delta) return &Response{ Code: code.CoinReserveUnderflow, - Log: fmt.Sprintf("coin %s reserve is too small (%s, required at least %s)", m.GetFullSymbol(), m.Reserve().String(), min.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinReserveUnderflow)), - "coin": m.Symbol().String(), - "coin_reserve": m.Reserve().String(), - "min_coin_reserve": min.String(), - }), + Log: fmt.Sprintf("coin %s reserve is too small (%s, required at least %s)", coin.GetFullSymbol(), coin.Reserve().String(), min.String()), + Info: EncodeError(code.NewCoinReserveUnderflow(delta.String(), coin.Reserve().String(), total.String(), minCoinReserve.String(), coin.GetFullSymbol(), coin.ID().String())), } } diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index d9f557b6f..947dbd62c 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -28,9 +28,7 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R return &Response{ Code: code.DecodeError, Log: "Incorrect tx data", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.DecodeError)), - }), + Info: EncodeError(code.NewDecodeError()), } } @@ -38,10 +36,7 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R return &Response{ Code: code.CoinNotExists, Log: fmt.Sprintf("Coin %s not exists", data.Coin), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CoinNotExists)), - "coin_id": fmt.Sprintf("%s", data.Coin.String()), - }), + Info: EncodeError(code.NewCoinNotExists("", data.Coin.String())), } } @@ -139,12 +134,7 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool return Response{ Code: code.InsufficientFunds, Log: fmt.Sprintf("Insufficient funds for sender account: %s. Wanted %s %s", sender.String(), commission, gasCoin.GetFullSymbol()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.InsufficientFunds)), - "sender": sender.String(), - "needed_value": commission.String(), - "coin_symbol": gasCoin.GetFullSymbol(), - }), + Info: EncodeError(code.NewInsufficientFunds(sender.String(), commission.String(), gasCoin.GetFullSymbol(), gasCoin.ID().String())), } } From 02eb3325207b2776448b6ac02b022c46b0046ffd Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 15 Sep 2020 13:50:21 +0300 Subject: [PATCH 262/426] wip: errors models and refactor api --- core/code/code.go | 83 +++++++++++++++++++ core/transaction/declare_candidacy.go | 10 +-- core/transaction/edit_candidate_public_key.go | 15 +--- core/transaction/redeem_check.go | 4 +- core/transaction/unbond.go | 22 ++--- 5 files changed, 94 insertions(+), 40 deletions(-) diff --git a/core/code/code.go b/core/code/code.go index bd933e5c9..a0ca9e84a 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -268,3 +268,86 @@ type tooHighGasPrice struct { func NewTooHighGasPrice() *tooHighGasPrice { return &tooHighGasPrice{Code: strconv.Itoa(int(TooHighGasPrice))} } + +type candidateExists struct { + Code string `json:"code,omitempty"` + PublicKey string `json:"public_key,omitempty"` +} + +func NewCandidateExists(publicKey string) *candidateExists { + return &candidateExists{Code: strconv.Itoa(int(CandidateExists)), PublicKey: publicKey} +} + +type candidateNotFound struct { + Code string `json:"code,omitempty"` + PublicKey string `json:"public_key,omitempty"` +} + +func NewCandidateNotFound(publicKey string) *candidateNotFound { + return &candidateNotFound{Code: strconv.Itoa(int(CandidateNotFound)), PublicKey: publicKey} +} + +type publicKeyInBlockList struct { + Code string `json:"code,omitempty"` + PublicKey string `json:"public_key,omitempty"` +} + +func NewPublicKeyInBlockList(publicKey string) *publicKeyInBlockList { + return &publicKeyInBlockList{Code: strconv.Itoa(int(PublicKeyInBlockList)), PublicKey: publicKey} +} + +type newPublicKeyIsBad struct { + Code string `json:"code,omitempty"` + PublicKey string `json:"public_key,omitempty"` + NewPublicKey string `json:"new_public_key,omitempty"` +} + +func NewNewPublicKeyIsBad(publicKey, newPublicKey string) *newPublicKeyIsBad { + return &newPublicKeyIsBad{Code: strconv.Itoa(int(NewPublicKeyIsBad)), PublicKey: publicKey, NewPublicKey: newPublicKey} +} + +type insufficientWaitList struct { + Code string `json:"code,omitempty"` + WaitlistValue string `json:"waitlist_value,omitempty"` + NeededValue string `json:"needed_value,omitempty"` +} + +func NewInsufficientWaitList(waitlistValue, neededValue string) *insufficientWaitList { + return &insufficientWaitList{Code: strconv.Itoa(int(InsufficientWaitList)), WaitlistValue: waitlistValue} +} + +type stakeNotFound struct { + Code string `json:"code,omitempty"` + PublicKey string `json:"public_key,omitempty"` + Owner string `json:"owner,omitempty"` + CoinSymbol string `json:"coin_symbol,omitempty"` + CoinId string `json:"coin_id,omitempty"` +} + +func NewStakeNotFound(publicKey string, owner string, coinId string, coinSymbol string) *stakeNotFound { + return &stakeNotFound{Code: strconv.Itoa(int(StakeNotFound)), PublicKey: publicKey, Owner: owner, CoinId: coinId, CoinSymbol: coinSymbol} +} + +type insufficientStake struct { + Code string `json:"code,omitempty"` + PublicKey string `json:"public_key,omitempty"` + Owner string `json:"owner,omitempty"` + CoinSymbol string `json:"coin_symbol,omitempty"` + CoinId string `json:"coin_id,omitempty"` + StakeValue string `json:"stake_value,omitempty"` + NeededValue string `json:"needed_value,omitempty"` +} + +func NewInsufficientStake(publicKey string, owner string, coinId string, coinSymbol string, stakeValue string, neededValue string) *insufficientStake { + return &insufficientStake{Code: strconv.Itoa(int(InsufficientStake)), PublicKey: publicKey, Owner: owner, CoinId: coinId, CoinSymbol: coinSymbol, StakeValue: stakeValue, NeededValue: neededValue} +} + +type tooLongNonce struct { + Code string `json:"code,omitempty"` + NonceBytes string `json:"nonce_bytes,omitempty"` + MaxNonceBytes string `json:"max_nonce_bytes,omitempty"` +} + +func NewTooLongNonce(nonceBytes string, maxNonceBytes string) *tooLongNonce { + return &tooLongNonce{Code: strconv.Itoa(int(TooLongNonce)), NonceBytes: nonceBytes, MaxNonceBytes: maxNonceBytes} +} diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index e3111b463..1a1939454 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -47,10 +47,7 @@ func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.Chec return &Response{ Code: code.CandidateExists, Log: fmt.Sprintf("Candidate with such public key (%s) already exists", data.PubKey.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CandidateExists)), - "public_key": data.PubKey.String(), - }), + Info: EncodeError(code.NewCandidateExists(data.PubKey.String())), } } @@ -58,10 +55,7 @@ func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.Chec return &Response{ Code: code.PublicKeyInBlockList, Log: fmt.Sprintf("Candidate with such public key (%s) exists in block list", data.PubKey.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.PublicKeyInBlockList)), - "public_key": data.PubKey.String(), - }), + Info: EncodeError(code.NewCandidateExists(data.PubKey.String())), } } diff --git a/core/transaction/edit_candidate_public_key.go b/core/transaction/edit_candidate_public_key.go index d1a614274..4ec8368ab 100644 --- a/core/transaction/edit_candidate_public_key.go +++ b/core/transaction/edit_candidate_public_key.go @@ -3,15 +3,13 @@ package transaction import ( "encoding/hex" "fmt" - "math/big" - "strconv" - "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" + "math/big" ) type EditCandidatePublicKeyData struct { @@ -54,11 +52,7 @@ func (data EditCandidatePublicKeyData) Run(tx *Transaction, context state.Interf return Response{ Code: code.NewPublicKeyIsBad, Log: fmt.Sprintf("Current public key (%s) equals new public key (%s)", data.PubKey.String(), data.NewPubKey.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.NewPublicKeyIsBad)), - "public_key": data.PubKey.String(), - "new_public_key": data.NewPubKey.String(), - }), + Info: EncodeError(code.NewNewPublicKeyIsBad(data.PubKey.String(), data.NewPubKey.String())), } } @@ -88,10 +82,7 @@ func (data EditCandidatePublicKeyData) Run(tx *Transaction, context state.Interf return Response{ Code: code.PublicKeyInBlockList, Log: fmt.Sprintf("Public key (%s) exists in block list", data.NewPubKey.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.PublicKeyInBlockList)), - "new_public_key": data.NewPubKey.String(), - }), + Info: EncodeError(code.NewCandidateExists(data.NewPubKey.String())), } } diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index 58db52eeb..544bc5e4b 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -88,9 +88,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.TooLongNonce, Log: "Nonce is too big. Should be up to 16 bytes.", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.TooLongNonce)), - }), + Info: EncodeError(code.NewTooLongNonce(strconv.Itoa(len(decodedCheck.Nonce)), "16")), } } diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 947dbd62c..a283a845d 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -3,9 +3,6 @@ package transaction import ( "encoding/hex" "fmt" - "math/big" - "strconv" - "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" @@ -13,6 +10,7 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/MinterTeam/minter-go-node/hexutil" "github.com/tendermint/tendermint/libs/kv" + "math/big" ) const unbondPeriod = 518400 @@ -40,19 +38,14 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R } } - errorInfo := map[string]string{ - "pub_key": data.PubKey.String(), - } if !context.Candidates().Exists(data.PubKey) { - errorInfo["code"] = strconv.Itoa(int(code.CandidateNotFound)) return &Response{ Code: code.CandidateNotFound, Log: fmt.Sprintf("Candidate with such public key not found"), - Info: EncodeError(errorInfo), + Info: EncodeError(code.NewCandidateNotFound(data.PubKey.String())), } } - errorInfo["unbound_value"] = data.Value.String() sender, _ := tx.Sender() if waitlist := context.WaitList().Get(sender, data.PubKey, data.Coin); waitlist != nil { @@ -60,33 +53,28 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R if value.Sign() < 1 { return nil } - errorInfo["waitlist_value"] = waitlist.Value.String() - errorInfo["code"] = strconv.Itoa(int(code.InsufficientWaitList)) return &Response{ Code: code.InsufficientWaitList, Log: fmt.Sprintf("Insufficient amount at waitlist for sender account"), - Info: EncodeError(errorInfo), + Info: EncodeError(code.NewInsufficientWaitList(waitlist.Value.String(), data.Value.String())), } } stake := context.Candidates().GetStakeValueOfAddress(data.PubKey, sender, data.Coin) if stake == nil { - errorInfo["code"] = strconv.Itoa(int(code.StakeNotFound)) return &Response{ Code: code.StakeNotFound, Log: fmt.Sprintf("Stake of current user not found"), - Info: EncodeError(errorInfo), + Info: EncodeError(EncodeError(code.NewStakeNotFound(data.PubKey.String(), sender.String(), data.Coin.String(), context.Coins().GetCoin(data.Coin).GetFullSymbol()))), } } if stake.Cmp(data.Value) < 0 { - errorInfo["stake_value"] = stake.String() - errorInfo["code"] = strconv.Itoa(int(code.InsufficientStake)) return &Response{ Code: code.InsufficientStake, Log: fmt.Sprintf("Insufficient stake for sender account"), - Info: EncodeError(errorInfo), + Info: EncodeError(code.NewInsufficientStake(data.PubKey.String(), sender.String(), data.Coin.String(), context.Coins().GetCoin(data.Coin).GetFullSymbol(), stake.String(), data.Value.String())), } } From 026542abb0171ce24d66707e62259f7f942a2b05 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 15 Sep 2020 16:46:54 +0300 Subject: [PATCH 263/426] errors models --- api/v2/service/estimate_coin_buy.go | 9 +- api/v2/service/estimate_coin_sell.go | 9 +- api/v2/service/estimate_coin_sell_all.go | 9 +- core/code/code.go | 302 ++++++++++++++++-- core/transaction/buy_coin.go | 59 ++-- core/transaction/create_coin.go | 27 +- core/transaction/create_multisig.go | 32 +- core/transaction/declare_candidacy.go | 16 +- core/transaction/delegate.go | 20 +- core/transaction/edit_candidate.go | 13 +- core/transaction/edit_candidate_public_key.go | 2 +- core/transaction/edit_coin_owner.go | 9 +- core/transaction/edit_multisig_owners.go | 37 +-- core/transaction/executor.go | 30 +- core/transaction/recreate_coin.go | 25 +- core/transaction/redeem_check.go | 22 +- core/transaction/sell_all_coin.go | 53 +-- core/transaction/sell_coin.go | 57 ++-- core/transaction/set_halt_block.go | 10 +- core/transaction/switch_candidate_status.go | 13 +- 20 files changed, 412 insertions(+), 342 deletions(-) diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index ef95a0a41..dd7cf1813 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -53,13 +53,8 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe } if coinToSell == coinToBuy { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), transaction.EncodeError(map[string]string{ - "code": "400", - "coin_id_to_sell": coinToSell.String(), - "coin_to_sell": cState.Coins().GetCoin(coinToSell).Symbol().String(), - "coin_id_to_buy": coinToBuy.String(), - "coin_to_buy": cState.Coins().GetCoin(coinToBuy).Symbol().String(), - })) + return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), + transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).Symbol().String(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).Symbol().String()))) } commissionInBaseCoin := big.NewInt(commissions.ConvertTx) diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index 41c8cd6c2..bf4d34556 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -53,13 +53,8 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell } if coinToSell == coinToBuy { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), transaction.EncodeError(map[string]string{ - "code": "400", - "coin_id_to_sell": coinToSell.String(), - "coin_to_sell": cState.Coins().GetCoin(coinToSell).Symbol().String(), - "coin_id_to_buy": coinToBuy.String(), - "coin_to_buy": cState.Coins().GetCoin(coinToBuy).Symbol().String(), - })) + return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), + transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).Symbol().String(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).Symbol().String()))) } commissionInBaseCoin := big.NewInt(commissions.ConvertTx) diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index 443bec7b7..41b352afb 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -64,13 +64,8 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS } if coinToSell == coinToBuy { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), transaction.EncodeError(map[string]string{ - "code": "400", - "coin_id_to_sell": coinToSell.String(), - "coin_to_sell": cState.Coins().GetCoin(coinToSell).Symbol().String(), - "coin_id_to_buy": coinToBuy.String(), - "coin_to_buy": cState.Coins().GetCoin(coinToBuy).Symbol().String(), - })) + return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), + transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).Symbol().String(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).Symbol().String()))) } commissionInBaseCoin := big.NewInt(commissions.ConvertTx) diff --git a/core/code/code.go b/core/code/code.go index a0ca9e84a..6cf8f0a09 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -62,12 +62,15 @@ const ( TooLongNonce uint32 = 506 // multisig - IncorrectWeights uint32 = 601 - MultisigExists uint32 = 602 - MultisigNotExists uint32 = 603 - IncorrectMultiSignature uint32 = 604 - TooLargeOwnersList uint32 = 605 - DuplicatedAddresses uint32 = 606 + IncorrectWeights uint32 = 601 + MultisigExists uint32 = 602 + MultisigNotExists uint32 = 603 + IncorrectMultiSignature uint32 = 604 + TooLargeOwnersList uint32 = 605 + DuplicatedAddresses uint32 = 606 + DifferentCountAddressesAndWeights uint32 = 607 + IncorrectTotalWeights uint32 = 608 + NotEnoughMultisigVotes uint32 = 609 ) type wrongNonce struct { @@ -90,6 +93,18 @@ func NewCoinNotExists(coinSymbol string, coinId string) *coinNotExists { return &coinNotExists{Code: strconv.Itoa(int(CoinNotExists)), CoinSymbol: coinSymbol, CoinId: coinId} } +type wrongGasCoin struct { + Code string `json:"code,omitempty"` + TxGasCoinSymbol string `json:"tx_coin_symbol,omitempty"` + TxGasCoinId string `json:"tx_coin_id,omitempty"` + CheckGasCoinSymbol string `json:"check_coin_symbol,omitempty"` + CheckGasCoinId string `json:"check_coin_id,omitempty"` +} + +func NewWrongGasCoin(txCoinSymbol string, txCoinId string, checkGasCoinSymbol, checkGasCoinId string) *wrongGasCoin { + return &wrongGasCoin{Code: strconv.Itoa(int(WrongGasCoin)), TxGasCoinSymbol: txCoinSymbol, TxGasCoinId: txCoinId, CheckGasCoinId: checkGasCoinId, CheckGasCoinSymbol: checkGasCoinSymbol} +} + type coinReserveNotSufficient struct { Code string `json:"code,omitempty"` CoinSymbol string `json:"coin_symbol,omitempty"` @@ -178,12 +193,13 @@ func NewCoinSupplyOverflow(delta string, coinSupply string, currentSupply string } type txFromSenderAlreadyInMempool struct { - Code string `json:"code,omitempty"` - Sender string `json:"sender,omitempty"` + Code string `json:"code,omitempty"` + Sender string `json:"sender,omitempty"` + BlockHeight string `json:"block_height,omitempty"` } -func NewTxFromSenderAlreadyInMempool(sender string, itoa string) *txFromSenderAlreadyInMempool { - return &txFromSenderAlreadyInMempool{Code: strconv.Itoa(int(TxFromSenderAlreadyInMempool)), Sender: sender} +func NewTxFromSenderAlreadyInMempool(sender string, block string) *txFromSenderAlreadyInMempool { + return &txFromSenderAlreadyInMempool{Code: strconv.Itoa(int(TxFromSenderAlreadyInMempool)), Sender: sender, BlockHeight: block} } type tooLowGasPrice struct { @@ -250,23 +266,14 @@ func NewInvalidCoinName(maxBytes string, gotBytes string) *invalidCoinName { return &invalidCoinName{Code: strconv.Itoa(int(InvalidCoinName)), MaxBytes: maxBytes, GotBytes: gotBytes} } -// todo -type wrongCoinSupply struct { - Code string `json:"code,omitempty"` - MaxBytes string `json:"max_bytes,omitempty"` - GotBytes string `json:"got_bytes,omitempty"` -} - -func NewWrongCoinSupply(maxBytes string, gotBytes string) *wrongCoinSupply { - return &wrongCoinSupply{Code: strconv.Itoa(int(WrongCoinSupply)), MaxBytes: maxBytes, GotBytes: gotBytes} -} - type tooHighGasPrice struct { - Code string `json:"code,omitempty"` + Code string `json:"code,omitempty"` + MaxCheckGasPrice string `json:"max_check_gas_price,omitempty"` + CurrentGasPrice string `json:"current_gas_price,omitempty"` } -func NewTooHighGasPrice() *tooHighGasPrice { - return &tooHighGasPrice{Code: strconv.Itoa(int(TooHighGasPrice))} +func NewTooHighGasPrice(maxCheckGasPrice, currentGasPrice string) *tooHighGasPrice { + return &tooHighGasPrice{Code: strconv.Itoa(int(TooHighGasPrice)), MaxCheckGasPrice: maxCheckGasPrice, CurrentGasPrice: currentGasPrice} } type candidateExists struct { @@ -313,7 +320,7 @@ type insufficientWaitList struct { } func NewInsufficientWaitList(waitlistValue, neededValue string) *insufficientWaitList { - return &insufficientWaitList{Code: strconv.Itoa(int(InsufficientWaitList)), WaitlistValue: waitlistValue} + return &insufficientWaitList{Code: strconv.Itoa(int(InsufficientWaitList)), WaitlistValue: waitlistValue, NeededValue: neededValue} } type stakeNotFound struct { @@ -351,3 +358,248 @@ type tooLongNonce struct { func NewTooLongNonce(nonceBytes string, maxNonceBytes string) *tooLongNonce { return &tooLongNonce{Code: strconv.Itoa(int(TooLongNonce)), NonceBytes: nonceBytes, MaxNonceBytes: maxNonceBytes} } + +type tooLargeOwnersList struct { + Code string `json:"code,omitempty"` + CountOwners string `json:"count_owners,omitempty"` + MaxCountOwners string `json:"max_count_owners,omitempty"` +} + +func NewTooLargeOwnersList(countOwners string, maxCountOwners string) *tooLargeOwnersList { + return &tooLargeOwnersList{Code: strconv.Itoa(int(TooLargeOwnersList)), CountOwners: countOwners, MaxCountOwners: maxCountOwners} +} + +type incorrectWeights struct { + Code string `json:"code,omitempty"` + Address string `json:"address,omitempty"` + Weight string `json:"weight,omitempty"` + MaxWeight string `json:"max_weight,omitempty"` +} + +func NewIncorrectWeights(address string, weight string, maxWeight string) *incorrectWeights { + return &incorrectWeights{Code: strconv.Itoa(int(IncorrectWeights)), Address: address, Weight: weight, MaxWeight: maxWeight} +} + +type incorrectTotalWeights struct { + Code string `json:"code,omitempty"` + TotalWeights string `json:"total_weights,omitempty"` + Threshold string `json:"threshold,omitempty"` +} + +func NewIncorrectTotalWeights(totalWeight, threshold string) *incorrectTotalWeights { + return &incorrectTotalWeights{Code: strconv.Itoa(int(IncorrectTotalWeights)), Threshold: threshold, TotalWeights: totalWeight} +} + +type differentCountAddressesAndWeights struct { + Code string `json:"code,omitempty"` + CountAddresses string `json:"count_addresses,omitempty"` + CountWeights string `json:"count_weights,omitempty"` +} + +func NewDifferentCountAddressesAndWeights(countAddresses string, countWeights string) *differentCountAddressesAndWeights { + return &differentCountAddressesAndWeights{Code: strconv.Itoa(int(DifferentCountAddressesAndWeights)), CountAddresses: countAddresses, CountWeights: countWeights} +} + +type minimumValueToBuyReached struct { + Code string `json:"code,omitempty"` + MinimumValueToBuy string `json:"minimum_value_to_buy,omitempty"` + WillGetValue string `json:"will_get_value,omitempty"` + CoinSymbol string `json:"coin_symbol,omitempty"` + CoinId string `json:"coin_id,omitempty"` +} + +func NewMinimumValueToBuyReached(minimumValueToBuy string, willGetValue string, coinSymbol string, coinId string) *minimumValueToBuyReached { + return &minimumValueToBuyReached{Code: strconv.Itoa(int(MinimumValueToBuyReached)), MinimumValueToBuy: minimumValueToBuy, WillGetValue: willGetValue, CoinSymbol: coinSymbol, CoinId: coinId} +} + +type maximumValueToSellReached struct { + Code string `json:"code,omitempty"` + MaximumValueToSell string `json:"maximum_value_to_sell,omitempty"` + NeededSpendValue string `json:"needed_spend_value,omitempty"` + CoinSymbol string `json:"coin_symbol,omitempty"` + CoinId string `json:"coin_id,omitempty"` +} + +func NewMaximumValueToSellReached(maximumValueToSell string, neededSpendValue string, coinSymbol string, coinId string) *maximumValueToSellReached { + return &maximumValueToSellReached{Code: strconv.Itoa(int(MaximumValueToSellReached)), MaximumValueToSell: maximumValueToSell, NeededSpendValue: neededSpendValue, CoinSymbol: coinSymbol, CoinId: coinId} +} + +type duplicatedAddresses struct { + Code string `json:"code,omitempty"` + Address string `json:"address,omitempty"` +} + +func NewDuplicatedAddresses(address string) *duplicatedAddresses { + return &duplicatedAddresses{Code: strconv.Itoa(int(DuplicatedAddresses)), Address: address} +} + +type checkInvalidLock struct { + Code string `json:"code,omitempty"` +} + +func NewCheckInvalidLock() *checkInvalidLock { + return &checkInvalidLock{Code: strconv.Itoa(int(CheckInvalidLock))} +} + +type crossConvert struct { + Code string `json:"code,omitempty"` + CoinIdToSell string `json:"coin_id_to_sell,omitempty"` + CoinToSell string `json:"coin_to_sell,omitempty"` + CoinIdToBuy string `json:"coin_id_to_buy,omitempty"` + CoinToBuy string `json:"coin_to_buy,omitempty"` +} + +func NewCrossConvert(coinIdToSell string, coinToSell string, coinIdToBuy string, coinToBuy string) *crossConvert { + return &crossConvert{Code: strconv.Itoa(int(CrossConvert)), CoinIdToSell: coinIdToSell, CoinToSell: coinToSell, CoinIdToBuy: coinIdToBuy, CoinToBuy: coinToBuy} +} + +type isNotOwnerOfCoin struct { + Code string `json:"code,omitempty"` + CoinSymbol string `json:"coin_symbol,omitempty"` + Owner *string `json:"owner"` +} + +func NewIsNotOwnerOfCoin(coinSymbol string, owner *string) *isNotOwnerOfCoin { + var own *string + if owner != nil { + own = owner + } + return &isNotOwnerOfCoin{Code: strconv.Itoa(int(IsNotOwnerOfCoin)), CoinSymbol: coinSymbol, Owner: own} +} + +type isNotOwnerOfCandidate struct { + Code string `json:"code,omitempty"` + Sender string `json:"sender,omitempty"` + PublicKey string `json:"public_key,omitempty"` + Owner string `json:"owner,omitempty"` + Control string `json:"control,omitempty"` +} + +func NewIsNotOwnerOfCandidate(sender, pubKey string, owner, control string) *isNotOwnerOfCandidate { + return &isNotOwnerOfCandidate{Code: strconv.Itoa(int(IsNotOwnerOfCandidate)), PublicKey: pubKey, Owner: owner, Control: control, Sender: sender} +} + +type checkExpired struct { + Code string `json:"code,omitempty"` + DueBlock string `json:"due_block,omitempty"` + CurrentBlock string `json:"current_block,omitempty"` +} + +func MewCheckExpired(dueBlock string, currentBlock string) *checkExpired { + return &checkExpired{Code: strconv.Itoa(int(CheckExpired)), DueBlock: dueBlock, CurrentBlock: currentBlock} +} + +type checkUsed struct { + Code string `json:"code,omitempty"` +} + +func NewCheckUsed() *checkUsed { + return &checkUsed{Code: strconv.Itoa(int(CheckUsed))} +} + +type notEnoughMultisigVotes struct { + Code string `json:"code,omitempty"` + NeededVotes string `json:"needed_votes,omitempty"` + GotVotes string `json:"got_votes,omitempty"` +} + +func NewNotEnoughMultisigVotes(neededVotes, gotVotes string) *notEnoughMultisigVotes { + return ¬EnoughMultisigVotes{Code: strconv.Itoa(int(NotEnoughMultisigVotes)), NeededVotes: neededVotes, GotVotes: gotVotes} +} + +type incorrectMultiSignature struct { + Code string `json:"code,omitempty"` +} + +func NewIncorrectMultiSignature() *incorrectMultiSignature { + return &incorrectMultiSignature{Code: strconv.Itoa(int(IncorrectMultiSignature))} +} + +type wrongCrr struct { + Code string `json:"code,omitempty"` + MaxCrr string `json:"max_crr,omitempty"` + MinCrr string `json:"min_crr,omitempty"` + GotCrr string `json:"got_crr,omitempty"` +} + +func NewWrongCrr(min string, max string, got string) *wrongCrr { + return &wrongCrr{Code: strconv.Itoa(int(WrongCrr)), MinCrr: min, MaxCrr: max, GotCrr: got} +} + +type stakeShouldBePositive struct { + Code string `json:"code,omitempty"` + Stake string `json:"stake,omitempty"` +} + +func NewStakeShouldBePositive(stake string) *stakeShouldBePositive { + return &stakeShouldBePositive{Code: strconv.Itoa(int(StakeShouldBePositive)), Stake: stake} +} + +type wrongHaltHeight struct { + Code string `json:"code,omitempty"` + Height string `json:"height,omitempty"` +} + +func NewWrongHaltHeight(height string) *wrongHaltHeight { + return &wrongHaltHeight{Code: strconv.Itoa(int(WrongHaltHeight)), Height: height} +} + +type tooLowStake struct { + Code string `json:"code,omitempty"` + Sender string `json:"sender,omitempty"` + PublicKey string `json:"public_key,omitempty"` + Value string `json:"value,omitempty"` + CoinSymbol string `json:"coin_symbol,omitempty"` + CoinId string `json:"coin_id,omitempty"` +} + +func NewTooLowStake(sender string, pubKey string, value string, coinId string, coinSymbol string) *tooLowStake { + return &tooLowStake{Code: strconv.Itoa(int(TooLowStake)), Sender: sender, PublicKey: pubKey, Value: value, CoinId: coinId, CoinSymbol: coinSymbol} +} + +type wrongCommission struct { + Code string `json:"code,omitempty"` + GotCommission string `json:"got_commission,omitempty"` + MinCommission string `json:"min_commission,omitempty"` + MaxCommission string `json:"max_commission,omitempty"` +} + +func NewWrongCommission(got string, min string, max string) *wrongCommission { + return &wrongCommission{Code: strconv.Itoa(int(WrongCommission)), MaxCommission: max, MinCommission: min, GotCommission: got} +} + +type multisigNotExists struct { + Code string `json:"code,omitempty"` + Address string `json:"address,omitempty"` +} + +func NewMultisigNotExists(address string) *multisigNotExists { + return &multisigNotExists{Code: strconv.Itoa(int(MultisigNotExists)), Address: address} +} + +type multisigExists struct { + Code string `json:"code,omitempty"` + Address string `json:"address,omitempty"` +} + +func NewMultisigExists(address string) *multisigExists { + return &multisigExists{Code: strconv.Itoa(int(MultisigExists)), Address: address} +} + +type wrongCoinSupply struct { + Code string `json:"code,omitempty"` + + MaxCoinSupply string `json:"max_coin_supply,omitempty"` + CurrentCoinSupply string `json:"current_coin_supply,omitempty"` + + MinInitialReserve string `json:"min_initial_reserve,omitempty"` + CurrentInitialReserve string `json:"current_initial_reserve,omitempty"` + + MinInitialAmount string `json:"min_initial_amount,omitempty"` + MaxInitialAmount string `json:"max_initial_amount,omitempty"` + CurrentInitialAmount string `json:"current_initial_amount,omitempty"` +} + +func NewWrongCoinSupply(maxCoinSupply string, currentCoinSupply string, minInitialReserve string, currentInitialReserve string, minInitialAmount string, maxInitialAmount string, currentInitialAmount string) *wrongCoinSupply { + return &wrongCoinSupply{Code: strconv.Itoa(int(WrongCoinSupply)), MaxCoinSupply: maxCoinSupply, CurrentCoinSupply: currentCoinSupply, MinInitialReserve: minInitialReserve, CurrentInitialReserve: currentInitialReserve, MinInitialAmount: minInitialAmount, MaxInitialAmount: maxInitialAmount, CurrentInitialAmount: currentInitialAmount} +} diff --git a/core/transaction/buy_coin.go b/core/transaction/buy_coin.go index 152b38ae3..3156743b6 100644 --- a/core/transaction/buy_coin.go +++ b/core/transaction/buy_coin.go @@ -3,15 +3,13 @@ package transaction import ( "encoding/hex" "fmt" - "math/big" - "strconv" - "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" + "math/big" ) type BuyCoinData struct { @@ -59,13 +57,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( Log: fmt.Sprintf( "You wanted to sell maximum %s, but currently you need to spend %s to complete tx", data.MaximumValueToSell.String(), value.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.MaximumValueToSellReached)), - "coin_symbol": coin.GetFullSymbol(), - "coin_id": coin.ID().String(), - "maximum_value_to_sell": data.MaximumValueToSell.String(), - "needed_spend_value": value.String(), - }), + Info: EncodeError(code.NewMaximumValueToSellReached(data.MaximumValueToSell.String(), value.String(), coin.GetFullSymbol(), coin.ID().String())), } } @@ -130,13 +122,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( Log: fmt.Sprintf( "You wanted to sell maximum %s, but currently you need to spend %s to complete tx", data.MaximumValueToSell.String(), value.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.MaximumValueToSellReached)), - "coin_symbol": coin.GetFullSymbol(), - "coin_id": coin.ID().String(), - "maximum_value_to_sell": data.MaximumValueToSell.String(), - "needed_spend_value": value.String(), - }), + Info: EncodeError(code.NewMaximumValueToSellReached(data.MaximumValueToSell.String(), value.String(), coin.GetFullSymbol(), coin.ID().String())), } } @@ -215,13 +201,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( Code: code.MaximumValueToSellReached, Log: fmt.Sprintf("You wanted to sell maximum %s, but currently you need to spend %s to complete tx", data.MaximumValueToSell.String(), value.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.MaximumValueToSellReached)), - "coin_symbol": coinFrom.GetFullSymbol(), - "coin_id": coinFrom.ID().String(), - "maximum_value_to_sell": data.MaximumValueToSell.String(), - "needed_spend_value": value.String(), - }), + Info: EncodeError(code.NewMaximumValueToSellReached(data.MaximumValueToSell.String(), value.String(), coinFrom.GetFullSymbol(), coinFrom.ID().String())), } } @@ -266,13 +246,7 @@ func (data BuyCoinData) TotalSpend(tx *Transaction, context *state.CheckState) ( return nil, nil, nil, &Response{ Code: code.MaximumValueToSellReached, Log: fmt.Sprintf("You wanted to sell maximum %s, but currently you need to spend %s to complete tx", data.MaximumValueToSell.String(), totalValue.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.MaximumValueToSellReached)), - "coin_symbol": coinFrom.GetFullSymbol(), - "coin_id": coinFrom.ID().String(), - "maximum_value_to_sell": data.MaximumValueToSell.String(), - "needed_spend_value": value.String(), - }), + Info: EncodeError(code.NewMaximumValueToSellReached(data.MaximumValueToSell.String(), value.String(), coinFrom.GetFullSymbol(), coinFrom.ID().String())), } } } @@ -336,16 +310,6 @@ func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.CheckState) * } - if data.CoinToSell == data.CoinToBuy { - return &Response{ - Code: code.CrossConvert, - Log: fmt.Sprintf("\"From\" coin equals to \"to\" coin"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CrossConvert)), - }), - } - } - if !context.Coins().Exists(data.CoinToSell) { return &Response{ Code: code.CoinNotExists, @@ -362,6 +326,19 @@ func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.CheckState) * } } + if data.CoinToSell == data.CoinToBuy { + return &Response{ + Code: code.CrossConvert, + Log: fmt.Sprintf("\"From\" coin equals to \"to\" coin"), + Info: EncodeError(code.NewCrossConvert( + data.CoinToSell.String(), + context.Coins().GetCoin(data.CoinToSell).Symbol().String(), + data.CoinToBuy.String(), + context.Coins().GetCoin(data.CoinToBuy).Symbol().String()), + ), + } + } + return nil } diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index 34e58b028..cebfaebb2 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -71,43 +71,32 @@ func (data CreateCoinData) BasicCheck(tx *Transaction, context *state.CheckState return &Response{ Code: code.WrongCrr, Log: fmt.Sprintf("Constant Reserve Ratio should be between 10 and 100"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongCrr)), - })} + Info: EncodeError(code.NewWrongCrr("10", "100", strconv.Itoa(int(data.ConstantReserveRatio)))), + } } if data.MaxSupply.Cmp(maxCoinSupply) == 1 { return &Response{ Code: code.WrongCoinSupply, Log: fmt.Sprintf("Max coin supply should be less than %s", maxCoinSupply), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongCoinSupply)), - "max_coin_supply": maxCoinSupply.String(), - "current_coin_supply": data.MaxSupply.String(), - })} + Info: EncodeError(code.NewWrongCoinSupply(maxCoinSupply.String(), data.MaxSupply.String(), minCoinReserve.String(), data.InitialReserve.String(), minCoinSupply.String(), data.MaxSupply.String(), data.InitialAmount.String())), + } } if data.InitialAmount.Cmp(minCoinSupply) == -1 || data.InitialAmount.Cmp(data.MaxSupply) == 1 { return &Response{ Code: code.WrongCoinSupply, Log: fmt.Sprintf("Coin supply should be between %s and %s", minCoinSupply.String(), data.MaxSupply.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongCoinSupply)), - "min_initial_amount": minCoinSupply.String(), - "current_initial_amount": data.InitialAmount.String(), - "max_initial_amount": data.MaxSupply.String(), - })} + Info: EncodeError(code.NewWrongCoinSupply(maxCoinSupply.String(), data.MaxSupply.String(), minCoinReserve.String(), data.InitialReserve.String(), minCoinSupply.String(), data.MaxSupply.String(), data.InitialAmount.String())), + } } if data.InitialReserve.Cmp(minCoinReserve) == -1 { return &Response{ Code: code.WrongCoinSupply, Log: fmt.Sprintf("Coin reserve should be greater than or equal to %s", minCoinReserve.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongCoinSupply)), - "min_initial_reserve": minCoinReserve.String(), - "current_initial_reserve": data.InitialReserve.String(), - })} + Info: EncodeError(code.NewWrongCoinSupply(maxCoinSupply.String(), data.MaxSupply.String(), minCoinReserve.String(), data.InitialReserve.String(), minCoinSupply.String(), data.MaxSupply.String(), data.InitialAmount.String())), + } } return nil diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index 9515ef021..c35b2362d 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -27,31 +27,25 @@ func (data CreateMultisigData) BasicCheck(tx *Transaction, context *state.CheckS return &Response{ Code: code.TooLargeOwnersList, Log: "Owners list is limited to 32 items", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.TooLargeOwnersList)), - })} + Info: EncodeError(code.NewTooLargeOwnersList(strconv.Itoa(lenWeights), "32"))} } lenAddresses := len(data.Addresses) if lenAddresses != lenWeights { return &Response{ - Code: code.IncorrectWeights, - Log: fmt.Sprintf("Incorrect multisig weights"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.IncorrectWeights)), - "count_weights": fmt.Sprintf("%d", lenWeights), - "count_addresses": fmt.Sprintf("%d", lenAddresses), - }), + Code: code.DifferentCountAddressesAndWeights, + Log: fmt.Sprintf("Different count addresses and weights"), + Info: EncodeError(code.NewDifferentCountAddressesAndWeights(fmt.Sprintf("%d", lenAddresses), fmt.Sprintf("%d", lenWeights))), } } - for _, weight := range data.Weights { + for i, weight := range data.Weights { if weight > 1023 { return &Response{ Code: code.IncorrectWeights, - Log: "Incorrect multisig weights", Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.IncorrectWeights)), - })} + Log: "Incorrect multisig weights", + Info: EncodeError(code.NewIncorrectWeights(data.Addresses[i].String(), strconv.Itoa(int(weight)), "1024")), + } } } @@ -61,9 +55,8 @@ func (data CreateMultisigData) BasicCheck(tx *Transaction, context *state.CheckS return &Response{ Code: code.DuplicatedAddresses, Log: "Duplicated multisig addresses", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.DuplicatedAddresses)), - })} + Info: EncodeError(code.NewDuplicatedAddresses(address.String())), + } } usedAddresses[address] = true @@ -122,10 +115,7 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew return Response{ Code: code.MultisigExists, Log: fmt.Sprintf("Multisig %s already exists", msigAddress.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.MultisigExists)), - "multisig_address": msigAddress.String(), - }), + Info: EncodeError(code.NewMultisigExists(msigAddress.String())), } } diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index 1a1939454..93e4b44c4 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -3,9 +3,6 @@ package transaction import ( "encoding/hex" "fmt" - "math/big" - "strconv" - "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" @@ -13,6 +10,7 @@ import ( "github.com/MinterTeam/minter-go-node/core/validators" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" + "math/big" ) const minCommission = 0 @@ -55,7 +53,7 @@ func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.Chec return &Response{ Code: code.PublicKeyInBlockList, Log: fmt.Sprintf("Candidate with such public key (%s) exists in block list", data.PubKey.String()), - Info: EncodeError(code.NewCandidateExists(data.PubKey.String())), + Info: EncodeError(code.NewPublicKeyInBlockList(data.PubKey.String())), } } @@ -63,10 +61,7 @@ func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.Chec return &Response{ Code: code.WrongCommission, Log: fmt.Sprintf("Commission should be between 0 and 100"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongCommission)), - "got_commission": fmt.Sprintf("%d", data.Commission), - }), + Info: EncodeError(code.NewWrongCommission(fmt.Sprintf("%d", data.Commission), "0", "100")), } } @@ -102,9 +97,8 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r return Response{ Code: code.TooLowStake, Log: fmt.Sprintf("Given stake is too low"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.TooLowStake)), - })} + Info: EncodeError(code.NewTooLowStake(sender.String(), data.PubKey.String(), data.Stake.String(), data.Coin.String(), checkState.Coins().GetCoin(data.Coin).GetFullSymbol())), + } } commissionInBaseCoin := big.NewInt(0).Mul(big.NewInt(int64(tx.GasPrice)), big.NewInt(tx.Gas())) diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index 6f42e7d04..ba0e6f93b 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -3,9 +3,6 @@ package transaction import ( "encoding/hex" "fmt" - "math/big" - "strconv" - "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" @@ -13,6 +10,7 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/MinterTeam/minter-go-node/hexutil" "github.com/tendermint/tendermint/libs/kv" + "math/big" ) type DelegateData struct { @@ -50,19 +48,15 @@ func (data DelegateData) BasicCheck(tx *Transaction, context *state.CheckState) return &Response{ Code: code.StakeShouldBePositive, Log: fmt.Sprintf("Stake should be positive"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.StakeShouldBePositive)), - })} + Info: EncodeError(code.NewStakeShouldBePositive(data.Value.String())), + } } if !context.Candidates().Exists(data.PubKey) { return &Response{ Code: code.CandidateNotFound, Log: fmt.Sprintf("Candidate with such public key not found"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CandidateNotFound)), - "pub_key": data.PubKey.String(), - }), + Info: EncodeError(code.NewCandidateNotFound(data.PubKey.String())), } } @@ -71,10 +65,8 @@ func (data DelegateData) BasicCheck(tx *Transaction, context *state.CheckState) return &Response{ Code: code.TooLowStake, Log: fmt.Sprintf("Stake is too low"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.TooLowStake)), - "pub_key": data.PubKey.String(), - })} + Info: EncodeError(code.NewTooLowStake(sender.String(), data.PubKey.String(), data.Value.String(), data.Coin.String(), context.Coins().GetCoin(data.Coin).GetFullSymbol())), + } } return nil diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index efc8505b6..897f00c6a 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -3,15 +3,13 @@ package transaction import ( "encoding/hex" "fmt" - "math/big" - "strconv" - "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" + "math/big" ) type CandidateTx interface { @@ -107,10 +105,7 @@ func checkCandidateOwnership(data CandidateTx, tx *Transaction, context *state.C return &Response{ Code: code.CandidateNotFound, Log: fmt.Sprintf("Candidate with such public key (%s) not found", data.GetPubKey().String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CandidateNotFound)), - "public_key": data.GetPubKey().String(), - }), + Info: EncodeError(code.NewCandidateNotFound(data.GetPubKey().String())), } } @@ -120,9 +115,7 @@ func checkCandidateOwnership(data CandidateTx, tx *Transaction, context *state.C return &Response{ Code: code.IsNotOwnerOfCandidate, Log: fmt.Sprintf("Sender is not an owner of a candidate"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.IsNotOwnerOfCandidate)), - }), + Info: EncodeError(code.NewIsNotOwnerOfCandidate(sender.String(), data.GetPubKey().String(), owner.String(), "")), } } diff --git a/core/transaction/edit_candidate_public_key.go b/core/transaction/edit_candidate_public_key.go index 4ec8368ab..6a8b9ecfc 100644 --- a/core/transaction/edit_candidate_public_key.go +++ b/core/transaction/edit_candidate_public_key.go @@ -82,7 +82,7 @@ func (data EditCandidatePublicKeyData) Run(tx *Transaction, context state.Interf return Response{ Code: code.PublicKeyInBlockList, Log: fmt.Sprintf("Public key (%s) exists in block list", data.NewPubKey.String()), - Info: EncodeError(code.NewCandidateExists(data.NewPubKey.String())), + Info: EncodeError(code.NewPublicKeyInBlockList(data.NewPubKey.String())), } } diff --git a/core/transaction/edit_coin_owner.go b/core/transaction/edit_coin_owner.go index 849acb550..79044e743 100644 --- a/core/transaction/edit_coin_owner.go +++ b/core/transaction/edit_coin_owner.go @@ -3,15 +3,13 @@ package transaction import ( "encoding/hex" "fmt" - "math/big" - "strconv" - "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" + "math/big" ) type EditCoinOwnerData struct { @@ -32,12 +30,11 @@ func (data EditCoinOwnerData) BasicCheck(tx *Transaction, context *state.CheckSt } if info.OwnerAddress() == nil || info.OwnerAddress().Compare(sender) != 0 { + owner := info.OwnerAddress().String() return &Response{ Code: code.IsNotOwnerOfCoin, Log: "Sender is not owner of coin", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.IsNotOwnerOfCoin)), - }), + Info: EncodeError(code.NewIsNotOwnerOfCoin(data.Symbol.String(), &owner)), } } diff --git a/core/transaction/edit_multisig_owners.go b/core/transaction/edit_multisig_owners.go index d87b20f1d..bd2416678 100644 --- a/core/transaction/edit_multisig_owners.go +++ b/core/transaction/edit_multisig_owners.go @@ -27,10 +27,7 @@ func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.Ch return &Response{ Code: code.MultisigNotExists, Log: "Multisig does not exists", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.MultisigNotExists)), - "multisig_address": sender.String(), - }), + Info: EncodeError(code.NewMultisigNotExists(sender.String())), } } @@ -39,33 +36,25 @@ func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.Ch return &Response{ Code: code.TooLargeOwnersList, Log: fmt.Sprintf("Owners list is limited to 32 items"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.TooLargeOwnersList)), - }), + Info: EncodeError(code.NewTooLargeOwnersList(strconv.Itoa(lenWeights), "32")), } } lenAddresses := len(data.Addresses) if lenAddresses != lenWeights { return &Response{ - Code: code.IncorrectWeights, - Log: fmt.Sprintf("Incorrect multisig weights"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.IncorrectWeights)), - "count_weights": fmt.Sprintf("%d", lenWeights), - "count_addresses": fmt.Sprintf("%d", lenAddresses), - }), + Code: code.DifferentCountAddressesAndWeights, + Log: fmt.Sprintf("Different count addresses and weights"), + Info: EncodeError(code.NewDifferentCountAddressesAndWeights(fmt.Sprintf("%d", lenAddresses), fmt.Sprintf("%d", lenWeights))), } } - for _, weight := range data.Weights { + for i, weight := range data.Weights { if weight > 1023 { return &Response{ Code: code.IncorrectWeights, Log: "Incorrect multisig weights", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.IncorrectWeights)), - }), + Info: EncodeError(code.NewIncorrectWeights(data.Addresses[i].String(), strconv.Itoa(int(weight)), "1024")), } } } @@ -76,9 +65,7 @@ func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.Ch return &Response{ Code: code.DuplicatedAddresses, Log: fmt.Sprintf("Duplicated multisig addresses"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.DuplicatedAddresses)), - }), + Info: EncodeError(code.NewDuplicatedAddresses(address.String())), } } @@ -91,13 +78,9 @@ func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.Ch } if data.Threshold > totalWeight { return &Response{ - Code: code.IncorrectWeights, + Code: code.IncorrectTotalWeights, Log: "Incorrect multisig weights", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.IncorrectWeights)), - "total_weight": fmt.Sprintf("%d", totalWeight), - "threshold": fmt.Sprintf("%d", data.Threshold), - }), + Info: EncodeError(code.NewIncorrectTotalWeights(fmt.Sprintf("%d", totalWeight), fmt.Sprintf("%d", data.Threshold))), } } diff --git a/core/transaction/executor.go b/core/transaction/executor.go index 1465629be..dc7e90c1d 100644 --- a/core/transaction/executor.go +++ b/core/transaction/executor.go @@ -138,10 +138,7 @@ func RunTx(context state.Interface, return Response{ Code: code.MultisigNotExists, Log: "Multisig does not exists", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.MultisigNotExists)), - "multisig_address": tx.multisig.Multisig.String(), - }), + Info: EncodeError(code.NewMultisigNotExists(tx.multisig.Multisig.String())), } } @@ -151,9 +148,7 @@ func RunTx(context state.Interface, return Response{ Code: code.IncorrectMultiSignature, Log: "Incorrect multi-signature", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.IncorrectMultiSignature)), - }), + Info: EncodeError(code.NewIncorrectMultiSignature()), } } @@ -163,24 +158,19 @@ func RunTx(context state.Interface, for _, sig := range tx.multisig.Signatures { signer, err := RecoverPlain(txHash, sig.R, sig.S, sig.V) - if err != nil { return Response{ Code: code.IncorrectMultiSignature, Log: "Incorrect multi-signature", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.IncorrectMultiSignature)), - }), + Info: EncodeError(code.NewIncorrectMultiSignature()), } } if usedAccounts[signer] { return Response{ - Code: code.IncorrectMultiSignature, - Log: "Incorrect multi-signature", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.IncorrectMultiSignature)), - }), + Code: code.DuplicatedAddresses, + Log: "Duplicated multisig addresses", + Info: EncodeError(code.NewDuplicatedAddresses(signer.String())), } } @@ -190,13 +180,9 @@ func RunTx(context state.Interface, if totalWeight < multisigData.Threshold { return Response{ - Code: code.IncorrectMultiSignature, + Code: code.NotEnoughMultisigVotes, Log: fmt.Sprintf("Not enough multisig votes. Needed %d, has %d", multisigData.Threshold, totalWeight), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.IncorrectMultiSignature)), - "needed_votes": fmt.Sprintf("%d", multisigData.Threshold), - "got_votes": fmt.Sprintf("%d", totalWeight), - }), + Info: EncodeError(code.NewNotEnoughMultisigVotes(fmt.Sprintf("%d", multisigData.Threshold), fmt.Sprintf("%d", totalWeight))), } } diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index ca951b41a..7b85f4afb 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -44,9 +44,7 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta return &Response{ Code: code.WrongCrr, Log: fmt.Sprintf("Constant Reserve Ratio should be between 10 and 100"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongCrr)), - }), + Info: EncodeError(code.NewWrongCrr("10", "100", strconv.Itoa(int(data.ConstantReserveRatio)))), } } @@ -54,9 +52,7 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta return &Response{ Code: code.WrongCoinSupply, Log: fmt.Sprintf("Coin supply should be between %s and %s", minCoinSupply.String(), data.MaxSupply.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongCoinSupply)), - }), + Info: EncodeError(code.NewWrongCoinSupply(maxCoinSupply.String(), data.MaxSupply.String(), minCoinReserve.String(), data.InitialReserve.String(), minCoinSupply.String(), data.MaxSupply.String(), data.InitialAmount.String())), } } @@ -64,9 +60,7 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta return &Response{ Code: code.WrongCoinSupply, Log: fmt.Sprintf("Max coin supply should be less than %s", maxCoinSupply), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongCoinSupply)), - }), + Info: EncodeError(code.NewWrongCoinSupply(maxCoinSupply.String(), data.MaxSupply.String(), minCoinReserve.String(), data.InitialReserve.String(), minCoinSupply.String(), data.MaxSupply.String(), data.InitialAmount.String())), } } @@ -74,9 +68,7 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta return &Response{ Code: code.WrongCoinSupply, Log: fmt.Sprintf("Coin reserve should be greater than or equal to %s", minCoinReserve.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongCoinSupply)), - }), + Info: EncodeError(code.NewWrongCoinSupply(maxCoinSupply.String(), data.MaxSupply.String(), minCoinReserve.String(), data.InitialReserve.String(), minCoinSupply.String(), data.MaxSupply.String(), data.InitialAmount.String())), } } @@ -93,12 +85,15 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta symbolInfo := context.Coins().GetSymbolInfo(coin.Symbol()) if symbolInfo == nil || symbolInfo.OwnerAddress() == nil || symbolInfo.OwnerAddress().Compare(sender) != 0 { + var owner *string + if symbolInfo != nil && symbolInfo.OwnerAddress() != nil { + own := symbolInfo.OwnerAddress().String() + owner = &own + } return &Response{ Code: code.IsNotOwnerOfCoin, Log: "Sender is not owner of coin", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.IsNotOwnerOfCoin)), - }), + Info: EncodeError(code.NewIsNotOwnerOfCoin(data.Symbol.String(), owner)), } } diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index 544bc5e4b..93e357bff 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -38,7 +38,7 @@ func (data RedeemCheckData) BasicCheck(tx *Transaction, context *state.CheckStat return &Response{ Code: code.TooHighGasPrice, Log: fmt.Sprintf("Gas price for check is limited to 1"), - Info: EncodeError(code.NewTooHighGasPrice()), + Info: EncodeError(code.NewTooHighGasPrice("1", strconv.Itoa(int(tx.GasPrice)))), } } @@ -122,10 +122,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.WrongGasCoin, Log: fmt.Sprintf("Gas coin for redeem check transaction can only be %s", decodedCheck.GasCoin), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongGasCoin)), - "coin": fmt.Sprintf("%s", decodedCheck.GasCoin), - }), + Info: EncodeError(code.NewWrongGasCoin(checkState.Coins().GetCoin(tx.GasCoin).GetFullSymbol(), tx.GasCoin.String(), checkState.Coins().GetCoin(decodedCheck.GasCoin).GetFullSymbol(), decodedCheck.GasCoin.String())), } } @@ -133,11 +130,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.CheckExpired, Log: fmt.Sprintf("Check expired"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CheckExpired)), - "due_block": fmt.Sprintf("%d", decodedCheck.DueBlock), - "current_block": fmt.Sprintf("%d", currentBlock), - }), + Info: EncodeError(code.MewCheckExpired(fmt.Sprintf("%d", decodedCheck.DueBlock), fmt.Sprintf("%d", currentBlock))), } } @@ -145,9 +138,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward return Response{ Code: code.CheckUsed, Log: fmt.Sprintf("Check already redeemed"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CheckUsed)), - }), + Info: EncodeError(code.NewCheckUsed()), } } @@ -181,9 +172,8 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward if !bytes.Equal(lockPublicKey, pub) { return Response{ Code: code.CheckInvalidLock, - Log: "Invalid proof", Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CheckInvalidLock)), - }), + Log: "Invalid proof", + Info: EncodeError(code.NewCheckInvalidLock()), } } diff --git a/core/transaction/sell_all_coin.go b/core/transaction/sell_all_coin.go index 6e506d325..693c145ff 100644 --- a/core/transaction/sell_all_coin.go +++ b/core/transaction/sell_all_coin.go @@ -3,15 +3,13 @@ package transaction import ( "encoding/hex" "fmt" - "math/big" - "strconv" - "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" + "math/big" ) type SellAllCoinData struct { @@ -44,13 +42,7 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat return nil, nil, nil, &Response{ Code: code.MinimumValueToBuyReached, Log: fmt.Sprintf("You wanted to get minimum %s, but currently you will get %s", data.MinimumValueToBuy.String(), value.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), - "minimum_value_to_buy": data.MinimumValueToBuy.String(), - "will_get_value": value.String(), - "coin_symbol": coin.GetFullSymbol(), - "coin_id": coin.ID().String(), - }), + Info: EncodeError(code.NewMinimumValueToBuyReached(data.MinimumValueToBuy.String(), value.String(), coin.GetFullSymbol(), coin.ID().String())), } } @@ -74,13 +66,7 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat return nil, nil, nil, &Response{ Code: code.MinimumValueToBuyReached, Log: fmt.Sprintf("You wanted to get minimum %s, but currently you will get %s", data.MinimumValueToBuy.String(), ret.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), - "minimum_value_to_buy": data.MinimumValueToBuy.String(), - "will_get_value": ret.String(), - "coin_symbol": coin.GetFullSymbol(), - "coin_id": coin.ID().String(), - }), + Info: EncodeError(code.NewMinimumValueToBuyReached(data.MinimumValueToBuy.String(), ret.String(), coin.GetFullSymbol(), coin.ID().String())), } } @@ -123,13 +109,7 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat return nil, nil, nil, &Response{ Code: code.MinimumValueToBuyReached, Log: fmt.Sprintf("You wanted to get minimum %s, but currently you will get %s", data.MinimumValueToBuy.String(), value.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), - "minimum_value_to_buy": data.MinimumValueToBuy.String(), - "will_get_value": value.String(), - "coin_symbol": coinTo.GetFullSymbol(), - "coin_id": coinTo.ID().String(), - }), + Info: EncodeError(code.NewMinimumValueToBuyReached(data.MinimumValueToBuy.String(), value.String(), coinTo.GetFullSymbol(), coinTo.ID().String())), } } @@ -151,18 +131,6 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat } func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { - if data.CoinToSell == data.CoinToBuy { - return &Response{ - Code: code.CrossConvert, - Log: fmt.Sprintf("\"From\" coin equals to \"to\" coin"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CrossConvert)), - "coin_to_sell": fmt.Sprintf("%s", data.CoinToSell), - "coin_to_buy": fmt.Sprintf("%s", data.CoinToBuy), - }), - } - } - if !context.Coins().Exists(data.CoinToSell) { return &Response{ Code: code.CoinNotExists, @@ -179,6 +147,19 @@ func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.CheckStat } } + if data.CoinToSell == data.CoinToBuy { + return &Response{ + Code: code.CrossConvert, + Log: fmt.Sprintf("\"From\" coin equals to \"to\" coin"), + Info: EncodeError(code.NewCrossConvert( + data.CoinToSell.String(), + context.Coins().GetCoin(data.CoinToSell).Symbol().String(), + data.CoinToBuy.String(), + context.Coins().GetCoin(data.CoinToBuy).Symbol().String()), + ), + } + } + return nil } diff --git a/core/transaction/sell_coin.go b/core/transaction/sell_coin.go index 403ca2716..de74482ff 100644 --- a/core/transaction/sell_coin.go +++ b/core/transaction/sell_coin.go @@ -3,15 +3,13 @@ package transaction import ( "encoding/hex" "fmt" - "math/big" - "strconv" - "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" + "math/big" ) type SellCoinData struct { @@ -38,13 +36,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) return nil, nil, nil, &Response{ Code: code.MinimumValueToBuyReached, Log: fmt.Sprintf("You wanted to get minimum %s, but currently you will get %s", data.MinimumValueToBuy.String(), value.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), - "minimum_value_to_buy": data.MinimumValueToBuy.String(), - "will_get_value": value.String(), - "coin_symbol": coin.GetFullSymbol(), - "coin_id": coin.ID().String(), - }), + Info: EncodeError(code.NewMinimumValueToBuyReached(data.MinimumValueToBuy.String(), value.String(), coin.GetFullSymbol(), coin.ID().String())), } } @@ -87,13 +79,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) return nil, nil, nil, &Response{ Code: code.MinimumValueToBuyReached, Log: fmt.Sprintf("You wanted to get minimum %s, but currently you will get %s", data.MinimumValueToBuy.String(), value.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), - "minimum_value_to_buy": data.MinimumValueToBuy.String(), - "will_get_value": value.String(), - "coin_symbol": coin.GetFullSymbol(), - "coin_id": coin.ID().String(), - }), + Info: EncodeError(code.NewMinimumValueToBuyReached(data.MinimumValueToBuy.String(), value.String(), coin.GetFullSymbol(), coin.ID().String())), } } @@ -195,13 +181,7 @@ func (data SellCoinData) TotalSpend(tx *Transaction, context *state.CheckState) return nil, nil, nil, &Response{ Code: code.MinimumValueToBuyReached, Log: fmt.Sprintf("You wanted to get minimum %s, but currently you will get %s", data.MinimumValueToBuy.String(), value.String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.MinimumValueToBuyReached)), - "minimum_value_to_buy": data.MinimumValueToBuy.String(), - "will_get_value": value.String(), - "coin_symbol": coinTo.GetFullSymbol(), - "coin_id": coinTo.ID().String(), - }), + Info: EncodeError(code.NewMinimumValueToBuyReached(data.MinimumValueToBuy.String(), value.String(), coinTo.GetFullSymbol(), coinTo.ID().String())), } } @@ -284,21 +264,7 @@ func (data SellCoinData) BasicCheck(tx *Transaction, context *state.CheckState) return &Response{ Code: code.DecodeError, Log: "Incorrect tx data", - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CrossConvert)), - }), - } - } - - if data.CoinToSell == data.CoinToBuy { - return &Response{ - Code: code.CrossConvert, - Log: fmt.Sprintf("\"From\" coin equals to \"to\" coin"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CrossConvert)), - "coin_to_sell": fmt.Sprintf("%s", data.CoinToSell), - "coin_to_buy": fmt.Sprintf("%s", data.CoinToBuy), - }), + Info: EncodeError(code.NewDecodeError()), } } @@ -318,6 +284,19 @@ func (data SellCoinData) BasicCheck(tx *Transaction, context *state.CheckState) } } + if data.CoinToSell == data.CoinToBuy { + return &Response{ + Code: code.CrossConvert, + Log: fmt.Sprintf("\"From\" coin equals to \"to\" coin"), + Info: EncodeError(code.NewCrossConvert( + data.CoinToSell.String(), + context.Coins().GetCoin(data.CoinToSell).Symbol().String(), + data.CoinToBuy.String(), + context.Coins().GetCoin(data.CoinToBuy).Symbol().String()), + ), + } + } + return nil } diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index b7d5cdb47..8f7b8f484 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -29,10 +29,7 @@ func (data SetHaltBlockData) BasicCheck(tx *Transaction, context *state.CheckSta return &Response{ Code: code.CandidateNotFound, Log: fmt.Sprintf("Candidate with such public key not found"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CandidateNotFound)), - "pub_key": data.PubKey.String(), - }), + Info: EncodeError(code.NewCandidateNotFound(data.PubKey.String())), } } @@ -66,10 +63,7 @@ func (data SetHaltBlockData) Run(tx *Transaction, context state.Interface, rewar return Response{ Code: code.WrongHaltHeight, Log: fmt.Sprintf("Halt height should be equal or bigger than current: %d", currentBlock), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.WrongHaltHeight)), - "height": strconv.FormatUint(data.Height, 10), - }), + Info: EncodeError(code.NewWrongHaltHeight(strconv.FormatUint(data.Height, 10))), } } diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index fac13d23a..7ea8793c6 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -3,15 +3,13 @@ package transaction import ( "encoding/hex" "fmt" - "math/big" - "strconv" - "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/commissions" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" "github.com/tendermint/tendermint/libs/kv" + "math/big" ) type SetCandidateOnData struct { @@ -181,10 +179,7 @@ func checkCandidateControl(data CandidateTx, tx *Transaction, context *state.Che return &Response{ Code: code.CandidateNotFound, Log: fmt.Sprintf("Candidate with such public key (%s) not found", data.GetPubKey().String()), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.CandidateNotFound)), - "public_key": data.GetPubKey().String(), - }), + Info: EncodeError(code.NewCandidateNotFound(data.GetPubKey().String())), } } @@ -197,9 +192,7 @@ func checkCandidateControl(data CandidateTx, tx *Transaction, context *state.Che return &Response{ Code: code.IsNotOwnerOfCandidate, Log: fmt.Sprintf("Sender is not an owner of a candidate"), - Info: EncodeError(map[string]string{ - "code": strconv.Itoa(int(code.IsNotOwnerOfCandidate)), - }), + Info: EncodeError(code.NewIsNotOwnerOfCandidate(sender.String(), data.GetPubKey().String(), owner.String(), control.String())), } } From 285b9539f8c776f74748c8a9baa00f7e93cb4a93 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 15 Sep 2020 17:01:59 +0300 Subject: [PATCH 264/426] update tests --- core/state/candidates/candidate_test.go | 2 +- core/transaction/create_multisig_test.go | 4 ++-- core/transaction/edit_multisig_owners_test.go | 8 ++++---- core/transaction/executor_test.go | 8 ++++---- core/transaction/send_test.go | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/core/state/candidates/candidate_test.go b/core/state/candidates/candidate_test.go index 4fe446e0b..52ad09d2e 100644 --- a/core/state/candidates/candidate_test.go +++ b/core/state/candidates/candidate_test.go @@ -137,7 +137,7 @@ func TestCandidates_Commit_changePubKeyAndCheckBlockList(t *testing.T) { t.Fatalf("version %d", version) } - if fmt.Sprintf("%X", hash) != "C0DC396CF17399CF3E05EAFFD29D94A99698633C9160D46C469D5F6575DC66E0" { + if fmt.Sprintf("%X", hash) != "BB335E1AA631D9540C2CB0AC9C959B556C366B79D39B828B07106CF2DACE5A2D" { t.Fatalf("hash %X", hash) } diff --git a/core/transaction/create_multisig_test.go b/core/transaction/create_multisig_test.go index 7f1ce78c0..4cbe8380a 100644 --- a/core/transaction/create_multisig_test.go +++ b/core/transaction/create_multisig_test.go @@ -404,8 +404,8 @@ func TestCreateMultisigOwnersTxIncorrectWeights(t *testing.T) { } response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) - if response.Code != code.IncorrectWeights { - t.Fatalf("Response code is not %d. Error %s", code.IncorrectWeights, response.Log) + if response.Code != code.DifferentCountAddressesAndWeights { + t.Fatalf("Response code is not %d. Error %s", code.DifferentCountAddressesAndWeights, response.Log) } data.Weights = []uint{1, 2, 1024} diff --git a/core/transaction/edit_multisig_owners_test.go b/core/transaction/edit_multisig_owners_test.go index 8d549c7ac..6c1f33673 100644 --- a/core/transaction/edit_multisig_owners_test.go +++ b/core/transaction/edit_multisig_owners_test.go @@ -249,8 +249,8 @@ func TestEditMultisigOwnersTxIncorrectWeights(t *testing.T) { } response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) - if response.Code != code.IncorrectWeights { - t.Fatalf("Response code is not %d. Error %s", code.IncorrectWeights, response.Log) + if response.Code != code.DifferentCountAddressesAndWeights { + t.Fatalf("Response code is not %d. Error %s", code.DifferentCountAddressesAndWeights, response.Log) } data.Weights = []uint{1, 2, 1024} @@ -292,8 +292,8 @@ func TestEditMultisigOwnersTxIncorrectWeights(t *testing.T) { } response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) - if response.Code != code.IncorrectWeights { - t.Fatalf("Response code is not %d. Error %s", code.IncorrectWeights, response.Log) + if response.Code != code.IncorrectTotalWeights { + t.Fatalf("Response code is not %d. Error %s", code.IncorrectTotalWeights, response.Log) } } diff --git a/core/transaction/executor_test.go b/core/transaction/executor_test.go index f77fa0129..798230f6d 100644 --- a/core/transaction/executor_test.go +++ b/core/transaction/executor_test.go @@ -312,8 +312,8 @@ func TestMultiSigDoubleSignTx(t *testing.T) { response := RunTx(cState, txBytes, big.NewInt(0), 0, &sync.Map{}, 0) - if response.Code != code.IncorrectMultiSignature { - t.Fatalf("Error code is not %d, got %d", code.IncorrectMultiSignature, response.Code) + if response.Code != code.DuplicatedAddresses { + t.Fatalf("Error code is not %d, got %d", code.DuplicatedAddresses, response.Code) } } @@ -407,8 +407,8 @@ func TestMultiSigNotEnoughTx(t *testing.T) { response := RunTx(cState, txBytes, big.NewInt(0), 0, &sync.Map{}, 0) - if response.Code != code.IncorrectMultiSignature { - t.Fatalf("Error code is not %d. Error: %d", code.IncorrectMultiSignature, response.Code) + if response.Code != code.NotEnoughMultisigVotes { + t.Fatalf("Error code is not %d. Error: %d", code.NotEnoughMultisigVotes, response.Code) } } diff --git a/core/transaction/send_test.go b/core/transaction/send_test.go index f4c090be1..1dee5da2c 100644 --- a/core/transaction/send_test.go +++ b/core/transaction/send_test.go @@ -192,8 +192,8 @@ func TestSendFailedMultisigTx(t *testing.T) { } response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) - if response.Code != code.IncorrectMultiSignature { - t.Fatalf("Response code is not %d. Gor: %d", code.IncorrectMultiSignature, response.Code) + if response.Code != code.NotEnoughMultisigVotes { + t.Fatalf("Response code is not %d. Gor: %d", code.NotEnoughMultisigVotes, response.Code) } targetBalance, _ := big.NewInt(0).SetString("1000000000000000000000000", 10) From e87c054cecd26b717571db9d981083d879e01363 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 15 Sep 2020 17:14:26 +0300 Subject: [PATCH 265/426] test --- core/state/candidates/candidate_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/core/state/candidates/candidate_test.go b/core/state/candidates/candidate_test.go index 52ad09d2e..55d99b5cc 100644 --- a/core/state/candidates/candidate_test.go +++ b/core/state/candidates/candidate_test.go @@ -144,6 +144,21 @@ func TestCandidates_Commit_changePubKeyAndCheckBlockList(t *testing.T) { if !candidates.IsBlockedPubKey([32]byte{4}) { t.Fatal("pub_key is not blocked") } + + candidates, err = NewCandidates(bus.NewBus(), mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.LoadCandidates() + candidate := candidates.GetCandidate([32]byte{5}) + if candidate == nil { + t.Fatal("candidate not found") + } + if candidates.PubKey(candidate.ID) != [32]byte{5} { + t.Fatal("candidate map ids and pubKeys invalid") + } + } func TestCandidates_AddToBlockPubKey(t *testing.T) { mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) From 05d3c2e4935c5e0f3c3695b9ded82093f0ae471d Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 16 Sep 2020 11:56:40 +0300 Subject: [PATCH 266/426] types tests --- core/types/bytes_test.go | 68 ++++- core/types/constants_test.go | 23 ++ core/types/size_test.go | 17 ++ core/types/types.go | 9 - core/types/types_test.go | 509 ++++++++++++++++++++++++++++++++++- 5 files changed, 595 insertions(+), 31 deletions(-) create mode 100644 core/types/constants_test.go diff --git a/core/types/bytes_test.go b/core/types/bytes_test.go index 4f4187875..dea1f0d28 100644 --- a/core/types/bytes_test.go +++ b/core/types/bytes_test.go @@ -19,41 +19,44 @@ package types import ( "bytes" "testing" - - checker "gopkg.in/check.v1" ) -type BytesSuite struct{} - -var _ = checker.Suite(&BytesSuite{}) - -func (s *BytesSuite) TestCopyBytes(c *checker.C) { +func TestCopyBytes(t *testing.T) { data1 := []byte{1, 2, 3, 4} exp1 := []byte{1, 2, 3, 4} res1 := CopyBytes(data1) - c.Assert(res1, checker.DeepEquals, exp1) + + if !bytes.Equal(res1, exp1) { + t.Error("Bytes are not the same") + } + + if CopyBytes(nil) != nil { + t.Error("Incorrect result of copy bytes") + } } -func (s *BytesSuite) TestLeftPadBytes(c *checker.C) { +func TestLeftPadBytes(t *testing.T) { val1 := []byte{1, 2, 3, 4} exp1 := []byte{0, 0, 0, 0, 1, 2, 3, 4} res1 := LeftPadBytes(val1, 8) res2 := LeftPadBytes(val1, 2) - c.Assert(res1, checker.DeepEquals, exp1) - c.Assert(res2, checker.DeepEquals, val1) + if !bytes.Equal(res1, exp1) || !bytes.Equal(res2, val1) { + t.Error("Bytes are not the same") + } } -func (s *BytesSuite) TestRightPadBytes(c *checker.C) { +func TestRightPadBytes(t *testing.T) { val := []byte{1, 2, 3, 4} exp := []byte{1, 2, 3, 4, 0, 0, 0, 0} resstd := RightPadBytes(val, 8) resshrt := RightPadBytes(val, 2) - c.Assert(resstd, checker.DeepEquals, exp) - c.Assert(resshrt, checker.DeepEquals, val) + if !bytes.Equal(resstd, exp) || !bytes.Equal(resshrt, val) { + t.Error("Bytes are not the same") + } } func TestFromHex(t *testing.T) { @@ -103,3 +106,40 @@ func TestNoPrefixShortHexOddLength(t *testing.T) { t.Errorf("Expected %x got %x", expected, result) } } + +func TestToHex(t *testing.T) { + b := []byte{1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + if ToHex(b, "Mx") != "Mx0102030405000000000000000000000000000000" { + t.Error("Incorrect hex representation") + } + + if ToHex(nil, "Mx") != "Mx0" { + t.Error("Incorrect hex representation") + } +} + +func TestBytes2Hex(t *testing.T) { + if Bytes2Hex([]byte{1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) != "0102030405000000000000000000000000000000" { + t.Error("Incorrect hex representation") + } +} + +func TestHex2BytesFixed(t *testing.T) { + b := []byte{1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + b2 := Hex2BytesFixed("0102030405000000000000000000000000000000", 20) + if !bytes.Equal(b2, b) { + t.Error("Incorrect hex representation") + } + + b = []byte{0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + b2 = Hex2BytesFixed("0102030405000000000000000000000000000000", 21) + if !bytes.Equal(b2, b) { + t.Error("Incorrect hex representation") + } + + b = []byte{2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + b2 = Hex2BytesFixed("0102030405000000000000000000000000000000", 19) + if !bytes.Equal(b2, b) { + t.Error("Incorrect hex representation") + } +} diff --git a/core/types/constants_test.go b/core/types/constants_test.go new file mode 100644 index 000000000..35ed70db4 --- /dev/null +++ b/core/types/constants_test.go @@ -0,0 +1,23 @@ +package types + +import ( + "testing" +) + +func TestGetBaseCoin(t *testing.T) { + CurrentChainID = ChainTestnet + if GetBaseCoin().Compare(coinTestnet) != 0 { + t.Error("Incorrect base coin") + } + + CurrentChainID = ChainMainnet + if GetBaseCoin().Compare(coinMainnet) != 0 { + t.Error("Incorrect base coin") + } +} + +func TestGetBaseCoinID(t *testing.T) { + if GetBaseCoinID() != BasecoinID { + t.Error("Incorrect base coin id") + } +} diff --git a/core/types/size_test.go b/core/types/size_test.go index cf2d72681..f4f031d64 100644 --- a/core/types/size_test.go +++ b/core/types/size_test.go @@ -36,3 +36,20 @@ func TestStorageSizeString(t *testing.T) { } } } + +func TestStorageSizeToTerminalString(t *testing.T) { + tests := []struct { + size StorageSize + str string + }{ + {2381273, "2.38mB"}, + {2192, "2.19kB"}, + {12, "12.00B"}, + } + + for _, test := range tests { + if test.size.TerminalString() != test.str { + t.Errorf("%f: got %q, want %q", float64(test.size), test.size.TerminalString(), test.str) + } + } +} diff --git a/core/types/types.go b/core/types/types.go index 12d7c0157..96870e610 100644 --- a/core/types/types.go +++ b/core/types/types.go @@ -42,15 +42,6 @@ func BytesToHash(b []byte) Hash { return h } -// StringToHash converts given string to Hash -func StringToHash(s string) Hash { return BytesToHash([]byte(s)) } - -// BigToHash converts given big.Int to Hash -func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) } - -// HexToHash converts given hex string to Hash -func HexToHash(s string) Hash { return BytesToHash(FromHex(s, "Mh")) } - // Str returns the string representation of the underlying hash func (h Hash) Str() string { return string(h[:]) } diff --git a/core/types/types_test.go b/core/types/types_test.go index 5a9c9156b..e04131729 100644 --- a/core/types/types_test.go +++ b/core/types/types_test.go @@ -19,6 +19,7 @@ package types import ( "bytes" "encoding/json" + "github.com/MinterTeam/minter-go-node/helpers" "github.com/tendermint/go-amino" "math/big" "strings" @@ -169,6 +170,10 @@ func TestAppState(t *testing.T) { Coin: GetBaseCoinID(), Value: big.NewInt(1).String(), }, + { + Coin: GetBaseCoinID() + 1, + Value: big.NewInt(1).String(), + }, }, Nonce: 1, MultisigData: &Multisig{ @@ -180,12 +185,13 @@ func TestAppState(t *testing.T) { }, Coins: []Coin{ { - ID: GetBaseCoinID(), - Name: "ASD", - Symbol: GetBaseCoin(), - Volume: big.NewInt(1).String(), - Crr: 1, - Reserve: big.NewInt(1).String(), + ID: GetBaseCoinID() + 1, + Name: "ASD", + Symbol: StrToCoinSymbol("TEST"), + Volume: big.NewInt(1).String(), + Crr: 1, + Reserve: helpers.BipToPip(big.NewInt(100000)).String(), + MaxSupply: helpers.BipToPip(big.NewInt(100000)).String(), }, }, FrozenFunds: []FrozenFund{ @@ -198,13 +204,18 @@ func TestAppState(t *testing.T) { }, }, UsedChecks: []UsedCheck{ - "123", + "00004601d10c33eda76bb16a54a0d8882a57ec34e964aa23e2b5d9aa10957fee", }, - MaxGas: 10, + MaxGas: 10, + TotalSlashed: big.NewInt(1e18).String(), } cdc := amino.NewCodec() + if err := appState.Verify(); err != nil { + t.Error(err) + } + b1, err := cdc.MarshalJSON(appState) if err != nil { panic(err) @@ -225,3 +236,485 @@ func TestAppState(t *testing.T) { t.Errorf("Bytes are not the same") } } + +func TestAppStateToInvalidState(t *testing.T) { + testAddr := HexToAddress("Mx5aaeb6053f3e94c9b9a09f33669435e7ef1beaed") + pubkey := Pubkey{1, 2, 3} + ba := NewBitArray(24) + ba.SetIndex(3, true) + + appState := AppState{} + if appState.Verify() == nil { + t.Error("State is not correct") + } + + appState = AppState{ + TotalSlashed: big.NewInt(1e18).String(), + } + if appState.Verify() == nil { + t.Error("State is not correct") + } + + appState = AppState{ + TotalSlashed: big.NewInt(1e18).String(), + Validators: []Validator{ + { + TotalBipStake: big.NewInt(1).String(), + PubKey: pubkey, + AccumReward: big.NewInt(1).String(), + AbsentTimes: ba, + }, + { + TotalBipStake: big.NewInt(1).String(), + PubKey: pubkey, + AccumReward: big.NewInt(1).String(), + AbsentTimes: ba, + }, + }, + Candidates: []Candidate{ + { + RewardAddress: testAddr, + OwnerAddress: testAddr, + TotalBipStake: big.NewInt(1).String(), + PubKey: pubkey, + Commission: 1, + Stakes: []Stake{ + { + Owner: testAddr, + Coin: GetBaseCoinID(), + Value: big.NewInt(1).String(), + BipValue: big.NewInt(1).String(), + }, + }, + Status: 1, + }, + }, + } + + if appState.Verify() == nil { + t.Error("State is not correct") + } + + appState = AppState{ + TotalSlashed: big.NewInt(1e18).String(), + Validators: []Validator{ + { + TotalBipStake: big.NewInt(1).String(), + PubKey: pubkey, + AccumReward: big.NewInt(1).String(), + AbsentTimes: ba, + }, + }, + } + + if appState.Verify() == nil { + t.Error("State is not correct") + } + + appState = AppState{ + TotalSlashed: big.NewInt(1e18).String(), + Validators: []Validator{ + { + TotalBipStake: "", + PubKey: pubkey, + AccumReward: big.NewInt(1).String(), + AbsentTimes: ba, + }, + }, + Candidates: []Candidate{ + { + RewardAddress: testAddr, + OwnerAddress: testAddr, + TotalBipStake: big.NewInt(1).String(), + PubKey: pubkey, + Commission: 1, + Stakes: []Stake{ + { + Owner: testAddr, + Coin: GetBaseCoinID(), + Value: big.NewInt(1).String(), + BipValue: big.NewInt(1).String(), + }, + }, + Status: 1, + }, + }, + } + + if appState.Verify() == nil { + t.Error("State is not correct") + } + + appState.Validators[0].TotalBipStake = big.NewInt(1e18).String() + appState.Validators[0].AccumReward = "" + if appState.Verify() == nil { + t.Error("State is not correct") + } + + appState.Validators[0].AccumReward = big.NewInt(1e18).String() + appState.Validators[0].AbsentTimes = nil + if appState.Verify() == nil { + t.Error("State is not correct") + } + + appState.Accounts = []Account{ + { + Address: testAddr, + Balance: []Balance{ + { + Coin: GetBaseCoinID(), + Value: big.NewInt(1).String(), + }, + }, + Nonce: 1, + }, { + Address: testAddr, + Balance: []Balance{ + { + Coin: GetBaseCoinID(), + Value: big.NewInt(1).String(), + }, + }, + Nonce: 1, + }, + } + + appState.Validators[0].AbsentTimes = ba + if appState.Verify() == nil { + t.Error("State is not correct") + } + + appState.Accounts = []Account{ + { + Address: testAddr, + Balance: []Balance{ + { + Coin: GetBaseCoinID(), + Value: "", + }, + }, + Nonce: 1, + }, + } + + if appState.Verify() == nil { + t.Error("State is not correct") + } + + appState.Accounts = []Account{ + { + Address: testAddr, + Balance: []Balance{ + { + Coin: GetBaseCoinID() + 1, + Value: big.NewInt(1).String(), + }, + }, + Nonce: 1, + }, + } + + if appState.Verify() == nil { + t.Error("State is not correct") + } + + appState.Accounts = []Account{ + { + Address: testAddr, + Balance: []Balance{ + { + Coin: GetBaseCoinID(), + Value: big.NewInt(1).String(), + }, + }, + Nonce: 1, + }, + } + + appState.Candidates[0].Stakes = []Stake{ + { + Owner: testAddr, + Coin: GetBaseCoinID(), + Value: big.NewInt(1).String(), + BipValue: big.NewInt(1).String(), + }, + { + Owner: testAddr, + Coin: GetBaseCoinID(), + Value: big.NewInt(1).String(), + BipValue: big.NewInt(1).String(), + }, + } + + if appState.Verify() == nil { + t.Error("State is not correct") + } + + appState.Candidates[0].Stakes = []Stake{ + { + Owner: testAddr, + Coin: GetBaseCoinID() + 1, + Value: big.NewInt(1).String(), + BipValue: big.NewInt(1).String(), + }, + } + + appState.Coins = []Coin{ + { + ID: GetBaseCoinID() + 2, + }, + } + + if appState.Verify() == nil { + t.Error("State is not correct") + } + + appState.Candidates[0].Stakes = []Stake{ + { + Owner: testAddr, + Coin: GetBaseCoinID() + 1, + Value: big.NewInt(1).String(), + BipValue: big.NewInt(1).String(), + }, + } + + appState.Coins = []Coin{ + { + ID: GetBaseCoinID() + 1, + Name: "ASD", + Symbol: StrToCoinSymbol("TEST"), + Volume: big.NewInt(1).String(), + Crr: 1, + Reserve: helpers.BipToPip(big.NewInt(100000)).String(), + MaxSupply: helpers.BipToPip(big.NewInt(100000)).String(), + }, + { + ID: GetBaseCoinID(), + Symbol: GetBaseCoin(), + }, + } + + if appState.Verify() == nil { + t.Error("State is not correct") + } + + appState.Coins = []Coin{ + { + ID: GetBaseCoinID() + 1, + Name: "ASD", + Symbol: StrToCoinSymbol("TEST"), + Volume: big.NewInt(1).String(), + Crr: 1, + Reserve: helpers.BipToPip(big.NewInt(100000)).String(), + MaxSupply: helpers.BipToPip(big.NewInt(100000)).String(), + }, + { + ID: GetBaseCoinID() + 1, + Name: "ASD", + Symbol: StrToCoinSymbol("TEST"), + Volume: big.NewInt(1).String(), + Crr: 1, + Reserve: helpers.BipToPip(big.NewInt(100000)).String(), + MaxSupply: helpers.BipToPip(big.NewInt(100000)).String(), + }, + { + ID: GetBaseCoinID(), + Symbol: GetBaseCoin(), + }, + } + + if appState.Verify() == nil { + t.Error("State is not correct") + } + + appState.Coins = []Coin{ + { + ID: GetBaseCoinID() + 1, + Name: "ASD", + Symbol: StrToCoinSymbol("TEST"), + Volume: big.NewInt(1).String(), + Crr: 1, + Reserve: helpers.BipToPip(big.NewInt(100000)).String(), + MaxSupply: helpers.BipToPip(big.NewInt(100000)).String(), + }, + } + + appState.UsedChecks = []UsedCheck{ + "00004601d10c33eda76bb16a54a0asddsd8882a57ec34e964aa23e2b5d9aa10957feea", + } + + if appState.Verify() == nil { + t.Error("State is not correct") + } +} + +func TestHashToString(t *testing.T) { + hash := Hash{5} + if hash.String() != "Mx0500000000000000000000000000000000000000000000000000000000000000" { + t.Error("Hash hex not the same") + } +} + +func TestHashToBytes(t *testing.T) { + b := []byte{5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + hash := BytesToHash(b) + + if !bytes.Equal(b, hash.Bytes()) { + t.Error("Bytes are the same") + } +} + +func TestEmptyHash(t *testing.T) { + if EmptyHash(Hash{}) != true { + t.Error("Hash is not empty") + } +} + +func TestHashToSetBytes(t *testing.T) { + b1 := []byte{1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + + h := Hash{} + h.SetBytes(b1) + + if !bytes.Equal(b1, h.Bytes()) { + t.Error("Bytes are not the same") + } + + b2 := []byte{2, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + h.SetBytes(b2) + + if !bytes.Equal(b1, h.Bytes()) { + t.Error("Bytes are not the same") + } +} + +func TestHashToSet(t *testing.T) { + h1, h2 := Hash{5}, Hash{} + h2.Set(h1) + + if !bytes.Equal(h1.Bytes(), h2.Bytes()) { + t.Error("Bytes are not the same") + } +} + +func TestHashToMarshalText(t *testing.T) { + b := []byte{77, 120, 48, 53, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48} + h := Hash{5} + hashBytes, err := h.MarshalText() + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(hashBytes, b) { + t.Error("Bytes are not the same") + } + + h2 := Hash{} + if err = h2.UnmarshalText(hashBytes); err != nil { + t.Fatal(err) + } + + if !bytes.Equal(h2.Bytes(), h.Bytes()) { + t.Error("Bytes are not the same") + } +} + +func TestGetVersionFromSymbol(t *testing.T) { + if GetVersionFromSymbol("BIP-5") != 5 { + t.Error("Coin version is incorrect") + } + + if GetVersionFromSymbol("BIP") != 0 { + t.Error("Coin version is incorrect") + } +} + +func TestAddressToSetBytes(t *testing.T) { + b1 := []byte{5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + + a := Address{} + a.SetBytes(b1) + if !bytes.Equal(b1, a.Bytes()) { + t.Error("Bytes are not the same") + } + + b2 := []byte{1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + a.SetBytes(b2) + + if !bytes.Equal(b1, a.Bytes()) { + t.Error("Bytes are not the same") + } +} + +func TestAddressToSet(t *testing.T) { + a1, a2 := Address{5}, Address{} + a2.Set(a1) + + if !bytes.Equal(a1.Bytes(), a2.Bytes()) { + t.Error("Bytes are not the same") + } +} + +func TestAddressToMarshalText(t *testing.T) { + b := []byte{77, 120, 48, 49, 48, 50, 48, 51, 48, 52, 48, 53, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48} + a := Address{1, 2, 3, 4, 5} + hashBytes, err := a.MarshalText() + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(hashBytes, b) { + t.Error("Bytes are not the same") + } + + a2 := Address{} + if err := a2.UnmarshalText(hashBytes); err != nil { + t.Fatal(err) + } + + if !bytes.Equal(a2.Bytes(), a.Bytes()) { + t.Error("Bytes are not the same") + } +} + +func TestHexToPubkey(t *testing.T) { + p1, p2 := Pubkey{10, 12}, HexToPubkey("Mp0a0c000000000000000000000000000000000000000000000000000000000000") + if !p1.Equals(p2) { + t.Error("Pubkeys are not equal") + } +} + +func TestBytesToPubkey(t *testing.T) { + b := []byte{1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + p := BytesToPubkey(b) + if !bytes.Equal(p.Bytes(), b) { + t.Error("Bytes are not the same") + } +} + +func TestPubkeyToSetBytes(t *testing.T) { + b, p := []byte{1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Pubkey{} + p.SetBytes(b) + if !bytes.Equal(p.Bytes(), b) { + t.Error("Bytes are not the same") + } + + b2 := []byte{5, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + p.SetBytes(b2) + if !bytes.Equal(p.Bytes(), b) { + t.Error("Bytes are not the same") + } +} + +func TestPubkeyToMarshalText(t *testing.T) { + b := []byte{77, 112, 48, 53, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48} + p := Pubkey{5} + hashBytes, err := p.MarshalText() + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(hashBytes, b) { + t.Error("Bytes are not the same") + } +} From 681041278ffe2ed992bd8b9d8d2bdce37823414e Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 16 Sep 2020 12:21:42 +0300 Subject: [PATCH 267/426] app state tests --- core/types/types_test.go | 57 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/core/types/types_test.go b/core/types/types_test.go index e04131729..72e25e40b 100644 --- a/core/types/types_test.go +++ b/core/types/types_test.go @@ -188,7 +188,7 @@ func TestAppState(t *testing.T) { ID: GetBaseCoinID() + 1, Name: "ASD", Symbol: StrToCoinSymbol("TEST"), - Volume: big.NewInt(1).String(), + Volume: big.NewInt(2).String(), Crr: 1, Reserve: helpers.BipToPip(big.NewInt(100000)).String(), MaxSupply: helpers.BipToPip(big.NewInt(100000)).String(), @@ -199,7 +199,7 @@ func TestAppState(t *testing.T) { Height: 1, Address: testAddr, CandidateKey: &pubkey, - Coin: GetBaseCoinID(), + Coin: GetBaseCoinID() + 1, Value: big.NewInt(1).String(), }, }, @@ -539,6 +539,58 @@ func TestAppStateToInvalidState(t *testing.T) { }, } + appState.FrozenFunds = []FrozenFund{ + { + Height: 1, + Address: testAddr, + CandidateKey: &pubkey, + Coin: GetBaseCoinID() + 1, + Value: big.NewInt(1e18).String(), + }, + } + + if appState.Verify() == nil { + t.Error("State is not correct") + } + + appState.FrozenFunds = []FrozenFund{ + { + Height: 1, + Address: testAddr, + CandidateKey: &pubkey, + Coin: GetBaseCoinID(), + Value: "", + }, + } + + if appState.Verify() == nil { + t.Error("State is not correct") + } + + appState.FrozenFunds = []FrozenFund{ + { + Height: 1, + Address: testAddr, + CandidateKey: &pubkey, + Coin: GetBaseCoinID() + 3, + Value: big.NewInt(1e18).String(), + }, + } + + if appState.Verify() == nil { + t.Error("State is not correct") + } + + appState.FrozenFunds = []FrozenFund{ + { + Height: 1, + Address: testAddr, + CandidateKey: &pubkey, + Coin: GetBaseCoinID(), + Value: big.NewInt(1e18).String(), + }, + } + appState.UsedChecks = []UsedCheck{ "00004601d10c33eda76bb16a54a0asddsd8882a57ec34e964aa23e2b5d9aa10957feea", } @@ -546,6 +598,7 @@ func TestAppStateToInvalidState(t *testing.T) { if appState.Verify() == nil { t.Error("State is not correct") } + } func TestHashToString(t *testing.T) { From 970033ffe6ed2e74fecaa888bd502df67b7914ff Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 16 Sep 2020 12:30:38 +0300 Subject: [PATCH 268/426] bit array tests --- core/types/bitarray_test.go | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 core/types/bitarray_test.go diff --git a/core/types/bitarray_test.go b/core/types/bitarray_test.go new file mode 100644 index 000000000..c2375259e --- /dev/null +++ b/core/types/bitarray_test.go @@ -0,0 +1,45 @@ +package types + +import ( + "bytes" + "testing" +) + +func TestNewBitArray(t *testing.T) { + if NewBitArray(0) != nil { + t.Error("bit array is not nil") + } +} + +func TestBitArraySize(t *testing.T) { + b := NewBitArray(10) + if b.Size() != 10 { + t.Error("incorrect size of bit array") + } + + b = NewBitArray(0) + if b.Size() != 0 { + t.Error("incorrect size of bit array") + } +} + +func TestBitArrayGetIndex(t *testing.T) { + b := NewBitArray(0) + if b.GetIndex(10) != false { + t.Error("invalid index of bit array") + } +} + +func TestBitArraySetIndex(t *testing.T) { + b := NewBitArray(0) + if b.SetIndex(10, true) != false { + t.Error("invalid index of bit array") + } +} + +func TestBitArrayBytes(t *testing.T) { + b := NewBitArray(10) + if !bytes.Equal(b.Bytes(), []byte{0, 0}) { + t.Error("Bytes are not equal") + } +} From 4b79528fcddb2fdc4b822599ebd74789c718f59d Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 16 Sep 2020 12:41:49 +0300 Subject: [PATCH 269/426] Update EditCandidatePublicKey commission --- core/commissions/commissions.go | 2 +- core/transaction/executor.go | 19 +++++-------------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/core/commissions/commissions.go b/core/commissions/commissions.go index 5598d46a6..82e8b0121 100644 --- a/core/commissions/commissions.go +++ b/core/commissions/commissions.go @@ -12,7 +12,7 @@ const ( PayloadByte int64 = 2 ToggleCandidateStatus int64 = 100 EditCandidate int64 = 10000 - EditCandidatePublicKey int64 = 10000 + EditCandidatePublicKey int64 = 100000000 MultisendDelta int64 = 5 RedeemCheckTx = SendTx * 3 SetHaltBlock int64 = 1000 diff --git a/core/transaction/executor.go b/core/transaction/executor.go index dc7e90c1d..69ce66013 100644 --- a/core/transaction/executor.go +++ b/core/transaction/executor.go @@ -22,7 +22,7 @@ const ( maxPayloadLength = 1024 maxServiceDataLength = 128 - coinGas = 5000 + stdGas = 5000 ) type Response struct { @@ -204,19 +204,10 @@ func RunTx(context state.Interface, response.GasPrice = tx.GasPrice - if tx.Type == TypeCreateCoin { - response.GasUsed = coinGas - response.GasWanted = coinGas - } - - if tx.Type == TypeEditCoinOwner { - response.GasUsed = coinGas - response.GasWanted = coinGas - } - - if tx.Type == TypeRecreateCoin { - response.GasUsed = coinGas - response.GasWanted = coinGas + switch tx.Type { + case TypeCreateCoin, TypeEditCoinOwner, TypeRecreateCoin, TypeEditCandidatePublicKey: + response.GasUsed = stdGas + response.GasWanted = stdGas } return response From 0c4c4f06a291be52bcde0557dbe27874992aa2ee Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 16 Sep 2020 12:46:48 +0300 Subject: [PATCH 270/426] Refactors --- core/transaction/declare_candidacy.go | 3 +-- core/transaction/executor.go | 14 ++++++-------- core/transaction/redeem_check.go | 3 +-- core/transaction/transaction.go | 4 ++++ 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index 93e4b44c4..8748e3b7f 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -101,8 +101,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r } } - commissionInBaseCoin := big.NewInt(0).Mul(big.NewInt(int64(tx.GasPrice)), big.NewInt(tx.Gas())) - commissionInBaseCoin.Mul(commissionInBaseCoin, CommissionMultiplier) + commissionInBaseCoin := tx.CommissionInBaseCoin() commission := big.NewInt(0).Set(commissionInBaseCoin) gasCoin := checkState.Coins().GetCoin(tx.GasCoin) diff --git a/core/transaction/executor.go b/core/transaction/executor.go index 69ce66013..c5000b9d3 100644 --- a/core/transaction/executor.go +++ b/core/transaction/executor.go @@ -13,18 +13,14 @@ import ( "github.com/tendermint/tendermint/libs/kv" ) -var ( - CommissionMultiplier = big.NewInt(10e14) -) - const ( maxTxLength = 7168 maxPayloadLength = 1024 maxServiceDataLength = 128 - - stdGas = 5000 + stdGas = 5000 ) +// Response represents standard response from tx delivery/check type Response struct { Code uint32 `json:"code,omitempty"` Data []byte `json:"data,omitempty"` @@ -36,6 +32,7 @@ type Response struct { GasPrice uint32 `json:"gas_price"` } +// RunTx executes transaction in given context func RunTx(context state.Interface, rawTx []byte, rewardPool *big.Int, @@ -213,10 +210,11 @@ func RunTx(context state.Interface, return response } +// EncodeError encodes error to json func EncodeError(data interface{}) string { - marshal, err := json.Marshal(data) + marshaled, err := json.Marshal(data) if err != nil { panic(err) } - return string(marshal) + return string(marshaled) } diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index 93e357bff..2ac2f068f 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -177,8 +177,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward } } - commissionInBaseCoin := big.NewInt(0).Mul(big.NewInt(int64(tx.GasPrice)), big.NewInt(tx.Gas())) - commissionInBaseCoin.Mul(commissionInBaseCoin, CommissionMultiplier) + commissionInBaseCoin := tx.CommissionInBaseCoin() commission := big.NewInt(0).Set(commissionInBaseCoin) gasCoin := checkState.Coins().GetCoin(decodedCheck.GasCoin) diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index e78fb52e3..36b8b98db 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -48,6 +48,10 @@ var ( ErrInvalidSig = errors.New("invalid transaction v, r, s values") ) +var ( + CommissionMultiplier = big.NewInt(10e14) +) + type Transaction struct { Nonce uint64 ChainID types.ChainID From fcc51676382b9d322ba8327a733765727981accb Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 16 Sep 2020 12:50:09 +0300 Subject: [PATCH 271/426] Fix test --- core/transaction/edit_candidate_public_key_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/transaction/edit_candidate_public_key_test.go b/core/transaction/edit_candidate_public_key_test.go index f53f6cc0e..71d441643 100644 --- a/core/transaction/edit_candidate_public_key_test.go +++ b/core/transaction/edit_candidate_public_key_test.go @@ -62,7 +62,7 @@ func TestEditCandidateNewPublicKeyTx(t *testing.T) { t.Fatalf("Response code is not 0. Error %s", response.Log) } - targetBalance, _ := big.NewInt(0).SetString("999990000000000000000000", 10) + targetBalance, _ := big.NewInt(0).SetString("900000000000000000000000", 10) balance := cState.Accounts.GetBalance(addr, coin) if balance.Cmp(targetBalance) != 0 { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", coin, targetBalance, balance) From 258ad7f2d9eb4c155a63aa26f649ae198e77b8bf Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 16 Sep 2020 13:00:20 +0300 Subject: [PATCH 272/426] Add math tests --- go.mod | 1 - math/exp_test.go | 120 +++++++++++++++++++++++++++++++++ math/log_test.go | 114 +++++++++++++++++++++++++++++++ math/misc_test.go | 84 +++++++++++++++++++++++ math/pow_test.go | 167 ++++++++++++++++++++++++++++++++++++++++++++++ math/sqrt_test.go | 130 ++++++++++++++++++++++++++++++++++++ 6 files changed, 615 insertions(+), 1 deletion(-) create mode 100644 math/exp_test.go create mode 100644 math/log_test.go create mode 100644 math/misc_test.go create mode 100644 math/pow_test.go create mode 100644 math/sqrt_test.go diff --git a/go.mod b/go.mod index 4b636350f..9097b7ca8 100644 --- a/go.mod +++ b/go.mod @@ -39,5 +39,4 @@ require ( golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/grpc v1.31.0 google.golang.org/protobuf v1.25.0 - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 ) diff --git a/math/exp_test.go b/math/exp_test.go new file mode 100644 index 000000000..0dc0308f5 --- /dev/null +++ b/math/exp_test.go @@ -0,0 +1,120 @@ +package math_test + +import ( + "fmt" + "math" + "math/big" + "math/rand" + "testing" + + bigfloat "github.com/MinterTeam/minter-go-node/math" +) + +func TestExp(t *testing.T) { + for _, test := range []struct { + z string + want string + }{ + {"0", "1"}, + {"1", "2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274274663919320030599218174135966290435729003342952605956307381323286279434907632338298807531952510190115738341879307021540891499348841675092447614606680822648001684774118537423454424371075390777449920695517027618386062613313845830007520449338265602976"}, + {"1.5", "4.4816890703380648226020554601192758190057498683696670567726500827859366744667137729810538313824533913886163506518301957689627464772204086069617596449736935381785298966216866555101351015468252930697652168582207145843214628870201383138594206299440366192845735003904511744769330306157776861818063974846024442278949433305735015582659896397844432731673273"}, + {"2", "7.3890560989306502272304274605750078131803155705518473240871278225225737960790577633843124850791217947737531612654788661238846036927812733744783922133980777749001228956074107537023913309475506820865818202696478682084042209822552348757424625414146799281293318880707633010193378997407299869600953033075153208188236846947930299135587714456831239232727646"}, + {"3", "20.085536923187667740928529654581717896987907838554150144378934229698845878091973731204497160253017702153607615851949002881811012479353506690232621784477250503945677100066077851812229047884383940258152534709352622981465538424555697733515108150118404754933838497843177676070913772862491787349396037822793717687131254060597553426640826030948663920216259"}, + + {"-1", "0.36787944117144232159552377016146086744581113103176783450783680169746149574489980335714727434591964374662732527684399520824697579279012900862665358949409878309219436737733811504863899112514561634498771997868447595793974730254989249545323936620796481051464752061229422308916492656660036507457728370553285373838810680478761195682989345449735073931859922"}, + {"-2", "0.13533528323661269189399949497248440340763154590957588146815887265407337410148768993709812249065704875507728718963355221244934687189285303815889513499670600559125022755868258230483842057584538468003599408344602481287135375015664353399593608501390049529421705857601948571122397095990883595090571764528251279379538022237440385068269131295459365886804367"}, + {"-3", "0.049787068367863942979342415650061776631699592188423215567627727606060667730199550154054244236633344526401328650893681950864643386736174297123488422626590132549710257089250891729183705544267766471294627261313755158051249249208013335774449487985072339959233419058693861230319791977014791562486437888837044087835498513120050395020976909328170160274676519"}, + + {"10", "22026.465794806716516957900645284244366353512618556781074235426355225202818570792575199120968164525895451555501092457836652423291606522895166222480137728972873485577837847275195480610095881417055888657927317236168401192698035170264925041101757502556764762696107543817931960834044404934236682455357614946828619042431465132389556031319229262768101604495"}, + {"100", "2.6881171418161354484126255515800135873611118773741922415191608615280287034909564914158871097219845710811670879190576068697597709761868233548459638929871966089629133626120029380957276534032962269865668016917743514451846065162804442237756762296960284731911402129862281040057911593878790384974173340084912432828126815454426051808828625966509400466909062e43"}, + {"1000", "1.9700711140170469938888793522433231253169379853238457899528029913850638507824411934749780765630268899309638179875202269359829817305446128992326278366015282523232053516958456675619227156760278807142246682631400685516850865349794166031604536781793809290529972858013286994585647028653437590045656435558915622042232026051882611228863835837224872472521451e434"}, + + {"-10", "0.000045399929762484851535591515560550610237918088866564969259071305650999421614302281652525004545947782321708055089686028492945199117244520388837183347709414567560990909217007363970181059501783900762968517787030908824365171548448722293652332416020501168264360305604941570107729975354408079403994232932138270780520042710498960354486166066837009201707573209"}, + {"-100", "3.7200759760208359629596958038631183373588922923767819671206138766632904758958157181571187786422814966019356176423110698002479856420525356002661856882839075574388191160228448691497585855102816611741608772370701345082175755257496876380478927279529400619796226477050521097935092405571614981699373980650794385017392666116669084820355852767349264735965334e-44"}, + {"-1000", "5.0759588975494567652918094795743369193055992828928373618323938454105405429748191756796621690465428678636671068310652851135787934480190632251259072300213915638091771495398351108574919194309548129952421441572726108465407163812260104924530270737073247546217081943180823516857873407345613076984468096760005536701904004361380296144254899617340297251706670e-435"}, + } { + for _, prec := range []uint{24, 53, 64, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000} { + want := new(big.Float).SetPrec(prec) + want.Parse(test.want, 10) + + z := new(big.Float).SetPrec(prec) + z.Parse(test.z, 10) + + x := bigfloat.ExpFloat(z) + + if x.Cmp(want) != 0 { + t.Errorf("prec = %d, Exp(%v) =\ngot %g;\nwant %g", prec, test.z, x, want) + } + } + } +} + +func testExpFloat64(scale float64, nTests int, t *testing.T) { + for i := 0; i < nTests; i++ { + r := rand.Float64() * scale + + z := big.NewFloat(r) + z64, acc := bigfloat.ExpFloat(z).Float64() + + want := math.Exp(r) + + // Unfortunately, the Go math.Exp function is not completely + // accurate, so it doesn't make sense to require 100% + // compatibility with it, since it happens that math.Exp + // returns a result with the last bit off (same as math.Log). + // + // Just require a relative error smaller than 1e-14. + if math.Abs(z64-want)/want > 1e-14 || acc != big.Exact { + t.Errorf("Exp(%g) =\n got %g (%s);\nwant %g (Exact)", z, z64, acc, want) + } + } +} + +func TestExpFloat64Small(t *testing.T) { + testExpFloat64(-100, 4e3, t) + testExpFloat64(-10, 4e3, t) + testExpFloat64(-1, 4e3, t) +} + +func TestExpFloat64Medium(t *testing.T) { + testExpFloat64(0.1, 5e3, t) + testExpFloat64(1, 5e3, t) +} + +func TestExpFloat64Big(t *testing.T) { + testExpFloat64(10, 5e3, t) + testExpFloat64(100, 5e3, t) +} + +func TestExpSpecialValues(t *testing.T) { + for _, f := range []float64{ + +0.0, + -0.0, + math.Inf(+1), + math.Inf(-1), + } { + z := big.NewFloat(f) + x64, acc := bigfloat.ExpFloat(z).Float64() + want := math.Exp(f) + if x64 != want || acc != big.Exact { + t.Errorf("Log(%f) =\n got %g (%s);\nwant %g (Exact)", f, x64, acc, want) + } + } +} + +// ---------- Benchmarks ---------- + +func BenchmarkExp(b *testing.B) { + z := big.NewFloat(2).SetPrec(1e5) + _ = bigfloat.ExpFloat(z) // fill pi cache before benchmarking + + for _, prec := range []uint{1e2, 1e3, 1e4, 1e5} { + z = big.NewFloat(2).SetPrec(prec) + b.Run(fmt.Sprintf("%v", prec), func(b *testing.B) { + b.ReportAllocs() + for n := 0; n < b.N; n++ { + bigfloat.ExpFloat(z) + } + }) + } +} diff --git a/math/log_test.go b/math/log_test.go new file mode 100644 index 000000000..b0c9ccb0b --- /dev/null +++ b/math/log_test.go @@ -0,0 +1,114 @@ +package math_test + +import ( + "fmt" + "math" + "math/big" + "math/rand" + "testing" + + bigfloat "github.com/MinterTeam/minter-go-node/math" +) + +// See note in sqrt_test.go about which numbers +// can we safely test this way. + +func TestLog(t *testing.T) { + for _, test := range []struct { + z string + want string + }{ + // 350 decimal digits are enough to give us up to 1000 binary digits + {"0.5", "-0.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641868754200148102057068573368552023575813055703267075163507596193072757082837143519030703862389167347112335011536449795523912047517268157493206515552473413952588295045300709532636664265410423915781495204374043038550080194417064167151864471283996817178454696"}, + {"0.25", "-1.3862943611198906188344642429163531361510002687205105082413600189867872439393894312117266539928373750840029620411413714673710404715162611140653415032701519238614551416567428703806140772477833469422467002307289959104782409503453631498641303110494682790517659009060141906527332853082084783156299040874808607710016038883412833430372894256799363435690939"}, + {"0.0125", "-4.3820266346738816122696878190588939118276018917095387383953679294477534755864366270535871860788543609679722271039983058344660861723571984277642996240040095752750899208106689864147210106979082189417635556550588715983462075888842670124944153533207460860520530946333864410280342429017041970928492563533263928706772062013203262792640026952942261381891629"}, + + {"1", "0.0"}, + {"2", "0.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641868754200148102057068573368552023575813055703267075163507596193072757082837143519030703862389167347112335011536449795523912047517268157493206515552473413952588295045300709532636664265410423915781495204374043038550080194417064167151864471283996817178454696"}, + {"10", "2.3025850929940456840179914546843642076011014886287729760333279009675726096773524802359972050895982983419677840422862486334095254650828067566662873690987816894829072083255546808437998948262331985283935053089653777326288461633662222876982198867465436674744042432743651550489343149393914796194044002221051017141748003688084012647080685567743216228355220"}, + {"4096", "8.3177661667193437130067854574981188169060016123230630494481601139207234636363365872703599239570242505040177722468482288042262428290975666843920490196209115431687308499404572222836844634867000816534802013843739754628694457020721788991847818662968096743105954054360851439163997118492508698937794245248851646260096233300477000582237365540796180614145634"}, + {"1e5", "11.512925464970228420089957273421821038005507443143864880166639504837863048386762401179986025447991491709838920211431243167047627325414033783331436845493908447414536041627773404218999474131165992641967526544826888663144230816831111438491099433732718337372021216371825775244671574696957398097022001110525508570874001844042006323540342783871608114177610"}, + } { + for _, prec := range []uint{24, 53, 64, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000} { + want := new(big.Float).SetPrec(prec) + want.Parse(test.want, 10) + + z := new(big.Float).SetPrec(prec) + z.Parse(test.z, 10) + + x := bigfloat.Log(z) + + if x.Cmp(want) != 0 { + t.Errorf("prec = %d, Log(%v) =\ngot %g;\n want %g", prec, test.z, x, want) + } + } + } +} + +func testLogFloat64(scale float64, nTests int, t *testing.T) { + for i := 0; i < nTests; i++ { + r := rand.Float64() * scale + + z := big.NewFloat(r) + x64, acc := bigfloat.Log(z).Float64() + + want := math.Log(r) + + // Unfortunately, the Go math.Log function is not completely + // accurate, so it doesn't make sense to require 100% + // compatibility with it, since it happens that math.Log + // returns a result with the last bit off (see Issue #9546). + // + // Just require a relative error smaller than 1e-14. + if math.Abs(x64-want)/want > 1e-14 || acc != big.Exact { + t.Errorf("Log(%g) =\n got %g (%s);\nwant %g (Exact)", z, x64, acc, want) + } + } +} + +func TestLogFloat64Small(t *testing.T) { + testLogFloat64(1e-100, 1e4, t) + testLogFloat64(1e-10, 1e4, t) +} + +func TestLogFloat64Medium(t *testing.T) { + testLogFloat64(1, 1e4, t) + testLogFloat64(100, 1e4, t) +} + +func TestLogFloat64Big(t *testing.T) { + testLogFloat64(1e10, 1e4, t) + testLogFloat64(1e100, 1e4, t) +} + +func TestLogSpecialValues(t *testing.T) { + for _, f := range []float64{ + +0.0, + -0.0, + math.Inf(+1), + } { + z := big.NewFloat(f) + x64, acc := bigfloat.Log(z).Float64() + want := math.Log(f) + if x64 != want || acc != big.Exact { + t.Errorf("Log(%f) =\n got %g (%s);\nwant %g (Exact)", f, x64, acc, want) + } + } +} + +// ---------- Benchmarks ---------- + +func BenchmarkLog(b *testing.B) { + z := big.NewFloat(2).SetPrec(1e5) + _ = bigfloat.Log(z) // fill pi cache before benchmarking + + for _, prec := range []uint{1e2, 1e3, 1e4, 1e5} { + z = big.NewFloat(2).SetPrec(prec) + b.Run(fmt.Sprintf("%v", prec), func(b *testing.B) { + b.ReportAllocs() + for n := 0; n < b.N; n++ { + bigfloat.Log(z) + } + }) + } +} diff --git a/math/misc_test.go b/math/misc_test.go new file mode 100644 index 000000000..9345b431b --- /dev/null +++ b/math/misc_test.go @@ -0,0 +1,84 @@ +package math + +import ( + "fmt" + "math/big" + "testing" +) + +const maxPrec uint = 1100 + +func TestAgm(t *testing.T) { + for _, test := range []struct { + a, b string + want string + }{ + // 350 decimal digits are enough to give us up to 1000 binary digits + {"1", "2", "1.4567910310469068691864323832650819749738639432213055907941723832679264545802509002574737128184484443281894018160367999355762430743401245116912132499522793768970211976726893728266666782707432902072384564600963133367494416649516400826932239086263376738382410254887262645136590660408875885100466728130947439789355129117201754471869564160356411130706061"}, + {"1", "10", "4.2504070949322748617281643183731348667984678641901928596701476622237553127409037845252854607876171790458817135897668652366410690187825866854343005714304399718866701345600268795095037823053677248108795697049522041225723229732458947507697835936406527028150257238518982793084569470658500853106997941082919334694146843915361847332301248942222685517896377"}, + {"1", "0.125", "0.45196952219967034359164911331276507645541557018306954112635037493237190371123433961098897571407153216488726488616781446636283304514042965741376539315003644325377859387794608118242990700589889155408232061013871480906595147189700268152276449512798584772002737950386745259435790965051247641106770187776231088478906739003673011639874297764052324720923824"}, + {"1", "0.00390625", "0.2266172673264813935990249059047521131153183423554951008357647589399579243281007098800682366778894106068183449922373565084840603788091294841822891406755449218057751291845474188560350241555526734834267320629182988862200822134426714354129001630331838172767684623648755579758508073234772093745831056731263684472818466567279847347734121500617411676068370"}, + {"1", "0.0001220703125", "0.15107867088555894565277006051956059212554039802503247524478909254186086852737399490629222674071181480492157167137547694132610166031526264375084434300568336411139925857454913414480542768807718797335060713475211709310835676172131569048902323084439330888400622327072954342544508199547787750415198261456314278054748992781108231991187512975110547417178045"}, + } { + for _, prec := range []uint{24, 53, 64, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000} { + want := new(big.Float).SetPrec(prec) + want.Parse(test.want, 10) + + a := new(big.Float).SetPrec(prec) + a.Parse(test.a, 10) + + b := new(big.Float).SetPrec(prec) + b.Parse(test.b, 10) + + z := agm(a, b) + + if z.Cmp(want) != 0 { + t.Errorf("prec = %d, Agm(%v, %v) =\ngot %g;\nwant %g", prec, test.a, test.b, z, want) + } + } + } +} + +func TestPi(t *testing.T) { + enablePiCache = false + piStr := "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153644" + for _, prec := range []uint{24, 53, 64, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000} { + + want := new(big.Float).SetPrec(prec) + want.Parse(piStr, 10) + + z := pi(prec) + + if z.Cmp(want) != 0 { + t.Errorf("Pi(%d) =\ngot %g;\nwant %g", prec, z, want) + } + } + enablePiCache = true +} + +// ---------- Benchmarks ---------- + +func BenchmarkAgm(b *testing.B) { + for _, prec := range []uint{1e2, 1e3, 1e4, 1e5} { + x := new(big.Float).SetPrec(prec).SetFloat64(1) + y := new(big.Float).SetPrec(prec).SetFloat64(0.125) + b.Run(fmt.Sprintf("%v", prec), func(b *testing.B) { + b.ReportAllocs() + for n := 0; n < b.N; n++ { + agm(x, y) + } + }) + } +} + +func BenchmarkPi(b *testing.B) { + enablePiCache = false + for _, prec := range []uint{1e2, 1e3, 1e4, 1e5} { + b.Run(fmt.Sprintf("%v", prec), func(b *testing.B) { + b.ReportAllocs() + for n := 0; n < b.N; n++ { + pi(prec) + } + }) + } +} diff --git a/math/pow_test.go b/math/pow_test.go new file mode 100644 index 000000000..8dd7893ac --- /dev/null +++ b/math/pow_test.go @@ -0,0 +1,167 @@ +package math_test + +import ( + "fmt" + bigfloat "github.com/MinterTeam/minter-go-node/math" + "math" + "math/big" + "math/rand" + "testing" +) + +func TestPow(t *testing.T) { + for _, test := range []struct { + z, w string + want string + }{ + {"1.5", "1.5", "1.8371173070873835736479630560294185439744606104925025963245194254382202830929862699048945748284801761139459509199606418436441490948783180062193379634279589146216845606457574284357225789531838276676109830092400181402243325144092030253566067045309391758849310432709781082027026621306513787250611923558785098172755465204952231278685708006003328040156619"}, + {"2", "1.5", "2.8284271247461900976033774484193961571393437507538961463533594759814649569242140777007750686552831454700276924618245940498496721117014744252882429941998716628264453318550111855115999010023055641211429402191199432119405490691937240294570348372817783972191046584609686174286429016795252072559905028159793745067930926636176592812412305167047901094915006"}, + + {"1.5", "-1.5", "0.54433105395181735515495201660130919821465499570148225076282057050021341721273667256441320735658671884857657805035870869441308121329727940925017421138606190062864727722837257138836224561575817116077362459533037574525165407834346756306862420874990790396590549430251203206006004803871151962224035329063066957548905082088747351936846542240009860859723315"}, + {"2", "-1.5", "0.35355339059327376220042218105242451964241796884423701829416993449768311961552675971259688358191039318375346155772807425623120901396268430316103037427498395785330566648187639818894998762528819551514286752738999290149256863364921550368212935466022229965238808230762107717858036270994065090699881285199742181334913658295220741015515381458809876368643757"}, + } { + for _, prec := range []uint{24, 53, 64, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000} { + want := new(big.Float).SetPrec(prec) + want.Parse(test.want, 10) + + z := new(big.Float).SetPrec(prec) + z.Parse(test.z, 10) + w := new(big.Float).SetPrec(prec) + w.Parse(test.w, 10) + + x := bigfloat.Pow(z, w) + + if x.Cmp(want) != 0 { + t.Errorf("prec = %d, Pow(%v, %v) =\ngot %g;\nwant %g", prec, test.z, test.w, x, want) + } + } + } +} + +func TestPowIntegers(t *testing.T) { + for _, test := range []struct { + z, w string + want string + }{ + {"2", "5", "32"}, + {"2", "10", "1024"}, + {"2", "64", "18446744073709551616"}, + + {"2", "-5", "0.03125"}, + {"2", "-10", "0.0009765625"}, + {"2", "-64", "5.42101086242752217003726400434970855712890625e-20"}, + + {"1.5", "8", "25.62890625"}, + } { + for _, prec := range []uint{24, 53, 64, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000} { + want := new(big.Float).SetPrec(prec) + want.Parse(test.want, 10) + + z := new(big.Float).SetPrec(prec) + z.Parse(test.z, 10) + w := new(big.Float).SetPrec(prec) + w.Parse(test.w, 10) + + x := bigfloat.Pow(z, w) + + if x.Cmp(want) != 0 { + t.Errorf("prec = %d, Pow(%v, %v) =\ngot %g;\nwant %g", prec, test.z, test.w, x, want) + } + } + } +} + +func testPowFloat64(scale float64, nTests int, t *testing.T) { + for i := 0; i < nTests; i++ { + r1 := math.Abs(rand.Float64() * scale) // base always > 0 + r2 := rand.Float64() * scale + + z := big.NewFloat(r1).SetPrec(53) + w := big.NewFloat(r2).SetPrec(53) + + x64, acc := bigfloat.Pow(z, w).Float64() + + want := math.Pow(r1, r2) + + // Unfortunately, the Go math.Pow function is not completely + // accurate, so it doesn't make sense to require 100% + // compatibility with it, since it happens that math.Pow + // returns a result with the last bit off (same as math.Log). + // + // Just require a relative error smaller than 1e-14. + if math.Abs(x64-want)/want > 1e-14 || acc != big.Exact { + t.Errorf("Pow(%g, %g) =\n got %g (%s);\nwant %g (Exact)", z, w, x64, acc, want) + } + } +} + +func TestPowFloat64Small(t *testing.T) { + testPowFloat64(-100, 1e3, t) + testPowFloat64(-10, 1e3, t) + testPowFloat64(-1, 1e3, t) +} + +func TestPowFloat64Medium(t *testing.T) { + testPowFloat64(0.1, 4e3, t) + testPowFloat64(1, 4e3, t) +} + +func TestPowFloat64Big(t *testing.T) { + testPowFloat64(10, 4e3, t) + testPowFloat64(100, 4e3, t) +} + +func TestPowSpecialValues(t *testing.T) { + for _, f := range []struct { + z, w float64 + }{ + {2, +0.0}, + {2, -0.0}, + {4.2, 1.0}, + {math.Inf(+1), 2.0}, + } { + z := big.NewFloat(f.z).SetPrec(53) + w := big.NewFloat(f.w).SetPrec(53) + x64, acc := bigfloat.Pow(z, w).Float64() + want := math.Pow(f.z, f.w) + if x64 != want || acc != big.Exact { + t.Errorf("Pow(%g, %g) =\n got %g (%s);\nwant %g (Exact)", f.z, f.w, x64, acc, want) + } + } +} + +// ---------- Benchmarks ---------- + +func BenchmarkPowInt(b *testing.B) { + z := big.NewFloat(2).SetPrec(1e5) + w := big.NewFloat(50).SetPrec(1e5) + _ = bigfloat.Pow(z, w) // fill pi cache before benchmarking + + for _, prec := range []uint{1e2, 1e3, 1e4, 1e5} { + z = big.NewFloat(2).SetPrec(prec) + w = big.NewFloat(50).SetPrec(prec) + b.Run(fmt.Sprintf("%v", prec), func(b *testing.B) { + b.ReportAllocs() + for n := 0; n < b.N; n++ { + bigfloat.Pow(z, w) + } + }) + } +} + +func BenchmarkPow(b *testing.B) { + z := big.NewFloat(2).SetPrec(1e5) + w := big.NewFloat(1.5).SetPrec(1e5) + _ = bigfloat.Pow(z, w) // fill pi cache before benchmarking + + for _, prec := range []uint{1e2, 1e3, 1e4, 1e5} { + z = big.NewFloat(2).SetPrec(prec) + w = big.NewFloat(1.5).SetPrec(prec) + b.Run(fmt.Sprintf("%v", prec), func(b *testing.B) { + b.ReportAllocs() + for n := 0; n < b.N; n++ { + bigfloat.Pow(z, w) + } + }) + } +} diff --git a/math/sqrt_test.go b/math/sqrt_test.go new file mode 100644 index 000000000..699bfd7dc --- /dev/null +++ b/math/sqrt_test.go @@ -0,0 +1,130 @@ +package math_test + +import ( + "fmt" + "math" + "math/big" + "math/rand" + "testing" + + bigfloat "github.com/MinterTeam/minter-go-node/math" +) + +const maxPrec uint = 1100 + +// We can't guarantee that the result will have *prec* precision +// if we call Sqrt with an argument with *prec* precision, because +// the Newton's iteration will actually converge to a number that +// is not the square root of x with *prec+64* precision, but to a +// number that is the square root of x with *prec* precision. +// If we want Sqrt(x) with *prec* precision and correct rounding, +// we need to call Sqrt with an argument having precision greater +// than *prec*. +// +// This will happen for every test number which is not directly +// representable as a binary floating point value, so avoid those. + +func TestSqrt(t *testing.T) { + for _, test := range []struct { + z string + want string + }{ + // 350 decimal digits are enough to give us up to 1000 binary digits + {"0.5", "0.70710678118654752440084436210484903928483593768847403658833986899536623923105351942519376716382078636750692311545614851246241802792536860632206074854996791570661133296375279637789997525057639103028573505477998580298513726729843100736425870932044459930477616461524215435716072541988130181399762570399484362669827316590441482031030762917619752737287514"}, + {"2.0", "1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927557999505011527820605714701095599716059702745345968620147285174186408891986095523292304843087143214508397626036279952514079896872533965463318088296406206152583523950547457503"}, + {"3.0", "1.7320508075688772935274463415058723669428052538103806280558069794519330169088000370811461867572485756756261414154067030299699450949989524788116555120943736485280932319023055820679748201010846749232650153123432669033228866506722546689218379712270471316603678615880190499865373798593894676503475065760507566183481296061009476021871903250831458295239598"}, + {"4.0", "2.0"}, + {"5", "2.2360679774997896964091736687312762354406183596115257242708972454105209256378048994144144083787822749695081761507737835042532677244470738635863601215334527088667781731918791658112766453226398565805357613504175337850034233924140644420864325390972525926272288762995174024406816117759089094984923713907297288984820886415426898940991316935770197486788844"}, + {"6", "2.4494897427831780981972840747058913919659474806566701284326925672509603774573150265398594331046402348185946012266141891248588654598377573416257839512372785528289127475276765712476301052709117702234813106789866908536324433525456040338088089393745855678465747243613041442702702161742018383000815898078380130897007286939936308371580944008004437386875492"}, + {"7", "2.6457513110645905905016157536392604257102591830824501803683344592010688232302836277603928864745436106150645783384974630957435298886272147844273905558801077227171507297283238922996895948650872607009780542037238280237159411003419391160015785255963059457410351523968027164073737990740415815199044034743194536713997305970050513996922375456160971190273782"}, + + {"1p512", "1p256"}, + {"1p1024", "1p512"}, + {"1p2048", "1p1024"}, + {"1p4096", "1p2048"}, + {"2p512", "1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927557999505011527820605714701095599716059702745345968620147285174186408891986095523292304843087143214508397626036279952514079896872533965463318088296406206152583523950547457503p256"}, + {"2p1024", "1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927557999505011527820605714701095599716059702745345968620147285174186408891986095523292304843087143214508397626036279952514079896872533965463318088296406206152583523950547457503p512"}, + {"2p2048", "1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927557999505011527820605714701095599716059702745345968620147285174186408891986095523292304843087143214508397626036279952514079896872533965463318088296406206152583523950547457503p1024"}, + + {"1p-512", "1p-256"}, + {"1p-1024", "1p-512"}, + {"1p-2048", "1p-1024"}, + {"1p-4096", "1p-2048"}, + {"2p-512", "1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927557999505011527820605714701095599716059702745345968620147285174186408891986095523292304843087143214508397626036279952514079896872533965463318088296406206152583523950547457503p-256"}, + {"2p-1024", "1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927557999505011527820605714701095599716059702745345968620147285174186408891986095523292304843087143214508397626036279952514079896872533965463318088296406206152583523950547457503p-512"}, + {"2p-2048", "1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927557999505011527820605714701095599716059702745345968620147285174186408891986095523292304843087143214508397626036279952514079896872533965463318088296406206152583523950547457503p-1024"}, + } { + for _, prec := range []uint{24, 53, 64, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000} { + want := new(big.Float).SetPrec(prec) + want.Parse(test.want, 10) + + z := new(big.Float).SetPrec(prec) + z.Parse(test.z, 10) + + x := bigfloat.Sqrt(z) + + if x.Cmp(want) != 0 { + t.Errorf("prec = %d, Sqrt(%v) =\ngot %g;\nwant %g", prec, test.z, x, want) + } + } + } +} + +func testSqrtFloat64(scale float64, nTests int, t *testing.T) { + for i := 0; i < nTests; i++ { + r := rand.Float64() * scale + + z := big.NewFloat(r) + x64, acc := bigfloat.Sqrt(z).Float64() + + want := math.Sqrt(r) + + if x64 != want || acc != big.Exact { + t.Errorf("Sqrt(%g) =\n got %g (%s);\nwant %g (Exact)", z, x64, acc, want) + } + } +} + +func TestSqrtFloat64Small(t *testing.T) { + testSqrtFloat64(1e-100, 1e5, t) + testSqrtFloat64(1e-10, 1e5, t) +} + +func TestSqrtFloa64Medium(t *testing.T) { + testSqrtFloat64(1, 1e5, t) + testSqrtFloat64(100, 1e5, t) +} + +func TestSqrtFloat64Big(t *testing.T) { + testSqrtFloat64(1e10, 1e5, t) + testSqrtFloat64(1e100, 1e5, t) +} + +func TestSqrtSpecialValues(t *testing.T) { + for _, f := range []float64{ + +0.0, + -0.0, + math.Inf(+1), + } { + z := big.NewFloat(f) + x64, acc := bigfloat.Sqrt(z).Float64() + want := math.Sqrt(f) + if x64 != want || acc != big.Exact { + t.Errorf("Sqrt(%g) =\n got %g (%s);\nwant %g (Exact)", z, x64, acc, want) + } + } +} + +// ---------- Benchmarks ---------- + +func BenchmarkSqrt(b *testing.B) { + for _, prec := range []uint{1e2, 1e3, 1e4, 1e5} { + z := big.NewFloat(2).SetPrec(prec) + b.Run(fmt.Sprintf("%v", prec), func(b *testing.B) { + b.ReportAllocs() + for n := 0; n < b.N; n++ { + bigfloat.Sqrt(z) + } + }) + } +} From 5a42dc45dfffba7f0a104c2f1ab99c77c14f0a8c Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 16 Sep 2020 13:05:42 +0300 Subject: [PATCH 273/426] Add math tests --- math/big.go | 6 + math/big_test.go | 326 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 332 insertions(+) create mode 100644 math/big_test.go diff --git a/math/big.go b/math/big.go index ae03c388e..9ab048290 100644 --- a/math/big.go +++ b/math/big.go @@ -176,6 +176,12 @@ func U256(x *big.Int) *big.Int { return x.And(x, tt256m1) } +// U256Bytes converts a big Int into a 256bit EVM number. +// This operation is destructive. +func U256Bytes(n *big.Int) []byte { + return PaddedBigBytes(U256(n), 32) +} + // S256 interprets x as a two's complement number. // x must not exceed 256 bits (the result is undefined if it does) and is not modified. // diff --git a/math/big_test.go b/math/big_test.go new file mode 100644 index 000000000..a7ee17aa2 --- /dev/null +++ b/math/big_test.go @@ -0,0 +1,326 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package math + +import ( + "bytes" + "encoding/hex" + "github.com/MinterTeam/minter-go-node/core/types" + "math/big" + "testing" +) + +func TestHexOrDecimal256(t *testing.T) { + tests := []struct { + input string + num *big.Int + ok bool + }{ + {"", big.NewInt(0), true}, + {"0", big.NewInt(0), true}, + {"0x0", big.NewInt(0), true}, + {"12345678", big.NewInt(12345678), true}, + {"0x12345678", big.NewInt(0x12345678), true}, + {"0X12345678", big.NewInt(0x12345678), true}, + // Tests for leading zero behaviour: + {"0123456789", big.NewInt(123456789), true}, // note: not octal + {"00", big.NewInt(0), true}, + {"0x00", big.NewInt(0), true}, + {"0x012345678abc", big.NewInt(0x12345678abc), true}, + // Invalid syntax: + {"abcdef", nil, false}, + {"0xgg", nil, false}, + // Larger than 256 bits: + {"115792089237316195423570985008687907853269984665640564039457584007913129639936", nil, false}, + } + for _, test := range tests { + var num HexOrDecimal256 + err := num.UnmarshalText([]byte(test.input)) + if (err == nil) != test.ok { + t.Errorf("ParseBig(%q) -> (err == nil) == %t, want %t", test.input, err == nil, test.ok) + continue + } + if test.num != nil && (*big.Int)(&num).Cmp(test.num) != 0 { + t.Errorf("ParseBig(%q) -> %d, want %d", test.input, (*big.Int)(&num), test.num) + } + } +} + +func TestMustParseBig256(t *testing.T) { + defer func() { + if recover() == nil { + t.Error("MustParseBig should've panicked") + } + }() + MustParseBig256("ggg") +} + +func TestBigMax(t *testing.T) { + a := big.NewInt(10) + b := big.NewInt(5) + + max1 := BigMax(a, b) + if max1 != a { + t.Errorf("Expected %d got %d", a, max1) + } + + max2 := BigMax(b, a) + if max2 != a { + t.Errorf("Expected %d got %d", a, max2) + } +} + +func TestBigMin(t *testing.T) { + a := big.NewInt(10) + b := big.NewInt(5) + + min1 := BigMin(a, b) + if min1 != b { + t.Errorf("Expected %d got %d", b, min1) + } + + min2 := BigMin(b, a) + if min2 != b { + t.Errorf("Expected %d got %d", b, min2) + } +} + +func TestFirstBigSet(t *testing.T) { + tests := []struct { + num *big.Int + ix int + }{ + {big.NewInt(0), 0}, + {big.NewInt(1), 0}, + {big.NewInt(2), 1}, + {big.NewInt(0x100), 8}, + } + for _, test := range tests { + if ix := FirstBitSet(test.num); ix != test.ix { + t.Errorf("FirstBitSet(b%b) = %d, want %d", test.num, ix, test.ix) + } + } +} + +func TestPaddedBigBytes(t *testing.T) { + tests := []struct { + num *big.Int + n int + result []byte + }{ + {num: big.NewInt(0), n: 4, result: []byte{0, 0, 0, 0}}, + {num: big.NewInt(1), n: 4, result: []byte{0, 0, 0, 1}}, + {num: big.NewInt(512), n: 4, result: []byte{0, 0, 2, 0}}, + {num: BigPow(2, 32), n: 4, result: []byte{1, 0, 0, 0, 0}}, + } + for _, test := range tests { + if result := PaddedBigBytes(test.num, test.n); !bytes.Equal(result, test.result) { + t.Errorf("PaddedBigBytes(%d, %d) = %v, want %v", test.num, test.n, result, test.result) + } + } +} + +func BenchmarkPaddedBigBytesLargePadding(b *testing.B) { + bigint := MustParseBig256("123456789123456789123456789123456789") + for i := 0; i < b.N; i++ { + PaddedBigBytes(bigint, 200) + } +} + +func BenchmarkPaddedBigBytesSmallPadding(b *testing.B) { + bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC") + for i := 0; i < b.N; i++ { + PaddedBigBytes(bigint, 5) + } +} + +func BenchmarkPaddedBigBytesSmallOnePadding(b *testing.B) { + bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC") + for i := 0; i < b.N; i++ { + PaddedBigBytes(bigint, 32) + } +} + +func BenchmarkByteAtBrandNew(b *testing.B) { + bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC") + for i := 0; i < b.N; i++ { + bigEndianByteAt(bigint, 15) + } +} + +func BenchmarkByteAt(b *testing.B) { + bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC") + for i := 0; i < b.N; i++ { + bigEndianByteAt(bigint, 15) + } +} + +func BenchmarkByteAtOld(b *testing.B) { + + bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC") + for i := 0; i < b.N; i++ { + PaddedBigBytes(bigint, 32) + } +} + +func TestReadBits(t *testing.T) { + check := func(input string) { + want, _ := hex.DecodeString(input) + int, _ := new(big.Int).SetString(input, 16) + buf := make([]byte, len(want)) + ReadBits(int, buf) + if !bytes.Equal(buf, want) { + t.Errorf("have: %x\nwant: %x", buf, want) + } + } + check("000000000000000000000000000000000000000000000000000000FEFCF3F8F0") + check("0000000000012345000000000000000000000000000000000000FEFCF3F8F0") + check("18F8F8F1000111000110011100222004330052300000000000000000FEFCF3F8F0") +} + +func TestU256(t *testing.T) { + tests := []struct{ x, y *big.Int }{ + {x: big.NewInt(0), y: big.NewInt(0)}, + {x: big.NewInt(1), y: big.NewInt(1)}, + {x: BigPow(2, 255), y: BigPow(2, 255)}, + {x: BigPow(2, 256), y: big.NewInt(0)}, + {x: new(big.Int).Add(BigPow(2, 256), big.NewInt(1)), y: big.NewInt(1)}, + // negative values + {x: big.NewInt(-1), y: new(big.Int).Sub(BigPow(2, 256), big.NewInt(1))}, + {x: big.NewInt(-2), y: new(big.Int).Sub(BigPow(2, 256), big.NewInt(2))}, + {x: BigPow(2, -255), y: big.NewInt(1)}, + } + for _, test := range tests { + if y := U256(new(big.Int).Set(test.x)); y.Cmp(test.y) != 0 { + t.Errorf("U256(%x) = %x, want %x", test.x, y, test.y) + } + } +} + +func TestU256Bytes(t *testing.T) { + ubytes := make([]byte, 32) + ubytes[31] = 1 + + unsigned := U256Bytes(big.NewInt(1)) + if !bytes.Equal(unsigned, ubytes) { + t.Errorf("expected %x got %x", ubytes, unsigned) + } +} + +func TestBigEndianByteAt(t *testing.T) { + tests := []struct { + x string + y int + exp byte + }{ + {"00", 0, 0x00}, + {"01", 1, 0x00}, + {"00", 1, 0x00}, + {"01", 0, 0x01}, + {"0000000000000000000000000000000000000000000000000000000000102030", 0, 0x30}, + {"0000000000000000000000000000000000000000000000000000000000102030", 1, 0x20}, + {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 31, 0xAB}, + {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 32, 0x00}, + {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 500, 0x00}, + } + for _, test := range tests { + v := new(big.Int).SetBytes(types.Hex2Bytes(test.x)) + actual := bigEndianByteAt(v, test.y) + if actual != test.exp { + t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.x, test.y, test.exp, actual) + } + + } +} +func TestLittleEndianByteAt(t *testing.T) { + tests := []struct { + x string + y int + exp byte + }{ + {"00", 0, 0x00}, + {"01", 1, 0x00}, + {"00", 1, 0x00}, + {"01", 0, 0x00}, + {"0000000000000000000000000000000000000000000000000000000000102030", 0, 0x00}, + {"0000000000000000000000000000000000000000000000000000000000102030", 1, 0x00}, + {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 31, 0x00}, + {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 32, 0x00}, + {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 0, 0xAB}, + {"ABCDEF0908070605040302010000000000000000000000000000000000000000", 1, 0xCD}, + {"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", 0, 0x00}, + {"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", 1, 0xCD}, + {"0000000000000000000000000000000000000000000000000000000000102030", 31, 0x30}, + {"0000000000000000000000000000000000000000000000000000000000102030", 30, 0x20}, + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 32, 0x0}, + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 31, 0xFF}, + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0xFFFF, 0x0}, + } + for _, test := range tests { + v := new(big.Int).SetBytes(types.Hex2Bytes(test.x)) + actual := Byte(v, 32, test.y) + if actual != test.exp { + t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.x, test.y, test.exp, actual) + } + + } +} + +func TestS256(t *testing.T) { + tests := []struct{ x, y *big.Int }{ + {x: big.NewInt(0), y: big.NewInt(0)}, + {x: big.NewInt(1), y: big.NewInt(1)}, + {x: big.NewInt(2), y: big.NewInt(2)}, + { + x: new(big.Int).Sub(BigPow(2, 255), big.NewInt(1)), + y: new(big.Int).Sub(BigPow(2, 255), big.NewInt(1)), + }, + { + x: BigPow(2, 255), + y: new(big.Int).Neg(BigPow(2, 255)), + }, + { + x: new(big.Int).Sub(BigPow(2, 256), big.NewInt(1)), + y: big.NewInt(-1), + }, + { + x: new(big.Int).Sub(BigPow(2, 256), big.NewInt(2)), + y: big.NewInt(-2), + }, + } + for _, test := range tests { + if y := S256(test.x); y.Cmp(test.y) != 0 { + t.Errorf("S256(%x) = %x, want %x", test.x, y, test.y) + } + } +} + +func TestExp(t *testing.T) { + tests := []struct{ base, exponent, result *big.Int }{ + {base: big.NewInt(0), exponent: big.NewInt(0), result: big.NewInt(1)}, + {base: big.NewInt(1), exponent: big.NewInt(0), result: big.NewInt(1)}, + {base: big.NewInt(1), exponent: big.NewInt(1), result: big.NewInt(1)}, + {base: big.NewInt(1), exponent: big.NewInt(2), result: big.NewInt(1)}, + {base: big.NewInt(3), exponent: big.NewInt(144), result: MustParseBig256("507528786056415600719754159741696356908742250191663887263627442114881")}, + {base: big.NewInt(2), exponent: big.NewInt(255), result: MustParseBig256("57896044618658097711785492504343953926634992332820282019728792003956564819968")}, + } + for _, test := range tests { + if result := Exp(test.base, test.exponent); result.Cmp(test.result) != 0 { + t.Errorf("Exp(%d, %d) = %d, want %d", test.base, test.exponent, result, test.result) + } + } +} From dfd9f7ef279f16145cc0c210529f525376c7e98a Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 16 Sep 2020 13:26:28 +0300 Subject: [PATCH 274/426] Add more tests --- hexutil/hexutil.go | 2 +- hexutil/hexutil_test.go | 203 ++++++++++++++++++++++ hexutil/json.go | 6 +- hexutil/json_test.go | 374 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 581 insertions(+), 4 deletions(-) create mode 100644 hexutil/hexutil_test.go create mode 100644 hexutil/json_test.go diff --git a/hexutil/hexutil.go b/hexutil/hexutil.go index b92397c68..86abadf80 100644 --- a/hexutil/hexutil.go +++ b/hexutil/hexutil.go @@ -182,7 +182,7 @@ func EncodeBig(bigint *big.Int) string { if nbits == 0 { return "Mx0" } - return fmt.Sprintf("%#x", bigint) + return fmt.Sprintf("Mx%x", bigint) } func hasMxPrefix(input string) bool { diff --git a/hexutil/hexutil_test.go b/hexutil/hexutil_test.go new file mode 100644 index 000000000..abc1f564e --- /dev/null +++ b/hexutil/hexutil_test.go @@ -0,0 +1,203 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package hexutil + +import ( + "bytes" + "math/big" + "testing" +) + +type marshalTest struct { + input interface{} + want string +} + +type unmarshalTest struct { + input string + want interface{} + wantErr error // if set, decoding must fail on any platform + wantErr32bit error // if set, decoding must fail on 32bit platforms (used for Uint tests) +} + +var ( + encodeBytesTests = []marshalTest{ + {[]byte{}, "Mx"}, + {[]byte{0}, "Mx00"}, + {[]byte{0, 0, 1, 2}, "Mx00000102"}, + } + + encodeBigTests = []marshalTest{ + {referenceBig("0"), "Mx0"}, + {referenceBig("1"), "Mx1"}, + {referenceBig("ff"), "Mxff"}, + {referenceBig("112233445566778899aabbccddeeff"), "Mx112233445566778899aabbccddeeff"}, + {referenceBig("80a7f2c1bcc396c00"), "Mx80a7f2c1bcc396c00"}, + {referenceBig("-80a7f2c1bcc396c00"), "Mx-80a7f2c1bcc396c00"}, + } + + encodeUint64Tests = []marshalTest{ + {uint64(0), "Mx0"}, + {uint64(1), "Mx1"}, + {uint64(0xff), "Mxff"}, + {uint64(0x1122334455667788), "Mx1122334455667788"}, + } + + encodeUintTests = []marshalTest{ + {uint(0), "Mx0"}, + {uint(1), "Mx1"}, + {uint(0xff), "Mxff"}, + {uint(0x11223344), "Mx11223344"}, + } + + decodeBytesTests = []unmarshalTest{ + // invalid + {input: ``, wantErr: ErrEmptyString}, + {input: `0`, wantErr: ErrMissingPrefix}, + {input: `Mx0`, wantErr: ErrOddLength}, + {input: `Mx023`, wantErr: ErrOddLength}, + {input: `Mxxx`, wantErr: ErrSyntax}, + {input: `Mx01zz01`, wantErr: ErrSyntax}, + // valid + {input: `Mx`, want: []byte{}}, + {input: `MX`, want: []byte{}}, + {input: `Mx02`, want: []byte{0x02}}, + {input: `MX02`, want: []byte{0x02}}, + {input: `Mxffffffffff`, want: []byte{0xff, 0xff, 0xff, 0xff, 0xff}}, + { + input: `Mxffffffffffffffffffffffffffffffffffff`, + want: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + }, + } + + decodeBigTests = []unmarshalTest{ + // invalid + {input: `0`, wantErr: ErrMissingPrefix}, + {input: `Mx`, wantErr: ErrEmptyNumber}, + {input: `Mx01`, wantErr: ErrLeadingZero}, + {input: `Mxx`, wantErr: ErrSyntax}, + {input: `Mx1zz01`, wantErr: ErrSyntax}, + { + input: `Mx10000000000000000000000000000000000000000000000000000000000000000`, + wantErr: ErrBig256Range, + }, + // valid + {input: `Mx0`, want: big.NewInt(0)}, + {input: `Mx2`, want: big.NewInt(0x2)}, + {input: `Mx2F2`, want: big.NewInt(0x2f2)}, + {input: `MX2F2`, want: big.NewInt(0x2f2)}, + {input: `Mx1122aaff`, want: big.NewInt(0x1122aaff)}, + {input: `MxbBb`, want: big.NewInt(0xbbb)}, + {input: `Mxfffffffff`, want: big.NewInt(0xfffffffff)}, + { + input: `Mx112233445566778899aabbccddeeff`, + want: referenceBig("112233445566778899aabbccddeeff"), + }, + { + input: `Mxffffffffffffffffffffffffffffffffffff`, + want: referenceBig("ffffffffffffffffffffffffffffffffffff"), + }, + { + input: `Mxffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff`, + want: referenceBig("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + }, + } + + decodeUint64Tests = []unmarshalTest{ + // invalid + {input: `0`, wantErr: ErrMissingPrefix}, + {input: `Mx`, wantErr: ErrEmptyNumber}, + {input: `Mx01`, wantErr: ErrLeadingZero}, + {input: `Mxfffffffffffffffff`, wantErr: ErrUint64Range}, + {input: `Mxx`, wantErr: ErrSyntax}, + {input: `Mx1zz01`, wantErr: ErrSyntax}, + // valid + {input: `Mx0`, want: uint64(0)}, + {input: `Mx2`, want: uint64(0x2)}, + {input: `Mx2F2`, want: uint64(0x2f2)}, + {input: `MX2F2`, want: uint64(0x2f2)}, + {input: `Mx1122aaff`, want: uint64(0x1122aaff)}, + {input: `Mxbbb`, want: uint64(0xbbb)}, + {input: `Mxffffffffffffffff`, want: uint64(0xffffffffffffffff)}, + } +) + +func TestEncode(t *testing.T) { + for _, test := range encodeBytesTests { + enc := Encode(test.input.([]byte)) + if enc != test.want { + t.Errorf("input %x: wrong encoding %s", test.input, enc) + } + } +} + +func TestDecode(t *testing.T) { + for _, test := range decodeBytesTests { + dec, err := Decode(test.input) + if !checkError(t, test.input, err, test.wantErr) { + continue + } + if !bytes.Equal(test.want.([]byte), dec) { + t.Errorf("input %s: value mismatch: got %x, want %x", test.input, dec, test.want) + continue + } + } +} + +func TestEncodeBig(t *testing.T) { + for _, test := range encodeBigTests { + enc := EncodeBig(test.input.(*big.Int)) + if enc != test.want { + t.Errorf("input %x: wrong encoding %s", test.input, enc) + } + } +} + +func TestDecodeBig(t *testing.T) { + for _, test := range decodeBigTests { + dec, err := DecodeBig(test.input) + if !checkError(t, test.input, err, test.wantErr) { + continue + } + if dec.Cmp(test.want.(*big.Int)) != 0 { + t.Errorf("input %s: value mismatch: got %x, want %x", test.input, dec, test.want) + continue + } + } +} + +func TestEncodeUint64(t *testing.T) { + for _, test := range encodeUint64Tests { + enc := EncodeUint64(test.input.(uint64)) + if enc != test.want { + t.Errorf("input %x: wrong encoding %s", test.input, enc) + } + } +} + +func TestDecodeUint64(t *testing.T) { + for _, test := range decodeUint64Tests { + dec, err := DecodeUint64(test.input) + if !checkError(t, test.input, err, test.wantErr) { + continue + } + if dec != test.want.(uint64) { + t.Errorf("input %s: value mismatch: got %x, want %x", test.input, dec, test.want) + continue + } + } +} diff --git a/hexutil/json.go b/hexutil/json.go index 407cda9b6..618c4f32d 100644 --- a/hexutil/json.go +++ b/hexutil/json.go @@ -273,7 +273,7 @@ func isString(input []byte) bool { return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' } -func bytesHave0xPrefix(input []byte) bool { +func bytesHaveMxPrefix(input []byte) bool { return len(input) >= 2 && input[0] == 'M' && (input[1] == 'x' || input[1] == 'X') } @@ -281,7 +281,7 @@ func checkText(input []byte, wantPrefix bool) ([]byte, error) { if len(input) == 0 { return nil, nil // empty strings are allowed } - if bytesHave0xPrefix(input) { + if bytesHaveMxPrefix(input) { input = input[2:] } else if wantPrefix { return nil, ErrMissingPrefix @@ -296,7 +296,7 @@ func checkNumberText(input []byte) (raw []byte, err error) { if len(input) == 0 { return nil, nil // empty strings are allowed } - if !bytesHave0xPrefix(input) { + if !bytesHaveMxPrefix(input) { return nil, ErrMissingPrefix } input = input[2:] diff --git a/hexutil/json_test.go b/hexutil/json_test.go new file mode 100644 index 000000000..b7cbf67c5 --- /dev/null +++ b/hexutil/json_test.go @@ -0,0 +1,374 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package hexutil + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "errors" + "math/big" + "testing" +) + +func checkError(t *testing.T, input string, got, want error) bool { + if got == nil { + if want != nil { + t.Errorf("input %s: got no error, want %q", input, want) + return false + } + return true + } + if want == nil { + t.Errorf("input %s: unexpected error %q", input, got) + } else if got.Error() != want.Error() { + t.Errorf("input %s: got error %q, want %q", input, got, want) + } + return false +} + +func referenceBig(s string) *big.Int { + b, ok := new(big.Int).SetString(s, 16) + if !ok { + panic("invalid") + } + return b +} + +func referenceBytes(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return b +} + +var errJSONEOF = errors.New("unexpected end of JSON input") + +var unmarshalBytesTests = []unmarshalTest{ + // invalid encoding + {input: "", wantErr: errJSONEOF}, + {input: "null", wantErr: errNonString(bytesT)}, + {input: "10", wantErr: errNonString(bytesT)}, + {input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, bytesT)}, + {input: `"Mx0"`, wantErr: wrapTypeError(ErrOddLength, bytesT)}, + {input: `"Mxxx"`, wantErr: wrapTypeError(ErrSyntax, bytesT)}, + {input: `"Mx01zz01"`, wantErr: wrapTypeError(ErrSyntax, bytesT)}, + + // valid encoding + {input: `""`, want: referenceBytes("")}, + {input: `"Mx"`, want: referenceBytes("")}, + {input: `"Mx02"`, want: referenceBytes("02")}, + {input: `"MX02"`, want: referenceBytes("02")}, + {input: `"Mxffffffffff"`, want: referenceBytes("ffffffffff")}, + { + input: `"Mxffffffffffffffffffffffffffffffffffff"`, + want: referenceBytes("ffffffffffffffffffffffffffffffffffff"), + }, +} + +func TestUnmarshalBytes(t *testing.T) { + for _, test := range unmarshalBytesTests { + var v Bytes + err := json.Unmarshal([]byte(test.input), &v) + if !checkError(t, test.input, err, test.wantErr) { + continue + } + if !bytes.Equal(test.want.([]byte), []byte(v)) { + t.Errorf("input %s: value mismatch: got %x, want %x", test.input, &v, test.want) + continue + } + } +} + +func BenchmarkUnmarshalBytes(b *testing.B) { + input := []byte(`"Mx123456789abcdef123456789abcdef"`) + for i := 0; i < b.N; i++ { + var v Bytes + if err := v.UnmarshalJSON(input); err != nil { + b.Fatal(err) + } + } +} + +func TestMarshalBytes(t *testing.T) { + for _, test := range encodeBytesTests { + in := test.input.([]byte) + out, err := json.Marshal(Bytes(in)) + if err != nil { + t.Errorf("%x: %v", in, err) + continue + } + if want := `"` + test.want + `"`; string(out) != want { + t.Errorf("%x: MarshalJSON output mismatch: got %q, want %q", in, out, want) + continue + } + if out := Bytes(in).String(); out != test.want { + t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want) + continue + } + } +} + +var unmarshalBigTests = []unmarshalTest{ + // invalid encoding + {input: "", wantErr: errJSONEOF}, + {input: "null", wantErr: errNonString(bigT)}, + {input: "10", wantErr: errNonString(bigT)}, + {input: `"0"`, wantErr: wrapTypeError(ErrMissingPrefix, bigT)}, + {input: `"Mx"`, wantErr: wrapTypeError(ErrEmptyNumber, bigT)}, + {input: `"Mx01"`, wantErr: wrapTypeError(ErrLeadingZero, bigT)}, + {input: `"Mxx"`, wantErr: wrapTypeError(ErrSyntax, bigT)}, + {input: `"Mx1zz01"`, wantErr: wrapTypeError(ErrSyntax, bigT)}, + { + input: `"Mx10000000000000000000000000000000000000000000000000000000000000000"`, + wantErr: wrapTypeError(ErrBig256Range, bigT), + }, + + // valid encoding + {input: `""`, want: big.NewInt(0)}, + {input: `"Mx0"`, want: big.NewInt(0)}, + {input: `"Mx2"`, want: big.NewInt(0x2)}, + {input: `"Mx2F2"`, want: big.NewInt(0x2f2)}, + {input: `"MX2F2"`, want: big.NewInt(0x2f2)}, + {input: `"Mx1122aaff"`, want: big.NewInt(0x1122aaff)}, + {input: `"MxbBb"`, want: big.NewInt(0xbbb)}, + {input: `"Mxfffffffff"`, want: big.NewInt(0xfffffffff)}, + { + input: `"Mx112233445566778899aabbccddeeff"`, + want: referenceBig("112233445566778899aabbccddeeff"), + }, + { + input: `"Mxffffffffffffffffffffffffffffffffffff"`, + want: referenceBig("ffffffffffffffffffffffffffffffffffff"), + }, + { + input: `"Mxffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"`, + want: referenceBig("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + }, +} + +func TestUnmarshalBig(t *testing.T) { + for _, test := range unmarshalBigTests { + var v Big + err := json.Unmarshal([]byte(test.input), &v) + if !checkError(t, test.input, err, test.wantErr) { + continue + } + if test.want != nil && test.want.(*big.Int).Cmp((*big.Int)(&v)) != 0 { + t.Errorf("input %s: value mismatch: got %x, want %x", test.input, (*big.Int)(&v), test.want) + continue + } + } +} + +func BenchmarkUnmarshalBig(b *testing.B) { + input := []byte(`"Mx123456789abcdef123456789abcdef"`) + for i := 0; i < b.N; i++ { + var v Big + if err := v.UnmarshalJSON(input); err != nil { + b.Fatal(err) + } + } +} + +func TestMarshalBig(t *testing.T) { + for _, test := range encodeBigTests { + in := test.input.(*big.Int) + out, err := json.Marshal((*Big)(in)) + if err != nil { + t.Errorf("%d: %v", in, err) + continue + } + if want := `"` + test.want + `"`; string(out) != want { + t.Errorf("%d: MarshalJSON output mismatch: got %q, want %q", in, out, want) + continue + } + if out := (*Big)(in).String(); out != test.want { + t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want) + continue + } + } +} + +var unmarshalUint64Tests = []unmarshalTest{ + // invalid encoding + {input: "", wantErr: errJSONEOF}, + {input: "null", wantErr: errNonString(uint64T)}, + {input: "10", wantErr: errNonString(uint64T)}, + {input: `"M"`, wantErr: wrapTypeError(ErrMissingPrefix, uint64T)}, + {input: `"Mx"`, wantErr: wrapTypeError(ErrEmptyNumber, uint64T)}, + {input: `"Mx01"`, wantErr: wrapTypeError(ErrLeadingZero, uint64T)}, + {input: `"Mxfffffffffffffffff"`, wantErr: wrapTypeError(ErrUint64Range, uint64T)}, + {input: `"Mxx"`, wantErr: wrapTypeError(ErrSyntax, uint64T)}, + {input: `"Mx1zz01"`, wantErr: wrapTypeError(ErrSyntax, uint64T)}, + + // valid encoding + {input: `""`, want: uint64(0)}, + {input: `"Mx0"`, want: uint64(0)}, + {input: `"Mx2"`, want: uint64(0x2)}, + {input: `"Mx2F2"`, want: uint64(0x2f2)}, + {input: `"MX2F2"`, want: uint64(0x2f2)}, + {input: `"Mx1122aaff"`, want: uint64(0x1122aaff)}, + {input: `"Mxbbb"`, want: uint64(0xbbb)}, + {input: `"Mxffffffffffffffff"`, want: uint64(0xffffffffffffffff)}, +} + +func TestUnmarshalUint64(t *testing.T) { + for _, test := range unmarshalUint64Tests { + var v Uint64 + err := json.Unmarshal([]byte(test.input), &v) + if !checkError(t, test.input, err, test.wantErr) { + continue + } + if uint64(v) != test.want.(uint64) { + t.Errorf("input %s: value mismatch: got %d, want %d", test.input, v, test.want) + continue + } + } +} + +func BenchmarkUnmarshalUint64(b *testing.B) { + input := []byte(`"Mx123456789abcdf"`) + for i := 0; i < b.N; i++ { + var v Uint64 + v.UnmarshalJSON(input) + } +} + +func TestMarshalUint64(t *testing.T) { + for _, test := range encodeUint64Tests { + in := test.input.(uint64) + out, err := json.Marshal(Uint64(in)) + if err != nil { + t.Errorf("%d: %v", in, err) + continue + } + if want := `"` + test.want + `"`; string(out) != want { + t.Errorf("%d: MarshalJSON output mismatch: got %q, want %q", in, out, want) + continue + } + if out := (Uint64)(in).String(); out != test.want { + t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want) + continue + } + } +} + +func TestMarshalUint(t *testing.T) { + for _, test := range encodeUintTests { + in := test.input.(uint) + out, err := json.Marshal(Uint(in)) + if err != nil { + t.Errorf("%d: %v", in, err) + continue + } + if want := `"` + test.want + `"`; string(out) != want { + t.Errorf("%d: MarshalJSON output mismatch: got %q, want %q", in, out, want) + continue + } + if out := (Uint)(in).String(); out != test.want { + t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want) + continue + } + } +} + +var ( + // These are variables (not constants) to avoid constant overflow + // checks in the compiler on 32bit platforms. + maxUint33bits = uint64(^uint32(0)) + 1 + maxUint64bits = ^uint64(0) +) + +var unmarshalUintTests = []unmarshalTest{ + // invalid encoding + {input: "", wantErr: errJSONEOF}, + {input: "null", wantErr: errNonString(uintT)}, + {input: "10", wantErr: errNonString(uintT)}, + {input: `"M"`, wantErr: wrapTypeError(ErrMissingPrefix, uintT)}, + {input: `"Mx"`, wantErr: wrapTypeError(ErrEmptyNumber, uintT)}, + {input: `"Mx01"`, wantErr: wrapTypeError(ErrLeadingZero, uintT)}, + {input: `"Mx100000000"`, want: uint(maxUint33bits), wantErr32bit: wrapTypeError(ErrUintRange, uintT)}, + {input: `"Mxfffffffffffffffff"`, wantErr: wrapTypeError(ErrUintRange, uintT)}, + {input: `"Mxx"`, wantErr: wrapTypeError(ErrSyntax, uintT)}, + {input: `"Mx1zz01"`, wantErr: wrapTypeError(ErrSyntax, uintT)}, + + // valid encoding + {input: `""`, want: uint(0)}, + {input: `"Mx0"`, want: uint(0)}, + {input: `"Mx2"`, want: uint(0x2)}, + {input: `"Mx2F2"`, want: uint(0x2f2)}, + {input: `"MX2F2"`, want: uint(0x2f2)}, + {input: `"Mx1122aaff"`, want: uint(0x1122aaff)}, + {input: `"Mxbbb"`, want: uint(0xbbb)}, + {input: `"Mxffffffff"`, want: uint(0xffffffff)}, + {input: `"Mxffffffffffffffff"`, want: uint(maxUint64bits), wantErr32bit: wrapTypeError(ErrUintRange, uintT)}, +} + +func TestUnmarshalUint(t *testing.T) { + for _, test := range unmarshalUintTests { + var v Uint + err := json.Unmarshal([]byte(test.input), &v) + if uintBits == 32 && test.wantErr32bit != nil { + checkError(t, test.input, err, test.wantErr32bit) + continue + } + if !checkError(t, test.input, err, test.wantErr) { + continue + } + if uint(v) != test.want.(uint) { + t.Errorf("input %s: value mismatch: got %d, want %d", test.input, v, test.want) + continue + } + } +} + +func TestUnmarshalFixedUnprefixedText(t *testing.T) { + tests := []struct { + input string + want []byte + wantErr error + }{ + {input: "0x2", wantErr: ErrOddLength}, + {input: "2", wantErr: ErrOddLength}, + {input: "4444", wantErr: errors.New("hex string has length 4, want 8 for x")}, + {input: "4444", wantErr: errors.New("hex string has length 4, want 8 for x")}, + // check that output is not modified for partially correct input + {input: "444444gg", wantErr: ErrSyntax, want: []byte{0, 0, 0, 0}}, + {input: "Mx444444gg", wantErr: ErrSyntax, want: []byte{0, 0, 0, 0}}, + // valid inputs + {input: "44444444", want: []byte{0x44, 0x44, 0x44, 0x44}}, + {input: "Mx44444444", want: []byte{0x44, 0x44, 0x44, 0x44}}, + } + + for _, test := range tests { + out := make([]byte, 4) + err := UnmarshalFixedUnprefixedText("x", []byte(test.input), out) + switch { + case err == nil && test.wantErr != nil: + t.Errorf("%q: got no error, expected %q", test.input, test.wantErr) + case err != nil && test.wantErr == nil: + t.Errorf("%q: unexpected error %q", test.input, err) + case err != nil && err.Error() != test.wantErr.Error(): + t.Errorf("%q: error mismatch: got %q, want %q", test.input, err, test.wantErr) + } + if test.want != nil && !bytes.Equal(out, test.want) { + t.Errorf("%q: output mismatch: got %x, want %x", test.input, out, test.want) + } + } +} From 95d6d89c71e6460799368440c06466edc63d7b91 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 16 Sep 2020 14:00:02 +0300 Subject: [PATCH 275/426] Add more tests --- formula/formula_test.go | 80 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 3 deletions(-) diff --git a/formula/formula_test.go b/formula/formula_test.go index 50f054aa7..8407c3793 100644 --- a/formula/formula_test.go +++ b/formula/formula_test.go @@ -14,7 +14,6 @@ type PurchaseReturnData struct { } func TestCalculatePurchaseReturn(t *testing.T) { - data := []PurchaseReturnData{ { Supply: big.NewInt(1000000), @@ -30,6 +29,13 @@ func TestCalculatePurchaseReturn(t *testing.T) { Deposit: big.NewInt(100), Result: big.NewInt(1000000), }, + { + Supply: big.NewInt(1000000), + Reserve: big.NewInt(100), + Crr: 100, + Deposit: big.NewInt(0), + Result: big.NewInt(0), + }, } for _, item := range data { @@ -41,6 +47,48 @@ func TestCalculatePurchaseReturn(t *testing.T) { } } +type PurchaseAmountData struct { + Supply *big.Int + Reserve *big.Int + Crr uint + WantReceive *big.Int + Deposit *big.Int +} + +func TestCalculatePurchaseAmount(t *testing.T) { + data := []PurchaseAmountData{ + { + Supply: big.NewInt(1000000), + Reserve: big.NewInt(1000000), + Crr: 40, + WantReceive: big.NewInt(100), + Deposit: big.NewInt(250), + }, + { + Supply: big.NewInt(1000000), + Reserve: big.NewInt(1000000), + Crr: 100, + WantReceive: big.NewInt(100), + Deposit: big.NewInt(100), + }, + { + Supply: big.NewInt(1000000), + Reserve: big.NewInt(1000000), + Crr: 100, + WantReceive: big.NewInt(0), + Deposit: big.NewInt(0), + }, + } + + for _, item := range data { + deposit := CalculatePurchaseAmount(item.Supply, item.Reserve, item.Crr, item.WantReceive) + + if deposit.Cmp(item.Deposit) != 0 { + t.Errorf("CalculatePurchaseAmount Deposit is not correct. Expected %s, got %s", item.Deposit, deposit) + } + } +} + type CalculateSaleReturnData struct { Supply *big.Int Reserve *big.Int @@ -50,7 +98,6 @@ type CalculateSaleReturnData struct { } func TestCalculateSaleReturn(t *testing.T) { - data := []CalculateSaleReturnData{ { Supply: big.NewInt(1000000), @@ -66,6 +113,20 @@ func TestCalculateSaleReturn(t *testing.T) { SellAmount: big.NewInt(100000), Result: big.NewInt(65), }, + { + Supply: big.NewInt(1000000), + Reserve: big.NewInt(100), + Crr: 10, + SellAmount: big.NewInt(0), + Result: big.NewInt(0), + }, + { + Supply: big.NewInt(1000000), + Reserve: big.NewInt(1000000), + Crr: 100, + SellAmount: big.NewInt(100), + Result: big.NewInt(100), + }, } for _, item := range data { @@ -86,7 +147,6 @@ type CalculateBuyDepositData struct { } func TestCalculateBuyDeposit(t *testing.T) { - data := []CalculateBuyDepositData{ { Supply: big.NewInt(1000000), @@ -102,6 +162,20 @@ func TestCalculateBuyDeposit(t *testing.T) { WantReceive: big.NewInt(100), Result: big.NewInt(1000000), }, + { + Supply: big.NewInt(1000000), + Reserve: big.NewInt(1000000), + Crr: 100, + WantReceive: big.NewInt(100), + Result: big.NewInt(100), + }, + { + Supply: big.NewInt(1000000), + Reserve: big.NewInt(1000000), + Crr: 100, + WantReceive: big.NewInt(0), + Result: big.NewInt(0), + }, } for _, item := range data { From f085299fc5152c55b939b7f504c9a64f248fc411 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 16 Sep 2020 15:17:12 +0300 Subject: [PATCH 276/426] Refactor --- core/check/check.go | 4 +- core/transaction/redeem_check.go | 4 +- core/transaction/redeem_check_test.go | 24 +- core/transaction/transaction.go | 4 +- crypto/sha3/LICENSE | 27 -- crypto/sha3/PATENTS | 22 -- crypto/sha3/doc.go | 66 ----- crypto/sha3/hashes.go | 71 ----- crypto/sha3/keccakf.go | 412 -------------------------- crypto/sha3/keccakf_amd64.go | 13 - crypto/sha3/keccakf_amd64.s | 390 ------------------------ crypto/sha3/register.go | 18 -- crypto/sha3/sha3.go | 192 ------------ crypto/sha3/shake.go | 60 ---- crypto/sha3/xor.go | 14 - crypto/sha3/xor_unaligned.go | 56 ---- 16 files changed, 18 insertions(+), 1359 deletions(-) delete mode 100644 crypto/sha3/LICENSE delete mode 100644 crypto/sha3/PATENTS delete mode 100644 crypto/sha3/doc.go delete mode 100644 crypto/sha3/hashes.go delete mode 100644 crypto/sha3/keccakf.go delete mode 100644 crypto/sha3/keccakf_amd64.go delete mode 100644 crypto/sha3/keccakf_amd64.s delete mode 100644 crypto/sha3/register.go delete mode 100644 crypto/sha3/sha3.go delete mode 100644 crypto/sha3/shake.go delete mode 100644 crypto/sha3/xor.go delete mode 100644 crypto/sha3/xor_unaligned.go diff --git a/core/check/check.go b/core/check/check.go index 2eaedc81d..15940ee98 100644 --- a/core/check/check.go +++ b/core/check/check.go @@ -7,8 +7,8 @@ import ( "fmt" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" - "github.com/MinterTeam/minter-go-node/crypto/sha3" "github.com/MinterTeam/minter-go-node/rlp" + "golang.org/x/crypto/sha3" "math/big" ) @@ -134,7 +134,7 @@ func DecodeFromBytes(buf []byte) (*Check, error) { } func rlpHash(x interface{}) (h types.Hash) { - hw := sha3.NewKeccak256() + hw := sha3.NewLegacyKeccak256() err := rlp.Encode(hw, x) if err != nil { panic(err) diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index 2ac2f068f..f790d63f5 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -13,10 +13,10 @@ import ( "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" - "github.com/MinterTeam/minter-go-node/crypto/sha3" "github.com/MinterTeam/minter-go-node/formula" "github.com/MinterTeam/minter-go-node/rlp" "github.com/tendermint/tendermint/libs/kv" + "golang.org/x/crypto/sha3" ) type RedeemCheckData struct { @@ -153,7 +153,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward } var senderAddressHash types.Hash - hw := sha3.NewKeccak256() + hw := sha3.NewLegacyKeccak256() _ = rlp.Encode(hw, []interface{}{ sender, }) diff --git a/core/transaction/redeem_check_test.go b/core/transaction/redeem_check_test.go index f18f8e6cb..a08fd6804 100644 --- a/core/transaction/redeem_check_test.go +++ b/core/transaction/redeem_check_test.go @@ -11,9 +11,9 @@ import ( "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" - "github.com/MinterTeam/minter-go-node/crypto/sha3" "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/rlp" + "golang.org/x/crypto/sha3" ) func TestRedeemCheckTx(t *testing.T) { @@ -63,7 +63,7 @@ func TestRedeemCheckTx(t *testing.T) { rawCheck, _ := rlp.EncodeToBytes(check) var senderAddressHash types.Hash - hw := sha3.NewKeccak256() + hw := sha3.NewLegacyKeccak256() _ = rlp.Encode(hw, []interface{}{ receiverAddr, }) @@ -165,7 +165,7 @@ func TestRedeemCheckTxToDecodeError(t *testing.T) { } var senderAddressHash types.Hash - hw := sha3.NewKeccak256() + hw := sha3.NewLegacyKeccak256() _ = rlp.Encode(hw, []interface{}{ receiverAddr, }) @@ -270,7 +270,7 @@ func TestRedeemCheckTxToHighGasPrice(t *testing.T) { rawCheck, _ := rlp.EncodeToBytes(check) var senderAddressHash types.Hash - hw := sha3.NewKeccak256() + hw := sha3.NewLegacyKeccak256() _ = rlp.Encode(hw, []interface{}{ receiverAddr, }) @@ -364,7 +364,7 @@ func TestRedeemCheckTxToWrongChainID(t *testing.T) { rawCheck, _ := rlp.EncodeToBytes(check) var senderAddressHash types.Hash - hw := sha3.NewKeccak256() + hw := sha3.NewLegacyKeccak256() _ = rlp.Encode(hw, []interface{}{ receiverAddr, }) @@ -458,7 +458,7 @@ func TestRedeemCheckTxToNonceLength(t *testing.T) { rawCheck, _ := rlp.EncodeToBytes(check) var senderAddressHash types.Hash - hw := sha3.NewKeccak256() + hw := sha3.NewLegacyKeccak256() _ = rlp.Encode(hw, []interface{}{ receiverAddr, }) @@ -552,7 +552,7 @@ func TestRedeemCheckTxToCheckData(t *testing.T) { rawCheck, _ := rlp.EncodeToBytes(check) var senderAddressHash types.Hash - hw := sha3.NewKeccak256() + hw := sha3.NewLegacyKeccak256() _ = rlp.Encode(hw, []interface{}{ receiverAddr, }) @@ -758,7 +758,7 @@ func TestRedeemCheckTxToUsed(t *testing.T) { cState.Checks.UseCheck(&check) var senderAddressHash types.Hash - hw := sha3.NewKeccak256() + hw := sha3.NewLegacyKeccak256() _ = rlp.Encode(hw, []interface{}{ receiverAddr, }) @@ -850,7 +850,7 @@ func TestRedeemCheckTxToInsufficientFunds(t *testing.T) { rawCheck, _ := rlp.EncodeToBytes(check) var senderAddressHash types.Hash - hw := sha3.NewKeccak256() + hw := sha3.NewLegacyKeccak256() _ = rlp.Encode(hw, []interface{}{ receiverAddr, }) @@ -943,7 +943,7 @@ func TestRedeemCheckTxToCoinReserveUnderflow(t *testing.T) { rawCheck, _ := rlp.EncodeToBytes(check) var senderAddressHash types.Hash - hw := sha3.NewKeccak256() + hw := sha3.NewLegacyKeccak256() _ = rlp.Encode(hw, []interface{}{ receiverAddr, }) @@ -1035,7 +1035,7 @@ func TestRedeemCheckTxToInsufficientFundsForCheckCoin(t *testing.T) { rawCheck, _ := rlp.EncodeToBytes(check) var senderAddressHash types.Hash - hw := sha3.NewKeccak256() + hw := sha3.NewLegacyKeccak256() _ = rlp.Encode(hw, []interface{}{ receiverAddr, }) @@ -1129,7 +1129,7 @@ func TestRedeemCheckTxToInsufficientFundsForCheckGasCoin(t *testing.T) { rawCheck, _ := rlp.EncodeToBytes(check) var senderAddressHash types.Hash - hw := sha3.NewKeccak256() + hw := sha3.NewLegacyKeccak256() _ = rlp.Encode(hw, []interface{}{ receiverAddr, }) diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index 36b8b98db..5d49e5f95 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -10,8 +10,8 @@ import ( "github.com/MinterTeam/minter-go-node/core/state/coins" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" - "github.com/MinterTeam/minter-go-node/crypto/sha3" "github.com/MinterTeam/minter-go-node/rlp" + "golang.org/x/crypto/sha3" "math/big" ) @@ -291,7 +291,7 @@ func RecoverPlain(sighash types.Hash, R, S, Vb *big.Int) (types.Address, error) } func rlpHash(x interface{}) (h types.Hash) { - hw := sha3.NewKeccak256() + hw := sha3.NewLegacyKeccak256() err := rlp.Encode(hw, x) if err != nil { panic(err) diff --git a/crypto/sha3/LICENSE b/crypto/sha3/LICENSE deleted file mode 100644 index 6a66aea5e..000000000 --- a/crypto/sha3/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/crypto/sha3/PATENTS b/crypto/sha3/PATENTS deleted file mode 100644 index 733099041..000000000 --- a/crypto/sha3/PATENTS +++ /dev/null @@ -1,22 +0,0 @@ -Additional IP Rights Grant (Patents) - -"This implementation" means the copyrightable works distributed by -Google as part of the Go project. - -Google hereby grants to You a perpetual, worldwide, non-exclusive, -no-charge, royalty-free, irrevocable (except as stated in this section) -patent license to make, have made, use, offer to sell, sell, import, -transfer and otherwise run, modify and propagate the contents of this -implementation of Go, where such license applies only to those patent -claims, both currently owned or controlled by Google and acquired in -the future, licensable by Google that are necessarily infringed by this -implementation of Go. This grant does not include claims that would be -infringed only as a consequence of further modification of this -implementation. If you or your agent or exclusive licensee institute or -order or agree to the institution of patent litigation against any -entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of Go or any code incorporated within this -implementation of Go constitutes direct or contributory patent -infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of Go -shall terminate as of the date such litigation is filed. diff --git a/crypto/sha3/doc.go b/crypto/sha3/doc.go deleted file mode 100644 index 3dab530f8..000000000 --- a/crypto/sha3/doc.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package sha3 implements the SHA-3 fixed-output-length hash functions and -// the SHAKE variable-output-length hash functions defined by FIPS-202. -// -// Both types of hash function use the "sponge" construction and the Keccak -// permutation. For a detailed specification see http://keccak.noekeon.org/ -// -// -// Guidance -// -// If you aren't sure what function you need, use SHAKE256 with at least 64 -// bytes of output. The SHAKE instances are faster than the SHA3 instances; -// the latter have to allocate memory to conform to the hash.Hash interface. -// -// If you need a secret-key MAC (message authentication code), prepend the -// secret key to the input, hash with SHAKE256 and read at least 32 bytes of -// output. -// -// -// Security strengths -// -// The SHA3-x (x equals 224, 256, 384, or 512) functions have a security -// strength against preimage attacks of x bits. Since they only produce "x" -// bits of output, their collision-resistance is only "x/2" bits. -// -// The SHAKE-256 and -128 functions have a generic security strength of 256 and -// 128 bits against all attacks, provided that at least 2x bits of their output -// is used. Requesting more than 64 or 32 bytes of output, respectively, does -// not increase the collision-resistance of the SHAKE functions. -// -// -// The sponge construction -// -// A sponge builds a pseudo-random function from a public pseudo-random -// permutation, by applying the permutation to a state of "rate + capacity" -// bytes, but hiding "capacity" of the bytes. -// -// A sponge starts out with a zero state. To hash an input using a sponge, up -// to "rate" bytes of the input are XORed into the sponge's state. The sponge -// is then "full" and the permutation is applied to "empty" it. This process is -// repeated until all the input has been "absorbed". The input is then padded. -// The digest is "squeezed" from the sponge in the same way, except that output -// output is copied out instead of input being XORed in. -// -// A sponge is parameterized by its generic security strength, which is equal -// to half its capacity; capacity + rate is equal to the permutation's width. -// Since the KeccakF-1600 permutation is 1600 bits (200 bytes) wide, this means -// that the security strength of a sponge instance is equal to (1600 - bitrate) / 2. -// -// -// Recommendations -// -// The SHAKE functions are recommended for most new uses. They can produce -// output of arbitrary length. SHAKE256, with an output length of at least -// 64 bytes, provides 256-bit security against all attacks. The Keccak team -// recommends it for most applications upgrading from SHA2-512. (NIST chose a -// much stronger, but much slower, sponge instance for SHA3-512.) -// -// The SHA-3 functions are "drop-in" replacements for the SHA-2 functions. -// They produce output of the same length, with the same security strengths -// against all attacks. This means, in particular, that SHA3-256 only has -// 128-bit collision resistance, because its output length is 32 bytes. -package sha3 diff --git a/crypto/sha3/hashes.go b/crypto/sha3/hashes.go deleted file mode 100644 index fa0d7b436..000000000 --- a/crypto/sha3/hashes.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package sha3 - -// This file provides functions for creating instances of the SHA-3 -// and SHAKE hash functions, as well as utility functions for hashing -// bytes. - -import ( - "hash" -) - -// NewKeccak256 creates a new Keccak-256 hash. -func NewKeccak256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x01} } - -// NewKeccak512 creates a new Keccak-512 hash. -func NewKeccak512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x01} } - -// New224 creates a new SHA3-224 hash. -// Its generic security strength is 224 bits against preimage attacks, -// and 112 bits against collision attacks. -func New224() hash.Hash { return &state{rate: 144, outputLen: 28, dsbyte: 0x06} } - -// New256 creates a new SHA3-256 hash. -// Its generic security strength is 256 bits against preimage attacks, -// and 128 bits against collision attacks. -func New256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x06} } - -// New384 creates a new SHA3-384 hash. -// Its generic security strength is 384 bits against preimage attacks, -// and 192 bits against collision attacks. -func New384() hash.Hash { return &state{rate: 104, outputLen: 48, dsbyte: 0x06} } - -// New512 creates a new SHA3-512 hash. -// Its generic security strength is 512 bits against preimage attacks, -// and 256 bits against collision attacks. -func New512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x06} } - -// Sum224 returns the SHA3-224 digest of the data. -func Sum224(data []byte) (digest [28]byte) { - h := New224() - h.Write(data) - h.Sum(digest[:0]) - return -} - -// Sum256 returns the SHA3-256 digest of the data. -func Sum256(data []byte) (digest [32]byte) { - h := New256() - h.Write(data) - h.Sum(digest[:0]) - return -} - -// Sum384 returns the SHA3-384 digest of the data. -func Sum384(data []byte) (digest [48]byte) { - h := New384() - h.Write(data) - h.Sum(digest[:0]) - return -} - -// Sum512 returns the SHA3-512 digest of the data. -func Sum512(data []byte) (digest [64]byte) { - h := New512() - h.Write(data) - h.Sum(digest[:0]) - return -} diff --git a/crypto/sha3/keccakf.go b/crypto/sha3/keccakf.go deleted file mode 100644 index 46d03ed38..000000000 --- a/crypto/sha3/keccakf.go +++ /dev/null @@ -1,412 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !amd64 appengine gccgo - -package sha3 - -// rc stores the round constants for use in the ι step. -var rc = [24]uint64{ - 0x0000000000000001, - 0x0000000000008082, - 0x800000000000808A, - 0x8000000080008000, - 0x000000000000808B, - 0x0000000080000001, - 0x8000000080008081, - 0x8000000000008009, - 0x000000000000008A, - 0x0000000000000088, - 0x0000000080008009, - 0x000000008000000A, - 0x000000008000808B, - 0x800000000000008B, - 0x8000000000008089, - 0x8000000000008003, - 0x8000000000008002, - 0x8000000000000080, - 0x000000000000800A, - 0x800000008000000A, - 0x8000000080008081, - 0x8000000000008080, - 0x0000000080000001, - 0x8000000080008008, -} - -// keccakF1600 applies the Keccak permutation to a 1600b-wide -// state represented as a slice of 25 uint64s. -func keccakF1600(a *[25]uint64) { - // Implementation translated from Keccak-inplace.c - // in the keccak reference code. - var t, bc0, bc1, bc2, bc3, bc4, d0, d1, d2, d3, d4 uint64 - - for i := 0; i < 24; i += 4 { - // Combines the 5 steps in each round into 2 steps. - // Unrolls 4 rounds per loop and spreads some steps across rounds. - - // Round 1 - bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] - bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] - bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] - bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] - bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] - d0 = bc4 ^ (bc1<<1 | bc1>>63) - d1 = bc0 ^ (bc2<<1 | bc2>>63) - d2 = bc1 ^ (bc3<<1 | bc3>>63) - d3 = bc2 ^ (bc4<<1 | bc4>>63) - d4 = bc3 ^ (bc0<<1 | bc0>>63) - - bc0 = a[0] ^ d0 - t = a[6] ^ d1 - bc1 = t<<44 | t>>(64-44) - t = a[12] ^ d2 - bc2 = t<<43 | t>>(64-43) - t = a[18] ^ d3 - bc3 = t<<21 | t>>(64-21) - t = a[24] ^ d4 - bc4 = t<<14 | t>>(64-14) - a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i] - a[6] = bc1 ^ (bc3 &^ bc2) - a[12] = bc2 ^ (bc4 &^ bc3) - a[18] = bc3 ^ (bc0 &^ bc4) - a[24] = bc4 ^ (bc1 &^ bc0) - - t = a[10] ^ d0 - bc2 = t<<3 | t>>(64-3) - t = a[16] ^ d1 - bc3 = t<<45 | t>>(64-45) - t = a[22] ^ d2 - bc4 = t<<61 | t>>(64-61) - t = a[3] ^ d3 - bc0 = t<<28 | t>>(64-28) - t = a[9] ^ d4 - bc1 = t<<20 | t>>(64-20) - a[10] = bc0 ^ (bc2 &^ bc1) - a[16] = bc1 ^ (bc3 &^ bc2) - a[22] = bc2 ^ (bc4 &^ bc3) - a[3] = bc3 ^ (bc0 &^ bc4) - a[9] = bc4 ^ (bc1 &^ bc0) - - t = a[20] ^ d0 - bc4 = t<<18 | t>>(64-18) - t = a[1] ^ d1 - bc0 = t<<1 | t>>(64-1) - t = a[7] ^ d2 - bc1 = t<<6 | t>>(64-6) - t = a[13] ^ d3 - bc2 = t<<25 | t>>(64-25) - t = a[19] ^ d4 - bc3 = t<<8 | t>>(64-8) - a[20] = bc0 ^ (bc2 &^ bc1) - a[1] = bc1 ^ (bc3 &^ bc2) - a[7] = bc2 ^ (bc4 &^ bc3) - a[13] = bc3 ^ (bc0 &^ bc4) - a[19] = bc4 ^ (bc1 &^ bc0) - - t = a[5] ^ d0 - bc1 = t<<36 | t>>(64-36) - t = a[11] ^ d1 - bc2 = t<<10 | t>>(64-10) - t = a[17] ^ d2 - bc3 = t<<15 | t>>(64-15) - t = a[23] ^ d3 - bc4 = t<<56 | t>>(64-56) - t = a[4] ^ d4 - bc0 = t<<27 | t>>(64-27) - a[5] = bc0 ^ (bc2 &^ bc1) - a[11] = bc1 ^ (bc3 &^ bc2) - a[17] = bc2 ^ (bc4 &^ bc3) - a[23] = bc3 ^ (bc0 &^ bc4) - a[4] = bc4 ^ (bc1 &^ bc0) - - t = a[15] ^ d0 - bc3 = t<<41 | t>>(64-41) - t = a[21] ^ d1 - bc4 = t<<2 | t>>(64-2) - t = a[2] ^ d2 - bc0 = t<<62 | t>>(64-62) - t = a[8] ^ d3 - bc1 = t<<55 | t>>(64-55) - t = a[14] ^ d4 - bc2 = t<<39 | t>>(64-39) - a[15] = bc0 ^ (bc2 &^ bc1) - a[21] = bc1 ^ (bc3 &^ bc2) - a[2] = bc2 ^ (bc4 &^ bc3) - a[8] = bc3 ^ (bc0 &^ bc4) - a[14] = bc4 ^ (bc1 &^ bc0) - - // Round 2 - bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] - bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] - bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] - bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] - bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] - d0 = bc4 ^ (bc1<<1 | bc1>>63) - d1 = bc0 ^ (bc2<<1 | bc2>>63) - d2 = bc1 ^ (bc3<<1 | bc3>>63) - d3 = bc2 ^ (bc4<<1 | bc4>>63) - d4 = bc3 ^ (bc0<<1 | bc0>>63) - - bc0 = a[0] ^ d0 - t = a[16] ^ d1 - bc1 = t<<44 | t>>(64-44) - t = a[7] ^ d2 - bc2 = t<<43 | t>>(64-43) - t = a[23] ^ d3 - bc3 = t<<21 | t>>(64-21) - t = a[14] ^ d4 - bc4 = t<<14 | t>>(64-14) - a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+1] - a[16] = bc1 ^ (bc3 &^ bc2) - a[7] = bc2 ^ (bc4 &^ bc3) - a[23] = bc3 ^ (bc0 &^ bc4) - a[14] = bc4 ^ (bc1 &^ bc0) - - t = a[20] ^ d0 - bc2 = t<<3 | t>>(64-3) - t = a[11] ^ d1 - bc3 = t<<45 | t>>(64-45) - t = a[2] ^ d2 - bc4 = t<<61 | t>>(64-61) - t = a[18] ^ d3 - bc0 = t<<28 | t>>(64-28) - t = a[9] ^ d4 - bc1 = t<<20 | t>>(64-20) - a[20] = bc0 ^ (bc2 &^ bc1) - a[11] = bc1 ^ (bc3 &^ bc2) - a[2] = bc2 ^ (bc4 &^ bc3) - a[18] = bc3 ^ (bc0 &^ bc4) - a[9] = bc4 ^ (bc1 &^ bc0) - - t = a[15] ^ d0 - bc4 = t<<18 | t>>(64-18) - t = a[6] ^ d1 - bc0 = t<<1 | t>>(64-1) - t = a[22] ^ d2 - bc1 = t<<6 | t>>(64-6) - t = a[13] ^ d3 - bc2 = t<<25 | t>>(64-25) - t = a[4] ^ d4 - bc3 = t<<8 | t>>(64-8) - a[15] = bc0 ^ (bc2 &^ bc1) - a[6] = bc1 ^ (bc3 &^ bc2) - a[22] = bc2 ^ (bc4 &^ bc3) - a[13] = bc3 ^ (bc0 &^ bc4) - a[4] = bc4 ^ (bc1 &^ bc0) - - t = a[10] ^ d0 - bc1 = t<<36 | t>>(64-36) - t = a[1] ^ d1 - bc2 = t<<10 | t>>(64-10) - t = a[17] ^ d2 - bc3 = t<<15 | t>>(64-15) - t = a[8] ^ d3 - bc4 = t<<56 | t>>(64-56) - t = a[24] ^ d4 - bc0 = t<<27 | t>>(64-27) - a[10] = bc0 ^ (bc2 &^ bc1) - a[1] = bc1 ^ (bc3 &^ bc2) - a[17] = bc2 ^ (bc4 &^ bc3) - a[8] = bc3 ^ (bc0 &^ bc4) - a[24] = bc4 ^ (bc1 &^ bc0) - - t = a[5] ^ d0 - bc3 = t<<41 | t>>(64-41) - t = a[21] ^ d1 - bc4 = t<<2 | t>>(64-2) - t = a[12] ^ d2 - bc0 = t<<62 | t>>(64-62) - t = a[3] ^ d3 - bc1 = t<<55 | t>>(64-55) - t = a[19] ^ d4 - bc2 = t<<39 | t>>(64-39) - a[5] = bc0 ^ (bc2 &^ bc1) - a[21] = bc1 ^ (bc3 &^ bc2) - a[12] = bc2 ^ (bc4 &^ bc3) - a[3] = bc3 ^ (bc0 &^ bc4) - a[19] = bc4 ^ (bc1 &^ bc0) - - // Round 3 - bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] - bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] - bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] - bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] - bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] - d0 = bc4 ^ (bc1<<1 | bc1>>63) - d1 = bc0 ^ (bc2<<1 | bc2>>63) - d2 = bc1 ^ (bc3<<1 | bc3>>63) - d3 = bc2 ^ (bc4<<1 | bc4>>63) - d4 = bc3 ^ (bc0<<1 | bc0>>63) - - bc0 = a[0] ^ d0 - t = a[11] ^ d1 - bc1 = t<<44 | t>>(64-44) - t = a[22] ^ d2 - bc2 = t<<43 | t>>(64-43) - t = a[8] ^ d3 - bc3 = t<<21 | t>>(64-21) - t = a[19] ^ d4 - bc4 = t<<14 | t>>(64-14) - a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+2] - a[11] = bc1 ^ (bc3 &^ bc2) - a[22] = bc2 ^ (bc4 &^ bc3) - a[8] = bc3 ^ (bc0 &^ bc4) - a[19] = bc4 ^ (bc1 &^ bc0) - - t = a[15] ^ d0 - bc2 = t<<3 | t>>(64-3) - t = a[1] ^ d1 - bc3 = t<<45 | t>>(64-45) - t = a[12] ^ d2 - bc4 = t<<61 | t>>(64-61) - t = a[23] ^ d3 - bc0 = t<<28 | t>>(64-28) - t = a[9] ^ d4 - bc1 = t<<20 | t>>(64-20) - a[15] = bc0 ^ (bc2 &^ bc1) - a[1] = bc1 ^ (bc3 &^ bc2) - a[12] = bc2 ^ (bc4 &^ bc3) - a[23] = bc3 ^ (bc0 &^ bc4) - a[9] = bc4 ^ (bc1 &^ bc0) - - t = a[5] ^ d0 - bc4 = t<<18 | t>>(64-18) - t = a[16] ^ d1 - bc0 = t<<1 | t>>(64-1) - t = a[2] ^ d2 - bc1 = t<<6 | t>>(64-6) - t = a[13] ^ d3 - bc2 = t<<25 | t>>(64-25) - t = a[24] ^ d4 - bc3 = t<<8 | t>>(64-8) - a[5] = bc0 ^ (bc2 &^ bc1) - a[16] = bc1 ^ (bc3 &^ bc2) - a[2] = bc2 ^ (bc4 &^ bc3) - a[13] = bc3 ^ (bc0 &^ bc4) - a[24] = bc4 ^ (bc1 &^ bc0) - - t = a[20] ^ d0 - bc1 = t<<36 | t>>(64-36) - t = a[6] ^ d1 - bc2 = t<<10 | t>>(64-10) - t = a[17] ^ d2 - bc3 = t<<15 | t>>(64-15) - t = a[3] ^ d3 - bc4 = t<<56 | t>>(64-56) - t = a[14] ^ d4 - bc0 = t<<27 | t>>(64-27) - a[20] = bc0 ^ (bc2 &^ bc1) - a[6] = bc1 ^ (bc3 &^ bc2) - a[17] = bc2 ^ (bc4 &^ bc3) - a[3] = bc3 ^ (bc0 &^ bc4) - a[14] = bc4 ^ (bc1 &^ bc0) - - t = a[10] ^ d0 - bc3 = t<<41 | t>>(64-41) - t = a[21] ^ d1 - bc4 = t<<2 | t>>(64-2) - t = a[7] ^ d2 - bc0 = t<<62 | t>>(64-62) - t = a[18] ^ d3 - bc1 = t<<55 | t>>(64-55) - t = a[4] ^ d4 - bc2 = t<<39 | t>>(64-39) - a[10] = bc0 ^ (bc2 &^ bc1) - a[21] = bc1 ^ (bc3 &^ bc2) - a[7] = bc2 ^ (bc4 &^ bc3) - a[18] = bc3 ^ (bc0 &^ bc4) - a[4] = bc4 ^ (bc1 &^ bc0) - - // Round 4 - bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] - bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] - bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] - bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] - bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] - d0 = bc4 ^ (bc1<<1 | bc1>>63) - d1 = bc0 ^ (bc2<<1 | bc2>>63) - d2 = bc1 ^ (bc3<<1 | bc3>>63) - d3 = bc2 ^ (bc4<<1 | bc4>>63) - d4 = bc3 ^ (bc0<<1 | bc0>>63) - - bc0 = a[0] ^ d0 - t = a[1] ^ d1 - bc1 = t<<44 | t>>(64-44) - t = a[2] ^ d2 - bc2 = t<<43 | t>>(64-43) - t = a[3] ^ d3 - bc3 = t<<21 | t>>(64-21) - t = a[4] ^ d4 - bc4 = t<<14 | t>>(64-14) - a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+3] - a[1] = bc1 ^ (bc3 &^ bc2) - a[2] = bc2 ^ (bc4 &^ bc3) - a[3] = bc3 ^ (bc0 &^ bc4) - a[4] = bc4 ^ (bc1 &^ bc0) - - t = a[5] ^ d0 - bc2 = t<<3 | t>>(64-3) - t = a[6] ^ d1 - bc3 = t<<45 | t>>(64-45) - t = a[7] ^ d2 - bc4 = t<<61 | t>>(64-61) - t = a[8] ^ d3 - bc0 = t<<28 | t>>(64-28) - t = a[9] ^ d4 - bc1 = t<<20 | t>>(64-20) - a[5] = bc0 ^ (bc2 &^ bc1) - a[6] = bc1 ^ (bc3 &^ bc2) - a[7] = bc2 ^ (bc4 &^ bc3) - a[8] = bc3 ^ (bc0 &^ bc4) - a[9] = bc4 ^ (bc1 &^ bc0) - - t = a[10] ^ d0 - bc4 = t<<18 | t>>(64-18) - t = a[11] ^ d1 - bc0 = t<<1 | t>>(64-1) - t = a[12] ^ d2 - bc1 = t<<6 | t>>(64-6) - t = a[13] ^ d3 - bc2 = t<<25 | t>>(64-25) - t = a[14] ^ d4 - bc3 = t<<8 | t>>(64-8) - a[10] = bc0 ^ (bc2 &^ bc1) - a[11] = bc1 ^ (bc3 &^ bc2) - a[12] = bc2 ^ (bc4 &^ bc3) - a[13] = bc3 ^ (bc0 &^ bc4) - a[14] = bc4 ^ (bc1 &^ bc0) - - t = a[15] ^ d0 - bc1 = t<<36 | t>>(64-36) - t = a[16] ^ d1 - bc2 = t<<10 | t>>(64-10) - t = a[17] ^ d2 - bc3 = t<<15 | t>>(64-15) - t = a[18] ^ d3 - bc4 = t<<56 | t>>(64-56) - t = a[19] ^ d4 - bc0 = t<<27 | t>>(64-27) - a[15] = bc0 ^ (bc2 &^ bc1) - a[16] = bc1 ^ (bc3 &^ bc2) - a[17] = bc2 ^ (bc4 &^ bc3) - a[18] = bc3 ^ (bc0 &^ bc4) - a[19] = bc4 ^ (bc1 &^ bc0) - - t = a[20] ^ d0 - bc3 = t<<41 | t>>(64-41) - t = a[21] ^ d1 - bc4 = t<<2 | t>>(64-2) - t = a[22] ^ d2 - bc0 = t<<62 | t>>(64-62) - t = a[23] ^ d3 - bc1 = t<<55 | t>>(64-55) - t = a[24] ^ d4 - bc2 = t<<39 | t>>(64-39) - a[20] = bc0 ^ (bc2 &^ bc1) - a[21] = bc1 ^ (bc3 &^ bc2) - a[22] = bc2 ^ (bc4 &^ bc3) - a[23] = bc3 ^ (bc0 &^ bc4) - a[24] = bc4 ^ (bc1 &^ bc0) - } -} diff --git a/crypto/sha3/keccakf_amd64.go b/crypto/sha3/keccakf_amd64.go deleted file mode 100644 index de035c550..000000000 --- a/crypto/sha3/keccakf_amd64.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!appengine,!gccgo - -package sha3 - -// This function is implemented in keccakf_amd64.s. - -//go:noescape - -func keccakF1600(state *[25]uint64) diff --git a/crypto/sha3/keccakf_amd64.s b/crypto/sha3/keccakf_amd64.s deleted file mode 100644 index f88533acc..000000000 --- a/crypto/sha3/keccakf_amd64.s +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!appengine,!gccgo - -// This code was translated into a form compatible with 6a from the public -// domain sources at https://github.com/gvanas/KeccakCodePackage - -// Offsets in state -#define _ba (0*8) -#define _be (1*8) -#define _bi (2*8) -#define _bo (3*8) -#define _bu (4*8) -#define _ga (5*8) -#define _ge (6*8) -#define _gi (7*8) -#define _go (8*8) -#define _gu (9*8) -#define _ka (10*8) -#define _ke (11*8) -#define _ki (12*8) -#define _ko (13*8) -#define _ku (14*8) -#define _ma (15*8) -#define _me (16*8) -#define _mi (17*8) -#define _mo (18*8) -#define _mu (19*8) -#define _sa (20*8) -#define _se (21*8) -#define _si (22*8) -#define _so (23*8) -#define _su (24*8) - -// Temporary registers -#define rT1 AX - -// Round vars -#define rpState DI -#define rpStack SP - -#define rDa BX -#define rDe CX -#define rDi DX -#define rDo R8 -#define rDu R9 - -#define rBa R10 -#define rBe R11 -#define rBi R12 -#define rBo R13 -#define rBu R14 - -#define rCa SI -#define rCe BP -#define rCi rBi -#define rCo rBo -#define rCu R15 - -#define MOVQ_RBI_RCE MOVQ rBi, rCe -#define XORQ_RT1_RCA XORQ rT1, rCa -#define XORQ_RT1_RCE XORQ rT1, rCe -#define XORQ_RBA_RCU XORQ rBa, rCu -#define XORQ_RBE_RCU XORQ rBe, rCu -#define XORQ_RDU_RCU XORQ rDu, rCu -#define XORQ_RDA_RCA XORQ rDa, rCa -#define XORQ_RDE_RCE XORQ rDe, rCe - -#define mKeccakRound(iState, oState, rc, B_RBI_RCE, G_RT1_RCA, G_RT1_RCE, G_RBA_RCU, K_RT1_RCA, K_RT1_RCE, K_RBA_RCU, M_RT1_RCA, M_RT1_RCE, M_RBE_RCU, S_RDU_RCU, S_RDA_RCA, S_RDE_RCE) \ - /* Prepare round */ \ - MOVQ rCe, rDa; \ - ROLQ $1, rDa; \ - \ - MOVQ _bi(iState), rCi; \ - XORQ _gi(iState), rDi; \ - XORQ rCu, rDa; \ - XORQ _ki(iState), rCi; \ - XORQ _mi(iState), rDi; \ - XORQ rDi, rCi; \ - \ - MOVQ rCi, rDe; \ - ROLQ $1, rDe; \ - \ - MOVQ _bo(iState), rCo; \ - XORQ _go(iState), rDo; \ - XORQ rCa, rDe; \ - XORQ _ko(iState), rCo; \ - XORQ _mo(iState), rDo; \ - XORQ rDo, rCo; \ - \ - MOVQ rCo, rDi; \ - ROLQ $1, rDi; \ - \ - MOVQ rCu, rDo; \ - XORQ rCe, rDi; \ - ROLQ $1, rDo; \ - \ - MOVQ rCa, rDu; \ - XORQ rCi, rDo; \ - ROLQ $1, rDu; \ - \ - /* Result b */ \ - MOVQ _ba(iState), rBa; \ - MOVQ _ge(iState), rBe; \ - XORQ rCo, rDu; \ - MOVQ _ki(iState), rBi; \ - MOVQ _mo(iState), rBo; \ - MOVQ _su(iState), rBu; \ - XORQ rDe, rBe; \ - ROLQ $44, rBe; \ - XORQ rDi, rBi; \ - XORQ rDa, rBa; \ - ROLQ $43, rBi; \ - \ - MOVQ rBe, rCa; \ - MOVQ rc, rT1; \ - ORQ rBi, rCa; \ - XORQ rBa, rT1; \ - XORQ rT1, rCa; \ - MOVQ rCa, _ba(oState); \ - \ - XORQ rDu, rBu; \ - ROLQ $14, rBu; \ - MOVQ rBa, rCu; \ - ANDQ rBe, rCu; \ - XORQ rBu, rCu; \ - MOVQ rCu, _bu(oState); \ - \ - XORQ rDo, rBo; \ - ROLQ $21, rBo; \ - MOVQ rBo, rT1; \ - ANDQ rBu, rT1; \ - XORQ rBi, rT1; \ - MOVQ rT1, _bi(oState); \ - \ - NOTQ rBi; \ - ORQ rBa, rBu; \ - ORQ rBo, rBi; \ - XORQ rBo, rBu; \ - XORQ rBe, rBi; \ - MOVQ rBu, _bo(oState); \ - MOVQ rBi, _be(oState); \ - B_RBI_RCE; \ - \ - /* Result g */ \ - MOVQ _gu(iState), rBe; \ - XORQ rDu, rBe; \ - MOVQ _ka(iState), rBi; \ - ROLQ $20, rBe; \ - XORQ rDa, rBi; \ - ROLQ $3, rBi; \ - MOVQ _bo(iState), rBa; \ - MOVQ rBe, rT1; \ - ORQ rBi, rT1; \ - XORQ rDo, rBa; \ - MOVQ _me(iState), rBo; \ - MOVQ _si(iState), rBu; \ - ROLQ $28, rBa; \ - XORQ rBa, rT1; \ - MOVQ rT1, _ga(oState); \ - G_RT1_RCA; \ - \ - XORQ rDe, rBo; \ - ROLQ $45, rBo; \ - MOVQ rBi, rT1; \ - ANDQ rBo, rT1; \ - XORQ rBe, rT1; \ - MOVQ rT1, _ge(oState); \ - G_RT1_RCE; \ - \ - XORQ rDi, rBu; \ - ROLQ $61, rBu; \ - MOVQ rBu, rT1; \ - ORQ rBa, rT1; \ - XORQ rBo, rT1; \ - MOVQ rT1, _go(oState); \ - \ - ANDQ rBe, rBa; \ - XORQ rBu, rBa; \ - MOVQ rBa, _gu(oState); \ - NOTQ rBu; \ - G_RBA_RCU; \ - \ - ORQ rBu, rBo; \ - XORQ rBi, rBo; \ - MOVQ rBo, _gi(oState); \ - \ - /* Result k */ \ - MOVQ _be(iState), rBa; \ - MOVQ _gi(iState), rBe; \ - MOVQ _ko(iState), rBi; \ - MOVQ _mu(iState), rBo; \ - MOVQ _sa(iState), rBu; \ - XORQ rDi, rBe; \ - ROLQ $6, rBe; \ - XORQ rDo, rBi; \ - ROLQ $25, rBi; \ - MOVQ rBe, rT1; \ - ORQ rBi, rT1; \ - XORQ rDe, rBa; \ - ROLQ $1, rBa; \ - XORQ rBa, rT1; \ - MOVQ rT1, _ka(oState); \ - K_RT1_RCA; \ - \ - XORQ rDu, rBo; \ - ROLQ $8, rBo; \ - MOVQ rBi, rT1; \ - ANDQ rBo, rT1; \ - XORQ rBe, rT1; \ - MOVQ rT1, _ke(oState); \ - K_RT1_RCE; \ - \ - XORQ rDa, rBu; \ - ROLQ $18, rBu; \ - NOTQ rBo; \ - MOVQ rBo, rT1; \ - ANDQ rBu, rT1; \ - XORQ rBi, rT1; \ - MOVQ rT1, _ki(oState); \ - \ - MOVQ rBu, rT1; \ - ORQ rBa, rT1; \ - XORQ rBo, rT1; \ - MOVQ rT1, _ko(oState); \ - \ - ANDQ rBe, rBa; \ - XORQ rBu, rBa; \ - MOVQ rBa, _ku(oState); \ - K_RBA_RCU; \ - \ - /* Result m */ \ - MOVQ _ga(iState), rBe; \ - XORQ rDa, rBe; \ - MOVQ _ke(iState), rBi; \ - ROLQ $36, rBe; \ - XORQ rDe, rBi; \ - MOVQ _bu(iState), rBa; \ - ROLQ $10, rBi; \ - MOVQ rBe, rT1; \ - MOVQ _mi(iState), rBo; \ - ANDQ rBi, rT1; \ - XORQ rDu, rBa; \ - MOVQ _so(iState), rBu; \ - ROLQ $27, rBa; \ - XORQ rBa, rT1; \ - MOVQ rT1, _ma(oState); \ - M_RT1_RCA; \ - \ - XORQ rDi, rBo; \ - ROLQ $15, rBo; \ - MOVQ rBi, rT1; \ - ORQ rBo, rT1; \ - XORQ rBe, rT1; \ - MOVQ rT1, _me(oState); \ - M_RT1_RCE; \ - \ - XORQ rDo, rBu; \ - ROLQ $56, rBu; \ - NOTQ rBo; \ - MOVQ rBo, rT1; \ - ORQ rBu, rT1; \ - XORQ rBi, rT1; \ - MOVQ rT1, _mi(oState); \ - \ - ORQ rBa, rBe; \ - XORQ rBu, rBe; \ - MOVQ rBe, _mu(oState); \ - \ - ANDQ rBa, rBu; \ - XORQ rBo, rBu; \ - MOVQ rBu, _mo(oState); \ - M_RBE_RCU; \ - \ - /* Result s */ \ - MOVQ _bi(iState), rBa; \ - MOVQ _go(iState), rBe; \ - MOVQ _ku(iState), rBi; \ - XORQ rDi, rBa; \ - MOVQ _ma(iState), rBo; \ - ROLQ $62, rBa; \ - XORQ rDo, rBe; \ - MOVQ _se(iState), rBu; \ - ROLQ $55, rBe; \ - \ - XORQ rDu, rBi; \ - MOVQ rBa, rDu; \ - XORQ rDe, rBu; \ - ROLQ $2, rBu; \ - ANDQ rBe, rDu; \ - XORQ rBu, rDu; \ - MOVQ rDu, _su(oState); \ - \ - ROLQ $39, rBi; \ - S_RDU_RCU; \ - NOTQ rBe; \ - XORQ rDa, rBo; \ - MOVQ rBe, rDa; \ - ANDQ rBi, rDa; \ - XORQ rBa, rDa; \ - MOVQ rDa, _sa(oState); \ - S_RDA_RCA; \ - \ - ROLQ $41, rBo; \ - MOVQ rBi, rDe; \ - ORQ rBo, rDe; \ - XORQ rBe, rDe; \ - MOVQ rDe, _se(oState); \ - S_RDE_RCE; \ - \ - MOVQ rBo, rDi; \ - MOVQ rBu, rDo; \ - ANDQ rBu, rDi; \ - ORQ rBa, rDo; \ - XORQ rBi, rDi; \ - XORQ rBo, rDo; \ - MOVQ rDi, _si(oState); \ - MOVQ rDo, _so(oState) \ - -// func keccakF1600(state *[25]uint64) -TEXT ·keccakF1600(SB), 0, $200-8 - MOVQ state+0(FP), rpState - - // Convert the user state into an internal state - NOTQ _be(rpState) - NOTQ _bi(rpState) - NOTQ _go(rpState) - NOTQ _ki(rpState) - NOTQ _mi(rpState) - NOTQ _sa(rpState) - - // Execute the KeccakF permutation - MOVQ _ba(rpState), rCa - MOVQ _be(rpState), rCe - MOVQ _bu(rpState), rCu - - XORQ _ga(rpState), rCa - XORQ _ge(rpState), rCe - XORQ _gu(rpState), rCu - - XORQ _ka(rpState), rCa - XORQ _ke(rpState), rCe - XORQ _ku(rpState), rCu - - XORQ _ma(rpState), rCa - XORQ _me(rpState), rCe - XORQ _mu(rpState), rCu - - XORQ _sa(rpState), rCa - XORQ _se(rpState), rCe - MOVQ _si(rpState), rDi - MOVQ _so(rpState), rDo - XORQ _su(rpState), rCu - - mKeccakRound(rpState, rpStack, $0x0000000000000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x0000000000008082, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x800000000000808a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x8000000080008000, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x000000000000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x8000000000008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x000000000000008a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x0000000000000088, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x0000000080008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x000000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x000000008000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x800000000000008b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x8000000000008089, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x8000000000008003, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x8000000000008002, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x8000000000000080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x000000000000800a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x800000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x8000000000008080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpState, rpStack, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) - mKeccakRound(rpStack, rpState, $0x8000000080008008, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP) - - // Revert the internal state to the user state - NOTQ _be(rpState) - NOTQ _bi(rpState) - NOTQ _go(rpState) - NOTQ _ki(rpState) - NOTQ _mi(rpState) - NOTQ _sa(rpState) - - RET diff --git a/crypto/sha3/register.go b/crypto/sha3/register.go deleted file mode 100644 index 3cf6a22e0..000000000 --- a/crypto/sha3/register.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.4 - -package sha3 - -import ( - "crypto" -) - -func init() { - crypto.RegisterHash(crypto.SHA3_224, New224) - crypto.RegisterHash(crypto.SHA3_256, New256) - crypto.RegisterHash(crypto.SHA3_384, New384) - crypto.RegisterHash(crypto.SHA3_512, New512) -} diff --git a/crypto/sha3/sha3.go b/crypto/sha3/sha3.go deleted file mode 100644 index b12a35c87..000000000 --- a/crypto/sha3/sha3.go +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package sha3 - -// spongeDirection indicates the direction bytes are flowing through the sponge. -type spongeDirection int - -const ( - // spongeAbsorbing indicates that the sponge is absorbing input. - spongeAbsorbing spongeDirection = iota - // spongeSqueezing indicates that the sponge is being squeezed. - spongeSqueezing -) - -const ( - // maxRate is the maximum size of the internal buffer. SHAKE-256 - // currently needs the largest buffer. - maxRate = 168 -) - -type state struct { - // Generic sponge components. - a [25]uint64 // main state of the hash - buf []byte // points into storage - rate int // the number of bytes of state to use - - // dsbyte contains the "domain separation" bits and the first bit of - // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the - // SHA-3 and SHAKE functions by appending bitstrings to the message. - // Using a little-endian bit-ordering convention, these are "01" for SHA-3 - // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the - // padding rule from section 5.1 is applied to pad the message to a multiple - // of the rate, which involves adding a "1" bit, zero or more "0" bits, and - // a final "1" bit. We merge the first "1" bit from the padding into dsbyte, - // giving 00000110b (0x06) and 00011111b (0x1f). - // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf - // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and - // Extendable-Output Functions (May 2014)" - dsbyte byte - storage [maxRate]byte - - // Specific to SHA-3 and SHAKE. - outputLen int // the default output size in bytes - state spongeDirection // whether the sponge is absorbing or squeezing -} - -// BlockSize returns the rate of sponge underlying this hash function. -func (d *state) BlockSize() int { return d.rate } - -// Size returns the output size of the hash function in bytes. -func (d *state) Size() int { return d.outputLen } - -// Reset clears the internal state by zeroing the sponge state and -// the byte buffer, and setting Sponge.state to absorbing. -func (d *state) Reset() { - // Zero the permutation's state. - for i := range d.a { - d.a[i] = 0 - } - d.state = spongeAbsorbing - d.buf = d.storage[:0] -} - -func (d *state) clone() *state { - ret := *d - if ret.state == spongeAbsorbing { - ret.buf = ret.storage[:len(ret.buf)] - } else { - ret.buf = ret.storage[d.rate-cap(d.buf) : d.rate] - } - - return &ret -} - -// permute applies the KeccakF-1600 permutation. It handles -// any input-output buffering. -func (d *state) permute() { - switch d.state { - case spongeAbsorbing: - // If we're absorbing, we need to xor the input into the state - // before applying the permutation. - xorIn(d, d.buf) - d.buf = d.storage[:0] - keccakF1600(&d.a) - case spongeSqueezing: - // If we're squeezing, we need to apply the permutatin before - // copying more output. - keccakF1600(&d.a) - d.buf = d.storage[:d.rate] - copyOut(d, d.buf) - } -} - -// pads appends the domain separation bits in dsbyte, applies -// the multi-bitrate 10..1 padding rule, and permutes the state. -func (d *state) padAndPermute(dsbyte byte) { - if d.buf == nil { - d.buf = d.storage[:0] - } - // Pad with this instance's domain-separator bits. We know that there's - // at least one byte of space in d.buf because, if it were full, - // permute would have been called to empty it. dsbyte also contains the - // first one bit for the padding. See the comment in the state struct. - d.buf = append(d.buf, dsbyte) - zerosStart := len(d.buf) - d.buf = d.storage[:d.rate] - for i := zerosStart; i < d.rate; i++ { - d.buf[i] = 0 - } - // This adds the final one bit for the padding. Because of the way that - // bits are numbered from the LSB upwards, the final bit is the MSB of - // the last byte. - d.buf[d.rate-1] ^= 0x80 - // Apply the permutation - d.permute() - d.state = spongeSqueezing - d.buf = d.storage[:d.rate] - copyOut(d, d.buf) -} - -// Write absorbs more data into the hash's state. It produces an error -// if more data is written to the ShakeHash after writing -func (d *state) Write(p []byte) (written int, err error) { - if d.state != spongeAbsorbing { - panic("sha3: write to sponge after read") - } - if d.buf == nil { - d.buf = d.storage[:0] - } - written = len(p) - - for len(p) > 0 { - if len(d.buf) == 0 && len(p) >= d.rate { - // The fast path; absorb a full "rate" bytes of input and apply the permutation. - xorIn(d, p[:d.rate]) - p = p[d.rate:] - keccakF1600(&d.a) - } else { - // The slow path; buffer the input until we can fill the sponge, and then xor it in. - todo := d.rate - len(d.buf) - if todo > len(p) { - todo = len(p) - } - d.buf = append(d.buf, p[:todo]...) - p = p[todo:] - - // If the sponge is full, apply the permutation. - if len(d.buf) == d.rate { - d.permute() - } - } - } - - return -} - -// Read squeezes an arbitrary number of bytes from the sponge. -func (d *state) Read(out []byte) (n int, err error) { - // If we're still absorbing, pad and apply the permutation. - if d.state == spongeAbsorbing { - d.padAndPermute(d.dsbyte) - } - - n = len(out) - - // Now, do the squeezing. - for len(out) > 0 { - n := copy(out, d.buf) - d.buf = d.buf[n:] - out = out[n:] - - // Apply the permutation if we've squeezed the sponge dry. - if len(d.buf) == 0 { - d.permute() - } - } - - return -} - -// Sum applies padding to the hash state and then squeezes out the desired -// number of output bytes. -func (d *state) Sum(in []byte) []byte { - // Make a copy of the original hash so that caller can keep writing - // and summing. - dup := d.clone() - hash := make([]byte, dup.outputLen) - dup.Read(hash) - return append(in, hash...) -} diff --git a/crypto/sha3/shake.go b/crypto/sha3/shake.go deleted file mode 100644 index 841f9860f..000000000 --- a/crypto/sha3/shake.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package sha3 - -// This file defines the ShakeHash interface, and provides -// functions for creating SHAKE instances, as well as utility -// functions for hashing bytes to arbitrary-length output. - -import ( - "io" -) - -// ShakeHash defines the interface to hash functions that -// support arbitrary-length output. -type ShakeHash interface { - // Write absorbs more data into the hash's state. It panics if input is - // written to it after output has been read from it. - io.Writer - - // Read reads more output from the hash; reading affects the hash's - // state. (ShakeHash.Read is thus very different from Hash.Sum) - // It never returns an error. - io.Reader - - // Clone returns a copy of the ShakeHash in its current state. - Clone() ShakeHash - - // Reset resets the ShakeHash to its initial state. - Reset() -} - -func (d *state) Clone() ShakeHash { - return d.clone() -} - -// NewShake128 creates a new SHAKE128 variable-output-length ShakeHash. -// Its generic security strength is 128 bits against all attacks if at -// least 32 bytes of its output are used. -func NewShake128() ShakeHash { return &state{rate: 168, dsbyte: 0x1f} } - -// NewShake256 creates a new SHAKE128 variable-output-length ShakeHash. -// Its generic security strength is 256 bits against all attacks if -// at least 64 bytes of its output are used. -func NewShake256() ShakeHash { return &state{rate: 136, dsbyte: 0x1f} } - -// ShakeSum128 writes an arbitrary-length digest of data into hash. -func ShakeSum128(hash, data []byte) { - h := NewShake128() - h.Write(data) - h.Read(hash) -} - -// ShakeSum256 writes an arbitrary-length digest of data into hash. -func ShakeSum256(hash, data []byte) { - h := NewShake256() - h.Write(data) - h.Read(hash) -} diff --git a/crypto/sha3/xor.go b/crypto/sha3/xor.go deleted file mode 100644 index 42137426b..000000000 --- a/crypto/sha3/xor.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !amd64,!386,!ppc64le appengine - -package sha3 - -var ( - xorIn = xorInGeneric - copyOut = copyOutGeneric - xorInUnaligned = xorInGeneric - copyOutUnaligned = copyOutGeneric -) diff --git a/crypto/sha3/xor_unaligned.go b/crypto/sha3/xor_unaligned.go deleted file mode 100644 index 6b7a6628c..000000000 --- a/crypto/sha3/xor_unaligned.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64 386 ppc64le -// +build !appengine - -package sha3 - -import "unsafe" - -func xorInUnaligned(d *state, buf []byte) { - bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0])) - n := len(buf) - if n >= 72 { - d.a[0] ^= bw[0] - d.a[1] ^= bw[1] - d.a[2] ^= bw[2] - d.a[3] ^= bw[3] - d.a[4] ^= bw[4] - d.a[5] ^= bw[5] - d.a[6] ^= bw[6] - d.a[7] ^= bw[7] - d.a[8] ^= bw[8] - } - if n >= 104 { - d.a[9] ^= bw[9] - d.a[10] ^= bw[10] - d.a[11] ^= bw[11] - d.a[12] ^= bw[12] - } - if n >= 136 { - d.a[13] ^= bw[13] - d.a[14] ^= bw[14] - d.a[15] ^= bw[15] - d.a[16] ^= bw[16] - } - if n >= 144 { - d.a[17] ^= bw[17] - } - if n >= 168 { - d.a[18] ^= bw[18] - d.a[19] ^= bw[19] - d.a[20] ^= bw[20] - } -} - -func copyOutUnaligned(d *state, buf []byte) { - ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0])) - copy(buf, ab[:]) -} - -var ( - xorIn = xorInUnaligned - copyOut = copyOutUnaligned -) From 1c52e08bfe461d74604e893faf5a04558e635f36 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 16 Sep 2020 16:39:49 +0300 Subject: [PATCH 277/426] Update tests --- helpers/helpers.go | 16 +++++++++++++--- helpers/helpers_test.go | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/helpers/helpers.go b/helpers/helpers.go index 06d95f54b..3c07cf4a3 100644 --- a/helpers/helpers.go +++ b/helpers/helpers.go @@ -1,6 +1,7 @@ package helpers import ( + "errors" "fmt" "math/big" ) @@ -16,16 +17,25 @@ func BipToPip(bip *big.Int) *big.Int { // StringToBigInt converts string to BigInt, panics on empty strings and errors func StringToBigInt(s string) *big.Int { + result, err := stringToBigInt(s) + if err != nil { + panic(err) + } + + return result +} + +func stringToBigInt(s string) (*big.Int, error) { if s == "" { - panic("string is empty") + return nil, errors.New("string is empty") } b, success := big.NewInt(0).SetString(s, 10) if !success { - panic(fmt.Sprintf("Cannot decode %s into big.Int", s)) + return nil, fmt.Errorf("cannot decode %s into big.Int", s) } - return b + return b, nil } // IsValidBigInt verifies that string is a valid int diff --git a/helpers/helpers_test.go b/helpers/helpers_test.go index 7353c6658..46464c3af 100644 --- a/helpers/helpers_test.go +++ b/helpers/helpers_test.go @@ -1,6 +1,9 @@ package helpers -import "testing" +import ( + "math/big" + "testing" +) func TestIsValidBigInt(t *testing.T) { cases := map[string]bool{ @@ -17,3 +20,34 @@ func TestIsValidBigInt(t *testing.T) { } } } + +func TestStringToBigInt(t *testing.T) { + cases := map[string]bool{ + "": false, + "1": true, + "1s": false, + "-1": true, + "123437456298465928764598276349587623948756928764958762934569": true, + } + + for str, result := range cases { + _, err := stringToBigInt(str) + + if err != nil && result || err == nil && !result { + t.Fatalf("%s %s", err, str) + } + } + + result := StringToBigInt("10") + if result.Cmp(big.NewInt(10)) != 0 { + t.Fail() + } +} + +func TestBipToPip(t *testing.T) { + pip := BipToPip(big.NewInt(1)) + + if pip.Cmp(big.NewInt(1000000000000000000)) != 0 { + t.Fail() + } +} From 8d4cc6e28c06b7330577100614903bb6bed6873b Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 16 Sep 2020 17:45:38 +0300 Subject: [PATCH 278/426] refactor api and test minter.go --- api/v2/service/block.go | 4 +- api/v2/service/missed_blocks.go | 28 +- api/v2/service/send_transaction.go | 2 +- api/v2/service/transaction.go | 2 +- api/v2/service/transactions.go | 2 +- api/v2/service/waitlist.go | 2 +- core/minter/minter.go | 7 +- core/minter/minter_test.go | 885 ++++++++++++++++------------- core/state/state.go | 6 +- tests/byz_test.go | 98 ++++ tree/tree.go | 10 +- 11 files changed, 621 insertions(+), 425 deletions(-) create mode 100644 tests/byz_test.go diff --git a/api/v2/service/block.go b/api/v2/service/block.go index f77451e4a..35b726568 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -56,7 +56,7 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes cState, err = s.blockchain.GetStateForHeight(uint64(height)) if err != nil { - return nil, err + return new(pb.BlockResponse), status.Error(codes.NotFound, err.Error()) } response.Transactions, err = s.blockTransaction(block, blockResults, cState.Coins()) @@ -117,7 +117,7 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes if cState == nil { cState, err = s.blockchain.GetStateForHeight(uint64(height)) if err != nil { - return nil, err + return new(pb.BlockResponse), status.Error(codes.NotFound, err.Error()) } } diff --git a/api/v2/service/missed_blocks.go b/api/v2/service/missed_blocks.go index 4d10ede96..505ea240f 100644 --- a/api/v2/service/missed_blocks.go +++ b/api/v2/service/missed_blocks.go @@ -12,25 +12,16 @@ import ( // MissedBlocks returns missed blocks by validator public key. func (s *Service) MissedBlocks(ctx context.Context, req *pb.MissedBlocksRequest) (*pb.MissedBlocksResponse, error) { - blocks, count, err := missedBlocks(s, req.Height, req.PublicKey) - if err != nil { - return new(pb.MissedBlocksResponse), err - } - - return &pb.MissedBlocksResponse{MissedBlocks: blocks, MissedBlocksCount: fmt.Sprintf("%d", count)}, nil -} - -func missedBlocks(s *Service, height uint64, pubKey string) (missedBlocks string, missedBlocksCount int, err error) { - if !strings.HasPrefix(pubKey, "Mp") { - return "", 0, status.Error(codes.InvalidArgument, "public key don't has prefix 'Mp'") + if !strings.HasPrefix(req.PublicKey, "Mp") { + return new(pb.MissedBlocksResponse), status.Error(codes.InvalidArgument, "public key don't has prefix 'Mp'") } - cState, err := s.blockchain.GetStateForHeight(height) + cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { - return "", 0, status.Error(codes.NotFound, err.Error()) + return new(pb.MissedBlocksResponse), status.Error(codes.NotFound, err.Error()) } - if height != 0 { + if req.Height != 0 { cState.Lock() cState.Validators().LoadValidators() cState.Unlock() @@ -39,10 +30,13 @@ func missedBlocks(s *Service, height uint64, pubKey string) (missedBlocks string cState.RLock() defer cState.RUnlock() - val := cState.Validators().GetByPublicKey(types.HexToPubkey(pubKey)) + val := cState.Validators().GetByPublicKey(types.HexToPubkey(req.PublicKey)) if val == nil { - return "", 0, status.Error(codes.NotFound, "Validator not found") + return new(pb.MissedBlocksResponse), status.Error(codes.NotFound, "Validator not found") } - return val.AbsentTimes.String(), val.CountAbsentTimes(), nil + return &pb.MissedBlocksResponse{ + MissedBlocks: val.AbsentTimes.String(), + MissedBlocksCount: fmt.Sprintf("%d", val.CountAbsentTimes()), + }, nil } diff --git a/api/v2/service/send_transaction.go b/api/v2/service/send_transaction.go index 922e8ec3d..304259933 100644 --- a/api/v2/service/send_transaction.go +++ b/api/v2/service/send_transaction.go @@ -35,7 +35,7 @@ func (s *Service) SendTransaction(ctx context.Context, req *pb.SendTransactionRe return &pb.SendTransactionResponse{ Code: fmt.Sprintf("%d", result.Code), Log: result.Log, - Hash: result.Hash.String(), + Hash: "Mt" + strings.ToLower(result.Hash.String()), }, nil default: return new(pb.SendTransactionResponse), s.createError(status.New(codes.InvalidArgument, result.Log), result.Info) diff --git a/api/v2/service/transaction.go b/api/v2/service/transaction.go index be645272a..fde571ea4 100644 --- a/api/v2/service/transaction.go +++ b/api/v2/service/transaction.go @@ -36,7 +36,7 @@ func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) ( cState, err := s.blockchain.GetStateForHeight(uint64(tx.Height)) if err != nil { - return new(pb.TransactionResponse), status.Error(codes.Internal, err.Error()) + return new(pb.TransactionResponse), status.Error(codes.NotFound, err.Error()) } cState.RLock() diff --git a/api/v2/service/transactions.go b/api/v2/service/transactions.go index 16bedf1a3..e8b5d7b1e 100644 --- a/api/v2/service/transactions.go +++ b/api/v2/service/transactions.go @@ -32,7 +32,7 @@ func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) cState, err := s.blockchain.GetStateForHeight(uint64(rpcResult.Txs[0].Height)) if err != nil { - return new(pb.TransactionsResponse), status.Error(codes.Internal, err.Error()) + return new(pb.TransactionsResponse), status.Error(codes.NotFound, err.Error()) } for _, tx := range rpcResult.Txs { diff --git a/api/v2/service/waitlist.go b/api/v2/service/waitlist.go index e798a851e..84a7e6a66 100644 --- a/api/v2/service/waitlist.go +++ b/api/v2/service/waitlist.go @@ -31,7 +31,7 @@ func (s *Service) WaitList(ctx context.Context, req *pb.WaitListRequest) (*pb.Wa cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { - return nil, err + return new(pb.WaitListResponse), status.Error(codes.NotFound, err.Error()) } cState.RLock() diff --git a/core/minter/minter.go b/core/minter/minter.go index 425f73ba1..56c448609 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -2,7 +2,6 @@ package minter import ( "bytes" - "errors" "fmt" "github.com/MinterTeam/minter-go-node/cmd/utils" "github.com/MinterTeam/minter-go-node/config" @@ -166,12 +165,12 @@ func (app *Blockchain) InitChain(req abciTypes.RequestInitChain) abciTypes.Respo func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.ResponseBeginBlock { height := uint64(req.Header.Height) - app.StatisticData().PushStartBlock(&statistics.StartRequest{Height: int64(height), Now: time.Now(), HeaderTime: req.Header.Time}) - if app.isApplicationHalted(height) { panic(fmt.Sprintf("Application halted at height %d", height)) } + app.StatisticData().PushStartBlock(&statistics.StartRequest{Height: int64(height), Now: time.Now(), HeaderTime: req.Header.Time}) + app.stateDeliver.Lock() // compute max gas @@ -495,7 +494,7 @@ func (app *Blockchain) GetStateForHeight(height uint64) (*state.CheckState, erro if height > 0 { s, err := state.NewCheckStateAtHeight(height, app.stateDB) if err != nil { - return nil, errors.New("state at given height not found") + return nil, err } return s, nil } diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index 8d646f4fe..e464ed6a0 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -10,16 +10,18 @@ import ( "github.com/MinterTeam/minter-go-node/cmd/utils" "github.com/MinterTeam/minter-go-node/config" "github.com/MinterTeam/minter-go-node/core/developers" + eventsdb "github.com/MinterTeam/minter-go-node/core/events" candidates2 "github.com/MinterTeam/minter-go-node/core/state/candidates" + "github.com/MinterTeam/minter-go-node/core/state/validators" + "github.com/MinterTeam/minter-go-node/core/statistics" "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/crypto" "github.com/MinterTeam/minter-go-node/helpers" + "github.com/MinterTeam/minter-go-node/legacy/candidates" "github.com/MinterTeam/minter-go-node/log" "github.com/MinterTeam/minter-go-node/rlp" - "github.com/tendermint/go-amino" - tmConfig "github.com/tendermint/tendermint/config" log2 "github.com/tendermint/tendermint/libs/log" tmos "github.com/tendermint/tendermint/libs/os" tmNode "github.com/tendermint/tendermint/node" @@ -32,29 +34,120 @@ import ( "math/big" "math/rand" "os" - "path/filepath" - "sync" + "strconv" "testing" "time" ) -var pv *privval.FilePV -var cfg *tmConfig.Config -var tmCli *rpc.Local -var app *Blockchain -var privateKey *ecdsa.PrivateKey -var l sync.Mutex -var nonce = uint64(1) - -func init() { - l.Lock() - go initNode() - l.Lock() +func getPrivateKey() *ecdsa.PrivateKey { + b, _ := hex.DecodeString("825ca965c34ef1c8343e8e377959108370c23ba6194d858452b63432456403f9") + privateKey, _ := crypto.ToECDSA(b) + return privateKey +} + +func makeTestValidatorsAndCandidates(pubkeys []string, stake *big.Int) ([]types.Validator, []types.Candidate) { + vals := make([]types.Validator, len(pubkeys)) + cands := make([]types.Candidate, len(pubkeys)) + + for i, val := range pubkeys { + pkeyBytes, err := base64.StdEncoding.DecodeString(val) + if err != nil { + panic(err) + } + + var pkey types.Pubkey + copy(pkey[:], pkeyBytes) + addr := developers.Address + + vals[i] = types.Validator{ + TotalBipStake: stake.String(), + PubKey: pkey, + AccumReward: big.NewInt(0).String(), + AbsentTimes: types.NewBitArray(24), + } + + cands[i] = types.Candidate{ + ID: uint32(i) + 1, + RewardAddress: addr, + OwnerAddress: crypto.PubkeyToAddress(getPrivateKey().PublicKey), + ControlAddress: addr, + TotalBipStake: big.NewInt(1).String(), + PubKey: pkey, + Commission: 100, + Stakes: []types.Stake{ + { + Owner: addr, + Coin: types.GetBaseCoinID(), + Value: stake.String(), + BipValue: stake.String(), + }, + }, + Status: candidates2.CandidateStatusOnline, + } + } + + return vals, cands +} + +func getTestGenesis(pv *privval.FilePV) func() (*types2.GenesisDoc, error) { + return func() (*types2.GenesisDoc, error) { + + appHash := [32]byte{} + + validators, candidates := makeTestValidatorsAndCandidates([]string{base64.StdEncoding.EncodeToString(pv.Key.PubKey.Bytes()[5:])}, big.NewInt(10000000)) + + appState := types.AppState{ + TotalSlashed: "0", + Accounts: []types.Account{ + { + Address: crypto.PubkeyToAddress(getPrivateKey().PublicKey), + Balance: []types.Balance{ + { + Coin: types.GetBaseCoinID(), + Value: helpers.BipToPip(big.NewInt(1000000)).String(), + }, + }, + }, + }, + Validators: validators, + Candidates: candidates, + } + + appStateJSON, err := amino.MarshalJSON(appState) + if err != nil { + return nil, err + } + + genesisDoc := types2.GenesisDoc{ + ChainID: "minter-test-network", + GenesisTime: time.Now(), + AppHash: appHash[:], + AppState: json.RawMessage(appStateJSON), + } + + err = genesisDoc.ValidateAndComplete() + if err != nil { + return nil, err + } + + genesisFile := utils.GetMinterHome() + "/config/genesis.json" + if err := genesisDoc.SaveAs(genesisFile); err != nil { + panic(err) + } + + return &genesisDoc, nil + } } -func initNode() { - utils.MinterHome = os.ExpandEnv(filepath.Join("$HOME", ".minter_test")) - _ = os.RemoveAll(utils.MinterHome) +var port = 0 + +func getPort() string { + port++ + return strconv.Itoa(port) +} + +func initTestNode(t *testing.T) (*Blockchain, *rpc.Local, *privval.FilePV) { + utils.MinterHome = os.ExpandEnv(t.TempDir()) if err := tmos.EnsureDir(utils.GetMinterHome()+"/tmdata/blockstore.db", 0777); err != nil { panic(err.Error()) @@ -62,7 +155,7 @@ func initNode() { minterCfg := config.GetConfig() logger := log.NewLogger(minterCfg) - cfg = config.GetTmConfig(minterCfg) + cfg := config.GetTmConfig(minterCfg) cfg.Consensus.TimeoutPropose = 0 cfg.Consensus.TimeoutPrecommit = 0 cfg.Consensus.TimeoutPrevote = 0 @@ -72,18 +165,15 @@ func initNode() { cfg.Consensus.TimeoutProposeDelta = 0 cfg.Consensus.SkipTimeoutCommit = true cfg.RPC.ListenAddress = "" - cfg.P2P.ListenAddress = "0.0.0.0:25566" + cfg.P2P.ListenAddress = "0.0.0.0:2556" + getPort() // todo cfg.P2P.Seeds = "" cfg.P2P.PersistentPeers = "" cfg.DBBackend = "memdb" - pv = privval.GenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()) + pv := privval.GenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()) pv.Save() - b, _ := hex.DecodeString("825ca965c34ef1c8343e8e377959108370c23ba6194d858452b63432456403f9") - privateKey, _ = crypto.ToECDSA(b) - - app = NewMinterBlockchain(minterCfg) + app := NewMinterBlockchain(minterCfg) nodeKey, err := p2p.LoadOrGenNodeKey(cfg.NodeKeyFile()) if err != nil { panic(err) @@ -94,7 +184,7 @@ func initNode() { pv, nodeKey, proxy.NewLocalClientCreator(app), - getGenesis, + getTestGenesis(pv), tmNode.DefaultDBProvider, tmNode.DefaultMetricsProvider(cfg.Instrumentation), log2.NewTMLogger(os.Stdout), @@ -110,42 +200,65 @@ func initNode() { logger.Info("Started node", "nodeInfo", node.Switch().NodeInfo()) app.SetTmNode(node) - tmCli = rpc.New(node) - l.Unlock() -} -func TestBlocksCreation(t *testing.T) { - // Wait for blocks - blocks, err := tmCli.Subscribe(context.TODO(), "test-client", "tm.event = 'NewBlock'") + tmCli := rpc.New(blockchain.tmNode) + + blocks, err := tmCli.Subscribe(context.Background(), "test-client", "tm.event = 'NewBlock'") if err != nil { - panic(err) + t.Fatal(err) } select { case <-blocks: - // got block + err = tmCli.UnsubscribeAll(context.Background(), "test-client") + if err != nil { + t.Fatal(err) + } case <-time.After(10 * time.Second): - t.Fatalf("Timeout waiting for the first block") + t.Fatal("Timeout waiting for the first block") } - err = tmCli.UnsubscribeAll(context.TODO(), "test-client") + return app, tmCli, pv +} + +func TestBlockchain_Height(t *testing.T) { + blockchain, tmCli, _ := initTestNode(t) + defer blockchain.Stop() + + blocks, err := tmCli.Subscribe(context.Background(), "test-client", "tm.event = 'NewBlock'") if err != nil { - panic(err) + t.Fatal(err) + } + + block := <-blocks + if block.Data.(types2.EventDataNewBlock).Block.Height != int64(blockchain.Height()) { + t.Fatal("invalid blockchain height") } } -func TestSendTx(t *testing.T) { - for blockchain.Height() < 2 { - time.Sleep(time.Millisecond) +func TestBlockchain_SetStatisticData(t *testing.T) { + blockchain, tmCli, _ := initTestNode(t) + defer blockchain.Stop() + + ctx, _ := context.WithTimeout(context.Background(), time.Second*3) + blockchain.SetStatisticData(statistics.New()).Statistic(ctx) + blocks, err := tmCli.Subscribe(context.Background(), "test-client", "tm.event = 'NewBlock'") + if err != nil { + t.Fatal(err) } + block := <-blocks + if block.Data.(types2.EventDataNewBlock).Block.Header.Time.Nanosecond() != blockchain.StatisticData().BlockEnd.LastBlockInfo.HeaderTimestamp.Nanosecond() { + t.Fatal("statistic last block and event event last block header time not equal") + } +} - value := helpers.BipToPip(big.NewInt(10)) - to := types.Address([20]byte{1}) +func TestBlockchain_IsApplicationHalted(t *testing.T) { + blockchain, tmCli, pv := initTestNode(t) + defer blockchain.Stop() - data := transaction.SendData{ - Coin: types.GetBaseCoinID(), - To: to, - Value: value, + data := transaction.SetHaltBlockData{ + PubKey: types.BytesToPubkey(pv.Key.PubKey.Bytes()[5:]), + Height: 5, } encodedData, err := rlp.EncodeToBytes(data) @@ -154,63 +267,61 @@ func TestSendTx(t *testing.T) { } tx := transaction.Transaction{ - Nonce: nonce, + Nonce: 1, ChainID: types.CurrentChainID, GasPrice: 1, GasCoin: types.GetBaseCoinID(), - Type: transaction.TypeSend, + Type: transaction.TypeSetHaltBlock, Data: encodedData, SignatureType: transaction.SigTypeSingle, } - nonce++ - if err := tx.Sign(privateKey); err != nil { + if err := tx.Sign(getPrivateKey()); err != nil { t.Fatal(err) } txBytes, _ := tx.Serialize() - res, err := tmCli.BroadcastTxSync(txBytes) if err != nil { t.Fatalf("Failed: %s", err.Error()) } - if res.Code != 0 { - t.Fatalf("CheckTx code is not 0: %d", res.Code) + t.Fatalf("CheckTx code is not 0: %d, %s", res.Code, res.Log) } - txs, err := tmCli.Subscribe(context.TODO(), "test-client", "tm.event = 'Tx'") + blocks, err := tmCli.Subscribe(context.Background(), "test-client", "tm.event = 'NewBlock'") if err != nil { - panic(err) + t.Fatal(err) } - select { - case <-txs: - // got tx - case <-time.After(10 * time.Second): - t.Fatalf("Timeout waiting for the tx to be committed") - } + for { + select { + case block := <-blocks: + height := block.Data.(types2.EventDataNewBlock).Block.Height + if height < int64(data.Height) { + continue + } - err = tmCli.UnsubscribeAll(context.TODO(), "test-client") - if err != nil { - panic(err) + t.Fatalf("don't stop on block %d", height) + return + case <-time.After(2 * time.Second): + return + } } } -// TODO: refactor -func TestSmallStakeValidator(t *testing.T) { - for blockchain.Height() < 2 { - time.Sleep(time.Millisecond) - } - - pubkey := types.Pubkey{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} +func TestBlockchain_GetStateForHeightAndDeleteStateVersions(t *testing.T) { + blockchain, tmCli, _ := initTestNode(t) + defer blockchain.Stop() - data := transaction.DeclareCandidacyData{ - Address: crypto.PubkeyToAddress(privateKey.PublicKey), - PubKey: pubkey, - Commission: 10, - Coin: types.GetBaseCoinID(), - Stake: big.NewInt(0), + symbol := types.StrToCoinSymbol("AAA123") + data := transaction.CreateCoinData{ + Name: "nAAA123", + Symbol: symbol, + InitialAmount: helpers.BipToPip(big.NewInt(1000000)), + InitialReserve: helpers.BipToPip(big.NewInt(10000)), + ConstantReserveRatio: 70, + MaxSupply: big.NewInt(0).Exp(big.NewInt(10), big.NewInt(15+18), nil), } encodedData, err := rlp.EncodeToBytes(data) @@ -219,444 +330,436 @@ func TestSmallStakeValidator(t *testing.T) { } tx := transaction.Transaction{ - Nonce: nonce, + Nonce: 1, ChainID: types.CurrentChainID, GasPrice: 1, GasCoin: types.GetBaseCoinID(), - Type: transaction.TypeDeclareCandidacy, + Type: transaction.TypeCreateCoin, Data: encodedData, SignatureType: transaction.SigTypeSingle, } - nonce++ - if err := tx.Sign(privateKey); err != nil { + if err := tx.Sign(getPrivateKey()); err != nil { t.Fatal(err) } txBytes, _ := tx.Serialize() - res, err := tmCli.BroadcastTxSync(txBytes) + res, err := tmCli.BroadcastTxCommit(txBytes) if err != nil { t.Fatalf("Failed: %s", err.Error()) } - if res.Code != 0 { - t.Fatalf("CheckTx code is not 0: %d", res.Code) - } time.Sleep(time.Second) - setOnData := transaction.SetCandidateOnData{ - PubKey: pubkey, - } - - encodedData, err = rlp.EncodeToBytes(setOnData) + resultTx, err := tmCli.Tx(res.Hash.Bytes(), false) if err != nil { - t.Fatal(err) + t.Fatalf("Failed: %s", err.Error()) } - tx = transaction.Transaction{ - Nonce: nonce, - GasPrice: 1, - ChainID: types.CurrentChainID, - GasCoin: types.GetBaseCoinID(), - Type: transaction.TypeSetCandidateOnline, - Data: encodedData, - SignatureType: transaction.SigTypeSingle, - } - nonce++ + checkState := blockchain.CurrentState() - if err := tx.Sign(privateKey); err != nil { - t.Fatal(err) + if !checkState.Coins().ExistsBySymbol(symbol) { + t.Fatalf("Failed: %s", "state invalid") } - txBytes, _ = tx.Serialize() - res, err = tmCli.BroadcastTxSync(txBytes) + checkState, err = blockchain.GetStateForHeight(uint64(resultTx.Height - 1)) if err != nil { t.Fatalf("Failed: %s", err.Error()) } - if res.Code != 0 { - t.Fatalf("CheckTx code is not 0: %d", res.Code) - } - status, _ := tmCli.Status() - targetBlockHeight := status.SyncInfo.LatestBlockHeight - (status.SyncInfo.LatestBlockHeight % 120) + 150 - println("target block", targetBlockHeight) + if checkState.Coins().ExistsBySymbol(symbol) { + t.Fatalf("Failed: %s", "state invalid") + } - blocks, err := tmCli.Subscribe(context.TODO(), "test-client", "tm.event = 'NewBlock'") + err = blockchain.DeleteStateVersions(0, resultTx.Height) if err != nil { - panic(err) + t.Fatalf("Failed: %s", err.Error()) } - ready := false - for !ready { - select { - case block := <-blocks: - if block.Data.(types2.EventDataNewBlock).Block.Height < targetBlockHeight { - continue - } + checkState, err = blockchain.GetStateForHeight(uint64(resultTx.Height - 1)) + if err == nil { + t.Fatalf("Failed: %s", "state not deleted") + } +} - vals, _ := tmCli.Validators(&targetBlockHeight, 1, 1000) +func TestBlockchain_SendTx(t *testing.T) { + blockchain, tmCli, _ := initTestNode(t) + defer blockchain.Stop() - if len(vals.Validators) > 1 { - t.Errorf("There are should be 1 validator (has %d)", len(vals.Validators)) - } - - if len(app.stateDeliver.Validators.GetValidators()) > 1 { - t.Errorf("There are should be 1 validator (has %d)", len(app.stateDeliver.Validators.GetValidators())) - } + value := helpers.BipToPip(big.NewInt(10)) + to := types.Address([20]byte{1}) - ready = true - case <-time.After(10 * time.Second): - t.Fatalf("Timeout waiting for the block") - } - } - err = tmCli.UnsubscribeAll(context.TODO(), "test-client") - if err != nil { - panic(err) + data := transaction.SendData{ + Coin: types.GetBaseCoinID(), + To: to, + Value: value, } - time.Sleep(time.Second) - - encodedData, err = rlp.EncodeToBytes(setOnData) + encodedData, err := rlp.EncodeToBytes(data) if err != nil { t.Fatal(err) } - tx = transaction.Transaction{ + nonce := uint64(1) + tx := transaction.Transaction{ Nonce: nonce, - GasPrice: 1, ChainID: types.CurrentChainID, + GasPrice: 1, GasCoin: types.GetBaseCoinID(), - Type: transaction.TypeSetCandidateOnline, + Type: transaction.TypeSend, Data: encodedData, SignatureType: transaction.SigTypeSingle, } nonce++ - if err := tx.Sign(privateKey); err != nil { + if err := tx.Sign(getPrivateKey()); err != nil { t.Fatal(err) } - txBytes, _ = tx.Serialize() - res, err = tmCli.BroadcastTxSync(txBytes) + txBytes, _ := tx.Serialize() + + res, err := tmCli.BroadcastTxSync(txBytes) if err != nil { t.Fatalf("Failed: %s", err.Error()) } + if res.Code != 0 { t.Fatalf("CheckTx code is not 0: %d", res.Code) } - status, _ = tmCli.Status() - targetBlockHeight = status.SyncInfo.LatestBlockHeight - (status.SyncInfo.LatestBlockHeight % 120) + 120 + 5 - println("target block", targetBlockHeight) - - blocks, err = tmCli.Subscribe(context.TODO(), "test-client", "tm.event = 'NewBlock'") + txs, err := tmCli.Subscribe(context.Background(), "test-client", "tm.event = 'Tx'") if err != nil { - panic(err) - } - -FORLOOP2: - for { - select { - case block := <-blocks: - if block.Data.(types2.EventDataNewBlock).Block.Height < targetBlockHeight { - continue FORLOOP2 - } - - vals, _ := tmCli.Validators(&targetBlockHeight, 1, 100) - - if len(vals.Validators) > 1 { - t.Errorf("There should be only 1 validator, got %d", len(vals.Validators)) - } - - mvals := app.stateDeliver.Validators.GetValidators() - if len(mvals) > 1 { - t.Errorf("There should be only 1 validator, got %d", len(mvals)) - } - - break FORLOOP2 - case <-time.After(10 * time.Second): - t.Fatalf("Timeout waiting for the block") - } + t.Fatal(err) } - err = tmCli.UnsubscribeAll(context.TODO(), "test-client") - if err != nil { - panic(err) + select { + case <-txs: + // got tx + case <-time.After(10 * time.Second): + t.Fatalf("Timeout waiting for the tx to be committed") } } -func TestStopNetworkByHaltBlocks(t *testing.T) { - haltHeight := 500000 + uint64(5) +func TestBlockchain_FrozenFunds(t *testing.T) { + blockchain, tmCli, pv := initTestNode(t) + defer blockchain.Stop() - v1Pubkey := [32]byte{} - v2Pubkey := [32]byte{} - v3Pubkey := [32]byte{} + targetHeight := uint64(10) + value := big.NewInt(1000) + pubkey := types.BytesToPubkey(pv.Key.PubKey.Bytes()[5:]) + blockchain.stateDeliver.Lock() + blockchain.stateDeliver.Candidates.SubStake(developers.Address, pubkey, 0, value) + blockchain.stateDeliver.FrozenFunds.AddFund(targetHeight, developers.Address, pubkey, 0, value) + blockchain.stateDeliver.Unlock() - rand.Read(v1Pubkey[:]) - rand.Read(v2Pubkey[:]) - rand.Read(v3Pubkey[:]) + blocks, err := tmCli.Subscribe(context.Background(), "test-client", "tm.event = 'NewBlock'") + if err != nil { + t.Fatal(err) + } - app.stateDeliver.Validators.Create(v1Pubkey, helpers.BipToPip(big.NewInt(3))) - app.stateDeliver.Validators.Create(v2Pubkey, helpers.BipToPip(big.NewInt(5))) - app.stateDeliver.Validators.Create(v3Pubkey, helpers.BipToPip(big.NewInt(3))) + for block := range blocks { + if block.Data.(types2.EventDataNewBlock).Block.Height < int64(targetHeight) { + continue + } + break + } - v1Address := app.stateDeliver.Validators.GetValidators()[1].GetAddress() - v2Address := app.stateDeliver.Validators.GetValidators()[2].GetAddress() - v3Address := app.stateDeliver.Validators.GetValidators()[3].GetAddress() + blockchain.lock.RLock() + defer blockchain.lock.RLock() - app.validatorsStatuses = map[types.TmAddress]int8{} - app.validatorsStatuses[v1Address] = ValidatorPresent - app.validatorsStatuses[v2Address] = ValidatorPresent - app.validatorsStatuses[v3Address] = ValidatorPresent + events := blockchain.GetEventsDB().LoadEvents(uint32(targetHeight)) - app.stateDeliver.Halts.AddHaltBlock(haltHeight, v1Pubkey) - app.stateDeliver.Halts.AddHaltBlock(haltHeight, v3Pubkey) - if app.isApplicationHalted(haltHeight) { - t.Fatalf("Application halted at height %d", haltHeight) + if len(events) == 0 { + t.Errorf("empty events for %d block", targetHeight) } - - haltHeight++ - app.stateDeliver.Halts.AddHaltBlock(haltHeight, v1Pubkey) - app.stateDeliver.Halts.AddHaltBlock(haltHeight, v2Pubkey) - if !app.isApplicationHalted(haltHeight) { - t.Fatalf("Application not halted at height %d", haltHeight) + if _, ok := events[0].(*eventsdb.UnbondEvent); !ok { + t.Fatal("event is not UnbondEvent") } -} - -func TestRecalculateStakes(t *testing.T) { - for blockchain.Height() < 2 { - time.Sleep(time.Millisecond) + if events[0].AddressString() != developers.Address.String() { + t.Error("event address invalid") + } + if events[0].ValidatorPubKeyString() != pubkey.String() { + t.Error("event validator pubkey invalid") } - symbol := types.StrToCoinSymbol("AAA123") - data := transaction.CreateCoinData{ - Name: "nAAA123", - Symbol: symbol, - InitialAmount: helpers.BipToPip(big.NewInt(1000000)), - InitialReserve: helpers.BipToPip(big.NewInt(10000)), - ConstantReserveRatio: 70, - MaxSupply: big.NewInt(0).Exp(big.NewInt(10), big.NewInt(15+18), nil), + balance := blockchain.CurrentState().Accounts().GetBalance(developers.Address, 0) + if balance.String() != value.String() { + t.Fatal("balance is empty") } +} - encodedData, err := rlp.EncodeToBytes(data) +func TestBlockchain_RecalculateStakes_andRemoveValidator(t *testing.T) { + blockchain, tmCli, pv := initTestNode(t) + defer blockchain.Stop() + + txs, err := tmCli.Subscribe(context.Background(), "test-client", "tm.event = 'Tx'") if err != nil { t.Fatal(err) } + symbol := types.StrToCoinSymbol("AAA123") + nonce := uint64(1) + { + data := transaction.CreateCoinData{ + Name: "nAAA123", + Symbol: symbol, + InitialAmount: helpers.BipToPip(big.NewInt(1000000)), + InitialReserve: helpers.BipToPip(big.NewInt(10000)), + ConstantReserveRatio: 70, + MaxSupply: big.NewInt(0).Exp(big.NewInt(10), big.NewInt(15+18), nil), + } - tx := transaction.Transaction{ - Nonce: nonce, - ChainID: types.CurrentChainID, - GasPrice: 1, - GasCoin: types.GetBaseCoinID(), - Type: transaction.TypeCreateCoin, - Data: encodedData, - SignatureType: transaction.SigTypeSingle, - } - nonce++ + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } - if err := tx.Sign(privateKey); err != nil { - t.Fatal(err) - } + tx := transaction.Transaction{ + Nonce: nonce, + ChainID: types.CurrentChainID, + GasPrice: 1, + GasCoin: types.GetBaseCoinID(), + Type: transaction.TypeCreateCoin, + Data: encodedData, + SignatureType: transaction.SigTypeSingle, + } - txBytes, _ := tx.Serialize() - res, err := tmCli.BroadcastTxSync(txBytes) - if err != nil { - t.Fatalf("Failed: %s", err.Error()) - } - if res.Code != 0 { - t.Fatalf("CheckTx code is not 0: %d", res.Code) + if err := tx.Sign(getPrivateKey()); err != nil { + t.Fatal(err) + } + + txBytes, _ := tx.Serialize() + res, err := tmCli.BroadcastTxSync(txBytes) + if err != nil { + t.Fatalf("Failed: %s", err.Error()) + } + if res.Code != 0 { + t.Fatalf("CheckTx code is not 0: %d", res.Code) + } } + <-txs + nonce++ + blockchain.lock.RLock() + coinID := blockchain.CurrentState().Coins().GetCoinBySymbol(symbol, 0).ID() + blockchain.lock.RUnlock() + { + buyCoinData := transaction.BuyCoinData{ + CoinToBuy: coinID, + ValueToBuy: helpers.BipToPip(big.NewInt(10000000)), + CoinToSell: 0, + MaximumValueToSell: helpers.BipToPip(big.NewInt(10000000000000000)), + } - time.Sleep(time.Second) + encodedData, err := rlp.EncodeToBytes(buyCoinData) + if err != nil { + t.Fatal(err) + } - coinID := blockchain.stateCheck.Coins().GetCoinBySymbol(symbol, 0).ID() - buyCoinData := transaction.BuyCoinData{ - CoinToBuy: coinID, - ValueToBuy: helpers.BipToPip(big.NewInt(10000000)), - CoinToSell: 0, - MaximumValueToSell: helpers.BipToPip(big.NewInt(10000000000000000)), - } + tx := transaction.Transaction{ + Nonce: nonce, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: transaction.TypeBuyCoin, + Data: encodedData, + SignatureType: transaction.SigTypeSingle, + } - encodedData, err = rlp.EncodeToBytes(buyCoinData) - if err != nil { - t.Fatal(err) - } + if err := tx.Sign(getPrivateKey()); err != nil { + t.Fatal(err) + } - tx = transaction.Transaction{ - Nonce: nonce, - GasPrice: 1, - ChainID: types.CurrentChainID, - GasCoin: types.GetBaseCoinID(), - Type: transaction.TypeBuyCoin, - Data: encodedData, - SignatureType: transaction.SigTypeSingle, + txBytes, _ := tx.Serialize() + res, err := tmCli.BroadcastTxSync(txBytes) + if err != nil { + t.Fatalf("Failed: %s", err.Error()) + } + if res.Code != 0 { + t.Fatalf("CheckTx code is not 0: %d", res.Code) + } } + <-txs nonce++ + { + delegateData := transaction.DelegateData{ + PubKey: types.BytesToPubkey(pv.Key.PubKey.Bytes()[5:]), + Coin: coinID, + Value: helpers.BipToPip(big.NewInt(9000000)), + } - if err := tx.Sign(privateKey); err != nil { - t.Fatal(err) - } + encodedData, err := rlp.EncodeToBytes(delegateData) + if err != nil { + t.Fatal(err) + } - txBytes, _ = tx.Serialize() - res, err = tmCli.BroadcastTxSync(txBytes) - if err != nil { - t.Fatalf("Failed: %s", err.Error()) - } - if res.Code != 0 { - t.Fatalf("CheckTx code is not 0: %d", res.Code) - } + tx := transaction.Transaction{ + Nonce: nonce, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: types.GetBaseCoinID(), + Type: transaction.TypeDelegate, + Data: encodedData, + SignatureType: transaction.SigTypeSingle, + } - time.Sleep(time.Second) + if err := tx.Sign(getPrivateKey()); err != nil { + t.Fatal(err) + } - delegateData := transaction.DelegateData{ - PubKey: blockchain.stateCheck.Candidates().GetCandidates()[0].PubKey, - Coin: coinID, - Value: helpers.BipToPip(big.NewInt(9000000)), + txBytes, _ := tx.Serialize() + res, err := tmCli.BroadcastTxSync(txBytes) + if err != nil { + t.Fatalf("Failed: %s", err.Error()) + } + if res.Code != 0 { + t.Fatalf("CheckTx code is not 0: %d", res.Code) + } } + <-txs + nonce++ + { + data := transaction.DeclareCandidacyData{ + Address: types.Address{1}, + PubKey: types.Pubkey{1}, + Commission: 10, + Coin: 0, + Stake: big.NewInt(10000), + } - encodedData, err = rlp.EncodeToBytes(delegateData) - if err != nil { - t.Fatal(err) - } + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } - tx = transaction.Transaction{ - Nonce: nonce, - GasPrice: 1, - ChainID: types.CurrentChainID, - GasCoin: types.GetBaseCoinID(), - Type: transaction.TypeDelegate, - Data: encodedData, - SignatureType: transaction.SigTypeSingle, - } - nonce++ + tx := transaction.Transaction{ + Nonce: nonce, + ChainID: types.CurrentChainID, + GasPrice: 1, + GasCoin: types.GetBaseCoinID(), + Type: transaction.TypeDeclareCandidacy, + Data: encodedData, + SignatureType: transaction.SigTypeSingle, + } - if err := tx.Sign(privateKey); err != nil { - t.Fatal(err) - } + if err := tx.Sign(getPrivateKey()); err != nil { + t.Fatal(err) + } - txBytes, _ = tx.Serialize() - res, err = tmCli.BroadcastTxSync(txBytes) - if err != nil { - t.Fatalf("Failed: %s", err.Error()) - } - if res.Code != 0 { - t.Fatalf("CheckTx code is not 0: %d", res.Code) - } + txBytes, _ := tx.Serialize() - time.Sleep(time.Second) + res, err := tmCli.BroadcastTxSync(txBytes) + if err != nil { + t.Fatalf("Failed: %s", err.Error()) + } - blocks, err := tmCli.Subscribe(context.TODO(), "test-client", "tm.event = 'NewBlock'") - if err != nil { - panic(err) + if res.Code != 0 { + t.Fatalf("CheckTx code is not 0: %d, %s", res.Code, res.Log) + } } + <-txs + nonce++ + { + data := transaction.SetCandidateOnData{ + PubKey: types.Pubkey{1}, + } - defer func() { - err = tmCli.UnsubscribeAll(context.TODO(), "test-client") + encodedData, err := rlp.EncodeToBytes(data) if err != nil { - panic(err) + t.Fatal(err) } - }() - for { - select { - case block := <-blocks: - if block.Data.(types2.EventDataNewBlock).Block.Height < 150 { - continue - } - return - case <-time.After(10 * time.Second): - t.Fatalf("Timeout waiting for the block") + tx := transaction.Transaction{ + Nonce: nonce, + ChainID: types.CurrentChainID, + GasPrice: 1, + GasCoin: types.GetBaseCoinID(), + Type: transaction.TypeSetCandidateOnline, + Data: encodedData, + SignatureType: transaction.SigTypeSingle, } - } -} -func getGenesis() (*types2.GenesisDoc, error) { - appHash := [32]byte{} + if err := tx.Sign(getPrivateKey()); err != nil { + t.Fatal(err) + } - validators, candidates := makeValidatorsAndCandidates([]string{base64.StdEncoding.EncodeToString(pv.Key.PubKey.Bytes()[5:])}, big.NewInt(10000000)) + txBytes, _ := tx.Serialize() - appState := types.AppState{ - TotalSlashed: "0", - Accounts: []types.Account{ - { - Address: crypto.PubkeyToAddress(privateKey.PublicKey), - Balance: []types.Balance{ - { - Coin: types.GetBaseCoinID(), - Value: helpers.BipToPip(big.NewInt(1000000)).String(), - }, - }, - }, - }, - Validators: validators, - Candidates: candidates, - } + res, err := tmCli.BroadcastTxSync(txBytes) + if err != nil { + t.Fatalf("Failed: %s", err.Error()) + } - appStateJSON, err := amino.MarshalJSON(appState) - if err != nil { - return nil, err + if res.Code != 0 { + t.Fatalf("CheckTx code is not 0: %d, %s", res.Code, res.Log) + } } + <-txs - genesisDoc := types2.GenesisDoc{ - ChainID: "minter-test-network", - GenesisTime: time.Now(), - AppHash: appHash[:], - AppState: json.RawMessage(appStateJSON), + err = tmCli.Unsubscribe(context.Background(), "test-client", "tm.event = 'Tx'") + if err != nil { + t.Fatal(err) } - err = genesisDoc.ValidateAndComplete() + blocks, err := tmCli.Subscribe(context.Background(), "test-client", "tm.event = 'NewBlock'") if err != nil { - return nil, err + t.Fatal(err) } - genesisFile := utils.GetMinterHome() + "/config/genesis.json" - if err := genesisDoc.SaveAs(genesisFile); err != nil { - panic(err) + targetHeight := int64(123 + validators.ValidatorMaxAbsentTimes) + for block := range blocks { + if block.Data.(types2.EventDataNewBlock).Block.Height <= targetHeight { + continue + } + return + } + blockchain.lock.RLock() + candidate := blockchain.CurrentState().Candidates().GetCandidate(types.Pubkey{1}) + if candidate == nil { + t.Fatal("candidate not found") } + blockchain.lock.RUnlock() - return &genesisDoc, nil + if candidate.Status == candidates.CandidateStatusOnline { + t.Fatal("candidate not Offline") + } } -func makeValidatorsAndCandidates(pubkeys []string, stake *big.Int) ([]types.Validator, []types.Candidate) { - validators := make([]types.Validator, len(pubkeys)) - candidates := make([]types.Candidate, len(pubkeys)) - addr := developers.Address +func TestStopNetworkByHaltBlocks(t *testing.T) { + blockchain, _, _ := initTestNode(t) + blockchain.Stop() - for i, val := range pubkeys { - pkeyBytes, err := base64.StdEncoding.DecodeString(val) - if err != nil { - panic(err) - } + haltHeight := uint64(50) - var pkey types.Pubkey - copy(pkey[:], pkeyBytes) + v1Pubkey := [32]byte{} + v2Pubkey := [32]byte{} + v3Pubkey := [32]byte{} - validators[i] = types.Validator{ - TotalBipStake: stake.String(), - PubKey: pkey, - AccumReward: big.NewInt(0).String(), - AbsentTimes: types.NewBitArray(24), - } + rand.Read(v1Pubkey[:]) + rand.Read(v2Pubkey[:]) + rand.Read(v3Pubkey[:]) - candidates[i] = types.Candidate{ - ID: uint32(i) + 1, - RewardAddress: addr, - OwnerAddress: addr, - ControlAddress: addr, - TotalBipStake: big.NewInt(1).String(), - PubKey: pkey, - Commission: 100, - Stakes: []types.Stake{ - { - Owner: addr, - Coin: types.GetBaseCoinID(), - Value: stake.String(), - BipValue: stake.String(), - }, - }, - Status: candidates2.CandidateStatusOnline, - } + blockchain.stateDeliver.Validators.Create(v1Pubkey, helpers.BipToPip(big.NewInt(3))) + blockchain.stateDeliver.Validators.Create(v2Pubkey, helpers.BipToPip(big.NewInt(5))) + blockchain.stateDeliver.Validators.Create(v3Pubkey, helpers.BipToPip(big.NewInt(3))) + + v1Address := blockchain.stateDeliver.Validators.GetValidators()[1].GetAddress() + v2Address := blockchain.stateDeliver.Validators.GetValidators()[2].GetAddress() + v3Address := blockchain.stateDeliver.Validators.GetValidators()[3].GetAddress() + + blockchain.validatorsStatuses = map[types.TmAddress]int8{} + blockchain.validatorsStatuses[v1Address] = ValidatorPresent + blockchain.validatorsStatuses[v2Address] = ValidatorPresent + blockchain.validatorsStatuses[v3Address] = ValidatorPresent + + blockchain.stateDeliver.Halts.AddHaltBlock(haltHeight, v1Pubkey) + blockchain.stateDeliver.Halts.AddHaltBlock(haltHeight, v3Pubkey) + if blockchain.isApplicationHalted(haltHeight) { + t.Fatalf("Application halted at height %d", haltHeight) } - return validators, candidates + haltHeight++ + blockchain.stateDeliver.Halts.AddHaltBlock(haltHeight, v1Pubkey) + blockchain.stateDeliver.Halts.AddHaltBlock(haltHeight, v2Pubkey) + if !blockchain.isApplicationHalted(haltHeight) { + t.Fatalf("Application not halted at height %d", haltHeight) + } } diff --git a/core/state/state.go b/core/state/state.go index 20a173bc3..226d3e514 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -183,8 +183,10 @@ func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, } func NewCheckStateAtHeight(height uint64, db db.DB) (*CheckState, error) { - iavlTree := tree.NewImmutableTree(height, db) - + iavlTree, err := tree.NewImmutableTree(height, db) + if err != nil { + return nil, err + } return newCheckStateForTree(iavlTree, nil, db, 0) } diff --git a/tests/byz_test.go b/tests/byz_test.go new file mode 100644 index 000000000..d63c4f537 --- /dev/null +++ b/tests/byz_test.go @@ -0,0 +1,98 @@ +package tests + +import ( + "github.com/MinterTeam/minter-go-node/core/types" + tmTypes "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto/ed25519" + "testing" + "time" +) + +func TestBlockchain_ByzantineValidators(t *testing.T) { + state := DefaultAppState() // generate default state + + state.Validators = append(state.Validators, types.Validator{ + TotalBipStake: "10000", + PubKey: types.Pubkey{1}, + AccumReward: "10", + AbsentTimes: nil, + }) + state.Candidates = append(state.Candidates, types.Candidate{ + ID: 1, + RewardAddress: types.Address{}, + OwnerAddress: types.Address{}, + ControlAddress: types.Address{}, + TotalBipStake: "10000", + PubKey: types.Pubkey{1}, + Commission: 10, + Stakes: []types.Stake{ + { + Owner: types.Address{}, + Coin: 0, + Value: "10000", + BipValue: "10000", + }, + }, + Updates: nil, + Status: 2, + }) + + var pubkey ed25519.PubKeyEd25519 + copy(pubkey[:], types.Pubkey{1}.Bytes()) + var address types.TmAddress + copy(address[:], pubkey.Address().Bytes()) + + app := CreateApp(state) // create application + req := tmTypes.RequestBeginBlock{ + Hash: nil, + Header: tmTypes.Header{ + Version: tmTypes.Version{}, + ChainID: "", + Height: 1, + Time: time.Time{}, + LastBlockId: tmTypes.BlockID{}, + LastCommitHash: nil, + DataHash: nil, + ValidatorsHash: nil, + NextValidatorsHash: nil, + ConsensusHash: nil, + AppHash: nil, + LastResultsHash: nil, + EvidenceHash: nil, + ProposerAddress: nil, + }, + LastCommitInfo: tmTypes.LastCommitInfo{ + Round: 0, + Votes: nil, + }, + ByzantineValidators: []tmTypes.Evidence{ + { + Type: "", + Validator: tmTypes.Validator{ + Address: address[:], + Power: 10, + }, + Height: 1, + Time: time.Time{}, + TotalVotingPower: 0, + }, + }, + } + app.BeginBlock(req) + // SendBeginBlock(app) // send BeginBlock + + SendEndBlock(app) // send EndBlock + SendCommit(app) // send Commit + + if validator := app.CurrentState().Validators().GetByPublicKey([32]byte{1}); validator != nil { + t.Error("validator exists") + } + candidate := app.CurrentState().Candidates().GetCandidate([32]byte{1}) + if candidate == nil { + t.Fatal("candidate is not exists") + } + if candidate.GetTotalBipStake().String() != "0" { + t.Fatal("candidate total bip stake is not 0") + } + +} diff --git a/tree/tree.go b/tree/tree.go index d59fab804..c5e1af1b0 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -156,7 +156,7 @@ func (t *mutableTree) SaveVersion() ([]byte, int64, error) { return t.tree.SaveVersion() } -//Should use GlobalLock() and GlobalUnlock +// Should use GlobalLock() and GlobalUnlock func (t *mutableTree) DeleteVersionsIfExists(from, to int64) error { t.lock.Lock() defer t.lock.Unlock() @@ -170,7 +170,7 @@ func (t *mutableTree) DeleteVersionsIfExists(from, to int64) error { return t.tree.DeleteVersions(existsVersions...) } -//Should use GlobalLock() and GlobalUnlock +// Should use GlobalLock() and GlobalUnlock func (t *mutableTree) DeleteVersionIfExists(version int64) error { t.lock.Lock() defer t.lock.Unlock() @@ -211,13 +211,13 @@ type ImmutableTree struct { // NewImmutableTree returns MTree from given db at given height // Warning: returns the MTree interface, but you should only use ReadOnlyTree -func NewImmutableTree(height uint64, db dbm.DB) MTree { +func NewImmutableTree(height uint64, db dbm.DB) (MTree, error) { tree := NewMutableTree(0, db, 1024) _, err := tree.LazyLoadVersion(int64(height)) if err != nil { - panic(err) + return nil, err } - return tree + return tree, nil } // Iterate iterates over all keys of the tree, in order. The keys and values must not be modified, From 2796fbc72d11c83ff3428af0a0599074613e8e88 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 16 Sep 2020 18:12:05 +0300 Subject: [PATCH 279/426] tx hash --- api/v2/service/block.go | 3 ++- api/v2/service/transaction.go | 4 ++-- api/v2/service/transactions.go | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/api/v2/service/block.go b/api/v2/service/block.go index 35b726568..0b573ec6b 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -15,6 +15,7 @@ import ( tmTypes "github.com/tendermint/tendermint/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "strings" "time" ) @@ -229,7 +230,7 @@ func (s *Service) blockTransaction(block *core_types.ResultBlock, blockResults * } txs = append(txs, &pb.BlockResponse_Transaction{ - Hash: fmt.Sprintf("Mt%x", rawTx.Hash()), + Hash: "Mt" + strings.ToLower(tx.Hash().String()), RawTx: fmt.Sprintf("%x", []byte(rawTx)), From: sender.String(), Nonce: fmt.Sprintf("%d", tx.Nonce), diff --git a/api/v2/service/transaction.go b/api/v2/service/transaction.go index fde571ea4..46ad0e725 100644 --- a/api/v2/service/transaction.go +++ b/api/v2/service/transaction.go @@ -6,9 +6,9 @@ import ( "fmt" "github.com/MinterTeam/minter-go-node/core/transaction" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" - tmbytes "github.com/tendermint/tendermint/libs/bytes" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "strings" ) // Transaction returns transaction info. @@ -51,7 +51,7 @@ func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) ( } return &pb.TransactionResponse{ - Hash: tmbytes.HexBytes(tx.Tx.Hash()).String(), + Hash: "Mt" + strings.ToLower(tx.Tx.String()), RawTx: fmt.Sprintf("%x", []byte(tx.Tx)), Height: fmt.Sprintf("%d", tx.Height), Index: fmt.Sprintf("%d", tx.Index), diff --git a/api/v2/service/transactions.go b/api/v2/service/transactions.go index e8b5d7b1e..57ad780e2 100644 --- a/api/v2/service/transactions.go +++ b/api/v2/service/transactions.go @@ -5,9 +5,9 @@ import ( "fmt" "github.com/MinterTeam/minter-go-node/core/transaction" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" - "github.com/tendermint/tendermint/libs/bytes" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "strings" ) // Transactions return transactions by query. @@ -54,7 +54,7 @@ func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) } result = append(result, &pb.TransactionResponse{ - Hash: bytes.HexBytes(tx.Tx.Hash()).String(), + Hash: "Mt" + strings.ToLower(tx.Tx.String()), RawTx: fmt.Sprintf("%x", []byte(tx.Tx)), Height: fmt.Sprintf("%d", tx.Height), Index: fmt.Sprintf("%d", tx.Index), From 7794d75cce1c567d2a37d851f956128c584f6f78 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 16 Sep 2020 18:54:44 +0300 Subject: [PATCH 280/426] tx hash fix --- api/v2/service/transaction.go | 2 +- api/v2/service/transactions.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/api/v2/service/transaction.go b/api/v2/service/transaction.go index 46ad0e725..1fd5a9ef2 100644 --- a/api/v2/service/transaction.go +++ b/api/v2/service/transaction.go @@ -51,7 +51,7 @@ func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) ( } return &pb.TransactionResponse{ - Hash: "Mt" + strings.ToLower(tx.Tx.String()), + Hash: "Mt" + strings.ToLower(hex.EncodeToString(tx.Tx.Hash())), RawTx: fmt.Sprintf("%x", []byte(tx.Tx)), Height: fmt.Sprintf("%d", tx.Height), Index: fmt.Sprintf("%d", tx.Index), diff --git a/api/v2/service/transactions.go b/api/v2/service/transactions.go index 57ad780e2..85310b306 100644 --- a/api/v2/service/transactions.go +++ b/api/v2/service/transactions.go @@ -2,6 +2,7 @@ package service import ( "context" + "encoding/hex" "fmt" "github.com/MinterTeam/minter-go-node/core/transaction" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" @@ -54,7 +55,7 @@ func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) } result = append(result, &pb.TransactionResponse{ - Hash: "Mt" + strings.ToLower(tx.Tx.String()), + Hash: "Mt" + strings.ToLower(hex.EncodeToString(tx.Tx.Hash())), RawTx: fmt.Sprintf("%x", []byte(tx.Tx)), Height: fmt.Sprintf("%d", tx.Height), Index: fmt.Sprintf("%d", tx.Index), From d9877a037ad7309c672d678c2c223f3944a1ffa4 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 16 Sep 2020 19:09:37 +0300 Subject: [PATCH 281/426] tx hash fix --- api/v2/service/block.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v2/service/block.go b/api/v2/service/block.go index 0b573ec6b..6dc4cc3d2 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -230,7 +230,7 @@ func (s *Service) blockTransaction(block *core_types.ResultBlock, blockResults * } txs = append(txs, &pb.BlockResponse_Transaction{ - Hash: "Mt" + strings.ToLower(tx.Hash().String()), + Hash: strings.Title(fmt.Sprintf("Mt%x", rawTx.Hash())), RawTx: fmt.Sprintf("%x", []byte(rawTx)), From: sender.String(), Nonce: fmt.Sprintf("%d", tx.Nonce), From 617494cd18c6d11df6f58b2f0cfaed26048fe32f Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 17 Sep 2020 04:50:58 +0300 Subject: [PATCH 282/426] rename EditMultisigOwnersData --- api/v2/service/data_encoder.go | 6 +-- core/commissions/commissions.go | 2 +- core/transaction/create_multisig_test.go | 4 +- core/transaction/decoder.go | 2 +- ...it_multisig_owners.go => edit_multisig.go} | 14 +++---- ...g_owners_test.go => edit_multisig_test.go} | 42 +++++++++---------- core/transaction/encoder/encoder.go | 2 +- core/transaction/encoder/resources.go | 10 ++--- core/transaction/transaction.go | 2 +- go.mod | 6 +-- go.sum | 12 +++--- 11 files changed, 51 insertions(+), 51 deletions(-) rename core/transaction/{edit_multisig_owners.go => edit_multisig.go} (90%) rename core/transaction/{edit_multisig_owners_test.go => edit_multisig_test.go} (91%) diff --git a/api/v2/service/data_encoder.go b/api/v2/service/data_encoder.go index b9745eabb..268919717 100644 --- a/api/v2/service/data_encoder.go +++ b/api/v2/service/data_encoder.go @@ -96,8 +96,8 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { PubKey: d.PubKey.String(), NewPubKey: d.NewPubKey.String(), } - case *transaction.EditMultisigOwnersData: - d := data.(*transaction.EditMultisigOwnersData) + case *transaction.EditMultisigData: + d := data.(*transaction.EditMultisigData) weights := make([]string, 0, len(d.Weights)) for _, weight := range d.Weights { weights = append(weights, strconv.Itoa(int(weight))) @@ -106,7 +106,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { for _, address := range d.Addresses { addresses = append(addresses, address.String()) } - m = &pb.EditMultisigOwnersData{ + m = &pb.EditMultisigData{ Threshold: strconv.Itoa(int(d.Threshold)), Weights: weights, Addresses: addresses, diff --git a/core/commissions/commissions.go b/core/commissions/commissions.go index 82e8b0121..aa7b21f51 100644 --- a/core/commissions/commissions.go +++ b/core/commissions/commissions.go @@ -18,6 +18,6 @@ const ( SetHaltBlock int64 = 1000 RecreateCoin int64 = 10000000 EditOwner int64 = 10000000 - EditMultisigOwnersData int64 = 1000 + EditMultisigData int64 = 1000 PriceVoteData int64 = 10 ) diff --git a/core/transaction/create_multisig_test.go b/core/transaction/create_multisig_test.go index 4cbe8380a..396e19099 100644 --- a/core/transaction/create_multisig_test.go +++ b/core/transaction/create_multisig_test.go @@ -276,7 +276,7 @@ func TestCreateMultisigOwnersTxToNonExistenAddress(t *testing.T) { privateKey3, _ := crypto.GenerateKey() addr3 := crypto.PubkeyToAddress(privateKey3.PublicKey) - data := EditMultisigOwnersData{ + data := EditMultisigData{ Threshold: 3, Weights: []uint{2, 1, 2}, Addresses: []types.Address{addr1, addr2, addr3}, @@ -292,7 +292,7 @@ func TestCreateMultisigOwnersTxToNonExistenAddress(t *testing.T) { GasPrice: 1, ChainID: types.CurrentChainID, GasCoin: types.GetBaseCoinID(), - Type: TypeEditMultisigOwner, + Type: TypeEditMultisig, Data: encodedData, SignatureType: SigTypeMulti, } diff --git a/core/transaction/decoder.go b/core/transaction/decoder.go index 47ecd2254..0a1b8ae8b 100644 --- a/core/transaction/decoder.go +++ b/core/transaction/decoder.go @@ -29,7 +29,7 @@ func init() { TxDecoder.RegisterType(TypeSetHaltBlock, SetHaltBlockData{}) TxDecoder.RegisterType(TypeRecreateCoin, RecreateCoinData{}) TxDecoder.RegisterType(TypeEditCoinOwner, EditCoinOwnerData{}) - TxDecoder.RegisterType(TypeEditMultisigOwner, EditMultisigOwnersData{}) + TxDecoder.RegisterType(TypeEditMultisig, EditMultisigData{}) TxDecoder.RegisterType(TypePriceVote, PriceVoteData{}) TxDecoder.RegisterType(TypeEditCandidatePublicKey, EditCandidatePublicKeyData{}) } diff --git a/core/transaction/edit_multisig_owners.go b/core/transaction/edit_multisig.go similarity index 90% rename from core/transaction/edit_multisig_owners.go rename to core/transaction/edit_multisig.go index bd2416678..4aedac173 100644 --- a/core/transaction/edit_multisig_owners.go +++ b/core/transaction/edit_multisig.go @@ -14,13 +14,13 @@ import ( "github.com/tendermint/tendermint/libs/kv" ) -type EditMultisigOwnersData struct { +type EditMultisigData struct { Threshold uint Weights []uint Addresses []types.Address } -func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { +func (data EditMultisigData) BasicCheck(tx *Transaction, context *state.CheckState) *Response { sender, _ := tx.Sender() if !context.Accounts().GetAccount(sender).IsMultisig() { @@ -87,15 +87,15 @@ func (data EditMultisigOwnersData) BasicCheck(tx *Transaction, context *state.Ch return nil } -func (data EditMultisigOwnersData) String() string { +func (data EditMultisigData) String() string { return "EDIT MULTISIG OWNERS" } -func (data EditMultisigOwnersData) Gas() int64 { - return commissions.EditMultisigOwnersData +func (data EditMultisigData) Gas() int64 { + return commissions.EditMultisigData } -func (data EditMultisigOwnersData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { +func (data EditMultisigData) Run(tx *Transaction, context state.Interface, rewardPool *big.Int, currentBlock uint64) Response { sender, _ := tx.Sender() var checkState *state.CheckState @@ -145,7 +145,7 @@ func (data EditMultisigOwnersData) Run(tx *Transaction, context state.Interface, address := []byte(hex.EncodeToString(sender[:])) tags := kv.Pairs{ - kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeEditMultisigOwner)}))}, + kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeEditMultisig)}))}, kv.Pair{Key: []byte("tx.from"), Value: address}, } diff --git a/core/transaction/edit_multisig_owners_test.go b/core/transaction/edit_multisig_test.go similarity index 91% rename from core/transaction/edit_multisig_owners_test.go rename to core/transaction/edit_multisig_test.go index 6c1f33673..85f78541f 100644 --- a/core/transaction/edit_multisig_owners_test.go +++ b/core/transaction/edit_multisig_test.go @@ -15,7 +15,7 @@ import ( "github.com/MinterTeam/minter-go-node/rlp" ) -func TestEditMultisigOwnersTx(t *testing.T) { +func TestEditMultisigTx(t *testing.T) { cState := getState() pubkey := [32]byte{} @@ -37,7 +37,7 @@ func TestEditMultisigOwnersTx(t *testing.T) { initialBalance := big.NewInt(1) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(initialBalance)) - data := EditMultisigOwnersData{ + data := EditMultisigData{ Threshold: 3, Weights: []uint{2, 1, 2}, Addresses: []types.Address{addr1, addr2, addr4}, @@ -54,7 +54,7 @@ func TestEditMultisigOwnersTx(t *testing.T) { GasPrice: 1, ChainID: types.CurrentChainID, GasCoin: coin, - Type: TypeEditMultisigOwner, + Type: TypeEditMultisig, Data: encodedData, SignatureType: SigTypeMulti, } @@ -98,7 +98,7 @@ func TestEditMultisigOwnersTx(t *testing.T) { } } -func TestEditMultisigOwnersTxToNonExistenAddress(t *testing.T) { +func TestEditMultisigTxToNonExistenAddress(t *testing.T) { cState := getState() addr := types.Address{0} @@ -109,7 +109,7 @@ func TestEditMultisigOwnersTxToNonExistenAddress(t *testing.T) { privateKey3, _ := crypto.GenerateKey() addr3 := crypto.PubkeyToAddress(privateKey3.PublicKey) - data := EditMultisigOwnersData{ + data := EditMultisigData{ Threshold: 3, Weights: []uint{2, 1, 2}, Addresses: []types.Address{addr1, addr2, addr3}, @@ -125,7 +125,7 @@ func TestEditMultisigOwnersTxToNonExistenAddress(t *testing.T) { GasPrice: 1, ChainID: types.CurrentChainID, GasCoin: types.GetBaseCoinID(), - Type: TypeEditMultisigOwner, + Type: TypeEditMultisig, Data: encodedData, SignatureType: SigTypeMulti, } @@ -143,7 +143,7 @@ func TestEditMultisigOwnersTxToNonExistenAddress(t *testing.T) { } } -func TestEditMultisigOwnersTxToTooLargeOwnersList(t *testing.T) { +func TestEditMultisigTxToTooLargeOwnersList(t *testing.T) { cState := getState() addr := types.Address{0} @@ -163,7 +163,7 @@ func TestEditMultisigOwnersTxToTooLargeOwnersList(t *testing.T) { weights[i] = i } - data := EditMultisigOwnersData{ + data := EditMultisigData{ Threshold: 3, Weights: weights, Addresses: []types.Address{addr1, addr2, addr3}, @@ -179,7 +179,7 @@ func TestEditMultisigOwnersTxToTooLargeOwnersList(t *testing.T) { GasPrice: 1, ChainID: types.CurrentChainID, GasCoin: coin, - Type: TypeEditMultisigOwner, + Type: TypeEditMultisig, Data: encodedData, SignatureType: SigTypeMulti, } @@ -201,7 +201,7 @@ func TestEditMultisigOwnersTxToTooLargeOwnersList(t *testing.T) { } } -func TestEditMultisigOwnersTxIncorrectWeights(t *testing.T) { +func TestEditMultisigTxIncorrectWeights(t *testing.T) { cState := getState() addr := types.Address{0} @@ -216,7 +216,7 @@ func TestEditMultisigOwnersTxIncorrectWeights(t *testing.T) { cState.Accounts.CreateMultisig([]uint{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) - data := EditMultisigOwnersData{ + data := EditMultisigData{ Threshold: 3, Weights: []uint{1, 2, 3, 4}, Addresses: []types.Address{addr1, addr2, addr3}, @@ -232,7 +232,7 @@ func TestEditMultisigOwnersTxIncorrectWeights(t *testing.T) { GasPrice: 1, ChainID: types.CurrentChainID, GasCoin: coin, - Type: TypeEditMultisigOwner, + Type: TypeEditMultisig, Data: encodedData, SignatureType: SigTypeMulti, } @@ -297,7 +297,7 @@ func TestEditMultisigOwnersTxIncorrectWeights(t *testing.T) { } } -func TestEditMultisigOwnersTxToAddressDuplication(t *testing.T) { +func TestEditMultisigTxToAddressDuplication(t *testing.T) { cState := getState() addr := types.Address{0} @@ -312,7 +312,7 @@ func TestEditMultisigOwnersTxToAddressDuplication(t *testing.T) { cState.Accounts.CreateMultisig([]uint{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) - data := EditMultisigOwnersData{ + data := EditMultisigData{ Threshold: 3, Weights: []uint{1, 2, 3}, Addresses: []types.Address{addr1, addr1, addr3}, @@ -328,7 +328,7 @@ func TestEditMultisigOwnersTxToAddressDuplication(t *testing.T) { GasPrice: 1, ChainID: types.CurrentChainID, GasCoin: coin, - Type: TypeEditMultisigOwner, + Type: TypeEditMultisig, Data: encodedData, SignatureType: SigTypeMulti, } @@ -350,7 +350,7 @@ func TestEditMultisigOwnersTxToAddressDuplication(t *testing.T) { } } -func TestEditMultisigOwnersTxToInsufficientFunds(t *testing.T) { +func TestEditMultisigTxToInsufficientFunds(t *testing.T) { cState := getState() addr := types.Address{0} @@ -365,7 +365,7 @@ func TestEditMultisigOwnersTxToInsufficientFunds(t *testing.T) { cState.Accounts.CreateMultisig([]uint{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) - data := EditMultisigOwnersData{ + data := EditMultisigData{ Threshold: 3, Weights: []uint{1, 2, 3}, Addresses: []types.Address{addr1, addr2, addr3}, @@ -381,7 +381,7 @@ func TestEditMultisigOwnersTxToInsufficientFunds(t *testing.T) { GasPrice: 1, ChainID: types.CurrentChainID, GasCoin: coin, - Type: TypeEditMultisigOwner, + Type: TypeEditMultisig, Data: encodedData, SignatureType: SigTypeMulti, } @@ -403,7 +403,7 @@ func TestEditMultisigOwnersTxToInsufficientFunds(t *testing.T) { } } -func TestEditMultisigOwnersTxToGasCoinReserveUnderflow(t *testing.T) { +func TestEditMultisigTxToGasCoinReserveUnderflow(t *testing.T) { cState := getState() addr := types.Address{0} @@ -419,7 +419,7 @@ func TestEditMultisigOwnersTxToGasCoinReserveUnderflow(t *testing.T) { cState.Accounts.CreateMultisig([]uint{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) - data := EditMultisigOwnersData{ + data := EditMultisigData{ Threshold: 3, Weights: []uint{1, 2, 3}, Addresses: []types.Address{addr1, addr2, addr3}, @@ -435,7 +435,7 @@ func TestEditMultisigOwnersTxToGasCoinReserveUnderflow(t *testing.T) { GasPrice: 1, ChainID: types.CurrentChainID, GasCoin: coin, - Type: TypeEditMultisigOwner, + Type: TypeEditMultisig, Data: encodedData, SignatureType: SigTypeMulti, } diff --git a/core/transaction/encoder/encoder.go b/core/transaction/encoder/encoder.go index bb719212f..fc6c921bf 100644 --- a/core/transaction/encoder/encoder.go +++ b/core/transaction/encoder/encoder.go @@ -51,7 +51,7 @@ var resourcesConfig = map[transaction.TxType]TxDataResource{ transaction.TypeSetHaltBlock: new(SetHaltBlockDataResource), transaction.TypeRecreateCoin: new(RecreateCoinDataResource), transaction.TypeEditCoinOwner: new(EditCoinOwnerDataResource), - transaction.TypeEditMultisigOwner: new(EditMultisigOwnersResource), + transaction.TypeEditMultisig: new(EditMultisigResource), transaction.TypePriceVote: new(PriceVoteResource), transaction.TypeEditCandidatePublicKey: new(EditCandidatePublicKeyResource), } diff --git a/core/transaction/encoder/resources.go b/core/transaction/encoder/resources.go index 9e6ea3453..c1302ab54 100644 --- a/core/transaction/encoder/resources.go +++ b/core/transaction/encoder/resources.go @@ -346,18 +346,18 @@ func (EditCoinOwnerDataResource) Transform(txData interface{}, context *state.Ch } } -// EditMultisigOwnersResource is JSON representation of TxType 0x12 -type EditMultisigOwnersResource struct { +// EditMultisigResource is JSON representation of TxType 0x12 +type EditMultisigResource struct { Threshold string `json:"threshold"` Weights []string `json:"weights"` Addresses []types.Address `json:"addresses"` } // Transform returns TxDataResource from given txData. Used for JSON encoder. -func (EditMultisigOwnersResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { - data := txData.(*transaction.EditMultisigOwnersData) +func (EditMultisigResource) Transform(txData interface{}, context *state.CheckState) TxDataResource { + data := txData.(*transaction.EditMultisigData) - resource := EditMultisigOwnersResource{ + resource := EditMultisigResource{ Addresses: data.Addresses, Threshold: strconv.Itoa(int(data.Threshold)), } diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index 5d49e5f95..462d1cc81 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -36,7 +36,7 @@ const ( TypeSetHaltBlock TxType = 0x0F TypeRecreateCoin TxType = 0x10 TypeEditCoinOwner TxType = 0x11 - TypeEditMultisigOwner TxType = 0x12 + TypeEditMultisig TxType = 0x12 TypePriceVote TxType = 0x13 TypeEditCandidatePublicKey TxType = 0x14 diff --git a/go.mod b/go.mod index 9097b7ca8..7b9a2d511 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200914084650-1886df946f7a + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200917013747-c25ba3234571 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 @@ -13,7 +13,7 @@ require ( github.com/gorilla/websocket v1.4.2 github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 - github.com/grpc-ecosystem/grpc-gateway v1.14.7 + github.com/grpc-ecosystem/grpc-gateway v1.14.8 github.com/marcusolsson/tui-go v0.4.0 github.com/mattn/go-tty v0.0.3 // indirect github.com/pkg/errors v0.9.1 @@ -37,6 +37,6 @@ require ( golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 golang.org/x/sys v0.0.0-20200523222454-059865788121 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - google.golang.org/grpc v1.31.0 + google.golang.org/grpc v1.31.1 google.golang.org/protobuf v1.25.0 ) diff --git a/go.sum b/go.sum index b09370ad4..d624d7e8d 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200914084650-1886df946f7a h1:VnbpxZI8gat0tUv1ZF1Si5QqmiDiQbDsfAv47rEOm7A= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200914084650-1886df946f7a/go.mod h1:qQbnQmtHQPubkT2hF/4qSBe/XMcHm+QVMLhm6AfQT5M= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200917013747-c25ba3234571 h1:Kvnxm5G3Q7807tSxplY5z3TYB6qIZ32cXAuuRCU06DI= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200917013747-c25ba3234571/go.mod h1:ySmK0RhCHr7W0MoDmtED6ebYQcxYAXWPqAnvLFaWXEU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= @@ -196,8 +196,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0 h1:bM6ZAFZmc/wPFaRDi0d5L7hGEZEx/2u+Tmr2evNHDiI= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.14.7 h1:Nk5kuHrnWUTf/0GL1a/vchH/om9Ap2/HnVna+jYZgTY= -github.com/grpc-ecosystem/grpc-gateway v1.14.7/go.mod h1:oYZKL012gGh6LMyg/xA7Q2yq6j8bu0wa+9w14EEthWU= +github.com/grpc-ecosystem/grpc-gateway v1.14.8 h1:hXClj+iFpmLM8i3lkO6i4Psli4P2qObQuQReiII26U8= +github.com/grpc-ecosystem/grpc-gateway v1.14.8/go.mod h1:NZE8t6vs6TnwLL/ITkaK8W3ecMLGAbh2jXTclvpiwYo= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f h1:8N8XWLZelZNibkhM1FuF+3Ad3YIbgirjdMiVA0eUkaM= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= @@ -651,8 +651,8 @@ google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k= google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.31.0 h1:T7P4R73V3SSDPhH7WW7ATbfViLtmamH0DKrP3f9AuDI= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1 h1:SfXqXS5hkufcdZ/mHtYCh53P2b+92WQq/DZcKLgsFRs= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From cb3ea2e89fc7b89af1f32d1dd08f824843fa1192 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 17 Sep 2020 15:09:38 +0300 Subject: [PATCH 283/426] fix test --- core/minter/minter_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index e464ed6a0..26f0fb183 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -147,7 +147,7 @@ func getPort() string { } func initTestNode(t *testing.T) (*Blockchain, *rpc.Local, *privval.FilePV) { - utils.MinterHome = os.ExpandEnv(t.TempDir()) + utils.MinterHome = t.TempDir() if err := tmos.EnsureDir(utils.GetMinterHome()+"/tmdata/blockstore.db", 0777); err != nil { panic(err.Error()) From cc6f75f22325bea2bfcc4a9628334fdbedb4bef8 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 17 Sep 2020 15:10:02 +0300 Subject: [PATCH 284/426] add coin_id to tags --- core/transaction/create_coin.go | 9 ++++++--- core/transaction/recreate_coin.go | 25 ++++++++++++------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index cebfaebb2..6a5595afc 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -183,6 +183,7 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP } } + var coinId types.CoinID if deliverState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) @@ -193,8 +194,9 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) coinID := deliverState.App.GetCoinsCount() + 1 + coinId = types.CoinID(coinID) deliverState.Coins.Create( - types.CoinID(coinID), + coinId, data.Symbol, data.Name, data.InitialAmount, @@ -205,14 +207,15 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP ) deliverState.App.SetCoinsCount(coinID) - deliverState.Accounts.AddBalance(sender, types.CoinID(coinID), data.InitialAmount) + deliverState.Accounts.AddBalance(sender, coinId, data.InitialAmount) deliverState.Accounts.SetNonce(sender, tx.Nonce) } tags := kv.Pairs{ kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeCreateCoin)}))}, kv.Pair{Key: []byte("tx.from"), Value: []byte(hex.EncodeToString(sender[:]))}, - kv.Pair{Key: []byte("tx.coin"), Value: []byte(data.Symbol.String())}, + kv.Pair{Key: []byte("tx.coin_symbol"), Value: []byte(data.Symbol.String())}, + kv.Pair{Key: []byte("tx.coin_id"), Value: []byte(coinId.String())}, } return Response{ diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 7b85f4afb..9443cccb0 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -171,11 +171,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar } } - tags := kv.Pairs{ - kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeRecreateCoin)}))}, - kv.Pair{Key: []byte("tx.from"), Value: []byte(hex.EncodeToString(sender[:]))}, - } - + var coinId types.CoinID if deliverState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) @@ -185,9 +181,9 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar deliverState.Accounts.SubBalance(sender, types.GetBaseCoinID(), data.InitialReserve) deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) - coinID := deliverState.App.GetNextCoinID() + coinId = deliverState.App.GetNextCoinID() deliverState.Coins.Recreate( - coinID, + coinId, data.Name, data.Symbol, data.InitialAmount, @@ -196,14 +192,17 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar data.MaxSupply, ) - deliverState.App.SetCoinsCount(coinID.Uint32()) - deliverState.Accounts.AddBalance(sender, coinID, data.InitialAmount) + deliverState.App.SetCoinsCount(coinId.Uint32()) + deliverState.Accounts.AddBalance(sender, coinId, data.InitialAmount) deliverState.Accounts.SetNonce(sender, tx.Nonce) - tags = append(tags, kv.Pair{ - Key: []byte("tx.coin"), - Value: []byte(data.Symbol.String()), - }) + } + + tags := kv.Pairs{ + kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeRecreateCoin)}))}, + kv.Pair{Key: []byte("tx.from"), Value: []byte(hex.EncodeToString(sender[:]))}, + kv.Pair{Key: []byte("tx.coin_symbol"), Value: []byte(data.Symbol.String())}, + kv.Pair{Key: []byte("tx.coin_id"), Value: []byte(coinId.String())}, } return Response{ From 63c522a64b8a56cdaa0fd1696c5f715a4acec612 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 17 Sep 2020 15:11:07 +0300 Subject: [PATCH 285/426] edit path frozen/{address} --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7b9a2d511..5826ce4d6 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200917013747-c25ba3234571 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200917115953-484c5d19df4d github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index d624d7e8d..b08aec64c 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200917013747-c25ba3234571 h1:Kvnxm5G3Q7807tSxplY5z3TYB6qIZ32cXAuuRCU06DI= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200917013747-c25ba3234571/go.mod h1:ySmK0RhCHr7W0MoDmtED6ebYQcxYAXWPqAnvLFaWXEU= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200917115953-484c5d19df4d h1:OGb2maPQoa4+B1yiNlAQPP3wMqkI6+i1dtxXtsSVoxc= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200917115953-484c5d19df4d/go.mod h1:ySmK0RhCHr7W0MoDmtED6ebYQcxYAXWPqAnvLFaWXEU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 2a09d666064f72324eeca7bd9e2b92389c38273b Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 17 Sep 2020 15:51:09 +0300 Subject: [PATCH 286/426] remove progress from prune_block --- cli/service/client.go | 27 +++++++-------------------- cli/service/service.go | 2 +- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/cli/service/client.go b/cli/service/client.go index 2fce090dd..4eb8f7c11 100644 --- a/cli/service/client.go +++ b/cli/service/client.go @@ -13,9 +13,9 @@ import ( grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry" "github.com/marcusolsson/tui-go" "github.com/urfave/cli/v2" - "gitlab.com/tslocum/cview" "google.golang.org/grpc" "io" + "log" "os" "strings" "time" @@ -388,20 +388,9 @@ func pruneBlocksCMD(client pb.ManagerServiceClient) func(c *cli.Context) error { return err } - progress := cview.NewProgressBar() - app := cview.NewApplication().SetRoot(progress, true) - errCh := make(chan error) - quitUI := make(chan error) recvCh := make(chan *pb.PruneBlocksResponse) - next := make(chan struct{}) - go func() { - close(next) - quitUI <- app.Run() - }() - <-next - go func() { for { select { @@ -425,13 +414,8 @@ func pruneBlocksCMD(client pb.ManagerServiceClient) func(c *cli.Context) error { for { select { case <-c.Done(): - app.Stop() return c.Err() - case err := <-quitUI: - fmt.Println(progress.GetTitle()) - return err case err, more := <-errCh: - app.Stop() _ = stream.CloseSend() if more { close(errCh) @@ -440,9 +424,12 @@ func pruneBlocksCMD(client pb.ManagerServiceClient) func(c *cli.Context) error { fmt.Println("OK") return nil case recv := <-recvCh: - progress.SetMax(int(recv.Total)) - progress.SetProgress(int(recv.Current)) - app.QueueUpdateDraw(func() {}) + var percent int64 + if recv.Total != 0 { + percent = int64(float64(recv.Current) / float64(recv.Total) * 100.0) + } + log.Println() + fmt.Printf("%d%% successfully removed (%d of %d)\n", percent, recv.Current, recv.Total) } } } diff --git a/cli/service/service.go b/cli/service/service.go index aceb1192f..18d13e02d 100644 --- a/cli/service/service.go +++ b/cli/service/service.go @@ -232,7 +232,7 @@ func (m *Manager) PruneBlocks(req *pb.PruneBlocksRequest, stream pb.ManagerServi return status.Errorf(codes.FailedPrecondition, "cannot delete latest saved version (%d)", current) } - min := req.FromHeight - 1 + min := req.FromHeight total := req.ToHeight - min from := req.FromHeight From e71f072bf316a6e76a20e449031a53c71af95207 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 18 Sep 2020 10:57:17 +0300 Subject: [PATCH 287/426] fix transaction tags --- core/state/app/app.go | 1 + core/transaction/create_coin.go | 6 ++---- core/transaction/edit_coin_owner.go | 2 +- core/transaction/recreate_coin.go | 3 +-- core/transaction/redeem_check.go | 2 +- core/transaction/send.go | 2 +- 6 files changed, 7 insertions(+), 9 deletions(-) diff --git a/core/state/app/app.go b/core/state/app/app.go index 7ba776b64..2460858f0 100644 --- a/core/state/app/app.go +++ b/core/state/app/app.go @@ -16,6 +16,7 @@ type RApp interface { GetMaxGas() uint64 GetTotalSlashed() *big.Int GetCoinsCount() uint32 + GetNextCoinID() types.CoinID } func (v *App) Tree() tree.ReadOnlyTree { diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index 6a5595afc..7004f39ab 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -183,7 +183,7 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP } } - var coinId types.CoinID + var coinId = checkState.App().GetNextCoinID() if deliverState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) @@ -193,8 +193,6 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP deliverState.Accounts.SubBalance(sender, types.GetBaseCoinID(), data.InitialReserve) deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) - coinID := deliverState.App.GetCoinsCount() + 1 - coinId = types.CoinID(coinID) deliverState.Coins.Create( coinId, data.Symbol, @@ -206,7 +204,7 @@ func (data CreateCoinData) Run(tx *Transaction, context state.Interface, rewardP &sender, ) - deliverState.App.SetCoinsCount(coinID) + deliverState.App.SetCoinsCount(coinId.Uint32()) deliverState.Accounts.AddBalance(sender, coinId, data.InitialAmount) deliverState.Accounts.SetNonce(sender, tx.Nonce) } diff --git a/core/transaction/edit_coin_owner.go b/core/transaction/edit_coin_owner.go index 79044e743..4cb7fa04f 100644 --- a/core/transaction/edit_coin_owner.go +++ b/core/transaction/edit_coin_owner.go @@ -99,7 +99,7 @@ func (data EditCoinOwnerData) Run(tx *Transaction, context state.Interface, rewa tags := kv.Pairs{ kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeEditCoinOwner)}))}, kv.Pair{Key: []byte("tx.from"), Value: []byte(hex.EncodeToString(sender[:]))}, - kv.Pair{Key: []byte("tx.coin"), Value: []byte(data.Symbol.String())}, + kv.Pair{Key: []byte("tx.coin_symbol"), Value: []byte(data.Symbol.String())}, } return Response{ diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 9443cccb0..d5f98958b 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -171,7 +171,7 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar } } - var coinId types.CoinID + var coinId = checkState.App().GetNextCoinID() if deliverState, ok := context.(*state.State); ok { rewardPool.Add(rewardPool, commissionInBaseCoin) @@ -181,7 +181,6 @@ func (data RecreateCoinData) Run(tx *Transaction, context state.Interface, rewar deliverState.Accounts.SubBalance(sender, types.GetBaseCoinID(), data.InitialReserve) deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) - coinId = deliverState.App.GetNextCoinID() deliverState.Coins.Recreate( coinId, data.Name, diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index f790d63f5..763a20718 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -235,7 +235,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeRedeemCheck)}))}, kv.Pair{Key: []byte("tx.from"), Value: []byte(hex.EncodeToString(checkSender[:]))}, kv.Pair{Key: []byte("tx.to"), Value: []byte(hex.EncodeToString(sender[:]))}, - kv.Pair{Key: []byte("tx.coin"), Value: []byte(decodedCheck.Coin.String())}, + kv.Pair{Key: []byte("tx.coin_id"), Value: []byte(decodedCheck.Coin.String())}, } return Response{ diff --git a/core/transaction/send.go b/core/transaction/send.go index 4bd87e330..9d4483120 100644 --- a/core/transaction/send.go +++ b/core/transaction/send.go @@ -138,7 +138,7 @@ func (data SendData) Run(tx *Transaction, context state.Interface, rewardPool *b kv.Pair{Key: []byte("tx.type"), Value: []byte(hex.EncodeToString([]byte{byte(TypeSend)}))}, kv.Pair{Key: []byte("tx.from"), Value: []byte(hex.EncodeToString(sender[:]))}, kv.Pair{Key: []byte("tx.to"), Value: []byte(hex.EncodeToString(data.To[:]))}, - kv.Pair{Key: []byte("tx.coin"), Value: []byte(data.Coin.String())}, + kv.Pair{Key: []byte("tx.coin_id"), Value: []byte(data.Coin.String())}, } return Response{ From dcbf30f2fa27d49cb7182770c651694229896fdd Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 18 Sep 2020 11:30:47 +0300 Subject: [PATCH 288/426] fix ws timeout --- api/v2/v2.go | 1 - 1 file changed, 1 deletion(-) diff --git a/api/v2/v2.go b/api/v2/v2.go index 5e9a3fd16..8440c0c1f 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -48,7 +48,6 @@ func Run(srv *service.Service, addrGRPC, addrApi string, traceLog bool) error { contextWithTimeoutInterceptor(srv.TimeoutDuration()), ), ) - runtime.DefaultContextTimeout = 10 * time.Second runtime.GlobalHTTPErrorHandler = httpError gw.RegisterApiServiceServer(grpcServer, srv) grpc_prometheus.Register(grpcServer) From 610d129ebf83d56c46316abab8f4e64907da8a8d Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 18 Sep 2020 11:33:54 +0300 Subject: [PATCH 289/426] clean up go.mod --- go.mod | 1 - go.sum | 25 ++++--------------------- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/go.mod b/go.mod index 5826ce4d6..4e586b7b2 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,6 @@ require ( github.com/tendermint/tm-db v0.5.1 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 github.com/urfave/cli/v2 v2.0.0 - gitlab.com/tslocum/cview v1.4.7 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 golang.org/x/net v0.0.0-20200822124328-c89045814202 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 diff --git a/go.sum b/go.sum index b08aec64c..0b1d77f55 100644 --- a/go.sum +++ b/go.sum @@ -4,7 +4,6 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= -github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200917115953-484c5d19df4d h1:OGb2maPQoa4+B1yiNlAQPP3wMqkI6+i1dtxXtsSVoxc= github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200917115953-484c5d19df4d/go.mod h1:ySmK0RhCHr7W0MoDmtED6ebYQcxYAXWPqAnvLFaWXEU= @@ -107,12 +106,10 @@ github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVB github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/gdamore/encoding v0.0.0-20151215212835-b23993cbb635 h1:hheUEMzaOie/wKeIc1WPa7CDVuIO5hqQxjS+dwTQEnI= github.com/gdamore/encoding v0.0.0-20151215212835-b23993cbb635/go.mod h1:yrQYJKKDTrHmbYxI7CYi+/hbdiDT2m4Hj+t0ikCjsrQ= -github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= -github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= +github.com/gdamore/tcell v1.1.0 h1:RbQgl7jukmdqROeNcKps7R2YfDCQbWkOd1BwdXrxfr4= github.com/gdamore/tcell v1.1.0/go.mod h1:tqyG50u7+Ctv1w5VX67kLzKcj9YXR/JSBZQq/+mLl1A= -github.com/gdamore/tcell v1.3.0 h1:r35w0JBADPZCVQijYebl6YMWWtHRqVEGt7kL2eBADRM= -github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= @@ -263,10 +260,8 @@ github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOS github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lucasb-eyer/go-colorful v0.0.0-20180709185858-c7842319cf3a h1:B2QfFRl5yGVGGcyEVFzfdXlC1BBvszsIAsCeef2oD0k= github.com/lucasb-eyer/go-colorful v0.0.0-20180709185858-c7842319cf3a/go.mod h1:NXg0ArsFk0Y01623LgUqoqcouGDB+PwCCQlrwrG6xJ4= -github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s= -github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac= -github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= @@ -283,13 +278,8 @@ github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW1 github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.6 h1:V2iyH+aX9C5fsYCpK60U8BYIvmhqxuOL3JZcqc1NB7k= github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.8 h1:3tS41NlGYSmhhe/8fhGRzc+z3AYCw1Fe1WAyLuujKs0= -github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-tty v0.0.3 h1:5OfyWorkyO7xP52Mq7tB36ajHDG5OHrmBGIS/DtakQI= github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= @@ -397,8 +387,6 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhD github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= -github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -482,10 +470,6 @@ github.com/urfave/cli/v2 v2.0.0 h1:+HU9SCbu8GnEUFtIBfuUNXN39ofWViIEJIp6SURMpCg= github.com/urfave/cli/v2 v2.0.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -gitlab.com/tslocum/cbind v0.1.1 h1:JXXtxMWHgWLvoF+QkrvcNvOQ59juy7OE1RhT7hZfdt0= -gitlab.com/tslocum/cbind v0.1.1/go.mod h1:rX7vkl0pUSg/yy427MmD1FZAf99S7WwpUlxF/qTpPqk= -gitlab.com/tslocum/cview v1.4.7 h1:8HkA2iwk9008FKDTbi6L0KkHoj2mFbgUW73DHw9iG1U= -gitlab.com/tslocum/cview v1.4.7/go.mod h1:87HOuFUfgmyY0zfg+7qKg6jyN9gI/znsa/KE2ZZHDSs= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -578,7 +562,6 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -587,7 +570,6 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgmDSfjglYZ3vStQ/gSCU= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121 h1:rITEj+UZHYC927n8GT97eC3zrpzXdb/voyeOuVKS46o= @@ -666,6 +648,7 @@ google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEG google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 h1:FVCohIoYO7IJoDDVpV2pdq7SgrMH6wHnuTyrdrxJNoY= gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtWgA5THM5lhBAw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 45b18c7cb3be3ddeb2cf3126d64a46d8a15567c3 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 18 Sep 2020 19:56:04 +0300 Subject: [PATCH 290/426] add log_level api:info --- api/v2/v2.go | 58 ++++++++++++++++++++++++++++++++---------- cmd/minter/cmd/node.go | 3 +-- go.mod | 2 +- go.sum | 18 +++++++++++++ 4 files changed, 64 insertions(+), 17 deletions(-) diff --git a/api/v2/v2.go b/api/v2/v2.go index 8440c0c1f..56292687e 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -4,23 +4,19 @@ import ( "context" "encoding/json" "fmt" - "mime" - "net" - "net/http" - "os" - "strconv" - "strings" - "time" - "github.com/MinterTeam/minter-go-node/api/v2/service" gw "github.com/MinterTeam/node-grpc-gateway/api_pb" _ "github.com/MinterTeam/node-grpc-gateway/statik" + kit_log "github.com/go-kit/kit/log" "github.com/gorilla/handlers" grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" + "github.com/grpc-ecosystem/go-grpc-middleware/logging/kit" grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" + grpc_ctxtags "github.com/grpc-ecosystem/go-grpc-middleware/tags" grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/rakyll/statik/fs" + "github.com/tendermint/tendermint/libs/log" "github.com/tmc/grpc-websocket-proxy/wsproxy" "golang.org/x/sync/errgroup" "google.golang.org/grpc" @@ -28,23 +24,39 @@ import ( "google.golang.org/grpc/grpclog" "google.golang.org/grpc/status" _struct "google.golang.org/protobuf/types/known/structpb" + "mime" + "net" + "net/http" + "strconv" + "strings" + "time" ) // Start gRPC and API v2 -func Run(srv *service.Service, addrGRPC, addrApi string, traceLog bool) error { +func Run(srv *service.Service, addrGRPC, addrApi string, logger log.Logger) error { lis, err := net.Listen("tcp", addrGRPC) if err != nil { return err } + // kitLogger := kit_log.NewJSONLogger(os.Stdout) // &kitLogger{logger} + kitLogger := &kitLogger{logger} + + loggerOpts := []kit.Option{ + kit.WithLevels(func(code codes.Code, logger kit_log.Logger) kit_log.Logger { return logger }), + } grpcServer := grpc.NewServer( grpc_middleware.WithStreamServerChain( grpc_prometheus.StreamServerInterceptor, + grpc_ctxtags.StreamServerInterceptor(requestExtractorFields()), + kit.StreamServerInterceptor(kitLogger, loggerOpts...), grpc_recovery.StreamServerInterceptor(), ), grpc_middleware.WithUnaryServerChain( grpc_prometheus.UnaryServerInterceptor, grpc_recovery.UnaryServerInterceptor(), + grpc_ctxtags.UnaryServerInterceptor(requestExtractorFields()), + kit.UnaryServerInterceptor(kitLogger, loggerOpts...), contextWithTimeoutInterceptor(srv.TimeoutDuration()), ), ) @@ -74,12 +86,9 @@ func Run(srv *service.Service, addrGRPC, addrApi string, traceLog bool) error { mux := http.NewServeMux() handler := wsproxy.WebsocketProxy(gwmux) - if traceLog { - handler = handlers.CombinedLoggingHandler(os.Stdout, handler) - } - mux.Handle("/", handler) + mux.Handle("/", handlers.CompressHandler(handler)) if err := serveOpenAPI(mux); err != nil { - //ignore + // ignore } group.Go(func() error { @@ -185,3 +194,24 @@ func httpError(ctx context.Context, mux *runtime.ServeMux, marshaler runtime.Mar w.Write([]byte(fallback)) } } + +func requestExtractorFields() grpc_ctxtags.Option { + return grpc_ctxtags.WithFieldExtractorForInitialReq(func(fullMethod string, req interface{}) map[string]interface{} { + retMap := make(map[string]interface{}) + marshal, _ := json.Marshal(req) + _ = json.Unmarshal(marshal, &retMap) + if len(retMap) == 0 { + return nil + } + return retMap + }) +} + +type kitLogger struct { + log.Logger +} + +func (l *kitLogger) Log(keyvals ...interface{}) error { + l.Info("API", keyvals...) + return nil +} diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index 5c69ee958..3305518d7 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -124,9 +124,8 @@ func runAPI(logger tmLog.Logger, app *minter.Blockchain, client *rpc.Local, node if err != nil { logger.Error("Failed to parse API v2 address", err) } - traceLog := os.Getenv("API_V2_LOG_LEVEL") == "trace" logger.Error("Failed to start Api V2 in both gRPC and RESTful", - apiV2.Run(srv, grpcURL.Host, apiV2url.Host, traceLog)) + apiV2.Run(srv, grpcURL.Host, apiV2url.Host, logger.With("module", "api"))) }(serviceApi.NewService(amino.NewCodec(), app, client, node, cfg, version.Version)) go apiV1.RunAPI(app, client, cfg, logger) diff --git a/go.mod b/go.mod index 4e586b7b2..600dd3901 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/google/uuid v1.1.1 github.com/gorilla/handlers v1.4.2 github.com/gorilla/websocket v1.4.2 - github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 + github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/grpc-gateway v1.14.8 github.com/marcusolsson/tui-go v0.4.0 diff --git a/go.sum b/go.sum index 0b1d77f55..5c2190e32 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,9 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= @@ -111,6 +113,7 @@ github.com/gdamore/encoding v0.0.0-20151215212835-b23993cbb635/go.mod h1:yrQYJKK github.com/gdamore/tcell v1.1.0 h1:RbQgl7jukmdqROeNcKps7R2YfDCQbWkOd1BwdXrxfr4= github.com/gdamore/tcell v1.1.0/go.mod h1:tqyG50u7+Ctv1w5VX67kLzKcj9YXR/JSBZQq/+mLl1A= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -188,6 +191,8 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0 h1:bM6ZAFZmc/wPFaRDi0d5L7hGEZEx/2u+Tmr2evNHDiI= @@ -502,14 +507,20 @@ golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -533,6 +544,7 @@ golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 h1:2mqDk8w/o6UmeUCu5Qiq2y7iM golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -559,11 +571,13 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -572,6 +586,7 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgm golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121 h1:rITEj+UZHYC927n8GT97eC3zrpzXdb/voyeOuVKS46o= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= @@ -596,6 +611,7 @@ golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114 h1:DnSr2mCsxyCE6ZgIkmcWUQY2R5cH/6wL7eIxEmQOMSE= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= @@ -613,6 +629,7 @@ google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70 h1:wboULUXGF3c5qdUnKp+6gLAccE6PRpa/czkYvQ4UXv8= @@ -633,6 +650,7 @@ google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k= google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.31.1 h1:SfXqXS5hkufcdZ/mHtYCh53P2b+92WQq/DZcKLgsFRs= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= From 739091599bbafdca6234ac71d2d661e34c0a3a65 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 18 Sep 2020 19:58:47 +0300 Subject: [PATCH 291/426] remove "data" from resultTx --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 600dd3901..f8e879217 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200917115953-484c5d19df4d + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200918113650-a0198fae398e github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 5c2190e32..49f7373aa 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200917115953-484c5d19df4d h1:OGb2maPQoa4+B1yiNlAQPP3wMqkI6+i1dtxXtsSVoxc= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200917115953-484c5d19df4d/go.mod h1:ySmK0RhCHr7W0MoDmtED6ebYQcxYAXWPqAnvLFaWXEU= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200918113650-a0198fae398e h1:KJ8UXR+Suh+xSwTN9DcK75EZ43Z5M+XYHeJzCpeuZ9g= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200918113650-a0198fae398e/go.mod h1:ySmK0RhCHr7W0MoDmtED6ebYQcxYAXWPqAnvLFaWXEU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 45beb726c0c407631dbae8323a24b08248367664 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 18 Sep 2020 20:05:18 +0300 Subject: [PATCH 292/426] refactor --- cmd/minter/cmd/node.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index 3305518d7..dd671f8a4 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -125,7 +125,7 @@ func runAPI(logger tmLog.Logger, app *minter.Blockchain, client *rpc.Local, node logger.Error("Failed to parse API v2 address", err) } logger.Error("Failed to start Api V2 in both gRPC and RESTful", - apiV2.Run(srv, grpcURL.Host, apiV2url.Host, logger.With("module", "api"))) + apiV2.Run(srv, grpcURL.Host, apiV2url.Host, logger.With("module", "rpc"))) }(serviceApi.NewService(amino.NewCodec(), app, client, node, cfg, version.Version)) go apiV1.RunAPI(app, client, cfg, logger) From b052e66ec599f09223f5e69b25994ea4135040e6 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 18 Sep 2020 21:26:11 +0300 Subject: [PATCH 293/426] refactor --- api/v2/service/service.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/api/v2/service/service.go b/api/v2/service/service.go index 83373a60c..0c671f93d 100644 --- a/api/v2/service/service.go +++ b/api/v2/service/service.go @@ -8,7 +8,6 @@ import ( "github.com/tendermint/go-amino" tmNode "github.com/tendermint/tendermint/node" rpc "github.com/tendermint/tendermint/rpc/client/local" - "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "time" ) @@ -72,11 +71,7 @@ func (s *Service) TimeoutDuration() time.Duration { func (s *Service) checkTimeout(ctx context.Context) *status.Status { select { case <-ctx.Done(): - if ctx.Err() != context.DeadlineExceeded { - return status.New(codes.Canceled, ctx.Err().Error()) - } - - return status.New(codes.DeadlineExceeded, ctx.Err().Error()) + return status.FromContextError(ctx.Err()) default: return nil } From e2a6ab331260529ba626e422736ce83bdc76ca59 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 18 Sep 2020 22:05:47 +0300 Subject: [PATCH 294/426] refactor --- api/v2/service/ws.go | 4 +++- api/v2/v2.go | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/api/v2/service/ws.go b/api/v2/service/ws.go index 4a19ee765..080c68d98 100644 --- a/api/v2/service/ws.go +++ b/api/v2/service/ws.go @@ -13,7 +13,7 @@ import ( ) const ( - SubscribeTimeout = 5 * time.Second + SubscribeTimeout = 15 * time.Second ) // Subscribe returns a subscription for events by query. @@ -42,6 +42,8 @@ func (s *Service) Subscribe(request *pb.SubscribeRequest, stream pb.ApiService_S select { case <-stream.Context().Done(): return stream.Context().Err() + case <-subCtx.Done(): + return stream.Context().Err() case msg, ok := <-sub: if !ok { return nil diff --git a/api/v2/v2.go b/api/v2/v2.go index 56292687e..a829e5874 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -48,16 +48,16 @@ func Run(srv *service.Service, addrGRPC, addrApi string, logger log.Logger) erro grpcServer := grpc.NewServer( grpc_middleware.WithStreamServerChain( grpc_prometheus.StreamServerInterceptor, + grpc_recovery.StreamServerInterceptor(), grpc_ctxtags.StreamServerInterceptor(requestExtractorFields()), kit.StreamServerInterceptor(kitLogger, loggerOpts...), - grpc_recovery.StreamServerInterceptor(), ), grpc_middleware.WithUnaryServerChain( grpc_prometheus.UnaryServerInterceptor, grpc_recovery.UnaryServerInterceptor(), grpc_ctxtags.UnaryServerInterceptor(requestExtractorFields()), kit.UnaryServerInterceptor(kitLogger, loggerOpts...), - contextWithTimeoutInterceptor(srv.TimeoutDuration()), + unaryTimeoutInterceptor(srv.TimeoutDuration()), ), ) runtime.GlobalHTTPErrorHandler = httpError @@ -134,7 +134,7 @@ func serveOpenAPI(mux *http.ServeMux) error { return nil } -func contextWithTimeoutInterceptor(timeout time.Duration) func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { +func unaryTimeoutInterceptor(timeout time.Duration) func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { withTimeout, _ := context.WithTimeout(ctx, timeout) return handler(withTimeout, req) From 0cec06e8f984a9e0c66d4b45dcac1c27237b2397 Mon Sep 17 00:00:00 2001 From: klim0v Date: Sat, 19 Sep 2020 00:20:29 +0300 Subject: [PATCH 295/426] update OpenAPI --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f8e879217..d60548de3 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200918113650-a0198fae398e + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200918211905-799cc7aba34d github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 49f7373aa..69a0612c8 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200918113650-a0198fae398e h1:KJ8UXR+Suh+xSwTN9DcK75EZ43Z5M+XYHeJzCpeuZ9g= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200918113650-a0198fae398e/go.mod h1:ySmK0RhCHr7W0MoDmtED6ebYQcxYAXWPqAnvLFaWXEU= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200918211905-799cc7aba34d h1:hLzu3T2OXQyVcnhis8bh1kDMSIK/ElVpm/C36kuJS0E= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200918211905-799cc7aba34d/go.mod h1:ySmK0RhCHr7W0MoDmtED6ebYQcxYAXWPqAnvLFaWXEU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 6a3915d36a9f258788055be6cb271c8da2129678 Mon Sep 17 00:00:00 2001 From: klim0v Date: Sat, 19 Sep 2020 02:14:05 +0300 Subject: [PATCH 296/426] refactor --- api/v2/service/ws.go | 10 ++++------ api/v2/v2.go | 1 - 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/api/v2/service/ws.go b/api/v2/service/ws.go index 080c68d98..68215c3a0 100644 --- a/api/v2/service/ws.go +++ b/api/v2/service/ws.go @@ -25,10 +25,10 @@ func (s *Service) Subscribe(request *pb.SubscribeRequest, stream pb.ApiService_S s.client.Logger.Info("Subscribe to query", "query", request.Query) - subCtx, cancel := context.WithTimeout(stream.Context(), SubscribeTimeout) + ctx, cancel := context.WithTimeout(stream.Context(), SubscribeTimeout) defer cancel() subscriber := uuid.New().String() - sub, err := s.client.Subscribe(subCtx, subscriber, request.Query) + sub, err := s.client.Subscribe(ctx, subscriber, request.Query) if err != nil { return status.Error(codes.Internal, err.Error()) } @@ -40,10 +40,8 @@ func (s *Service) Subscribe(request *pb.SubscribeRequest, stream pb.ApiService_S for { select { - case <-stream.Context().Done(): - return stream.Context().Err() - case <-subCtx.Done(): - return stream.Context().Err() + case <-ctx.Done(): + return status.FromContextError(stream.Context().Err()).Err() case msg, ok := <-sub: if !ok { return nil diff --git a/api/v2/v2.go b/api/v2/v2.go index a829e5874..808f264ae 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -39,7 +39,6 @@ func Run(srv *service.Service, addrGRPC, addrApi string, logger log.Logger) erro return err } - // kitLogger := kit_log.NewJSONLogger(os.Stdout) // &kitLogger{logger} kitLogger := &kitLogger{logger} loggerOpts := []kit.Option{ From 300d69a22b9199757883bbf28f6026332b2116dc Mon Sep 17 00:00:00 2001 From: klim0v Date: Sun, 20 Sep 2020 00:39:27 +0300 Subject: [PATCH 297/426] add prefix v2 --- api/v2/v2.go | 8 +++----- go.mod | 2 +- go.sum | 5 +++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/api/v2/v2.go b/api/v2/v2.go index 808f264ae..8b846d5bc 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -83,9 +83,7 @@ func Run(srv *service.Service, addrGRPC, addrApi string, logger log.Logger) erro return gw.RegisterApiServiceHandlerFromEndpoint(ctx, gwmux, addrGRPC, opts) }) mux := http.NewServeMux() - handler := wsproxy.WebsocketProxy(gwmux) - - mux.Handle("/", handlers.CompressHandler(handler)) + mux.Handle("/v2/", http.StripPrefix("/v2", handlers.CompressHandler(wsproxy.WebsocketProxy(gwmux)))) if err := serveOpenAPI(mux); err != nil { // ignore } @@ -126,9 +124,9 @@ func serveOpenAPI(mux *http.ServeMux) error { return err } - // Expose files in static on /openapi-ui + // Expose files in static on /v2/openapi-ui fileServer := http.FileServer(statikFS) - prefix := "/openapi-ui/" + prefix := "/v2/openapi-ui/" mux.Handle(prefix, http.StripPrefix(prefix, fileServer)) return nil } diff --git a/go.mod b/go.mod index d60548de3..9cf6b443e 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200918211905-799cc7aba34d + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200919195438-b83fa5d5c167 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 69a0612c8..7ad7f612c 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200918211905-799cc7aba34d h1:hLzu3T2OXQyVcnhis8bh1kDMSIK/ElVpm/C36kuJS0E= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200918211905-799cc7aba34d/go.mod h1:ySmK0RhCHr7W0MoDmtED6ebYQcxYAXWPqAnvLFaWXEU= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200919195438-b83fa5d5c167 h1:5mPDx6AJX2ZIfLmjAWbkDGgU7u8VdKTVRKI/z6SWMrw= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200919195438-b83fa5d5c167/go.mod h1:ySmK0RhCHr7W0MoDmtED6ebYQcxYAXWPqAnvLFaWXEU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= @@ -183,6 +183,7 @@ github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51 github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= From 9b371306a5c3a05284254b5448a03b4e068d0c22 Mon Sep 17 00:00:00 2001 From: klim0v Date: Sun, 20 Sep 2020 00:49:46 +0300 Subject: [PATCH 298/426] refactor --- api/v2/v2.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v2/v2.go b/api/v2/v2.go index 8b846d5bc..c65730a9e 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -83,13 +83,13 @@ func Run(srv *service.Service, addrGRPC, addrApi string, logger log.Logger) erro return gw.RegisterApiServiceHandlerFromEndpoint(ctx, gwmux, addrGRPC, opts) }) mux := http.NewServeMux() - mux.Handle("/v2/", http.StripPrefix("/v2", handlers.CompressHandler(wsproxy.WebsocketProxy(gwmux)))) + mux.Handle("/v2/", http.StripPrefix("/v2", handlers.CompressHandler(allowCORS(wsproxy.WebsocketProxy(gwmux))))) if err := serveOpenAPI(mux); err != nil { // ignore } group.Go(func() error { - return http.ListenAndServe(addrApi, allowCORS(mux)) + return http.ListenAndServe(addrApi, mux) }) return group.Wait() From 09f1c86a23b31e5e90aa01a827fd04e2417fda9c Mon Sep 17 00:00:00 2001 From: klim0v Date: Sun, 20 Sep 2020 16:07:12 +0300 Subject: [PATCH 299/426] api frozen --- api/v2/service/frozen.go | 81 ++++++++++++-------------- core/state/frozenfunds/frozen_funds.go | 1 + go.mod | 2 +- go.sum | 4 +- 4 files changed, 41 insertions(+), 47 deletions(-) diff --git a/api/v2/service/frozen.go b/api/v2/service/frozen.go index 3c6ad368f..e11d4c084 100644 --- a/api/v2/service/frozen.go +++ b/api/v2/service/frozen.go @@ -2,8 +2,11 @@ package service import ( "context" - "encoding/hex" "fmt" + "github.com/MinterTeam/minter-go-node/core/code" + "github.com/MinterTeam/minter-go-node/core/state/candidates" + "github.com/MinterTeam/minter-go-node/core/state/coins" + "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/core/types" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" @@ -17,68 +20,58 @@ func (s *Service) Frozen(ctx context.Context, req *pb.FrozenRequest) (*pb.Frozen return new(pb.FrozenResponse), status.Error(codes.InvalidArgument, "invalid address") } - decodeString, err := hex.DecodeString(req.Address[2:]) - if err != nil { - return new(pb.FrozenResponse), status.Error(codes.InvalidArgument, "invalid address") - } - - address := types.BytesToAddress(decodeString) - cState := s.blockchain.CurrentState() cState.RLock() defer cState.RUnlock() + var reqCoin *coins.Model + + if req.CoinId != nil { + coinID := types.CoinID(req.CoinId.GetValue()) + reqCoin = cState.Coins().GetCoin(coinID) + if reqCoin == nil { + return new(pb.FrozenResponse), s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(transaction.EncodeError(code.NewCoinNotExists("", coinID.String())))) + } + } var frozen []*pb.FrozenResponse_Frozen - appState := new(types.AppState) - cState.FrozenFunds().Export(appState, s.blockchain.Height()) + cState.FrozenFunds().GetFrozenFunds(s.blockchain.Height()) - var emptyAddress types.Address + for i := s.blockchain.Height(); i <= s.blockchain.Height()+candidates.UnbondPeriod; i++ { - if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.FrozenResponse), timeoutStatus.Err() - } + if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { + return new(pb.FrozenResponse), timeoutStatus.Err() + } - if req.Coin == "" && address == emptyAddress { - for _, fund := range appState.FrozenFunds { - frozen = append(frozen, &pb.FrozenResponse_Frozen{ - Height: fmt.Sprintf("%d", fund.Height), - Address: fund.Address.String(), - CandidateKey: fund.CandidateKey.String(), - Coin: fund.Coin.String(), - Value: fund.Value, - }) + funds := cState.FrozenFunds().GetFrozenFunds(i) + if funds == nil { + continue } - return &pb.FrozenResponse{Frozen: frozen}, nil - } - if req.Coin != "" && address != emptyAddress { - for _, fund := range appState.FrozenFunds { - if fund.Coin.String() != req.Coin || fund.Address != address { + for _, fund := range funds.List { + if fund.Address.String() != req.Address { continue } + coin := reqCoin + if coin == nil { + coin = cState.Coins().GetCoin(fund.Coin) + } else { + if coin.ID() != fund.Coin { + continue + } + } frozen = append(frozen, &pb.FrozenResponse_Frozen{ - Height: fmt.Sprintf("%d", fund.Height), + Height: fmt.Sprintf("%d", funds.Height()), Address: fund.Address.String(), CandidateKey: fund.CandidateKey.String(), - Coin: fund.Coin.String(), - Value: fund.Value, + Coin: &pb.Coin{ + Id: fund.Coin.String(), + Symbol: coin.GetFullSymbol(), + }, + Value: fund.Value.String(), }) } - return &pb.FrozenResponse{Frozen: frozen}, nil } - for _, fund := range appState.FrozenFunds { - if fund.Coin.String() != req.Coin && fund.Address != address { - continue - } - frozen = append(frozen, &pb.FrozenResponse_Frozen{ - Height: fmt.Sprintf("%d", fund.Height), - Address: fund.Address.String(), - CandidateKey: fund.CandidateKey.String(), - Coin: fund.Coin.String(), - Value: fund.Value, - }) - } return &pb.FrozenResponse{Frozen: frozen}, nil } diff --git a/core/state/frozenfunds/frozen_funds.go b/core/state/frozenfunds/frozen_funds.go index 37d03976e..b0b230e6d 100644 --- a/core/state/frozenfunds/frozen_funds.go +++ b/core/state/frozenfunds/frozen_funds.go @@ -20,6 +20,7 @@ const mainPrefix = byte('f') type RFrozenFunds interface { Export(state *types.AppState, height uint64) + GetFrozenFunds(height uint64) *Model } type FrozenFunds struct { diff --git a/go.mod b/go.mod index 9cf6b443e..89c39598b 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200919195438-b83fa5d5c167 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200920125449-53e6ef7aaa48 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 7ad7f612c..d9c1b8a28 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200919195438-b83fa5d5c167 h1:5mPDx6AJX2ZIfLmjAWbkDGgU7u8VdKTVRKI/z6SWMrw= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200919195438-b83fa5d5c167/go.mod h1:ySmK0RhCHr7W0MoDmtED6ebYQcxYAXWPqAnvLFaWXEU= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200920125449-53e6ef7aaa48 h1:f/eDnYQJtQbyqGD+b0ylkHAXKMqPP68XSE0d4/k0wPk= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200920125449-53e6ef7aaa48/go.mod h1:ySmK0RhCHr7W0MoDmtED6ebYQcxYAXWPqAnvLFaWXEU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From aaa380099c6eafaf52cc936e0e07324361b446b5 Mon Sep 17 00:00:00 2001 From: klim0v Date: Sun, 20 Sep 2020 22:42:08 +0300 Subject: [PATCH 300/426] update grpc-gateway --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 89c39598b..68a39d716 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200920125449-53e6ef7aaa48 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200920180544-2bc88646bf02 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 @@ -13,7 +13,7 @@ require ( github.com/gorilla/websocket v1.4.2 github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 - github.com/grpc-ecosystem/grpc-gateway v1.14.8 + github.com/grpc-ecosystem/grpc-gateway v1.15.0 github.com/marcusolsson/tui-go v0.4.0 github.com/mattn/go-tty v0.0.3 // indirect github.com/pkg/errors v0.9.1 @@ -36,6 +36,6 @@ require ( golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 golang.org/x/sys v0.0.0-20200523222454-059865788121 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - google.golang.org/grpc v1.31.1 + google.golang.org/grpc v1.32.0 google.golang.org/protobuf v1.25.0 ) diff --git a/go.sum b/go.sum index d9c1b8a28..02d54cec6 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200920125449-53e6ef7aaa48 h1:f/eDnYQJtQbyqGD+b0ylkHAXKMqPP68XSE0d4/k0wPk= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200920125449-53e6ef7aaa48/go.mod h1:ySmK0RhCHr7W0MoDmtED6ebYQcxYAXWPqAnvLFaWXEU= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200920180544-2bc88646bf02 h1:HJBzwDqs7xSCYRkJ6ehUJ3+ScLzFY2gg8mo3aRptsPs= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200920180544-2bc88646bf02/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= @@ -199,8 +199,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0 h1:bM6ZAFZmc/wPFaRDi0d5L7hGEZEx/2u+Tmr2evNHDiI= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.14.8 h1:hXClj+iFpmLM8i3lkO6i4Psli4P2qObQuQReiII26U8= -github.com/grpc-ecosystem/grpc-gateway v1.14.8/go.mod h1:NZE8t6vs6TnwLL/ITkaK8W3ecMLGAbh2jXTclvpiwYo= +github.com/grpc-ecosystem/grpc-gateway v1.15.0 h1:ntPNC9TD/6l2XDenJZe6T5lSMg95thpV9sGAqHX4WU8= +github.com/grpc-ecosystem/grpc-gateway v1.15.0/go.mod h1:vO11I9oWA+KsxmfFQPhLnnIb1VDE24M+pdxZFiuZcA8= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f h1:8N8XWLZelZNibkhM1FuF+3Ad3YIbgirjdMiVA0eUkaM= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= @@ -652,8 +652,8 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k= google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.31.1 h1:SfXqXS5hkufcdZ/mHtYCh53P2b+92WQq/DZcKLgsFRs= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.32.0 h1:zWTV+LMdc3kaiJMSTOFz2UgSBgx8RNQoTGiZu3fR9S0= +google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 7456ca421eb6fab2d81d146a5341964631d29db8 Mon Sep 17 00:00:00 2001 From: klim0v Date: Sun, 20 Sep 2020 22:46:03 +0300 Subject: [PATCH 301/426] optimization --- api/v2/v2.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/api/v2/v2.go b/api/v2/v2.go index c65730a9e..a7ead8aaf 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -79,9 +79,10 @@ func Run(srv *service.Service, addrGRPC, addrApi string, logger log.Logger) erro grpc.WithInsecure(), grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(50000000)), } - group.Go(func() error { - return gw.RegisterApiServiceHandlerFromEndpoint(ctx, gwmux, addrGRPC, opts) - }) + err = gw.RegisterApiServiceHandlerFromEndpoint(ctx, gwmux, addrGRPC, opts) + if err != nil { + return err + } mux := http.NewServeMux() mux.Handle("/v2/", http.StripPrefix("/v2", handlers.CompressHandler(allowCORS(wsproxy.WebsocketProxy(gwmux))))) if err := serveOpenAPI(mux); err != nil { From c77cb45ab97bcf78ee3f9649e21503170595f6d5 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 21 Sep 2020 10:33:07 +0300 Subject: [PATCH 302/426] update gateway doc --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 68a39d716..f38d1d075 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200920180544-2bc88646bf02 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200921073010-0e0331cde460 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 02d54cec6..2e70ca8c2 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200920180544-2bc88646bf02 h1:HJBzwDqs7xSCYRkJ6ehUJ3+ScLzFY2gg8mo3aRptsPs= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200920180544-2bc88646bf02/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200921073010-0e0331cde460 h1:joYzlUOfkSr2j+jmkMxXqLF5HguzwlYx6lfJmE6/brs= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200921073010-0e0331cde460/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From ca7d011a28bbccd858339e7af588d2f0e7251084 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 21 Sep 2020 10:40:35 +0300 Subject: [PATCH 303/426] fix error messages --- api/v2/service/coin_info.go | 2 +- api/v2/service/estimate_coin_sell_all.go | 2 +- api/v2/service/frozen.go | 2 +- core/transaction/unbond.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index 655d2fbd4..4bca3f252 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -65,7 +65,7 @@ func (s *Service) CoinInfoById(ctx context.Context, req *pb.CoinIdRequest) (*pb. coin := cState.Coins().GetCoin(types.CoinID(req.Id)) if coin == nil { - return new(pb.CoinInfoResponse), s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(transaction.EncodeError(code.NewCoinNotExists("", strconv.Itoa(int(req.Id)))))) + return new(pb.CoinInfoResponse), s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(code.NewCoinNotExists("", strconv.Itoa(int(req.Id))))) } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index 41b352afb..31eb26b17 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -44,7 +44,7 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS } else { coinToBuy = types.CoinID(req.GetCoinIdToBuy()) if !cState.Coins().Exists(coinToBuy) { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(transaction.EncodeError(code.NewCoinNotExists("", coinToBuy.String())))) + return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(code.NewCoinNotExists("", coinToBuy.String()))) } } diff --git a/api/v2/service/frozen.go b/api/v2/service/frozen.go index e11d4c084..a566e4dc1 100644 --- a/api/v2/service/frozen.go +++ b/api/v2/service/frozen.go @@ -30,7 +30,7 @@ func (s *Service) Frozen(ctx context.Context, req *pb.FrozenRequest) (*pb.Frozen coinID := types.CoinID(req.CoinId.GetValue()) reqCoin = cState.Coins().GetCoin(coinID) if reqCoin == nil { - return new(pb.FrozenResponse), s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(transaction.EncodeError(code.NewCoinNotExists("", coinID.String())))) + return new(pb.FrozenResponse), s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(code.NewCoinNotExists("", coinID.String()))) } } var frozen []*pb.FrozenResponse_Frozen diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index a283a845d..10692b5d9 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -66,7 +66,7 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R return &Response{ Code: code.StakeNotFound, Log: fmt.Sprintf("Stake of current user not found"), - Info: EncodeError(EncodeError(code.NewStakeNotFound(data.PubKey.String(), sender.String(), data.Coin.String(), context.Coins().GetCoin(data.Coin).GetFullSymbol()))), + Info: EncodeError(code.NewStakeNotFound(data.PubKey.String(), sender.String(), data.Coin.String(), context.Coins().GetCoin(data.Coin).GetFullSymbol())), } } From bc73bfdc5b37943a91ce6256121a790fa4b7f85c Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 22 Sep 2020 14:01:09 +0300 Subject: [PATCH 304/426] refactor --- api/api.go | 2 +- api/v2/service/data_encoder.go | 22 +-------------------- api/v2/service/ws.go | 2 +- api/v2/v2.go | 6 +----- cli/service/client.go | 6 +++--- cli/service/server.go | 1 - core/minter/minter_test.go | 3 +-- core/statistics/statistics.go | 4 +--- core/transaction/buy_coin.go | 2 +- core/transaction/buy_coin_test.go | 3 --- core/transaction/create_coin.go | 4 ++-- core/transaction/create_multisig.go | 2 +- core/transaction/declare_candidacy.go | 4 ++-- core/transaction/delegate.go | 6 +++--- core/transaction/edit_candidate.go | 2 +- core/transaction/edit_multisig.go | 6 +++--- core/transaction/multisend.go | 2 +- core/transaction/recreate_coin.go | 2 +- core/transaction/redeem_check.go | 10 +++++----- core/transaction/sell_all_coin.go | 10 +++++----- core/transaction/sell_coin.go | 6 +++--- core/transaction/set_halt_block.go | 2 +- core/transaction/switch_candidate_status.go | 2 +- core/transaction/unbond.go | 8 ++++---- go.mod | 2 +- go.sum | 4 ++-- 26 files changed, 46 insertions(+), 77 deletions(-) diff --git a/api/api.go b/api/api.go index 66e58fa03..d7c974f47 100644 --- a/api/api.go +++ b/api/api.go @@ -61,7 +61,7 @@ func responseTime(b *minter.Blockchain) func(f func(http.ResponseWriter, *http.R return func(w http.ResponseWriter, r *http.Request) { start := time.Now() f(w, r) - go b.StatisticData().SetApiTime(time.Now().Sub(start), r.URL.Path) + go b.StatisticData().SetApiTime(time.Since(start), r.URL.Path) } } } diff --git a/api/v2/service/data_encoder.go b/api/v2/service/data_encoder.go index 268919717..eff64c4e0 100644 --- a/api/v2/service/data_encoder.go +++ b/api/v2/service/data_encoder.go @@ -14,9 +14,8 @@ import ( func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { var m proto.Message - switch data.(type) { + switch d := data.(type) { case *transaction.BuyCoinData: - d := data.(*transaction.BuyCoinData) m = &pb.BuyCoinData{ CoinToBuy: &pb.Coin{ Id: d.CoinToBuy.String(), @@ -30,13 +29,11 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { MaximumValueToSell: d.MaximumValueToSell.String(), } case *transaction.EditCoinOwnerData: - d := data.(*transaction.EditCoinOwnerData) m = &pb.EditCoinOwnerData{ Symbol: d.Symbol.String(), NewOwner: d.NewOwner.String(), } case *transaction.CreateCoinData: - d := data.(*transaction.CreateCoinData) m = &pb.CreateCoinData{ Name: d.Name, Symbol: d.Symbol.String(), @@ -46,7 +43,6 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { MaxSupply: d.MaxSupply.String(), } case *transaction.CreateMultisigData: - d := data.(*transaction.CreateMultisigData) weights := make([]string, 0, len(d.Weights)) for _, weight := range d.Weights { weights = append(weights, strconv.Itoa(int(weight))) @@ -61,7 +57,6 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { Addresses: addresses, } case *transaction.DeclareCandidacyData: - d := data.(*transaction.DeclareCandidacyData) m = &pb.DeclareCandidacyData{ Address: d.Address.String(), PubKey: d.PubKey.String(), @@ -73,7 +68,6 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { Stake: d.Stake.String(), } case *transaction.DelegateData: - d := data.(*transaction.DelegateData) m = &pb.DelegateData{ PubKey: d.PubKey.String(), Coin: &pb.Coin{ @@ -83,7 +77,6 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { Value: d.Value.String(), } case *transaction.EditCandidateData: - d := data.(*transaction.EditCandidateData) m = &pb.EditCandidateData{ PubKey: d.PubKey.String(), RewardAddress: d.RewardAddress.String(), @@ -91,13 +84,11 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { ControlAddress: d.ControlAddress.String(), } case *transaction.EditCandidatePublicKeyData: - d := data.(*transaction.EditCandidatePublicKeyData) m = &pb.EditCandidatePublicKeyData{ PubKey: d.PubKey.String(), NewPubKey: d.NewPubKey.String(), } case *transaction.EditMultisigData: - d := data.(*transaction.EditMultisigData) weights := make([]string, 0, len(d.Weights)) for _, weight := range d.Weights { weights = append(weights, strconv.Itoa(int(weight))) @@ -112,7 +103,6 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { Addresses: addresses, } case *transaction.MultisendData: - d := data.(*transaction.MultisendData) list := make([]*pb.SendData, 0, len(d.List)) for _, item := range d.List { list = append(list, &pb.SendData{ @@ -128,12 +118,10 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { List: list, } case *transaction.PriceVoteData: - d := data.(*transaction.PriceVoteData) m = &pb.PriceVoteData{ Price: strconv.Itoa(int(d.Price)), } case *transaction.RecreateCoinData: - d := data.(*transaction.RecreateCoinData) m = &pb.RecreateCoinData{ Name: d.Name, Symbol: d.Symbol.String(), @@ -143,13 +131,11 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { MaxSupply: d.MaxSupply.String(), } case *transaction.RedeemCheckData: - d := data.(*transaction.RedeemCheckData) m = &pb.RedeemCheckData{ RawCheck: base64.StdEncoding.EncodeToString(d.RawCheck), Proof: base64.StdEncoding.EncodeToString(d.Proof[:]), } case *transaction.SellAllCoinData: - d := data.(*transaction.SellAllCoinData) m = &pb.SellAllCoinData{ CoinToSell: &pb.Coin{ Id: d.CoinToSell.String(), @@ -162,7 +148,6 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { MinimumValueToBuy: d.MinimumValueToBuy.String(), } case *transaction.SellCoinData: - d := data.(*transaction.SellCoinData) m = &pb.SellCoinData{ CoinToSell: &pb.Coin{ Id: d.CoinToSell.String(), @@ -176,7 +161,6 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { MinimumValueToBuy: d.MinimumValueToBuy.String(), } case *transaction.SendData: - d := data.(*transaction.SendData) m = &pb.SendData{ Coin: &pb.Coin{ Id: d.Coin.String(), @@ -186,23 +170,19 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { Value: d.Value.String(), } case *transaction.SetHaltBlockData: - d := data.(*transaction.SetHaltBlockData) m = &pb.SetHaltBlockData{ PubKey: d.PubKey.String(), Height: strconv.Itoa(int(d.Height)), } case *transaction.SetCandidateOnData: - d := data.(*transaction.SetCandidateOnData) m = &pb.SetCandidateOnData{ PubKey: d.PubKey.String(), } case *transaction.SetCandidateOffData: - d := data.(*transaction.SetCandidateOffData) m = &pb.SetCandidateOffData{ PubKey: d.PubKey.String(), } case *transaction.UnbondData: - d := data.(*transaction.UnbondData) m = &pb.UnbondData{ PubKey: d.PubKey.String(), Coin: &pb.Coin{ diff --git a/api/v2/service/ws.go b/api/v2/service/ws.go index 68215c3a0..ccdaec5a7 100644 --- a/api/v2/service/ws.go +++ b/api/v2/service/ws.go @@ -30,7 +30,7 @@ func (s *Service) Subscribe(request *pb.SubscribeRequest, stream pb.ApiService_S subscriber := uuid.New().String() sub, err := s.client.Subscribe(ctx, subscriber, request.Query) if err != nil { - return status.Error(codes.Internal, err.Error()) + return status.Error(codes.InvalidArgument, err.Error()) } defer func() { if err := s.client.UnsubscribeAll(context.Background(), subscriber); err != nil { diff --git a/api/v2/v2.go b/api/v2/v2.go index a7ead8aaf..6b45bd3a5 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -85,10 +85,7 @@ func Run(srv *service.Service, addrGRPC, addrApi string, logger log.Logger) erro } mux := http.NewServeMux() mux.Handle("/v2/", http.StripPrefix("/v2", handlers.CompressHandler(allowCORS(wsproxy.WebsocketProxy(gwmux))))) - if err := serveOpenAPI(mux); err != nil { - // ignore - } - + _ = serveOpenAPI(mux) group.Go(func() error { return http.ListenAndServe(addrApi, mux) }) @@ -114,7 +111,6 @@ func preflightHandler(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Access-Control-Allow-Headers", strings.Join(headers, ",")) methods := []string{"GET", "HEAD", "POST", "PUT", "DELETE"} w.Header().Set("Access-Control-Allow-Methods", strings.Join(methods, ",")) - return } func serveOpenAPI(mux *http.ServeMux) error { diff --git a/cli/service/client.go b/cli/service/client.go index 4eb8f7c11..d0ecdb317 100644 --- a/cli/service/client.go +++ b/cli/service/client.go @@ -121,7 +121,7 @@ func NewCLI(socketPath string) (*ManagerConsole, error) { app := cli.NewApp() app.CommandNotFound = func(ctx *cli.Context, cmd string) { - fmt.Println(fmt.Sprintf("No help topic for '%v'", cmd)) + fmt.Printf("No help topic for '%v'\n", cmd) } app.UseShortOptionHandling = true jsonFlag := &cli.BoolFlag{Name: "json", Aliases: []string{"j"}, Required: false, Usage: "echo in json format"} @@ -347,7 +347,7 @@ func netInfoCMD(client pb.ManagerServiceClient) func(c *cli.Context) error { if err != nil { return err } - fmt.Println(string(bb.Bytes())) + fmt.Println(bb.String()) return nil } fmt.Println(proto.MarshalTextString(response)) @@ -367,7 +367,7 @@ func statusCMD(client pb.ManagerServiceClient) func(c *cli.Context) error { if err != nil { return err } - fmt.Println(string(bb.Bytes())) + fmt.Println(bb.String()) return nil } fmt.Println(proto.MarshalTextString(response)) diff --git a/cli/service/server.go b/cli/service/server.go index 3ccac407d..ba634fbd2 100644 --- a/cli/service/server.go +++ b/cli/service/server.go @@ -39,7 +39,6 @@ func StartCLIServer(socketPath string, manager pb.ManagerServiceServer, ctx cont server.GracefulStop() case <-kill: } - return }() if err := server.Serve(lis); err != nil { diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index 26f0fb183..c1f6bff9c 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -29,7 +29,6 @@ import ( "github.com/tendermint/tendermint/privval" "github.com/tendermint/tendermint/proxy" rpc "github.com/tendermint/tendermint/rpc/client/local" - _ "github.com/tendermint/tendermint/types" types2 "github.com/tendermint/tendermint/types" "math/big" "math/rand" @@ -376,7 +375,7 @@ func TestBlockchain_GetStateForHeightAndDeleteStateVersions(t *testing.T) { t.Fatalf("Failed: %s", err.Error()) } - checkState, err = blockchain.GetStateForHeight(uint64(resultTx.Height - 1)) + _, err = blockchain.GetStateForHeight(uint64(resultTx.Height - 1)) if err == nil { t.Fatalf("Failed: %s", "state not deleted") } diff --git a/core/statistics/statistics.go b/core/statistics/statistics.go index 050d554b3..092e24a0e 100644 --- a/core/statistics/statistics.go +++ b/core/statistics/statistics.go @@ -199,7 +199,7 @@ func (d *Data) handleStartBlocks(ctx context.Context) { for { d.BlockStart.RLock() - ok := (height == d.BlockStart.height+1) || 0 == d.BlockStart.height + ok := (height == d.BlockStart.height+1) || d.BlockStart.height == 0 d.BlockStart.RUnlock() if ok { break @@ -295,8 +295,6 @@ func (d *Data) handleEndBlock(ctx context.Context) { d.Speed.startTime = time.Now().Add(-12 * time.Hour) d.Speed.startHeight = height - (height-d.Speed.startHeight)/2 d.Speed.duration = d.Speed.duration/2 + duration.Nanoseconds() - - return }() } } diff --git a/core/transaction/buy_coin.go b/core/transaction/buy_coin.go index 3156743b6..af4aa27e2 100644 --- a/core/transaction/buy_coin.go +++ b/core/transaction/buy_coin.go @@ -329,7 +329,7 @@ func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.CheckState) * if data.CoinToSell == data.CoinToBuy { return &Response{ Code: code.CrossConvert, - Log: fmt.Sprintf("\"From\" coin equals to \"to\" coin"), + Log: "\"From\" coin equals to \"to\" coin", Info: EncodeError(code.NewCrossConvert( data.CoinToSell.String(), context.Coins().GetCoin(data.CoinToSell).Symbol().String(), diff --git a/core/transaction/buy_coin_test.go b/core/transaction/buy_coin_test.go index 0d0922be0..f281ec4c0 100644 --- a/core/transaction/buy_coin_test.go +++ b/core/transaction/buy_coin_test.go @@ -16,13 +16,10 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/rlp" - "github.com/tendermint/go-amino" db "github.com/tendermint/tm-db" ) var ( - cdc = amino.NewCodec() - rnd = rand.New(rand.NewSource(time.Now().Unix())) ) diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index 7004f39ab..64fc9a437 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -62,7 +62,7 @@ func (data CreateCoinData) BasicCheck(tx *Transaction, context *state.CheckState if context.Coins().ExistsBySymbol(data.Symbol) { return &Response{ Code: code.CoinAlreadyExists, - Log: fmt.Sprintf("Coin already exists"), + Log: "Coin already exists", Info: EncodeError(code.NewCoinAlreadyExists(types.StrToCoinSymbol(data.Symbol.String()).String(), context.Coins().GetCoinBySymbol(data.Symbol, 0).ID().String())), } } @@ -70,7 +70,7 @@ func (data CreateCoinData) BasicCheck(tx *Transaction, context *state.CheckState if data.ConstantReserveRatio < 10 || data.ConstantReserveRatio > 100 { return &Response{ Code: code.WrongCrr, - Log: fmt.Sprintf("Constant Reserve Ratio should be between 10 and 100"), + Log: "Constant Reserve Ratio should be between 10 and 100", Info: EncodeError(code.NewWrongCrr("10", "100", strconv.Itoa(int(data.ConstantReserveRatio)))), } } diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index c35b2362d..e1412feeb 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -34,7 +34,7 @@ func (data CreateMultisigData) BasicCheck(tx *Transaction, context *state.CheckS if lenAddresses != lenWeights { return &Response{ Code: code.DifferentCountAddressesAndWeights, - Log: fmt.Sprintf("Different count addresses and weights"), + Log: "Different count addresses and weights", Info: EncodeError(code.NewDifferentCountAddressesAndWeights(fmt.Sprintf("%d", lenAddresses), fmt.Sprintf("%d", lenWeights))), } } diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index 8748e3b7f..b04cd65c3 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -60,7 +60,7 @@ func (data DeclareCandidacyData) BasicCheck(tx *Transaction, context *state.Chec if data.Commission < minCommission || data.Commission > maxCommission { return &Response{ Code: code.WrongCommission, - Log: fmt.Sprintf("Commission should be between 0 and 100"), + Log: "Commission should be between 0 and 100", Info: EncodeError(code.NewWrongCommission(fmt.Sprintf("%d", data.Commission), "0", "100")), } } @@ -96,7 +96,7 @@ func (data DeclareCandidacyData) Run(tx *Transaction, context state.Interface, r if checkState.Candidates().Count() >= maxCandidatesCount && !checkState.Candidates().IsNewCandidateStakeSufficient(data.Coin, data.Stake, maxCandidatesCount) { return Response{ Code: code.TooLowStake, - Log: fmt.Sprintf("Given stake is too low"), + Log: "Given stake is too low", Info: EncodeError(code.NewTooLowStake(sender.String(), data.PubKey.String(), data.Stake.String(), data.Coin.String(), checkState.Coins().GetCoin(data.Coin).GetFullSymbol())), } } diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index ba0e6f93b..f1d5034b2 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -47,7 +47,7 @@ func (data DelegateData) BasicCheck(tx *Transaction, context *state.CheckState) if data.Value.Cmp(types.Big0) < 1 { return &Response{ Code: code.StakeShouldBePositive, - Log: fmt.Sprintf("Stake should be positive"), + Log: "Stake should be positive", Info: EncodeError(code.NewStakeShouldBePositive(data.Value.String())), } } @@ -55,7 +55,7 @@ func (data DelegateData) BasicCheck(tx *Transaction, context *state.CheckState) if !context.Candidates().Exists(data.PubKey) { return &Response{ Code: code.CandidateNotFound, - Log: fmt.Sprintf("Candidate with such public key not found"), + Log: "Candidate with such public key not found", Info: EncodeError(code.NewCandidateNotFound(data.PubKey.String())), } } @@ -64,7 +64,7 @@ func (data DelegateData) BasicCheck(tx *Transaction, context *state.CheckState) if !context.Candidates().IsDelegatorStakeSufficient(sender, data.PubKey, data.Coin, data.Value) { return &Response{ Code: code.TooLowStake, - Log: fmt.Sprintf("Stake is too low"), + Log: "Stake is too low", Info: EncodeError(code.NewTooLowStake(sender.String(), data.PubKey.String(), data.Value.String(), data.Coin.String(), context.Coins().GetCoin(data.Coin).GetFullSymbol())), } } diff --git a/core/transaction/edit_candidate.go b/core/transaction/edit_candidate.go index 897f00c6a..3f7616b87 100644 --- a/core/transaction/edit_candidate.go +++ b/core/transaction/edit_candidate.go @@ -114,7 +114,7 @@ func checkCandidateOwnership(data CandidateTx, tx *Transaction, context *state.C if owner != sender { return &Response{ Code: code.IsNotOwnerOfCandidate, - Log: fmt.Sprintf("Sender is not an owner of a candidate"), + Log: "Sender is not an owner of a candidate", Info: EncodeError(code.NewIsNotOwnerOfCandidate(sender.String(), data.GetPubKey().String(), owner.String(), "")), } } diff --git a/core/transaction/edit_multisig.go b/core/transaction/edit_multisig.go index 4aedac173..88adaa2c1 100644 --- a/core/transaction/edit_multisig.go +++ b/core/transaction/edit_multisig.go @@ -35,7 +35,7 @@ func (data EditMultisigData) BasicCheck(tx *Transaction, context *state.CheckSta if lenWeights > 32 { return &Response{ Code: code.TooLargeOwnersList, - Log: fmt.Sprintf("Owners list is limited to 32 items"), + Log: "Owners list is limited to 32 items", Info: EncodeError(code.NewTooLargeOwnersList(strconv.Itoa(lenWeights), "32")), } } @@ -44,7 +44,7 @@ func (data EditMultisigData) BasicCheck(tx *Transaction, context *state.CheckSta if lenAddresses != lenWeights { return &Response{ Code: code.DifferentCountAddressesAndWeights, - Log: fmt.Sprintf("Different count addresses and weights"), + Log: "Different count addresses and weights", Info: EncodeError(code.NewDifferentCountAddressesAndWeights(fmt.Sprintf("%d", lenAddresses), fmt.Sprintf("%d", lenWeights))), } } @@ -64,7 +64,7 @@ func (data EditMultisigData) BasicCheck(tx *Transaction, context *state.CheckSta if usedAddresses[address] { return &Response{ Code: code.DuplicatedAddresses, - Log: fmt.Sprintf("Duplicated multisig addresses"), + Log: "Duplicated multisig addresses", Info: EncodeError(code.NewDuplicatedAddresses(address.String())), } } diff --git a/core/transaction/multisend.go b/core/transaction/multisend.go index 2f7c425ef..0d018cc74 100644 --- a/core/transaction/multisend.go +++ b/core/transaction/multisend.go @@ -55,7 +55,7 @@ func (item MultisendDataItem) MarshalJSON() ([]byte, error) { } func (data MultisendData) String() string { - return fmt.Sprintf("MULTISEND") + return "MULTISEND" } func (data MultisendData) Gas() int64 { diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index d5f98958b..c5fbf57b6 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -43,7 +43,7 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta if data.ConstantReserveRatio < 10 || data.ConstantReserveRatio > 100 { return &Response{ Code: code.WrongCrr, - Log: fmt.Sprintf("Constant Reserve Ratio should be between 10 and 100"), + Log: "Constant Reserve Ratio should be between 10 and 100", Info: EncodeError(code.NewWrongCrr("10", "100", strconv.Itoa(int(data.ConstantReserveRatio)))), } } diff --git a/core/transaction/redeem_check.go b/core/transaction/redeem_check.go index 763a20718..ff5c406a8 100644 --- a/core/transaction/redeem_check.go +++ b/core/transaction/redeem_check.go @@ -37,7 +37,7 @@ func (data RedeemCheckData) BasicCheck(tx *Transaction, context *state.CheckStat if tx.GasPrice != 1 { return &Response{ Code: code.TooHighGasPrice, - Log: fmt.Sprintf("Gas price for check is limited to 1"), + Log: "Gas price for check is limited to 1", Info: EncodeError(code.NewTooHighGasPrice("1", strconv.Itoa(int(tx.GasPrice)))), } } @@ -105,7 +105,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward if !checkState.Coins().Exists(decodedCheck.Coin) { return Response{ Code: code.CoinNotExists, - Log: fmt.Sprintf("Coin not exists"), + Log: "Coin not exists", Info: EncodeError(code.NewCoinNotExists("", decodedCheck.Coin.String())), } } @@ -113,7 +113,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward if !checkState.Coins().Exists(decodedCheck.GasCoin) { return Response{ Code: code.CoinNotExists, - Log: fmt.Sprintf("Gas coin not exists"), + Log: "Gas coin not exists", Info: EncodeError(code.NewCoinNotExists("", decodedCheck.GasCoin.String())), } } @@ -129,7 +129,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward if decodedCheck.DueBlock < currentBlock { return Response{ Code: code.CheckExpired, - Log: fmt.Sprintf("Check expired"), + Log: "Check expired", Info: EncodeError(code.MewCheckExpired(fmt.Sprintf("%d", decodedCheck.DueBlock), fmt.Sprintf("%d", currentBlock))), } } @@ -137,7 +137,7 @@ func (data RedeemCheckData) Run(tx *Transaction, context state.Interface, reward if checkState.Checks().IsCheckUsed(decodedCheck) { return Response{ Code: code.CheckUsed, - Log: fmt.Sprintf("Check already redeemed"), + Log: "Check already redeemed", Info: EncodeError(code.NewCheckUsed()), } } diff --git a/core/transaction/sell_all_coin.go b/core/transaction/sell_all_coin.go index 693c145ff..cd8acef8a 100644 --- a/core/transaction/sell_all_coin.go +++ b/core/transaction/sell_all_coin.go @@ -73,7 +73,7 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat if ret.Cmp(commissionInBaseCoin) == -1 { return nil, nil, nil, &Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account"), + Log: "Insufficient funds for sender account", Info: EncodeError(code.NewInsufficientFunds(sender.String(), commissionInBaseCoin.String(), coin.GetFullSymbol(), coin.ID().String())), } } @@ -97,7 +97,7 @@ func (data SellAllCoinData) TotalSpend(tx *Transaction, context *state.CheckStat if basecoinValue.Cmp(commissionInBaseCoin) == -1 { return nil, nil, nil, &Response{ Code: code.InsufficientFunds, - Log: fmt.Sprintf("Insufficient funds for sender account"), + Log: "Insufficient funds for sender account", Info: EncodeError(code.NewInsufficientFunds(sender.String(), commissionInBaseCoin.String(), coinFrom.GetFullSymbol(), coinFrom.ID().String())), } } @@ -134,7 +134,7 @@ func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.CheckStat if !context.Coins().Exists(data.CoinToSell) { return &Response{ Code: code.CoinNotExists, - Log: fmt.Sprintf("Coin to sell not exists"), + Log: "Coin to sell not exists", Info: EncodeError(code.NewCoinNotExists("", data.CoinToSell.String())), } } @@ -142,7 +142,7 @@ func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.CheckStat if !context.Coins().Exists(data.CoinToBuy) { return &Response{ Code: code.CoinNotExists, - Log: fmt.Sprintf("Coin to buy not exists"), + Log: "Coin to buy not exists", Info: EncodeError(code.NewCoinNotExists("", data.CoinToBuy.String())), } } @@ -150,7 +150,7 @@ func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.CheckStat if data.CoinToSell == data.CoinToBuy { return &Response{ Code: code.CrossConvert, - Log: fmt.Sprintf("\"From\" coin equals to \"to\" coin"), + Log: "\"From\" coin equals to \"to\" coin", Info: EncodeError(code.NewCrossConvert( data.CoinToSell.String(), context.Coins().GetCoin(data.CoinToSell).Symbol().String(), diff --git a/core/transaction/sell_coin.go b/core/transaction/sell_coin.go index de74482ff..946fe6924 100644 --- a/core/transaction/sell_coin.go +++ b/core/transaction/sell_coin.go @@ -271,7 +271,7 @@ func (data SellCoinData) BasicCheck(tx *Transaction, context *state.CheckState) if !context.Coins().Exists(data.CoinToSell) { return &Response{ Code: code.CoinNotExists, - Log: fmt.Sprintf("Coin not exists"), + Log: "Coin not exists", Info: EncodeError(code.NewCoinNotExists("", data.CoinToSell.String())), } } @@ -279,7 +279,7 @@ func (data SellCoinData) BasicCheck(tx *Transaction, context *state.CheckState) if !context.Coins().Exists(data.CoinToBuy) { return &Response{ Code: code.CoinNotExists, - Log: fmt.Sprintf("Coin not exists"), + Log: "Coin not exists", Info: EncodeError(code.NewCoinNotExists("", data.CoinToBuy.String())), } } @@ -287,7 +287,7 @@ func (data SellCoinData) BasicCheck(tx *Transaction, context *state.CheckState) if data.CoinToSell == data.CoinToBuy { return &Response{ Code: code.CrossConvert, - Log: fmt.Sprintf("\"From\" coin equals to \"to\" coin"), + Log: "\"From\" coin equals to \"to\" coin", Info: EncodeError(code.NewCrossConvert( data.CoinToSell.String(), context.Coins().GetCoin(data.CoinToSell).Symbol().String(), diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index 8f7b8f484..18469f61a 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -28,7 +28,7 @@ func (data SetHaltBlockData) BasicCheck(tx *Transaction, context *state.CheckSta if !context.Candidates().Exists(data.PubKey) { return &Response{ Code: code.CandidateNotFound, - Log: fmt.Sprintf("Candidate with such public key not found"), + Log: "Candidate with such public key not found", Info: EncodeError(code.NewCandidateNotFound(data.PubKey.String())), } } diff --git a/core/transaction/switch_candidate_status.go b/core/transaction/switch_candidate_status.go index 7ea8793c6..54995e41f 100644 --- a/core/transaction/switch_candidate_status.go +++ b/core/transaction/switch_candidate_status.go @@ -191,7 +191,7 @@ func checkCandidateControl(data CandidateTx, tx *Transaction, context *state.Che default: return &Response{ Code: code.IsNotOwnerOfCandidate, - Log: fmt.Sprintf("Sender is not an owner of a candidate"), + Log: "Sender is not an owner of a candidate", Info: EncodeError(code.NewIsNotOwnerOfCandidate(sender.String(), data.GetPubKey().String(), owner.String(), control.String())), } } diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 10692b5d9..6fced0c3f 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -41,7 +41,7 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R if !context.Candidates().Exists(data.PubKey) { return &Response{ Code: code.CandidateNotFound, - Log: fmt.Sprintf("Candidate with such public key not found"), + Log: "Candidate with such public key not found", Info: EncodeError(code.NewCandidateNotFound(data.PubKey.String())), } } @@ -55,7 +55,7 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R } return &Response{ Code: code.InsufficientWaitList, - Log: fmt.Sprintf("Insufficient amount at waitlist for sender account"), + Log: "Insufficient amount at waitlist for sender account", Info: EncodeError(code.NewInsufficientWaitList(waitlist.Value.String(), data.Value.String())), } } @@ -65,7 +65,7 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R if stake == nil { return &Response{ Code: code.StakeNotFound, - Log: fmt.Sprintf("Stake of current user not found"), + Log: "Stake of current user not found", Info: EncodeError(code.NewStakeNotFound(data.PubKey.String(), sender.String(), data.Coin.String(), context.Coins().GetCoin(data.Coin).GetFullSymbol())), } } @@ -73,7 +73,7 @@ func (data UnbondData) BasicCheck(tx *Transaction, context *state.CheckState) *R if stake.Cmp(data.Value) < 0 { return &Response{ Code: code.InsufficientStake, - Log: fmt.Sprintf("Insufficient stake for sender account"), + Log: "Insufficient stake for sender account", Info: EncodeError(code.NewInsufficientStake(data.PubKey.String(), sender.String(), data.Coin.String(), context.Coins().GetCoin(data.Coin).GetFullSymbol(), stake.String(), data.Value.String())), } } diff --git a/go.mod b/go.mod index f38d1d075..dfbad580c 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200921073010-0e0331cde460 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922105853-257357501cf1 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 2e70ca8c2..5647cdfed 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200921073010-0e0331cde460 h1:joYzlUOfkSr2j+jmkMxXqLF5HguzwlYx6lfJmE6/brs= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200921073010-0e0331cde460/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922105853-257357501cf1 h1:IkfQX4L8t9axMgZIiK9GIiIH7pEJejiT1klWGwLcmio= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922105853-257357501cf1/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 94f3049cbd17dae32e10efb7d923064382b662f1 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 22 Sep 2020 14:34:59 +0300 Subject: [PATCH 305/426] refactor --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dfbad580c..117a24c40 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922105853-257357501cf1 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922113354-964e0be5bca1 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 5647cdfed..db9119be3 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922105853-257357501cf1 h1:IkfQX4L8t9axMgZIiK9GIiIH7pEJejiT1klWGwLcmio= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922105853-257357501cf1/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922113354-964e0be5bca1 h1:Pl1SWF+cnGdDPYfFUEAPZ+Eqfad7E00F9WjFUsxCApw= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922113354-964e0be5bca1/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From deadb19a92a48f6eab174b8ae816298c10cf3cf5 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 22 Sep 2020 14:44:47 +0300 Subject: [PATCH 306/426] update openapi --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 117a24c40..1169f8d56 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922113354-964e0be5bca1 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922114348-418a230208a8 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index db9119be3..a6c7efc71 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922113354-964e0be5bca1 h1:Pl1SWF+cnGdDPYfFUEAPZ+Eqfad7E00F9WjFUsxCApw= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922113354-964e0be5bca1/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922114348-418a230208a8 h1:3C/50f/+Vhc+7/GlofHgsWYr8PmItWM1bTk3TlRnUPE= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922114348-418a230208a8/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 2c4dafdc0b7a4836c8e9271180ca5e9ac9635473 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 22 Sep 2020 19:36:47 +0300 Subject: [PATCH 307/426] fix coin info --- api/v2/service/coin_info.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index 4bca3f252..c27158c55 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -44,7 +44,7 @@ func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.Co return &pb.CoinInfoResponse{ Id: coin.ID().String(), Name: coin.Name(), - Symbol: coin.Symbol().String(), + Symbol: coin.GetFullSymbol(), Volume: coin.Volume().String(), Crr: fmt.Sprintf("%d", coin.Crr()), ReserveBalance: coin.Reserve().String(), @@ -53,7 +53,7 @@ func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.Co }, nil } -// Returns information about coin ID. +// CoinInfoById returns information about coin ID. func (s *Service) CoinInfoById(ctx context.Context, req *pb.CoinIdRequest) (*pb.CoinInfoResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { @@ -83,7 +83,7 @@ func (s *Service) CoinInfoById(ctx context.Context, req *pb.CoinIdRequest) (*pb. return &pb.CoinInfoResponse{ Id: coin.ID().String(), Name: coin.Name(), - Symbol: coin.Symbol().String(), + Symbol: coin.GetFullSymbol(), Volume: coin.Volume().String(), Crr: fmt.Sprintf("%d", coin.Crr()), ReserveBalance: coin.Reserve().String(), From fa1fa16ca90709412cfb22d400ee98c0ff4a101b Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 23 Sep 2020 10:50:15 +0300 Subject: [PATCH 308/426] events --- api/v2/service/events.go | 2 ++ core/events/types.go | 2 +- core/transaction/transaction.go | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/api/v2/service/events.go b/api/v2/service/events.go index 04fec7405..e90fec82b 100644 --- a/api/v2/service/events.go +++ b/api/v2/service/events.go @@ -50,6 +50,8 @@ func (s *Service) Events(ctx context.Context, req *pb.EventsRequest) (*pb.Events t = "minter/SlashEvent" case *eventsdb.UnbondEvent: t = "minter/UnbondEvent" + case *eventsdb.StakeKickEvent: + t = "minter/StakeKickEvent" default: t = "Undefined Type" } diff --git a/core/events/types.go b/core/events/types.go index 96a426448..c3ecbf5e8 100644 --- a/core/events/types.go +++ b/core/events/types.go @@ -16,7 +16,7 @@ func RegisterAminoEvents(codec *amino.Codec) { codec.RegisterConcrete(UnbondEvent{}, "minter/UnbondEvent", nil) codec.RegisterConcrete(StakeKickEvent{}, - "minter/StakeKick", nil) + "minter/StakeKickEvent", nil) } type Event interface { diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index 462d1cc81..d99d7f3bd 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -15,7 +15,9 @@ import ( "math/big" ) +// TxType of transaction is determined by a single byte. type TxType byte + type SigType byte const ( From 5860869dd75a6f94d94a79c35349433020332404 Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 23 Sep 2020 14:15:26 +0300 Subject: [PATCH 309/426] check public key exists for EditCandidatePublicKeyData --- core/transaction/edit_candidate_public_key.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/transaction/edit_candidate_public_key.go b/core/transaction/edit_candidate_public_key.go index 6a8b9ecfc..b19440c51 100644 --- a/core/transaction/edit_candidate_public_key.go +++ b/core/transaction/edit_candidate_public_key.go @@ -56,6 +56,14 @@ func (data EditCandidatePublicKeyData) Run(tx *Transaction, context state.Interf } } + if checkState.Candidates().Exists(data.NewPubKey) { + return Response{ + Code: code.CandidateExists, + Log: fmt.Sprintf("Candidate with such public key (%s) already exists", data.NewPubKey.String()), + Info: EncodeError(code.NewCandidateExists(data.NewPubKey.String())), + } + } + commissionInBaseCoin := tx.CommissionInBaseCoin() commission := big.NewInt(0).Set(commissionInBaseCoin) From 628aebf8f7c99aa254aae2069c005736bb086dae Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 23 Sep 2020 14:26:23 +0300 Subject: [PATCH 310/426] tests --- .../edit_candidate_public_key_test.go | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/core/transaction/edit_candidate_public_key_test.go b/core/transaction/edit_candidate_public_key_test.go index 71d441643..ebddb5924 100644 --- a/core/transaction/edit_candidate_public_key_test.go +++ b/core/transaction/edit_candidate_public_key_test.go @@ -376,3 +376,71 @@ func TestEditCandidatePublicKeyTxToCandidateOwnership(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.IsNotOwnerOfCandidate, response.Log) } } + +func TestEditCandidatePublicKeyData_Exists(t *testing.T) { + cState := getState() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + newpubkey := [32]byte{} + rand.Read(newpubkey[:]) + + cState.Candidates.Create(addr, addr, addr, newpubkey, 10) + cState.Validators.Create(newpubkey, helpers.BipToPip(big.NewInt(1))) + + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + + candidate1 := cState.Candidates.GetCandidate(newpubkey) + if candidate1 == nil { + t.Fatalf("Candidate not found") + } + candidate2 := cState.Candidates.GetCandidate(pubkey) + if candidate2 == nil { + t.Fatalf("Candidate not found") + } + + data := EditCandidatePublicKeyData{ + PubKey: pubkey, + NewPubKey: newpubkey, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeEditCandidatePublicKey, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CandidateExists { + t.Fatalf("Response code is %d. Error %s", response.Code, response.Log) + } + + if candidate1.PubKey == candidate2.PubKey { + t.Fatalf("Candidates pulic keys are equal") + } + +} From 476248846a995defffd3277b9dbc890c72cd6091 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 24 Sep 2020 17:17:48 +0300 Subject: [PATCH 311/426] update genesis types. --- api/candidate.go | 2 +- api/coin_info.go | 2 +- core/minter/minter_test.go | 6 +-- core/state/accounts/accounts.go | 8 ++-- core/state/accounts/accounts_test.go | 10 ++-- core/state/accounts/model.go | 6 +-- core/state/bus/candidates.go | 2 +- core/state/bus/coins.go | 2 +- core/state/candidates/candidate_test.go | 6 +-- core/state/candidates/candidates.go | 20 ++++---- core/state/candidates/model.go | 2 +- core/state/coins/coins.go | 8 ++-- core/state/coins/model.go | 4 +- core/state/frozenfunds/frozen_funds.go | 2 +- core/state/state.go | 12 ++--- core/state/state_test.go | 18 +++---- core/state/waitlist/waitlist.go | 4 +- core/transaction/buy_coin_test.go | 4 +- core/transaction/create_coin.go | 2 +- core/transaction/create_coin_test.go | 22 ++++----- core/transaction/create_multisig.go | 4 +- core/transaction/create_multisig_test.go | 22 ++++----- core/transaction/declare_candidacy.go | 2 +- core/transaction/declare_candidacy_test.go | 18 +++---- core/transaction/edit_multisig.go | 6 +-- core/transaction/edit_multisig_test.go | 32 ++++++------- core/transaction/executor.go | 2 +- core/transaction/executor_test.go | 10 ++-- core/transaction/recreate_coin.go | 2 +- core/transaction/recreate_coin_test.go | 20 ++++---- core/transaction/send_test.go | 4 +- core/types/appstate.go | 50 ++++++++++--------- core/types/types_test.go | 56 +++++++++++----------- formula/formula.go | 8 ++-- formula/formula_test.go | 8 ++-- legacy/accounts/model.go | 6 +-- legacy/candidates/candidates.go | 8 ++-- legacy/candidates/model.go | 2 +- legacy/coins/coins.go | 8 ++-- tests/send_test.go | 2 +- 40 files changed, 209 insertions(+), 203 deletions(-) diff --git a/api/candidate.go b/api/candidate.go index f63dced26..4172e4723 100644 --- a/api/candidate.go +++ b/api/candidate.go @@ -19,7 +19,7 @@ type CandidateResponse struct { OwnerAddress string `json:"owner_address"` TotalStake string `json:"total_stake"` PubKey string `json:"pub_key"` - Commission uint `json:"commission"` + Commission uint32 `json:"commission"` Stakes []Stake `json:"stakes,omitempty"` Status byte `json:"status"` } diff --git a/api/coin_info.go b/api/coin_info.go index 5193f6865..726fc630d 100644 --- a/api/coin_info.go +++ b/api/coin_info.go @@ -11,7 +11,7 @@ type CoinInfoResponse struct { Name string `json:"name"` Symbol string `json:"symbol"` Volume string `json:"volume"` - Crr uint `json:"crr"` + Crr uint32 `json:"crr"` ReserveBalance string `json:"reserve_balance"` MaxSupply string `json:"max_supply"` OwnerAddress *string `json:"owner_address"` diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index c1f6bff9c..286a420c9 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -66,7 +66,7 @@ func makeTestValidatorsAndCandidates(pubkeys []string, stake *big.Int) ([]types. } cands[i] = types.Candidate{ - ID: uint32(i) + 1, + ID: uint64(i) + 1, RewardAddress: addr, OwnerAddress: crypto.PubkeyToAddress(getPrivateKey().PublicKey), ControlAddress: addr, @@ -76,7 +76,7 @@ func makeTestValidatorsAndCandidates(pubkeys []string, stake *big.Int) ([]types. Stakes: []types.Stake{ { Owner: addr, - Coin: types.GetBaseCoinID(), + Coin: uint64(types.GetBaseCoinID()), Value: stake.String(), BipValue: stake.String(), }, @@ -102,7 +102,7 @@ func getTestGenesis(pv *privval.FilePV) func() (*types2.GenesisDoc, error) { Address: crypto.PubkeyToAddress(getPrivateKey().PublicKey), Balance: []types.Balance{ { - Coin: types.GetBaseCoinID(), + Coin: uint64(types.GetBaseCoinID()), Value: helpers.BipToPip(big.NewInt(1000000)).String(), }, }, diff --git a/core/state/accounts/accounts.go b/core/state/accounts/accounts.go index 9e9aac3f2..5d456da07 100644 --- a/core/state/accounts/accounts.go +++ b/core/state/accounts/accounts.go @@ -190,7 +190,7 @@ func (a *Accounts) ExistsMultisig(msigAddress types.Address) bool { return false } -func (a *Accounts) CreateMultisig(weights []uint, addresses []types.Address, threshold uint, height uint64, address types.Address) types.Address { +func (a *Accounts) CreateMultisig(weights []uint32, addresses []types.Address, threshold uint32, height uint64, address types.Address) types.Address { msig := Multisig{ Weights: weights, Threshold: threshold, @@ -219,7 +219,7 @@ func (a *Accounts) CreateMultisig(weights []uint, addresses []types.Address, thr return address } -func (a *Accounts) EditMultisig(threshold uint, weights []uint, addresses []types.Address, address types.Address) types.Address { +func (a *Accounts) EditMultisig(threshold uint32, weights []uint32, addresses []types.Address, address types.Address) types.Address { account := a.get(address) msig := Multisig{ @@ -333,14 +333,14 @@ func (a *Accounts) Export(state *types.AppState) { var balance []types.Balance for _, b := range a.GetBalances(account.address) { balance = append(balance, types.Balance{ - Coin: b.Coin.ID, + Coin: uint64(b.Coin.ID), Value: b.Value.String(), }) } // sort balances by coin symbol sort.SliceStable(balance, func(i, j int) bool { - return bytes.Compare(balance[i].Coin.Bytes(), balance[j].Coin.Bytes()) == 1 + return bytes.Compare(types.CoinID(balance[i].Coin).Bytes(), types.CoinID(balance[j].Coin).Bytes()) == 1 }) acc := types.Account{ diff --git a/core/state/accounts/accounts_test.go b/core/state/accounts/accounts_test.go index b445adcf6..2deaeade5 100644 --- a/core/state/accounts/accounts_test.go +++ b/core/state/accounts/accounts_test.go @@ -22,7 +22,7 @@ func TestAccounts_CreateMultisig(t *testing.T) { if err != nil { t.Fatal(err) } - multisigAddr := accounts.CreateMultisig([]uint{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, 2, 0, [20]byte{4}) + multisigAddr := accounts.CreateMultisig([]uint32{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, 2, 0, [20]byte{4}) account := accounts.GetAccount(multisigAddr) if account == nil { @@ -209,7 +209,7 @@ func TestAccounts_ExistsMultisig(t *testing.T) { accounts.SetNonce(msigAddress, 0) - _ = accounts.CreateMultisig([]uint{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, 2, 0, msigAddress) + _ = accounts.CreateMultisig([]uint32{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, 2, 0, msigAddress) if !accounts.ExistsMultisig(msigAddress) { t.Fatal("multisig address is free") @@ -265,8 +265,8 @@ func TestAccounts_EditMultisig(t *testing.T) { msigAddress := CreateMultisigAddress([20]byte{4}, 12) - _ = accounts.CreateMultisig([]uint{3, 3, 6}, []types.Address{[20]byte{1, 1}, [20]byte{2, 3}, [20]byte{3, 3}}, 6, 0, msigAddress) - _ = accounts.EditMultisig(2, []uint{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, msigAddress) + _ = accounts.CreateMultisig([]uint32{3, 3, 6}, []types.Address{[20]byte{1, 1}, [20]byte{2, 3}, [20]byte{3, 3}}, 6, 0, msigAddress) + _ = accounts.EditMultisig(2, []uint32{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, msigAddress) account := accounts.GetAccount(msigAddress) if account == nil { @@ -361,7 +361,7 @@ func TestAccounts_Export(t *testing.T) { } accounts.SetBalance([20]byte{4}, symbol.ID(), big.NewInt(1001)) - _ = accounts.CreateMultisig([]uint{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, 2, 0, [20]byte{4}) + _ = accounts.CreateMultisig([]uint32{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, 2, 0, [20]byte{4}) err = accounts.Commit() if err != nil { diff --git a/core/state/accounts/model.go b/core/state/accounts/model.go index 45fd20867..b94585d07 100644 --- a/core/state/accounts/model.go +++ b/core/state/accounts/model.go @@ -27,8 +27,8 @@ type Model struct { } type Multisig struct { - Threshold uint - Weights []uint + Threshold uint32 + Weights []uint32 Addresses []types.Address } @@ -47,7 +47,7 @@ func CreateMultisigAddress(owner types.Address, nonce uint64) types.Address { return addr } -func (m *Multisig) GetWeight(address types.Address) uint { +func (m *Multisig) GetWeight(address types.Address) uint32 { for i, addr := range m.Addresses { if addr == address { return m.Weights[i] diff --git a/core/state/bus/candidates.go b/core/state/bus/candidates.go index f53e0512d..8049c190b 100644 --- a/core/state/bus/candidates.go +++ b/core/state/bus/candidates.go @@ -26,6 +26,6 @@ type Candidate struct { RewardAddress types.Address OwnerAddress types.Address ControlAddress types.Address - Commission uint + Commission uint32 Status byte } diff --git a/core/state/bus/coins.go b/core/state/bus/coins.go index e26c7474b..9c5d9534f 100644 --- a/core/state/bus/coins.go +++ b/core/state/bus/coins.go @@ -15,7 +15,7 @@ type Coins interface { type Coin struct { ID types.CoinID Name string - Crr uint + Crr uint32 Symbol types.CoinSymbol Version types.CoinVersion Volume *big.Int diff --git a/core/state/candidates/candidate_test.go b/core/state/candidates/candidate_test.go index 55d99b5cc..ac471c1d1 100644 --- a/core/state/candidates/candidate_test.go +++ b/core/state/candidates/candidate_test.go @@ -567,7 +567,7 @@ func TestCandidates_GetTotalStake_forCustomCoins(t *testing.T) { value := strconv.Itoa(i + 2000) stakes = append(stakes, types.Stake{ Owner: types.StringToAddress(strconv.Itoa(i)), - Coin: symbol.ID(), + Coin: uint64(symbol.ID()), Value: value, BipValue: "0", }) @@ -773,7 +773,7 @@ func TestCandidates_Punish(t *testing.T) { }, { Owner: [20]byte{1}, - Coin: symbol.ID(), + Coin: uint64(symbol.ID()), Value: "100", BipValue: "0", }, @@ -863,7 +863,7 @@ func TestCandidates_PunishByzantineCandidate(t *testing.T) { }, { Owner: [20]byte{1}, - Coin: symbol.ID(), + Coin: uint64(symbol.ID()), Value: "100", BipValue: "0", }, diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 1f96f6914..1434757d5 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -231,7 +231,7 @@ func (c *Candidates) GetNewCandidates(valCount int) []Candidate { } // Create creates a new candidate with given params and adds it to state -func (c *Candidates) Create(ownerAddress, rewardAddress, controlAddress types.Address, pubkey types.Pubkey, commission uint) { +func (c *Candidates) Create(ownerAddress, rewardAddress, controlAddress types.Address, pubkey types.Pubkey, commission uint32) { candidate := &Candidate{ ID: 0, PubKey: pubkey, @@ -252,7 +252,7 @@ func (c *Candidates) Create(ownerAddress, rewardAddress, controlAddress types.Ad // CreateWithID creates a new candidate with given params and adds it to state // CreateWithID uses given ID to be associated with public key of a candidate -func (c *Candidates) CreateWithID(ownerAddress, rewardAddress, controlAddress types.Address, pubkey types.Pubkey, commission uint, id uint32) { +func (c *Candidates) CreateWithID(ownerAddress, rewardAddress, controlAddress types.Address, pubkey types.Pubkey, commission uint32, id uint32) { c.setPubKeyID(pubkey, id) c.Create(ownerAddress, rewardAddress, controlAddress, pubkey, commission) } @@ -808,7 +808,7 @@ func (c *Candidates) SetStakes(pubkey types.Pubkey, stakes []types.Stake, update for _, u := range updates { candidate.addUpdate(&stake{ Owner: u.Owner, - Coin: u.Coin, + Coin: types.CoinID(u.Coin), Value: helpers.StringToBigInt(u.Value), BipValue: helpers.StringToBigInt(u.BipValue), }) @@ -821,7 +821,7 @@ func (c *Candidates) SetStakes(pubkey types.Pubkey, stakes []types.Stake, update for _, u := range stakes[1000:] { candidate.addUpdate(&stake{ Owner: u.Owner, - Coin: u.Coin, + Coin: types.CoinID(u.Coin), Value: helpers.StringToBigInt(u.Value), BipValue: helpers.StringToBigInt(u.BipValue), }) @@ -831,7 +831,7 @@ func (c *Candidates) SetStakes(pubkey types.Pubkey, stakes []types.Stake, update for i, s := range stakes[:count] { candidate.stakes[i] = &stake{ Owner: s.Owner, - Coin: s.Coin, + Coin: types.CoinID(s.Coin), Value: helpers.StringToBigInt(s.Value), BipValue: helpers.StringToBigInt(s.BipValue), markDirty: func(index int) { @@ -857,7 +857,7 @@ func (c *Candidates) Export(state *types.AppState) { for i, s := range candidateStakes { stakes[i] = types.Stake{ Owner: s.Owner, - Coin: s.Coin, + Coin: uint64(s.Coin), Value: s.Value.String(), BipValue: s.BipValue.String(), } @@ -867,21 +867,21 @@ func (c *Candidates) Export(state *types.AppState) { for i, u := range candidate.updates { updates[i] = types.Stake{ Owner: u.Owner, - Coin: u.Coin, + Coin: uint64(u.Coin), Value: u.Value.String(), BipValue: u.BipValue.String(), } } state.Candidates = append(state.Candidates, types.Candidate{ - ID: candidate.ID, + ID: uint64(candidate.ID), RewardAddress: candidate.RewardAddress, OwnerAddress: candidate.OwnerAddress, ControlAddress: candidate.ControlAddress, TotalBipStake: candidate.GetTotalBipStake().String(), PubKey: candidate.PubKey, - Commission: candidate.Commission, - Status: candidate.Status, + Commission: uint64(candidate.Commission), + Status: uint64(candidate.Status), Updates: updates, Stakes: stakes, }) diff --git a/core/state/candidates/model.go b/core/state/candidates/model.go index ff7f97c82..534dd5690 100644 --- a/core/state/candidates/model.go +++ b/core/state/candidates/model.go @@ -19,7 +19,7 @@ type Candidate struct { RewardAddress types.Address OwnerAddress types.Address ControlAddress types.Address - Commission uint + Commission uint32 Status byte ID uint32 diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index c8fd05539..3ad5fb7e3 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -185,7 +185,7 @@ func (c *Coins) AddReserve(id types.CoinID, amount *big.Int) { } func (c *Coins) Create(id types.CoinID, symbol types.CoinSymbol, name string, - volume *big.Int, crr uint, reserve *big.Int, maxSupply *big.Int, owner *types.Address, + volume *big.Int, crr uint32, reserve *big.Int, maxSupply *big.Int, owner *types.Address, ) { coin := &Model{ CName: name, @@ -222,7 +222,7 @@ func (c *Coins) Create(id types.CoinID, symbol types.CoinSymbol, name string, } func (c *Coins) Recreate(newID types.CoinID, name string, symbol types.CoinSymbol, - volume *big.Int, crr uint, reserve *big.Int, maxSupply *big.Int, + volume *big.Int, crr uint32, reserve *big.Int, maxSupply *big.Int, ) { recreateCoin := c.GetCoinBySymbol(symbol, 0) if recreateCoin == nil { @@ -371,11 +371,11 @@ func (c *Coins) Export(state *types.AppState) { } state.Coins = append(state.Coins, types.Coin{ - ID: coin.ID(), + ID: uint64(coin.ID()), Name: coin.Name(), Symbol: coin.Symbol(), Volume: coin.Volume().String(), - Crr: coin.Crr(), + Crr: uint64(coin.Crr()), Reserve: coin.Reserve().String(), MaxSupply: coin.MaxSupply().String(), Version: coin.Version(), diff --git a/core/state/coins/model.go b/core/state/coins/model.go index 61e7053a1..0e265716c 100644 --- a/core/state/coins/model.go +++ b/core/state/coins/model.go @@ -11,7 +11,7 @@ var minCoinReserve = helpers.BipToPip(big.NewInt(10000)) type Model struct { CName string - CCrr uint + CCrr uint32 CMaxSupply *big.Int CVersion types.CoinVersion CSymbol types.CoinSymbol @@ -38,7 +38,7 @@ func (m Model) ID() types.CoinID { return m.id } -func (m Model) Crr() uint { +func (m Model) Crr() uint32 { return m.CCrr } diff --git a/core/state/frozenfunds/frozen_funds.go b/core/state/frozenfunds/frozen_funds.go index b0b230e6d..8f9aa6264 100644 --- a/core/state/frozenfunds/frozen_funds.go +++ b/core/state/frozenfunds/frozen_funds.go @@ -212,7 +212,7 @@ func (f *FrozenFunds) Export(state *types.AppState, height uint64) { Height: i, Address: frozenFund.Address, CandidateKey: frozenFund.CandidateKey, - Coin: frozenFund.Coin, + Coin: uint64(frozenFund.Coin), Value: frozenFund.Value.String(), }) } diff --git a/core/state/state.go b/core/state/state.go index 226d3e514..2e82836ee 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -297,13 +297,13 @@ func (s *State) Import(state types.AppState) error { s.Accounts.SetNonce(a.Address, a.Nonce) for _, b := range a.Balance { - s.Accounts.SetBalance(a.Address, b.Coin, helpers.StringToBigInt(b.Value)) + s.Accounts.SetBalance(a.Address, types.CoinID(b.Coin), helpers.StringToBigInt(b.Value)) } } for _, c := range state.Coins { - s.Coins.Create(c.ID, c.Symbol, c.Name, helpers.StringToBigInt(c.Volume), - c.Crr, helpers.StringToBigInt(c.Reserve), helpers.StringToBigInt(c.MaxSupply), c.OwnerAddress) + s.Coins.Create(types.CoinID(c.ID), c.Symbol, c.Name, helpers.StringToBigInt(c.Volume), + uint32(c.Crr), helpers.StringToBigInt(c.Reserve), helpers.StringToBigInt(c.MaxSupply), c.OwnerAddress) } var vals []*validators.Validator @@ -325,7 +325,7 @@ func (s *State) Import(state types.AppState) error { } for _, c := range state.Candidates { - s.Candidates.CreateWithID(c.OwnerAddress, c.RewardAddress, c.ControlAddress, c.PubKey, c.Commission, c.ID) + s.Candidates.CreateWithID(c.OwnerAddress, c.RewardAddress, c.ControlAddress, c.PubKey, uint32(c.Commission), uint32(c.ID)) if c.Status == candidates.CandidateStatusOnline { s.Candidates.SetOnline(c.PubKey) } @@ -339,7 +339,7 @@ func (s *State) Import(state types.AppState) error { if !ok { panic(fmt.Sprintf("Cannot decode %s into big.Int", w.Value)) } - s.Waitlist.AddWaitList(w.Owner, s.Candidates.PubKey(w.CandidateID), w.Coin, value) + s.Waitlist.AddWaitList(w.Owner, s.Candidates.PubKey(uint32(w.CandidateID)), types.CoinID(w.Coin), value) } for _, hashString := range state.UsedChecks { @@ -350,7 +350,7 @@ func (s *State) Import(state types.AppState) error { } for _, ff := range state.FrozenFunds { - s.FrozenFunds.AddFund(ff.Height, ff.Address, *ff.CandidateKey, ff.Coin, helpers.StringToBigInt(ff.Value)) + s.FrozenFunds.AddFund(ff.Height, ff.Address, *ff.CandidateKey, types.CoinID(ff.Coin), helpers.StringToBigInt(ff.Value)) } return nil diff --git a/core/state/state_test.go b/core/state/state_test.go index a80fcaaa2..c096fb24b 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -155,7 +155,7 @@ func TestStateExport(t *testing.T) { if funds.Height != height || funds.Address != address1 || - funds.Coin != coinTestID || + funds.Coin != uint64(coinTestID) || *funds.CandidateKey != types.Pubkey(candidatePubKey1) || funds.Value != helpers.BipToPip(big.NewInt(100)).String() { t.Fatalf("Wrong new state frozen fund data") @@ -163,7 +163,7 @@ func TestStateExport(t *testing.T) { if funds1.Height != height+10 || funds1.Address != address1 || - funds1.Coin != types.GetBaseCoinID() || + funds1.Coin != uint64(types.GetBaseCoinID()) || *funds1.CandidateKey != types.Pubkey(candidatePubKey1) || funds1.Value != helpers.BipToPip(big.NewInt(3)).String() { t.Fatalf("Wrong new state frozen fund data") @@ -171,7 +171,7 @@ func TestStateExport(t *testing.T) { if funds2.Height != height+100 || funds2.Address != address2 || - funds2.Coin != coinTestID || + funds2.Coin != uint64(coinTestID) || *funds2.CandidateKey != types.Pubkey(candidatePubKey1) || funds2.Value != helpers.BipToPip(big.NewInt(500)).String() { t.Fatalf("Wrong new state frozen fund data") @@ -179,7 +179,7 @@ func TestStateExport(t *testing.T) { if funds3.Height != height+150 || funds3.Address != address2 || - funds3.Coin != coinTest2ID || + funds3.Coin != uint64(coinTest2ID) || *funds3.CandidateKey != types.Pubkey(candidatePubKey1) || funds3.Value != helpers.BipToPip(big.NewInt(1000)).String() { t.Fatalf("Wrong new state frozen fund data") @@ -217,15 +217,15 @@ func TestStateExport(t *testing.T) { t.Fatal("Wrong new state account balances size") } - if account1.Balance[0].Coin != coinTestID || account1.Balance[0].Value != helpers.BipToPip(big.NewInt(1)).String() { + if account1.Balance[0].Coin != uint64(coinTestID) || account1.Balance[0].Value != helpers.BipToPip(big.NewInt(1)).String() { t.Fatal("Wrong new state account balance data") } - if account1.Balance[1].Coin != types.GetBaseCoinID() || account1.Balance[1].Value != helpers.BipToPip(big.NewInt(1)).String() { + if account1.Balance[1].Coin != uint64(types.GetBaseCoinID()) || account1.Balance[1].Value != helpers.BipToPip(big.NewInt(1)).String() { t.Fatal("Wrong new state account balance data") } - if account2.Balance[0].Coin != coinTest2ID || account2.Balance[0].Value != helpers.BipToPip(big.NewInt(2)).String() { + if account2.Balance[0].Coin != uint64(coinTest2ID) || account2.Balance[0].Value != helpers.BipToPip(big.NewInt(2)).String() { t.Fatal("Wrong new state account balance data") } @@ -281,11 +281,11 @@ func TestStateExport(t *testing.T) { t.Fatalf("Invalid amount of waitlist: %d. Expected 2", len(newState.Waitlist)) } - if newState.Waitlist[0].Coin != coinTest2ID || newState.Waitlist[0].Value != big.NewInt(2e18).String() || newState.Waitlist[0].Owner.Compare(wlAddr2) != 0 { + if newState.Waitlist[0].Coin != uint64(coinTest2ID) || newState.Waitlist[0].Value != big.NewInt(2e18).String() || newState.Waitlist[0].Owner.Compare(wlAddr2) != 0 { t.Fatal("Invalid waitlist data") } - if newState.Waitlist[1].Coin != coinTestID || newState.Waitlist[1].Value != big.NewInt(1e18).String() || newState.Waitlist[1].Owner.Compare(wlAddr1) != 0 { + if newState.Waitlist[1].Coin != uint64(coinTestID) || newState.Waitlist[1].Value != big.NewInt(1e18).String() || newState.Waitlist[1].Owner.Compare(wlAddr1) != 0 { t.Fatal("Invalid waitlist data") } } diff --git a/core/state/waitlist/waitlist.go b/core/state/waitlist/waitlist.go index 55f0b2352..0c6b3193e 100644 --- a/core/state/waitlist/waitlist.go +++ b/core/state/waitlist/waitlist.go @@ -53,9 +53,9 @@ func (wl *WaitList) Export(state *types.AppState) { if model != nil && len(model.List) != 0 { for _, w := range model.List { state.Waitlist = append(state.Waitlist, types.Waitlist{ - CandidateID: w.CandidateId, + CandidateID: uint64(w.CandidateId), Owner: address, - Coin: w.Coin, + Coin: uint64(w.Coin), Value: w.Value.String(), }) } diff --git a/core/transaction/buy_coin_test.go b/core/transaction/buy_coin_test.go index f281ec4c0..b9eb9a205 100644 --- a/core/transaction/buy_coin_test.go +++ b/core/transaction/buy_coin_test.go @@ -1341,13 +1341,13 @@ func getAccount() (*ecdsa.PrivateKey, types.Address) { return privateKey, addr } -func createTestCoinWithSymbol(stateDB *state.State, symbol types.CoinSymbol) (types.CoinID, *big.Int, *big.Int, uint) { +func createTestCoinWithSymbol(stateDB *state.State, symbol types.CoinSymbol) (types.CoinID, *big.Int, *big.Int, uint32) { volume := helpers.BipToPip(big.NewInt(100000)) reserve := helpers.BipToPip(big.NewInt(100000)) volume.Mul(volume, big.NewInt(int64(rnd.Intn(9))+1)) reserve.Mul(reserve, big.NewInt(int64(rnd.Intn(9))+1)) - crr := uint(10 + rnd.Intn(90)) + crr := uint32(10 + rnd.Intn(90)) id := stateDB.App.GetNextCoinID() stateDB.Coins.Create(id, symbol, "TEST COIN", volume, crr, reserve, big.NewInt(0).Mul(volume, big.NewInt(10)), nil) diff --git a/core/transaction/create_coin.go b/core/transaction/create_coin.go index 64fc9a437..e483d755f 100644 --- a/core/transaction/create_coin.go +++ b/core/transaction/create_coin.go @@ -30,7 +30,7 @@ type CreateCoinData struct { Symbol types.CoinSymbol InitialAmount *big.Int InitialReserve *big.Int - ConstantReserveRatio uint + ConstantReserveRatio uint32 MaxSupply *big.Int } diff --git a/core/transaction/create_coin_test.go b/core/transaction/create_coin_test.go index 486d147e2..daf0b3ac9 100644 --- a/core/transaction/create_coin_test.go +++ b/core/transaction/create_coin_test.go @@ -25,7 +25,7 @@ func TestCreateCoinTx(t *testing.T) { toCreate := types.StrToCoinSymbol("ABCDEF") reserve := helpers.BipToPip(big.NewInt(10000)) amount := helpers.BipToPip(big.NewInt(100)) - crr := uint(50) + crr := uint32(50) name := "My Test Coin" data := CreateCoinData{ @@ -127,7 +127,7 @@ func TestCreateCoinWithIncorrectName(t *testing.T) { toCreate := types.StrToCoinSymbol("ABCDEF") reserve := helpers.BipToPip(big.NewInt(10000)) amount := helpers.BipToPip(big.NewInt(100)) - crr := uint(50) + crr := uint32(50) var name [65]byte binary.BigEndian.PutUint64(name[:], 0) @@ -185,7 +185,7 @@ func TestCreateCoinWithInvalidSymbol(t *testing.T) { toCreate := types.StrToCoinSymbol("ABC-DEF") reserve := helpers.BipToPip(big.NewInt(10000)) amount := helpers.BipToPip(big.NewInt(100)) - crr := uint(50) + crr := uint32(50) name := "My Test Coin" data := CreateCoinData{ @@ -244,7 +244,7 @@ func TestCreateCoinWithExistingSymbol(t *testing.T) { toCreate := types.StrToCoinSymbol("TEST") reserve := helpers.BipToPip(big.NewInt(10000)) amount := helpers.BipToPip(big.NewInt(100)) - crr := uint(50) + crr := uint32(50) name := "My Test Coin" data := CreateCoinData{ @@ -298,7 +298,7 @@ func TestCreateCoinWithWrongCrr(t *testing.T) { toCreate := types.StrToCoinSymbol("ABCDEF") reserve := helpers.BipToPip(big.NewInt(10000)) amount := helpers.BipToPip(big.NewInt(100)) - crr := uint(9) + crr := uint32(9) name := "My Test Coin" data := CreateCoinData{ @@ -339,7 +339,7 @@ func TestCreateCoinWithWrongCrr(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.WrongCrr, response.Log) } - data.ConstantReserveRatio = uint(101) + data.ConstantReserveRatio = uint32(101) encodedData, err = rlp.EncodeToBytes(data) if err != nil { @@ -382,7 +382,7 @@ func TestCreateCoinWithWrongCoinSupply(t *testing.T) { toCreate := types.StrToCoinSymbol("ABCDEF") reserve := helpers.BipToPip(big.NewInt(10000)) - crr := uint(50) + crr := uint32(50) name := "My Test Coin" data := CreateCoinData{ @@ -535,7 +535,7 @@ func TestCreateCoinWithInsufficientFundsForGas(t *testing.T) { toCreate := types.StrToCoinSymbol("ABCDEF") reserve := helpers.BipToPip(big.NewInt(10000)) - crr := uint(50) + crr := uint32(50) name := "My Test Coin" data := CreateCoinData{ @@ -587,7 +587,7 @@ func TestCreateCoinTxToGasCoinReserveUnderflow(t *testing.T) { toCreate := types.StrToCoinSymbol("ABCDEF") reserve := helpers.BipToPip(big.NewInt(10000)) - crr := uint(50) + crr := uint32(50) name := "My Test Coin" addr := crypto.PubkeyToAddress(privateKey.PublicKey) @@ -641,7 +641,7 @@ func TestCreateCoinToInsufficientFundsForGasCoin(t *testing.T) { toCreate := types.StrToCoinSymbol("ABCDEF") reserve := helpers.BipToPip(big.NewInt(10000)) - crr := uint(50) + crr := uint32(50) name := "My Test Coin" addr := crypto.PubkeyToAddress(privateKey.PublicKey) @@ -693,7 +693,7 @@ func TestCreateCoinToInsufficientFundsForInitialReserve(t *testing.T) { toCreate := types.StrToCoinSymbol("ABCDEF") reserve := helpers.BipToPip(big.NewInt(11000)) - crr := uint(50) + crr := uint32(50) name := "My Test Coin" addr := crypto.PubkeyToAddress(privateKey.PublicKey) diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index e1412feeb..08c79c360 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -16,8 +16,8 @@ import ( ) type CreateMultisigData struct { - Threshold uint - Weights []uint + Threshold uint32 + Weights []uint32 Addresses []types.Address } diff --git a/core/transaction/create_multisig_test.go b/core/transaction/create_multisig_test.go index 396e19099..1eddad884 100644 --- a/core/transaction/create_multisig_test.go +++ b/core/transaction/create_multisig_test.go @@ -33,7 +33,7 @@ func TestCreateMultisigTx(t *testing.T) { addr2, } - weights := []uint{1, 1} + weights := []uint32{1, 1} data := CreateMultisigData{ Threshold: 1, @@ -126,7 +126,7 @@ func TestCreateMultisigFromExistingAccountTx(t *testing.T) { addr2, } - weights := []uint{1, 1} + weights := []uint32{1, 1} data := CreateMultisigData{ Threshold: 1, @@ -224,7 +224,7 @@ func TestCreateExistingMultisigTx(t *testing.T) { data := CreateMultisigData{ Threshold: 1, - Weights: []uint{1, 1}, + Weights: []uint32{1, 1}, Addresses: []types.Address{ addr, addr2, @@ -278,7 +278,7 @@ func TestCreateMultisigOwnersTxToNonExistenAddress(t *testing.T) { data := EditMultisigData{ Threshold: 3, - Weights: []uint{2, 1, 2}, + Weights: []uint32{2, 1, 2}, Addresses: []types.Address{addr1, addr2, addr3}, } @@ -322,8 +322,8 @@ func TestCreateMultisigOwnersTxToTooLargeOwnersList(t *testing.T) { coin := types.GetBaseCoinID() - weights := make([]uint, 33) - for i := uint(0); i <= 32; i++ { + weights := make([]uint32, 33) + for i := uint32(0); i <= 32; i++ { weights[i] = i } @@ -375,7 +375,7 @@ func TestCreateMultisigOwnersTxIncorrectWeights(t *testing.T) { data := CreateMultisigData{ Threshold: 3, - Weights: []uint{1, 2, 3, 4}, + Weights: []uint32{1, 2, 3, 4}, Addresses: []types.Address{addr1, addr2, addr3}, } @@ -408,7 +408,7 @@ func TestCreateMultisigOwnersTxIncorrectWeights(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.DifferentCountAddressesAndWeights, response.Log) } - data.Weights = []uint{1, 2, 1024} + data.Weights = []uint32{1, 2, 1024} encodedData, err = rlp.EncodeToBytes(data) if err != nil { t.Fatal(err) @@ -440,7 +440,7 @@ func TestCreateMultisigOwnersTxToAddressDuplication(t *testing.T) { data := CreateMultisigData{ Threshold: 3, - Weights: []uint{1, 2, 3}, + Weights: []uint32{1, 2, 3}, Addresses: []types.Address{addr1, addr1, addr3}, } @@ -486,7 +486,7 @@ func TestCreateMultisigOwnersTxToInsufficientFunds(t *testing.T) { data := CreateMultisigData{ Threshold: 3, - Weights: []uint{1, 2, 3}, + Weights: []uint32{1, 2, 3}, Addresses: []types.Address{addr1, addr2, addr3}, } @@ -537,7 +537,7 @@ func TestCreateMultisigTxToGasCoinReserveUnderflow(t *testing.T) { data := CreateMultisigData{ Threshold: 3, - Weights: []uint{1, 2, 3}, + Weights: []uint32{1, 2, 3}, Addresses: []types.Address{addr1, addr2, addr3}, } diff --git a/core/transaction/declare_candidacy.go b/core/transaction/declare_candidacy.go index b04cd65c3..bdbbde914 100644 --- a/core/transaction/declare_candidacy.go +++ b/core/transaction/declare_candidacy.go @@ -19,7 +19,7 @@ const maxCommission = 100 type DeclareCandidacyData struct { Address types.Address PubKey types.Pubkey - Commission uint + Commission uint32 Coin types.CoinID Stake *big.Int } diff --git a/core/transaction/declare_candidacy_test.go b/core/transaction/declare_candidacy_test.go index 37068d3f0..1b0fd623c 100644 --- a/core/transaction/declare_candidacy_test.go +++ b/core/transaction/declare_candidacy_test.go @@ -30,7 +30,7 @@ func TestDeclareCandidacyTx(t *testing.T) { var publicKey types.Pubkey copy(publicKey[:], publicKeyBytes) - commission := uint(10) + commission := uint32(10) data := DeclareCandidacyData{ Address: addr, @@ -136,7 +136,7 @@ func TestDeclareCandidacyTxOverflow(t *testing.T) { data := DeclareCandidacyData{ Address: addr, PubKey: publicKey, - Commission: uint(10), + Commission: uint32(10), Coin: coin, Stake: helpers.BipToPip(big.NewInt(10)), } @@ -197,7 +197,7 @@ func TestDeclareCandidacyTxWithBlockPybKey(t *testing.T) { cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) - commission := uint(10) + commission := uint32(10) data := DeclareCandidacyData{ Address: addr, @@ -277,7 +277,7 @@ func TestDeclareCandidacyToNonExistenCoin(t *testing.T) { var publicKey types.Pubkey copy(publicKey[:], publicKeyBytes) - commission := uint(10) + commission := uint32(10) data := DeclareCandidacyData{ Address: addr, @@ -332,9 +332,9 @@ func TestDeclareCandidacyToExistenCandidate(t *testing.T) { var publicKey types.Pubkey copy(publicKey[:], publicKeyBytes) - cState.Candidates.Create(addr, addr, addr, publicKey, uint(10)) + cState.Candidates.Create(addr, addr, addr, publicKey, uint32(10)) - commission := uint(10) + commission := uint32(10) data := DeclareCandidacyData{ Address: addr, @@ -389,7 +389,7 @@ func TestDeclareCandidacyToDecodeError(t *testing.T) { var publicKey types.Pubkey copy(publicKey[:], publicKeyBytes) - commission := uint(10) + commission := uint32(10) data := DeclareCandidacyData{ Address: addr, @@ -492,7 +492,7 @@ func TestDeclareCandidacyToInsufficientFunds(t *testing.T) { data := DeclareCandidacyData{ Address: addr, PubKey: publicKey, - Commission: uint(10), + Commission: uint32(10), Coin: coin, Stake: stake, } @@ -592,7 +592,7 @@ func TestDeclareCandidacyTxToGasCoinReserveUnderflow(t *testing.T) { data := DeclareCandidacyData{ Address: addr, PubKey: publicKey, - Commission: uint(10), + Commission: uint32(10), Coin: coin, Stake: stake, } diff --git a/core/transaction/edit_multisig.go b/core/transaction/edit_multisig.go index 88adaa2c1..a07229729 100644 --- a/core/transaction/edit_multisig.go +++ b/core/transaction/edit_multisig.go @@ -15,8 +15,8 @@ import ( ) type EditMultisigData struct { - Threshold uint - Weights []uint + Threshold uint32 + Weights []uint32 Addresses []types.Address } @@ -72,7 +72,7 @@ func (data EditMultisigData) BasicCheck(tx *Transaction, context *state.CheckSta usedAddresses[address] = true } - var totalWeight uint + var totalWeight uint32 for _, weight := range data.Weights { totalWeight += weight } diff --git a/core/transaction/edit_multisig_test.go b/core/transaction/edit_multisig_test.go index 85f78541f..028722600 100644 --- a/core/transaction/edit_multisig_test.go +++ b/core/transaction/edit_multisig_test.go @@ -31,7 +31,7 @@ func TestEditMultisigTx(t *testing.T) { privateKey4, _ := crypto.GenerateKey() addr4 := crypto.PubkeyToAddress(privateKey4.PublicKey) - cState.Accounts.CreateMultisig([]uint{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) coin := types.GetBaseCoinID() initialBalance := big.NewInt(1) @@ -39,7 +39,7 @@ func TestEditMultisigTx(t *testing.T) { data := EditMultisigData{ Threshold: 3, - Weights: []uint{2, 1, 2}, + Weights: []uint32{2, 1, 2}, Addresses: []types.Address{addr1, addr2, addr4}, } @@ -111,7 +111,7 @@ func TestEditMultisigTxToNonExistenAddress(t *testing.T) { data := EditMultisigData{ Threshold: 3, - Weights: []uint{2, 1, 2}, + Weights: []uint32{2, 1, 2}, Addresses: []types.Address{addr1, addr2, addr3}, } @@ -156,10 +156,10 @@ func TestEditMultisigTxToTooLargeOwnersList(t *testing.T) { coin := types.GetBaseCoinID() - cState.Accounts.CreateMultisig([]uint{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) - weights := make([]uint, 33) - for i := uint(0); i <= 32; i++ { + weights := make([]uint32, 33) + for i := uint32(0); i <= 32; i++ { weights[i] = i } @@ -214,11 +214,11 @@ func TestEditMultisigTxIncorrectWeights(t *testing.T) { coin := types.GetBaseCoinID() - cState.Accounts.CreateMultisig([]uint{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) data := EditMultisigData{ Threshold: 3, - Weights: []uint{1, 2, 3, 4}, + Weights: []uint32{1, 2, 3, 4}, Addresses: []types.Address{addr1, addr2, addr3}, } @@ -253,7 +253,7 @@ func TestEditMultisigTxIncorrectWeights(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.DifferentCountAddressesAndWeights, response.Log) } - data.Weights = []uint{1, 2, 1024} + data.Weights = []uint32{1, 2, 1024} encodedData, err = rlp.EncodeToBytes(data) if err != nil { t.Fatal(err) @@ -274,7 +274,7 @@ func TestEditMultisigTxIncorrectWeights(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.IncorrectWeights, response.Log) } - data.Weights = []uint{1, 2, 3} + data.Weights = []uint32{1, 2, 3} data.Threshold = 7 encodedData, err = rlp.EncodeToBytes(data) if err != nil { @@ -310,11 +310,11 @@ func TestEditMultisigTxToAddressDuplication(t *testing.T) { coin := types.GetBaseCoinID() - cState.Accounts.CreateMultisig([]uint{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) data := EditMultisigData{ Threshold: 3, - Weights: []uint{1, 2, 3}, + Weights: []uint32{1, 2, 3}, Addresses: []types.Address{addr1, addr1, addr3}, } @@ -363,11 +363,11 @@ func TestEditMultisigTxToInsufficientFunds(t *testing.T) { coin := types.GetBaseCoinID() - cState.Accounts.CreateMultisig([]uint{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) data := EditMultisigData{ Threshold: 3, - Weights: []uint{1, 2, 3}, + Weights: []uint32{1, 2, 3}, Addresses: []types.Address{addr1, addr2, addr3}, } @@ -417,11 +417,11 @@ func TestEditMultisigTxToGasCoinReserveUnderflow(t *testing.T) { coin := createTestCoin(cState) cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) - cState.Accounts.CreateMultisig([]uint{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) data := EditMultisigData{ Threshold: 3, - Weights: []uint{1, 2, 3}, + Weights: []uint32{1, 2, 3}, Addresses: []types.Address{addr1, addr2, addr3}, } diff --git a/core/transaction/executor.go b/core/transaction/executor.go index c5000b9d3..148f119a6 100644 --- a/core/transaction/executor.go +++ b/core/transaction/executor.go @@ -150,7 +150,7 @@ func RunTx(context state.Interface, } txHash := tx.Hash() - var totalWeight uint + var totalWeight uint32 var usedAccounts = map[types.Address]bool{} for _, sig := range tx.multisig.Signatures { diff --git a/core/transaction/executor_test.go b/core/transaction/executor_test.go index 798230f6d..f376284a6 100644 --- a/core/transaction/executor_test.go +++ b/core/transaction/executor_test.go @@ -232,7 +232,7 @@ func TestMultiSigTx(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - msigAddress := cState.Accounts.CreateMultisig([]uint{1}, []types.Address{addr}, 1, 1, accounts.CreateMultisigAddress(addr, 1)) + msigAddress := cState.Accounts.CreateMultisig([]uint32{1}, []types.Address{addr}, 1, 1, accounts.CreateMultisigAddress(addr, 1)) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ @@ -276,7 +276,7 @@ func TestMultiSigDoubleSignTx(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - msigAddress := cState.Accounts.CreateMultisig([]uint{1, 1}, []types.Address{addr, {}}, 2, 1, accounts.CreateMultisigAddress(addr, 1)) + msigAddress := cState.Accounts.CreateMultisig([]uint32{1, 1}, []types.Address{addr, {}}, 2, 1, accounts.CreateMultisigAddress(addr, 1)) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ @@ -324,7 +324,7 @@ func TestMultiSigTooManySignsTx(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - msigAddress := cState.Accounts.CreateMultisig([]uint{1, 1}, []types.Address{addr, {}}, 2, 1, accounts.CreateMultisigAddress(addr, 1)) + msigAddress := cState.Accounts.CreateMultisig([]uint32{1, 1}, []types.Address{addr, {}}, 2, 1, accounts.CreateMultisigAddress(addr, 1)) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ @@ -375,7 +375,7 @@ func TestMultiSigNotEnoughTx(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - msigAddress := cState.Accounts.CreateMultisig([]uint{1}, []types.Address{addr}, 2, 1, accounts.CreateMultisigAddress(addr, 1)) + msigAddress := cState.Accounts.CreateMultisig([]uint32{1}, []types.Address{addr}, 2, 1, accounts.CreateMultisigAddress(addr, 1)) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ @@ -419,7 +419,7 @@ func TestMultiSigIncorrectSignsTx(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - msigAddress := cState.Accounts.CreateMultisig([]uint{1}, []types.Address{addr}, 1, 1, accounts.CreateMultisigAddress(addr, 1)) + msigAddress := cState.Accounts.CreateMultisig([]uint32{1}, []types.Address{addr}, 1, 1, accounts.CreateMultisigAddress(addr, 1)) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index c5fbf57b6..355a4359b 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -19,7 +19,7 @@ type RecreateCoinData struct { Symbol types.CoinSymbol InitialAmount *big.Int InitialReserve *big.Int - ConstantReserveRatio uint + ConstantReserveRatio uint32 MaxSupply *big.Int } diff --git a/core/transaction/recreate_coin_test.go b/core/transaction/recreate_coin_test.go index 34f971e98..b5f6eac2c 100644 --- a/core/transaction/recreate_coin_test.go +++ b/core/transaction/recreate_coin_test.go @@ -27,7 +27,7 @@ func TestRecreateCoinTx(t *testing.T) { reserve := helpers.BipToPip(big.NewInt(10000)) amount := helpers.BipToPip(big.NewInt(100)) - crr := uint(50) + crr := uint32(50) data := RecreateCoinData{ Name: "TEST", @@ -118,7 +118,7 @@ func TestRecreateCoinTxWithWrongOwner(t *testing.T) { reserve := helpers.BipToPip(big.NewInt(10000)) amount := helpers.BipToPip(big.NewInt(100)) - crr := uint(50) + crr := uint32(50) data := RecreateCoinData{ Symbol: getTestCoinSymbol(), @@ -152,7 +152,7 @@ func TestRecreateCoinTxWithWrongSymbol(t *testing.T) { reserve := helpers.BipToPip(big.NewInt(10000)) amount := helpers.BipToPip(big.NewInt(100)) - crr := uint(50) + crr := uint32(50) data := RecreateCoinData{ Symbol: types.StrToCoinSymbol("UNKNOWN"), @@ -185,7 +185,7 @@ func TestRecreateCoinWithIncorrectName(t *testing.T) { toCreate := types.StrToCoinSymbol("ABCDEF") reserve := helpers.BipToPip(big.NewInt(10000)) amount := helpers.BipToPip(big.NewInt(100)) - crr := uint(50) + crr := uint32(50) var name [65]byte binary.BigEndian.PutUint64(name[:], 0) @@ -243,7 +243,7 @@ func TestRecreateCoinWithWrongCrr(t *testing.T) { toCreate := types.StrToCoinSymbol("ABCDEF") reserve := helpers.BipToPip(big.NewInt(10000)) amount := helpers.BipToPip(big.NewInt(100)) - crr := uint(9) + crr := uint32(9) name := "My Test Coin" data := RecreateCoinData{ @@ -284,7 +284,7 @@ func TestRecreateCoinWithWrongCrr(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.WrongCrr, response.Log) } - data.ConstantReserveRatio = uint(101) + data.ConstantReserveRatio = uint32(101) encodedData, err = rlp.EncodeToBytes(data) if err != nil { t.Fatal(err) @@ -326,7 +326,7 @@ func TestRecreateCoinWithWrongCoinSupply(t *testing.T) { toCreate := types.StrToCoinSymbol("ABCDEF") reserve := helpers.BipToPip(big.NewInt(10000)) - crr := uint(50) + crr := uint32(50) name := "My Test Coin" data := RecreateCoinData{ @@ -452,7 +452,7 @@ func TestRecreateCoinWithInsufficientFundsForGas(t *testing.T) { toCreate := types.StrToCoinSymbol("TEST") reserve := helpers.BipToPip(big.NewInt(10000)) - crr := uint(50) + crr := uint32(50) name := "My Test Coin" data := RecreateCoinData{ @@ -525,7 +525,7 @@ func TestRecreateCoinToInsufficientFundsForInitialReserve(t *testing.T) { toCreate := types.StrToCoinSymbol("TEST") reserve := helpers.BipToPip(big.NewInt(100000)) - crr := uint(50) + crr := uint32(50) name := "My Test Coin" data := RecreateCoinData{ @@ -563,7 +563,7 @@ func TestRecreateCoinToGasCoinReserveUnderflow(t *testing.T) { toCreate := types.StrToCoinSymbol("TEST") reserve := helpers.BipToPip(big.NewInt(100000)) - crr := uint(50) + crr := uint32(50) name := "My Test Coin" data := RecreateCoinData{ diff --git a/core/transaction/send_test.go b/core/transaction/send_test.go index 1dee5da2c..5d9538813 100644 --- a/core/transaction/send_test.go +++ b/core/transaction/send_test.go @@ -84,7 +84,7 @@ func TestSendMultisigTx(t *testing.T) { coin := types.GetBaseCoinID() - msig := cState.Accounts.CreateMultisig([]uint{1, 1}, []types.Address{addr1, addr2}, 1, 1, accounts.CreateMultisigAddress(addr1, 1)) + msig := cState.Accounts.CreateMultisig([]uint32{1, 1}, []types.Address{addr1, addr2}, 1, 1, accounts.CreateMultisigAddress(addr1, 1)) cState.Accounts.AddBalance(msig, coin, helpers.BipToPip(big.NewInt(1000000))) @@ -152,7 +152,7 @@ func TestSendFailedMultisigTx(t *testing.T) { coin := types.GetBaseCoinID() - msig := cState.Accounts.CreateMultisig([]uint{1, 3}, []types.Address{addr1, addr2}, 3, 1, accounts.CreateMultisigAddress(addr1, 1)) + msig := cState.Accounts.CreateMultisig([]uint32{1, 3}, []types.Address{addr1, addr2}, 3, 1, accounts.CreateMultisigAddress(addr1, 1)) cState.Accounts.AddBalance(msig, coin, helpers.BipToPip(big.NewInt(1000000))) diff --git a/core/types/appstate.go b/core/types/appstate.go index 8ef627ca1..a634a9e46 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -82,18 +82,20 @@ func (s *AppState) Verify() error { return fmt.Errorf("not valid balance for account %s", acc.Address.String()) } - if !bal.Coin.IsBaseCoin() { + coinID := CoinID(bal.Coin) + if !coinID.IsBaseCoin() { // check not existing coins foundCoin := false for _, coin := range s.Coins { - if coin.ID == bal.Coin { + id := CoinID(coin.ID) + if id == coinID { foundCoin = true break } } if !foundCoin { - return fmt.Errorf("coin %s not found", bal.Coin) + return fmt.Errorf("coin %s not found", coinID) } } } @@ -103,24 +105,26 @@ func (s *AppState) Verify() error { stakes := map[string]struct{}{} for _, stake := range candidate.Stakes { // check duplicated stakes - key := fmt.Sprintf("%s:%s", stake.Owner.String(), stake.Coin.String()) + coinID := CoinID(stake.Coin) + key := fmt.Sprintf("%s:%s", stake.Owner.String(), coinID.String()) if _, exists := stakes[key]; exists { return fmt.Errorf("duplicated stake %s", key) } stakes[key] = struct{}{} // check not existing coins - if !stake.Coin.IsBaseCoin() { + if !coinID.IsBaseCoin() { foundCoin := false for _, coin := range s.Coins { - if coin.ID == stake.Coin { + id := CoinID(coin.ID) + if id == coinID { foundCoin = true break } } if !foundCoin { - return fmt.Errorf("coin %s not found", stake.Coin) + return fmt.Errorf("coin %s not found", coinID) } } } @@ -173,17 +177,19 @@ func (s *AppState) Verify() error { } // check not existing coins - if !ff.Coin.IsBaseCoin() { + coinID := CoinID(ff.Coin) + if !coinID.IsBaseCoin() { foundCoin := false for _, coin := range s.Coins { - if coin.ID == ff.Coin { + id := CoinID(coin.ID) + if id == coinID { foundCoin = true break } } if !foundCoin { - return fmt.Errorf("coin %s not found", ff.Coin) + return fmt.Errorf("coin %s not found", coinID) } } } @@ -211,38 +217,38 @@ type Validator struct { } type Candidate struct { - ID uint32 `json:"id"` + ID uint64 `json:"id"` RewardAddress Address `json:"reward_address"` OwnerAddress Address `json:"owner_address"` ControlAddress Address `json:"control_address"` TotalBipStake string `json:"total_bip_stake"` PubKey Pubkey `json:"public_key"` - Commission uint `json:"commission"` + Commission uint64 `json:"commission"` Stakes []Stake `json:"stakes"` Updates []Stake `json:"updates"` - Status byte `json:"status"` + Status uint64 `json:"status"` } type Stake struct { Owner Address `json:"owner"` - Coin CoinID `json:"coin"` + Coin uint64 `json:"coin"` Value string `json:"value"` BipValue string `json:"bip_value"` } type Waitlist struct { - CandidateID uint32 `json:"candidate_id"` + CandidateID uint64 `json:"candidate_id"` Owner Address `json:"owner"` - Coin CoinID `json:"coin"` + Coin uint64 `json:"coin"` Value string `json:"value"` } type Coin struct { - ID CoinID `json:"id"` + ID uint64 `json:"id"` Name string `json:"name"` Symbol CoinSymbol `json:"symbol"` Volume string `json:"volume"` - Crr uint `json:"crr"` + Crr uint64 `json:"crr"` Reserve string `json:"reserve"` MaxSupply string `json:"max_supply"` Version CoinVersion `json:"version"` @@ -253,7 +259,7 @@ type FrozenFund struct { Height uint64 `json:"height"` Address Address `json:"address"` CandidateKey *Pubkey `json:"candidate_key,omitempty"` - Coin CoinID `json:"coin"` + Coin uint64 `json:"coin"` Value string `json:"value"` } @@ -267,13 +273,13 @@ type Account struct { } type Balance struct { - Coin CoinID `json:"coin"` + Coin uint64 `json:"coin"` Value string `json:"value"` } type Multisig struct { - Weights []uint `json:"weights"` - Threshold uint `json:"threshold"` + Weights []uint32 `json:"weights"` + Threshold uint32 `json:"threshold"` Addresses []Address `json:"addresses"` } diff --git a/core/types/types_test.go b/core/types/types_test.go index 72e25e40b..d1c074ed4 100644 --- a/core/types/types_test.go +++ b/core/types/types_test.go @@ -154,7 +154,7 @@ func TestAppState(t *testing.T) { Stakes: []Stake{ { Owner: testAddr, - Coin: GetBaseCoinID(), + Coin: uint64(GetBaseCoinID()), Value: big.NewInt(1).String(), BipValue: big.NewInt(1).String(), }, @@ -167,17 +167,17 @@ func TestAppState(t *testing.T) { Address: testAddr, Balance: []Balance{ { - Coin: GetBaseCoinID(), + Coin: uint64(GetBaseCoinID()), Value: big.NewInt(1).String(), }, { - Coin: GetBaseCoinID() + 1, + Coin: uint64(GetBaseCoinID() + 1), Value: big.NewInt(1).String(), }, }, Nonce: 1, MultisigData: &Multisig{ - Weights: []uint{1, 2, 3}, + Weights: []uint32{1, 2, 3}, Threshold: 1, Addresses: []Address{testAddr, testAddr}, }, @@ -185,7 +185,7 @@ func TestAppState(t *testing.T) { }, Coins: []Coin{ { - ID: GetBaseCoinID() + 1, + ID: uint64(GetBaseCoinID() + 1), Name: "ASD", Symbol: StrToCoinSymbol("TEST"), Volume: big.NewInt(2).String(), @@ -199,7 +199,7 @@ func TestAppState(t *testing.T) { Height: 1, Address: testAddr, CandidateKey: &pubkey, - Coin: GetBaseCoinID() + 1, + Coin: uint64(GetBaseCoinID() + 1), Value: big.NewInt(1).String(), }, }, @@ -281,7 +281,7 @@ func TestAppStateToInvalidState(t *testing.T) { Stakes: []Stake{ { Owner: testAddr, - Coin: GetBaseCoinID(), + Coin: uint64(GetBaseCoinID()), Value: big.NewInt(1).String(), BipValue: big.NewInt(1).String(), }, @@ -331,7 +331,7 @@ func TestAppStateToInvalidState(t *testing.T) { Stakes: []Stake{ { Owner: testAddr, - Coin: GetBaseCoinID(), + Coin: uint64(GetBaseCoinID()), Value: big.NewInt(1).String(), BipValue: big.NewInt(1).String(), }, @@ -362,7 +362,7 @@ func TestAppStateToInvalidState(t *testing.T) { Address: testAddr, Balance: []Balance{ { - Coin: GetBaseCoinID(), + Coin: uint64(GetBaseCoinID()), Value: big.NewInt(1).String(), }, }, @@ -371,7 +371,7 @@ func TestAppStateToInvalidState(t *testing.T) { Address: testAddr, Balance: []Balance{ { - Coin: GetBaseCoinID(), + Coin: uint64(GetBaseCoinID()), Value: big.NewInt(1).String(), }, }, @@ -389,7 +389,7 @@ func TestAppStateToInvalidState(t *testing.T) { Address: testAddr, Balance: []Balance{ { - Coin: GetBaseCoinID(), + Coin: uint64(GetBaseCoinID()), Value: "", }, }, @@ -406,7 +406,7 @@ func TestAppStateToInvalidState(t *testing.T) { Address: testAddr, Balance: []Balance{ { - Coin: GetBaseCoinID() + 1, + Coin: uint64(GetBaseCoinID() + 1), Value: big.NewInt(1).String(), }, }, @@ -423,7 +423,7 @@ func TestAppStateToInvalidState(t *testing.T) { Address: testAddr, Balance: []Balance{ { - Coin: GetBaseCoinID(), + Coin: uint64(GetBaseCoinID()), Value: big.NewInt(1).String(), }, }, @@ -434,13 +434,13 @@ func TestAppStateToInvalidState(t *testing.T) { appState.Candidates[0].Stakes = []Stake{ { Owner: testAddr, - Coin: GetBaseCoinID(), + Coin: uint64(GetBaseCoinID()), Value: big.NewInt(1).String(), BipValue: big.NewInt(1).String(), }, { Owner: testAddr, - Coin: GetBaseCoinID(), + Coin: uint64(GetBaseCoinID()), Value: big.NewInt(1).String(), BipValue: big.NewInt(1).String(), }, @@ -453,7 +453,7 @@ func TestAppStateToInvalidState(t *testing.T) { appState.Candidates[0].Stakes = []Stake{ { Owner: testAddr, - Coin: GetBaseCoinID() + 1, + Coin: uint64(GetBaseCoinID() + 1), Value: big.NewInt(1).String(), BipValue: big.NewInt(1).String(), }, @@ -461,7 +461,7 @@ func TestAppStateToInvalidState(t *testing.T) { appState.Coins = []Coin{ { - ID: GetBaseCoinID() + 2, + ID: uint64(GetBaseCoinID() + 2), }, } @@ -472,7 +472,7 @@ func TestAppStateToInvalidState(t *testing.T) { appState.Candidates[0].Stakes = []Stake{ { Owner: testAddr, - Coin: GetBaseCoinID() + 1, + Coin: uint64(GetBaseCoinID() + 1), Value: big.NewInt(1).String(), BipValue: big.NewInt(1).String(), }, @@ -480,7 +480,7 @@ func TestAppStateToInvalidState(t *testing.T) { appState.Coins = []Coin{ { - ID: GetBaseCoinID() + 1, + ID: uint64(GetBaseCoinID() + 1), Name: "ASD", Symbol: StrToCoinSymbol("TEST"), Volume: big.NewInt(1).String(), @@ -489,7 +489,7 @@ func TestAppStateToInvalidState(t *testing.T) { MaxSupply: helpers.BipToPip(big.NewInt(100000)).String(), }, { - ID: GetBaseCoinID(), + ID: uint64(GetBaseCoinID()), Symbol: GetBaseCoin(), }, } @@ -500,7 +500,7 @@ func TestAppStateToInvalidState(t *testing.T) { appState.Coins = []Coin{ { - ID: GetBaseCoinID() + 1, + ID: uint64(GetBaseCoinID() + 1), Name: "ASD", Symbol: StrToCoinSymbol("TEST"), Volume: big.NewInt(1).String(), @@ -509,7 +509,7 @@ func TestAppStateToInvalidState(t *testing.T) { MaxSupply: helpers.BipToPip(big.NewInt(100000)).String(), }, { - ID: GetBaseCoinID() + 1, + ID: uint64(GetBaseCoinID() + 1), Name: "ASD", Symbol: StrToCoinSymbol("TEST"), Volume: big.NewInt(1).String(), @@ -518,7 +518,7 @@ func TestAppStateToInvalidState(t *testing.T) { MaxSupply: helpers.BipToPip(big.NewInt(100000)).String(), }, { - ID: GetBaseCoinID(), + ID: uint64(GetBaseCoinID()), Symbol: GetBaseCoin(), }, } @@ -529,7 +529,7 @@ func TestAppStateToInvalidState(t *testing.T) { appState.Coins = []Coin{ { - ID: GetBaseCoinID() + 1, + ID: uint64(GetBaseCoinID() + 1), Name: "ASD", Symbol: StrToCoinSymbol("TEST"), Volume: big.NewInt(1).String(), @@ -544,7 +544,7 @@ func TestAppStateToInvalidState(t *testing.T) { Height: 1, Address: testAddr, CandidateKey: &pubkey, - Coin: GetBaseCoinID() + 1, + Coin: uint64(GetBaseCoinID() + 1), Value: big.NewInt(1e18).String(), }, } @@ -558,7 +558,7 @@ func TestAppStateToInvalidState(t *testing.T) { Height: 1, Address: testAddr, CandidateKey: &pubkey, - Coin: GetBaseCoinID(), + Coin: uint64(GetBaseCoinID()), Value: "", }, } @@ -572,7 +572,7 @@ func TestAppStateToInvalidState(t *testing.T) { Height: 1, Address: testAddr, CandidateKey: &pubkey, - Coin: GetBaseCoinID() + 3, + Coin: uint64(GetBaseCoinID() + 3), Value: big.NewInt(1e18).String(), }, } @@ -586,7 +586,7 @@ func TestAppStateToInvalidState(t *testing.T) { Height: 1, Address: testAddr, CandidateKey: &pubkey, - Coin: GetBaseCoinID(), + Coin: uint64(GetBaseCoinID()), Value: big.NewInt(1e18).String(), }, } diff --git a/formula/formula.go b/formula/formula.go index a703e1dd3..bd8769a72 100644 --- a/formula/formula.go +++ b/formula/formula.go @@ -12,7 +12,7 @@ const ( // CalculatePurchaseReturn calculates amount of coin that user will receive by depositing given amount of BIP // Return = supply * ((1 + deposit / reserve) ^ (crr / 100) - 1) -func CalculatePurchaseReturn(supply *big.Int, reserve *big.Int, crr uint, deposit *big.Int) *big.Int { +func CalculatePurchaseReturn(supply *big.Int, reserve *big.Int, crr uint32, deposit *big.Int) *big.Int { if deposit.Cmp(types.Big0) == 0 { return big.NewInt(0) } @@ -40,7 +40,7 @@ func CalculatePurchaseReturn(supply *big.Int, reserve *big.Int, crr uint, deposi // CalculatePurchaseAmount is the reversed version of function CalculatePurchaseReturn // Deposit = reserve * (((wantReceive + supply) / supply)^(100/c) - 1) -func CalculatePurchaseAmount(supply *big.Int, reserve *big.Int, crr uint, wantReceive *big.Int) *big.Int { +func CalculatePurchaseAmount(supply *big.Int, reserve *big.Int, crr uint32, wantReceive *big.Int) *big.Int { if wantReceive.Cmp(types.Big0) == 0 { return big.NewInt(0) } @@ -68,7 +68,7 @@ func CalculatePurchaseAmount(supply *big.Int, reserve *big.Int, crr uint, wantRe // CalculateSaleReturn returns amount of BIP user will receive by depositing given amount of coins // Return = reserve * (1 - (1 - sellAmount / supply) ^ (100 / crr)) -func CalculateSaleReturn(supply *big.Int, reserve *big.Int, crr uint, sellAmount *big.Int) *big.Int { +func CalculateSaleReturn(supply *big.Int, reserve *big.Int, crr uint32, sellAmount *big.Int) *big.Int { // special case for 0 sell amount if sellAmount.Cmp(types.Big0) == 0 { return big.NewInt(0) @@ -103,7 +103,7 @@ func CalculateSaleReturn(supply *big.Int, reserve *big.Int, crr uint, sellAmount // CalculateSaleAmount is the reversed version of function CalculateSaleReturn // Deposit = -(-1 + (-(wantReceive - reserve)/reserve)^(1/crr)) * supply -func CalculateSaleAmount(supply *big.Int, reserve *big.Int, crr uint, wantReceive *big.Int) *big.Int { +func CalculateSaleAmount(supply *big.Int, reserve *big.Int, crr uint32, wantReceive *big.Int) *big.Int { if wantReceive.Cmp(types.Big0) == 0 { return big.NewInt(0) } diff --git a/formula/formula_test.go b/formula/formula_test.go index 8407c3793..f56f4aaf6 100644 --- a/formula/formula_test.go +++ b/formula/formula_test.go @@ -8,7 +8,7 @@ import ( type PurchaseReturnData struct { Supply *big.Int Reserve *big.Int - Crr uint + Crr uint32 Deposit *big.Int Result *big.Int } @@ -50,7 +50,7 @@ func TestCalculatePurchaseReturn(t *testing.T) { type PurchaseAmountData struct { Supply *big.Int Reserve *big.Int - Crr uint + Crr uint32 WantReceive *big.Int Deposit *big.Int } @@ -92,7 +92,7 @@ func TestCalculatePurchaseAmount(t *testing.T) { type CalculateSaleReturnData struct { Supply *big.Int Reserve *big.Int - Crr uint + Crr uint32 SellAmount *big.Int Result *big.Int } @@ -141,7 +141,7 @@ func TestCalculateSaleReturn(t *testing.T) { type CalculateBuyDepositData struct { Supply *big.Int Reserve *big.Int - Crr uint + Crr uint32 WantReceive *big.Int Result *big.Int } diff --git a/legacy/accounts/model.go b/legacy/accounts/model.go index 307773997..ef67c6fb4 100644 --- a/legacy/accounts/model.go +++ b/legacy/accounts/model.go @@ -27,8 +27,8 @@ type Model struct { } type Multisig struct { - Threshold uint - Weights []uint + Threshold uint32 + Weights []uint32 Addresses []types.Address } @@ -44,7 +44,7 @@ func (m *Multisig) Address() types.Address { return addr } -func (m *Multisig) GetWeight(address types.Address) uint { +func (m *Multisig) GetWeight(address types.Address) uint32 { for i, addr := range m.Addresses { if addr == address { return m.Weights[i] diff --git a/legacy/candidates/candidates.go b/legacy/candidates/candidates.go index 5c1eb7bd1..edfe8d3d9 100644 --- a/legacy/candidates/candidates.go +++ b/legacy/candidates/candidates.go @@ -68,7 +68,7 @@ func (c *Candidates) GetNewCandidates(valCount int) []Candidate { return result } -func (c *Candidates) Create(ownerAddress types.Address, rewardAddress types.Address, pubkey types.Pubkey, commission uint) { +func (c *Candidates) Create(ownerAddress types.Address, rewardAddress types.Address, pubkey types.Pubkey, commission uint32) { candidate := &Candidate{ PubKey: pubkey, RewardAddress: rewardAddress, @@ -259,14 +259,14 @@ func (c *Candidates) Export(state *types.AppState, coinsMap map[types.CoinSymbol } state.Candidates = append(state.Candidates, types.Candidate{ - ID: maxID, + ID: uint64(maxID), RewardAddress: candidate.RewardAddress, OwnerAddress: candidate.OwnerAddress, ControlAddress: candidate.OwnerAddress, TotalBipStake: candidate.GetTotalBipStake().String(), PubKey: candidate.PubKey, - Commission: candidate.Commission, - Status: candidate.Status, + Commission: uint64(candidate.Commission), + Status: uint64(candidate.Status), Updates: updates, Stakes: stakes, }) diff --git a/legacy/candidates/model.go b/legacy/candidates/model.go index 6b6830b09..10c4395bf 100644 --- a/legacy/candidates/model.go +++ b/legacy/candidates/model.go @@ -11,7 +11,7 @@ type Candidate struct { PubKey types.Pubkey RewardAddress types.Address OwnerAddress types.Address - Commission uint + Commission uint32 Status byte totalBipStake *big.Int diff --git a/legacy/coins/coins.go b/legacy/coins/coins.go index e3fe6b590..08f1b2b4d 100644 --- a/legacy/coins/coins.go +++ b/legacy/coins/coins.go @@ -117,7 +117,7 @@ func (c *Coins) Export(state *types.AppState) map[types.CoinSymbol]types.Coin { Name: coin.Name(), Symbol: coin.Symbol(), Volume: coin.Volume().String(), - Crr: coin.Crr(), + Crr: uint64(coin.Crr()), Reserve: coin.Reserve().String(), MaxSupply: coin.MaxSupply().String(), Version: 0, @@ -134,10 +134,10 @@ func (c *Coins) Export(state *types.AppState) map[types.CoinSymbol]types.Coin { }) coinsMap := make(map[types.CoinSymbol]types.Coin, len(coins)) - coinsMap[types.GetBaseCoin()] = types.Coin{ID: types.GetBaseCoinID()} + coinsMap[types.GetBaseCoin()] = types.Coin{ID: uint64(types.GetBaseCoinID())} - for i, _ := range coins { - coins[i].ID = types.CoinID(i + 1) + for i := range coins { + coins[i].ID = uint64(i + 1) coinsMap[coins[i].Symbol] = coins[i] } diff --git a/tests/send_test.go b/tests/send_test.go index 9abd9ea70..3726475a4 100644 --- a/tests/send_test.go +++ b/tests/send_test.go @@ -19,7 +19,7 @@ func TestSend(t *testing.T) { Address: address, Balance: []types.Balance{ { - Coin: types.GetBaseCoinID(), + Coin: uint64(types.GetBaseCoinID()), Value: helpers.BipToPip(big.NewInt(1)).String(), }, }, From 526e5ab49d3a4c645c35183cd52c51899f6c7250 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 24 Sep 2020 19:49:20 +0300 Subject: [PATCH 312/426] update api types --- api/v2/service/address.go | 9 ++-- api/v2/service/addresses.go | 8 ++-- api/v2/service/block.go | 29 +++++++------ api/v2/service/candidate.go | 11 +++-- api/v2/service/coin_info.go | 9 ++-- api/v2/service/data_encoder.go | 42 +++++++++---------- api/v2/service/frozen.go | 5 +-- api/v2/service/gas.go | 11 +++-- api/v2/service/genesis.go | 17 ++++---- api/v2/service/halts.go | 2 +- api/v2/service/missed_blocks.go | 3 +- api/v2/service/net_info.go | 67 ++++++++++++++++++------------ api/v2/service/send_transaction.go | 3 +- api/v2/service/status.go | 4 +- api/v2/service/transaction.go | 27 ++++++------ api/v2/service/transactions.go | 27 ++++++------ api/v2/service/unconfirmed_txs.go | 12 ++++-- api/v2/service/validators.go | 3 +- api/v2/service/waitlist.go | 2 +- core/state/coins/coins.go | 2 +- core/types/appstate.go | 18 ++++---- go.mod | 2 +- go.sum | 4 +- 23 files changed, 168 insertions(+), 149 deletions(-) diff --git a/api/v2/service/address.go b/api/v2/service/address.go index 9a677f1a1..ba0baa510 100644 --- a/api/v2/service/address.go +++ b/api/v2/service/address.go @@ -3,7 +3,6 @@ package service import ( "context" "encoding/hex" - "fmt" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/formula" @@ -57,7 +56,7 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr totalStakesGroupByCoin[coin.Coin.ID] = coin.Value res.Balance = append(res.Balance, &pb.AddressBalance{ Coin: &pb.Coin{ - Id: coin.Coin.ID.String(), + Id: uint64(coin.Coin.ID), Symbol: cState.Coins().GetCoin(coin.Coin.ID).Symbol().String(), }, Value: coin.Value.String(), @@ -96,7 +95,7 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr for coinID, delegatedStake := range userDelegatedStakesGroupByCoin { res.Delegated = append(res.Delegated, &pb.AddressDelegatedBalance{ Coin: &pb.Coin{ - Id: coinID.String(), + Id: uint64(coinID), Symbol: cState.Coins().GetCoin(coinID).Symbol().String(), }, Value: delegatedStake.Value.String(), @@ -124,7 +123,7 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr if req.Delegated { res.Total = append(res.Total, &pb.AddressBalance{ Coin: &pb.Coin{ - Id: coinID.String(), + Id: uint64(coinID), Symbol: cState.Coins().GetCoin(coinID).Symbol().String(), }, Value: stake.String(), @@ -134,7 +133,7 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr coinsBipValue.Add(coinsBipValue, balance) } res.BipValue = coinsBipValue.String() - res.TransactionCount = fmt.Sprintf("%d", cState.Accounts().GetNonce(address)) + res.TransactionCount = cState.Accounts().GetNonce(address) return &res, nil } diff --git a/api/v2/service/addresses.go b/api/v2/service/addresses.go index f6caa4162..f5f55c1fe 100644 --- a/api/v2/service/addresses.go +++ b/api/v2/service/addresses.go @@ -58,7 +58,7 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. totalStakesGroupByCoin[coin.Coin.ID] = coin.Value res.Balance = append(res.Balance, &pb.AddressBalance{ Coin: &pb.Coin{ - Id: coin.Coin.ID.String(), + Id: uint64(coin.Coin.ID), Symbol: cState.Coins().GetCoin(coin.Coin.ID).Symbol().String(), }, Value: coin.Value.String(), @@ -97,7 +97,7 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. for coinID, delegatedStake := range userDelegatedStakesGroupByCoin { res.Delegated = append(res.Delegated, &pb.AddressDelegatedBalance{ Coin: &pb.Coin{ - Id: coinID.String(), + Id: uint64(coinID), Symbol: cState.Coins().GetCoin(coinID).Symbol().String(), }, Value: delegatedStake.Value.String(), @@ -125,7 +125,7 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. if req.Delegated { res.Total = append(res.Total, &pb.AddressBalance{ Coin: &pb.Coin{ - Id: coinID.String(), + Id: uint64(coinID), Symbol: cState.Coins().GetCoin(coinID).Symbol().String(), }, Value: stake.String(), @@ -135,7 +135,7 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. coinsBipValue.Add(coinsBipValue, balance) } res.BipValue = coinsBipValue.String() - res.TransactionCount = fmt.Sprintf("%d", cState.Accounts().GetNonce(address)) + res.TransactionCount = uint64(cState.Accounts().GetNonce(address)) response.Addresses[addr] = &res } diff --git a/api/v2/service/block.go b/api/v2/service/block.go index 6dc4cc3d2..067d4b5b8 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -39,16 +39,16 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes response := &pb.BlockResponse{ Hash: hex.EncodeToString(block.Block.Hash()), - Height: fmt.Sprintf("%d", block.Block.Height), + Height: uint64(block.Block.Height), Time: block.Block.Time.Format(time.RFC3339Nano), - TransactionCount: fmt.Sprintf("%d", len(block.Block.Txs)), + TransactionCount: uint64(len(block.Block.Txs)), } var totalValidators []*tmTypes.Validator var cState *state.CheckState if len(req.Fields) == 0 { - response.Size = fmt.Sprintf("%d", len(s.cdc.MustMarshalBinaryLengthPrefixed(block))) + response.Size = uint64(len(s.cdc.MustMarshalBinaryLengthPrefixed(block))) response.BlockReward = rewards.GetRewardForBlock(uint64(height)).String() if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { @@ -111,7 +111,7 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes } switch field { case pb.BlockRequest_size: - response.Size = fmt.Sprintf("%d", len(s.cdc.MustMarshalBinaryLengthPrefixed(block))) + response.Size = uint64(len(s.cdc.MustMarshalBinaryLengthPrefixed(block))) case pb.BlockRequest_block_reward: response.BlockReward = rewards.GetRewardForBlock(uint64(height)).String() case pb.BlockRequest_transactions, pb.BlockRequest_missed: @@ -163,7 +163,7 @@ func blockEvidence(block *core_types.ResultBlock) *pb.BlockResponse_Evidence { evidences := make([]*pb.BlockResponse_Evidence_Evidence, 0, len(block.Block.Evidence.Evidence)) for _, evidence := range block.Block.Evidence.Evidence { evidences = append(evidences, &pb.BlockResponse_Evidence_Evidence{ - Height: fmt.Sprintf("%d", evidence.Height()), + Height: uint64(evidence.Height()), Time: evidence.Time().Format(time.RFC3339Nano), Address: fmt.Sprintf("%s", evidence.Address()), Hash: fmt.Sprintf("%s", evidence.Hash()), @@ -233,17 +233,20 @@ func (s *Service) blockTransaction(block *core_types.ResultBlock, blockResults * Hash: strings.Title(fmt.Sprintf("Mt%x", rawTx.Hash())), RawTx: fmt.Sprintf("%x", []byte(rawTx)), From: sender.String(), - Nonce: fmt.Sprintf("%d", tx.Nonce), - GasPrice: fmt.Sprintf("%d", tx.GasPrice), - Type: fmt.Sprintf("%d", tx.Type), + Nonce: uint64(tx.Nonce), + GasPrice: uint64(tx.GasPrice), + Type: uint64(tx.Type), Data: data, Payload: tx.Payload, ServiceData: tx.ServiceData, - Gas: fmt.Sprintf("%d", tx.Gas()), - GasCoin: tx.GasCoin.String(), - Tags: tags, - Code: fmt.Sprintf("%d", blockResults.TxsResults[i].Code), - Log: blockResults.TxsResults[i].Log, + Gas: uint64(tx.Gas()), + GasCoin: &pb.Coin{ + Id: uint64(tx.Gas()), + Symbol: coins.GetCoin(types.CoinID(tx.Gas())).GetFullSymbol(), + }, + Tags: tags, + Code: uint64(blockResults.TxsResults[i].Code), + Log: blockResults.TxsResults[i].Log, }) } return txs, nil diff --git a/api/v2/service/candidate.go b/api/v2/service/candidate.go index fcb01f04e..3ef961ba0 100644 --- a/api/v2/service/candidate.go +++ b/api/v2/service/candidate.go @@ -3,7 +3,6 @@ package service import ( "context" "encoding/hex" - "fmt" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/state/candidates" "github.com/MinterTeam/minter-go-node/core/types" @@ -56,8 +55,8 @@ func makeResponseCandidate(state *state.CheckState, c *candidates.Candidate, inc ControlAddress: c.ControlAddress.String(), TotalStake: state.Candidates().GetTotalStake(c.PubKey).String(), PublicKey: c.PubKey.String(), - Commission: fmt.Sprintf("%d", c.Commission), - Status: fmt.Sprintf("%d", c.Status), + Commission: uint64(c.Commission), + Status: uint64(c.Status), } if includeStakes { @@ -65,13 +64,13 @@ func makeResponseCandidate(state *state.CheckState, c *candidates.Candidate, inc minStake := big.NewInt(0) stakes := state.Candidates().GetStakes(c.PubKey) usedSlots := len(stakes) - candidate.UsedSlots = fmt.Sprintf("%d", usedSlots) + candidate.UsedSlots = uint64(usedSlots) candidate.Stakes = make([]*pb.CandidateResponse_Stake, 0, usedSlots) for i, stake := range stakes { candidate.Stakes = append(candidate.Stakes, &pb.CandidateResponse_Stake{ Owner: stake.Owner.String(), Coin: &pb.Coin{ - Id: stake.Coin.String(), + Id: uint64(stake.Coin), Symbol: state.Coins().GetCoin(stake.Coin).Symbol().String(), }, Value: stake.Value.String(), @@ -85,7 +84,7 @@ func makeResponseCandidate(state *state.CheckState, c *candidates.Candidate, inc minStake = stake.BipValue } } - candidate.UniqUsers = fmt.Sprintf("%d", len(addresses)) + candidate.UniqUsers = uint64(len(addresses)) candidate.MinStake = minStake.String() } diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index c27158c55..0954ac851 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -2,7 +2,6 @@ package service import ( "context" - "fmt" "strconv" "github.com/MinterTeam/minter-go-node/core/code" @@ -42,11 +41,11 @@ func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.Co } return &pb.CoinInfoResponse{ - Id: coin.ID().String(), + Id: uint64(coin.ID()), Name: coin.Name(), Symbol: coin.GetFullSymbol(), Volume: coin.Volume().String(), - Crr: fmt.Sprintf("%d", coin.Crr()), + Crr: uint64(coin.Crr()), ReserveBalance: coin.Reserve().String(), MaxSupply: coin.MaxSupply().String(), OwnerAddress: ownerAddress, @@ -81,11 +80,11 @@ func (s *Service) CoinInfoById(ctx context.Context, req *pb.CoinIdRequest) (*pb. } return &pb.CoinInfoResponse{ - Id: coin.ID().String(), + Id: uint64(coin.ID()), Name: coin.Name(), Symbol: coin.GetFullSymbol(), Volume: coin.Volume().String(), - Crr: fmt.Sprintf("%d", coin.Crr()), + Crr: uint64(coin.Crr()), ReserveBalance: coin.Reserve().String(), MaxSupply: coin.MaxSupply().String(), OwnerAddress: ownerAddress, diff --git a/api/v2/service/data_encoder.go b/api/v2/service/data_encoder.go index eff64c4e0..efc6f20d8 100644 --- a/api/v2/service/data_encoder.go +++ b/api/v2/service/data_encoder.go @@ -18,12 +18,12 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { case *transaction.BuyCoinData: m = &pb.BuyCoinData{ CoinToBuy: &pb.Coin{ - Id: d.CoinToBuy.String(), + Id: uint64(d.CoinToBuy), Symbol: coins.GetCoin(d.CoinToBuy).Symbol().String(), }, ValueToBuy: d.ValueToBuy.String(), CoinToSell: &pb.Coin{ - Id: d.CoinToSell.String(), + Id: uint64(d.CoinToSell), Symbol: coins.GetCoin(d.CoinToSell).Symbol().String(), }, MaximumValueToSell: d.MaximumValueToSell.String(), @@ -39,20 +39,20 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { Symbol: d.Symbol.String(), InitialAmount: d.InitialAmount.String(), InitialReserve: d.InitialReserve.String(), - ConstantReserveRatio: strconv.Itoa(int(d.ConstantReserveRatio)), + ConstantReserveRatio: uint64(d.ConstantReserveRatio), MaxSupply: d.MaxSupply.String(), } case *transaction.CreateMultisigData: - weights := make([]string, 0, len(d.Weights)) + weights := make([]uint64, 0, len(d.Weights)) for _, weight := range d.Weights { - weights = append(weights, strconv.Itoa(int(weight))) + weights = append(weights, uint64(weight)) } addresses := make([]string, 0, len(d.Addresses)) for _, address := range d.Addresses { addresses = append(addresses, address.String()) } m = &pb.CreateMultisigData{ - Threshold: strconv.Itoa(int(d.Threshold)), + Threshold: uint64(d.Threshold), Weights: weights, Addresses: addresses, } @@ -60,9 +60,9 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { m = &pb.DeclareCandidacyData{ Address: d.Address.String(), PubKey: d.PubKey.String(), - Commission: strconv.Itoa(int(d.Commission)), + Commission: uint64(d.Commission), Coin: &pb.Coin{ - Id: d.Coin.String(), + Id: uint64(d.Coin), Symbol: coins.GetCoin(d.Coin).Symbol().String(), }, Stake: d.Stake.String(), @@ -71,7 +71,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { m = &pb.DelegateData{ PubKey: d.PubKey.String(), Coin: &pb.Coin{ - Id: d.Coin.String(), + Id: uint64(d.Coin), Symbol: coins.GetCoin(d.Coin).Symbol().String(), }, Value: d.Value.String(), @@ -89,16 +89,16 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { NewPubKey: d.NewPubKey.String(), } case *transaction.EditMultisigData: - weights := make([]string, 0, len(d.Weights)) + weights := make([]uint64, 0, len(d.Weights)) for _, weight := range d.Weights { - weights = append(weights, strconv.Itoa(int(weight))) + weights = append(weights, uint64(weight)) } addresses := make([]string, 0, len(d.Addresses)) for _, address := range d.Addresses { addresses = append(addresses, address.String()) } m = &pb.EditMultisigData{ - Threshold: strconv.Itoa(int(d.Threshold)), + Threshold: uint64(d.Threshold), Weights: weights, Addresses: addresses, } @@ -107,7 +107,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { for _, item := range d.List { list = append(list, &pb.SendData{ Coin: &pb.Coin{ - Id: item.Coin.String(), + Id: uint64(item.Coin), Symbol: coins.GetCoin(item.Coin).Symbol().String(), }, To: item.To.String(), @@ -127,7 +127,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { Symbol: d.Symbol.String(), InitialAmount: d.InitialAmount.String(), InitialReserve: d.InitialReserve.String(), - ConstantReserveRatio: strconv.Itoa(int(d.ConstantReserveRatio)), + ConstantReserveRatio: uint64(d.ConstantReserveRatio), MaxSupply: d.MaxSupply.String(), } case *transaction.RedeemCheckData: @@ -138,11 +138,11 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { case *transaction.SellAllCoinData: m = &pb.SellAllCoinData{ CoinToSell: &pb.Coin{ - Id: d.CoinToSell.String(), + Id: uint64(d.CoinToSell), Symbol: coins.GetCoin(d.CoinToSell).Symbol().String(), }, CoinToBuy: &pb.Coin{ - Id: d.CoinToBuy.String(), + Id: uint64(d.CoinToBuy), Symbol: coins.GetCoin(d.CoinToBuy).Symbol().String(), }, MinimumValueToBuy: d.MinimumValueToBuy.String(), @@ -150,12 +150,12 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { case *transaction.SellCoinData: m = &pb.SellCoinData{ CoinToSell: &pb.Coin{ - Id: d.CoinToSell.String(), + Id: uint64(d.CoinToSell), Symbol: coins.GetCoin(d.CoinToSell).Symbol().String(), }, ValueToSell: d.ValueToSell.String(), CoinToBuy: &pb.Coin{ - Id: d.CoinToBuy.String(), + Id: uint64(d.CoinToBuy), Symbol: coins.GetCoin(d.CoinToBuy).Symbol().String(), }, MinimumValueToBuy: d.MinimumValueToBuy.String(), @@ -163,7 +163,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { case *transaction.SendData: m = &pb.SendData{ Coin: &pb.Coin{ - Id: d.Coin.String(), + Id: uint64(d.Coin), Symbol: coins.GetCoin(d.Coin).Symbol().String(), }, To: d.To.String(), @@ -172,7 +172,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { case *transaction.SetHaltBlockData: m = &pb.SetHaltBlockData{ PubKey: d.PubKey.String(), - Height: strconv.Itoa(int(d.Height)), + Height: uint64(d.Height), } case *transaction.SetCandidateOnData: m = &pb.SetCandidateOnData{ @@ -186,7 +186,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { m = &pb.UnbondData{ PubKey: d.PubKey.String(), Coin: &pb.Coin{ - Id: d.Coin.String(), + Id: uint64(d.Coin), Symbol: coins.GetCoin(d.Coin).Symbol().String(), }, Value: d.Value.String(), diff --git a/api/v2/service/frozen.go b/api/v2/service/frozen.go index a566e4dc1..cf6eaadf2 100644 --- a/api/v2/service/frozen.go +++ b/api/v2/service/frozen.go @@ -2,7 +2,6 @@ package service import ( "context" - "fmt" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/state/candidates" "github.com/MinterTeam/minter-go-node/core/state/coins" @@ -61,11 +60,11 @@ func (s *Service) Frozen(ctx context.Context, req *pb.FrozenRequest) (*pb.Frozen } } frozen = append(frozen, &pb.FrozenResponse_Frozen{ - Height: fmt.Sprintf("%d", funds.Height()), + Height: funds.Height(), Address: fund.Address.String(), CandidateKey: fund.CandidateKey.String(), Coin: &pb.Coin{ - Id: fund.Coin.String(), + Id: uint64(fund.Coin), Symbol: coin.GetFullSymbol(), }, Value: fund.Value.String(), diff --git a/api/v2/service/gas.go b/api/v2/service/gas.go index e93b5196d..46d6b8325 100644 --- a/api/v2/service/gas.go +++ b/api/v2/service/gas.go @@ -2,7 +2,6 @@ package service import ( "context" - "fmt" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "github.com/golang/protobuf/ptypes/empty" "google.golang.org/grpc/codes" @@ -12,18 +11,18 @@ import ( // MinGasPrice returns current min gas price. func (s *Service) MinGasPrice(context.Context, *empty.Empty) (*pb.MinGasPriceResponse, error) { return &pb.MinGasPriceResponse{ - MinGasPrice: fmt.Sprintf("%d", s.blockchain.MinGasPrice()), + MinGasPrice: uint64(s.blockchain.MinGasPrice()), }, nil } // MaxGas returns current max gas. -func (s *Service) MaxGas(ctx context.Context, req *pb.MaxGasRequest) (*pb.MaxGasResponse, error) { +func (s *Service) MaxGasPrice(ctx context.Context, req *pb.MaxGasPriceRequest) (*pb.MaxGasPriceResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { - return new(pb.MaxGasResponse), status.Error(codes.NotFound, err.Error()) + return new(pb.MaxGasPriceResponse), status.Error(codes.NotFound, err.Error()) } - return &pb.MaxGasResponse{ - MaxGas: fmt.Sprintf("%d", cState.App().GetMaxGas()), + return &pb.MaxGasPriceResponse{ + MaxGasPrice: cState.App().GetMaxGas(), }, nil } diff --git a/api/v2/service/genesis.go b/api/v2/service/genesis.go index 7fab9fad7..5e32b1103 100644 --- a/api/v2/service/genesis.go +++ b/api/v2/service/genesis.go @@ -2,7 +2,7 @@ package service import ( "context" - "fmt" + "encoding/json" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "github.com/golang/protobuf/ptypes/empty" "google.golang.org/grpc/codes" @@ -21,7 +21,8 @@ func (s *Service) Genesis(ctx context.Context, _ *empty.Empty) (*pb.GenesisRespo return new(pb.GenesisResponse), timeoutStatus.Err() } - appState, err := encodeToStruct(result.Genesis.AppState) + var appState pb.GenesisResponse_AppState + err = json.Unmarshal(result.Genesis.AppState, &appState) if err != nil { return new(pb.GenesisResponse), status.Error(codes.Internal, err.Error()) } @@ -35,19 +36,19 @@ func (s *Service) Genesis(ctx context.Context, _ *empty.Empty) (*pb.GenesisRespo ChainId: result.Genesis.ChainID, ConsensusParams: &pb.GenesisResponse_ConsensusParams{ Block: &pb.GenesisResponse_ConsensusParams_Block{ - MaxBytes: fmt.Sprintf("%d", result.Genesis.ConsensusParams.Block.MaxBytes), - MaxGas: fmt.Sprintf("%d", result.Genesis.ConsensusParams.Block.MaxGas), - TimeIotaMs: fmt.Sprintf("%d", result.Genesis.ConsensusParams.Block.TimeIotaMs), + MaxBytes: result.Genesis.ConsensusParams.Block.MaxBytes, + MaxGas: result.Genesis.ConsensusParams.Block.MaxGas, + TimeIotaMs: result.Genesis.ConsensusParams.Block.TimeIotaMs, }, Evidence: &pb.GenesisResponse_ConsensusParams_Evidence{ - MaxAgeNumBlocks: fmt.Sprintf("%d", result.Genesis.ConsensusParams.Evidence.MaxAgeNumBlocks), - MaxAgeDuration: fmt.Sprintf("%d", result.Genesis.ConsensusParams.Evidence.MaxAgeDuration), + MaxAgeNumBlocks: result.Genesis.ConsensusParams.Evidence.MaxAgeNumBlocks, + MaxAgeDuration: int64(result.Genesis.ConsensusParams.Evidence.MaxAgeDuration), }, Validator: &pb.GenesisResponse_ConsensusParams_Validator{ PubKeyTypes: result.Genesis.ConsensusParams.Validator.PubKeyTypes, }, }, AppHash: result.Genesis.AppHash.String(), - AppState: appState, + AppState: &appState, // todo }, nil } diff --git a/api/v2/service/halts.go b/api/v2/service/halts.go index 7045ac916..6ea9b93a7 100644 --- a/api/v2/service/halts.go +++ b/api/v2/service/halts.go @@ -26,6 +26,6 @@ func (s *Service) Halts(_ context.Context, req *pb.HaltsRequest) (*pb.HaltsRespo } return &pb.HaltsResponse{ - Votes: votes, + PublicKeys: votes, }, nil } diff --git a/api/v2/service/missed_blocks.go b/api/v2/service/missed_blocks.go index 505ea240f..a7e52988c 100644 --- a/api/v2/service/missed_blocks.go +++ b/api/v2/service/missed_blocks.go @@ -2,7 +2,6 @@ package service import ( "context" - "fmt" "github.com/MinterTeam/minter-go-node/core/types" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" @@ -37,6 +36,6 @@ func (s *Service) MissedBlocks(ctx context.Context, req *pb.MissedBlocksRequest) return &pb.MissedBlocksResponse{ MissedBlocks: val.AbsentTimes.String(), - MissedBlocksCount: fmt.Sprintf("%d", val.CountAbsentTimes()), + MissedBlocksCount: int64(val.CountAbsentTimes()), }, nil } diff --git a/api/v2/service/net_info.go b/api/v2/service/net_info.go index d46316c2f..122a2d2c3 100644 --- a/api/v2/service/net_info.go +++ b/api/v2/service/net_info.go @@ -2,7 +2,6 @@ package service import ( "context" - "fmt" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "github.com/golang/protobuf/ptypes/empty" "github.com/golang/protobuf/ptypes/wrappers" @@ -24,10 +23,10 @@ func (s *Service) NetInfo(ctx context.Context, _ *empty.Empty) (*pb.NetInfoRespo var peers []*pb.NetInfoResponse_Peer for _, peer := range result.Peers { - var currentHeight *wrappers.StringValue + var currentHeight *wrappers.UInt64Value peerHeight := peerHeight(s.tmNode.Switch(), peer.NodeInfo.ID()) if peerHeight != 0 { - currentHeight = &wrappers.StringValue{Value: fmt.Sprintf("%d", peerHeight)} + currentHeight = &wrappers.UInt64Value{Value: uint64(peerHeight)} } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { @@ -37,11 +36,11 @@ func (s *Service) NetInfo(ctx context.Context, _ *empty.Empty) (*pb.NetInfoRespo var channels []*pb.NetInfoResponse_Peer_ConnectionStatus_Channel for _, channel := range peer.ConnectionStatus.Channels { channels = append(channels, &pb.NetInfoResponse_Peer_ConnectionStatus_Channel{ - Id: fmt.Sprintf("%d", channel.ID), - SendQueueCapacity: fmt.Sprintf("%d", channel.SendQueueCapacity), - SendQueueSize: fmt.Sprintf("%d", channel.SendQueueSize), - Priority: fmt.Sprintf("%d", channel.Priority), - RecentlySent: fmt.Sprintf("%d", channel.RecentlySent), + Id: int64(channel.ID), + SendQueueCapacity: int64(channel.SendQueueCapacity), + SendQueueSize: int64(channel.SendQueueSize), + Priority: int64(channel.Priority), + RecentlySent: channel.RecentlySent, }) } @@ -49,9 +48,9 @@ func (s *Service) NetInfo(ctx context.Context, _ *empty.Empty) (*pb.NetInfoRespo LatestBlockHeight: currentHeight, NodeInfo: &pb.NodeInfo{ ProtocolVersion: &pb.NodeInfo_ProtocolVersion{ - P2P: fmt.Sprintf("%d", peer.NodeInfo.ProtocolVersion.P2P), - Block: fmt.Sprintf("%d", peer.NodeInfo.ProtocolVersion.Block), - App: fmt.Sprintf("%d", peer.NodeInfo.ProtocolVersion.App), + P2P: uint64(peer.NodeInfo.ProtocolVersion.P2P), + Block: uint64(peer.NodeInfo.ProtocolVersion.Block), + App: uint64(peer.NodeInfo.ProtocolVersion.App), }, Id: string(peer.NodeInfo.ID()), ListenAddr: peer.NodeInfo.ListenAddr, @@ -66,24 +65,38 @@ func (s *Service) NetInfo(ctx context.Context, _ *empty.Empty) (*pb.NetInfoRespo }, IsOutbound: peer.IsOutbound, ConnectionStatus: &pb.NetInfoResponse_Peer_ConnectionStatus{ - Duration: fmt.Sprintf("%d", peer.ConnectionStatus.Duration), + Duration: uint64(peer.ConnectionStatus.Duration), SendMonitor: &pb.NetInfoResponse_Peer_ConnectionStatus_Monitor{ - Active: false, + Active: peer.ConnectionStatus.SendMonitor.Active, Start: peer.ConnectionStatus.SendMonitor.Start.Format(time.RFC3339Nano), - Duration: fmt.Sprintf("%d", peer.ConnectionStatus.SendMonitor.Duration.Nanoseconds()), - Idle: fmt.Sprintf("%d", peer.ConnectionStatus.SendMonitor.Idle.Nanoseconds()), - Bytes: fmt.Sprintf("%d", peer.ConnectionStatus.SendMonitor.Bytes), - Samples: fmt.Sprintf("%d", peer.ConnectionStatus.SendMonitor.Samples), - InstRate: fmt.Sprintf("%d", peer.ConnectionStatus.SendMonitor.InstRate), - CurRate: fmt.Sprintf("%d", peer.ConnectionStatus.SendMonitor.CurRate), - AvgRate: fmt.Sprintf("%d", peer.ConnectionStatus.SendMonitor.AvgRate), - PeakRate: fmt.Sprintf("%d", peer.ConnectionStatus.SendMonitor.PeakRate), - BytesRem: fmt.Sprintf("%d", peer.ConnectionStatus.SendMonitor.BytesRem), - TimeRem: fmt.Sprintf("%d", peer.ConnectionStatus.SendMonitor.TimeRem.Nanoseconds()), - Progress: fmt.Sprintf("%d", peer.ConnectionStatus.SendMonitor.Progress), + Duration: peer.ConnectionStatus.SendMonitor.Duration.Nanoseconds(), + Idle: peer.ConnectionStatus.SendMonitor.Idle.Nanoseconds(), + Bytes: peer.ConnectionStatus.SendMonitor.Bytes, + Samples: peer.ConnectionStatus.SendMonitor.Samples, + InstRate: peer.ConnectionStatus.SendMonitor.InstRate, + CurRate: peer.ConnectionStatus.SendMonitor.CurRate, + AvgRate: peer.ConnectionStatus.SendMonitor.AvgRate, + PeakRate: peer.ConnectionStatus.SendMonitor.PeakRate, + BytesRem: peer.ConnectionStatus.SendMonitor.BytesRem, + TimeRem: peer.ConnectionStatus.SendMonitor.TimeRem.Nanoseconds(), + Progress: uint64(peer.ConnectionStatus.SendMonitor.Progress), }, - RecvMonitor: nil, - Channels: channels, + RecvMonitor: &pb.NetInfoResponse_Peer_ConnectionStatus_Monitor{ + Active: peer.ConnectionStatus.RecvMonitor.Active, + Start: peer.ConnectionStatus.RecvMonitor.Start.Format(time.RFC3339Nano), + Duration: peer.ConnectionStatus.RecvMonitor.Duration.Nanoseconds(), + Idle: peer.ConnectionStatus.RecvMonitor.Idle.Nanoseconds(), + Bytes: peer.ConnectionStatus.RecvMonitor.Bytes, + Samples: peer.ConnectionStatus.RecvMonitor.Samples, + InstRate: peer.ConnectionStatus.RecvMonitor.InstRate, + CurRate: peer.ConnectionStatus.RecvMonitor.CurRate, + AvgRate: peer.ConnectionStatus.RecvMonitor.AvgRate, + PeakRate: peer.ConnectionStatus.RecvMonitor.PeakRate, + BytesRem: peer.ConnectionStatus.RecvMonitor.BytesRem, + TimeRem: peer.ConnectionStatus.RecvMonitor.TimeRem.Nanoseconds(), + Progress: uint64(peer.ConnectionStatus.RecvMonitor.Progress), + }, + Channels: channels, }, RemoteIp: peer.RemoteIP, }) @@ -92,7 +105,7 @@ func (s *Service) NetInfo(ctx context.Context, _ *empty.Empty) (*pb.NetInfoRespo return &pb.NetInfoResponse{ Listening: result.Listening, Listeners: result.Listeners, - CountPeers: fmt.Sprintf("%d", result.NPeers), + CountPeers: int64(result.NPeers), Peers: peers, }, nil } diff --git a/api/v2/service/send_transaction.go b/api/v2/service/send_transaction.go index 304259933..1c86a69fc 100644 --- a/api/v2/service/send_transaction.go +++ b/api/v2/service/send_transaction.go @@ -3,7 +3,6 @@ package service import ( "context" "encoding/hex" - "fmt" "github.com/MinterTeam/minter-go-node/core/code" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" abci "github.com/tendermint/tendermint/abci/types" @@ -33,7 +32,7 @@ func (s *Service) SendTransaction(ctx context.Context, req *pb.SendTransactionRe switch result.Code { case code.OK: return &pb.SendTransactionResponse{ - Code: fmt.Sprintf("%d", result.Code), + Code: uint64(result.Code), Log: result.Log, Hash: "Mt" + strings.ToLower(result.Hash.String()), }, nil diff --git a/api/v2/service/status.go b/api/v2/service/status.go index 6e47691f1..bab346c13 100644 --- a/api/v2/service/status.go +++ b/api/v2/service/status.go @@ -25,9 +25,9 @@ func (s *Service) Status(context.Context, *empty.Empty) (*pb.StatusResponse, err Version: s.version, LatestBlockHash: fmt.Sprintf("%X", result.SyncInfo.LatestBlockHash), LatestAppHash: fmt.Sprintf("%X", result.SyncInfo.LatestAppHash), - LatestBlockHeight: fmt.Sprintf("%d", result.SyncInfo.LatestBlockHeight), + LatestBlockHeight: uint64(result.SyncInfo.LatestBlockHeight), LatestBlockTime: result.SyncInfo.LatestBlockTime.Format(time.RFC3339Nano), - KeepLastStates: fmt.Sprintf("%d", s.minterCfg.BaseConfig.KeepLastStates), + KeepLastStates: uint64(s.minterCfg.BaseConfig.KeepLastStates), TotalSlashed: cState.App().GetTotalSlashed().String(), CatchingUp: result.SyncInfo.CatchingUp, PublicKey: fmt.Sprintf("Mp%x", result.ValidatorInfo.PubKey.Bytes()[5:]), diff --git a/api/v2/service/transaction.go b/api/v2/service/transaction.go index 1fd5a9ef2..3f8a6f33b 100644 --- a/api/v2/service/transaction.go +++ b/api/v2/service/transaction.go @@ -53,18 +53,21 @@ func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) ( return &pb.TransactionResponse{ Hash: "Mt" + strings.ToLower(hex.EncodeToString(tx.Tx.Hash())), RawTx: fmt.Sprintf("%x", []byte(tx.Tx)), - Height: fmt.Sprintf("%d", tx.Height), - Index: fmt.Sprintf("%d", tx.Index), + Height: uint64(tx.Height), + Index: uint64(tx.Index), From: sender.String(), - Nonce: fmt.Sprintf("%d", decodedTx.Nonce), - GasPrice: fmt.Sprintf("%d", decodedTx.GasPrice), - GasCoin: decodedTx.GasCoin.String(), - Gas: fmt.Sprintf("%d", decodedTx.Gas()), - Type: fmt.Sprintf("%d", uint8(decodedTx.Type)), - Data: dataStruct, - Payload: decodedTx.Payload, - Tags: tags, - Code: fmt.Sprintf("%d", tx.TxResult.Code), - Log: tx.TxResult.Log, + Nonce: decodedTx.Nonce, + GasPrice: uint64(decodedTx.GasPrice), + GasCoin: &pb.Coin{ + Id: uint64(decodedTx.GasCoin), + Symbol: cState.Coins().GetCoin(decodedTx.GasCoin).GetFullSymbol(), + }, + Gas: uint64(decodedTx.Gas()), + Type: uint64(decodedTx.Type), + Data: dataStruct, + Payload: decodedTx.Payload, + Tags: tags, + Code: uint64(tx.TxResult.Code), + Log: tx.TxResult.Log, }, nil } diff --git a/api/v2/service/transactions.go b/api/v2/service/transactions.go index 85310b306..0ff014eb8 100644 --- a/api/v2/service/transactions.go +++ b/api/v2/service/transactions.go @@ -57,19 +57,22 @@ func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) result = append(result, &pb.TransactionResponse{ Hash: "Mt" + strings.ToLower(hex.EncodeToString(tx.Tx.Hash())), RawTx: fmt.Sprintf("%x", []byte(tx.Tx)), - Height: fmt.Sprintf("%d", tx.Height), - Index: fmt.Sprintf("%d", tx.Index), + Height: uint64(tx.Height), + Index: uint64(tx.Index), From: sender.String(), - Nonce: fmt.Sprintf("%d", decodedTx.Nonce), - GasPrice: fmt.Sprintf("%d", decodedTx.GasPrice), - GasCoin: decodedTx.GasCoin.String(), - Gas: fmt.Sprintf("%d", decodedTx.Gas()), - Type: fmt.Sprintf("%d", uint8(decodedTx.Type)), - Data: data, - Payload: decodedTx.Payload, - Tags: tags, - Code: fmt.Sprintf("%d", tx.TxResult.Code), - Log: tx.TxResult.Log, + Nonce: uint64(decodedTx.Nonce), + GasPrice: uint64(decodedTx.GasPrice), + GasCoin: &pb.Coin{ + Id: uint64(decodedTx.GasCoin), + Symbol: cState.Coins().GetCoin(decodedTx.GasCoin).GetFullSymbol(), + }, + Gas: uint64(decodedTx.Gas()), + Type: uint64(uint8(decodedTx.Type)), + Data: data, + Payload: decodedTx.Payload, + Tags: tags, + Code: uint64(tx.TxResult.Code), + Log: tx.TxResult.Log, }) } } diff --git a/api/v2/service/unconfirmed_txs.go b/api/v2/service/unconfirmed_txs.go index a0e37d84c..bf7a97b62 100644 --- a/api/v2/service/unconfirmed_txs.go +++ b/api/v2/service/unconfirmed_txs.go @@ -2,7 +2,6 @@ package service import ( "context" - "fmt" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -14,9 +13,14 @@ func (s *Service) UnconfirmedTxs(ctx context.Context, req *pb.UnconfirmedTxsRequ if err != nil { return new(pb.UnconfirmedTxsResponse), status.Error(codes.Internal, err.Error()) } + transactions := make([]string, 0, len(txs.Txs)) + for _, tx := range txs.Txs { + transactions = append(transactions, tx.String()) + } return &pb.UnconfirmedTxsResponse{ - TransactionCount: fmt.Sprintf("%d", txs.Count), - TotalTransactions: fmt.Sprintf("%d", txs.Total), - TotalBytes: fmt.Sprintf("%d", txs.TotalBytes), + TransactionCount: uint64(txs.Count), + TotalTransactions: uint64(txs.Total), + TotalBytes: uint64(txs.TotalBytes), + Transactions: transactions, }, nil } diff --git a/api/v2/service/validators.go b/api/v2/service/validators.go index 619128aa5..a2a5a5eaf 100644 --- a/api/v2/service/validators.go +++ b/api/v2/service/validators.go @@ -2,7 +2,6 @@ package service import ( "context" - "fmt" "github.com/MinterTeam/minter-go-node/core/types" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" @@ -31,7 +30,7 @@ func (s *Service) Validators(ctx context.Context, req *pb.ValidatorsRequest) (*p copy(pk[:], val.PubKey.Bytes()[5:]) responseValidators = append(responseValidators, &pb.ValidatorsResponse_Result{ PublicKey: pk.String(), - VotingPower: fmt.Sprintf("%d", val.VotingPower), + VotingPower: uint64(val.VotingPower), }) } return &pb.ValidatorsResponse{Validators: responseValidators}, nil diff --git a/api/v2/service/waitlist.go b/api/v2/service/waitlist.go index 84a7e6a66..6de679740 100644 --- a/api/v2/service/waitlist.go +++ b/api/v2/service/waitlist.go @@ -51,7 +51,7 @@ func (s *Service) WaitList(ctx context.Context, req *pb.WaitListRequest) (*pb.Wa response.List = append(response.List, &pb.WaitListResponse_Wait{ Coin: &pb.Coin{ - Id: item.Coin.String(), + Id: uint64(item.Coin), Symbol: cState.Coins().GetCoin(item.Coin).CSymbol.String(), }, Value: item.Value.String(), diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index 3ad5fb7e3..dd46710d0 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -378,7 +378,7 @@ func (c *Coins) Export(state *types.AppState) { Crr: uint64(coin.Crr()), Reserve: coin.Reserve().String(), MaxSupply: coin.MaxSupply().String(), - Version: coin.Version(), + Version: uint64(coin.Version()), OwnerAddress: owner, }) } diff --git a/core/types/appstate.go b/core/types/appstate.go index a634a9e46..3c50250a7 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -244,15 +244,15 @@ type Waitlist struct { } type Coin struct { - ID uint64 `json:"id"` - Name string `json:"name"` - Symbol CoinSymbol `json:"symbol"` - Volume string `json:"volume"` - Crr uint64 `json:"crr"` - Reserve string `json:"reserve"` - MaxSupply string `json:"max_supply"` - Version CoinVersion `json:"version"` - OwnerAddress *Address `json:"owner_address"` + ID uint64 `json:"id"` + Name string `json:"name"` + Symbol CoinSymbol `json:"symbol"` + Volume string `json:"volume"` + Crr uint64 `json:"crr"` + Reserve string `json:"reserve"` + MaxSupply string `json:"max_supply"` + Version uint64 `json:"version"` + OwnerAddress *Address `json:"owner_address"` } type FrozenFund struct { diff --git a/go.mod b/go.mod index 1169f8d56..7519e93b7 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922114348-418a230208a8 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924164205-36a4cb92bbaf github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index a6c7efc71..254913801 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922114348-418a230208a8 h1:3C/50f/+Vhc+7/GlofHgsWYr8PmItWM1bTk3TlRnUPE= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200922114348-418a230208a8/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924164205-36a4cb92bbaf h1:Zl3caJN40aP5vWDRjGOibJwqdt1yKaZu2FDQZd2TaxA= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924164205-36a4cb92bbaf/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 41367ad4631233fb65cd6f9dc65b90d03d319533 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 24 Sep 2020 20:46:17 +0300 Subject: [PATCH 313/426] update api types --- api/v2/service/genesis.go | 6 +++--- cli/service/client.go | 13 +++++-------- go.mod | 2 +- go.sum | 8 ++++++-- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/api/v2/service/genesis.go b/api/v2/service/genesis.go index 5e32b1103..08fe0ff49 100644 --- a/api/v2/service/genesis.go +++ b/api/v2/service/genesis.go @@ -2,11 +2,11 @@ package service import ( "context" - "encoding/json" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "github.com/golang/protobuf/ptypes/empty" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/encoding/protojson" "time" ) @@ -22,7 +22,7 @@ func (s *Service) Genesis(ctx context.Context, _ *empty.Empty) (*pb.GenesisRespo } var appState pb.GenesisResponse_AppState - err = json.Unmarshal(result.Genesis.AppState, &appState) + err = protojson.Unmarshal(result.Genesis.AppState, &appState) if err != nil { return new(pb.GenesisResponse), status.Error(codes.Internal, err.Error()) } @@ -49,6 +49,6 @@ func (s *Service) Genesis(ctx context.Context, _ *empty.Empty) (*pb.GenesisRespo }, }, AppHash: result.Genesis.AppHash.String(), - AppState: &appState, // todo + AppState: &appState, }, nil } diff --git a/cli/service/client.go b/cli/service/client.go index d0ecdb317..66922e273 100644 --- a/cli/service/client.go +++ b/cli/service/client.go @@ -1,12 +1,10 @@ package service import ( - "bytes" "context" "fmt" pb "github.com/MinterTeam/minter-go-node/cli/cli_pb" "github.com/c-bata/go-prompt" - "github.com/golang/protobuf/jsonpb" "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/empty" @@ -14,6 +12,7 @@ import ( "github.com/marcusolsson/tui-go" "github.com/urfave/cli/v2" "google.golang.org/grpc" + "google.golang.org/protobuf/encoding/protojson" "io" "log" "os" @@ -342,12 +341,11 @@ func netInfoCMD(client pb.ManagerServiceClient) func(c *cli.Context) error { return err } if c.Bool("json") { - bb := new(bytes.Buffer) - err := (&jsonpb.Marshaler{EmitDefaults: true}).Marshal(bb, response) + bb, err := protojson.Marshal(response) if err != nil { return err } - fmt.Println(bb.String()) + fmt.Println(string(bb)) return nil } fmt.Println(proto.MarshalTextString(response)) @@ -362,12 +360,11 @@ func statusCMD(client pb.ManagerServiceClient) func(c *cli.Context) error { return err } if c.Bool("json") { - bb := new(bytes.Buffer) - err := (&jsonpb.Marshaler{EmitDefaults: true}).Marshal(bb, response) + bb, err := protojson.Marshal(response) if err != nil { return err } - fmt.Println(bb.String()) + fmt.Println(string(bb)) return nil } fmt.Println(proto.MarshalTextString(response)) diff --git a/go.mod b/go.mod index 7519e93b7..f37ef6c93 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924164205-36a4cb92bbaf + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924174250-5d401bed5a7f github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 254913801..dc4267a35 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,12 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924164205-36a4cb92bbaf h1:Zl3caJN40aP5vWDRjGOibJwqdt1yKaZu2FDQZd2TaxA= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924164205-36a4cb92bbaf/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924170413-14ef8e69c842 h1:NNBoiD379q55K/YSMqgjxfVeNmcMe+NAeEoaqcXqDdk= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924170413-14ef8e69c842/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924172357-3add24de9dae h1:fXjUIhBWzHXkLYXVpXuhJm70Hi5p/YhhJd9UPJD3KI0= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924172357-3add24de9dae/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924174250-5d401bed5a7f h1:Gn5HS6oW0ExOhUeQZPBGV8KEx4QM5uX6U0nBvZICvYM= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924174250-5d401bed5a7f/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 1479337f693b909c4089673d95d7cf5953389088 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 25 Sep 2020 01:01:04 +0300 Subject: [PATCH 314/426] update openapi --- go.mod | 2 +- go.sum | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index f37ef6c93..567ecb036 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924174250-5d401bed5a7f + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924215921-1e86f38ac67c github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index dc4267a35..6336bc108 100644 --- a/go.sum +++ b/go.sum @@ -7,12 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924170413-14ef8e69c842 h1:NNBoiD379q55K/YSMqgjxfVeNmcMe+NAeEoaqcXqDdk= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924170413-14ef8e69c842/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924172357-3add24de9dae h1:fXjUIhBWzHXkLYXVpXuhJm70Hi5p/YhhJd9UPJD3KI0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924172357-3add24de9dae/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924174250-5d401bed5a7f h1:Gn5HS6oW0ExOhUeQZPBGV8KEx4QM5uX6U0nBvZICvYM= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924174250-5d401bed5a7f/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924215921-1e86f38ac67c h1:90nbZ96AfzYL8lvHLSPob8zNRFEFOa8LWsJ//0Bcj/s= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924215921-1e86f38ac67c/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 09aaad4c6ba84608542558be121d30873bef2c4a Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 25 Sep 2020 03:52:47 +0300 Subject: [PATCH 315/426] fix v2 --- api/v2/service/block.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v2/service/block.go b/api/v2/service/block.go index 067d4b5b8..3e742f798 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -241,8 +241,8 @@ func (s *Service) blockTransaction(block *core_types.ResultBlock, blockResults * ServiceData: tx.ServiceData, Gas: uint64(tx.Gas()), GasCoin: &pb.Coin{ - Id: uint64(tx.Gas()), - Symbol: coins.GetCoin(types.CoinID(tx.Gas())).GetFullSymbol(), + Id: uint64(tx.GasCoin), + Symbol: coins.GetCoin(tx.GasCoin).GetFullSymbol(), }, Tags: tags, Code: uint64(blockResults.TxsResults[i].Code), From 725c49b5216c06cb0b3921147321fd8b1dfe32a0 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 25 Sep 2020 03:54:34 +0300 Subject: [PATCH 316/426] change url /waitlist/{address} --- api/v2/service/waitlist.go | 23 ++++++++++++++++------- go.mod | 2 +- go.sum | 2 ++ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/api/v2/service/waitlist.go b/api/v2/service/waitlist.go index 6de679740..bbcf91dba 100644 --- a/api/v2/service/waitlist.go +++ b/api/v2/service/waitlist.go @@ -3,6 +3,7 @@ package service import ( "context" "encoding/hex" + "github.com/MinterTeam/minter-go-node/core/state/waitlist" "github.com/MinterTeam/minter-go-node/core/types" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" @@ -23,12 +24,6 @@ func (s *Service) WaitList(ctx context.Context, req *pb.WaitListRequest) (*pb.Wa address := types.BytesToAddress(decodeString) - if !strings.HasPrefix(req.PublicKey, "Mp") { - return new(pb.WaitListResponse), status.Error(codes.InvalidArgument, "public key don't has prefix 'Mp'") - } - - publickKey := types.HexToPubkey(req.PublicKey) - cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.WaitListResponse), status.Error(codes.NotFound, err.Error()) @@ -42,7 +37,20 @@ func (s *Service) WaitList(ctx context.Context, req *pb.WaitListRequest) (*pb.Wa } response := new(pb.WaitListResponse) - items := cState.WaitList().GetByAddressAndPubKey(address, publickKey) + var items []waitlist.Item + publicKey := req.PublicKey + if publicKey != "" { + if !strings.HasPrefix(publicKey, "Mp") { + return new(pb.WaitListResponse), status.Error(codes.InvalidArgument, "public key don't has prefix 'Mp'") + } + items = cState.WaitList().GetByAddressAndPubKey(address, types.HexToPubkey(publicKey)) + } else { + model := cState.WaitList().GetByAddress(address) + if model == nil { + return response, nil + } + items = model.List + } response.List = make([]*pb.WaitListResponse_Wait, 0, len(items)) for _, item := range items { if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { @@ -50,6 +58,7 @@ func (s *Service) WaitList(ctx context.Context, req *pb.WaitListRequest) (*pb.Wa } response.List = append(response.List, &pb.WaitListResponse_Wait{ + PublicKey: cState.Candidates().PubKey(item.CandidateId).String(), Coin: &pb.Coin{ Id: uint64(item.Coin), Symbol: cState.Coins().GetCoin(item.Coin).CSymbol.String(), diff --git a/go.mod b/go.mod index 567ecb036..c5565a6ea 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924215921-1e86f38ac67c + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200925002945-15b5cde8e354 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 6336bc108..fadd8b7a3 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1: github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924215921-1e86f38ac67c h1:90nbZ96AfzYL8lvHLSPob8zNRFEFOa8LWsJ//0Bcj/s= github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924215921-1e86f38ac67c/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200925002945-15b5cde8e354 h1:HpjApkir3UtOL4WzGzkgQcdT9SyqwiZ/wbGrahzIlLQ= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200925002945-15b5cde8e354/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 81d8f5a935264192bde88149c61d4a0148869269 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 25 Sep 2020 03:55:01 +0300 Subject: [PATCH 317/426] fix error --- core/state/accounts/accounts_test.go | 24 +++++----- core/state/candidates/candidate_test.go | 48 ++++++++++---------- core/state/candidates/candidates.go | 1 + core/state/halts/halts_test.go | 4 +- core/state/state.go | 7 ++- core/state/validators/validators_test.go | 22 +++++----- core/state/waitlist/waitlist.go | 4 ++ core/state/waitlist/waitlist_test.go | 2 +- core/transaction/buy_coin_test.go | 1 - core/transaction/delegate_test.go | 56 +++++++++++++++++++++++- tree/tree.go | 12 ++--- 11 files changed, 121 insertions(+), 60 deletions(-) diff --git a/core/state/accounts/accounts_test.go b/core/state/accounts/accounts_test.go index 2deaeade5..eefcde863 100644 --- a/core/state/accounts/accounts_test.go +++ b/core/state/accounts/accounts_test.go @@ -15,7 +15,7 @@ import ( ) func TestAccounts_CreateMultisig(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) accounts, err := NewAccounts(b, mutableTree) @@ -52,7 +52,7 @@ func TestAccounts_CreateMultisig(t *testing.T) { } func TestAccounts_SetNonce(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) accounts, err := NewAccounts(b, mutableTree) @@ -66,7 +66,7 @@ func TestAccounts_SetNonce(t *testing.T) { } func TestAccounts_SetBalance(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) accounts, err := NewAccounts(b, mutableTree) @@ -84,7 +84,7 @@ func TestAccounts_SetBalance(t *testing.T) { } func TestAccounts_SetBalance_fromDB(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) accounts, err := NewAccounts(b, mutableTree) @@ -107,7 +107,7 @@ func TestAccounts_SetBalance_fromDB(t *testing.T) { } func TestAccounts_SetBalance_0(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) accounts, err := NewAccounts(b, mutableTree) @@ -130,7 +130,7 @@ func TestAccounts_SetBalance_0(t *testing.T) { } func TestAccounts_GetBalances(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) busCoins, err := coins.NewCoins(b, mutableTree) @@ -184,7 +184,7 @@ func TestAccounts_GetBalances(t *testing.T) { } func TestAccounts_ExistsMultisig(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) accounts, err := NewAccounts(b, mutableTree) @@ -217,7 +217,7 @@ func TestAccounts_ExistsMultisig(t *testing.T) { } func TestAccounts_AddBalance_bus(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) accounts, err := NewAccounts(b, mutableTree) @@ -234,7 +234,7 @@ func TestAccounts_AddBalance_bus(t *testing.T) { } func TestAccounts_SubBalance(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) accounts, err := NewAccounts(b, mutableTree) @@ -255,7 +255,7 @@ func TestAccounts_SubBalance(t *testing.T) { } func TestAccounts_EditMultisig(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) accounts, err := NewAccounts(b, mutableTree) @@ -293,7 +293,7 @@ func TestAccounts_EditMultisig(t *testing.T) { } func TestAccounts_Commit(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) accounts, err := NewAccounts(b, mutableTree) @@ -322,7 +322,7 @@ func TestAccounts_Commit(t *testing.T) { } func TestAccounts_Export(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() busCoins, err := coins.NewCoins(b, mutableTree) if err != nil { diff --git a/core/state/candidates/candidate_test.go b/core/state/candidates/candidate_test.go index ac471c1d1..70c61470d 100644 --- a/core/state/candidates/candidate_test.go +++ b/core/state/candidates/candidate_test.go @@ -20,7 +20,7 @@ import ( ) func TestCandidates_Create_oneCandidate(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) candidates, err := NewCandidates(bus.NewBus(), mutableTree) if err != nil { t.Fatal(err) @@ -44,7 +44,7 @@ func TestCandidates_Create_oneCandidate(t *testing.T) { } func TestCandidates_Commit_createThreeCandidates(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) candidates, err := NewCandidates(bus.NewBus(), mutableTree) if err != nil { t.Fatal(err) @@ -93,7 +93,7 @@ func TestCandidates_Commit_createThreeCandidates(t *testing.T) { } func TestCandidates_Commit_changePubKeyAndCheckBlockList(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) candidates, err := NewCandidates(bus.NewBus(), mutableTree) if err != nil { t.Fatal(err) @@ -161,7 +161,7 @@ func TestCandidates_Commit_changePubKeyAndCheckBlockList(t *testing.T) { } func TestCandidates_AddToBlockPubKey(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) candidates, err := NewCandidates(bus.NewBus(), mutableTree) if err != nil { t.Fatal(err) @@ -175,7 +175,7 @@ func TestCandidates_AddToBlockPubKey(t *testing.T) { } func TestCandidates_Commit_withStakeAndUpdate(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) candidates, err := NewCandidates(bus.NewBus(), mutableTree) if err != nil { t.Fatal(err) @@ -236,7 +236,7 @@ func TestCandidates_Commit_withStakeAndUpdate(t *testing.T) { } func TestCandidates_Commit_edit(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) candidates, err := NewCandidates(bus.NewBus(), mutableTree) if err != nil { t.Fatal(err) @@ -293,7 +293,7 @@ func TestCandidates_Commit_edit(t *testing.T) { } func TestCandidates_Commit_createOneCandidateWithID(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) candidates, err := NewCandidates(bus.NewBus(), mutableTree) if err != nil { t.Fatal(err) @@ -326,7 +326,7 @@ func TestCandidates_Commit_createOneCandidateWithID(t *testing.T) { } func TestCandidates_Commit_Delegate(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) candidates, err := NewCandidates(b, mutableTree) @@ -376,7 +376,7 @@ func TestCandidates_Commit_Delegate(t *testing.T) { } func TestCandidates_SetOnlineAndBusSetOffline(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) candidates, err := NewCandidates(b, mutableTree) @@ -407,7 +407,7 @@ func TestCandidates_SetOnlineAndBusSetOffline(t *testing.T) { } func TestCandidates_Count(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) candidates, err := NewCandidates(b, mutableTree) @@ -444,7 +444,7 @@ func TestCandidates_Count(t *testing.T) { } func TestCandidates_GetTotalStake_fromModelAndFromDB(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() wl, err := waitlist.NewWaitList(b, mutableTree) if err != nil { @@ -518,7 +518,7 @@ func TestCandidates_GetTotalStake_fromModelAndFromDB(t *testing.T) { func TestCandidates_GetTotalStake_forCustomCoins(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() wl, err := waitlist.NewWaitList(b, mutableTree) if err != nil { @@ -585,7 +585,7 @@ func TestCandidates_GetTotalStake_forCustomCoins(t *testing.T) { } func TestCandidates_Export(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) candidates, err := NewCandidates(bus.NewBus(), mutableTree) if err != nil { t.Fatal(err) @@ -637,7 +637,7 @@ func TestCandidates_Export(t *testing.T) { } func TestCandidates_busGetStakes(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) candidates, err := NewCandidates(bus.NewBus(), mutableTree) if err != nil { t.Fatal(err) @@ -676,7 +676,7 @@ func TestCandidates_busGetStakes(t *testing.T) { } func TestCandidates_GetCandidateByTendermintAddress(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) candidates, err := NewCandidates(bus.NewBus(), mutableTree) if err != nil { t.Fatal(err) @@ -695,7 +695,7 @@ func TestCandidates_GetCandidateByTendermintAddress(t *testing.T) { } } func TestCandidates_busGetCandidateByTendermintAddress(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) candidates, err := NewCandidates(bus.NewBus(), mutableTree) if err != nil { t.Fatal(err) @@ -715,7 +715,7 @@ func TestCandidates_busGetCandidateByTendermintAddress(t *testing.T) { } func TestCandidates_Punish(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() wl, err := waitlist.NewWaitList(b, mutableTree) if err != nil { @@ -803,7 +803,7 @@ func (fr *fr) AddFrozenFund(_ uint64, _ types.Address, _ types.Pubkey, _ types.C fr.unbounds = append(fr.unbounds, value) } func TestCandidates_PunishByzantineCandidate(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() frozenfunds := &fr{} b.SetFrozenFunds(frozenfunds) @@ -897,7 +897,7 @@ func TestCandidates_PunishByzantineCandidate(t *testing.T) { } func TestCandidates_SubStake(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) candidates, err := NewCandidates(b, mutableTree) @@ -931,7 +931,7 @@ func TestCandidates_SubStake(t *testing.T) { } func TestCandidates_IsNewCandidateStakeSufficient(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) candidates, err := NewCandidates(b, mutableTree) @@ -960,7 +960,7 @@ func TestCandidates_IsNewCandidateStakeSufficient(t *testing.T) { } func TestCandidates_IsDelegatorStakeSufficient(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() wl, err := waitlist.NewWaitList(b, mutableTree) if err != nil { @@ -1024,7 +1024,7 @@ func TestCandidates_IsDelegatorStakeSufficient(t *testing.T) { } } func TestCandidates_IsDelegatorStakeSufficient_false(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) candidates, err := NewCandidates(b, mutableTree) @@ -1054,7 +1054,7 @@ func TestCandidates_IsDelegatorStakeSufficient_false(t *testing.T) { } func TestCandidates_GetNewCandidates(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) candidates, err := NewCandidates(b, mutableTree) @@ -1097,7 +1097,7 @@ func TestCandidates_GetNewCandidates(t *testing.T) { } func TestCandidate_GetFilteredUpdates(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) candidates, err := NewCandidates(b, mutableTree) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 1434757d5..3cb45e8aa 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -45,6 +45,7 @@ type RCandidates interface { Export(state *types.AppState) Exists(pubkey types.Pubkey) bool IsBlockedPubKey(pubkey types.Pubkey) bool + PubKey(id uint32) types.Pubkey Count() int IsNewCandidateStakeSufficient(coin types.CoinID, stake *big.Int, limit int) bool IsDelegatorStakeSufficient(address types.Address, pubkey types.Pubkey, coin types.CoinID, amount *big.Int) bool diff --git a/core/state/halts/halts_test.go b/core/state/halts/halts_test.go index 1ef49dd0a..21f0e1394 100644 --- a/core/state/halts/halts_test.go +++ b/core/state/halts/halts_test.go @@ -9,7 +9,7 @@ import ( ) func TestHaltsToDeleteModel(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) h, err := NewHalts(bus.NewBus(), mutableTree) if err != nil { t.Fatal(err) @@ -47,7 +47,7 @@ func TestHaltsToDeleteModel(t *testing.T) { } func TestBusToAddHaltBlock(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) h, err := NewHalts(bus.NewBus(), mutableTree) if err != nil { t.Fatal(err) diff --git a/core/state/state.go b/core/state/state.go index 2e82836ee..c3cc9bdf3 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -168,7 +168,10 @@ type State struct { func (s *State) isValue_State() {} func NewState(height uint64, db db.DB, events eventsdb.IEventsDB, cacheSize int, keepLastStates int64) (*State, error) { - iavlTree := tree.NewMutableTree(height, db, cacheSize) + iavlTree, err := tree.NewMutableTree(height, db, cacheSize) + if err != nil { + return nil, err + } state, err := newStateForTree(iavlTree, events, db, keepLastStates) if err != nil { @@ -219,7 +222,7 @@ func (s *State) Check() error { } if delta.Cmp(volume) != 0 { - return fmt.Errorf("invariants error on coin %s: %s", coin.String(), big.NewInt(0).Sub(volumeDeltas[coin], delta).String()) + return fmt.Errorf("invariants error on coin %s: %s", coin.String(), big.NewInt(0).Sub(volume, delta).String()) } } diff --git a/core/state/validators/validators_test.go b/core/state/validators/validators_test.go index 2e00bfc3b..09e6327a5 100644 --- a/core/state/validators/validators_test.go +++ b/core/state/validators/validators_test.go @@ -19,7 +19,7 @@ import ( ) func TestValidators_GetValidators(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() validators, err := NewValidators(b, mutableTree) @@ -48,7 +48,7 @@ func TestValidators_GetValidators(t *testing.T) { } func TestValidators_GetByPublicKey(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() validators, err := NewValidators(b, mutableTree) @@ -70,7 +70,7 @@ func TestValidators_GetByPublicKey(t *testing.T) { } func TestValidators_GetByTmAddress(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() validators, err := NewValidators(b, mutableTree) @@ -94,7 +94,7 @@ func TestValidators_GetByTmAddress(t *testing.T) { } func TestValidators_PunishByzantineValidator(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() validators, err := NewValidators(b, mutableTree) @@ -116,7 +116,7 @@ func TestValidators_PunishByzantineValidator(t *testing.T) { } func TestValidators_LoadValidators(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) validators, err := NewValidators(b, mutableTree) @@ -169,7 +169,7 @@ func TestValidators_LoadValidators(t *testing.T) { } func TestValidators_SetValidators(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() validators, err := NewValidators(b, mutableTree) @@ -201,7 +201,7 @@ func TestValidators_SetValidators(t *testing.T) { } func TestValidators_PayRewards(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() accs, err := accounts.NewAccounts(b, mutableTree) if err != nil { @@ -269,7 +269,7 @@ func TestValidators_PayRewards(t *testing.T) { } func TestValidators_SetValidatorAbsent(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() accs, err := accounts.NewAccounts(b, mutableTree) if err != nil { @@ -327,7 +327,7 @@ func TestValidators_SetValidatorAbsent(t *testing.T) { } } func TestValidators_SetValidatorPresent(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() validators, err := NewValidators(b, mutableTree) @@ -356,7 +356,7 @@ func TestValidators_SetValidatorPresent(t *testing.T) { } func TestValidators_SetToDrop(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() validators, err := NewValidators(b, mutableTree) @@ -381,7 +381,7 @@ func TestValidators_SetToDrop(t *testing.T) { } func TestValidators_Export(t *testing.T) { - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() accs, err := accounts.NewAccounts(b, mutableTree) if err != nil { diff --git a/core/state/waitlist/waitlist.go b/core/state/waitlist/waitlist.go index 0c6b3193e..e5fd5f264 100644 --- a/core/state/waitlist/waitlist.go +++ b/core/state/waitlist/waitlist.go @@ -164,16 +164,20 @@ func (wl *WaitList) Delete(address types.Address, pubkey types.Pubkey, coin type log.Panicf("Candidate not found: %s", pubkey.String()) } + value := big.NewInt(0) items := make([]Item, 0, len(w.List)) for _, item := range w.List { if item.CandidateId != candidate.ID && item.Coin != coin { items = append(items, item) + } else { + value.Add(value, item.Value) } } w.List = items wl.markDirty(address) wl.setToMap(address, w) + wl.bus.Checker().AddCoinVolume(coin, value) } func (wl *WaitList) getOrNew(address types.Address) *Model { diff --git a/core/state/waitlist/waitlist_test.go b/core/state/waitlist/waitlist_test.go index 345dc899f..e5fa3c844 100644 --- a/core/state/waitlist/waitlist_test.go +++ b/core/state/waitlist/waitlist_test.go @@ -12,7 +12,7 @@ import ( func TestWaitListToGetByAddressAndPubKey(t *testing.T) { b := bus.NewBus() - mutableTree := tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) wl, err := NewWaitList(b, mutableTree) if err != nil { diff --git a/core/transaction/buy_coin_test.go b/core/transaction/buy_coin_test.go index b9eb9a205..55979b031 100644 --- a/core/transaction/buy_coin_test.go +++ b/core/transaction/buy_coin_test.go @@ -25,7 +25,6 @@ var ( func getState() *state.State { s, err := state.NewState(0, db.NewMemDB(), nil, 1, 1) - if err != nil { panic(err) } diff --git a/core/transaction/delegate_test.go b/core/transaction/delegate_test.go index b462514a4..881804a61 100644 --- a/core/transaction/delegate_test.go +++ b/core/transaction/delegate_test.go @@ -2,7 +2,6 @@ package transaction import ( "encoding/binary" - "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/core/types" @@ -493,3 +492,58 @@ func TestDelegateTxToGasCoinReserveUnderflow(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } } + +func TestDelegateData_addFromWaitlist(t *testing.T) { + cState := getState() + + pubkey := createTestCandidate(cState) + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + cState.Waitlist.AddWaitList(addr, pubkey, 0, big.NewInt(100)) + cState.Accounts.AddBalance(addr, 0, helpers.BipToPip(big.NewInt(1000000))) + cState.Checker.AddCoinVolume(0, helpers.BipToPip(big.NewInt(1000000))) + + value := big.NewInt(10000000000) + data := DelegateData{ + PubKey: pubkey, + Coin: 0, + Value: value, + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: 0, + Type: TypeDelegate, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + rewards := big.NewInt(0) + response := RunTx(cState, encodedTx, rewards, 0, &sync.Map{}, 0) + if response.Code != 0 { + t.Fatalf("Response code is not %d. Error %s", code.OK, response.Log) + } + cState.Checker.AddCoin(0, rewards) + + err = cState.Check() + if err != nil { + t.Fatal(err) + } +} diff --git a/tree/tree.go b/tree/tree.go index c5e1af1b0..82954ad33 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -34,25 +34,25 @@ type MTree interface { // NewMutableTree creates and returns new MutableTree using given db. Panics on error. // If you want to get read-only state, you should use height = 0 and LazyLoadVersion (version), see NewImmutableTree -func NewMutableTree(height uint64, db dbm.DB, cacheSize int) MTree { +func NewMutableTree(height uint64, db dbm.DB, cacheSize int) (MTree, error) { tree, err := iavl.NewMutableTree(db, cacheSize) if err != nil { - panic(err) + return nil, err } if height == 0 { return &mutableTree{ tree: tree, - } + }, nil } if _, err := tree.LoadVersionForOverwriting(int64(height)); err != nil { - panic(err) + return nil, err } return &mutableTree{ tree: tree, - } + }, nil } type mutableTree struct { @@ -212,7 +212,7 @@ type ImmutableTree struct { // NewImmutableTree returns MTree from given db at given height // Warning: returns the MTree interface, but you should only use ReadOnlyTree func NewImmutableTree(height uint64, db dbm.DB) (MTree, error) { - tree := NewMutableTree(0, db, 1024) + tree, _ := NewMutableTree(0, db, 1024) _, err := tree.LazyLoadVersion(int64(height)) if err != nil { return nil, err From 56a6db9e4e25f70ca84e51135876af3070a792fa Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 25 Sep 2020 15:20:39 +0300 Subject: [PATCH 318/426] CHANGELOG.md --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81fecd723..23d768990 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,12 @@ - [core] Added RecreateCoin tx - [core] Added ChangeCoinOwner tx - [core] Limit validators slots to 64 -- [core] Add EditMultisigOwnersData tx +- [core] Add EditMultisigData tx - [core] Add PriceVoteData tx - [core] Stake value calculation changes +- [console] Added PruneBlocks command +- [api] Marked as deprecated version of API v1 +- [api] Added Swagger UI for API v2 ## 1.1.8 From bd1ac797c9bd559e0d54eddfba81c5311ee456ba Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Fri, 25 Sep 2020 15:22:58 +0300 Subject: [PATCH 319/426] Fix tests --- core/state/frozenfunds/frozen_funds_test.go | 12 ++++++++---- go.sum | 2 -- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/core/state/frozenfunds/frozen_funds_test.go b/core/state/frozenfunds/frozen_funds_test.go index 5442fe58c..974bf7702 100644 --- a/core/state/frozenfunds/frozen_funds_test.go +++ b/core/state/frozenfunds/frozen_funds_test.go @@ -12,7 +12,9 @@ import ( ) func TestFrozenFundsToAddModel(t *testing.T) { - b, mutableTree := bus.NewBus(), tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) + ff, err := NewFrozenFunds(b, mutableTree) if err != nil { t.Fatal(err) @@ -58,7 +60,8 @@ func TestFrozenFundsToAddModel(t *testing.T) { } func TestFrozenFundsToDeleteModel(t *testing.T) { - b, mutableTree := bus.NewBus(), tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) ff, err := NewFrozenFunds(b, mutableTree) if err != nil { t.Fatal(err) @@ -104,8 +107,9 @@ func TestFrozenFundsToDeleteModel(t *testing.T) { } } -func TestFrozenFundsToDeleteNotExistenFund(t *testing.T) { - b, mutableTree := bus.NewBus(), tree.NewMutableTree(0, db.NewMemDB(), 1024) +func TestFrozenFundsToDeleteNotExistingFund(t *testing.T) { + b := bus.NewBus() + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) ff, err := NewFrozenFunds(b, mutableTree) if err != nil { t.Fatal(err) diff --git a/go.sum b/go.sum index fadd8b7a3..7265811eb 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924215921-1e86f38ac67c h1:90nbZ96AfzYL8lvHLSPob8zNRFEFOa8LWsJ//0Bcj/s= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200924215921-1e86f38ac67c/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200925002945-15b5cde8e354 h1:HpjApkir3UtOL4WzGzkgQcdT9SyqwiZ/wbGrahzIlLQ= github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200925002945-15b5cde8e354/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= From 0bc8c28673346df6d253df5fcac259335bd579f6 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 25 Sep 2020 15:26:08 +0300 Subject: [PATCH 320/426] fix tests --- core/state/frozenfunds/frozen_funds_test.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/core/state/frozenfunds/frozen_funds_test.go b/core/state/frozenfunds/frozen_funds_test.go index 5442fe58c..b5941e3bb 100644 --- a/core/state/frozenfunds/frozen_funds_test.go +++ b/core/state/frozenfunds/frozen_funds_test.go @@ -12,7 +12,11 @@ import ( ) func TestFrozenFundsToAddModel(t *testing.T) { - b, mutableTree := bus.NewBus(), tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, err := tree.NewMutableTree(0, db.NewMemDB(), 1024) + if err != nil { + t.Fatal(err) + } + b := bus.NewBus() ff, err := NewFrozenFunds(b, mutableTree) if err != nil { t.Fatal(err) @@ -58,7 +62,11 @@ func TestFrozenFundsToAddModel(t *testing.T) { } func TestFrozenFundsToDeleteModel(t *testing.T) { - b, mutableTree := bus.NewBus(), tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, err := tree.NewMutableTree(0, db.NewMemDB(), 1024) + if err != nil { + t.Fatal(err) + } + b := bus.NewBus() ff, err := NewFrozenFunds(b, mutableTree) if err != nil { t.Fatal(err) @@ -105,7 +113,11 @@ func TestFrozenFundsToDeleteModel(t *testing.T) { } func TestFrozenFundsToDeleteNotExistenFund(t *testing.T) { - b, mutableTree := bus.NewBus(), tree.NewMutableTree(0, db.NewMemDB(), 1024) + mutableTree, err := tree.NewMutableTree(0, db.NewMemDB(), 1024) + if err != nil { + t.Fatal(err) + } + b := bus.NewBus() ff, err := NewFrozenFunds(b, mutableTree) if err != nil { t.Fatal(err) From 4198e4159dfd1eb7a9bc90d14fe0eb1abafbca29 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 25 Sep 2020 16:03:38 +0300 Subject: [PATCH 321/426] tests --- core/minter/minter_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index 286a420c9..7259ad03e 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -149,7 +149,7 @@ func initTestNode(t *testing.T) (*Blockchain, *rpc.Local, *privval.FilePV) { utils.MinterHome = t.TempDir() if err := tmos.EnsureDir(utils.GetMinterHome()+"/tmdata/blockstore.db", 0777); err != nil { - panic(err.Error()) + t.Fatal(err) } minterCfg := config.GetConfig() @@ -175,7 +175,7 @@ func initTestNode(t *testing.T) (*Blockchain, *rpc.Local, *privval.FilePV) { app := NewMinterBlockchain(minterCfg) nodeKey, err := p2p.LoadOrGenNodeKey(cfg.NodeKeyFile()) if err != nil { - panic(err) + t.Fatal(err) } node, err := tmNode.NewNode( @@ -190,11 +190,11 @@ func initTestNode(t *testing.T) (*Blockchain, *rpc.Local, *privval.FilePV) { ) if err != nil { - panic(fmt.Sprintf("Failed to create a node: %v", err)) + t.Fatal(fmt.Sprintf("Failed to create a node: %v", err)) } if err = node.Start(); err != nil { - panic(fmt.Sprintf("Failed to start node: %v", err)) + t.Fatal(fmt.Sprintf("Failed to start node: %v", err)) } logger.Info("Started node", "nodeInfo", node.Switch().NodeInfo()) From bba6acc5e7304b347df33e84a6655076cc5103cb Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 25 Sep 2020 22:05:40 +0300 Subject: [PATCH 322/426] fix candidate not found --- core/state/waitlist/waitlist.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/core/state/waitlist/waitlist.go b/core/state/waitlist/waitlist.go index e5fd5f264..2b4f4ec06 100644 --- a/core/state/waitlist/waitlist.go +++ b/core/state/waitlist/waitlist.go @@ -103,7 +103,7 @@ func (wl *WaitList) Get(address types.Address, pubkey types.Pubkey, coin types.C candidate := wl.bus.Candidates().GetCandidate(pubkey) if candidate == nil { - log.Panicf("Candidate not found: %s", pubkey.String()) + return nil } for _, item := range waitlist.List { @@ -123,20 +123,16 @@ func (wl *WaitList) GetByAddressAndPubKey(address types.Address, pubkey types.Pu candidate := wl.bus.Candidates().GetCandidate(pubkey) if candidate == nil { - log.Panicf("Candidate not found: %s", pubkey.String()) + return nil } - items := make([]Item, len(waitlist.List)) - for i, item := range waitlist.List { + var items []Item + for _, item := range waitlist.List { if item.CandidateId == candidate.ID { - items[i] = item + items = append(items, item) } } - if len(items) == 0 { - return nil - } - return items } From 3fe504ac801fa12b8da04904df302957c1998911 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 25 Sep 2020 22:35:45 +0300 Subject: [PATCH 323/426] fix mutex --- api/v2/service/address.go | 6 +++--- api/v2/service/addresses.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/api/v2/service/address.go b/api/v2/service/address.go index ba0baa510..851ca513c 100644 --- a/api/v2/service/address.go +++ b/api/v2/service/address.go @@ -36,9 +36,6 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr return new(pb.AddressResponse), status.Error(codes.NotFound, err.Error()) } - cState.RLock() - defer cState.RUnlock() - if req.Height != 0 && req.Delegated { cState.Lock() cState.Candidates().LoadCandidates() @@ -46,6 +43,9 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr cState.Unlock() } + cState.RLock() + defer cState.RUnlock() + balances := cState.Accounts().GetBalances(address) var res pb.AddressResponse diff --git a/api/v2/service/addresses.go b/api/v2/service/addresses.go index f5f55c1fe..a9572e3e1 100644 --- a/api/v2/service/addresses.go +++ b/api/v2/service/addresses.go @@ -18,9 +18,6 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. return new(pb.AddressesResponse), status.Error(codes.NotFound, err.Error()) } - cState.RLock() - defer cState.RUnlock() - if req.Height != 0 && req.Delegated { cState.Lock() cState.Candidates().LoadCandidates() @@ -28,6 +25,9 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. cState.Unlock() } + cState.RLock() + defer cState.RUnlock() + response := &pb.AddressesResponse{ Addresses: make(map[string]*pb.AddressesResponse_Result, len(req.Addresses)), } From 345d062b85658ec161970134049493641e2c437a Mon Sep 17 00:00:00 2001 From: klim0v Date: Sun, 27 Sep 2020 20:09:08 +0300 Subject: [PATCH 324/426] add load candidates for /waitlist --- api/v2/service/waitlist.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/api/v2/service/waitlist.go b/api/v2/service/waitlist.go index bbcf91dba..f7d807f5d 100644 --- a/api/v2/service/waitlist.go +++ b/api/v2/service/waitlist.go @@ -29,6 +29,12 @@ func (s *Service) WaitList(ctx context.Context, req *pb.WaitListRequest) (*pb.Wa return new(pb.WaitListResponse), status.Error(codes.NotFound, err.Error()) } + if req.Height != 0 { + cState.Lock() + cState.Candidates().LoadCandidates() + cState.Unlock() + } + cState.RLock() defer cState.RUnlock() From 2d3184cd85add90ec9fa8be88975a3b30bb58a2f Mon Sep 17 00:00:00 2001 From: klim0v Date: Sun, 27 Sep 2020 20:18:33 +0300 Subject: [PATCH 325/426] add network to status --- api/v2/service/status.go | 1 + go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/api/v2/service/status.go b/api/v2/service/status.go index bab346c13..3b40b2777 100644 --- a/api/v2/service/status.go +++ b/api/v2/service/status.go @@ -23,6 +23,7 @@ func (s *Service) Status(context.Context, *empty.Empty) (*pb.StatusResponse, err return &pb.StatusResponse{ Version: s.version, + Network: result.NodeInfo.Network, LatestBlockHash: fmt.Sprintf("%X", result.SyncInfo.LatestBlockHash), LatestAppHash: fmt.Sprintf("%X", result.SyncInfo.LatestAppHash), LatestBlockHeight: uint64(result.SyncInfo.LatestBlockHeight), diff --git a/go.mod b/go.mod index c5565a6ea..aabdeb8fb 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200925002945-15b5cde8e354 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200927171657-f776ba10feca github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 7265811eb..225e0f58a 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200925002945-15b5cde8e354 h1:HpjApkir3UtOL4WzGzkgQcdT9SyqwiZ/wbGrahzIlLQ= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200925002945-15b5cde8e354/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200927171657-f776ba10feca h1:dnzof1I43yr3aI+TX+cNxnveDKmtoqt1RHNGR3JfsOM= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200927171657-f776ba10feca/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 27a5f017f0cbf22dd242b38604c23fa032f2ab3e Mon Sep 17 00:00:00 2001 From: klim0v Date: Sun, 27 Sep 2020 20:46:24 +0300 Subject: [PATCH 326/426] fix coin checker --- core/state/candidates/candidates.go | 1 - core/state/waitlist/waitlist.go | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 3cb45e8aa..61d6debce 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -399,7 +399,6 @@ func (c *Candidates) stakeKick(owner types.Address, value *big.Int, coin types.C Coin: coin, ValidatorPubKey: pubKey, }) - c.bus.Accounts().AddBalance(owner, coin, value) c.bus.Checker().AddCoin(coin, big.NewInt(0).Neg(value)) } diff --git a/core/state/waitlist/waitlist.go b/core/state/waitlist/waitlist.go index 2b4f4ec06..5fdb8f193 100644 --- a/core/state/waitlist/waitlist.go +++ b/core/state/waitlist/waitlist.go @@ -147,6 +147,7 @@ func (wl *WaitList) AddWaitList(address types.Address, pubkey types.Pubkey, coin w.AddToList(candidate.ID, coin, value) wl.setToMap(address, w) w.markDirty(address) + wl.bus.Checker().AddCoin(coin, value) } func (wl *WaitList) Delete(address types.Address, pubkey types.Pubkey, coin types.CoinID) { @@ -173,7 +174,7 @@ func (wl *WaitList) Delete(address types.Address, pubkey types.Pubkey, coin type w.List = items wl.markDirty(address) wl.setToMap(address, w) - wl.bus.Checker().AddCoinVolume(coin, value) + wl.bus.Checker().AddCoin(coin, big.NewInt(0).Neg(value)) } func (wl *WaitList) getOrNew(address types.Address) *Model { From e47579c599b5dbd401850edde9bed3b37d1e36e1 Mon Sep 17 00:00:00 2001 From: klim0v Date: Sun, 27 Sep 2020 22:46:53 +0300 Subject: [PATCH 327/426] fix test --- core/state/waitlist/waitlist_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/state/waitlist/waitlist_test.go b/core/state/waitlist/waitlist_test.go index e5fa3c844..795cacdbb 100644 --- a/core/state/waitlist/waitlist_test.go +++ b/core/state/waitlist/waitlist_test.go @@ -3,6 +3,7 @@ package waitlist import ( "github.com/MinterTeam/minter-go-node/core/state/bus" "github.com/MinterTeam/minter-go-node/core/state/candidates" + "github.com/MinterTeam/minter-go-node/core/state/checker" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/tree" db "github.com/tendermint/tm-db" @@ -12,6 +13,7 @@ import ( func TestWaitListToGetByAddressAndPubKey(t *testing.T) { b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) wl, err := NewWaitList(b, mutableTree) From b87fcc3570750b65ef8b6d703ae3a9b6b18ffed9 Mon Sep 17 00:00:00 2001 From: klim0v Date: Sun, 27 Sep 2020 22:51:41 +0300 Subject: [PATCH 328/426] fix test --- core/transaction/delegate_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/transaction/delegate_test.go b/core/transaction/delegate_test.go index 881804a61..8c8595e1f 100644 --- a/core/transaction/delegate_test.go +++ b/core/transaction/delegate_test.go @@ -501,8 +501,9 @@ func TestDelegateData_addFromWaitlist(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) cState.Waitlist.AddWaitList(addr, pubkey, 0, big.NewInt(100)) + cState.Checker.AddCoin(0, big.NewInt(0).Neg(big.NewInt(100))) cState.Accounts.AddBalance(addr, 0, helpers.BipToPip(big.NewInt(1000000))) - cState.Checker.AddCoinVolume(0, helpers.BipToPip(big.NewInt(1000000))) + cState.Checker.AddCoin(0, helpers.BipToPip(big.NewInt(0).Neg(big.NewInt(1000000)))) value := big.NewInt(10000000000) data := DelegateData{ From db4001b407101a70c3d7d6c58ed5bbd0b8deaf56 Mon Sep 17 00:00:00 2001 From: Vladyslav Tokarchuk Date: Mon, 28 Sep 2020 13:02:14 +0300 Subject: [PATCH 329/426] Fixed database path inside container. --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 54c056882..20853b00e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,7 +4,7 @@ services: image: minterteam/minter:latest #build: . volumes: - - minter_data:/minter/data + - minter_data:/minter/.minter ports: - "8841:8841" - "127.0.0.1:3000:3000" From b58a78cf90eb8e145a924df24fff51b7ad501144 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 28 Sep 2020 15:28:53 +0300 Subject: [PATCH 330/426] fix RecalculateStakes --- core/state/candidates/candidate_test.go | 148 ++++++++++++++++++++++++ core/state/candidates/coins_cache.go | 6 +- 2 files changed, 151 insertions(+), 3 deletions(-) diff --git a/core/state/candidates/candidate_test.go b/core/state/candidates/candidate_test.go index 70c61470d..e3c595c2f 100644 --- a/core/state/candidates/candidate_test.go +++ b/core/state/candidates/candidate_test.go @@ -1147,3 +1147,151 @@ func TestCandidate_GetFilteredUpdates(t *testing.T) { t.Fatal("error merge updates") } } + +func TestCandidates_RecalculateStakes(t *testing.T) { + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + busCoins, err := coins.NewCoins(b, mutableTree) + if err != nil { + t.Fatal(err) + } + b.SetCoins(coins.NewBus(busCoins)) + candidates, err := NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + coinsState, err := coins.NewCoins(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + candidates.Create([20]byte{1}, [20]byte{1}, [20]byte{1}, [32]byte{1}, 1) + candidates.SetStakes([32]byte{1}, []types.Stake{ + { + Owner: types.Address{1}, + Coin: 52, + Value: "27331500301898443574821601", + BipValue: "0", + }, + { + Owner: types.Address{1}, + Coin: 52, + Value: "26788352158593847436109305", + BipValue: "0", + }, + { + Owner: types.Address{1}, + Coin: 52, + Value: "23056159980819190092008573", + BipValue: "0", + }, + { + Owner: types.Address{1}, + Coin: 52, + Value: "11588709101209768903338862", + BipValue: "0", + }, + { + Owner: types.Address{1}, + Coin: 52, + Value: "10699458018244407488345007", + BipValue: "0", + }, + { + Owner: types.Address{1}, + Coin: 52, + Value: "10178615801247206484340203", + BipValue: "0", + }, + { + Owner: types.Address{1}, + Coin: 52, + Value: "9695040709408605598614475", + BipValue: "0", + }, + { + Owner: types.Address{1}, + Coin: 52, + Value: "9311613733840163086812673", + BipValue: "0", + }, + { + Owner: types.Address{1}, + Coin: 52, + Value: "8035237015568850680085714", + BipValue: "0", + }, + { + Owner: types.Address{1}, + Coin: 52, + Value: "7751636678470495902806639", + BipValue: "0", + }, + { + Owner: types.Address{1}, + Coin: 52, + Value: "7729118857616059555215844", + BipValue: "0", + }, + { + Owner: types.Address{1}, + Coin: 52, + Value: "7246351659896715230790480", + BipValue: "0", + }, + { + Owner: types.Address{1}, + Coin: 52, + Value: "5634000000000000000000000", + BipValue: "0", + }, + { + Owner: types.Address{1}, + Coin: 52, + Value: "5111293424492290525817483", + BipValue: "0", + }, + { + Owner: types.Address{1}, + Coin: 52, + Value: "4636302767358508700208179", + BipValue: "0", + }, + { + Owner: types.Address{1}, + Coin: 52, + Value: "4375153667350433703873779", + BipValue: "0", + }, + { + Owner: types.Address{1}, + Coin: 52, + Value: "6468592759016388938414535", + BipValue: "0", + }, + }, nil) + volume, _ := big.NewInt(0).SetString("235304453408778922901904166", 10) + reserve, _ := big.NewInt(0).SetString("3417127836274022127064945", 10) + maxSupply, _ := big.NewInt(0).SetString("1000000000000000000000000000000000", 10) + coinsState.Create(52, + types.StrToCoinSymbol("ONLY1"), + "ONLY1", + volume, + 70, + reserve, + maxSupply, + nil) + + amount, _ := big.NewInt(0).SetString("407000000000000000000000", 10) + cache := newCoinsCache() + bipValue := candidates.calculateBipValue(52, amount, false, true, cache) + if bipValue.Sign() < 0 { + t.Fatalf("%s", bipValue.String()) + } + bipValue = candidates.calculateBipValue(52, amount, false, true, cache) + if bipValue.Sign() < 0 { + t.Fatalf("%s", bipValue.String()) + } +} diff --git a/core/state/candidates/coins_cache.go b/core/state/candidates/coins_cache.go index fbf45c23d..d18961dd0 100644 --- a/core/state/candidates/coins_cache.go +++ b/core/state/candidates/coins_cache.go @@ -29,7 +29,7 @@ func (c *coinsCache) Exists(id types.CoinID) bool { } func (c *coinsCache) Get(id types.CoinID) (saleReturn *big.Int, totalAmount *big.Int) { - return big.NewInt(0).Set(c.list[id].totalAmount), big.NewInt(0).Set(c.list[id].totalAmount) + return big.NewInt(0).Set(c.list[id].saleReturn), big.NewInt(0).Set(c.list[id].totalAmount) } func (c *coinsCache) Set(id types.CoinID, saleReturn *big.Int, totalAmount *big.Int) { @@ -41,6 +41,6 @@ func (c *coinsCache) Set(id types.CoinID, saleReturn *big.Int, totalAmount *big. c.list[id] = &coinsCacheItem{} } - c.list[id].totalAmount = totalAmount - c.list[id].saleReturn = saleReturn + c.list[id].totalAmount = big.NewInt(0).Set(totalAmount) + c.list[id].saleReturn = big.NewInt(0).Set(saleReturn) } From 4529cd2a06109f42f678abaf034ae65f0bfb6ee2 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 28 Sep 2020 15:44:53 +0300 Subject: [PATCH 331/426] test GetTotalStake --- core/state/candidates/candidate_test.go | 78 +++---------------------- 1 file changed, 8 insertions(+), 70 deletions(-) diff --git a/core/state/candidates/candidate_test.go b/core/state/candidates/candidate_test.go index e3c595c2f..09bef51c7 100644 --- a/core/state/candidates/candidate_test.go +++ b/core/state/candidates/candidate_test.go @@ -516,74 +516,6 @@ func TestCandidates_GetTotalStake_fromModelAndFromDB(t *testing.T) { } } -func TestCandidates_GetTotalStake_forCustomCoins(t *testing.T) { - - mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) - b := bus.NewBus() - wl, err := waitlist.NewWaitList(b, mutableTree) - if err != nil { - t.Fatal(err) - } - b.SetEvents(eventsdb.NewEventsStore(db.NewMemDB())) - b.SetWaitList(waitlist.NewBus(wl)) - accs, err := accounts.NewAccounts(b, mutableTree) - if err != nil { - t.Fatal(err) - } - b.SetAccounts(accounts.NewBus(accs)) - b.SetChecker(checker.NewChecker(b)) - candidates, err := NewCandidates(b, mutableTree) - if err != nil { - t.Fatal(err) - } - - coinsState, err := coins.NewCoins(b, mutableTree) - if err != nil { - t.Fatal(err) - } - - candidates.Create([20]byte{1}, [20]byte{2}, [20]byte{3}, [32]byte{4}, 10) - coinsState.Create(1, - types.StrToCoinSymbol("AAA"), - "AAACOIN", - helpers.BipToPip(big.NewInt(10)), - 10, - helpers.BipToPip(big.NewInt(10000)), - big.NewInt(0).Exp(big.NewInt(10), big.NewInt(10+18), nil), - nil) - - err = coinsState.Commit() - if err != nil { - t.Fatal(err) - } - - symbol := coinsState.GetCoinBySymbol(types.StrToCoinSymbol("AAA"), 0) - if symbol == nil { - t.Fatal("coin not found") - } - - var stakes []types.Stake - for i := 0; i < 50; i++ { - value := strconv.Itoa(i + 2000) - stakes = append(stakes, types.Stake{ - Owner: types.StringToAddress(strconv.Itoa(i)), - Coin: uint64(symbol.ID()), - Value: value, - BipValue: "0", - }) - } - candidates.SetStakes([32]byte{4}, stakes, nil) - - candidates.RecalculateStakes(0) - - candidates.LoadCandidates() - totalStake := candidates.GetTotalStake([32]byte{4}) - totalStakeString := totalStake.String() - if totalStakeString != "9802420350703877401368" { - t.Fatalf("total stake %s", totalStakeString) - } -} - func TestCandidates_Export(t *testing.T) { mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) candidates, err := NewCandidates(bus.NewBus(), mutableTree) @@ -953,7 +885,6 @@ func TestCandidates_IsNewCandidateStakeSufficient(t *testing.T) { t.Fatal(err) } - // todo: validators.GetCandidatesCountForBlock(1) if !candidates.IsNewCandidateStakeSufficient(0, big.NewInt(1000), 1) { t.Log("is not new candidate stake sufficient") } @@ -1148,7 +1079,7 @@ func TestCandidate_GetFilteredUpdates(t *testing.T) { } } -func TestCandidates_RecalculateStakes(t *testing.T) { +func TestCandidates_CalculateBipValue_RecalculateStakes_GetTotalStake(t *testing.T) { mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) b := bus.NewBus() b.SetChecker(checker.NewChecker(b)) @@ -1286,6 +1217,7 @@ func TestCandidates_RecalculateStakes(t *testing.T) { amount, _ := big.NewInt(0).SetString("407000000000000000000000", 10) cache := newCoinsCache() + bipValue := candidates.calculateBipValue(52, amount, false, true, cache) if bipValue.Sign() < 0 { t.Fatalf("%s", bipValue.String()) @@ -1294,4 +1226,10 @@ func TestCandidates_RecalculateStakes(t *testing.T) { if bipValue.Sign() < 0 { t.Fatalf("%s", bipValue.String()) } + + candidates.RecalculateStakes(0) + totalStake := candidates.GetTotalStake([32]byte{1}) + if totalStake.String() != "2435386873327199834002556" { + t.Fatalf("total stake %s", totalStake.String()) + } } From b0d1d436868f9f57619c84f37c70ea3711a40091 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 28 Sep 2020 19:52:01 +0300 Subject: [PATCH 332/426] fix change pubkey --- core/state/candidates/candidates.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 61d6debce..7ff5bdbdc 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -1026,7 +1026,9 @@ func (c *Candidates) ChangePubKey(old types.Pubkey, new types.Pubkey) { panic("Candidate with such public key (" + new.String() + ") exists in block list") } - c.getFromMap(old).setPublicKey(new) + candidate := c.getFromMap(old) + candidate.setPublicKey(new) + candidate.setTmAddress() c.setBlockPubKey(old) c.setPubKeyID(new, c.pubKeyIDs[old]) delete(c.pubKeyIDs, old) From a48d14ae426621185fc03f993ef16d61108b7489 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 28 Sep 2020 19:55:30 +0300 Subject: [PATCH 333/426] fix change pubkey (optimization) --- core/state/candidates/candidates.go | 4 +--- core/state/candidates/model.go | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 7ff5bdbdc..61d6debce 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -1026,9 +1026,7 @@ func (c *Candidates) ChangePubKey(old types.Pubkey, new types.Pubkey) { panic("Candidate with such public key (" + new.String() + ") exists in block list") } - candidate := c.getFromMap(old) - candidate.setPublicKey(new) - candidate.setTmAddress() + c.getFromMap(old).setPublicKey(new) c.setBlockPubKey(old) c.setPubKeyID(new, c.pubKeyIDs[old]) delete(c.pubKeyIDs, old) diff --git a/core/state/candidates/model.go b/core/state/candidates/model.go index 534dd5690..78c3e8ff0 100644 --- a/core/state/candidates/model.go +++ b/core/state/candidates/model.go @@ -64,6 +64,7 @@ func (candidate *Candidate) setControl(address types.Address) { func (candidate *Candidate) setPublicKey(pubKey types.Pubkey) { candidate.isDirty = true candidate.PubKey = pubKey + candidate.setTmAddress() } func (candidate *Candidate) addUpdate(stake *stake) { From 314931e34adfa98a1688f13f67f832804171e694 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 29 Sep 2020 03:55:31 +0300 Subject: [PATCH 334/426] tmAddress test --- core/state/candidates/candidate_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/state/candidates/candidate_test.go b/core/state/candidates/candidate_test.go index 09bef51c7..16aaa2f41 100644 --- a/core/state/candidates/candidate_test.go +++ b/core/state/candidates/candidate_test.go @@ -13,6 +13,7 @@ import ( "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/tree" + "github.com/tendermint/tendermint/crypto/ed25519" db "github.com/tendermint/tm-db" "math/big" "strconv" @@ -155,6 +156,13 @@ func TestCandidates_Commit_changePubKeyAndCheckBlockList(t *testing.T) { if candidate == nil { t.Fatal("candidate not found") } + var pubkey ed25519.PubKeyEd25519 + copy(pubkey[:], types.Pubkey{5}.Bytes()) + var address types.TmAddress + copy(address[:], pubkey.Address().Bytes()) + if *(candidate.tmAddress) != address { + t.Fatal("tmAddress not change") + } if candidates.PubKey(candidate.ID) != [32]byte{5} { t.Fatal("candidate map ids and pubKeys invalid") } From 35b0def9fa45b37da756536788ec117cebc23a0d Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 29 Sep 2020 09:14:40 +0300 Subject: [PATCH 335/426] fix min stake --- core/state/candidates/candidates.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 61d6debce..0d8726a41 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -37,7 +37,7 @@ const ( ) var ( - minValidatorBipStake = big.NewInt(1000) + minValidatorBipStake = helpers.BipToPip(big.NewInt(10000)) ) // RCandidates interface represents Candidates state From 59b356ff5f46e57fbca412d9f6c07a9fc528c4fd Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 29 Sep 2020 09:15:17 +0300 Subject: [PATCH 336/426] fix min stake --- core/state/candidates/candidates.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 0d8726a41..5bd91eaf9 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -37,7 +37,7 @@ const ( ) var ( - minValidatorBipStake = helpers.BipToPip(big.NewInt(10000)) + minValidatorBipStake = helpers.BipToPip(big.NewInt(1000)) ) // RCandidates interface represents Candidates state From 04bd73e9ebf53acd61abf2c3d972b29155eb2ef3 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 29 Sep 2020 09:21:42 +0300 Subject: [PATCH 337/426] fix tests --- core/state/candidates/candidate_test.go | 8 ++++---- core/state/candidates_test.go | 2 +- core/state/validators/validators_test.go | 19 ++++++++++--------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/core/state/candidates/candidate_test.go b/core/state/candidates/candidate_test.go index 09bef51c7..bb67d5ce3 100644 --- a/core/state/candidates/candidate_test.go +++ b/core/state/candidates/candidate_test.go @@ -998,8 +998,8 @@ func TestCandidates_GetNewCandidates(t *testing.T) { { Owner: [20]byte{1}, Coin: 0, - Value: "1000000000000000", - BipValue: "1000000000000000", + Value: "1000000000000000000000", + BipValue: "1000000000000000000000", }, }, nil) candidates.SetOnline([32]byte{4}) @@ -1009,8 +1009,8 @@ func TestCandidates_GetNewCandidates(t *testing.T) { { Owner: [20]byte{1}, Coin: 0, - Value: "1000000000000000", - BipValue: "1000000000000000", + Value: "1000000000000000000000", + BipValue: "1000000000000000000000", }, }, nil) candidates.SetOnline([32]byte{5}) diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index a32a9e210..0c9428fe0 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -338,7 +338,7 @@ func TestDoubleAbsentPenalty(t *testing.T) { pubkey := createTestCandidate(st) coin := types.GetBaseCoinID() - amount := big.NewInt(1000) + amount := helpers.BipToPip(big.NewInt(1000)) var addr types.Address binary.BigEndian.PutUint64(addr[:], 1) st.Candidates.Delegate(addr, pubkey, coin, amount, big.NewInt(0)) diff --git a/core/state/validators/validators_test.go b/core/state/validators/validators_test.go index 09e6327a5..09908d1f7 100644 --- a/core/state/validators/validators_test.go +++ b/core/state/validators/validators_test.go @@ -12,6 +12,7 @@ import ( "github.com/MinterTeam/minter-go-node/core/state/candidates" "github.com/MinterTeam/minter-go-node/core/state/checker" "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/tree" db "github.com/tendermint/tm-db" "math/big" @@ -244,8 +245,8 @@ func TestValidators_PayRewards(t *testing.T) { { Owner: [20]byte{1}, Coin: 0, - Value: "10000", - BipValue: "10000", + Value: "1000000000000000000000", + BipValue: "1000000000000000000000", }, }, nil) candidatesS.RecalculateStakes(0) @@ -308,8 +309,8 @@ func TestValidators_SetValidatorAbsent(t *testing.T) { { Owner: [20]byte{1}, Coin: 0, - Value: "10000", - BipValue: "10000", + Value: "1000000000000000000000", + BipValue: "1000000000000000000000", }, }, nil) candidatesS.RecalculateStakes(0) @@ -402,7 +403,7 @@ func TestValidators_Export(t *testing.T) { newValidator := NewValidator( [32]byte{4}, types.NewBitArray(ValidatorMaxAbsentWindow), - big.NewInt(1000000), + helpers.BipToPip(big.NewInt(1000000)), big.NewInt(100), true, true, @@ -420,8 +421,8 @@ func TestValidators_Export(t *testing.T) { { Owner: [20]byte{1}, Coin: 0, - Value: "10000", - BipValue: "10000", + Value: "1000000000000000000000", + BipValue: "1000000000000000000000", }, }, nil) candidatesS.RecalculateStakes(0) @@ -440,7 +441,7 @@ func TestValidators_Export(t *testing.T) { t.Fatalf("version %d", version) } - if fmt.Sprintf("%X", hash) != "9387AD1250A4943193BCB44AFF1F4EBFEC626B53FD5A980181AFD7E03079862E" { + if fmt.Sprintf("%X", hash) != "1D50F5F03FAB5D800DBF8D9254DDC68AEAC589BD30F2839A3A5B68887CE0E34C" { t.Fatalf("hash %X", hash) } @@ -452,7 +453,7 @@ func TestValidators_Export(t *testing.T) { t.Fatal(err) } - if string(bytes) != "[{\"total_bip_stake\":\"10000\",\"public_key\":\"Mp0400000000000000000000000000000000000000000000000000000000000000\",\"accum_reward\":\"100\",\"absent_times\":\"________________________\"}]" { + if string(bytes) != "[{\"total_bip_stake\":\"1000000000000000000000\",\"public_key\":\"Mp0400000000000000000000000000000000000000000000000000000000000000\",\"accum_reward\":\"100\",\"absent_times\":\"________________________\"}]" { t.Log(string(bytes)) t.Fatal("not equal JSON") } From b625f1af9f8c986ca0f33fa162ef7b333f38c301 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 29 Sep 2020 13:46:48 +0300 Subject: [PATCH 338/426] add intent and start-height to export cli --- cmd/minter/cmd/export.go | 21 ++++++++++++++++++++- cmd/minter/main.go | 2 ++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/cmd/minter/cmd/export.go b/cmd/minter/cmd/export.go index e3cf37ba3..e55b904bc 100644 --- a/cmd/minter/cmd/export.go +++ b/cmd/minter/cmd/export.go @@ -41,6 +41,11 @@ func export(cmd *cobra.Command, args []string) error { log.Panicf("Cannot parse height: %s", err) } + startHeight, err := cmd.Flags().GetUint64("start-height") + if err != nil { + log.Panicf("Cannot parse start-height: %s", err) + } + chainID, err := cmd.Flags().GetString("chain_id") if err != nil { log.Panicf("Cannot parse chain id: %s", err) @@ -51,6 +56,11 @@ func export(cmd *cobra.Command, args []string) error { log.Panicf("Cannot parse genesis time: %s", err) } + indent, err := cmd.Flags().GetBool("indent") + if err != nil { + log.Panicf("Cannot parse indent: %s", err) + } + fmt.Println("Start exporting...") ldb, err := db.NewGoLevelDB("state", utils.GetMinterHome()+"/data") @@ -66,7 +76,16 @@ func export(cmd *cobra.Command, args []string) error { exportTimeStart, newState := time.Now(), currentState.Export11To12(height) fmt.Printf("State has been exported. Took %s", time.Since(exportTimeStart)) - jsonBytes, err := amino.NewCodec().MarshalJSONIndent(newState, "", " ") + if startHeight > 0 { + newState.StartHeight = startHeight + } + + var jsonBytes []byte + if indent { + jsonBytes, err = amino.NewCodec().MarshalJSONIndent(newState, "", " ") + } else { + jsonBytes, err = amino.NewCodec().MarshalJSON(newState) + } if err != nil { log.Panicf("Cannot marshal state to json: %s", err) } diff --git a/cmd/minter/main.go b/cmd/minter/main.go index c22163dab..73ba5195c 100644 --- a/cmd/minter/main.go +++ b/cmd/minter/main.go @@ -36,6 +36,8 @@ func main() { rootCmd.PersistentFlags().String("pprof-addr", "0.0.0.0:6060", "pprof listen addr") cmd.ExportCommand.Flags().Uint64("height", 0, "export height") + cmd.ExportCommand.Flags().Uint64("start-height", 0, "height for starting a new chain") + cmd.ExportCommand.Flags().Bool("indent", false, "using indent") cmd.ExportCommand.Flags().String("chain_id", "", "export chain id") cmd.ExportCommand.Flags().Duration("genesis_time", 0, "export height") From 4f4202a2c372bd221852e6bec8eebc7b1dff7428 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 29 Sep 2020 13:51:15 +0300 Subject: [PATCH 339/426] edit flag names --- cmd/minter/cmd/export.go | 4 ++-- cmd/minter/main.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/minter/cmd/export.go b/cmd/minter/cmd/export.go index e55b904bc..fb86f18c2 100644 --- a/cmd/minter/cmd/export.go +++ b/cmd/minter/cmd/export.go @@ -46,12 +46,12 @@ func export(cmd *cobra.Command, args []string) error { log.Panicf("Cannot parse start-height: %s", err) } - chainID, err := cmd.Flags().GetString("chain_id") + chainID, err := cmd.Flags().GetString("chain-id") if err != nil { log.Panicf("Cannot parse chain id: %s", err) } - genesisTime, err := cmd.Flags().GetDuration("genesis_time") + genesisTime, err := cmd.Flags().GetDuration("genesis-time") if err != nil { log.Panicf("Cannot parse genesis time: %s", err) } diff --git a/cmd/minter/main.go b/cmd/minter/main.go index 73ba5195c..4e9980aa7 100644 --- a/cmd/minter/main.go +++ b/cmd/minter/main.go @@ -38,8 +38,8 @@ func main() { cmd.ExportCommand.Flags().Uint64("height", 0, "export height") cmd.ExportCommand.Flags().Uint64("start-height", 0, "height for starting a new chain") cmd.ExportCommand.Flags().Bool("indent", false, "using indent") - cmd.ExportCommand.Flags().String("chain_id", "", "export chain id") - cmd.ExportCommand.Flags().Duration("genesis_time", 0, "export height") + cmd.ExportCommand.Flags().String("chain-id", "", "export chain id") + cmd.ExportCommand.Flags().Duration("genesis-time", 0, "export height") if err := rootCmd.ExecuteContext(ctx); err != nil { panic(err) From 45b32d87df80e69fbbbb53bd4a4021099b139276 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 29 Sep 2020 19:16:10 +0300 Subject: [PATCH 340/426] fix eventKick bug --- core/events/store.go | 3 ++- core/minter/minter.go | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/core/events/store.go b/core/events/store.go index 6cdb61906..30d3b53ba 100644 --- a/core/events/store.go +++ b/core/events/store.go @@ -39,6 +39,7 @@ func NewEventsStore(db db.DB) IEventsDB { codec.RegisterConcrete(&reward{}, "reward", nil) codec.RegisterConcrete(&slash{}, "slash", nil) codec.RegisterConcrete(&unbond{}, "unbond", nil) + codec.RegisterConcrete(&stakeKick{}, "stakeKick", nil) return &eventsStore{ cdc: codec, @@ -117,7 +118,7 @@ func (store *eventsStore) CommitEvents() error { store.Lock() defer store.Unlock() if err := store.db.Set(uint32ToBytes(store.pending.height), bytes); err != nil { - panic(err) + return err } return nil } diff --git a/core/minter/minter.go b/core/minter/minter.go index 56c448609..40621716b 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -444,7 +444,10 @@ func (app *Blockchain) Commit() abciTypes.ResponseCommit { } // Flush events db - _ = app.eventsDB.CommitEvents() + err = app.eventsDB.CommitEvents() + if err != nil { + panic(err) + } // Persist application hash and height app.appDB.SetLastBlockHash(hash) From d5f5b85f069a46e443ab3ee90553dc20051ee22c Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 29 Sep 2020 20:30:01 +0300 Subject: [PATCH 341/426] v2/candidates --- api/v2/service/candidates.go | 4 ++++ go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/api/v2/service/candidates.go b/api/v2/service/candidates.go index bcf0313e6..72498eccd 100644 --- a/api/v2/service/candidates.go +++ b/api/v2/service/candidates.go @@ -37,6 +37,10 @@ func (s *Service) Candidates(ctx context.Context, req *pb.CandidatesRequest) (*p return new(pb.CandidatesResponse), timeoutStatus.Err() } + if req.Status != pb.CandidateStatus(0) && req.Status != pb.CandidateStatus(candidate.Status) { + continue + } + response.Candidates = append(response.Candidates, makeResponseCandidate(cState, candidate, req.IncludeStakes)) } diff --git a/go.mod b/go.mod index aabdeb8fb..868e80247 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200927171657-f776ba10feca + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929172758-23647e16cf1b github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 225e0f58a..362c9fa64 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200927171657-f776ba10feca h1:dnzof1I43yr3aI+TX+cNxnveDKmtoqt1RHNGR3JfsOM= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200927171657-f776ba10feca/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929172758-23647e16cf1b h1:P+HKEsNMNymSLCJRSefe5Br5FffPMxkyaPlsKufaBPs= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929172758-23647e16cf1b/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From f4f459248ceb51a3b90a4492c2a910d256954d38 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 29 Sep 2020 21:01:18 +0300 Subject: [PATCH 342/426] delete validator paging --- api/v2/service/validators.go | 2 +- go.mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v2/service/validators.go b/api/v2/service/validators.go index a2a5a5eaf..5db87973b 100644 --- a/api/v2/service/validators.go +++ b/api/v2/service/validators.go @@ -15,7 +15,7 @@ func (s *Service) Validators(ctx context.Context, req *pb.ValidatorsRequest) (*p height = int64(s.blockchain.Height()) } - tmVals, err := s.client.Validators(&height, int(req.Page), int(req.PerPage)) + tmVals, err := s.client.Validators(&height, 1, 100) if err != nil { return new(pb.ValidatorsResponse), status.Error(codes.FailedPrecondition, err.Error()) } diff --git a/go.mod b/go.mod index 868e80247..4c56a9d90 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929172758-23647e16cf1b + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929175107-bc08f6f64978 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 From 31178ce727d367d386213ac6debd7496f24bb84b Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 29 Sep 2020 21:02:04 +0300 Subject: [PATCH 343/426] update go.sum --- go.sum | 2 ++ 1 file changed, 2 insertions(+) diff --git a/go.sum b/go.sum index 362c9fa64..12b4167d9 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1: github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929172758-23647e16cf1b h1:P+HKEsNMNymSLCJRSefe5Br5FffPMxkyaPlsKufaBPs= github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929172758-23647e16cf1b/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929175107-bc08f6f64978 h1:cz30FAbFGDc0rbyrF9jjHZrKGunpzlNRusmpBkji32U= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929175107-bc08f6f64978/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 0bc88fe80e5720054be7f4bb770eef8a03d2e615 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 29 Sep 2020 21:19:18 +0300 Subject: [PATCH 344/426] refactor --- api/v2/service/ws.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/v2/service/ws.go b/api/v2/service/ws.go index ccdaec5a7..222a885d6 100644 --- a/api/v2/service/ws.go +++ b/api/v2/service/ws.go @@ -13,19 +13,19 @@ import ( ) const ( - SubscribeTimeout = 15 * time.Second + subscribeTimeout = 15 * time.Second ) // Subscribe returns a subscription for events by query. func (s *Service) Subscribe(request *pb.SubscribeRequest, stream pb.ApiService_SubscribeServer) error { if s.client.NumClients() >= s.minterCfg.RPC.MaxSubscriptionClients { - return status.Error(codes.Internal, fmt.Sprintf("max_subscription_clients %d reached", s.minterCfg.RPC.MaxSubscriptionClients)) + return status.Error(codes.Canceled, fmt.Sprintf("max_subscription_clients %d reached", s.minterCfg.RPC.MaxSubscriptionClients)) } s.client.Logger.Info("Subscribe to query", "query", request.Query) - ctx, cancel := context.WithTimeout(stream.Context(), SubscribeTimeout) + ctx, cancel := context.WithTimeout(stream.Context(), subscribeTimeout) defer cancel() subscriber := uuid.New().String() sub, err := s.client.Subscribe(ctx, subscriber, request.Query) @@ -41,7 +41,7 @@ func (s *Service) Subscribe(request *pb.SubscribeRequest, stream pb.ApiService_S for { select { case <-ctx.Done(): - return status.FromContextError(stream.Context().Err()).Err() + return status.FromContextError(ctx.Err()).Err() case msg, ok := <-sub: if !ok { return nil From 10f3993a78a4b40bc9a4e8cb034f19edd759603d Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 29 Sep 2020 21:23:28 +0300 Subject: [PATCH 345/426] delete validators paging --- api/api.go | 2 +- api/block.go | 11 ++++------- api/validators.go | 4 ++-- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/api/api.go b/api/api.go index d7c974f47..e69a09cb0 100644 --- a/api/api.go +++ b/api/api.go @@ -34,7 +34,7 @@ var Routes = map[string]*rpcserver.RPCFunc{ "status": rpcserver.NewRPCFunc(Status, ""), "candidates": rpcserver.NewRPCFunc(Candidates, "height,include_stakes"), "candidate": rpcserver.NewRPCFunc(Candidate, "pub_key,height"), - "validators": rpcserver.NewRPCFunc(Validators, "height,page,perPage"), + "validators": rpcserver.NewRPCFunc(Validators, "height"), "address": rpcserver.NewRPCFunc(Address, "address,height"), "addresses": rpcserver.NewRPCFunc(Addresses, "addresses,height"), "send_transaction": rpcserver.NewRPCFunc(SendTransaction, "tx"), diff --git a/api/block.go b/api/block.go index e5e677cf0..71ff25aee 100644 --- a/api/block.go +++ b/api/block.go @@ -67,14 +67,11 @@ func Block(height int64) (*BlockResponse, error) { valHeight = 1 } - var totalValidators []*tmTypes.Validator - for i := 0; i < (((len(block.Block.LastCommit.Signatures) - 1) / 100) + 1); i++ { - tmValidators, err := client.Validators(&valHeight, i+1, 100) - if err != nil { - return nil, rpctypes.RPCError{Code: 500, Message: err.Error()} - } - totalValidators = append(totalValidators, tmValidators.Validators...) + tmValidators, err := client.Validators(&valHeight, 1, 100) + if err != nil { + return nil, rpctypes.RPCError{Code: 500, Message: err.Error()} } + totalValidators := tmValidators.Validators cState, err := GetStateForHeight(int(height)) if err != nil { diff --git a/api/validators.go b/api/validators.go index f744c179b..b370fc082 100644 --- a/api/validators.go +++ b/api/validators.go @@ -11,13 +11,13 @@ type ValidatorResponse struct { type ResponseValidators []ValidatorResponse -func Validators(height uint64, page, perPage int) (*ResponseValidators, error) { +func Validators(height uint64) (*ResponseValidators, error) { if height == 0 { height = blockchain.Height() } h := int64(height) - tmVals, err := client.Validators(&h, page, perPage) + tmVals, err := client.Validators(&h, 1, 100) if err != nil { return nil, err } From 32c0112c22b5b5f89878191cef8b866cdf1d3d33 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 29 Sep 2020 21:26:37 +0300 Subject: [PATCH 346/426] refactor --- api/v2/service/validators.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v2/service/validators.go b/api/v2/service/validators.go index 5db87973b..210e65cda 100644 --- a/api/v2/service/validators.go +++ b/api/v2/service/validators.go @@ -17,7 +17,7 @@ func (s *Service) Validators(ctx context.Context, req *pb.ValidatorsRequest) (*p tmVals, err := s.client.Validators(&height, 1, 100) if err != nil { - return new(pb.ValidatorsResponse), status.Error(codes.FailedPrecondition, err.Error()) + return new(pb.ValidatorsResponse), status.Error(codes.Internal, err.Error()) } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { From 252ab5721e43339599e85a634eaf8e6116fb01de Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 30 Sep 2020 20:49:23 +0300 Subject: [PATCH 347/426] fix verify genesis --- cmd/minter/cmd/node.go | 7 ------- cmd/minter/cmd/root.go | 8 ++++++++ core/types/appstate.go | 1 + 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index dd671f8a4..93ed2154d 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -10,7 +10,6 @@ import ( "github.com/MinterTeam/minter-go-node/config" "github.com/MinterTeam/minter-go-node/core/minter" "github.com/MinterTeam/minter-go-node/core/statistics" - minterTypes "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/log" "github.com/MinterTeam/minter-go-node/version" "github.com/spf13/cobra" @@ -56,12 +55,6 @@ func runNode(cmd *cobra.Command) error { return err } - isTestnet, _ := cmd.Flags().GetBool("testnet") - if isTestnet { - minterTypes.CurrentChainID = minterTypes.ChainTestnet - version.Version += "-testnet" - } - pprofOn, err := cmd.Flags().GetBool("pprof") if err != nil { return err diff --git a/cmd/minter/cmd/root.go b/cmd/minter/cmd/root.go index 91825387f..4a75ea4c3 100644 --- a/cmd/minter/cmd/root.go +++ b/cmd/minter/cmd/root.go @@ -3,6 +3,8 @@ package cmd import ( "github.com/MinterTeam/minter-go-node/cmd/utils" "github.com/MinterTeam/minter-go-node/config" + "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/version" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -28,5 +30,11 @@ var RootCmd = &cobra.Command{ if cfg.KeepLastStates < 1 { panic("keep_last_states field should be greater than 0") } + + isTestnet, _ := cmd.Flags().GetBool("testnet") + if isTestnet { + types.CurrentChainID = types.ChainTestnet + version.Version += "-testnet" + } }, } diff --git a/core/types/appstate.go b/core/types/appstate.go index 3c50250a7..b8705beb9 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -140,6 +140,7 @@ func (s *AppState) Verify() error { if _, exists := coins[coin.Symbol]; exists { return fmt.Errorf("duplicated coin %s", coin.Symbol) } + coins[coin.Symbol] = struct{}{} // check coins' volume From 6dd35aca4bd77f62304b77ba2f2d46e7a17956db Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 30 Sep 2020 20:55:33 +0300 Subject: [PATCH 348/426] fix updates --- core/types/appstate.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/types/appstate.go b/core/types/appstate.go index b8705beb9..9c49c2aad 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -157,6 +157,12 @@ func (s *AppState) Verify() error { volume.Add(volume, helpers.StringToBigInt(stake.Value)) } } + + for _, stake := range candidate.Updates { + if stake.Coin == coin.ID { + volume.Add(volume, helpers.StringToBigInt(stake.Value)) + } + } } for _, account := range s.Accounts { From 33574dd136a48c451901060320e90aad58ed6ffd Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 30 Sep 2020 21:58:29 +0300 Subject: [PATCH 349/426] refactor api, fixes --- api/api.go | 2 +- api/estimate_coin_buy.go | 5 ++--- api/estimate_coin_sell.go | 4 ++-- api/estimate_coin_sell_all.go | 12 ++++------- api/v2/service/candidates.go | 6 ++---- api/v2/service/estimate_coin_buy.go | 26 ++++++++++++------------ api/v2/service/estimate_coin_sell.go | 12 +++++------ api/v2/service/estimate_coin_sell_all.go | 22 +++++++++----------- api/v2/service/transactions.go | 11 +--------- go.mod | 2 +- go.sum | 4 ++++ 11 files changed, 46 insertions(+), 60 deletions(-) diff --git a/api/api.go b/api/api.go index e69a09cb0..136e716cd 100644 --- a/api/api.go +++ b/api/api.go @@ -45,7 +45,7 @@ var Routes = map[string]*rpcserver.RPCFunc{ "net_info": rpcserver.NewRPCFunc(NetInfo, ""), "coin_info": rpcserver.NewRPCFunc(CoinInfo, "symbol,id,height"), "estimate_coin_sell": rpcserver.NewRPCFunc(EstimateCoinSell, "coin_to_sell,coin_to_buy,value_to_sell,height"), - "estimate_coin_sell_all": rpcserver.NewRPCFunc(EstimateCoinSellAll, "coin_to_sell,coin_to_buy,value_to_sell,gas_price,height"), + "estimate_coin_sell_all": rpcserver.NewRPCFunc(EstimateCoinSellAll, "coin_to_sell,coin_to_buy,value_to_sell,height"), "estimate_coin_buy": rpcserver.NewRPCFunc(EstimateCoinBuy, "coin_to_sell,coin_to_buy,value_to_buy,height"), "estimate_tx_commission": rpcserver.NewRPCFunc(EstimateTxCommission, "tx,height"), "unconfirmed_txs": rpcserver.NewRPCFunc(UnconfirmedTxs, "limit"), diff --git a/api/estimate_coin_buy.go b/api/estimate_coin_buy.go index 6ffcd869f..99d59bbed 100644 --- a/api/estimate_coin_buy.go +++ b/api/estimate_coin_buy.go @@ -56,14 +56,13 @@ func EstimateCoinBuy(coinToSell, coinToBuy string, valueToBuy *big.Int, height i switch { case coinTo.ID().IsBaseCoin(): - result = formula.CalculatePurchaseAmount(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), valueToBuy) - case coinFrom.ID().IsBaseCoin(): if coinFrom.Reserve().Cmp(valueToBuy) < 0 { return nil, rpctypes.RPCError{Code: 400, Message: fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coinFrom.Reserve().String(), valueToBuy.String())} } - result = formula.CalculateSaleAmount(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToBuy) + case coinFrom.ID().IsBaseCoin(): + result = formula.CalculatePurchaseAmount(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), valueToBuy) default: baseCoinNeeded := formula.CalculatePurchaseAmount(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), valueToBuy) if coinFrom.Reserve().Cmp(baseCoinNeeded) < 0 { diff --git a/api/estimate_coin_sell.go b/api/estimate_coin_sell.go index 2709617b9..85e0dc199 100644 --- a/api/estimate_coin_sell.go +++ b/api/estimate_coin_sell.go @@ -62,9 +62,9 @@ func EstimateCoinSell(coinToSell, coinToBuy string, valueToSell *big.Int, height switch { case coinFrom.ID().IsBaseCoin(): - result = formula.CalculatePurchaseReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) + result = formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), valueToSell) case coinTo.ID().IsBaseCoin(): - result = formula.CalculateSaleReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), valueToSell) + result = formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) default: basecoinValue := formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) result = formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), basecoinValue) diff --git a/api/estimate_coin_sell_all.go b/api/estimate_coin_sell_all.go index 3316b22bd..fb5df5d66 100644 --- a/api/estimate_coin_sell_all.go +++ b/api/estimate_coin_sell_all.go @@ -15,7 +15,7 @@ type EstimateCoinSellAllResponse struct { } // EstimateCoinSellAll returns an estimate of sell all coin transaction -func EstimateCoinSellAll(coinToSell, coinToBuy string, valueToSell *big.Int, gasPrice uint64, height int) (*EstimateCoinSellAllResponse, +func EstimateCoinSellAll(coinToSell, coinToBuy string, valueToSell *big.Int, height int) (*EstimateCoinSellAllResponse, error) { cState, err := GetStateForHeight(height) if err != nil { @@ -25,10 +25,6 @@ func EstimateCoinSellAll(coinToSell, coinToBuy string, valueToSell *big.Int, gas cState.RLock() defer cState.RUnlock() - if gasPrice < 1 { - gasPrice = 1 - } - coinFrom := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToSell), types.GetVersionFromSymbol(coinToSell)) if coinFrom == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to sell not exists"} @@ -52,13 +48,13 @@ func EstimateCoinSellAll(coinToSell, coinToBuy string, valueToSell *big.Int, gas switch { case coinFrom.ID().IsBaseCoin(): valueToSell.Sub(valueToSell, commission) - if valueToSell.Cmp(big.NewInt(0)) != 1 { + if valueToSell.Sign() != 1 { return nil, rpctypes.RPCError{Code: 400, Message: "Not enough coins to pay commission"} } - result = formula.CalculatePurchaseReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) + result = formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), valueToSell) case coinTo.ID().IsBaseCoin(): - result = formula.CalculateSaleReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), valueToSell) + result = formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) result.Sub(result, commission) if result.Cmp(big.NewInt(0)) != 1 { diff --git a/api/v2/service/candidates.go b/api/v2/service/candidates.go index 72498eccd..bc00a0b9e 100644 --- a/api/v2/service/candidates.go +++ b/api/v2/service/candidates.go @@ -28,16 +28,14 @@ func (s *Service) Candidates(ctx context.Context, req *pb.CandidatesRequest) (*p candidates := cState.Candidates().GetCandidates() - response := &pb.CandidatesResponse{ - Candidates: make([]*pb.CandidateResponse, 0, len(candidates)), - } + response := &pb.CandidatesResponse{} for _, candidate := range candidates { if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { return new(pb.CandidatesResponse), timeoutStatus.Err() } - if req.Status != pb.CandidateStatus(0) && req.Status != pb.CandidateStatus(candidate.Status) { + if req.Status != pb.CandidatesRequest_all && req.Status != pb.CandidatesRequest_CandidateStatus(candidate.Status) { continue } diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index dd7cf1813..03e249ef0 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -16,6 +16,11 @@ import ( // EstimateCoinBuy return estimate of buy coin transaction. func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRequest) (*pb.EstimateCoinBuyResponse, error) { + valueToBuy, ok := big.NewInt(0).SetString(req.ValueToBuy, 10) + if !ok { + return new(pb.EstimateCoinBuyResponse), status.Error(codes.InvalidArgument, "Value to buy not specified") + } + cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.EstimateCoinBuyResponse), status.Error(codes.NotFound, err.Error()) @@ -57,8 +62,7 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).Symbol().String(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).Symbol().String()))) } - commissionInBaseCoin := big.NewInt(commissions.ConvertTx) - commissionInBaseCoin.Mul(commissionInBaseCoin, transaction.CommissionMultiplier) + commissionInBaseCoin := big.NewInt(0).Mul(big.NewInt(commissions.ConvertTx), transaction.CommissionMultiplier) commission := big.NewInt(0).Set(commissionInBaseCoin) coinFrom := cState.Coins().GetCoin(coinToSell) @@ -81,24 +85,20 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe commission = formula.CalculateSaleAmount(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), commissionInBaseCoin) } - valueToBuy, ok := big.NewInt(0).SetString(req.ValueToBuy, 10) - if !ok { - return new(pb.EstimateCoinBuyResponse), status.Error(codes.InvalidArgument, "Value to buy not specified") - } - value := valueToBuy - if !coinToSell.IsBaseCoin() { - value = formula.CalculatePurchaseAmount(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToBuy) - if errResp := transaction.CheckReserveUnderflow(coinFrom, value); errResp != nil { + + if !coinToBuy.IsBaseCoin() { + if errResp := transaction.CheckForCoinSupplyOverflow(coinTo, value); errResp != nil { return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } + value = formula.CalculatePurchaseAmount(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), value) } - if !coinToBuy.IsBaseCoin() { - if errResp := transaction.CheckForCoinSupplyOverflow(coinTo, value); errResp != nil { + if !coinToSell.IsBaseCoin() { + value = formula.CalculateSaleAmount(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToBuy) + if errResp := transaction.CheckReserveUnderflow(coinFrom, value); errResp != nil { return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } - value = formula.CalculateSaleAmount(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), value) } return &pb.EstimateCoinBuyResponse{ diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index bf4d34556..089e70f45 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -16,6 +16,11 @@ import ( // EstimateCoinSell return estimate of sell coin transaction. func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSellRequest) (*pb.EstimateCoinSellResponse, error) { + valueToSell, ok := big.NewInt(0).SetString(req.ValueToSell, 10) + if !ok { + return new(pb.EstimateCoinSellResponse), status.Error(codes.InvalidArgument, "Value to sell not specified") + } + cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.EstimateCoinSellResponse), status.Error(codes.NotFound, err.Error()) @@ -57,13 +62,8 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).Symbol().String(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).Symbol().String()))) } - commissionInBaseCoin := big.NewInt(commissions.ConvertTx) - commissionInBaseCoin.Mul(commissionInBaseCoin, transaction.CommissionMultiplier) + commissionInBaseCoin := big.NewInt(0).Mul(big.NewInt(commissions.ConvertTx), transaction.CommissionMultiplier) commission := big.NewInt(0).Set(commissionInBaseCoin) - valueToSell, ok := big.NewInt(0).SetString(req.ValueToSell, 10) - if !ok { - return new(pb.EstimateCoinSellResponse), status.Error(codes.InvalidArgument, "Value to sell not specified") - } coinFrom := cState.Coins().GetCoin(coinToSell) coinTo := cState.Coins().GetCoin(coinToBuy) diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index 31eb26b17..d7f8457ea 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -16,6 +16,11 @@ import ( // EstimateCoinSellAll return estimate of sell all coin transaction. func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinSellAllRequest) (*pb.EstimateCoinSellAllResponse, error) { + valueToSell, ok := big.NewInt(0).SetString(req.ValueToSell, 10) + if !ok { + return new(pb.EstimateCoinSellAllResponse), status.Error(codes.InvalidArgument, "Value to sell not specified") + } + cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { return new(pb.EstimateCoinSellAllResponse), status.Error(codes.NotFound, err.Error()) @@ -24,16 +29,6 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS cState.RLock() defer cState.RUnlock() - gasPrice := req.GasPrice - if gasPrice < 1 { - gasPrice = 1 - } - - valueToSell, ok := big.NewInt(0).SetString(req.ValueToSell, 10) - if !ok { - return new(pb.EstimateCoinSellAllResponse), status.Error(codes.InvalidArgument, "Value to sell not specified") - } - var coinToBuy types.CoinID if req.GetCoinToBuy() != "" { symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), types.GetVersionFromSymbol(req.GetCoinToBuy())) @@ -68,8 +63,7 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).Symbol().String(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).Symbol().String()))) } - commissionInBaseCoin := big.NewInt(commissions.ConvertTx) - commissionInBaseCoin.Mul(commissionInBaseCoin, transaction.CommissionMultiplier) + commissionInBaseCoin := big.NewInt(0).Mul(big.NewInt(commissions.ConvertTx), transaction.CommissionMultiplier) coinFrom := cState.Coins().GetCoin(coinToSell) coinTo := cState.Coins().GetCoin(coinToBuy) @@ -99,6 +93,10 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS if errResp := transaction.CheckForCoinSupplyOverflow(coinTo, value); errResp != nil { return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } + value.Sub(value, valueToSell) + if value.Sign() != 1 { + return new(pb.EstimateCoinSellAllResponse), status.New(codes.FailedPrecondition, "Not enough coins to pay commission").Err() + } value = formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), value) } diff --git a/api/v2/service/transactions.go b/api/v2/service/transactions.go index 0ff014eb8..e740aab4b 100644 --- a/api/v2/service/transactions.go +++ b/api/v2/service/transactions.go @@ -13,16 +13,7 @@ import ( // Transactions return transactions by query. func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) (*pb.TransactionsResponse, error) { - page := int(req.Page) - if page == 0 { - page = 1 - } - perPage := int(req.PerPage) - if perPage == 0 { - perPage = 100 - } - - rpcResult, err := s.client.TxSearch(req.Query, false, page, perPage, "desc") + rpcResult, err := s.client.TxSearch(req.Query, false, int(req.Page), int(req.PerPage), "desc") if err != nil { return new(pb.TransactionsResponse), status.Error(codes.FailedPrecondition, err.Error()) } diff --git a/go.mod b/go.mod index 4c56a9d90..a5767b36c 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929175107-bc08f6f64978 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200930185357-a7a2d98d223d github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 12b4167d9..06d95550d 100644 --- a/go.sum +++ b/go.sum @@ -11,6 +11,10 @@ github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929172758-23647e16cf1b h1: github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929172758-23647e16cf1b/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929175107-bc08f6f64978 h1:cz30FAbFGDc0rbyrF9jjHZrKGunpzlNRusmpBkji32U= github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929175107-bc08f6f64978/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200930151406-443cd04c7b85 h1:25XNO/0my8AiHAXnVOEW/lSZVLj2ml+54YGIPPLKQ+k= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200930151406-443cd04c7b85/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200930185357-a7a2d98d223d h1:WWwVDGjkCePyF8KuOuifMS0m/xuywOTHGVkykBFMgdU= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200930185357-a7a2d98d223d/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 55dab168365f2f3ce06d5914ea1c8d0861a15293 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 1 Oct 2020 00:27:17 +0300 Subject: [PATCH 350/426] go.mod --- go.sum | 6 ------ 1 file changed, 6 deletions(-) diff --git a/go.sum b/go.sum index 06d95550d..bc9905662 100644 --- a/go.sum +++ b/go.sum @@ -7,12 +7,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929172758-23647e16cf1b h1:P+HKEsNMNymSLCJRSefe5Br5FffPMxkyaPlsKufaBPs= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929172758-23647e16cf1b/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929175107-bc08f6f64978 h1:cz30FAbFGDc0rbyrF9jjHZrKGunpzlNRusmpBkji32U= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200929175107-bc08f6f64978/go.mod h1:LZ+Y8IYfSBx0IQZY+a9pHLjztMwmlaCQX2ncTejoE2o= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200930151406-443cd04c7b85 h1:25XNO/0my8AiHAXnVOEW/lSZVLj2ml+54YGIPPLKQ+k= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200930151406-443cd04c7b85/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200930185357-a7a2d98d223d h1:WWwVDGjkCePyF8KuOuifMS0m/xuywOTHGVkykBFMgdU= github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200930185357-a7a2d98d223d/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= From 69d82df42774d38674421f30647b07ade65e9a2b Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 1 Oct 2020 02:47:02 +0300 Subject: [PATCH 351/426] replace new(api_pb.Response) to nil in api v2 --- api/v2/service/address.go | 6 +++--- api/v2/service/addresses.go | 6 +++--- api/v2/service/block.go | 12 ++++++------ api/v2/service/candidate.go | 8 ++++---- api/v2/service/candidates.go | 2 +- api/v2/service/coin_info.go | 4 ++-- api/v2/service/estimate_coin_buy.go | 4 ++-- api/v2/service/estimate_coin_sell.go | 4 ++-- api/v2/service/estimate_coin_sell_all.go | 4 ++-- api/v2/service/estimate_tx_commission.go | 6 +++--- api/v2/service/events.go | 4 ++-- api/v2/service/frozen.go | 2 +- api/v2/service/gas.go | 2 +- api/v2/service/genesis.go | 4 ++-- api/v2/service/halts.go | 2 +- api/v2/service/missed_blocks.go | 6 +++--- api/v2/service/net_info.go | 2 +- api/v2/service/send_transaction.go | 4 ++-- api/v2/service/status.go | 2 +- api/v2/service/transaction.go | 10 +++++----- api/v2/service/transactions.go | 6 +++--- api/v2/service/unconfirmed_txs.go | 2 +- api/v2/service/validators.go | 2 +- api/v2/service/waitlist.go | 8 ++++---- 24 files changed, 56 insertions(+), 56 deletions(-) diff --git a/api/v2/service/address.go b/api/v2/service/address.go index 851ca513c..767c05c8c 100644 --- a/api/v2/service/address.go +++ b/api/v2/service/address.go @@ -21,19 +21,19 @@ type stakeUser struct { // Address returns coins list, balance and transaction count of an address. func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.AddressResponse, error) { if !strings.HasPrefix(strings.Title(req.Address), "Mx") { - return new(pb.AddressResponse), status.Error(codes.InvalidArgument, "invalid address") + return nil, status.Error(codes.InvalidArgument, "invalid address") } decodeString, err := hex.DecodeString(req.Address[2:]) if err != nil { - return new(pb.AddressResponse), status.Error(codes.InvalidArgument, "invalid address") + return nil, status.Error(codes.InvalidArgument, "invalid address") } address := types.BytesToAddress(decodeString) cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { - return new(pb.AddressResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } if req.Height != 0 && req.Delegated { diff --git a/api/v2/service/addresses.go b/api/v2/service/addresses.go index a9572e3e1..1fe697055 100644 --- a/api/v2/service/addresses.go +++ b/api/v2/service/addresses.go @@ -15,7 +15,7 @@ import ( func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb.AddressesResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { - return new(pb.AddressesResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } if req.Height != 0 && req.Delegated { @@ -39,12 +39,12 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. } if len(addr) < 3 { - return new(pb.AddressesResponse), status.Error(codes.InvalidArgument, fmt.Sprintf("invalid address %s", addr)) + return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("invalid address %s", addr)) } decodeString, err := hex.DecodeString(addr[2:]) if err != nil { - return new(pb.AddressesResponse), status.Error(codes.InvalidArgument, err.Error()) + return nil, status.Error(codes.InvalidArgument, err.Error()) } address := types.BytesToAddress(decodeString) diff --git a/api/v2/service/block.go b/api/v2/service/block.go index 3e742f798..6aa54aad4 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -24,12 +24,12 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes height := int64(req.Height) block, err := s.client.Block(&height) if err != nil { - return new(pb.BlockResponse), status.Error(codes.NotFound, "Block not found") + return nil, status.Error(codes.NotFound, "Block not found") } blockResults, err := s.client.BlockResults(&height) if err != nil { - return new(pb.BlockResponse), status.Error(codes.NotFound, "Block results not found") + return nil, status.Error(codes.NotFound, "Block results not found") } valHeight := height - 1 @@ -57,7 +57,7 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes cState, err = s.blockchain.GetStateForHeight(uint64(height)) if err != nil { - return new(pb.BlockResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } response.Transactions, err = s.blockTransaction(block, blockResults, cState.Coins()) @@ -71,7 +71,7 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes tmValidators, err := s.client.Validators(&valHeight, 1, 100) if err != nil { - return new(pb.BlockResponse), status.Error(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } totalValidators = tmValidators.Validators @@ -118,7 +118,7 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes if cState == nil { cState, err = s.blockchain.GetStateForHeight(uint64(height)) if err != nil { - return new(pb.BlockResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } } @@ -136,7 +136,7 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes if len(totalValidators) == 0 { tmValidators, err := s.client.Validators(&valHeight, 1, 100) if err != nil { - return new(pb.BlockResponse), status.Error(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } totalValidators = tmValidators.Validators } diff --git a/api/v2/service/candidate.go b/api/v2/service/candidate.go index 3ef961ba0..f81465ff8 100644 --- a/api/v2/service/candidate.go +++ b/api/v2/service/candidate.go @@ -15,18 +15,18 @@ import ( // Candidate returns candidate’s info by provided public_key. It will respond with 404 code if candidate is not found. func (s *Service) Candidate(ctx context.Context, req *pb.CandidateRequest) (*pb.CandidateResponse, error) { if len(req.PublicKey) < 3 { - return new(pb.CandidateResponse), status.Error(codes.InvalidArgument, "invalid public_key") + return nil, status.Error(codes.InvalidArgument, "invalid public_key") } decodeString, err := hex.DecodeString(req.PublicKey[2:]) if err != nil { - return new(pb.CandidateResponse), status.Error(codes.InvalidArgument, err.Error()) + return nil, status.Error(codes.InvalidArgument, err.Error()) } pubkey := types.BytesToPubkey(decodeString) cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { - return new(pb.CandidateResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } if req.Height != 0 { @@ -41,7 +41,7 @@ func (s *Service) Candidate(ctx context.Context, req *pb.CandidateRequest) (*pb. candidate := cState.Candidates().GetCandidate(pubkey) if candidate == nil { - return new(pb.CandidateResponse), status.Error(codes.NotFound, "Candidate not found") + return nil, status.Error(codes.NotFound, "Candidate not found") } result := makeResponseCandidate(cState, candidate, true) diff --git a/api/v2/service/candidates.go b/api/v2/service/candidates.go index bc00a0b9e..2d934af30 100644 --- a/api/v2/service/candidates.go +++ b/api/v2/service/candidates.go @@ -11,7 +11,7 @@ import ( func (s *Service) Candidates(ctx context.Context, req *pb.CandidatesRequest) (*pb.CandidatesResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { - return new(pb.CandidatesResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } if req.Height != 0 { diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index 0954ac851..86c107842 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -17,7 +17,7 @@ import ( func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.CoinInfoResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { - return new(pb.CoinInfoResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } cState.RLock() @@ -56,7 +56,7 @@ func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.Co func (s *Service) CoinInfoById(ctx context.Context, req *pb.CoinIdRequest) (*pb.CoinInfoResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { - return new(pb.CoinInfoResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } cState.RLock() diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index 03e249ef0..ba47a7951 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -18,12 +18,12 @@ import ( func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRequest) (*pb.EstimateCoinBuyResponse, error) { valueToBuy, ok := big.NewInt(0).SetString(req.ValueToBuy, 10) if !ok { - return new(pb.EstimateCoinBuyResponse), status.Error(codes.InvalidArgument, "Value to buy not specified") + return nil, status.Error(codes.InvalidArgument, "Value to buy not specified") } cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { - return new(pb.EstimateCoinBuyResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } cState.RLock() diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index 089e70f45..26eb94899 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -18,12 +18,12 @@ import ( func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSellRequest) (*pb.EstimateCoinSellResponse, error) { valueToSell, ok := big.NewInt(0).SetString(req.ValueToSell, 10) if !ok { - return new(pb.EstimateCoinSellResponse), status.Error(codes.InvalidArgument, "Value to sell not specified") + return nil, status.Error(codes.InvalidArgument, "Value to sell not specified") } cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { - return new(pb.EstimateCoinSellResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } cState.RLock() diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index d7f8457ea..43ce6a45e 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -18,12 +18,12 @@ import ( func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinSellAllRequest) (*pb.EstimateCoinSellAllResponse, error) { valueToSell, ok := big.NewInt(0).SetString(req.ValueToSell, 10) if !ok { - return new(pb.EstimateCoinSellAllResponse), status.Error(codes.InvalidArgument, "Value to sell not specified") + return nil, status.Error(codes.InvalidArgument, "Value to sell not specified") } cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { - return new(pb.EstimateCoinSellAllResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } cState.RLock() diff --git a/api/v2/service/estimate_tx_commission.go b/api/v2/service/estimate_tx_commission.go index 096b5af97..dc86737f9 100644 --- a/api/v2/service/estimate_tx_commission.go +++ b/api/v2/service/estimate_tx_commission.go @@ -19,19 +19,19 @@ import ( func (s *Service) EstimateTxCommission(ctx context.Context, req *pb.EstimateTxCommissionRequest) (*pb.EstimateTxCommissionResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { - return new(pb.EstimateTxCommissionResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } cState.RLock() defer cState.RUnlock() if !strings.HasPrefix(strings.Title(req.GetTx()), "0x") { - return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, "invalid transaction") + return nil, status.Error(codes.InvalidArgument, "invalid transaction") } decodeString, err := hex.DecodeString(req.GetTx()[2:]) if err != nil { - return new(pb.EstimateTxCommissionResponse), status.Error(codes.InvalidArgument, err.Error()) + return nil, status.Error(codes.InvalidArgument, err.Error()) } decodedTx, err := transaction.TxDecoder.DecodeFromBytesWithoutSig(decodeString) diff --git a/api/v2/service/events.go b/api/v2/service/events.go index e90fec82b..30311b346 100644 --- a/api/v2/service/events.go +++ b/api/v2/service/events.go @@ -34,12 +34,12 @@ func (s *Service) Events(ctx context.Context, req *pb.EventsRequest) (*pb.Events b, err := json.Marshal(event) if err != nil { - return new(pb.EventsResponse), status.Error(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } data, err := encodeToStruct(b) if err != nil { - return new(pb.EventsResponse), status.Error(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } var t string diff --git a/api/v2/service/frozen.go b/api/v2/service/frozen.go index cf6eaadf2..fe5e44a74 100644 --- a/api/v2/service/frozen.go +++ b/api/v2/service/frozen.go @@ -16,7 +16,7 @@ import ( // Frozen returns frozen balance. func (s *Service) Frozen(ctx context.Context, req *pb.FrozenRequest) (*pb.FrozenResponse, error) { if !strings.HasPrefix(strings.Title(req.Address), "Mx") { - return new(pb.FrozenResponse), status.Error(codes.InvalidArgument, "invalid address") + return nil, status.Error(codes.InvalidArgument, "invalid address") } cState := s.blockchain.CurrentState() diff --git a/api/v2/service/gas.go b/api/v2/service/gas.go index 46d6b8325..81f77a8e7 100644 --- a/api/v2/service/gas.go +++ b/api/v2/service/gas.go @@ -19,7 +19,7 @@ func (s *Service) MinGasPrice(context.Context, *empty.Empty) (*pb.MinGasPriceRes func (s *Service) MaxGasPrice(ctx context.Context, req *pb.MaxGasPriceRequest) (*pb.MaxGasPriceResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { - return new(pb.MaxGasPriceResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } return &pb.MaxGasPriceResponse{ diff --git a/api/v2/service/genesis.go b/api/v2/service/genesis.go index 08fe0ff49..24e450e5c 100644 --- a/api/v2/service/genesis.go +++ b/api/v2/service/genesis.go @@ -14,7 +14,7 @@ import ( func (s *Service) Genesis(ctx context.Context, _ *empty.Empty) (*pb.GenesisResponse, error) { result, err := s.client.Genesis() if err != nil { - return new(pb.GenesisResponse), status.Error(codes.FailedPrecondition, err.Error()) + return nil, status.Error(codes.FailedPrecondition, err.Error()) } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { @@ -24,7 +24,7 @@ func (s *Service) Genesis(ctx context.Context, _ *empty.Empty) (*pb.GenesisRespo var appState pb.GenesisResponse_AppState err = protojson.Unmarshal(result.Genesis.AppState, &appState) if err != nil { - return new(pb.GenesisResponse), status.Error(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { diff --git a/api/v2/service/halts.go b/api/v2/service/halts.go index 6ea9b93a7..2f3280779 100644 --- a/api/v2/service/halts.go +++ b/api/v2/service/halts.go @@ -11,7 +11,7 @@ import ( func (s *Service) Halts(_ context.Context, req *pb.HaltsRequest) (*pb.HaltsResponse, error) { cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { - return new(pb.HaltsResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } blocks := cState.Halts().GetHaltBlocks(req.Height) diff --git a/api/v2/service/missed_blocks.go b/api/v2/service/missed_blocks.go index a7e52988c..776d70d57 100644 --- a/api/v2/service/missed_blocks.go +++ b/api/v2/service/missed_blocks.go @@ -12,12 +12,12 @@ import ( // MissedBlocks returns missed blocks by validator public key. func (s *Service) MissedBlocks(ctx context.Context, req *pb.MissedBlocksRequest) (*pb.MissedBlocksResponse, error) { if !strings.HasPrefix(req.PublicKey, "Mp") { - return new(pb.MissedBlocksResponse), status.Error(codes.InvalidArgument, "public key don't has prefix 'Mp'") + return nil, status.Error(codes.InvalidArgument, "public key don't has prefix 'Mp'") } cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { - return new(pb.MissedBlocksResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } if req.Height != 0 { @@ -31,7 +31,7 @@ func (s *Service) MissedBlocks(ctx context.Context, req *pb.MissedBlocksRequest) val := cState.Validators().GetByPublicKey(types.HexToPubkey(req.PublicKey)) if val == nil { - return new(pb.MissedBlocksResponse), status.Error(codes.NotFound, "Validator not found") + return nil, status.Error(codes.NotFound, "Validator not found") } return &pb.MissedBlocksResponse{ diff --git a/api/v2/service/net_info.go b/api/v2/service/net_info.go index 122a2d2c3..22a8ff69d 100644 --- a/api/v2/service/net_info.go +++ b/api/v2/service/net_info.go @@ -17,7 +17,7 @@ import ( func (s *Service) NetInfo(ctx context.Context, _ *empty.Empty) (*pb.NetInfoResponse, error) { result, err := s.client.NetInfo() if err != nil { - return new(pb.NetInfoResponse), status.Error(codes.FailedPrecondition, err.Error()) + return nil, status.Error(codes.FailedPrecondition, err.Error()) } var peers []*pb.NetInfoResponse_Peer diff --git a/api/v2/service/send_transaction.go b/api/v2/service/send_transaction.go index 1c86a69fc..7e751d791 100644 --- a/api/v2/service/send_transaction.go +++ b/api/v2/service/send_transaction.go @@ -17,11 +17,11 @@ import ( // SendTransaction returns the result of sending signed tx. To ensure that transaction was successfully committed to the blockchain, you need to find the transaction by the hash and ensure that the status code equals to 0. func (s *Service) SendTransaction(ctx context.Context, req *pb.SendTransactionRequest) (*pb.SendTransactionResponse, error) { if !strings.HasPrefix(strings.Title(req.GetTx()), "0x") { - return new(pb.SendTransactionResponse), status.Error(codes.InvalidArgument, "invalid transaction") + return nil, status.Error(codes.InvalidArgument, "invalid transaction") } decodeString, err := hex.DecodeString(req.Tx[2:]) if err != nil { - return new(pb.SendTransactionResponse), status.Error(codes.InvalidArgument, err.Error()) + return nil, status.Error(codes.InvalidArgument, err.Error()) } result, statusErr := s.broadcastTxSync(decodeString, ctx /*timeout*/) diff --git a/api/v2/service/status.go b/api/v2/service/status.go index 3b40b2777..98e967d72 100644 --- a/api/v2/service/status.go +++ b/api/v2/service/status.go @@ -14,7 +14,7 @@ import ( func (s *Service) Status(context.Context, *empty.Empty) (*pb.StatusResponse, error) { result, err := s.client.Status() if err != nil { - return new(pb.StatusResponse), status.Error(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } cState := s.blockchain.CurrentState() diff --git a/api/v2/service/transaction.go b/api/v2/service/transaction.go index 3f8a6f33b..b88de3b4d 100644 --- a/api/v2/service/transaction.go +++ b/api/v2/service/transaction.go @@ -14,16 +14,16 @@ import ( // Transaction returns transaction info. func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) (*pb.TransactionResponse, error) { if len(req.Hash) < 3 { - return new(pb.TransactionResponse), status.Error(codes.InvalidArgument, "invalid hash") + return nil, status.Error(codes.InvalidArgument, "invalid hash") } decodeString, err := hex.DecodeString(req.Hash[2:]) if err != nil { - return new(pb.TransactionResponse), status.Error(codes.InvalidArgument, err.Error()) + return nil, status.Error(codes.InvalidArgument, err.Error()) } tx, err := s.client.Tx(decodeString, false) if err != nil { - return new(pb.TransactionResponse), status.Error(codes.FailedPrecondition, err.Error()) + return nil, status.Error(codes.FailedPrecondition, err.Error()) } decodedTx, _ := transaction.TxDecoder.DecodeFromBytes(tx.Tx) @@ -36,7 +36,7 @@ func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) ( cState, err := s.blockchain.GetStateForHeight(uint64(tx.Height)) if err != nil { - return new(pb.TransactionResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } cState.RLock() @@ -47,7 +47,7 @@ func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) ( } dataStruct, err := encode(decodedTx.GetDecodedData(), cState.Coins()) if err != nil { - return new(pb.TransactionResponse), status.Error(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } return &pb.TransactionResponse{ diff --git a/api/v2/service/transactions.go b/api/v2/service/transactions.go index e740aab4b..9d010875b 100644 --- a/api/v2/service/transactions.go +++ b/api/v2/service/transactions.go @@ -15,7 +15,7 @@ import ( func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) (*pb.TransactionsResponse, error) { rpcResult, err := s.client.TxSearch(req.Query, false, int(req.Page), int(req.PerPage), "desc") if err != nil { - return new(pb.TransactionsResponse), status.Error(codes.FailedPrecondition, err.Error()) + return nil, status.Error(codes.FailedPrecondition, err.Error()) } lenTx := len(rpcResult.Txs) @@ -24,7 +24,7 @@ func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) cState, err := s.blockchain.GetStateForHeight(uint64(rpcResult.Txs[0].Height)) if err != nil { - return new(pb.TransactionsResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } for _, tx := range rpcResult.Txs { @@ -42,7 +42,7 @@ func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) data, err := encode(decodedTx.GetDecodedData(), cState.Coins()) if err != nil { - return new(pb.TransactionsResponse), status.Error(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } result = append(result, &pb.TransactionResponse{ diff --git a/api/v2/service/unconfirmed_txs.go b/api/v2/service/unconfirmed_txs.go index bf7a97b62..7bf9778e5 100644 --- a/api/v2/service/unconfirmed_txs.go +++ b/api/v2/service/unconfirmed_txs.go @@ -11,7 +11,7 @@ import ( func (s *Service) UnconfirmedTxs(ctx context.Context, req *pb.UnconfirmedTxsRequest) (*pb.UnconfirmedTxsResponse, error) { txs, err := s.client.UnconfirmedTxs(int(req.Limit)) if err != nil { - return new(pb.UnconfirmedTxsResponse), status.Error(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } transactions := make([]string, 0, len(txs.Txs)) for _, tx := range txs.Txs { diff --git a/api/v2/service/validators.go b/api/v2/service/validators.go index 210e65cda..27891b2ed 100644 --- a/api/v2/service/validators.go +++ b/api/v2/service/validators.go @@ -17,7 +17,7 @@ func (s *Service) Validators(ctx context.Context, req *pb.ValidatorsRequest) (*p tmVals, err := s.client.Validators(&height, 1, 100) if err != nil { - return new(pb.ValidatorsResponse), status.Error(codes.Internal, err.Error()) + return nil, status.Error(codes.Internal, err.Error()) } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { diff --git a/api/v2/service/waitlist.go b/api/v2/service/waitlist.go index f7d807f5d..6d7744d6b 100644 --- a/api/v2/service/waitlist.go +++ b/api/v2/service/waitlist.go @@ -14,19 +14,19 @@ import ( // WaitList returns the list of address stakes in waitlist. func (s *Service) WaitList(ctx context.Context, req *pb.WaitListRequest) (*pb.WaitListResponse, error) { if !strings.HasPrefix(strings.Title(req.Address), "Mx") { - return new(pb.WaitListResponse), status.Error(codes.InvalidArgument, "invalid address") + return nil, status.Error(codes.InvalidArgument, "invalid address") } decodeString, err := hex.DecodeString(req.Address[2:]) if err != nil { - return new(pb.WaitListResponse), status.Error(codes.InvalidArgument, "invalid address") + return nil, status.Error(codes.InvalidArgument, "invalid address") } address := types.BytesToAddress(decodeString) cState, err := s.blockchain.GetStateForHeight(req.Height) if err != nil { - return new(pb.WaitListResponse), status.Error(codes.NotFound, err.Error()) + return nil, status.Error(codes.NotFound, err.Error()) } if req.Height != 0 { @@ -47,7 +47,7 @@ func (s *Service) WaitList(ctx context.Context, req *pb.WaitListRequest) (*pb.Wa publicKey := req.PublicKey if publicKey != "" { if !strings.HasPrefix(publicKey, "Mp") { - return new(pb.WaitListResponse), status.Error(codes.InvalidArgument, "public key don't has prefix 'Mp'") + return nil, status.Error(codes.InvalidArgument, "public key don't has prefix 'Mp'") } items = cState.WaitList().GetByAddressAndPubKey(address, types.HexToPubkey(publicKey)) } else { From 36f6e03477ce504c7b0b424efa381341dcee4297 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 1 Oct 2020 03:33:27 +0300 Subject: [PATCH 352/426] replace new(api_pb.Response) to nil in api v2 --- api/v2/service/address.go | 6 +++--- api/v2/service/addresses.go | 6 +++--- api/v2/service/block.go | 22 +++++++++++----------- api/v2/service/candidates.go | 2 +- api/v2/service/coin_info.go | 8 ++++---- api/v2/service/estimate_coin_buy.go | 16 ++++++++-------- api/v2/service/estimate_coin_sell.go | 16 ++++++++-------- api/v2/service/estimate_coin_sell_all.go | 18 +++++++++--------- api/v2/service/estimate_tx_commission.go | 4 ++-- api/v2/service/events.go | 2 +- api/v2/service/frozen.go | 4 ++-- api/v2/service/genesis.go | 4 ++-- api/v2/service/net_info.go | 2 +- api/v2/service/send_transaction.go | 4 ++-- api/v2/service/transaction.go | 2 +- api/v2/service/transactions.go | 2 +- api/v2/service/validators.go | 2 +- api/v2/service/waitlist.go | 4 ++-- 18 files changed, 62 insertions(+), 62 deletions(-) diff --git a/api/v2/service/address.go b/api/v2/service/address.go index 767c05c8c..fbd22f787 100644 --- a/api/v2/service/address.go +++ b/api/v2/service/address.go @@ -65,7 +65,7 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.AddressResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } if req.Delegated { @@ -88,7 +88,7 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.AddressResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } res.Delegated = make([]*pb.AddressDelegatedBalance, 0, len(userDelegatedStakesGroupByCoin)) @@ -113,7 +113,7 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.AddressResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } coinsBipValue := big.NewInt(0) diff --git a/api/v2/service/addresses.go b/api/v2/service/addresses.go index 1fe697055..54a4ae2ca 100644 --- a/api/v2/service/addresses.go +++ b/api/v2/service/addresses.go @@ -67,7 +67,7 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.AddressesResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } if req.Delegated { @@ -90,7 +90,7 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.AddressesResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } res.Delegated = make([]*pb.AddressDelegatedBalance, 0, len(userDelegatedStakesGroupByCoin)) @@ -115,7 +115,7 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.AddressesResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } coinsBipValue := big.NewInt(0) diff --git a/api/v2/service/block.go b/api/v2/service/block.go index 6aa54aad4..a8e643eef 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -52,7 +52,7 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes response.BlockReward = rewards.GetRewardForBlock(uint64(height)).String() if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.BlockResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } cState, err = s.blockchain.GetStateForHeight(uint64(height)) @@ -62,11 +62,11 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes response.Transactions, err = s.blockTransaction(block, blockResults, cState.Coins()) if err != nil { - return new(pb.BlockResponse), err + return nil, err } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.BlockResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } tmValidators, err := s.client.Validators(&valHeight, 1, 100) @@ -76,28 +76,28 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes totalValidators = tmValidators.Validators if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.BlockResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } response.Proposer, err = blockProposer(block, totalValidators) if err != nil { - return new(pb.BlockResponse), err + return nil, err } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.BlockResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } response.Validators = blockValidators(totalValidators, block) if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.BlockResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } response.Evidence = blockEvidence(block) if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.BlockResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } response.Missed = missedBlockValidators(cState) @@ -107,7 +107,7 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes for _, field := range req.Fields { if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.BlockResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } switch field { case pb.BlockRequest_size: @@ -129,7 +129,7 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes response.Transactions, err = s.blockTransaction(block, blockResults, cState.Coins()) if err != nil { - return new(pb.BlockResponse), err + return nil, err } case pb.BlockRequest_proposer, pb.BlockRequest_validators: @@ -148,7 +148,7 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes response.Proposer, err = blockProposer(block, totalValidators) if err != nil { - return new(pb.BlockResponse), err + return nil, err } case pb.BlockRequest_evidence: response.Evidence = blockEvidence(block) diff --git a/api/v2/service/candidates.go b/api/v2/service/candidates.go index 2d934af30..d07e9dec6 100644 --- a/api/v2/service/candidates.go +++ b/api/v2/service/candidates.go @@ -32,7 +32,7 @@ func (s *Service) Candidates(ctx context.Context, req *pb.CandidatesRequest) (*p for _, candidate := range candidates { if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.CandidatesResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } if req.Status != pb.CandidatesRequest_all && req.Status != pb.CandidatesRequest_CandidateStatus(candidate.Status) { diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index 86c107842..bfce9b771 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -25,11 +25,11 @@ func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.Co coin := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.Symbol), types.GetVersionFromSymbol(req.Symbol)) if coin == nil { - return new(pb.CoinInfoResponse), s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(code.NewCoinNotExists(req.Symbol, ""))) + return nil, s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(code.NewCoinNotExists(req.Symbol, ""))) } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.CoinInfoResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } var ownerAddress *wrappers.StringValue @@ -64,11 +64,11 @@ func (s *Service) CoinInfoById(ctx context.Context, req *pb.CoinIdRequest) (*pb. coin := cState.Coins().GetCoin(types.CoinID(req.Id)) if coin == nil { - return new(pb.CoinInfoResponse), s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(code.NewCoinNotExists("", strconv.Itoa(int(req.Id))))) + return nil, s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(code.NewCoinNotExists("", strconv.Itoa(int(req.Id))))) } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.CoinInfoResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } var ownerAddress *wrappers.StringValue diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index ba47a7951..f2849b5e4 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -33,13 +33,13 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe if req.GetCoinToBuy() != "" { symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), types.GetVersionFromSymbol(req.GetCoinToBuy())) if symbol == nil { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToBuy(), ""))) + return nil, s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToBuy(), ""))) } coinToBuy = symbol.ID() } else { coinToBuy = types.CoinID(req.GetCoinIdToBuy()) if !cState.Coins().Exists(coinToBuy) { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(code.NewCoinNotExists("", coinToBuy.String()))) + return nil, s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(code.NewCoinNotExists("", coinToBuy.String()))) } } @@ -47,18 +47,18 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe if req.GetCoinToSell() != "" { symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), types.GetVersionFromSymbol(req.GetCoinToSell())) if symbol == nil { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToSell(), ""))) + return nil, s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToSell(), ""))) } coinToSell = symbol.ID() } else { coinToSell = types.CoinID(req.GetCoinIdToSell()) if !cState.Coins().Exists(coinToSell) { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists("", coinToSell.String()))) + return nil, s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists("", coinToSell.String()))) } } if coinToSell == coinToBuy { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), + return nil, s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).Symbol().String(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).Symbol().String()))) } @@ -70,7 +70,7 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe if !coinToSell.IsBaseCoin() { if coinFrom.Reserve().Cmp(commissionInBaseCoin) < 0 { - return new(pb.EstimateCoinBuyResponse), s.createError( + return nil, s.createError( status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coinFrom.Reserve().String(), commissionInBaseCoin.String())), transaction.EncodeError(code.NewCoinReserveNotSufficient( @@ -89,7 +89,7 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe if !coinToBuy.IsBaseCoin() { if errResp := transaction.CheckForCoinSupplyOverflow(coinTo, value); errResp != nil { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) + return nil, s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } value = formula.CalculatePurchaseAmount(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), value) } @@ -97,7 +97,7 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe if !coinToSell.IsBaseCoin() { value = formula.CalculateSaleAmount(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToBuy) if errResp := transaction.CheckReserveUnderflow(coinFrom, value); errResp != nil { - return new(pb.EstimateCoinBuyResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) + return nil, s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } } diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index 26eb94899..5f8211a68 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -33,13 +33,13 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell if req.GetCoinToBuy() != "" { symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), types.GetVersionFromSymbol(req.GetCoinToBuy())) if symbol == nil { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToBuy(), ""))) + return nil, s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToBuy(), ""))) } coinToBuy = symbol.ID() } else { coinToBuy = types.CoinID(req.GetCoinIdToBuy()) if !cState.Coins().Exists(coinToBuy) { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(code.NewCoinNotExists("", coinToBuy.String()))) + return nil, s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(code.NewCoinNotExists("", coinToBuy.String()))) } } @@ -47,18 +47,18 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell if req.GetCoinToSell() != "" { symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), types.GetVersionFromSymbol(req.GetCoinToSell())) if symbol == nil { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToSell(), ""))) + return nil, s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToSell(), ""))) } coinToSell = symbol.ID() } else { coinToSell = types.CoinID(req.GetCoinIdToSell()) if !cState.Coins().Exists(coinToSell) { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists("", coinToSell.String()))) + return nil, s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists("", coinToSell.String()))) } } if coinToSell == coinToBuy { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), + return nil, s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).Symbol().String(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).Symbol().String()))) } @@ -70,7 +70,7 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell if !coinToSell.IsBaseCoin() { if coinFrom.Reserve().Cmp(commissionInBaseCoin) < 0 { - return new(pb.EstimateCoinSellResponse), s.createError( + return nil, s.createError( status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coinFrom.Reserve().String(), commissionInBaseCoin.String())), transaction.EncodeError(code.NewCoinReserveNotSufficient( @@ -89,13 +89,13 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell if !coinToSell.IsBaseCoin() { value = formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) if errResp := transaction.CheckReserveUnderflow(coinFrom, value); errResp != nil { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) + return nil, s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } } if !coinToBuy.IsBaseCoin() { if errResp := transaction.CheckForCoinSupplyOverflow(coinTo, value); errResp != nil { - return new(pb.EstimateCoinSellResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) + return nil, s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } value = formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), value) } diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index 43ce6a45e..64dacec05 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -33,13 +33,13 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS if req.GetCoinToBuy() != "" { symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), types.GetVersionFromSymbol(req.GetCoinToBuy())) if symbol == nil { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToBuy(), ""))) + return nil, s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToBuy(), ""))) } coinToBuy = symbol.ID() } else { coinToBuy = types.CoinID(req.GetCoinIdToBuy()) if !cState.Coins().Exists(coinToBuy) { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(code.NewCoinNotExists("", coinToBuy.String()))) + return nil, s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(code.NewCoinNotExists("", coinToBuy.String()))) } } @@ -47,19 +47,19 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS if req.GetCoinToSell() != "" { symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), types.GetVersionFromSymbol(req.GetCoinToSell())) if symbol == nil { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToSell(), ""))) + return nil, s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToSell(), ""))) } coinToSell = symbol.ID() } else { coinToSell = types.CoinID(req.GetCoinIdToSell()) if !cState.Coins().Exists(coinToSell) { - return new(pb.EstimateCoinSellAllResponse), + return nil, s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists("", coinToSell.String()))) } } if coinToSell == coinToBuy { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), + return nil, s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).Symbol().String(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).Symbol().String()))) } @@ -71,7 +71,7 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS value := valueToSell if !coinToSell.IsBaseCoin() { if coinFrom.Reserve().Cmp(commissionInBaseCoin) < 0 { - return new(pb.EstimateCoinSellAllResponse), s.createError( + return nil, s.createError( status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coinFrom.Reserve().String(), commissionInBaseCoin.String())), transaction.EncodeError(code.NewCoinReserveNotSufficient( @@ -85,17 +85,17 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS value = formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) if errResp := transaction.CheckReserveUnderflow(coinFrom, value); errResp != nil { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) + return nil, s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } } if !coinToBuy.IsBaseCoin() { if errResp := transaction.CheckForCoinSupplyOverflow(coinTo, value); errResp != nil { - return new(pb.EstimateCoinSellAllResponse), s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) + return nil, s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } value.Sub(value, valueToSell) if value.Sign() != 1 { - return new(pb.EstimateCoinSellAllResponse), status.New(codes.FailedPrecondition, "Not enough coins to pay commission").Err() + return nil, status.New(codes.FailedPrecondition, "Not enough coins to pay commission").Err() } value = formula.CalculatePurchaseReturn(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), value) } diff --git a/api/v2/service/estimate_tx_commission.go b/api/v2/service/estimate_tx_commission.go index dc86737f9..50820296c 100644 --- a/api/v2/service/estimate_tx_commission.go +++ b/api/v2/service/estimate_tx_commission.go @@ -36,7 +36,7 @@ func (s *Service) EstimateTxCommission(ctx context.Context, req *pb.EstimateTxCo decodedTx, err := transaction.TxDecoder.DecodeFromBytesWithoutSig(decodeString) if err != nil { - return new(pb.EstimateTxCommissionResponse), status.Errorf(codes.InvalidArgument, "Cannot decode transaction: %s", err.Error()) + return nil, status.Errorf(codes.InvalidArgument, "Cannot decode transaction: %s", err.Error()) } commissionInBaseCoin := decodedTx.CommissionInBaseCoin() @@ -46,7 +46,7 @@ func (s *Service) EstimateTxCommission(ctx context.Context, req *pb.EstimateTxCo coin := cState.Coins().GetCoin(decodedTx.GasCoin) if coin.Reserve().Cmp(commissionInBaseCoin) < 0 { - return new(pb.EstimateTxCommissionResponse), s.createError( + return nil, s.createError( status.New(codes.InvalidArgument, fmt.Sprintf("Coin reserve balance is not sufficient for transaction. Has: %s, required %s", coin.Reserve().String(), commissionInBaseCoin.String())), transaction.EncodeError(code.NewCoinReserveNotSufficient( diff --git a/api/v2/service/events.go b/api/v2/service/events.go index 30311b346..999af1969 100644 --- a/api/v2/service/events.go +++ b/api/v2/service/events.go @@ -17,7 +17,7 @@ func (s *Service) Events(ctx context.Context, req *pb.EventsRequest) (*pb.Events for _, event := range events { if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.EventsResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } var find = true diff --git a/api/v2/service/frozen.go b/api/v2/service/frozen.go index fe5e44a74..34eb21ce6 100644 --- a/api/v2/service/frozen.go +++ b/api/v2/service/frozen.go @@ -29,7 +29,7 @@ func (s *Service) Frozen(ctx context.Context, req *pb.FrozenRequest) (*pb.Frozen coinID := types.CoinID(req.CoinId.GetValue()) reqCoin = cState.Coins().GetCoin(coinID) if reqCoin == nil { - return new(pb.FrozenResponse), s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(code.NewCoinNotExists("", coinID.String()))) + return nil, s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(code.NewCoinNotExists("", coinID.String()))) } } var frozen []*pb.FrozenResponse_Frozen @@ -39,7 +39,7 @@ func (s *Service) Frozen(ctx context.Context, req *pb.FrozenRequest) (*pb.Frozen for i := s.blockchain.Height(); i <= s.blockchain.Height()+candidates.UnbondPeriod; i++ { if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.FrozenResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } funds := cState.FrozenFunds().GetFrozenFunds(i) diff --git a/api/v2/service/genesis.go b/api/v2/service/genesis.go index 24e450e5c..91e17316d 100644 --- a/api/v2/service/genesis.go +++ b/api/v2/service/genesis.go @@ -18,7 +18,7 @@ func (s *Service) Genesis(ctx context.Context, _ *empty.Empty) (*pb.GenesisRespo } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.GenesisResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } var appState pb.GenesisResponse_AppState @@ -28,7 +28,7 @@ func (s *Service) Genesis(ctx context.Context, _ *empty.Empty) (*pb.GenesisRespo } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.GenesisResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } return &pb.GenesisResponse{ diff --git a/api/v2/service/net_info.go b/api/v2/service/net_info.go index 22a8ff69d..8f8932fd7 100644 --- a/api/v2/service/net_info.go +++ b/api/v2/service/net_info.go @@ -30,7 +30,7 @@ func (s *Service) NetInfo(ctx context.Context, _ *empty.Empty) (*pb.NetInfoRespo } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.NetInfoResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } var channels []*pb.NetInfoResponse_Peer_ConnectionStatus_Channel diff --git a/api/v2/service/send_transaction.go b/api/v2/service/send_transaction.go index 7e751d791..8c6397427 100644 --- a/api/v2/service/send_transaction.go +++ b/api/v2/service/send_transaction.go @@ -26,7 +26,7 @@ func (s *Service) SendTransaction(ctx context.Context, req *pb.SendTransactionRe result, statusErr := s.broadcastTxSync(decodeString, ctx /*timeout*/) if statusErr != nil { - return new(pb.SendTransactionResponse), statusErr.Err() + return nil, statusErr.Err() } switch result.Code { @@ -37,7 +37,7 @@ func (s *Service) SendTransaction(ctx context.Context, req *pb.SendTransactionRe Hash: "Mt" + strings.ToLower(result.Hash.String()), }, nil default: - return new(pb.SendTransactionResponse), s.createError(status.New(codes.InvalidArgument, result.Log), result.Info) + return nil, s.createError(status.New(codes.InvalidArgument, result.Log), result.Info) } } diff --git a/api/v2/service/transaction.go b/api/v2/service/transaction.go index b88de3b4d..f166a551a 100644 --- a/api/v2/service/transaction.go +++ b/api/v2/service/transaction.go @@ -43,7 +43,7 @@ func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) ( defer cState.RUnlock() if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.TransactionResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } dataStruct, err := encode(decodedTx.GetDecodedData(), cState.Coins()) if err != nil { diff --git a/api/v2/service/transactions.go b/api/v2/service/transactions.go index 9d010875b..e3b9a92d4 100644 --- a/api/v2/service/transactions.go +++ b/api/v2/service/transactions.go @@ -29,7 +29,7 @@ func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) for _, tx := range rpcResult.Txs { if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.TransactionsResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } decodedTx, _ := transaction.TxDecoder.DecodeFromBytes(tx.Tx) diff --git a/api/v2/service/validators.go b/api/v2/service/validators.go index 27891b2ed..7c7334b80 100644 --- a/api/v2/service/validators.go +++ b/api/v2/service/validators.go @@ -21,7 +21,7 @@ func (s *Service) Validators(ctx context.Context, req *pb.ValidatorsRequest) (*p } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.ValidatorsResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } responseValidators := make([]*pb.ValidatorsResponse_Result, 0, len(tmVals.Validators)) diff --git a/api/v2/service/waitlist.go b/api/v2/service/waitlist.go index 6d7744d6b..4485fc885 100644 --- a/api/v2/service/waitlist.go +++ b/api/v2/service/waitlist.go @@ -39,7 +39,7 @@ func (s *Service) WaitList(ctx context.Context, req *pb.WaitListRequest) (*pb.Wa defer cState.RUnlock() if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.WaitListResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } response := new(pb.WaitListResponse) @@ -60,7 +60,7 @@ func (s *Service) WaitList(ctx context.Context, req *pb.WaitListRequest) (*pb.Wa response.List = make([]*pb.WaitListResponse_Wait, 0, len(items)) for _, item := range items { if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { - return new(pb.WaitListResponse), timeoutStatus.Err() + return nil, timeoutStatus.Err() } response.List = append(response.List, &pb.WaitListResponse_Wait{ From 6411bdb2fe9e95591de229db839738ab4c54a597 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 1 Oct 2020 16:56:37 +0300 Subject: [PATCH 353/426] add gasPrice to EstimateCoinSellAll --- api/v2/service/estimate_coin_sell_all.go | 6 +++++- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index 64dacec05..d901c9c4e 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -63,7 +63,11 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).Symbol().String(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).Symbol().String()))) } - commissionInBaseCoin := big.NewInt(0).Mul(big.NewInt(commissions.ConvertTx), transaction.CommissionMultiplier) + commissionInBaseCoin := big.NewInt(commissions.ConvertTx) + if req.GasPrice > 1 { + commissionInBaseCoin.Mul(commissionInBaseCoin, big.NewInt(int64(req.GasPrice))) + } + commissionInBaseCoin = big.NewInt(0).Mul(commissionInBaseCoin, transaction.CommissionMultiplier) coinFrom := cState.Coins().GetCoin(coinToSell) coinTo := cState.Coins().GetCoin(coinToBuy) diff --git a/go.mod b/go.mod index a5767b36c..68cac2012 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200930185357-a7a2d98d223d + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001133742-f5e8fee67ae0 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index bc9905662..ac2cd767f 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200930185357-a7a2d98d223d h1:WWwVDGjkCePyF8KuOuifMS0m/xuywOTHGVkykBFMgdU= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20200930185357-a7a2d98d223d/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001133742-f5e8fee67ae0 h1:p+9kSzG/HUOP+TOWt/GQyYLJqYBdhhOubbS362rU8+k= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001133742-f5e8fee67ae0/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 65cf3bbdc2005cd9460c860457e2a84dcc51d351 Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 1 Oct 2020 23:41:49 +0300 Subject: [PATCH 354/426] fix nullable fields --- api/v2/service/candidate.go | 7 ++++--- api/v2/service/coin_info.go | 14 +++++--------- api/v2/service/net_info.go | 6 +++--- core/state/accounts/accounts.go | 8 ++++++-- core/state/state.go | 6 +++++- core/types/appstate.go | 4 ++-- core/types/types_test.go | 2 +- go.mod | 2 +- go.sum | 4 ++-- legacy/accounts/accounts.go | 8 ++++++-- 10 files changed, 35 insertions(+), 26 deletions(-) diff --git a/api/v2/service/candidate.go b/api/v2/service/candidate.go index f81465ff8..60ae3aaf9 100644 --- a/api/v2/service/candidate.go +++ b/api/v2/service/candidate.go @@ -9,6 +9,7 @@ import ( pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/wrapperspb" "math/big" ) @@ -64,7 +65,7 @@ func makeResponseCandidate(state *state.CheckState, c *candidates.Candidate, inc minStake := big.NewInt(0) stakes := state.Candidates().GetStakes(c.PubKey) usedSlots := len(stakes) - candidate.UsedSlots = uint64(usedSlots) + candidate.UsedSlots = wrapperspb.UInt64(uint64(usedSlots)) candidate.Stakes = make([]*pb.CandidateResponse_Stake, 0, usedSlots) for i, stake := range stakes { candidate.Stakes = append(candidate.Stakes, &pb.CandidateResponse_Stake{ @@ -84,8 +85,8 @@ func makeResponseCandidate(state *state.CheckState, c *candidates.Candidate, inc minStake = stake.BipValue } } - candidate.UniqUsers = uint64(len(addresses)) - candidate.MinStake = minStake.String() + candidate.UniqUsers = wrapperspb.UInt64(uint64(len(addresses))) + candidate.MinStake = wrapperspb.String(minStake.String()) } return candidate diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index bfce9b771..359611042 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -2,13 +2,13 @@ package service import ( "context" + "google.golang.org/protobuf/types/known/wrapperspb" "strconv" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/core/types" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" - "github.com/golang/protobuf/ptypes/wrappers" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -32,12 +32,10 @@ func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.Co return nil, timeoutStatus.Err() } - var ownerAddress *wrappers.StringValue + var ownerAddress *wrapperspb.StringValue info := cState.Coins().GetSymbolInfo(coin.Symbol()) if info != nil && info.OwnerAddress() != nil { - ownerAddress = &wrappers.StringValue{ - Value: info.OwnerAddress().String(), - } + ownerAddress = wrapperspb.String(info.OwnerAddress().String()) } return &pb.CoinInfoResponse{ @@ -71,12 +69,10 @@ func (s *Service) CoinInfoById(ctx context.Context, req *pb.CoinIdRequest) (*pb. return nil, timeoutStatus.Err() } - var ownerAddress *wrappers.StringValue + var ownerAddress *wrapperspb.StringValue info := cState.Coins().GetSymbolInfo(coin.Symbol()) if info != nil && info.OwnerAddress() != nil { - ownerAddress = &wrappers.StringValue{ - Value: info.OwnerAddress().String(), - } + ownerAddress = wrapperspb.String(info.OwnerAddress().String()) } return &pb.CoinInfoResponse{ diff --git a/api/v2/service/net_info.go b/api/v2/service/net_info.go index 8f8932fd7..f68894789 100644 --- a/api/v2/service/net_info.go +++ b/api/v2/service/net_info.go @@ -4,12 +4,12 @@ import ( "context" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "github.com/golang/protobuf/ptypes/empty" - "github.com/golang/protobuf/ptypes/wrappers" "github.com/tendermint/tendermint/evidence" "github.com/tendermint/tendermint/p2p" typesTM "github.com/tendermint/tendermint/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/wrapperspb" "time" ) @@ -23,10 +23,10 @@ func (s *Service) NetInfo(ctx context.Context, _ *empty.Empty) (*pb.NetInfoRespo var peers []*pb.NetInfoResponse_Peer for _, peer := range result.Peers { - var currentHeight *wrappers.UInt64Value + var currentHeight *wrapperspb.UInt64Value peerHeight := peerHeight(s.tmNode.Switch(), peer.NodeInfo.ID()) if peerHeight != 0 { - currentHeight = &wrappers.UInt64Value{Value: uint64(peerHeight)} + currentHeight = wrapperspb.UInt64(uint64(peerHeight)) } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { diff --git a/core/state/accounts/accounts.go b/core/state/accounts/accounts.go index 5d456da07..2155d7ceb 100644 --- a/core/state/accounts/accounts.go +++ b/core/state/accounts/accounts.go @@ -350,9 +350,13 @@ func (a *Accounts) Export(state *types.AppState) { } if account.IsMultisig() { + var weights []uint64 + for _, weight := range account.MultisigData.Weights { + weights = append(weights, uint64(weight)) + } acc.MultisigData = &types.Multisig{ - Weights: account.MultisigData.Weights, - Threshold: account.MultisigData.Threshold, + Weights: weights, + Threshold: uint64(account.MultisigData.Threshold), Addresses: account.MultisigData.Addresses, } } diff --git a/core/state/state.go b/core/state/state.go index c3cc9bdf3..c8d849948 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -294,7 +294,11 @@ func (s *State) Import(state types.AppState) error { for _, a := range state.Accounts { if a.MultisigData != nil { - s.Accounts.CreateMultisig(a.MultisigData.Weights, a.MultisigData.Addresses, a.MultisigData.Threshold, 1, a.Address) + var weights []uint32 + for _, weight := range a.MultisigData.Weights { + weights = append(weights, uint32(weight)) + } + s.Accounts.CreateMultisig(weights, a.MultisigData.Addresses, uint32(a.MultisigData.Threshold), 1, a.Address) } s.Accounts.SetNonce(a.Address, a.Nonce) diff --git a/core/types/appstate.go b/core/types/appstate.go index 9c49c2aad..c438a5b0d 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -285,8 +285,8 @@ type Balance struct { } type Multisig struct { - Weights []uint32 `json:"weights"` - Threshold uint32 `json:"threshold"` + Weights []uint64 `json:"weights"` + Threshold uint64 `json:"threshold"` Addresses []Address `json:"addresses"` } diff --git a/core/types/types_test.go b/core/types/types_test.go index d1c074ed4..48cfe3f8d 100644 --- a/core/types/types_test.go +++ b/core/types/types_test.go @@ -177,7 +177,7 @@ func TestAppState(t *testing.T) { }, Nonce: 1, MultisigData: &Multisig{ - Weights: []uint32{1, 2, 3}, + Weights: []uint64{1, 2, 3}, Threshold: 1, Addresses: []Address{testAddr, testAddr}, }, diff --git a/go.mod b/go.mod index 68cac2012..318a9a3d8 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001133742-f5e8fee67ae0 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001202130-ffc12fa42455 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index ac2cd767f..3e7ccde4d 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001133742-f5e8fee67ae0 h1:p+9kSzG/HUOP+TOWt/GQyYLJqYBdhhOubbS362rU8+k= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001133742-f5e8fee67ae0/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001202130-ffc12fa42455 h1:KFvEVFmImXQctGGQKEZIUmGBlp0Lqg6ckhzCuhZYXWo= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001202130-ffc12fa42455/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= diff --git a/legacy/accounts/accounts.go b/legacy/accounts/accounts.go index 03aaf47ca..b330833ad 100644 --- a/legacy/accounts/accounts.go +++ b/legacy/accounts/accounts.go @@ -173,9 +173,13 @@ func (a *Accounts) Export(state *types.AppState, coinsMap map[types.CoinSymbol]t } if account.IsMultisig() { + var weights []uint64 + for _, weight := range account.MultisigData.Weights { + weights = append(weights, uint64(weight)) + } acc.MultisigData = &types.Multisig{ - Weights: account.MultisigData.Weights, - Threshold: account.MultisigData.Threshold, + Weights: weights, + Threshold: uint64(account.MultisigData.Threshold), Addresses: account.MultisigData.Addresses, } } From 8bffc5b78a35864cf6ba69e300df581bcdfda13e Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 2 Oct 2020 00:09:48 +0300 Subject: [PATCH 355/426] genesis FrozenFund nullable CandidateKey --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 318a9a3d8..c1b7531f4 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001202130-ffc12fa42455 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001210148-dba4a85e5927 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 3e7ccde4d..dbe243189 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001202130-ffc12fa42455 h1:KFvEVFmImXQctGGQKEZIUmGBlp0Lqg6ckhzCuhZYXWo= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001202130-ffc12fa42455/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001210148-dba4a85e5927 h1:CAQkO6HcfdHE2+y59m00Krsbq09VsxS9ZClIvEMC4qY= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001210148-dba4a85e5927/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 708bf6b66fd6674dfcaf46753f585df41f8680ec Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 2 Oct 2020 02:04:41 +0300 Subject: [PATCH 356/426] add RecalculateStakes and UpdateValidators in InitChain --- core/minter/minter.go | 141 ++++++++++++++------------------- core/state/state.go | 4 +- core/state/validators/model.go | 5 +- go.mod | 1 + go.sum | 1 + 5 files changed, 69 insertions(+), 83 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index 40621716b..f8ac94426 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -14,16 +14,12 @@ import ( "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/core/validators" - "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/version" "github.com/syndtr/goleveldb/leveldb/filter" "github.com/syndtr/goleveldb/leveldb/opt" "github.com/tendermint/go-amino" abciTypes "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto/ed25519" - cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" tmNode "github.com/tendermint/tendermint/node" - types2 "github.com/tendermint/tendermint/types" "github.com/tendermint/tm-db" "math/big" "sort" @@ -131,26 +127,7 @@ func (app *Blockchain) InitChain(req abciTypes.RequestInitChain) abciTypes.Respo panic(err) } - totalPower := big.NewInt(0) - for _, val := range genesisState.Validators { - totalPower.Add(totalPower, helpers.StringToBigInt(val.TotalBipStake)) - } - - vals := make([]abciTypes.ValidatorUpdate, len(genesisState.Validators)) - for i, val := range genesisState.Validators { - var validatorPubKey ed25519.PubKeyEd25519 - copy(validatorPubKey[:], val.PubKey[:]) - pkey, err := cryptoAmino.PubKeyFromBytes(validatorPubKey.Bytes()) - if err != nil { - panic(err) - } - - vals[i] = abciTypes.ValidatorUpdate{ - PubKey: types2.TM2PB.PubKey(pkey), - Power: big.NewInt(0).Div(big.NewInt(0).Mul(helpers.StringToBigInt(val.TotalBipStake), - big.NewInt(100000000)), totalPower).Int64(), - } - } + vals := app.updateValidators(0) app.appDB.SetStartHeight(genesisState.StartHeight) app.appDB.SaveValidators(vals) @@ -242,8 +219,6 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res func (app *Blockchain) EndBlock(req abciTypes.RequestEndBlock) abciTypes.ResponseEndBlock { height := uint64(req.Height) - var updates []abciTypes.ValidatorUpdate - vals := app.stateDeliver.Validators.GetValidators() hasDroppedValidators := false @@ -304,79 +279,85 @@ func (app *Blockchain) EndBlock(req abciTypes.RequestEndBlock) abciTypes.Respons } // update validators + var updates []abciTypes.ValidatorUpdate if req.Height%120 == 0 || hasDroppedValidators { - app.stateDeliver.Candidates.RecalculateStakes(height) + updates = app.updateValidators(height) + } - valsCount := validators.GetValidatorsCountForBlock(height) - newCandidates := app.stateDeliver.Candidates.GetNewCandidates(valsCount) - if len(newCandidates) < valsCount { - valsCount = len(newCandidates) - } + defer func() { + app.StatisticData().PushEndBlock(&statistics.EndRequest{TimeEnd: time.Now(), Height: int64(app.height)}) + }() + + return abciTypes.ResponseEndBlock{ + ValidatorUpdates: updates, + ConsensusParamUpdates: &abciTypes.ConsensusParams{ + Block: &abciTypes.BlockParams{ + MaxBytes: blockMaxBytes, + MaxGas: int64(app.stateDeliver.App.GetMaxGas()), + }, + }, + } +} - newValidators := make([]abciTypes.ValidatorUpdate, valsCount) +func (app *Blockchain) updateValidators(height uint64) []abciTypes.ValidatorUpdate { + app.stateDeliver.Candidates.RecalculateStakes(height) - // calculate total power - totalPower := big.NewInt(0) - for _, candidate := range newCandidates { - totalPower.Add(totalPower, app.stateDeliver.Candidates.GetTotalStake(candidate.PubKey)) - } + valsCount := validators.GetValidatorsCountForBlock(height) + newCandidates := app.stateDeliver.Candidates.GetNewCandidates(valsCount) + if len(newCandidates) < valsCount { + valsCount = len(newCandidates) + } - for i := range newCandidates { - power := big.NewInt(0).Div(big.NewInt(0).Mul(app.stateDeliver.Candidates.GetTotalStake(newCandidates[i].PubKey), - big.NewInt(100000000)), totalPower).Int64() + newValidators := make([]abciTypes.ValidatorUpdate, valsCount) - if power == 0 { - power = 1 - } + // calculate total power + totalPower := big.NewInt(0) + for _, candidate := range newCandidates { + totalPower.Add(totalPower, app.stateDeliver.Candidates.GetTotalStake(candidate.PubKey)) + } - newValidators[i] = abciTypes.Ed25519ValidatorUpdate(newCandidates[i].PubKey[:], power) + for i := range newCandidates { + power := big.NewInt(0).Div(big.NewInt(0).Mul(app.stateDeliver.Candidates.GetTotalStake(newCandidates[i].PubKey), + big.NewInt(100000000)), totalPower).Int64() + + if power == 0 { + power = 1 } - sort.SliceStable(newValidators, func(i, j int) bool { - return newValidators[i].Power > newValidators[j].Power - }) + newValidators[i] = abciTypes.Ed25519ValidatorUpdate(newCandidates[i].PubKey[:], power) + } - // update validators in state - app.stateDeliver.Validators.SetNewValidators(newCandidates) + sort.SliceStable(newValidators, func(i, j int) bool { + return newValidators[i].Power > newValidators[j].Power + }) - activeValidators := app.getCurrentValidators() + // update validators in state + app.stateDeliver.Validators.SetNewValidators(newCandidates) - app.saveCurrentValidators(newValidators) + activeValidators := app.getCurrentValidators() - updates = newValidators + app.saveCurrentValidators(newValidators) - for _, validator := range activeValidators { - persisted := false - for _, newValidator := range newValidators { - if bytes.Equal(validator.PubKey.Data, newValidator.PubKey.Data) { - persisted = true - break - } - } + updates := newValidators - // remove validator - if !persisted { - updates = append(updates, abciTypes.ValidatorUpdate{ - PubKey: validator.PubKey, - Power: 0, - }) + for _, validator := range activeValidators { + persisted := false + for _, newValidator := range newValidators { + if bytes.Equal(validator.PubKey.Data, newValidator.PubKey.Data) { + persisted = true + break } } - } - - defer func() { - app.StatisticData().PushEndBlock(&statistics.EndRequest{TimeEnd: time.Now(), Height: int64(app.height)}) - }() - return abciTypes.ResponseEndBlock{ - ValidatorUpdates: updates, - ConsensusParamUpdates: &abciTypes.ConsensusParams{ - Block: &abciTypes.BlockParams{ - MaxBytes: blockMaxBytes, - MaxGas: int64(app.stateDeliver.App.GetMaxGas()), - }, - }, + // remove validator + if !persisted { + updates = append(updates, abciTypes.ValidatorUpdate{ + PubKey: validator.PubKey, + Power: 0, + }) + } } + return updates } // Info return application info. Used for synchronization between Tendermint and Minter diff --git a/core/state/state.go b/core/state/state.go index c8d849948..452414d77 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -24,6 +24,7 @@ import ( legacyFrozenfunds "github.com/MinterTeam/minter-go-node/legacy/frozenfunds" "github.com/MinterTeam/minter-go-node/tree" db "github.com/tendermint/tm-db" + "gopkg.in/errgo.v2/fmt/errors" "log" "math/big" "sync" @@ -340,11 +341,12 @@ func (s *State) Import(state types.AppState) error { s.Candidates.SetTotalStake(c.PubKey, helpers.StringToBigInt(c.TotalBipStake)) s.Candidates.SetStakes(c.PubKey, c.Stakes, c.Updates) } + s.Candidates.RecalculateStakes(state.StartHeight) for _, w := range state.Waitlist { value, ok := big.NewInt(0).SetString(w.Value, 10) if !ok { - panic(fmt.Sprintf("Cannot decode %s into big.Int", w.Value)) + return errors.Newf("Cannot decode %s into big.Int", w.Value) } s.Waitlist.AddWaitList(w.Owner, s.Candidates.PubKey(uint32(w.CandidateID)), types.CoinID(w.Coin), value) } diff --git a/core/state/validators/model.go b/core/state/validators/model.go index a057db532..248c72777 100644 --- a/core/state/validators/model.go +++ b/core/state/validators/model.go @@ -67,9 +67,10 @@ func (v *Validator) GetTotalBipStake() *big.Int { // SetTotalBipStake sets total bip stake func (v *Validator) SetTotalBipStake(value *big.Int) { - if v.totalStake.Cmp(value) != 0 { - v.isTotalStakeDirty = true + if v.totalStake.Cmp(value) == 0 { + return } + v.isTotalStakeDirty = true v.totalStake = value } diff --git a/go.mod b/go.mod index c1b7531f4..3b7bb83ed 100644 --- a/go.mod +++ b/go.mod @@ -38,4 +38,5 @@ require ( golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/grpc v1.32.0 google.golang.org/protobuf v1.25.0 + gopkg.in/errgo.v2 v2.1.0 ) diff --git a/go.sum b/go.sum index dbe243189..7c0bef679 100644 --- a/go.sum +++ b/go.sum @@ -676,6 +676,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= From 9102705be412e69f832499c49823476b703e88fd Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 2 Oct 2020 02:19:19 +0300 Subject: [PATCH 357/426] check lash height in events --- api/v2/service/events.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/api/v2/service/events.go b/api/v2/service/events.go index 999af1969..7ae76c0a8 100644 --- a/api/v2/service/events.go +++ b/api/v2/service/events.go @@ -11,6 +11,11 @@ import ( // Events returns events at given height. func (s *Service) Events(ctx context.Context, req *pb.EventsRequest) (*pb.EventsResponse, error) { + currentHeight := s.blockchain.Height() + if req.Height > currentHeight { + return nil, status.Errorf(codes.NotFound, "wanted to load target %d but only found up to %d", req.Height, currentHeight) + } + height := uint32(req.Height) events := s.blockchain.GetEventsDB().LoadEvents(height) resultEvents := make([]*pb.EventsResponse_Event, 0, len(events)) From 086806547198c3f88fffff918dffef6a26484cb0 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 2 Oct 2020 03:26:28 +0300 Subject: [PATCH 358/426] update doc --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c1b7531f4..5975681d0 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001210148-dba4a85e5927 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201002002423-9c7eba45b3e4 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index dbe243189..d81080613 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001210148-dba4a85e5927 h1:CAQkO6HcfdHE2+y59m00Krsbq09VsxS9ZClIvEMC4qY= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201001210148-dba4a85e5927/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201002002423-9c7eba45b3e4 h1:yS7aXu1LI8spwdwp+EhLX1UmXiNDErZbPgPrbF+STQ8= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201002002423-9c7eba45b3e4/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 5750605a2c5386b923a0e93c2fda03df89a92a92 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 2 Oct 2020 13:56:04 +0300 Subject: [PATCH 359/426] add user to pubsub by address --- api/v2/service/ws.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/api/v2/service/ws.go b/api/v2/service/ws.go index 222a885d6..36fde0cdd 100644 --- a/api/v2/service/ws.go +++ b/api/v2/service/ws.go @@ -8,6 +8,7 @@ import ( "github.com/google/uuid" core_types "github.com/tendermint/tendermint/rpc/core/types" "google.golang.org/grpc/codes" + "google.golang.org/grpc/peer" "google.golang.org/grpc/status" "time" ) @@ -20,20 +21,25 @@ const ( func (s *Service) Subscribe(request *pb.SubscribeRequest, stream pb.ApiService_SubscribeServer) error { if s.client.NumClients() >= s.minterCfg.RPC.MaxSubscriptionClients { - return status.Error(codes.Canceled, fmt.Sprintf("max_subscription_clients %d reached", s.minterCfg.RPC.MaxSubscriptionClients)) + return status.Error(codes.ResourceExhausted, fmt.Sprintf("max_subscription_clients %d reached", s.minterCfg.RPC.MaxSubscriptionClients)) } s.client.Logger.Info("Subscribe to query", "query", request.Query) ctx, cancel := context.WithTimeout(stream.Context(), subscribeTimeout) defer cancel() - subscriber := uuid.New().String() - sub, err := s.client.Subscribe(ctx, subscriber, request.Query) + + remote := uuid.New().String() + subscriber, ok := peer.FromContext(ctx) + if ok { + remote = subscriber.Addr.String() + } + sub, err := s.client.Subscribe(ctx, remote, request.Query) if err != nil { return status.Error(codes.InvalidArgument, err.Error()) } defer func() { - if err := s.client.UnsubscribeAll(context.Background(), subscriber); err != nil { + if err := s.client.UnsubscribeAll(context.Background(), remote); err != nil { s.client.Logger.Error(err.Error()) } }() From 257e8fa7b2fe14e2844692b0ff715be82c2d20e1 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 2 Oct 2020 14:36:16 +0300 Subject: [PATCH 360/426] update swagger contact email --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5975681d0..4e886cf8b 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201002002423-9c7eba45b3e4 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201002113509-9b89a2a6277c github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index d81080613..45d245c49 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201002002423-9c7eba45b3e4 h1:yS7aXu1LI8spwdwp+EhLX1UmXiNDErZbPgPrbF+STQ8= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201002002423-9c7eba45b3e4/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201002113509-9b89a2a6277c h1:0GtBLTqt/9KnP9AgjbUbccsbwtMqYQxk9EmQ/YD8cxQ= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201002113509-9b89a2a6277c/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 4d01eade7fb923fed47ef6cc39228802a07951f5 Mon Sep 17 00:00:00 2001 From: klim0v Date: Sat, 3 Oct 2020 02:39:13 +0300 Subject: [PATCH 361/426] update wsproxy --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 4e886cf8b..6461c2f94 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/tendermint/iavl v0.14.0 github.com/tendermint/tendermint v0.33.8 github.com/tendermint/tm-db v0.5.1 - github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 + github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966 github.com/urfave/cli/v2 v2.0.0 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 golang.org/x/net v0.0.0-20200822124328-c89045814202 diff --git a/go.sum b/go.sum index 45d245c49..9ed22dfe5 100644 --- a/go.sum +++ b/go.sum @@ -468,6 +468,8 @@ github.com/tendermint/tm-db v0.5.1/go.mod h1:g92zWjHpCYlEvQXvy9M168Su8V1IBEeawpX github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966 h1:j6JEOq5QWFker+d7mFQYOhjTZonQ7YkLTHm56dbn+yM= +github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= From 4ceab226db3f35718f015ff648ed64177f70714f Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 5 Oct 2020 16:00:56 +0300 Subject: [PATCH 362/426] event type names --- api/v2/service/events.go | 17 +--------------- core/events/types.go | 37 +++++++++++++++++++++++++++++------ core/minter/minter_test.go | 2 +- core/state/candidates_test.go | 8 ++++++-- 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/api/v2/service/events.go b/api/v2/service/events.go index 7ae76c0a8..3f23c24e8 100644 --- a/api/v2/service/events.go +++ b/api/v2/service/events.go @@ -3,7 +3,6 @@ package service import ( "context" "encoding/json" - eventsdb "github.com/MinterTeam/minter-go-node/core/events" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -47,21 +46,7 @@ func (s *Service) Events(ctx context.Context, req *pb.EventsRequest) (*pb.Events return nil, status.Error(codes.Internal, err.Error()) } - var t string - switch event.(type) { - case *eventsdb.RewardEvent: - t = "minter/RewardEvent" - case *eventsdb.SlashEvent: - t = "minter/SlashEvent" - case *eventsdb.UnbondEvent: - t = "minter/UnbondEvent" - case *eventsdb.StakeKickEvent: - t = "minter/StakeKickEvent" - default: - t = "Undefined Type" - } - - resultEvents = append(resultEvents, &pb.EventsResponse_Event{Type: t, Value: data}) + resultEvents = append(resultEvents, &pb.EventsResponse_Event{Type: event.Type(), Value: data}) } return &pb.EventsResponse{ Events: resultEvents, diff --git a/core/events/types.go b/core/events/types.go index c3ecbf5e8..caa4ccd80 100644 --- a/core/events/types.go +++ b/core/events/types.go @@ -7,23 +7,32 @@ import ( "math/big" ) +// Event type names +const ( + TypeRewardEvent = "minter/RewardEvent" + TypeSlashEvent = "minter/SlashEvent" + TypeUnbondEvent = "minter/UnbondEvent" + TypeStakeKickEvent = "minter/StakeKickEvent" +) + func RegisterAminoEvents(codec *amino.Codec) { codec.RegisterInterface((*Event)(nil), nil) codec.RegisterConcrete(RewardEvent{}, - "minter/RewardEvent", nil) + TypeRewardEvent, nil) codec.RegisterConcrete(SlashEvent{}, - "minter/SlashEvent", nil) + TypeSlashEvent, nil) codec.RegisterConcrete(UnbondEvent{}, - "minter/UnbondEvent", nil) + TypeUnbondEvent, nil) codec.RegisterConcrete(StakeKickEvent{}, - "minter/StakeKickEvent", nil) + TypeStakeKickEvent, nil) } type Event interface { - address() types.Address - validatorPubKey() types.Pubkey + Type() string AddressString() string ValidatorPubKeyString() string + validatorPubKey() types.Pubkey + address() types.Address convert(pubKeyID uint16, addressID uint32) compactEvent } @@ -105,6 +114,10 @@ type RewardEvent struct { ValidatorPubKey types.Pubkey `json:"validator_pub_key"` } +func (re *RewardEvent) Type() string { + return TypeRewardEvent +} + func (re *RewardEvent) AddressString() string { return re.Address.String() } @@ -162,6 +175,10 @@ type SlashEvent struct { ValidatorPubKey types.Pubkey `json:"validator_pub_key"` } +func (se *SlashEvent) Type() string { + return TypeSlashEvent +} + func (se *SlashEvent) AddressString() string { return se.Address.String() } @@ -219,6 +236,10 @@ type UnbondEvent struct { ValidatorPubKey types.Pubkey `json:"validator_pub_key"` } +func (ue *UnbondEvent) Type() string { + return TypeUnbondEvent +} + func (ue *UnbondEvent) AddressString() string { return ue.Address.String() } @@ -276,6 +297,10 @@ type StakeKickEvent struct { ValidatorPubKey types.Pubkey `json:"validator_pub_key"` } +func (ue *StakeKickEvent) Type() string { + return TypeStakeKickEvent +} + func (ue *StakeKickEvent) AddressString() string { return ue.Address.String() } diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index 7259ad03e..7a2d9d157 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -471,7 +471,7 @@ func TestBlockchain_FrozenFunds(t *testing.T) { if len(events) == 0 { t.Errorf("empty events for %d block", targetHeight) } - if _, ok := events[0].(*eventsdb.UnbondEvent); !ok { + if events[0].Type() != eventsdb.TypeUnbondEvent { t.Fatal("event is not UnbondEvent") } if events[0].AddressString() != developers.Address.String() { diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index 0c9428fe0..3c6ae38ed 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -512,8 +512,12 @@ func TestRecalculateStakes(t *testing.T) { } stake := st.Candidates.GetStakeOfAddress(pubkey, [20]byte{1}, 1) - t.Log(stake.Value.String()) - t.Log(stake.BipValue.String()) + if stake.Value.String() != "1000000000000000000000" { + t.Errorf("stake value is %s", stake.Value.String()) + } + if stake.BipValue.String() != "13894954943731374342" { + t.Errorf("stake bip value is %s", stake.BipValue.String()) + } } func getState() *State { From 93c52b11a01e9a318cec7289b4275831dffe8ae6 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 6 Oct 2020 14:35:14 +0300 Subject: [PATCH 363/426] fix estimate_coin_buy.go --- api/v2/service/estimate_coin_buy.go | 6 +++--- api/v2/service/estimate_coin_sell.go | 1 + api/v2/service/estimate_coin_sell_all.go | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index f2849b5e4..362c2da00 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -88,14 +88,14 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe value := valueToBuy if !coinToBuy.IsBaseCoin() { - if errResp := transaction.CheckForCoinSupplyOverflow(coinTo, value); errResp != nil { + if errResp := transaction.CheckForCoinSupplyOverflow(coinTo, valueToBuy); errResp != nil { return nil, s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } - value = formula.CalculatePurchaseAmount(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), value) + value = formula.CalculatePurchaseAmount(coinTo.Volume(), coinTo.Reserve(), coinTo.Crr(), valueToBuy) } if !coinToSell.IsBaseCoin() { - value = formula.CalculateSaleAmount(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToBuy) + value = formula.CalculateSaleAmount(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), value) if errResp := transaction.CheckReserveUnderflow(coinFrom, value); errResp != nil { return nil, s.createError(status.New(codes.FailedPrecondition, errResp.Log), errResp.Info) } diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index 5f8211a68..86ed8b662 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -86,6 +86,7 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell } value := valueToSell + if !coinToSell.IsBaseCoin() { value = formula.CalculateSaleReturn(coinFrom.Volume(), coinFrom.Reserve(), coinFrom.Crr(), valueToSell) if errResp := transaction.CheckReserveUnderflow(coinFrom, value); errResp != nil { diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index d901c9c4e..38cdd150c 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -73,6 +73,7 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS coinTo := cState.Coins().GetCoin(coinToBuy) value := valueToSell + if !coinToSell.IsBaseCoin() { if coinFrom.Reserve().Cmp(commissionInBaseCoin) < 0 { return nil, s.createError( From 15f7d71e58911bc29475b02d950ff311f8915bc8 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 6 Oct 2020 16:46:32 +0300 Subject: [PATCH 364/426] set MaxCallRecvMsgSize to v2 --- api/v2/v2.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v2/v2.go b/api/v2/v2.go index 6b45bd3a5..6269f2b7f 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -77,7 +77,7 @@ func Run(srv *service.Service, addrGRPC, addrApi string, logger log.Logger) erro ) opts := []grpc.DialOption{ grpc.WithInsecure(), - grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(50000000)), + grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(200000000)), } err = gw.RegisterApiServiceHandlerFromEndpoint(ctx, gwmux, addrGRPC, opts) if err != nil { From f86b102dbbfd2d2d09e76d6b70f1f852067ce57b Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 7 Oct 2020 13:48:47 +0300 Subject: [PATCH 365/426] fix app halted --- core/minter/minter.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index f8ac94426..657a84ce8 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -142,10 +142,6 @@ func (app *Blockchain) InitChain(req abciTypes.RequestInitChain) abciTypes.Respo func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.ResponseBeginBlock { height := uint64(req.Header.Height) - if app.isApplicationHalted(height) { - panic(fmt.Sprintf("Application halted at height %d", height)) - } - app.StatisticData().PushStartBlock(&statistics.StartRequest{Height: int64(height), Now: time.Now(), HeaderTime: req.Header.Time}) app.stateDeliver.Lock() @@ -177,6 +173,10 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res } app.lock.Unlock() + if app.isApplicationHalted(height) { + panic(fmt.Sprintf("Application halted at height %d", height)) + } + // give penalty to Byzantine validators for _, byzVal := range req.ByzantineValidators { var address types.TmAddress From 2bb6f900ae04a42184553319a9f863ee1e0a499e Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 7 Oct 2020 17:42:51 +0300 Subject: [PATCH 366/426] fix minter_test.go --- core/minter/minter_test.go | 16 ++++++++-------- tests/byz_test.go | 11 +++++++---- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index 7a2d9d157..bd5349a05 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -45,8 +45,8 @@ func getPrivateKey() *ecdsa.PrivateKey { } func makeTestValidatorsAndCandidates(pubkeys []string, stake *big.Int) ([]types.Validator, []types.Candidate) { - vals := make([]types.Validator, len(pubkeys)) - cands := make([]types.Candidate, len(pubkeys)) + vals := make([]types.Validator, 0, len(pubkeys)) + cands := make([]types.Candidate, 0, len(pubkeys)) for i, val := range pubkeys { pkeyBytes, err := base64.StdEncoding.DecodeString(val) @@ -58,19 +58,19 @@ func makeTestValidatorsAndCandidates(pubkeys []string, stake *big.Int) ([]types. copy(pkey[:], pkeyBytes) addr := developers.Address - vals[i] = types.Validator{ + vals = append(vals, types.Validator{ TotalBipStake: stake.String(), PubKey: pkey, AccumReward: big.NewInt(0).String(), AbsentTimes: types.NewBitArray(24), - } + }) - cands[i] = types.Candidate{ + cands = append(cands, types.Candidate{ ID: uint64(i) + 1, RewardAddress: addr, OwnerAddress: crypto.PubkeyToAddress(getPrivateKey().PublicKey), ControlAddress: addr, - TotalBipStake: big.NewInt(1).String(), + TotalBipStake: stake.String(), PubKey: pkey, Commission: 100, Stakes: []types.Stake{ @@ -82,7 +82,7 @@ func makeTestValidatorsAndCandidates(pubkeys []string, stake *big.Int) ([]types. }, }, Status: candidates2.CandidateStatusOnline, - } + }) } return vals, cands @@ -93,7 +93,7 @@ func getTestGenesis(pv *privval.FilePV) func() (*types2.GenesisDoc, error) { appHash := [32]byte{} - validators, candidates := makeTestValidatorsAndCandidates([]string{base64.StdEncoding.EncodeToString(pv.Key.PubKey.Bytes()[5:])}, big.NewInt(10000000)) + validators, candidates := makeTestValidatorsAndCandidates([]string{base64.StdEncoding.EncodeToString(pv.Key.PubKey.Bytes()[5:])}, helpers.BipToPip(big.NewInt(1000))) appState := types.AppState{ TotalSlashed: "0", diff --git a/tests/byz_test.go b/tests/byz_test.go index d63c4f537..58b3b1462 100644 --- a/tests/byz_test.go +++ b/tests/byz_test.go @@ -2,8 +2,10 @@ package tests import ( "github.com/MinterTeam/minter-go-node/core/types" + "github.com/MinterTeam/minter-go-node/helpers" tmTypes "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto/ed25519" + "math/big" "testing" "time" ) @@ -11,8 +13,9 @@ import ( func TestBlockchain_ByzantineValidators(t *testing.T) { state := DefaultAppState() // generate default state + stake := helpers.BipToPip(big.NewInt(1000)).String() state.Validators = append(state.Validators, types.Validator{ - TotalBipStake: "10000", + TotalBipStake: stake, PubKey: types.Pubkey{1}, AccumReward: "10", AbsentTimes: nil, @@ -22,15 +25,15 @@ func TestBlockchain_ByzantineValidators(t *testing.T) { RewardAddress: types.Address{}, OwnerAddress: types.Address{}, ControlAddress: types.Address{}, - TotalBipStake: "10000", + TotalBipStake: stake, PubKey: types.Pubkey{1}, Commission: 10, Stakes: []types.Stake{ { Owner: types.Address{}, Coin: 0, - Value: "10000", - BipValue: "10000", + Value: stake, + BipValue: stake, }, }, Updates: nil, From fb1e3e0ed7db52e1b96ef8a98a9a65c9f70faa77 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 8 Oct 2020 09:12:48 +0300 Subject: [PATCH 367/426] fix creating the same coin symbol at one height --- core/state/coins/coins.go | 64 +++++++++++++++++++------ core/transaction/create_coin_test.go | 71 ++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 15 deletions(-) diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index dd46710d0..147878312 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -16,12 +16,22 @@ const ( mainPrefix = byte('q') infoPrefix = byte('i') symbolPrefix = byte('s') -) -const ( BaseVersion types.CoinVersion = 0 ) +var ( + baseModel = &Model{ + id: types.GetBaseCoinID(), + CSymbol: types.GetBaseCoin(), + CMaxSupply: helpers.BipToPip(big.NewInt(10000000000)), + info: &Info{ + Volume: big.NewInt(0), + Reserve: big.NewInt(0), + }, + } +) + type RCoins interface { Export(state *types.AppState) Exists(id types.CoinID) bool @@ -33,8 +43,9 @@ type RCoins interface { } type Coins struct { - list map[types.CoinID]*Model - dirty map[types.CoinID]struct{} + list map[types.CoinID]*Model + dirty map[types.CoinID]struct{} + symbolsList map[types.CoinSymbol]types.CoinID bus *bus.Bus iavl tree.MTree @@ -43,7 +54,12 @@ type Coins struct { } func NewCoins(stateBus *bus.Bus, iavl tree.MTree) (*Coins, error) { - coins := &Coins{bus: stateBus, iavl: iavl, list: map[types.CoinID]*Model{}, dirty: map[types.CoinID]struct{}{}} + coins := &Coins{ + bus: stateBus, iavl: iavl, + list: map[types.CoinID]*Model{}, + dirty: map[types.CoinID]struct{}{}, + symbolsList: map[types.CoinSymbol]types.CoinID{}, + } coins.bus.SetCoins(NewBus(coins)) return coins, nil @@ -101,6 +117,9 @@ func (c *Coins) Commit() error { } } + // clear list + c.symbolsList = make(map[types.CoinSymbol]types.CoinID) + return nil } @@ -125,6 +144,10 @@ func (c *Coins) ExistsBySymbol(symbol types.CoinSymbol) bool { return true } + if _, ok := c.getSymbolFromMap(symbol); ok { + return true + } + return c.getBySymbol(symbol) != nil } @@ -133,6 +156,10 @@ func (c *Coins) GetCoinBySymbol(symbol types.CoinSymbol, version types.CoinVersi return c.get(types.GetBaseCoinID()) } + if id, ok := c.getSymbolFromMap(symbol); ok { + return c.getFromMap(id) + } + coins := c.getBySymbol(symbol) if len(coins) == 0 { return nil @@ -211,6 +238,7 @@ func (c *Coins) Create(id types.CoinID, symbol types.CoinSymbol, name string, } c.setToMap(coin.id, coin) + c.setSymbolToMap(coin.id, coin.CSymbol) coin.SetReserve(reserve) coin.SetVolume(volume) @@ -262,16 +290,7 @@ func (c *Coins) ChangeOwner(symbol types.CoinSymbol, owner types.Address) { func (c *Coins) get(id types.CoinID) *Model { if id.IsBaseCoin() { - // TODO: refactor - return &Model{ - id: types.GetBaseCoinID(), - CSymbol: types.GetBaseCoin(), - CMaxSupply: helpers.BipToPip(big.NewInt(10000000000)), - info: &Info{ - Volume: big.NewInt(0), - Reserve: big.NewInt(0), - }, - } + return baseModel } if coin := c.getFromMap(id); coin != nil { @@ -401,6 +420,21 @@ func (c *Coins) setToMap(id types.CoinID, model *Model) { c.list[id] = model } +func (c *Coins) getSymbolFromMap(symbol types.CoinSymbol) (types.CoinID, bool) { + c.lock.RLock() + defer c.lock.RUnlock() + + id, ok := c.symbolsList[symbol] + return id, ok +} + +func (c *Coins) setSymbolToMap(id types.CoinID, symbol types.CoinSymbol) { + c.lock.Lock() + defer c.lock.Unlock() + + c.symbolsList[symbol] = id +} + func getSymbolCoinsPath(symbol types.CoinSymbol) []byte { path := append([]byte{mainPrefix}, []byte{symbolPrefix}...) return append(path, symbol.Bytes()...) diff --git a/core/transaction/create_coin_test.go b/core/transaction/create_coin_test.go index daf0b3ac9..7fca31595 100644 --- a/core/transaction/create_coin_test.go +++ b/core/transaction/create_coin_test.go @@ -737,3 +737,74 @@ func TestCreateCoinToInsufficientFundsForInitialReserve(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } } + +func TestCreateCoinToSameSymbolInOneBlock(t *testing.T) { + cState := getState() + coin := types.GetBaseCoinID() + + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + privateKey2, _ := crypto.GenerateKey() + addr2 := crypto.PubkeyToAddress(privateKey2.PublicKey) + + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + cState.Accounts.AddBalance(addr2, coin, helpers.BipToPip(big.NewInt(1000000))) + + toCreate := types.StrToCoinSymbol("TEST") + reserve := helpers.BipToPip(big.NewInt(10000)) + amount := helpers.BipToPip(big.NewInt(100)) + crr := uint32(50) + name := "My Test Coin" + + data := CreateCoinData{ + Name: name, + Symbol: toCreate, + InitialAmount: amount, + InitialReserve: reserve, + ConstantReserveRatio: crr, + MaxSupply: big.NewInt(0).Mul(amount, big.NewInt(10)), + } + + encodedData, err := rlp.EncodeToBytes(data) + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeCreateCoin, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != 0 { + t.Fatalf("Response code is not success. Error %s", response.Log) + } + + if err := tx.Sign(privateKey2); err != nil { + t.Fatal(err) + } + + encodedTx, err = rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response = RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) + if response.Code != code.CoinAlreadyExists { + t.Fatalf("Response code is not %d. Error %s", code.CoinAlreadyExists, response.Log) + } +} From 5509276d0dc82dff4741c6aa0c52ab9778bfc358 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 8 Oct 2020 09:41:54 +0300 Subject: [PATCH 368/426] fix coin volume --- core/state/state.go | 1 + legacy/coins/coins.go | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/core/state/state.go b/core/state/state.go index 452414d77..734d521b5 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -141,6 +141,7 @@ func (cs *CheckState) Export11To12(height uint64) types.AppState { frozenFundsState.Export(state, height, coinsMap) accountsState.Export(state, coinsMap) checksState.Export(state) + coinsState.Export(state) return *state } diff --git a/legacy/coins/coins.go b/legacy/coins/coins.go index 08f1b2b4d..08638f44b 100644 --- a/legacy/coins/coins.go +++ b/legacy/coins/coins.go @@ -8,6 +8,7 @@ import ( "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/rlp" "github.com/MinterTeam/minter-go-node/tree" + "math/big" "sort" "sync" ) @@ -104,6 +105,44 @@ func (c *Coins) getOrderedDirtyCoins() []types.CoinSymbol { func (c *Coins) Export(state *types.AppState) map[types.CoinSymbol]types.Coin { var coins []types.Coin + if len(state.Coins) != 0 { + for k, coin := range state.Coins { + // check coins' volume + volume := big.NewInt(0) + for _, ff := range state.FrozenFunds { + if ff.Coin == coin.ID { + volume.Add(volume, helpers.StringToBigInt(ff.Value)) + } + } + + for _, candidate := range state.Candidates { + for _, stake := range candidate.Stakes { + if stake.Coin == coin.ID { + volume.Add(volume, helpers.StringToBigInt(stake.Value)) + } + } + + for _, stake := range candidate.Updates { + if stake.Coin == coin.ID { + volume.Add(volume, helpers.StringToBigInt(stake.Value)) + } + } + } + + for _, account := range state.Accounts { + for _, bal := range account.Balance { + if bal.Coin == coin.ID { + volume.Add(volume, helpers.StringToBigInt(bal.Value)) + } + } + } + + state.Coins[k].Volume = volume.String() + } + + return nil + } + c.iavl.Iterate(func(key []byte, value []byte) bool { if key[0] == mainPrefix { if len(key[1:]) > types.CoinSymbolLength { From e558b8dd255b43534071498f5d4721bbd7019a43 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Thu, 8 Oct 2020 10:37:23 +0300 Subject: [PATCH 369/426] Update build scripts --- Makefile | 6 ------ scripts/dist.sh | 6 ------ 2 files changed, 12 deletions(-) diff --git a/Makefile b/Makefile index b227735a9..e7cc4318a 100644 --- a/Makefile +++ b/Makefile @@ -44,12 +44,6 @@ update_tools: @echo "--> Updating tools" @go get -u $(GOTOOLS) -#Run this from CI -get_vendor_deps: - @rm -rf vendor/ - @echo "--> Running dep" - @go mod vendor - #Run this locally. ensure_deps: @rm -rf vendor/ diff --git a/scripts/dist.sh b/scripts/dist.sh index 3507930af..ac3eff751 100644 --- a/scripts/dist.sh +++ b/scripts/dist.sh @@ -23,12 +23,6 @@ mkdir -p build/pkg GIT_COMMIT="$(git rev-parse --short=8 HEAD)" GIT_IMPORT="github.com/MinterTeam/minter-go-node/version" -# Make sure build tools are available. -make get_tools - -# Get VENDORED dependencies -make get_vendor_deps - #packr # Build! From 895ff6445e04dbcdcaa64c2929d949f9d4a0fde4 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Fri, 9 Oct 2020 13:00:35 +0300 Subject: [PATCH 370/426] fix coin search --- api/coin_info.go | 4 ++-- api/estimate_coin_buy.go | 4 ++-- api/estimate_coin_sell.go | 4 ++-- api/estimate_coin_sell_all.go | 4 ++-- api/v2/service/coin_info.go | 2 +- api/v2/service/estimate_coin_buy.go | 4 ++-- api/v2/service/estimate_coin_sell.go | 4 ++-- api/v2/service/estimate_coin_sell_all.go | 4 ++-- core/types/types.go | 10 ++++++++++ 9 files changed, 25 insertions(+), 15 deletions(-) diff --git a/api/coin_info.go b/api/coin_info.go index 726fc630d..eba1a5cca 100644 --- a/api/coin_info.go +++ b/api/coin_info.go @@ -33,9 +33,9 @@ func CoinInfo(coinSymbol *string, id *int, height int) (*CoinInfoResponse, error } if coinSymbol != nil { - coin = cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(*coinSymbol), types.GetVersionFromSymbol(*coinSymbol)) + coin = cState.Coins().GetCoinBySymbol(types.StrToCoinBaseSymbol(*coinSymbol), types.GetVersionFromSymbol(*coinSymbol)) if coin == nil { - return nil, rpctypes.RPCError{Code: 404, Message: "Coin not found"} + return nil, rpctypes.RPCError{Code: 404, Message: "Coin not found", Data: types.StrToCoinSymbol(*coinSymbol).String()} } } diff --git a/api/estimate_coin_buy.go b/api/estimate_coin_buy.go index 99d59bbed..a6caa9c49 100644 --- a/api/estimate_coin_buy.go +++ b/api/estimate_coin_buy.go @@ -26,12 +26,12 @@ func EstimateCoinBuy(coinToSell, coinToBuy string, valueToBuy *big.Int, height i cState.RLock() defer cState.RUnlock() - coinFrom := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToSell), types.GetVersionFromSymbol(coinToSell)) + coinFrom := cState.Coins().GetCoinBySymbol(types.StrToCoinBaseSymbol(coinToSell), types.GetVersionFromSymbol(coinToSell)) if coinFrom == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to sell not exists"} } - coinTo := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToBuy), types.GetVersionFromSymbol(coinToBuy)) + coinTo := cState.Coins().GetCoinBySymbol(types.StrToCoinBaseSymbol(coinToBuy), types.GetVersionFromSymbol(coinToBuy)) if coinTo == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to buy not exists"} } diff --git a/api/estimate_coin_sell.go b/api/estimate_coin_sell.go index 85e0dc199..ca447962e 100644 --- a/api/estimate_coin_sell.go +++ b/api/estimate_coin_sell.go @@ -26,12 +26,12 @@ func EstimateCoinSell(coinToSell, coinToBuy string, valueToSell *big.Int, height cState.RLock() defer cState.RUnlock() - coinFrom := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToSell), types.GetVersionFromSymbol(coinToSell)) + coinFrom := cState.Coins().GetCoinBySymbol(types.StrToCoinBaseSymbol(coinToSell), types.GetVersionFromSymbol(coinToSell)) if coinFrom == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to sell not exists"} } - coinTo := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToBuy), types.GetVersionFromSymbol(coinToBuy)) + coinTo := cState.Coins().GetCoinBySymbol(types.StrToCoinBaseSymbol(coinToBuy), types.GetVersionFromSymbol(coinToBuy)) if coinTo == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to buy not exists"} } diff --git a/api/estimate_coin_sell_all.go b/api/estimate_coin_sell_all.go index fb5df5d66..f42fdb654 100644 --- a/api/estimate_coin_sell_all.go +++ b/api/estimate_coin_sell_all.go @@ -25,12 +25,12 @@ func EstimateCoinSellAll(coinToSell, coinToBuy string, valueToSell *big.Int, hei cState.RLock() defer cState.RUnlock() - coinFrom := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToSell), types.GetVersionFromSymbol(coinToSell)) + coinFrom := cState.Coins().GetCoinBySymbol(types.StrToCoinBaseSymbol(coinToSell), types.GetVersionFromSymbol(coinToSell)) if coinFrom == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to sell not exists"} } - coinTo := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(coinToBuy), types.GetVersionFromSymbol(coinToBuy)) + coinTo := cState.Coins().GetCoinBySymbol(types.StrToCoinBaseSymbol(coinToBuy), types.GetVersionFromSymbol(coinToBuy)) if coinTo == nil { return nil, rpctypes.RPCError{Code: 404, Message: "Coin to buy not exists"} } diff --git a/api/v2/service/coin_info.go b/api/v2/service/coin_info.go index 359611042..a4fd519cf 100644 --- a/api/v2/service/coin_info.go +++ b/api/v2/service/coin_info.go @@ -23,7 +23,7 @@ func (s *Service) CoinInfo(ctx context.Context, req *pb.CoinInfoRequest) (*pb.Co cState.RLock() defer cState.RUnlock() - coin := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.Symbol), types.GetVersionFromSymbol(req.Symbol)) + coin := cState.Coins().GetCoinBySymbol(types.StrToCoinBaseSymbol(req.Symbol), types.GetVersionFromSymbol(req.Symbol)) if coin == nil { return nil, s.createError(status.New(codes.NotFound, "Coin not found"), transaction.EncodeError(code.NewCoinNotExists(req.Symbol, ""))) } diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index 362c2da00..8f3466ed0 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -31,7 +31,7 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe var coinToBuy types.CoinID if req.GetCoinToBuy() != "" { - symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), types.GetVersionFromSymbol(req.GetCoinToBuy())) + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinBaseSymbol(req.GetCoinToBuy()), types.GetVersionFromSymbol(req.GetCoinToBuy())) if symbol == nil { return nil, s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToBuy(), ""))) } @@ -45,7 +45,7 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe var coinToSell types.CoinID if req.GetCoinToSell() != "" { - symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), types.GetVersionFromSymbol(req.GetCoinToSell())) + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinBaseSymbol(req.GetCoinToSell()), types.GetVersionFromSymbol(req.GetCoinToSell())) if symbol == nil { return nil, s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToSell(), ""))) } diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index 86ed8b662..35827d647 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -31,7 +31,7 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell var coinToBuy types.CoinID if req.GetCoinToBuy() != "" { - symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), types.GetVersionFromSymbol(req.GetCoinToBuy())) + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinBaseSymbol(req.GetCoinToBuy()), types.GetVersionFromSymbol(req.GetCoinToBuy())) if symbol == nil { return nil, s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToBuy(), ""))) } @@ -45,7 +45,7 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell var coinToSell types.CoinID if req.GetCoinToSell() != "" { - symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), types.GetVersionFromSymbol(req.GetCoinToSell())) + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinBaseSymbol(req.GetCoinToSell()), types.GetVersionFromSymbol(req.GetCoinToSell())) if symbol == nil { return nil, s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToSell(), ""))) } diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index 38cdd150c..382ffac41 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -31,7 +31,7 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS var coinToBuy types.CoinID if req.GetCoinToBuy() != "" { - symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToBuy()), types.GetVersionFromSymbol(req.GetCoinToBuy())) + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinBaseSymbol(req.GetCoinToBuy()), types.GetVersionFromSymbol(req.GetCoinToBuy())) if symbol == nil { return nil, s.createError(status.New(codes.NotFound, "Coin to buy not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToBuy(), ""))) } @@ -45,7 +45,7 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS var coinToSell types.CoinID if req.GetCoinToSell() != "" { - symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinSymbol(req.GetCoinToSell()), types.GetVersionFromSymbol(req.GetCoinToSell())) + symbol := cState.Coins().GetCoinBySymbol(types.StrToCoinBaseSymbol(req.GetCoinToSell()), types.GetVersionFromSymbol(req.GetCoinToSell())) if symbol == nil { return nil, s.createError(status.New(codes.NotFound, "Coin to sell not exists"), transaction.EncodeError(code.NewCoinNotExists(req.GetCoinToSell(), ""))) } diff --git a/core/types/types.go b/core/types/types.go index 96870e610..d604e7628 100644 --- a/core/types/types.go +++ b/core/types/types.go @@ -177,6 +177,16 @@ func StrToCoinSymbol(s string) CoinSymbol { return symbol } +// StrToCoinBaseSymbol converts give string to a coin base symbol +func StrToCoinBaseSymbol(s string) CoinSymbol { + delimiter := strings.Index(s, "-") + if delimiter != -1 { + return StrToCoinSymbol(s[:delimiter]) + } + + return StrToCoinSymbol(s) +} + // GetVersionFromSymbol returns coin version extracted from symbol func GetVersionFromSymbol(s string) CoinVersion { parts := strings.Split(s, "-") From 1db401064cf6ffae7bc138a81140ac77d671a268 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Fri, 9 Oct 2020 13:01:40 +0300 Subject: [PATCH 371/426] fix --- api/coin_info.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/coin_info.go b/api/coin_info.go index eba1a5cca..fae90461e 100644 --- a/api/coin_info.go +++ b/api/coin_info.go @@ -35,7 +35,7 @@ func CoinInfo(coinSymbol *string, id *int, height int) (*CoinInfoResponse, error if coinSymbol != nil { coin = cState.Coins().GetCoinBySymbol(types.StrToCoinBaseSymbol(*coinSymbol), types.GetVersionFromSymbol(*coinSymbol)) if coin == nil { - return nil, rpctypes.RPCError{Code: 404, Message: "Coin not found", Data: types.StrToCoinSymbol(*coinSymbol).String()} + return nil, rpctypes.RPCError{Code: 404, Message: "Coin not found"} } } From 7c3a8069183172128a87d2843a32abc65483513a Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Fri, 9 Oct 2020 13:51:58 +0300 Subject: [PATCH 372/426] fix base coin model --- core/state/coins/coins.go | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index 147878312..6fe1c6869 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -20,18 +20,6 @@ const ( BaseVersion types.CoinVersion = 0 ) -var ( - baseModel = &Model{ - id: types.GetBaseCoinID(), - CSymbol: types.GetBaseCoin(), - CMaxSupply: helpers.BipToPip(big.NewInt(10000000000)), - info: &Info{ - Volume: big.NewInt(0), - Reserve: big.NewInt(0), - }, - } -) - type RCoins interface { Export(state *types.AppState) Exists(id types.CoinID) bool @@ -290,7 +278,15 @@ func (c *Coins) ChangeOwner(symbol types.CoinSymbol, owner types.Address) { func (c *Coins) get(id types.CoinID) *Model { if id.IsBaseCoin() { - return baseModel + return &Model{ + id: types.GetBaseCoinID(), + CSymbol: types.GetBaseCoin(), + CMaxSupply: helpers.BipToPip(big.NewInt(10000000000)), + info: &Info{ + Volume: big.NewInt(0), + Reserve: big.NewInt(0), + }, + } } if coin := c.getFromMap(id); coin != nil { From e4bf6493955fbe3a2a6ffeb10a351ef6e2ac4e60 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Fri, 9 Oct 2020 16:06:48 +0300 Subject: [PATCH 373/426] Update tests --- core/transaction/buy_coin_test.go | 105 +++++++++++++++++++++++++++--- core/transaction/delegate_test.go | 4 +- core/transaction/unbond_test.go | 4 +- core/types/appstate.go | 2 +- 4 files changed, 100 insertions(+), 15 deletions(-) diff --git a/core/transaction/buy_coin_test.go b/core/transaction/buy_coin_test.go index 55979b031..f17ebc517 100644 --- a/core/transaction/buy_coin_test.go +++ b/core/transaction/buy_coin_test.go @@ -29,6 +29,9 @@ func getState() *state.State { panic(err) } + s.Validators.Create(types.Pubkey{}, big.NewInt(1)) + s.Candidates.Create(types.Address{}, types.Address{}, types.Address{}, types.Pubkey{}, 10) + return s } @@ -47,6 +50,7 @@ func createTestCoin(stateDB *state.State) types.CoinID { stateDB.Coins.Create(id, getTestCoinSymbol(), "TEST COIN", volume, 10, reserve, big.NewInt(0).Mul(volume, big.NewInt(10)), nil) stateDB.App.SetCoinsCount(id.Uint32()) + stateDB.Accounts.AddBalance(types.Address{}, id, volume) return id } @@ -68,6 +72,17 @@ func createTestCoinWithOwner(stateDB *state.State, owner types.Address) types.Co return id } +func checkState(t *testing.T, cState *state.State) { + if _, err := cState.Commit(); err != nil { + t.Fatal(err) + } + + exportedState := cState.Export(1) + if err := exportedState.Verify(); err != nil { + t.Fatal(err) + } +} + func TestBuyCoinTxBaseToCustom(t *testing.T) { cState := getState() @@ -77,7 +92,9 @@ func TestBuyCoinTxBaseToCustom(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) + initBalance := helpers.BipToPip(big.NewInt(1000000)) + cState.Accounts.AddBalance(addr, coin, initBalance) + cState.Coins.AddVolume(coin, initBalance) toBuy := helpers.BipToPip(big.NewInt(10)) maxValToSell, _ := big.NewInt(0).SetString("159374246010000000000", 10) @@ -130,6 +147,8 @@ func TestBuyCoinTxBaseToCustom(t *testing.T) { if testBalance.Cmp(toBuy) != 0 { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", getTestCoinSymbol(), toBuy, testBalance) } + + checkState(t, cState) } func TestBuyCoinTxInsufficientFunds(t *testing.T) { @@ -184,6 +203,8 @@ func TestBuyCoinTxInsufficientFunds(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestBuyCoinTxEqualCoins(t *testing.T) { @@ -230,6 +251,8 @@ func TestBuyCoinTxEqualCoins(t *testing.T) { if response.Code != code.CrossConvert { t.Fatalf("Response code is not %d. Error %s", code.CrossConvert, response.Log) } + + checkState(t, cState) } func TestBuyCoinTxNotExistsBuyCoin(t *testing.T) { @@ -274,6 +297,8 @@ func TestBuyCoinTxNotExistsBuyCoin(t *testing.T) { if response.Code != code.CoinNotExists { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) } + + checkState(t, cState) } func TestBuyCoinTxNotExistsSellCoin(t *testing.T) { @@ -318,6 +343,8 @@ func TestBuyCoinTxNotExistsSellCoin(t *testing.T) { if response.Code != code.CoinNotExists { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) } + + checkState(t, cState) } func TestBuyCoinTxNotExistsGasCoin(t *testing.T) { @@ -364,6 +391,8 @@ func TestBuyCoinTxNotExistsGasCoin(t *testing.T) { if response.Code != code.CoinNotExists { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) } + + checkState(t, cState) } func TestBuyCoinTxNotGasCoin(t *testing.T) { @@ -374,13 +403,15 @@ func TestBuyCoinTxNotGasCoin(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - cState.Accounts.AddBalance(addr, coinToSellID, helpers.BipToPip(big.NewInt(1000))) + initBal := helpers.BipToPip(big.NewInt(1000)) + cState.Accounts.AddBalance(addr, coinToSellID, initBal) + cState.Coins.AddVolume(coinToSellID, initBal) data := BuyCoinData{ CoinToBuy: types.GetBaseCoinID(), ValueToBuy: big.NewInt(1), CoinToSell: coinToSellID, - MaximumValueToSell: big.NewInt(10004502852067863), + MaximumValueToSell: big.NewInt(10100004545002879), } encodedData, err := rlp.EncodeToBytes(data) @@ -414,6 +445,8 @@ func TestBuyCoinTxNotGasCoin(t *testing.T) { if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) } + + checkState(t, cState) } func TestBuyCoinTxCustomToBase(t *testing.T) { @@ -424,7 +457,9 @@ func TestBuyCoinTxCustomToBase(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - cState.Accounts.AddBalance(addr, coinToSellID, helpers.BipToPip(big.NewInt(10000000))) + initBal := helpers.BipToPip(big.NewInt(10000000)) + cState.Accounts.AddBalance(addr, coinToSellID, initBal) + cState.Coins.AddVolume(coinToSellID, initBal) toBuy := helpers.BipToPip(big.NewInt(10)) maxValToSell, _ := big.NewInt(0).SetString("159374246010000000000", 10) @@ -467,7 +502,7 @@ func TestBuyCoinTxCustomToBase(t *testing.T) { t.Fatalf("Response code is not 0. Error %s", response.Log) } - targetBalance, _ := big.NewInt(0).SetString("9999998989954092563427063", 10) + targetBalance, _ := big.NewInt(0).SetString("9999897985363348906133281", 10) balance := cState.Accounts.GetBalance(addr, coinToSellID) if balance.Cmp(targetBalance) != 0 { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", coinToSellID.String(), targetBalance, balance) @@ -485,10 +520,12 @@ func TestBuyCoinTxCustomToBase(t *testing.T) { t.Fatalf("Target %s reserve is not correct. Expected %s, got %s", coinToSellID.String(), targetBalance, coinData.Reserve()) } - targetVolume, _ := big.NewInt(0).SetString("99998989954092563427063", 10) + targetVolume, _ := big.NewInt(0).SetString("10099897985363348906133281", 10) if coinData.Volume().Cmp(targetVolume) != 0 { t.Fatalf("Target %s volume is not correct. Expected %s, got %s", coinToSellID.String(), targetVolume, coinData.Volume()) } + + checkState(t, cState) } func TestBuyCoinReserveUnderflow(t *testing.T) { @@ -499,10 +536,12 @@ func TestBuyCoinReserveUnderflow(t *testing.T) { privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) - cState.Accounts.AddBalance(addr, coinToSellID, helpers.BipToPip(big.NewInt(10000000))) + initBal := helpers.BipToPip(big.NewInt(10000000)) + cState.Accounts.AddBalance(addr, coinToSellID, initBal) + cState.Coins.AddVolume(coinToSellID, initBal) toBuy := helpers.BipToPip(big.NewInt(99000)) - maxValToSell, _ := big.NewInt(0).SetString("36904896537720035723223", 10) + maxValToSell, _ := big.NewInt(0).SetString("3727394550309723608045536", 10) data := BuyCoinData{ CoinToBuy: types.GetBaseCoinID(), ValueToBuy: toBuy, @@ -541,6 +580,8 @@ func TestBuyCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } func TestBuyCoinTxBaseToCustomBaseCommission(t *testing.T) { @@ -558,7 +599,9 @@ func TestBuyCoinTxBaseToCustomBaseCommission(t *testing.T) { coinToBuyID, initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToBuy) privateKey, addr := getAccount() + cState.Accounts.AddBalance(addr, coinToSell, initialBalance) + cState.Coins.AddVolume(coinToSell, initialBalance) tx := createBuyCoinTx(coinToSell, coinToBuyID, gasCoin, toBuy, 1) if err := tx.Sign(privateKey); err != nil { @@ -605,6 +648,8 @@ func TestBuyCoinTxBaseToCustomBaseCommission(t *testing.T) { if coinData.Volume().Cmp(estimatedSupply) != 0 { t.Fatalf("Wrong coin supply") } + + checkState(t, cState) } func TestBuyCoinTxCustomToBaseBaseCommission(t *testing.T) { @@ -623,8 +668,13 @@ func TestBuyCoinTxCustomToBaseBaseCommission(t *testing.T) { coinToSellID, initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToSell) privateKey, addr := getAccount() + cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) + cState.Coins.AddVolume(coinToSellID, initialBalance) + initialVolume.Add(initialVolume, initialBalance) + cState.Accounts.AddBalance(addr, gasCoin, initialGasBalance) + cState.Coins.AddVolume(gasCoin, initialGasBalance) tx := createBuyCoinTx(coinToSellID, coinToBuy, gasCoin, toBuy, 1) if err := tx.Sign(privateKey); err != nil { @@ -670,6 +720,8 @@ func TestBuyCoinTxCustomToBaseBaseCommission(t *testing.T) { if coinData.Volume().Cmp(estimatedSupply) != 0 { t.Fatalf("Wrong coin supply") } + + checkState(t, cState) } func TestBuyCoinTxCustomToCustomBaseCommission(t *testing.T) { @@ -691,6 +743,9 @@ func TestBuyCoinTxCustomToCustomBaseCommission(t *testing.T) { privateKey, addr := getAccount() cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) + cState.Coins.AddVolume(coinToSellID, initialBalance) + initialVolume1.Add(initialVolume1, initialBalance) + cState.Accounts.AddBalance(addr, gasCoin, initialGasBalance) tx := createBuyCoinTx(coinToSellID, coinToBuyID, gasCoin, toBuy, 1) @@ -739,6 +794,8 @@ func TestBuyCoinTxCustomToCustomBaseCommission(t *testing.T) { if coinData.Volume().Cmp(estimatedSupply) != 0 { t.Fatalf("Wrong coin supply") } + + checkState(t, cState) } func TestBuyCoinTxBaseToCustomCustomCommission(t *testing.T) { @@ -758,6 +815,8 @@ func TestBuyCoinTxBaseToCustomCustomCommission(t *testing.T) { privateKey, addr := getAccount() cState.Accounts.AddBalance(addr, coinToSell, initialBalance) cState.Accounts.AddBalance(addr, coinToBuyID, initialGasBalance) + cState.Coins.AddVolume(coinToBuyID, initialGasBalance) + initialVolume.Add(initialVolume, initialGasBalance) tx := createBuyCoinTx(coinToSell, coinToBuyID, coinToBuyID, toBuy, 1) if err := tx.Sign(privateKey); err != nil { @@ -810,6 +869,8 @@ func TestBuyCoinTxBaseToCustomCustomCommission(t *testing.T) { if coinData.Volume().Cmp(estimatedSupply) != 0 { t.Fatalf("Wrong coin supply. Expected %s, got %s", estimatedSupply.String(), coinData.Volume().String()) } + + checkState(t, cState) } func TestBuyCoinTxCustomToBaseCustomCommission(t *testing.T) { @@ -827,6 +888,8 @@ func TestBuyCoinTxCustomToBaseCustomCommission(t *testing.T) { privateKey, addr := getAccount() cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) + cState.Coins.AddVolume(coinToSellID, initialBalance) + initialVolume.Add(initialVolume, initialBalance) tx := createBuyCoinTx(coinToSellID, coinToBuy, coinToSellID, toBuy, 1) if err := tx.Sign(privateKey); err != nil { @@ -877,6 +940,8 @@ func TestBuyCoinTxCustomToBaseCustomCommission(t *testing.T) { t.Fatalf("Wrong coin supply. Expected %s, got %s", estimatedSupply.String(), coinData.Volume().String()) } } + + checkState(t, cState) } func TestBuyCoinTxCustomToCustomCustom1Commission(t *testing.T) { @@ -895,6 +960,8 @@ func TestBuyCoinTxCustomToCustomCustom1Commission(t *testing.T) { privateKey, addr := getAccount() cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) + cState.Coins.AddVolume(coinToSellID, initialBalance) + initialVolume1.Add(initialVolume1, initialBalance) tx := createBuyCoinTx(coinToSellID, coinToBuyID, coinToSellID, toBuy, 1) if err := tx.Sign(privateKey); err != nil { @@ -964,6 +1031,8 @@ func TestBuyCoinTxCustomToCustomCustom1Commission(t *testing.T) { t.Fatalf("Wrong coin supply") } } + + checkState(t, cState) } func TestBuyCoinTxCustomToCustomCustom2Commission(t *testing.T) { @@ -983,7 +1052,12 @@ func TestBuyCoinTxCustomToCustomCustom2Commission(t *testing.T) { privateKey, addr := getAccount() cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) + cState.Coins.AddVolume(coinToSellID, initialBalance) + initialVolume1.Add(initialVolume1, initialBalance) + cState.Accounts.AddBalance(addr, coinToBuyID, initialGasBalance) + cState.Coins.AddVolume(coinToBuyID, initialGasBalance) + initialVolume2.Add(initialVolume2, initialGasBalance) tx := createBuyCoinTx(coinToSellID, coinToBuyID, coinToBuyID, toBuy, 1) if err := tx.Sign(privateKey); err != nil { @@ -1055,6 +1129,8 @@ func TestBuyCoinTxCustomToCustomCustom2Commission(t *testing.T) { t.Fatalf("Wrong coin supply") } } + + checkState(t, cState) } func TestBuyCoinTxToCoinSupplyOverflow(t *testing.T) { @@ -1078,6 +1154,8 @@ func TestBuyCoinTxToCoinSupplyOverflow(t *testing.T) { if response.Code != code.CoinSupplyOverflow { t.Fatalf("Response code is not %d. Error %s", code.CoinSupplyOverflow, response.Log) } + + checkState(t, cState) } func TestBuyCoinTxToMaximumValueToSellReached(t *testing.T) { @@ -1087,6 +1165,7 @@ func TestBuyCoinTxToMaximumValueToSellReached(t *testing.T) { valueToBuy := big.NewInt(2e18) cState.Accounts.AddBalance(addr, sellCoinID, valueToBuy) + cState.Coins.AddVolume(sellCoinID, valueToBuy) data := BuyCoinData{ CoinToBuy: coinToBuyID, @@ -1126,6 +1205,7 @@ func TestBuyCoinTxToMaximumValueToSellReached(t *testing.T) { } cState.Accounts.AddBalance(addr, coinToBuyID, helpers.BipToPip(big.NewInt(100000))) + cState.Coins.AddVolume(coinToBuyID, helpers.BipToPip(big.NewInt(100000))) data.CoinToBuy = sellCoinID data.CoinToSell = coinToBuyID @@ -1208,6 +1288,8 @@ func TestBuyCoinTxToMaximumValueToSellReached(t *testing.T) { if response.Code != code.MaximumValueToSellReached { t.Fatalf("Response code is not %d. Error %s", code.MaximumValueToSellReached, response.Log) } + + checkState(t, cState) } func TestBuyCoinTxToCoinReserveNotSufficient(t *testing.T) { @@ -1219,10 +1301,10 @@ func TestBuyCoinTxToCoinReserveNotSufficient(t *testing.T) { cState.App.GetNextCoinID(), types.StrToCoinSymbol("TEST9"), "TEST COIN", - helpers.BipToPip(big.NewInt(100000)), + helpers.BipToPip(big.NewInt(5000000)), 10, helpers.BipToPip(big.NewInt(100000)), - helpers.BipToPip(big.NewInt(1000000)), + helpers.BipToPip(big.NewInt(10000000)), nil, ) @@ -1303,6 +1385,8 @@ func TestBuyCoinTxToCoinReserveNotSufficient(t *testing.T) { if response.Code != code.CoinReserveNotSufficient { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveNotSufficient, response.Log) } + + checkState(t, cState) } func createBuyCoinTx(sellCoin, buyCoin, gasCoin types.CoinID, valueToBuy *big.Int, nonce uint64) *Transaction { @@ -1351,6 +1435,7 @@ func createTestCoinWithSymbol(stateDB *state.State, symbol types.CoinSymbol) (ty id := stateDB.App.GetNextCoinID() stateDB.Coins.Create(id, symbol, "TEST COIN", volume, crr, reserve, big.NewInt(0).Mul(volume, big.NewInt(10)), nil) stateDB.App.SetCoinsCount(id.Uint32()) + stateDB.Accounts.AddBalance(types.Address{}, id, volume) return id, big.NewInt(0).Set(volume), big.NewInt(0).Set(reserve), crr } diff --git a/core/transaction/delegate_test.go b/core/transaction/delegate_test.go index 8c8595e1f..46cce4f2b 100644 --- a/core/transaction/delegate_test.go +++ b/core/transaction/delegate_test.go @@ -254,10 +254,10 @@ func TestDelegateTxToPositiveStake(t *testing.T) { } } -func TestDelegateTxToNonExistenCandidate(t *testing.T) { +func TestDelegateTxToNonExistCandidate(t *testing.T) { cState := getState() - pubkey := types.Pubkey{0} + pubkey := types.Pubkey{1} privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() diff --git a/core/transaction/unbond_test.go b/core/transaction/unbond_test.go index 4c64fb6dc..2c99badbd 100644 --- a/core/transaction/unbond_test.go +++ b/core/transaction/unbond_test.go @@ -310,9 +310,9 @@ func TestUnbondTxToNotExistenCoin(t *testing.T) { } } -func TestUnbondTxToNotExistenCandidate(t *testing.T) { +func TestUnbondTxToNotExistCandidate(t *testing.T) { cState := getState() - pubkey := types.Pubkey{0} + pubkey := types.Pubkey{1} privateKey, _ := crypto.GenerateKey() coin := types.GetBaseCoinID() value := helpers.BipToPip(big.NewInt(100)) diff --git a/core/types/appstate.go b/core/types/appstate.go index c438a5b0d..9fc009844 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -174,7 +174,7 @@ func (s *AppState) Verify() error { } if volume.Cmp(helpers.StringToBigInt(coin.Volume)) != 0 { - return fmt.Errorf("wrong coin %s volume", coin.Symbol.String()) + return fmt.Errorf("wrong coin %s volume (%s)", coin.Symbol.String(), big.NewInt(0).Sub(volume, helpers.StringToBigInt(coin.Volume))) } } From b0cb19575b1c4ab210ced80384e6d04bd5587520 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Fri, 9 Oct 2020 16:09:08 +0300 Subject: [PATCH 374/426] Fix typos in tests --- core/transaction/create_multisig_test.go | 2 +- core/transaction/declare_candidacy_test.go | 4 ++-- core/transaction/delegate_test.go | 2 +- core/transaction/edit_candidate_public_key_test.go | 2 +- core/transaction/edit_candidate_test.go | 2 +- core/transaction/edit_multisig_test.go | 2 +- core/transaction/sell_coin_test.go | 2 +- core/transaction/set_halt_block_test.go | 2 +- core/transaction/switch_candidate_status_test.go | 2 +- core/transaction/unbond_test.go | 4 ++-- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/core/transaction/create_multisig_test.go b/core/transaction/create_multisig_test.go index 1eddad884..eb341eb58 100644 --- a/core/transaction/create_multisig_test.go +++ b/core/transaction/create_multisig_test.go @@ -265,7 +265,7 @@ func TestCreateExistingMultisigTx(t *testing.T) { } } -func TestCreateMultisigOwnersTxToNonExistenAddress(t *testing.T) { +func TestCreateMultisigOwnersTxToNonExistAddress(t *testing.T) { cState := getState() addr := types.Address{0} diff --git a/core/transaction/declare_candidacy_test.go b/core/transaction/declare_candidacy_test.go index 1b0fd623c..6969cedb5 100644 --- a/core/transaction/declare_candidacy_test.go +++ b/core/transaction/declare_candidacy_test.go @@ -262,7 +262,7 @@ func TestDeclareCandidacyTxWithBlockPybKey(t *testing.T) { } } -func TestDeclareCandidacyToNonExistenCoin(t *testing.T) { +func TestDeclareCandidacyToNonExistCoin(t *testing.T) { cState := getState() privateKey, _ := crypto.GenerateKey() @@ -317,7 +317,7 @@ func TestDeclareCandidacyToNonExistenCoin(t *testing.T) { } } -func TestDeclareCandidacyToExistenCandidate(t *testing.T) { +func TestDeclareCandidacyToExistCandidate(t *testing.T) { cState := getState() privateKey, _ := crypto.GenerateKey() diff --git a/core/transaction/delegate_test.go b/core/transaction/delegate_test.go index 46cce4f2b..c2c2d6b70 100644 --- a/core/transaction/delegate_test.go +++ b/core/transaction/delegate_test.go @@ -160,7 +160,7 @@ func TestDelegateTxWithWatchlist(t *testing.T) { } } -func TestDelegateTxToNonExistenCoin(t *testing.T) { +func TestDelegateTxToNonExistCoin(t *testing.T) { cState := getState() pubkey := createTestCandidate(cState) diff --git a/core/transaction/edit_candidate_public_key_test.go b/core/transaction/edit_candidate_public_key_test.go index ebddb5924..8c6b68ede 100644 --- a/core/transaction/edit_candidate_public_key_test.go +++ b/core/transaction/edit_candidate_public_key_test.go @@ -281,7 +281,7 @@ func TestEditCandidatePublicKeyTxToGasCoinReserveUnderflow(t *testing.T) { } } -func TestEditCandidatePublicKeyToNotExistenCandidate(t *testing.T) { +func TestEditCandidatePublicKeyToNotExistCandidate(t *testing.T) { cState := getState() privateKey, _ := crypto.GenerateKey() diff --git a/core/transaction/edit_candidate_test.go b/core/transaction/edit_candidate_test.go index 09989f6c1..18fefc994 100644 --- a/core/transaction/edit_candidate_test.go +++ b/core/transaction/edit_candidate_test.go @@ -95,7 +95,7 @@ func TestEditCandidateTx(t *testing.T) { } } -func TestEditCandidateTxToNonExistenCandidate(t *testing.T) { +func TestEditCandidateTxToNonExistCandidate(t *testing.T) { cState := getState() privateKey, _ := crypto.GenerateKey() diff --git a/core/transaction/edit_multisig_test.go b/core/transaction/edit_multisig_test.go index 028722600..2647f330d 100644 --- a/core/transaction/edit_multisig_test.go +++ b/core/transaction/edit_multisig_test.go @@ -98,7 +98,7 @@ func TestEditMultisigTx(t *testing.T) { } } -func TestEditMultisigTxToNonExistenAddress(t *testing.T) { +func TestEditMultisigTxToNonExistAddress(t *testing.T) { cState := getState() addr := types.Address{0} diff --git a/core/transaction/sell_coin_test.go b/core/transaction/sell_coin_test.go index 0df5e019e..513f6bc57 100644 --- a/core/transaction/sell_coin_test.go +++ b/core/transaction/sell_coin_test.go @@ -887,7 +887,7 @@ func TestSellCoinTxEqualCoins(t *testing.T) { } } -func TestSellCoinTxToNonExistenCoins(t *testing.T) { +func TestSellCoinTxToNonExistCoins(t *testing.T) { cState := getState() coinID := createTestCoin(cState) privateKey, _ := crypto.GenerateKey() diff --git a/core/transaction/set_halt_block_test.go b/core/transaction/set_halt_block_test.go index 2a9cb9c52..48432aa96 100644 --- a/core/transaction/set_halt_block_test.go +++ b/core/transaction/set_halt_block_test.go @@ -212,7 +212,7 @@ func TestSetHaltBlockTxWithWrongOwnership(t *testing.T) { } } -func TestSetHaltBlockTxToNonExistenCandidate(t *testing.T) { +func TestSetHaltBlockTxToNonExistCandidate(t *testing.T) { cState, err := state.NewState(500000, db.NewMemDB(), nil, 1, 1) if err != nil { t.Fatalf("Cannot load state. Error %s", err) diff --git a/core/transaction/switch_candidate_status_test.go b/core/transaction/switch_candidate_status_test.go index 0b68f4427..6a205906e 100644 --- a/core/transaction/switch_candidate_status_test.go +++ b/core/transaction/switch_candidate_status_test.go @@ -140,7 +140,7 @@ func TestSetCandidateOffTx(t *testing.T) { } } -func TestSwitchCandidateStatusTxToNonExistenCandidate(t *testing.T) { +func TestSwitchCandidateStatusTxToNonExistCandidate(t *testing.T) { cState := getState() privateKey, _ := crypto.GenerateKey() diff --git a/core/transaction/unbond_test.go b/core/transaction/unbond_test.go index 2c99badbd..9224255f8 100644 --- a/core/transaction/unbond_test.go +++ b/core/transaction/unbond_test.go @@ -267,7 +267,7 @@ func TestUnbondTxToDecodeError(t *testing.T) { } } -func TestUnbondTxToNotExistenCoin(t *testing.T) { +func TestUnbondTxToNotExistCoin(t *testing.T) { cState := getState() pubkey := createTestCandidate(cState) privateKey, _ := crypto.GenerateKey() @@ -353,7 +353,7 @@ func TestUnbondTxToNotExistCandidate(t *testing.T) { } } -func TestUnbondTxToNotExistenStake(t *testing.T) { +func TestUnbondTxToNotExistStake(t *testing.T) { cState := getState() pubkey := createTestCandidate(cState) privateKey, _ := crypto.GenerateKey() From 5346a1cc660761d9f12db20b410ff88906dc5260 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 9 Oct 2020 17:11:43 +0300 Subject: [PATCH 375/426] upgrade events --- core/events/store.go | 18 +++-- core/events/store_test.go | 159 +++++++++++++++++++++++++++++--------- core/events/types.go | 44 +++++------ 3 files changed, 156 insertions(+), 65 deletions(-) diff --git a/core/events/store.go b/core/events/store.go index 30d3b53ba..f8bfed745 100644 --- a/core/events/store.go +++ b/core/events/store.go @@ -19,8 +19,8 @@ type eventsStore struct { sync.RWMutex db db.DB pending pendingEvents - idPubKey map[uint16]string - pubKeyID map[string]uint16 + idPubKey map[uint16][32]byte + pubKeyID map[[32]byte]uint16 idAddress map[uint32][20]byte addressID map[[20]byte]uint32 } @@ -46,14 +46,14 @@ func NewEventsStore(db db.DB) IEventsDB { RWMutex: sync.RWMutex{}, db: db, pending: pendingEvents{}, - idPubKey: make(map[uint16]string), - pubKeyID: make(map[string]uint16), + idPubKey: make(map[uint16][32]byte), + pubKeyID: make(map[[32]byte]uint16), idAddress: make(map[uint32][20]byte), addressID: make(map[[20]byte]uint32), } } -func (store *eventsStore) cachePubKey(id uint16, key string) { +func (store *eventsStore) cachePubKey(id uint16, key [32]byte) { store.idPubKey[id] = key store.pubKeyID[key] = id } @@ -157,7 +157,7 @@ func (store *eventsStore) saveAddress(address [20]byte) uint32 { func (store *eventsStore) savePubKey(validatorPubKey [32]byte) uint16 { - key := string(validatorPubKey[:]) + key := validatorPubKey if id, ok := store.pubKeyID[key]; ok { return id } @@ -177,11 +177,13 @@ func (store *eventsStore) savePubKey(validatorPubKey [32]byte) uint16 { func (store *eventsStore) loadPubKeys() { if count, _ := store.db.Get([]byte(pubKeysCountKey)); len(count) > 0 { for id := uint16(0); id < binary.BigEndian.Uint16(count); id++ { - pubKey, err := store.db.Get(append([]byte(pubKeyPrefix), uint16ToBytes(id)...)) + key, err := store.db.Get(append([]byte(pubKeyPrefix), uint16ToBytes(id)...)) if err != nil { panic(err) } - store.cachePubKey(id, string(pubKey)) + var pubKey [32]byte + copy(pubKey[:], key) + store.cachePubKey(id, pubKey) } } } diff --git a/core/events/store_test.go b/core/events/store_test.go index 076023153..867676116 100644 --- a/core/events/store_test.go +++ b/core/events/store_test.go @@ -1,9 +1,8 @@ package events import ( - "encoding/hex" + "github.com/MinterTeam/minter-go-node/core/types" db "github.com/tendermint/tm-db" - "math/big" "testing" ) @@ -11,46 +10,61 @@ func TestIEventsDB(t *testing.T) { store := NewEventsStore(db.NewMemDB()) { - amount, _ := big.NewInt(0).SetString("111497225000000000000", 10) event := &RewardEvent{ Role: RoleDevelopers.String(), - Address: [20]byte{}, - Amount: amount.String(), - ValidatorPubKey: [32]byte{}, + Address: types.HexToAddress("Mx04bea23efb744dc93b4fda4c20bf4a21c6e195f1"), + Amount: "111497225000000000000", + ValidatorPubKey: types.HexToPubkey("Mp9e13f2f5468dd782b316444fbd66595e13dba7d7bd3efa1becd50b42045f58c6"), } - bytesAddress, err := hex.DecodeString("Mx04bea23efb744dc93b4fda4c20bf4a21c6e195f1"[2:]) - if err != nil { - t.Fatal(err) - } - copy(event.Address[:], bytesAddress) - hexPubKey, err := hex.DecodeString("Mp9e13f2f5468dd782b316444fbd66595e13dba7d7bd3efa1becd50b42045f58c6"[2:]) - if err != nil { - t.Fatal(err) + store.AddEvent(12, event) + } + { + event := &StakeKickEvent{ + Coin: 1, + Address: types.HexToAddress("Mx18467bbb64a8edf890201d526c35957d82be3d95"), + Amount: "891977800000000000000", + ValidatorPubKey: types.HexToPubkey("Mp738da41ba6a7b7d69b7294afa158b89c5a1b410cbf0c2443c85c5fe24ad1dd1c"), } - copy(event.ValidatorPubKey[:], hexPubKey) store.AddEvent(12, event) } + err := store.CommitEvents() + if err != nil { + t.Fatal(err) + } + { - amount, _ := big.NewInt(0).SetString("891977800000000000000", 10) - event := &RewardEvent{ - Role: RoleValidator.String(), - Address: [20]byte{}, - Amount: amount.String(), - ValidatorPubKey: [32]byte{}, + event := &UnbondEvent{ + Coin: 1, + Address: types.HexToAddress("Mx18467bbb64a8edf890201d526c35957d82be3d91"), + Amount: "891977800000000000001", + ValidatorPubKey: types.HexToPubkey("Mp738da41ba6a7b7d69b7294afa158b89c5a1b410cbf0c2443c85c5fe24ad1dd11"), } - bytesAddress, err := hex.DecodeString("Mx18467bbb64a8edf890201d526c35957d82be3d95"[2:]) - if err != nil { - t.Fatal(err) + store.AddEvent(14, event) + } + { + event := &UnbondEvent{ + Coin: 2, + Address: types.HexToAddress("Mx18467bbb64a8edf890201d526c35957d82be3d92"), + Amount: "891977800000000000002", + ValidatorPubKey: types.HexToPubkey("Mp738da41ba6a7b7d69b7294afa158b89c5a1b410cbf0c2443c85c5fe24ad1dd12"), } - copy(event.Address[:], bytesAddress) - hexPubKey, err := hex.DecodeString("Mp738da41ba6a7b7d69b7294afa158b89c5a1b410cbf0c2443c85c5fe24ad1dd1c"[2:]) - if err != nil { - t.Fatal(err) + store.AddEvent(14, event) + } + err = store.CommitEvents() + if err != nil { + t.Fatal(err) + } + + { + event := &SlashEvent{ + Coin: 10, + Address: types.HexToAddress("Mx18467bbb64a8edf890201d526c35957d82be3d10"), + Amount: "891977800000000000010", + ValidatorPubKey: types.HexToPubkey("Mp738da41ba6a7b7d69b7294afa158b89c5a1b410cbf0c2443c85c5fe24ad1dd10"), } - copy(event.ValidatorPubKey[:], hexPubKey) - store.AddEvent(12, event) + store.AddEvent(11, event) } - err := store.CommitEvents() + err = store.CommitEvents() if err != nil { t.Fatal(err) } @@ -58,23 +72,98 @@ func TestIEventsDB(t *testing.T) { loadEvents := store.LoadEvents(12) if len(loadEvents) != 2 { - t.Fatal("count of events not equal 2") + t.Fatalf("count of events not equal 2, got %d", len(loadEvents)) } + if loadEvents[0].Type() != TypeRewardEvent { + t.Fatal("invalid event type") + } if loadEvents[0].(*RewardEvent).Amount != "111497225000000000000" { t.Fatal("invalid Amount") } - if loadEvents[0].(*RewardEvent).Address.String() != "Mx04bea23efb744dc93b4fda4c20bf4a21c6e195f1" { t.Fatal("invalid Address") } + if loadEvents[0].(*RewardEvent).ValidatorPubKey.String() != "Mp9e13f2f5468dd782b316444fbd66595e13dba7d7bd3efa1becd50b42045f58c6" { + t.Fatal("invalid PubKey") + } + if loadEvents[0].(*RewardEvent).Role != RoleDevelopers.String() { + t.Fatal("invalid Role") + } + + if loadEvents[1].Type() != TypeStakeKickEvent { + t.Fatal("invalid event type") + } + if loadEvents[1].(*StakeKickEvent).Amount != "891977800000000000000" { + t.Fatal("invalid Amount") + } + if loadEvents[1].(*StakeKickEvent).Address.String() != "Mx18467bbb64a8edf890201d526c35957d82be3d95" { + t.Fatal("invalid Address") + } + if loadEvents[1].(*StakeKickEvent).ValidatorPubKey.String() != "Mp738da41ba6a7b7d69b7294afa158b89c5a1b410cbf0c2443c85c5fe24ad1dd1c" { + t.Fatal("invalid PubKey") + } + if loadEvents[1].(*StakeKickEvent).Coin.Uint32() != 1 { + t.Fatal("invalid Coin") + } - if loadEvents[1].(*RewardEvent).Amount != "891977800000000000000" { + loadEvents = store.LoadEvents(14) + + if len(loadEvents) != 2 { + t.Fatal("count of events not equal 2") + } + + if loadEvents[0].Type() != TypeUnbondEvent { + t.Fatal("invalid event type") + } + if loadEvents[0].(*UnbondEvent).Amount != "891977800000000000001" { t.Fatal("invalid Amount") } + if loadEvents[0].(*UnbondEvent).Address.String() != "Mx18467bbb64a8edf890201d526c35957d82be3d91" { + t.Fatal("invalid Address") + } + if loadEvents[0].(*UnbondEvent).ValidatorPubKey.String() != "Mp738da41ba6a7b7d69b7294afa158b89c5a1b410cbf0c2443c85c5fe24ad1dd11" { + t.Fatal("invalid PubKey") + } + if loadEvents[0].(*UnbondEvent).Coin.Uint32() != 1 { + t.Fatal("invalid Coin") + } - if loadEvents[1].(*RewardEvent).Address.String() != "Mx18467bbb64a8edf890201d526c35957d82be3d95" { + if loadEvents[1].Type() != TypeUnbondEvent { + t.Fatal("invalid event type") + } + if loadEvents[1].(*UnbondEvent).Amount != "891977800000000000002" { + t.Fatal("invalid Amount") + } + if loadEvents[1].(*UnbondEvent).Address.String() != "Mx18467bbb64a8edf890201d526c35957d82be3d92" { t.Fatal("invalid Address") } + if loadEvents[1].(*UnbondEvent).ValidatorPubKey.String() != "Mp738da41ba6a7b7d69b7294afa158b89c5a1b410cbf0c2443c85c5fe24ad1dd12" { + t.Fatal("invalid PubKey") + } + if loadEvents[1].(*UnbondEvent).Coin.Uint32() != 2 { + t.Fatal("invalid Coin") + } + + loadEvents = store.LoadEvents(11) + + if len(loadEvents) != 1 { + t.Fatal("count of events not equal 1") + } + if loadEvents[0].Type() != TypeSlashEvent { + t.Fatal("invalid event type") + } + if loadEvents[0].(*SlashEvent).Amount != "891977800000000000010" { + t.Fatal("invalid Amount") + } + if loadEvents[0].(*SlashEvent).Address.String() != "Mx18467bbb64a8edf890201d526c35957d82be3d10" { + t.Fatal("invalid Address") + } + if loadEvents[0].(*SlashEvent).ValidatorPubKey.String() != "Mp738da41ba6a7b7d69b7294afa158b89c5a1b410cbf0c2443c85c5fe24ad1dd10" { + t.Fatal("invalid PubKey") + } + if loadEvents[0].(*SlashEvent).Coin.Uint32() != 10 { + t.Fatal("invalid Coin") + } } diff --git a/core/events/types.go b/core/events/types.go index caa4ccd80..fd8404791 100644 --- a/core/events/types.go +++ b/core/events/types.go @@ -37,7 +37,7 @@ type Event interface { } type compactEvent interface { - compile(pubKey string, address [20]byte) Event + compile(pubKey [32]byte, address [20]byte) Event addressID() uint32 pubKeyID() uint16 } @@ -90,10 +90,10 @@ type reward struct { PubKeyID uint16 } -func (r *reward) compile(pubKey string, address [20]byte) Event { +func (r *reward) compile(pubKey [32]byte, address [20]byte) Event { event := new(RewardEvent) - copy(event.ValidatorPubKey[:], pubKey) - copy(event.Address[:], address[:]) + event.ValidatorPubKey = pubKey + event.Address = address event.Role = r.Role.String() event.Amount = big.NewInt(0).SetBytes(r.Amount).String() return event @@ -147,15 +147,15 @@ func (re *RewardEvent) convert(pubKeyID uint16, addressID uint32) compactEvent { type slash struct { AddressID uint32 Amount []byte - Coin [10]byte + Coin uint32 PubKeyID uint16 } -func (s *slash) compile(pubKey string, address [20]byte) Event { +func (s *slash) compile(pubKey [32]byte, address [20]byte) Event { event := new(SlashEvent) - copy(event.ValidatorPubKey[:], pubKey) - copy(event.Address[:], address[:]) - copy(event.Coin.Bytes(), s.Coin[:]) + event.ValidatorPubKey = pubKey + event.Address = address + event.Coin = types.CoinID(s.Coin) event.Amount = big.NewInt(0).SetBytes(s.Amount).String() return event } @@ -198,7 +198,7 @@ func (se *SlashEvent) validatorPubKey() types.Pubkey { func (se *SlashEvent) convert(pubKeyID uint16, addressID uint32) compactEvent { result := new(slash) result.AddressID = addressID - copy(result.Coin[:], se.Coin.Bytes()) + result.Coin = se.Coin.Uint32() bi, _ := big.NewInt(0).SetString(se.Amount, 10) result.Amount = bi.Bytes() result.PubKeyID = pubKeyID @@ -208,15 +208,15 @@ func (se *SlashEvent) convert(pubKeyID uint16, addressID uint32) compactEvent { type unbond struct { AddressID uint32 Amount []byte - Coin [10]byte + Coin uint32 PubKeyID uint16 } -func (u *unbond) compile(pubKey string, address [20]byte) Event { +func (u *unbond) compile(pubKey [32]byte, address [20]byte) Event { event := new(UnbondEvent) - copy(event.ValidatorPubKey[:], pubKey) - copy(event.Address[:], address[:]) - copy(event.Coin.Bytes(), u.Coin[:]) + event.ValidatorPubKey = pubKey + event.Address = address + event.Coin = types.CoinID(u.Coin) event.Amount = big.NewInt(0).SetBytes(u.Amount).String() return event } @@ -259,7 +259,7 @@ func (ue *UnbondEvent) validatorPubKey() types.Pubkey { func (ue *UnbondEvent) convert(pubKeyID uint16, addressID uint32) compactEvent { result := new(unbond) result.AddressID = addressID - copy(result.Coin[:], ue.Coin.Bytes()) + result.Coin = ue.Coin.Uint32() bi, _ := big.NewInt(0).SetString(ue.Amount, 10) result.Amount = bi.Bytes() result.PubKeyID = pubKeyID @@ -269,15 +269,15 @@ func (ue *UnbondEvent) convert(pubKeyID uint16, addressID uint32) compactEvent { type stakeKick struct { AddressID uint32 Amount []byte - Coin [10]byte + Coin uint32 PubKeyID uint16 } -func (u *stakeKick) compile(pubKey string, address [20]byte) Event { +func (u *stakeKick) compile(pubKey [32]byte, address [20]byte) Event { event := new(StakeKickEvent) - copy(event.ValidatorPubKey[:], pubKey) - copy(event.Address[:], address[:]) - copy(event.Coin.Bytes(), u.Coin[:]) + event.ValidatorPubKey = pubKey + event.Address = address + event.Coin = types.CoinID(u.Coin) event.Amount = big.NewInt(0).SetBytes(u.Amount).String() return event } @@ -320,7 +320,7 @@ func (ue *StakeKickEvent) validatorPubKey() types.Pubkey { func (ue *StakeKickEvent) convert(pubKeyID uint16, addressID uint32) compactEvent { result := new(stakeKick) result.AddressID = addressID - copy(result.Coin[:], ue.Coin.Bytes()) + result.Coin = ue.Coin.Uint32() bi, _ := big.NewInt(0).SetString(ue.Amount, 10) result.Amount = bi.Bytes() result.PubKeyID = pubKeyID From 69768f4413e0dc8246aaae970f7d7c701af5d20c Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Mon, 12 Oct 2020 11:46:50 +0300 Subject: [PATCH 376/426] fix api v2 --- api/v2/service/address.go | 6 +++--- api/v2/service/addresses.go | 6 +++--- api/v2/service/candidate.go | 2 +- api/v2/service/data_encoder.go | 22 +++++++++++----------- api/v2/service/estimate_coin_buy.go | 2 +- api/v2/service/estimate_coin_sell.go | 2 +- api/v2/service/estimate_coin_sell_all.go | 2 +- core/transaction/buy_coin.go | 4 ++-- core/transaction/sell_all_coin.go | 4 ++-- core/transaction/sell_coin.go | 4 ++-- 10 files changed, 27 insertions(+), 27 deletions(-) diff --git a/api/v2/service/address.go b/api/v2/service/address.go index fbd22f787..dbcb68e88 100644 --- a/api/v2/service/address.go +++ b/api/v2/service/address.go @@ -57,7 +57,7 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr res.Balance = append(res.Balance, &pb.AddressBalance{ Coin: &pb.Coin{ Id: uint64(coin.Coin.ID), - Symbol: cState.Coins().GetCoin(coin.Coin.ID).Symbol().String(), + Symbol: cState.Coins().GetCoin(coin.Coin.ID).GetFullSymbol(), }, Value: coin.Value.String(), BipValue: customCoinBipBalance(coin.Coin.ID, coin.Value, cState).String(), @@ -96,7 +96,7 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr res.Delegated = append(res.Delegated, &pb.AddressDelegatedBalance{ Coin: &pb.Coin{ Id: uint64(coinID), - Symbol: cState.Coins().GetCoin(coinID).Symbol().String(), + Symbol: cState.Coins().GetCoin(coinID).GetFullSymbol(), }, Value: delegatedStake.Value.String(), DelegateBipValue: delegatedStake.BipValue.String(), @@ -124,7 +124,7 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr res.Total = append(res.Total, &pb.AddressBalance{ Coin: &pb.Coin{ Id: uint64(coinID), - Symbol: cState.Coins().GetCoin(coinID).Symbol().String(), + Symbol: cState.Coins().GetCoin(coinID).GetFullSymbol(), }, Value: stake.String(), BipValue: balance.String(), diff --git a/api/v2/service/addresses.go b/api/v2/service/addresses.go index 54a4ae2ca..cdd5982e4 100644 --- a/api/v2/service/addresses.go +++ b/api/v2/service/addresses.go @@ -59,7 +59,7 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. res.Balance = append(res.Balance, &pb.AddressBalance{ Coin: &pb.Coin{ Id: uint64(coin.Coin.ID), - Symbol: cState.Coins().GetCoin(coin.Coin.ID).Symbol().String(), + Symbol: cState.Coins().GetCoin(coin.Coin.ID).GetFullSymbol(), }, Value: coin.Value.String(), BipValue: customCoinBipBalance(coin.Coin.ID, coin.Value, cState).String(), @@ -98,7 +98,7 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. res.Delegated = append(res.Delegated, &pb.AddressDelegatedBalance{ Coin: &pb.Coin{ Id: uint64(coinID), - Symbol: cState.Coins().GetCoin(coinID).Symbol().String(), + Symbol: cState.Coins().GetCoin(coinID).GetFullSymbol(), }, Value: delegatedStake.Value.String(), DelegateBipValue: delegatedStake.BipValue.String(), @@ -126,7 +126,7 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. res.Total = append(res.Total, &pb.AddressBalance{ Coin: &pb.Coin{ Id: uint64(coinID), - Symbol: cState.Coins().GetCoin(coinID).Symbol().String(), + Symbol: cState.Coins().GetCoin(coinID).GetFullSymbol(), }, Value: stake.String(), BipValue: balance.String(), diff --git a/api/v2/service/candidate.go b/api/v2/service/candidate.go index 60ae3aaf9..1b77ccaea 100644 --- a/api/v2/service/candidate.go +++ b/api/v2/service/candidate.go @@ -72,7 +72,7 @@ func makeResponseCandidate(state *state.CheckState, c *candidates.Candidate, inc Owner: stake.Owner.String(), Coin: &pb.Coin{ Id: uint64(stake.Coin), - Symbol: state.Coins().GetCoin(stake.Coin).Symbol().String(), + Symbol: state.Coins().GetCoin(stake.Coin).GetFullSymbol(), }, Value: stake.Value.String(), BipValue: stake.BipValue.String(), diff --git a/api/v2/service/data_encoder.go b/api/v2/service/data_encoder.go index efc6f20d8..70f0bb92c 100644 --- a/api/v2/service/data_encoder.go +++ b/api/v2/service/data_encoder.go @@ -19,12 +19,12 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { m = &pb.BuyCoinData{ CoinToBuy: &pb.Coin{ Id: uint64(d.CoinToBuy), - Symbol: coins.GetCoin(d.CoinToBuy).Symbol().String(), + Symbol: coins.GetCoin(d.CoinToBuy).GetFullSymbol(), }, ValueToBuy: d.ValueToBuy.String(), CoinToSell: &pb.Coin{ Id: uint64(d.CoinToSell), - Symbol: coins.GetCoin(d.CoinToSell).Symbol().String(), + Symbol: coins.GetCoin(d.CoinToSell).GetFullSymbol(), }, MaximumValueToSell: d.MaximumValueToSell.String(), } @@ -63,7 +63,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { Commission: uint64(d.Commission), Coin: &pb.Coin{ Id: uint64(d.Coin), - Symbol: coins.GetCoin(d.Coin).Symbol().String(), + Symbol: coins.GetCoin(d.Coin).GetFullSymbol(), }, Stake: d.Stake.String(), } @@ -72,7 +72,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { PubKey: d.PubKey.String(), Coin: &pb.Coin{ Id: uint64(d.Coin), - Symbol: coins.GetCoin(d.Coin).Symbol().String(), + Symbol: coins.GetCoin(d.Coin).GetFullSymbol(), }, Value: d.Value.String(), } @@ -108,7 +108,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { list = append(list, &pb.SendData{ Coin: &pb.Coin{ Id: uint64(item.Coin), - Symbol: coins.GetCoin(item.Coin).Symbol().String(), + Symbol: coins.GetCoin(item.Coin).GetFullSymbol(), }, To: item.To.String(), Value: item.Value.String(), @@ -139,11 +139,11 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { m = &pb.SellAllCoinData{ CoinToSell: &pb.Coin{ Id: uint64(d.CoinToSell), - Symbol: coins.GetCoin(d.CoinToSell).Symbol().String(), + Symbol: coins.GetCoin(d.CoinToSell).GetFullSymbol(), }, CoinToBuy: &pb.Coin{ Id: uint64(d.CoinToBuy), - Symbol: coins.GetCoin(d.CoinToBuy).Symbol().String(), + Symbol: coins.GetCoin(d.CoinToBuy).GetFullSymbol(), }, MinimumValueToBuy: d.MinimumValueToBuy.String(), } @@ -151,12 +151,12 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { m = &pb.SellCoinData{ CoinToSell: &pb.Coin{ Id: uint64(d.CoinToSell), - Symbol: coins.GetCoin(d.CoinToSell).Symbol().String(), + Symbol: coins.GetCoin(d.CoinToSell).GetFullSymbol(), }, ValueToSell: d.ValueToSell.String(), CoinToBuy: &pb.Coin{ Id: uint64(d.CoinToBuy), - Symbol: coins.GetCoin(d.CoinToBuy).Symbol().String(), + Symbol: coins.GetCoin(d.CoinToBuy).GetFullSymbol(), }, MinimumValueToBuy: d.MinimumValueToBuy.String(), } @@ -164,7 +164,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { m = &pb.SendData{ Coin: &pb.Coin{ Id: uint64(d.Coin), - Symbol: coins.GetCoin(d.Coin).Symbol().String(), + Symbol: coins.GetCoin(d.Coin).GetFullSymbol(), }, To: d.To.String(), Value: d.Value.String(), @@ -187,7 +187,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { PubKey: d.PubKey.String(), Coin: &pb.Coin{ Id: uint64(d.Coin), - Symbol: coins.GetCoin(d.Coin).Symbol().String(), + Symbol: coins.GetCoin(d.Coin).GetFullSymbol(), }, Value: d.Value.String(), } diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index 8f3466ed0..f9f8f9d84 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -59,7 +59,7 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe if coinToSell == coinToBuy { return nil, s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), - transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).Symbol().String(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).Symbol().String()))) + transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).GetFullSymbol(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).GetFullSymbol()))) } commissionInBaseCoin := big.NewInt(0).Mul(big.NewInt(commissions.ConvertTx), transaction.CommissionMultiplier) diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index 35827d647..b63708ad5 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -59,7 +59,7 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell if coinToSell == coinToBuy { return nil, s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), - transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).Symbol().String(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).Symbol().String()))) + transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).GetFullSymbol(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).GetFullSymbol()))) } commissionInBaseCoin := big.NewInt(0).Mul(big.NewInt(commissions.ConvertTx), transaction.CommissionMultiplier) diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index 382ffac41..681be2443 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -60,7 +60,7 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS if coinToSell == coinToBuy { return nil, s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), - transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).Symbol().String(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).Symbol().String()))) + transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).GetFullSymbol(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).GetFullSymbol()))) } commissionInBaseCoin := big.NewInt(commissions.ConvertTx) diff --git a/core/transaction/buy_coin.go b/core/transaction/buy_coin.go index af4aa27e2..82c78a9cc 100644 --- a/core/transaction/buy_coin.go +++ b/core/transaction/buy_coin.go @@ -332,9 +332,9 @@ func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.CheckState) * Log: "\"From\" coin equals to \"to\" coin", Info: EncodeError(code.NewCrossConvert( data.CoinToSell.String(), - context.Coins().GetCoin(data.CoinToSell).Symbol().String(), + context.Coins().GetCoin(data.CoinToSell).GetFullSymbol(), data.CoinToBuy.String(), - context.Coins().GetCoin(data.CoinToBuy).Symbol().String()), + context.Coins().GetCoin(data.CoinToBuy).GetFullSymbol()), ), } } diff --git a/core/transaction/sell_all_coin.go b/core/transaction/sell_all_coin.go index cd8acef8a..121b60066 100644 --- a/core/transaction/sell_all_coin.go +++ b/core/transaction/sell_all_coin.go @@ -153,9 +153,9 @@ func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.CheckStat Log: "\"From\" coin equals to \"to\" coin", Info: EncodeError(code.NewCrossConvert( data.CoinToSell.String(), - context.Coins().GetCoin(data.CoinToSell).Symbol().String(), + context.Coins().GetCoin(data.CoinToSell).GetFullSymbol(), data.CoinToBuy.String(), - context.Coins().GetCoin(data.CoinToBuy).Symbol().String()), + context.Coins().GetCoin(data.CoinToBuy).GetFullSymbol()), ), } } diff --git a/core/transaction/sell_coin.go b/core/transaction/sell_coin.go index 946fe6924..f093ed68c 100644 --- a/core/transaction/sell_coin.go +++ b/core/transaction/sell_coin.go @@ -290,9 +290,9 @@ func (data SellCoinData) BasicCheck(tx *Transaction, context *state.CheckState) Log: "\"From\" coin equals to \"to\" coin", Info: EncodeError(code.NewCrossConvert( data.CoinToSell.String(), - context.Coins().GetCoin(data.CoinToSell).Symbol().String(), + context.Coins().GetCoin(data.CoinToSell).GetFullSymbol(), data.CoinToBuy.String(), - context.Coins().GetCoin(data.CoinToBuy).Symbol().String()), + context.Coins().GetCoin(data.CoinToBuy).GetFullSymbol()), ), } } From ad7648e1a5895763f298a3ee062e0e91c01680b1 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 12 Oct 2020 12:01:31 +0300 Subject: [PATCH 377/426] fix coin symbol --- api/v2/service/address.go | 6 +++--- api/v2/service/addresses.go | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/api/v2/service/address.go b/api/v2/service/address.go index fbd22f787..dbcb68e88 100644 --- a/api/v2/service/address.go +++ b/api/v2/service/address.go @@ -57,7 +57,7 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr res.Balance = append(res.Balance, &pb.AddressBalance{ Coin: &pb.Coin{ Id: uint64(coin.Coin.ID), - Symbol: cState.Coins().GetCoin(coin.Coin.ID).Symbol().String(), + Symbol: cState.Coins().GetCoin(coin.Coin.ID).GetFullSymbol(), }, Value: coin.Value.String(), BipValue: customCoinBipBalance(coin.Coin.ID, coin.Value, cState).String(), @@ -96,7 +96,7 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr res.Delegated = append(res.Delegated, &pb.AddressDelegatedBalance{ Coin: &pb.Coin{ Id: uint64(coinID), - Symbol: cState.Coins().GetCoin(coinID).Symbol().String(), + Symbol: cState.Coins().GetCoin(coinID).GetFullSymbol(), }, Value: delegatedStake.Value.String(), DelegateBipValue: delegatedStake.BipValue.String(), @@ -124,7 +124,7 @@ func (s *Service) Address(ctx context.Context, req *pb.AddressRequest) (*pb.Addr res.Total = append(res.Total, &pb.AddressBalance{ Coin: &pb.Coin{ Id: uint64(coinID), - Symbol: cState.Coins().GetCoin(coinID).Symbol().String(), + Symbol: cState.Coins().GetCoin(coinID).GetFullSymbol(), }, Value: stake.String(), BipValue: balance.String(), diff --git a/api/v2/service/addresses.go b/api/v2/service/addresses.go index 54a4ae2ca..b189135dd 100644 --- a/api/v2/service/addresses.go +++ b/api/v2/service/addresses.go @@ -59,7 +59,7 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. res.Balance = append(res.Balance, &pb.AddressBalance{ Coin: &pb.Coin{ Id: uint64(coin.Coin.ID), - Symbol: cState.Coins().GetCoin(coin.Coin.ID).Symbol().String(), + Symbol: cState.Coins().GetCoin(coin.Coin.ID).GetFullSymbol(), }, Value: coin.Value.String(), BipValue: customCoinBipBalance(coin.Coin.ID, coin.Value, cState).String(), @@ -98,7 +98,7 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. res.Delegated = append(res.Delegated, &pb.AddressDelegatedBalance{ Coin: &pb.Coin{ Id: uint64(coinID), - Symbol: cState.Coins().GetCoin(coinID).Symbol().String(), + Symbol: cState.Coins().GetCoin(coinID).GetFullSymbol(), }, Value: delegatedStake.Value.String(), DelegateBipValue: delegatedStake.BipValue.String(), @@ -126,7 +126,7 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. res.Total = append(res.Total, &pb.AddressBalance{ Coin: &pb.Coin{ Id: uint64(coinID), - Symbol: cState.Coins().GetCoin(coinID).Symbol().String(), + Symbol: cState.Coins().GetCoin(coinID).GetFullSymbol(), }, Value: stake.String(), BipValue: balance.String(), @@ -135,7 +135,7 @@ func (s *Service) Addresses(ctx context.Context, req *pb.AddressesRequest) (*pb. coinsBipValue.Add(coinsBipValue, balance) } res.BipValue = coinsBipValue.String() - res.TransactionCount = uint64(cState.Accounts().GetNonce(address)) + res.TransactionCount = cState.Accounts().GetNonce(address) response.Addresses[addr] = &res } From e7a8c05c31de4cb830d5b9a2a447aacce2dd582e Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 12 Oct 2020 12:02:28 +0300 Subject: [PATCH 378/426] fix delegate from waitlist with error min stake --- core/transaction/delegate.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index f1d5034b2..5c8836b5b 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -44,11 +44,17 @@ func (data DelegateData) BasicCheck(tx *Transaction, context *state.CheckState) } } - if data.Value.Cmp(types.Big0) < 1 { + sender, _ := tx.Sender() + value := big.NewInt(0).Set(data.Value) + if watchList := context.WaitList().Get(sender, data.PubKey, data.Coin); watchList != nil { + value.Add(value, watchList.Value) + } + + if value.Cmp(types.Big0) < 1 { return &Response{ Code: code.StakeShouldBePositive, Log: "Stake should be positive", - Info: EncodeError(code.NewStakeShouldBePositive(data.Value.String())), + Info: EncodeError(code.NewStakeShouldBePositive(value.String())), } } @@ -60,12 +66,11 @@ func (data DelegateData) BasicCheck(tx *Transaction, context *state.CheckState) } } - sender, _ := tx.Sender() - if !context.Candidates().IsDelegatorStakeSufficient(sender, data.PubKey, data.Coin, data.Value) { + if !context.Candidates().IsDelegatorStakeSufficient(sender, data.PubKey, data.Coin, value) { return &Response{ Code: code.TooLowStake, Log: "Stake is too low", - Info: EncodeError(code.NewTooLowStake(sender.String(), data.PubKey.String(), data.Value.String(), data.Coin.String(), context.Coins().GetCoin(data.Coin).GetFullSymbol())), + Info: EncodeError(code.NewTooLowStake(sender.String(), data.PubKey.String(), value.String(), data.Coin.String(), context.Coins().GetCoin(data.Coin).GetFullSymbol())), } } From d0626f9a77dbaf9541bf43606ad619fb6811f2d5 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 12 Oct 2020 12:06:21 +0300 Subject: [PATCH 379/426] fix full coin symbol --- api/v2/service/candidate.go | 2 +- api/v2/service/data_encoder.go | 22 +++++++++++----------- api/v2/service/estimate_coin_buy.go | 2 +- api/v2/service/estimate_coin_sell.go | 2 +- api/v2/service/estimate_coin_sell_all.go | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/api/v2/service/candidate.go b/api/v2/service/candidate.go index 60ae3aaf9..1b77ccaea 100644 --- a/api/v2/service/candidate.go +++ b/api/v2/service/candidate.go @@ -72,7 +72,7 @@ func makeResponseCandidate(state *state.CheckState, c *candidates.Candidate, inc Owner: stake.Owner.String(), Coin: &pb.Coin{ Id: uint64(stake.Coin), - Symbol: state.Coins().GetCoin(stake.Coin).Symbol().String(), + Symbol: state.Coins().GetCoin(stake.Coin).GetFullSymbol(), }, Value: stake.Value.String(), BipValue: stake.BipValue.String(), diff --git a/api/v2/service/data_encoder.go b/api/v2/service/data_encoder.go index efc6f20d8..70f0bb92c 100644 --- a/api/v2/service/data_encoder.go +++ b/api/v2/service/data_encoder.go @@ -19,12 +19,12 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { m = &pb.BuyCoinData{ CoinToBuy: &pb.Coin{ Id: uint64(d.CoinToBuy), - Symbol: coins.GetCoin(d.CoinToBuy).Symbol().String(), + Symbol: coins.GetCoin(d.CoinToBuy).GetFullSymbol(), }, ValueToBuy: d.ValueToBuy.String(), CoinToSell: &pb.Coin{ Id: uint64(d.CoinToSell), - Symbol: coins.GetCoin(d.CoinToSell).Symbol().String(), + Symbol: coins.GetCoin(d.CoinToSell).GetFullSymbol(), }, MaximumValueToSell: d.MaximumValueToSell.String(), } @@ -63,7 +63,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { Commission: uint64(d.Commission), Coin: &pb.Coin{ Id: uint64(d.Coin), - Symbol: coins.GetCoin(d.Coin).Symbol().String(), + Symbol: coins.GetCoin(d.Coin).GetFullSymbol(), }, Stake: d.Stake.String(), } @@ -72,7 +72,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { PubKey: d.PubKey.String(), Coin: &pb.Coin{ Id: uint64(d.Coin), - Symbol: coins.GetCoin(d.Coin).Symbol().String(), + Symbol: coins.GetCoin(d.Coin).GetFullSymbol(), }, Value: d.Value.String(), } @@ -108,7 +108,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { list = append(list, &pb.SendData{ Coin: &pb.Coin{ Id: uint64(item.Coin), - Symbol: coins.GetCoin(item.Coin).Symbol().String(), + Symbol: coins.GetCoin(item.Coin).GetFullSymbol(), }, To: item.To.String(), Value: item.Value.String(), @@ -139,11 +139,11 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { m = &pb.SellAllCoinData{ CoinToSell: &pb.Coin{ Id: uint64(d.CoinToSell), - Symbol: coins.GetCoin(d.CoinToSell).Symbol().String(), + Symbol: coins.GetCoin(d.CoinToSell).GetFullSymbol(), }, CoinToBuy: &pb.Coin{ Id: uint64(d.CoinToBuy), - Symbol: coins.GetCoin(d.CoinToBuy).Symbol().String(), + Symbol: coins.GetCoin(d.CoinToBuy).GetFullSymbol(), }, MinimumValueToBuy: d.MinimumValueToBuy.String(), } @@ -151,12 +151,12 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { m = &pb.SellCoinData{ CoinToSell: &pb.Coin{ Id: uint64(d.CoinToSell), - Symbol: coins.GetCoin(d.CoinToSell).Symbol().String(), + Symbol: coins.GetCoin(d.CoinToSell).GetFullSymbol(), }, ValueToSell: d.ValueToSell.String(), CoinToBuy: &pb.Coin{ Id: uint64(d.CoinToBuy), - Symbol: coins.GetCoin(d.CoinToBuy).Symbol().String(), + Symbol: coins.GetCoin(d.CoinToBuy).GetFullSymbol(), }, MinimumValueToBuy: d.MinimumValueToBuy.String(), } @@ -164,7 +164,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { m = &pb.SendData{ Coin: &pb.Coin{ Id: uint64(d.Coin), - Symbol: coins.GetCoin(d.Coin).Symbol().String(), + Symbol: coins.GetCoin(d.Coin).GetFullSymbol(), }, To: d.To.String(), Value: d.Value.String(), @@ -187,7 +187,7 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { PubKey: d.PubKey.String(), Coin: &pb.Coin{ Id: uint64(d.Coin), - Symbol: coins.GetCoin(d.Coin).Symbol().String(), + Symbol: coins.GetCoin(d.Coin).GetFullSymbol(), }, Value: d.Value.String(), } diff --git a/api/v2/service/estimate_coin_buy.go b/api/v2/service/estimate_coin_buy.go index 8f3466ed0..f9f8f9d84 100644 --- a/api/v2/service/estimate_coin_buy.go +++ b/api/v2/service/estimate_coin_buy.go @@ -59,7 +59,7 @@ func (s *Service) EstimateCoinBuy(ctx context.Context, req *pb.EstimateCoinBuyRe if coinToSell == coinToBuy { return nil, s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), - transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).Symbol().String(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).Symbol().String()))) + transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).GetFullSymbol(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).GetFullSymbol()))) } commissionInBaseCoin := big.NewInt(0).Mul(big.NewInt(commissions.ConvertTx), transaction.CommissionMultiplier) diff --git a/api/v2/service/estimate_coin_sell.go b/api/v2/service/estimate_coin_sell.go index 35827d647..b63708ad5 100644 --- a/api/v2/service/estimate_coin_sell.go +++ b/api/v2/service/estimate_coin_sell.go @@ -59,7 +59,7 @@ func (s *Service) EstimateCoinSell(ctx context.Context, req *pb.EstimateCoinSell if coinToSell == coinToBuy { return nil, s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), - transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).Symbol().String(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).Symbol().String()))) + transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).GetFullSymbol(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).GetFullSymbol()))) } commissionInBaseCoin := big.NewInt(0).Mul(big.NewInt(commissions.ConvertTx), transaction.CommissionMultiplier) diff --git a/api/v2/service/estimate_coin_sell_all.go b/api/v2/service/estimate_coin_sell_all.go index 382ffac41..681be2443 100644 --- a/api/v2/service/estimate_coin_sell_all.go +++ b/api/v2/service/estimate_coin_sell_all.go @@ -60,7 +60,7 @@ func (s *Service) EstimateCoinSellAll(ctx context.Context, req *pb.EstimateCoinS if coinToSell == coinToBuy { return nil, s.createError(status.New(codes.InvalidArgument, "\"From\" coin equals to \"to\" coin"), - transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).Symbol().String(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).Symbol().String()))) + transaction.EncodeError(code.NewCrossConvert(coinToSell.String(), cState.Coins().GetCoin(coinToSell).GetFullSymbol(), coinToBuy.String(), cState.Coins().GetCoin(coinToBuy).GetFullSymbol()))) } commissionInBaseCoin := big.NewInt(commissions.ConvertTx) From 60076ad87280b0fd1653d4e654b4f70c663f0a3c Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 12 Oct 2020 12:14:42 +0300 Subject: [PATCH 380/426] fix full coin symbol --- core/transaction/buy_coin.go | 4 ++-- core/transaction/sell_all_coin.go | 4 ++-- core/transaction/sell_coin.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/transaction/buy_coin.go b/core/transaction/buy_coin.go index af4aa27e2..82c78a9cc 100644 --- a/core/transaction/buy_coin.go +++ b/core/transaction/buy_coin.go @@ -332,9 +332,9 @@ func (data BuyCoinData) BasicCheck(tx *Transaction, context *state.CheckState) * Log: "\"From\" coin equals to \"to\" coin", Info: EncodeError(code.NewCrossConvert( data.CoinToSell.String(), - context.Coins().GetCoin(data.CoinToSell).Symbol().String(), + context.Coins().GetCoin(data.CoinToSell).GetFullSymbol(), data.CoinToBuy.String(), - context.Coins().GetCoin(data.CoinToBuy).Symbol().String()), + context.Coins().GetCoin(data.CoinToBuy).GetFullSymbol()), ), } } diff --git a/core/transaction/sell_all_coin.go b/core/transaction/sell_all_coin.go index cd8acef8a..121b60066 100644 --- a/core/transaction/sell_all_coin.go +++ b/core/transaction/sell_all_coin.go @@ -153,9 +153,9 @@ func (data SellAllCoinData) BasicCheck(tx *Transaction, context *state.CheckStat Log: "\"From\" coin equals to \"to\" coin", Info: EncodeError(code.NewCrossConvert( data.CoinToSell.String(), - context.Coins().GetCoin(data.CoinToSell).Symbol().String(), + context.Coins().GetCoin(data.CoinToSell).GetFullSymbol(), data.CoinToBuy.String(), - context.Coins().GetCoin(data.CoinToBuy).Symbol().String()), + context.Coins().GetCoin(data.CoinToBuy).GetFullSymbol()), ), } } diff --git a/core/transaction/sell_coin.go b/core/transaction/sell_coin.go index 946fe6924..f093ed68c 100644 --- a/core/transaction/sell_coin.go +++ b/core/transaction/sell_coin.go @@ -290,9 +290,9 @@ func (data SellCoinData) BasicCheck(tx *Transaction, context *state.CheckState) Log: "\"From\" coin equals to \"to\" coin", Info: EncodeError(code.NewCrossConvert( data.CoinToSell.String(), - context.Coins().GetCoin(data.CoinToSell).Symbol().String(), + context.Coins().GetCoin(data.CoinToSell).GetFullSymbol(), data.CoinToBuy.String(), - context.Coins().GetCoin(data.CoinToBuy).Symbol().String()), + context.Coins().GetCoin(data.CoinToBuy).GetFullSymbol()), ), } } From 896254e11f992dd6ef4b7c7ab49c0dd94241da89 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 12 Oct 2020 13:22:10 +0300 Subject: [PATCH 381/426] add environment path with the genesis file to download --- cmd/minter/cmd/node.go | 12 +++++++++--- cmd/minter/main.go | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index 93ed2154d..def80b433 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -230,10 +230,16 @@ func getGenesis() (doc *tmTypes.GenesisDoc, e error) { _, err := os.Stat(genDocFile) if err != nil { if !os.IsNotExist(err) { - panic(err) + return nil, err } - if err := downloadFile(genDocFile, "https://raw.githubusercontent.com/MinterTeam/minter-network-migrate/master/minter-mainnet-2/genesis.json"); err != nil { - panic(err) + + genesis, err := RootCmd.Flags().GetString("genesis") + if err != nil { + return nil, err + } + + if err := downloadFile(genDocFile, genesis); err != nil { + return nil, err } } return tmTypes.GenesisDocFromFile(genDocFile) diff --git a/cmd/minter/main.go b/cmd/minter/main.go index 4e9980aa7..9b8c6a997 100644 --- a/cmd/minter/main.go +++ b/cmd/minter/main.go @@ -34,6 +34,7 @@ func main() { rootCmd.PersistentFlags().Bool("testnet", false, "use \"true\" for testnet, mainnet is default") rootCmd.PersistentFlags().Bool("pprof", false, "enable pprof") rootCmd.PersistentFlags().String("pprof-addr", "0.0.0.0:6060", "pprof listen addr") + rootCmd.PersistentFlags().String("genesis", "https://raw.githubusercontent.com/MinterTeam/minter-network-migrate/master/minter-mainnet-2/genesis.json", "path with the genesis file to download") cmd.ExportCommand.Flags().Uint64("height", 0, "export height") cmd.ExportCommand.Flags().Uint64("start-height", 0, "height for starting a new chain") From 3310d48bd3e284fd90cbe8434e96b2d823b9b44e Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Mon, 12 Oct 2020 15:32:46 +0300 Subject: [PATCH 382/426] Add grace period --- core/state/validators/validators.go | 6 +++++- upgrades/grace.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 upgrades/grace.go diff --git a/core/state/validators/validators.go b/core/state/validators/validators.go index 1452cd61a..111fd201f 100644 --- a/core/state/validators/validators.go +++ b/core/state/validators/validators.go @@ -10,6 +10,7 @@ import ( "github.com/MinterTeam/minter-go-node/core/types" "github.com/MinterTeam/minter-go-node/rlp" "github.com/MinterTeam/minter-go-node/tree" + "github.com/MinterTeam/minter-go-node/upgrades" "math/big" ) @@ -101,7 +102,10 @@ func (v *Validators) SetValidatorAbsent(height uint64, address types.TmAddress) validator.SetAbsent(height) if validator.CountAbsentTimes() > ValidatorMaxAbsentTimes { - v.punishValidator(height, address) + if !upgrades.IsGraceBlock(height) { + v.punishValidator(height, address) + } + v.turnValidatorOff(address) } } diff --git a/upgrades/grace.go b/upgrades/grace.go new file mode 100644 index 000000000..d41a6eef2 --- /dev/null +++ b/upgrades/grace.go @@ -0,0 +1,28 @@ +package upgrades + +var gracePeriods = []*gracePeriod{ + newGracePeriod(1, 120), +} + +func IsGraceBlock(block uint64) bool { + for _, gp := range gracePeriods { + if gp.isApplicable(block) { + return true + } + } + + return false +} + +type gracePeriod struct { + from uint64 + to uint64 +} + +func (gp *gracePeriod) isApplicable(block uint64) bool { + return block >= gp.from && block <= gp.to +} + +func newGracePeriod(from uint64, to uint64) *gracePeriod { + return &gracePeriod{from: from, to: to} +} From aa50f8ef4ac760d6122a37637ef1d4f75a87389e Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 12 Oct 2020 18:50:35 +0300 Subject: [PATCH 383/426] add redirect from /v2/ to /v2/openapi-ui/ --- api/v2/v2.go | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/api/v2/v2.go b/api/v2/v2.go index 6269f2b7f..46831fc28 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -32,7 +32,7 @@ import ( "time" ) -// Start gRPC and API v2 +// Run initialises gRPC and API v2 interfaces func Run(srv *service.Service, addrGRPC, addrApi string, logger log.Logger) error { lis, err := net.Listen("tcp", addrGRPC) if err != nil { @@ -84,8 +84,15 @@ func Run(srv *service.Service, addrGRPC, addrApi string, logger log.Logger) erro return err } mux := http.NewServeMux() - mux.Handle("/v2/", http.StripPrefix("/v2", handlers.CompressHandler(allowCORS(wsproxy.WebsocketProxy(gwmux))))) - _ = serveOpenAPI(mux) + openapi := "/v2/openapi-ui/" + _ = serveOpenAPI(openapi, mux) + mux.HandleFunc("/v2/", func(writer http.ResponseWriter, request *http.Request) { + if request.URL.Path == "/v2/" { + http.Redirect(writer, request, openapi, 302) + return + } + http.StripPrefix("/v2", handlers.CompressHandler(allowCORS(wsproxy.WebsocketProxy(gwmux)))) + }) group.Go(func() error { return http.ListenAndServe(addrApi, mux) }) @@ -113,7 +120,7 @@ func preflightHandler(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Access-Control-Allow-Methods", strings.Join(methods, ",")) } -func serveOpenAPI(mux *http.ServeMux) error { +func serveOpenAPI(prefix string, mux *http.ServeMux) error { _ = mime.AddExtensionType(".svg", "image/svg+xml") statikFS, err := fs.New() @@ -123,7 +130,6 @@ func serveOpenAPI(mux *http.ServeMux) error { // Expose files in static on /v2/openapi-ui fileServer := http.FileServer(statikFS) - prefix := "/v2/openapi-ui/" mux.Handle(prefix, http.StripPrefix(prefix, fileServer)) return nil } From 61231964b07bd8dbff6cd7471f0e11916384876c Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 12 Oct 2020 20:56:00 +0300 Subject: [PATCH 384/426] small refactor --- api/v2/service/waitlist.go | 2 +- api/waitlist.go | 2 +- core/state/bus/{watchlist.go => waitlist.go} | 0 core/state/waitlist/waitlist.go | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename core/state/bus/{watchlist.go => waitlist.go} (100%) diff --git a/api/v2/service/waitlist.go b/api/v2/service/waitlist.go index 4485fc885..d94361f27 100644 --- a/api/v2/service/waitlist.go +++ b/api/v2/service/waitlist.go @@ -67,7 +67,7 @@ func (s *Service) WaitList(ctx context.Context, req *pb.WaitListRequest) (*pb.Wa PublicKey: cState.Candidates().PubKey(item.CandidateId).String(), Coin: &pb.Coin{ Id: uint64(item.Coin), - Symbol: cState.Coins().GetCoin(item.Coin).CSymbol.String(), + Symbol: cState.Coins().GetCoin(item.Coin).GetFullSymbol(), }, Value: item.Value.String(), }) diff --git a/api/waitlist.go b/api/waitlist.go index d89bdc0a4..0ebb6accb 100644 --- a/api/waitlist.go +++ b/api/waitlist.go @@ -29,7 +29,7 @@ func Waitlist(pubkey types.Pubkey, address types.Address, height int) (*Waitlist response.List = append(response.List, &Wait{ Coin: Coin{ ID: item.Coin.Uint32(), - Symbol: cState.Coins().GetCoin(item.Coin).CSymbol.String(), + Symbol: cState.Coins().GetCoin(item.Coin).GetFullSymbol(), }, Value: item.Value.String(), }) diff --git a/core/state/bus/watchlist.go b/core/state/bus/waitlist.go similarity index 100% rename from core/state/bus/watchlist.go rename to core/state/bus/waitlist.go diff --git a/core/state/waitlist/waitlist.go b/core/state/waitlist/waitlist.go index 5fdb8f193..2cdca5c0a 100644 --- a/core/state/waitlist/waitlist.go +++ b/core/state/waitlist/waitlist.go @@ -162,7 +162,7 @@ func (wl *WaitList) Delete(address types.Address, pubkey types.Pubkey, coin type } value := big.NewInt(0) - items := make([]Item, 0, len(w.List)) + items := make([]Item, 0, len(w.List)-1) for _, item := range w.List { if item.CandidateId != candidate.ID && item.Coin != coin { items = append(items, item) From 2ae7bda205ebf69623c80d7c590ef420645fd993 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 12 Oct 2020 21:54:03 +0300 Subject: [PATCH 385/426] Dockerfile-ci for github action tests --- .github/workflows/main.yml | 2 +- Dockerfile-ci | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 Dockerfile-ci diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a730c36cd..6a09ad1ea 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -34,7 +34,7 @@ jobs: 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) - name: Docker build - run: docker build -t $DOCKER_REPO/$DOCKER_IMAGE:$VERSION . + 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 diff --git a/Dockerfile-ci b/Dockerfile-ci new file mode 100644 index 000000000..efc237e8c --- /dev/null +++ b/Dockerfile-ci @@ -0,0 +1,24 @@ +FROM tazhate/dockerfile-gox as builder + +COPY . /gopath/src/github.com/MinterTeam/minter-go-node +WORKDIR /gopath/src/github.com/MinterTeam/minter-go-node +RUN apt-get update && apt-get install libleveldb-dev -y --no-install-recommends -q +RUN make get_tools +RUN make get_vendor_deps +RUN make build + +FROM ubuntu:bionic + +COPY --from=builder /gopath/src/github.com/MinterTeam/minter-go-node/build/minter/ /usr/bin/minter +RUN apt update && apt install libleveldb1v5 ca-certificates -y --no-install-recommends -q && \ + addgroup minteruser && \ + useradd --no-log-init -r -m -d /minter -g minteruser minteruser && \ + chown -R minteruser:minteruser /minter && \ + rm -rf /var/lib/apt/lists/* + +USER minteruser +WORKDIR /minter +RUN mkdir /minter/data +EXPOSE 8841 +ENTRYPOINT ["/usr/bin/minter"] +CMD ["node", "--home-dir", "/minter", "--genesis", "https://github.com/MinterTeam/minter-go-node/releases/download/v1.2-testnet-9/genesis.json"] From 3871ed8356add997db077586a1ec6cd1af28c6a2 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 12 Oct 2020 22:14:38 +0300 Subject: [PATCH 386/426] clean up Dockerfile-ci --- Dockerfile-ci | 2 -- 1 file changed, 2 deletions(-) diff --git a/Dockerfile-ci b/Dockerfile-ci index efc237e8c..c9ce18cf6 100644 --- a/Dockerfile-ci +++ b/Dockerfile-ci @@ -3,8 +3,6 @@ FROM tazhate/dockerfile-gox as builder COPY . /gopath/src/github.com/MinterTeam/minter-go-node WORKDIR /gopath/src/github.com/MinterTeam/minter-go-node RUN apt-get update && apt-get install libleveldb-dev -y --no-install-recommends -q -RUN make get_tools -RUN make get_vendor_deps RUN make build FROM ubuntu:bionic From b6d0386f758b23c173579030a56674ba81ed9ecd Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 12 Oct 2020 22:27:11 +0300 Subject: [PATCH 387/426] fix redirect --- api/v2/v2.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v2/v2.go b/api/v2/v2.go index 46831fc28..166b1cb66 100644 --- a/api/v2/v2.go +++ b/api/v2/v2.go @@ -91,7 +91,7 @@ func Run(srv *service.Service, addrGRPC, addrApi string, logger log.Logger) erro http.Redirect(writer, request, openapi, 302) return } - http.StripPrefix("/v2", handlers.CompressHandler(allowCORS(wsproxy.WebsocketProxy(gwmux)))) + http.StripPrefix("/v2", handlers.CompressHandler(allowCORS(wsproxy.WebsocketProxy(gwmux)))).ServeHTTP(writer, request) }) group.Go(func() error { return http.ListenAndServe(addrApi, mux) From 3dcfd5e873d5cd10903a550b0343dbe5f0bbcd5a Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 13 Oct 2020 09:14:57 +0300 Subject: [PATCH 388/426] fix waitlist --- core/state/waitlist/waitlist.go | 2 +- core/state/waitlist/waitlist_test.go | 52 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/core/state/waitlist/waitlist.go b/core/state/waitlist/waitlist.go index 2cdca5c0a..eb046d9fb 100644 --- a/core/state/waitlist/waitlist.go +++ b/core/state/waitlist/waitlist.go @@ -164,7 +164,7 @@ func (wl *WaitList) Delete(address types.Address, pubkey types.Pubkey, coin type value := big.NewInt(0) items := make([]Item, 0, len(w.List)-1) for _, item := range w.List { - if item.CandidateId != candidate.ID && item.Coin != coin { + if item.CandidateId != candidate.ID || item.Coin != coin { items = append(items, item) } else { value.Add(value, item.Value) diff --git a/core/state/waitlist/waitlist_test.go b/core/state/waitlist/waitlist_test.go index 795cacdbb..49e517bb9 100644 --- a/core/state/waitlist/waitlist_test.go +++ b/core/state/waitlist/waitlist_test.go @@ -54,3 +54,55 @@ func TestWaitListToGetByAddressAndPubKey(t *testing.T) { t.Fatal("Incorrect amount of items in waitlist") } } + +func TestWaitListToPartialDelete(t *testing.T) { + b := bus.NewBus() + b.SetChecker(checker.NewChecker(b)) + mutableTree, _ := tree.NewMutableTree(0, db.NewMemDB(), 1024) + + wl, err := NewWaitList(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + candidatesState, err := candidates.NewCandidates(b, mutableTree) + if err != nil { + t.Fatal(err) + } + + addr, pubkey, coin, val := types.Address{0}, types.Pubkey{0}, types.GetBaseCoinID(), big.NewInt(1e18) + candidatesState.Create(addr, addr, addr, pubkey, 10) + + wl.AddWaitList(addr, pubkey, coin, val) + wl.AddWaitList(addr, pubkey, 1, val) + wl.AddWaitList(addr, pubkey, 2, val) + if err := wl.Commit(); err != nil { + t.Fatal(err) + } + + _, _, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + wl.Delete(addr, pubkey, 0) + wl.Delete(addr, pubkey, 1) + wl.AddWaitList(addr, pubkey, 1, big.NewInt(1e17)) + _, _, err = mutableTree.SaveVersion() + if err != nil { + t.Fatal(err) + } + + items := wl.GetByAddressAndPubKey(addr, pubkey) + if len(items) != 2 { + t.Fatal("Incorrect amount of items in waitlist") + } + + if items[1].Value.Cmp(big.NewInt(1e17)) != 0 || items[1].Coin != 1 { + t.Fatal("Invalid waitlist data") + } + + if items[0].Value.Cmp(val) != 0 || items[0].Coin != 2 { + t.Fatal("Invalid waitlist data") + } +} From 0b86bd1989b6dd9f81751257657288f4b8b4c85b Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Tue, 13 Oct 2020 09:54:25 +0300 Subject: [PATCH 389/426] fix --- core/state/waitlist/model.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/state/waitlist/model.go b/core/state/waitlist/model.go index 0ddc7be37..c33d191e6 100644 --- a/core/state/waitlist/model.go +++ b/core/state/waitlist/model.go @@ -22,6 +22,6 @@ func (m *Model) AddToList(candidateId uint32, coin types.CoinID, value *big.Int) m.List = append(m.List, Item{ CandidateId: candidateId, Coin: coin, - Value: value, + Value: new(big.Int).Set(value), }) } From d637619f3391e12a3e6eef0bf50243db991ca9e7 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Tue, 13 Oct 2020 13:53:26 +0300 Subject: [PATCH 390/426] Refactor --- core/state/candidates/candidates.go | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 5bd91eaf9..9bb3299c4 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -79,7 +79,12 @@ type Candidates struct { // NewCandidates returns newly created Candidates state with a given bus and iavl func NewCandidates(bus *bus.Bus, iavl tree.MTree) (*Candidates, error) { - candidates := &Candidates{iavl: iavl, bus: bus} + candidates := &Candidates{ + iavl: iavl, + bus: bus, + blockList: map[types.Pubkey]struct{}{}, + pubKeyIDs: map[types.Pubkey]uint32{}, + } candidates.bus.SetCandidates(NewBus(candidates)) return candidates, nil @@ -411,9 +416,6 @@ func (c *Candidates) Exists(pubkey types.Pubkey) bool { } func (c *Candidates) existPubKey(pubKey types.Pubkey) bool { - if c.pubKeyIDs == nil { - return false - } _, exists := c.pubKeyIDs[pubKey] return exists } @@ -1075,31 +1077,26 @@ func (c *Candidates) PubKey(id uint32) types.Pubkey { return candidate.PubKey } -func (c *Candidates) setPubKeyID(pubkey types.Pubkey, u uint32) { - if u == 0 { +func (c *Candidates) setPubKeyID(pubkey types.Pubkey, id uint32) { + if id == 0 { panic("public key of candidate cannot be equal 0") } c.lock.Lock() defer c.lock.Unlock() - if c.maxID < u { - c.maxID = u + if c.maxID < id { + c.maxID = id } - if c.pubKeyIDs == nil { - c.pubKeyIDs = map[types.Pubkey]uint32{} - } - c.pubKeyIDs[pubkey] = u + c.pubKeyIDs[pubkey] = id c.isDirty = true } func (c *Candidates) setBlockPubKey(p types.Pubkey) { c.lock.Lock() defer c.lock.Unlock() - if c.blockList == nil { - c.blockList = map[types.Pubkey]struct{}{} - } + c.blockList[p] = struct{}{} c.isDirty = true } From 20f37d9ce4221a74090e7cedd411b4d94a74620d Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Tue, 13 Oct 2020 15:44:51 +0300 Subject: [PATCH 391/426] Update dockerfile --- scripts/DOCKER/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/DOCKER/Dockerfile b/scripts/DOCKER/Dockerfile index ec4779db1..31f7e34de 100644 --- a/scripts/DOCKER/Dockerfile +++ b/scripts/DOCKER/Dockerfile @@ -1,7 +1,7 @@ FROM ubuntu:18.04 RUN apt-get update && apt-get install -y software-properties-common build-essential wget -RUN wget https://dl.google.com/go/go1.14.linux-amd64.tar.gz && tar -C /usr/local -xzf go1.14.linux-amd64.tar.gz +RUN wget https://dl.google.com/go/go1.15.2.linux-amd64.tar.gz && tar -C /usr/local -xzf go1.15.2.linux-amd64.tar.gz ENV GOPATH=$HOME/go ENV PATH=$PATH:/usr/local/go/bin:$GOPATH/bin From 2379fab1e53a8b571181b7ef2d41d3e436b9c255 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 13 Oct 2020 18:11:34 +0300 Subject: [PATCH 392/426] fix evidence --- api/v2/service/block.go | 42 ++++++++++++++++++---------------- api/v2/service/data_encoder.go | 24 +++++++++++++++++++ api/v2/service/events.go | 8 +------ api/v2/service/service.go | 24 ++++++------------- api/v2/service/ws.go | 8 +------ go.mod | 2 +- go.sum | 4 ++-- 7 files changed, 58 insertions(+), 54 deletions(-) diff --git a/api/v2/service/block.go b/api/v2/service/block.go index a8e643eef..4e60ff821 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -11,6 +11,7 @@ import ( "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/core/types" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" + _struct "github.com/golang/protobuf/ptypes/struct" core_types "github.com/tendermint/tendermint/rpc/core/types" tmTypes "github.com/tendermint/tendermint/types" "google.golang.org/grpc/codes" @@ -94,7 +95,10 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes return nil, timeoutStatus.Err() } - response.Evidence = blockEvidence(block) + response.Evidence, err = blockEvidence(block) + if err != nil { + return nil, err + } if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { return nil, timeoutStatus.Err() @@ -151,7 +155,10 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes return nil, err } case pb.BlockRequest_evidence: - response.Evidence = blockEvidence(block) + response.Evidence, err = blockEvidence(block) + if err != nil { + return nil, err + } } } @@ -159,17 +166,16 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes return response, nil } -func blockEvidence(block *core_types.ResultBlock) *pb.BlockResponse_Evidence { - evidences := make([]*pb.BlockResponse_Evidence_Evidence, 0, len(block.Block.Evidence.Evidence)) +func blockEvidence(block *core_types.ResultBlock) (*pb.BlockResponse_Evidence, error) { + evidences := make([]*_struct.Struct, 0, len(block.Block.Evidence.Evidence)) for _, evidence := range block.Block.Evidence.Evidence { - evidences = append(evidences, &pb.BlockResponse_Evidence_Evidence{ - Height: uint64(evidence.Height()), - Time: evidence.Time().Format(time.RFC3339Nano), - Address: fmt.Sprintf("%s", evidence.Address()), - Hash: fmt.Sprintf("%s", evidence.Hash()), - }) + str, err := toStruct(evidence) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + evidences = append(evidences, str) } - return &pb.BlockResponse_Evidence{Evidence: evidences} + return &pb.BlockResponse_Evidence{Evidence: evidences}, nil } func blockValidators(totalValidators []*tmTypes.Validator, block *core_types.ResultBlock) []*pb.BlockResponse_Validator { @@ -201,11 +207,7 @@ func missedBlockValidators(s *state.CheckState) []string { } func blockProposer(block *core_types.ResultBlock, totalValidators []*tmTypes.Validator) (string, error) { - p, err := getBlockProposer(block, totalValidators) - if err != nil { - return "", status.Error(codes.FailedPrecondition, err.Error()) - } - + p := getBlockProposer(block, totalValidators) if p != nil { return p.String(), nil } @@ -233,7 +235,7 @@ func (s *Service) blockTransaction(block *core_types.ResultBlock, blockResults * Hash: strings.Title(fmt.Sprintf("Mt%x", rawTx.Hash())), RawTx: fmt.Sprintf("%x", []byte(rawTx)), From: sender.String(), - Nonce: uint64(tx.Nonce), + Nonce: tx.Nonce, GasPrice: uint64(tx.GasPrice), Type: uint64(tx.Type), Data: data, @@ -252,14 +254,14 @@ func (s *Service) blockTransaction(block *core_types.ResultBlock, blockResults * return txs, nil } -func getBlockProposer(block *core_types.ResultBlock, vals []*tmTypes.Validator) (*types.Pubkey, error) { +func getBlockProposer(block *core_types.ResultBlock, vals []*tmTypes.Validator) *types.Pubkey { for _, tmval := range vals { if bytes.Equal(tmval.Address.Bytes(), block.Block.ProposerAddress.Bytes()) { var result types.Pubkey copy(result[:], tmval.PubKey.Bytes()[5:]) - return &result, nil + return &result } } - return nil, status.Error(codes.NotFound, "Block proposer not found") + return nil } diff --git a/api/v2/service/data_encoder.go b/api/v2/service/data_encoder.go index 70f0bb92c..58410cc5f 100644 --- a/api/v2/service/data_encoder.go +++ b/api/v2/service/data_encoder.go @@ -2,6 +2,7 @@ package service import ( "encoding/base64" + "encoding/json" "errors" "github.com/MinterTeam/minter-go-node/core/state/coins" "github.com/MinterTeam/minter-go-node/core/transaction" @@ -9,6 +10,7 @@ import ( "github.com/golang/protobuf/ptypes/any" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" + _struct "google.golang.org/protobuf/types/known/structpb" "strconv" ) @@ -202,3 +204,25 @@ func encode(data transaction.Data, coins coins.RCoins) (*any.Any, error) { return a, nil } + +func encodeToStruct(b []byte) (*_struct.Struct, error) { + dataStruct := &_struct.Struct{} + if err := dataStruct.UnmarshalJSON(b); err != nil { + return nil, err + } + + return dataStruct, nil +} + +func toStruct(d interface{}) (*_struct.Struct, error) { + byteData, err := json.Marshal(d) + if err != nil { + return nil, err + } + + data, err := encodeToStruct(byteData) + if err != nil { + return nil, err + } + return data, nil +} diff --git a/api/v2/service/events.go b/api/v2/service/events.go index 3f23c24e8..019c56292 100644 --- a/api/v2/service/events.go +++ b/api/v2/service/events.go @@ -2,7 +2,6 @@ package service import ( "context" - "encoding/json" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -36,12 +35,7 @@ func (s *Service) Events(ctx context.Context, req *pb.EventsRequest) (*pb.Events continue } - b, err := json.Marshal(event) - if err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } - - data, err := encodeToStruct(b) + data, err := toStruct(event) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/api/v2/service/service.go b/api/v2/service/service.go index 0c671f93d..c4f04e042 100644 --- a/api/v2/service/service.go +++ b/api/v2/service/service.go @@ -4,7 +4,6 @@ import ( "context" "github.com/MinterTeam/minter-go-node/config" "github.com/MinterTeam/minter-go-node/core/minter" - _struct "github.com/golang/protobuf/ptypes/struct" "github.com/tendermint/go-amino" tmNode "github.com/tendermint/tendermint/node" rpc "github.com/tendermint/tendermint/rpc/client/local" @@ -12,7 +11,7 @@ import ( "time" ) -// gRPC implementation ApiServiceServer +// Service is gRPC implementation ApiServiceServer type Service struct { cdc *amino.Codec blockchain *minter.Blockchain @@ -22,7 +21,7 @@ type Service struct { version string } -// NewService create gRPC implementation +// NewService create gRPC server implementation func NewService(cdc *amino.Codec, blockchain *minter.Blockchain, client *rpc.Local, node *tmNode.Node, minterCfg *config.Config, version string) *Service { return &Service{ cdc: cdc, @@ -34,6 +33,11 @@ func NewService(cdc *amino.Codec, blockchain *minter.Blockchain, client *rpc.Loc } } +// TimeoutDuration gRPC +func (s *Service) TimeoutDuration() time.Duration { + return s.minterCfg.APIv2TimeoutDuration +} + func (s *Service) createError(statusErr *status.Status, data string) error { if len(data) == 0 { return statusErr.Err() @@ -54,20 +58,6 @@ func (s *Service) createError(statusErr *status.Status, data string) error { return withDetails.Err() } -func encodeToStruct(b []byte) (*_struct.Struct, error) { - dataStruct := &_struct.Struct{} - if err := dataStruct.UnmarshalJSON(b); err != nil { - return nil, err - } - - return dataStruct, nil -} - -// TimeoutDuration gRPC -func (s *Service) TimeoutDuration() time.Duration { - return s.minterCfg.APIv2TimeoutDuration -} - func (s *Service) checkTimeout(ctx context.Context) *status.Status { select { case <-ctx.Done(): diff --git a/api/v2/service/ws.go b/api/v2/service/ws.go index 36fde0cdd..2ec046fd1 100644 --- a/api/v2/service/ws.go +++ b/api/v2/service/ws.go @@ -2,7 +2,6 @@ package service import ( "context" - "encoding/json" "fmt" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" "github.com/google/uuid" @@ -72,12 +71,7 @@ func subscribeResponse(msg core_types.ResultEvent) (*pb.SubscribeResponse, error }) } - byteData, err := json.Marshal(msg.Data) - if err != nil { - return nil, err - } - - data, err := encodeToStruct(byteData) + data, err := toStruct(msg.Data) if err != nil { return nil, err } diff --git a/go.mod b/go.mod index d50dc5fd4..b8ecb3603 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201002113509-9b89a2a6277c + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201013150426-ead4ac3b38a1 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index afa7f1ea8..3efd5edb9 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201002113509-9b89a2a6277c h1:0GtBLTqt/9KnP9AgjbUbccsbwtMqYQxk9EmQ/YD8cxQ= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201002113509-9b89a2a6277c/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201013150426-ead4ac3b38a1 h1:Hfrty7j5jlcPlf4ER2xsDohI5CJChKwy4fzTfFgNT5Q= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201013150426-ead4ac3b38a1/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 4c6486d57a146a8b26e2ef951979003be174ae7f Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 13 Oct 2020 18:46:49 +0300 Subject: [PATCH 393/426] fix evidence --- api/api.go | 41 ++--------------------------------------- api/v2/service/block.go | 12 +++++++++++- cmd/minter/cmd/node.go | 40 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 51 insertions(+), 42 deletions(-) diff --git a/api/api.go b/api/api.go index 136e716cd..fb1cfc834 100644 --- a/api/api.go +++ b/api/api.go @@ -3,20 +3,13 @@ package api import ( "fmt" "github.com/MinterTeam/minter-go-node/config" - eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/minter" "github.com/MinterTeam/minter-go-node/core/state" "github.com/MinterTeam/minter-go-node/rpc/lib/server" "github.com/rs/cors" "github.com/tendermint/go-amino" - "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/crypto/ed25519" - "github.com/tendermint/tendermint/crypto/multisig" - "github.com/tendermint/tendermint/crypto/secp256k1" - "github.com/tendermint/tendermint/evidence" "github.com/tendermint/tendermint/libs/log" rpc "github.com/tendermint/tendermint/rpc/client/local" - "github.com/tendermint/tendermint/types" "net/http" "net/url" "strings" @@ -67,13 +60,9 @@ func responseTime(b *minter.Blockchain) func(f func(http.ResponseWriter, *http.R } // RunAPI start -func RunAPI(b *minter.Blockchain, tmRPC *rpc.Local, cfg *config.Config, logger log.Logger) { +func RunAPI(codec *amino.Codec, b *minter.Blockchain, tmRPC *rpc.Local, cfg *config.Config, logger log.Logger) { + cdc = codec minterCfg = cfg - - RegisterCryptoAmino(cdc) - eventsdb.RegisterAminoEvents(cdc) - RegisterEvidenceMessages(cdc) - client = tmRPC blockchain = b waitForTendermint() @@ -150,29 +139,3 @@ func GetStateForHeight(height int) (*state.CheckState, error) { return blockchain.CurrentState(), nil } - -// RegisterAmino registers all crypto related types in the given (amino) codec. -func RegisterCryptoAmino(cdc *amino.Codec) { - // These are all written here instead of - cdc.RegisterInterface((*crypto.PubKey)(nil), nil) - cdc.RegisterConcrete(ed25519.PubKeyEd25519{}, - ed25519.PubKeyAminoName, nil) - cdc.RegisterConcrete(secp256k1.PubKeySecp256k1{}, - secp256k1.PubKeyAminoName, nil) - cdc.RegisterConcrete(multisig.PubKeyMultisigThreshold{}, - multisig.PubKeyMultisigThresholdAminoRoute, nil) - - cdc.RegisterInterface((*crypto.PrivKey)(nil), nil) - cdc.RegisterConcrete(ed25519.PrivKeyEd25519{}, - ed25519.PrivKeyAminoName, nil) - cdc.RegisterConcrete(secp256k1.PrivKeySecp256k1{}, - secp256k1.PrivKeyAminoName, nil) -} - -func RegisterEvidenceMessages(cdc *amino.Codec) { - cdc.RegisterInterface((*evidence.Message)(nil), nil) - cdc.RegisterConcrete(&evidence.ListMessage{}, - "tendermint/evidence/EvidenceListMessage", nil) - cdc.RegisterInterface((*types.Evidence)(nil), nil) - cdc.RegisterConcrete(&types.DuplicateVoteEvidence{}, "tendermint/DuplicateVoteEvidence", nil) -} diff --git a/api/v2/service/block.go b/api/v2/service/block.go index 4e60ff821..1cb953cd6 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/hex" + "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/rewards" "github.com/MinterTeam/minter-go-node/core/state" @@ -169,7 +170,16 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes func blockEvidence(block *core_types.ResultBlock) (*pb.BlockResponse_Evidence, error) { evidences := make([]*_struct.Struct, 0, len(block.Block.Evidence.Evidence)) for _, evidence := range block.Block.Evidence.Evidence { - str, err := toStruct(evidence) + proto, err := tmTypes.EvidenceToProto(evidence) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + marshal, err := json.Marshal(proto) + if err != nil { + return nil, err + } + + str, err := encodeToStruct(marshal) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/cmd/minter/cmd/node.go b/cmd/minter/cmd/node.go index def80b433..9847f7a0f 100644 --- a/cmd/minter/cmd/node.go +++ b/cmd/minter/cmd/node.go @@ -8,6 +8,7 @@ import ( "github.com/MinterTeam/minter-go-node/cli/service" "github.com/MinterTeam/minter-go-node/cmd/utils" "github.com/MinterTeam/minter-go-node/config" + eventsdb "github.com/MinterTeam/minter-go-node/core/events" "github.com/MinterTeam/minter-go-node/core/minter" "github.com/MinterTeam/minter-go-node/core/statistics" "github.com/MinterTeam/minter-go-node/log" @@ -16,6 +17,11 @@ import ( "github.com/tendermint/go-amino" "github.com/tendermint/tendermint/abci/types" tmCfg "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/multisig" + "github.com/tendermint/tendermint/crypto/secp256k1" + "github.com/tendermint/tendermint/evidence" tmLog "github.com/tendermint/tendermint/libs/log" tmOS "github.com/tendermint/tendermint/libs/os" tmNode "github.com/tendermint/tendermint/node" @@ -107,7 +113,37 @@ func runCLI(cmd *cobra.Command, app *minter.Blockchain, client *rpc.Local, tmNod }() } +// RegisterAmino registers all crypto related types in the given (amino) codec. +func registerCryptoAmino(cdc *amino.Codec) { + // These are all written here instead of + cdc.RegisterInterface((*crypto.PubKey)(nil), nil) + cdc.RegisterConcrete(ed25519.PubKeyEd25519{}, + ed25519.PubKeyAminoName, nil) + cdc.RegisterConcrete(secp256k1.PubKeySecp256k1{}, + secp256k1.PubKeyAminoName, nil) + cdc.RegisterConcrete(multisig.PubKeyMultisigThreshold{}, + multisig.PubKeyMultisigThresholdAminoRoute, nil) + + cdc.RegisterInterface((*crypto.PrivKey)(nil), nil) + cdc.RegisterConcrete(ed25519.PrivKeyEd25519{}, + ed25519.PrivKeyAminoName, nil) + cdc.RegisterConcrete(secp256k1.PrivKeySecp256k1{}, + secp256k1.PrivKeyAminoName, nil) +} + +func registerEvidenceMessages(cdc *amino.Codec) { + cdc.RegisterInterface((*evidence.Message)(nil), nil) + cdc.RegisterConcrete(&evidence.ListMessage{}, + "tendermint/evidence/EvidenceListMessage", nil) + cdc.RegisterInterface((*tmTypes.Evidence)(nil), nil) + cdc.RegisterConcrete(&tmTypes.DuplicateVoteEvidence{}, "tendermint/DuplicateVoteEvidence", nil) +} + func runAPI(logger tmLog.Logger, app *minter.Blockchain, client *rpc.Local, node *tmNode.Node) { + cdc := amino.NewCodec() + registerCryptoAmino(cdc) + eventsdb.RegisterAminoEvents(cdc) + registerEvidenceMessages(cdc) go func(srv *serviceApi.Service) { grpcURL, err := url.Parse(cfg.GRPCListenAddress) if err != nil { @@ -119,9 +155,9 @@ func runAPI(logger tmLog.Logger, app *minter.Blockchain, client *rpc.Local, node } logger.Error("Failed to start Api V2 in both gRPC and RESTful", apiV2.Run(srv, grpcURL.Host, apiV2url.Host, logger.With("module", "rpc"))) - }(serviceApi.NewService(amino.NewCodec(), app, client, node, cfg, version.Version)) + }(serviceApi.NewService(cdc, app, client, node, cfg, version.Version)) - go apiV1.RunAPI(app, client, cfg, logger) + go apiV1.RunAPI(cdc, app, client, cfg, logger) } func enablePprof(cmd *cobra.Command, logger tmLog.Logger) error { From ed0713fce4b4678add7341ee87590caade372705 Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 13 Oct 2020 18:48:21 +0300 Subject: [PATCH 394/426] fix evidence --- api/v2/service/block.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/api/v2/service/block.go b/api/v2/service/block.go index 1cb953cd6..49e157454 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/hex" - "encoding/json" "fmt" "github.com/MinterTeam/minter-go-node/core/rewards" "github.com/MinterTeam/minter-go-node/core/state" @@ -174,12 +173,7 @@ func blockEvidence(block *core_types.ResultBlock) (*pb.BlockResponse_Evidence, e if err != nil { return nil, status.Error(codes.Internal, err.Error()) } - marshal, err := json.Marshal(proto) - if err != nil { - return nil, err - } - - str, err := encodeToStruct(marshal) + str, err := toStruct(proto) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } From 25f50da33b9d880747885ec6c4b2767cadaa8ffd Mon Sep 17 00:00:00 2001 From: klim0v Date: Tue, 13 Oct 2020 18:55:22 +0300 Subject: [PATCH 395/426] fix evidence --- api/v2/service/block.go | 2 +- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/v2/service/block.go b/api/v2/service/block.go index 49e157454..88d86a048 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -173,7 +173,7 @@ func blockEvidence(block *core_types.ResultBlock) (*pb.BlockResponse_Evidence, e if err != nil { return nil, status.Error(codes.Internal, err.Error()) } - str, err := toStruct(proto) + str, err := toStruct(proto.GetSum()) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/go.mod b/go.mod index b8ecb3603..cf6e74913 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201013150426-ead4ac3b38a1 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201013155331-4553afd65e47 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 3efd5edb9..5907d60a2 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201013150426-ead4ac3b38a1 h1:Hfrty7j5jlcPlf4ER2xsDohI5CJChKwy4fzTfFgNT5Q= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201013150426-ead4ac3b38a1/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201013155331-4553afd65e47 h1:QF4GtwN2nmudlctx8M1q08NmOYVAM8Pq4Idq283m0vg= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201013155331-4553afd65e47/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From 86f6ca7b4b225d21ef6619dcdcdf55f00af07c8e Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 14 Oct 2020 13:15:49 +0300 Subject: [PATCH 396/426] check state tests --- core/minter/minter_test.go | 50 +++++++++++++++++++-- core/state/candidates_test.go | 84 +++++++++++++++++++++++++++++++++-- 2 files changed, 127 insertions(+), 7 deletions(-) diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index bd5349a05..21eb0d787 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -233,6 +233,13 @@ func TestBlockchain_Height(t *testing.T) { if block.Data.(types2.EventDataNewBlock).Block.Height != int64(blockchain.Height()) { t.Fatal("invalid blockchain height") } + + blockchain.lock.RLock() + defer blockchain.lock.RUnlock() + exportedState := blockchain.CurrentState().Export(blockchain.Height() - 1) + if err := exportedState.Verify(); err != nil { + t.Fatal(err) + } } func TestBlockchain_SetStatisticData(t *testing.T) { @@ -249,6 +256,13 @@ func TestBlockchain_SetStatisticData(t *testing.T) { if block.Data.(types2.EventDataNewBlock).Block.Header.Time.Nanosecond() != blockchain.StatisticData().BlockEnd.LastBlockInfo.HeaderTimestamp.Nanosecond() { t.Fatal("statistic last block and event event last block header time not equal") } + + blockchain.lock.RLock() + defer blockchain.lock.RUnlock() + exportedState := blockchain.CurrentState().Export(blockchain.Height() - 1) + if err := exportedState.Verify(); err != nil { + t.Fatal(err) + } } func TestBlockchain_IsApplicationHalted(t *testing.T) { @@ -304,6 +318,12 @@ func TestBlockchain_IsApplicationHalted(t *testing.T) { t.Fatalf("don't stop on block %d", height) return case <-time.After(2 * time.Second): + blockchain.lock.RLock() + defer blockchain.lock.RUnlock() + exportedState := blockchain.CurrentState().Export(blockchain.Height() - 1) + if err := exportedState.Verify(); err != nil { + t.Fatal(err) + } return } } @@ -379,6 +399,13 @@ func TestBlockchain_GetStateForHeightAndDeleteStateVersions(t *testing.T) { if err == nil { t.Fatalf("Failed: %s", "state not deleted") } + + blockchain.lock.RLock() + defer blockchain.lock.RUnlock() + exportedState := blockchain.CurrentState().Export(blockchain.Height() - 1) + if err := exportedState.Verify(); err != nil { + t.Fatal(err) + } } func TestBlockchain_SendTx(t *testing.T) { @@ -437,6 +464,13 @@ func TestBlockchain_SendTx(t *testing.T) { case <-time.After(10 * time.Second): t.Fatalf("Timeout waiting for the tx to be committed") } + + blockchain.lock.RLock() + defer blockchain.lock.RUnlock() + exportedState := blockchain.CurrentState().Export(blockchain.Height() - 1) + if err := exportedState.Verify(); err != nil { + t.Fatal(err) + } } func TestBlockchain_FrozenFunds(t *testing.T) { @@ -466,6 +500,11 @@ func TestBlockchain_FrozenFunds(t *testing.T) { blockchain.lock.RLock() defer blockchain.lock.RLock() + exportedState := blockchain.CurrentState().Export(blockchain.Height() - 1) + if err := exportedState.Verify(); err != nil { + t.Fatal(err) + } + events := blockchain.GetEventsDB().LoadEvents(uint32(targetHeight)) if len(events) == 0 { @@ -481,10 +520,6 @@ func TestBlockchain_FrozenFunds(t *testing.T) { t.Error("event validator pubkey invalid") } - balance := blockchain.CurrentState().Accounts().GetBalance(developers.Address, 0) - if balance.String() != value.String() { - t.Fatal("balance is empty") - } } func TestBlockchain_RecalculateStakes_andRemoveValidator(t *testing.T) { @@ -720,6 +755,13 @@ func TestBlockchain_RecalculateStakes_andRemoveValidator(t *testing.T) { if candidate.Status == candidates.CandidateStatusOnline { t.Fatal("candidate not Offline") } + + blockchain.lock.RLock() + defer blockchain.lock.RUnlock() + exportedState := blockchain.CurrentState().Export(blockchain.Height() - 1) + if err := exportedState.Verify(); err != nil { + t.Fatal(err) + } } func TestStopNetworkByHaltBlocks(t *testing.T) { diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index 3c6ae38ed..b3d572d0f 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -13,7 +13,7 @@ import ( "testing" ) -const height = 500000 +const height = 1 func TestSimpleDelegate(t *testing.T) { st := getState() @@ -38,6 +38,11 @@ func TestSimpleDelegate(t *testing.T) { if stake.BipValue.Cmp(amount) != 0 { t.Errorf("Bip value of stake of address %s should be %s, got %s", address.String(), amount.String(), stake.BipValue.String()) } + + err := checkState(st) + if err != nil { + t.Error(err) + } } func TestDelegate(t *testing.T) { @@ -68,6 +73,11 @@ func TestDelegate(t *testing.T) { if stake.BipValue.Cmp(totalAmount) != 0 { t.Errorf("Bip value of stake of address %s should be %s, got %s", address.String(), amount.String(), stake.BipValue.String()) } + + err := checkState(st) + if err != nil { + t.Error(err) + } } func TestCustomDelegate(t *testing.T) { @@ -78,6 +88,7 @@ func TestCustomDelegate(t *testing.T) { coinID := st.App.GetNextCoinID() st.Coins.Create(coinID, types.StrToCoinSymbol("TEST"), "TEST COIN", volume, 10, reserve, volume, nil) + st.Accounts.AddBalance([20]byte{1}, 1, helpers.BipToPip(big.NewInt(1000000-500000))) st.App.SetCoinsCount(coinID.Uint32()) address := types.Address{} @@ -100,6 +111,11 @@ func TestCustomDelegate(t *testing.T) { if stake.BipValue.Cmp(bipValue) != 0 { t.Errorf("Bip value of stake of address %s should be %s, got %s", address.String(), bipValue.String(), stake.BipValue.String()) } + + err := checkState(st) + if err != nil { + t.Error(err) + } } func TestComplexDelegate(t *testing.T) { @@ -200,6 +216,11 @@ func TestComplexDelegate(t *testing.T) { t.Fatalf("Stake of address %s found, but should not be", addr.String()) } } + + err := checkState(st) + if err != nil { + t.Error(err) + } } func TestStakeSufficiency(t *testing.T) { @@ -249,6 +270,11 @@ func TestStakeSufficiency(t *testing.T) { t.Fatalf("Stake of %s %s of address %s shold be sufficient", stake.String(), coin.String(), addr.String()) } } + + err := checkState(st) + if err != nil { + t.Error(err) + } } func TestDoubleSignPenalty(t *testing.T) { @@ -300,6 +326,11 @@ func TestDoubleSignPenalty(t *testing.T) { if !exists { t.Fatalf("Frozen fund not found") } + + err := checkState(st) + if err != nil { + t.Error(err) + } } func TestAbsentPenalty(t *testing.T) { @@ -330,6 +361,11 @@ func TestAbsentPenalty(t *testing.T) { if stake.Cmp(newValue) != 0 { t.Fatalf("Stake is not correct. Expected %s, got %s", newValue, stake.String()) } + + err := checkState(st) + if err != nil { + t.Error(err) + } } func TestDoubleAbsentPenalty(t *testing.T) { @@ -338,10 +374,10 @@ func TestDoubleAbsentPenalty(t *testing.T) { pubkey := createTestCandidate(st) coin := types.GetBaseCoinID() - amount := helpers.BipToPip(big.NewInt(1000)) + amount := helpers.BipToPip(big.NewInt(10000)) var addr types.Address binary.BigEndian.PutUint64(addr[:], 1) - st.Candidates.Delegate(addr, pubkey, coin, amount, big.NewInt(0)) + st.Candidates.Delegate(addr, pubkey, coin, amount, amount) st.Candidates.SetOnline(pubkey) st.Candidates.RecalculateStakes(height) @@ -366,6 +402,13 @@ func TestDoubleAbsentPenalty(t *testing.T) { if stake.Cmp(newValue) != 0 { t.Fatalf("Stake is not correct. Expected %s, got %s", newValue, stake.String()) } + + st.Candidates.SetOnline(pubkey) + st.Validators.SetNewValidators(st.Candidates.GetNewCandidates(1)) + err := checkState(st) + if err != nil { + t.Error(err) + } } func TestZeroStakePenalty(t *testing.T) { @@ -398,6 +441,11 @@ func TestZeroStakePenalty(t *testing.T) { if stake.Cmp(newValue) != 0 { t.Fatalf("Stake is not correct. Expected %s, got %s", newValue, stake.String()) } + + err := checkState(st) + if err != nil { + t.Error(err) + } } func TestDelegationAfterUnbond(t *testing.T) { @@ -457,6 +505,11 @@ func TestDelegationAfterUnbond(t *testing.T) { } } + err := checkState(st) + if err != nil { + t.Error(err) + } + } func TestStakeKick(t *testing.T) { @@ -494,6 +547,11 @@ func TestStakeKick(t *testing.T) { if wl.Value.Cmp(big.NewInt(1)) != 0 { t.Fatalf("Waitlist is not correct") } + + err := checkState(st) + if err != nil { + t.Error(err) + } } func TestRecalculateStakes(t *testing.T) { @@ -502,6 +560,7 @@ func TestRecalculateStakes(t *testing.T) { st.Coins.Create(1, [10]byte{1}, "TestCoin", helpers.BipToPip(big.NewInt(100000)), 70, helpers.BipToPip(big.NewInt(10000)), nil, nil) pubkey := createTestCandidate(st) + st.Accounts.AddBalance([20]byte{1}, 1, helpers.BipToPip(big.NewInt(100000-1000))) amount := helpers.BipToPip(big.NewInt(1000)) st.Candidates.Delegate([20]byte{1}, pubkey, 1, amount, big.NewInt(0)) @@ -518,6 +577,11 @@ func TestRecalculateStakes(t *testing.T) { if stake.BipValue.String() != "13894954943731374342" { t.Errorf("stake bip value is %s", stake.BipValue.String()) } + + err = checkState(st) + if err != nil { + t.Error(err) + } } func getState() *State { @@ -530,11 +594,25 @@ func getState() *State { return s } +func checkState(cState *State) error { + if _, err := cState.Commit(); err != nil { + return err + } + + exportedState := cState.Export(height) + if err := exportedState.Verify(); err != nil { + return err + } + + return nil +} + func createTestCandidate(stateDB *State) types.Pubkey { address := types.Address{} pubkey := types.Pubkey{} _, _ = rand.Read(pubkey[:]) + stateDB.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1000))) stateDB.Candidates.Create(address, address, address, pubkey, 10) return pubkey From 6e93277da57c852bcc386637559fd39b70ff426b Mon Sep 17 00:00:00 2001 From: klim0v Date: Wed, 14 Oct 2020 13:27:06 +0300 Subject: [PATCH 397/426] check state tests --- core/state/state_test.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/core/state/state_test.go b/core/state/state_test.go index c096fb24b..47b88f19b 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -30,7 +30,7 @@ func TestStateExport(t *testing.T) { coinTestID, coinTest, "TEST", - helpers.BipToPip(big.NewInt(1)), + helpers.BipToPip(big.NewInt(601)), 10, helpers.BipToPip(big.NewInt(100)), helpers.BipToPip(big.NewInt(100)), @@ -41,7 +41,7 @@ func TestStateExport(t *testing.T) { coinTest2ID, coinTest2, "TEST2", - helpers.BipToPip(big.NewInt(2)), + helpers.BipToPip(big.NewInt(1002)), 50, helpers.BipToPip(big.NewInt(200)), helpers.BipToPip(big.NewInt(200)), @@ -107,6 +107,10 @@ func TestStateExport(t *testing.T) { newState := state.Export(height) + if err := newState.Verify(); err != nil { + t.Error(err) + } + if newState.StartHeight != height { t.Fatalf("Wrong new state start height. Expected %d, got %d", height, newState.StartHeight) } @@ -128,7 +132,7 @@ func TestStateExport(t *testing.T) { if newStateCoin.Name != "TEST" || newStateCoin.Symbol != coinTest || - newStateCoin.Volume != helpers.BipToPip(big.NewInt(1)).String() || + newStateCoin.Volume != helpers.BipToPip(big.NewInt(601)).String() || newStateCoin.Reserve != helpers.BipToPip(big.NewInt(100)).String() || newStateCoin.MaxSupply != helpers.BipToPip(big.NewInt(100)).String() || newStateCoin.Crr != 10 { @@ -137,7 +141,7 @@ func TestStateExport(t *testing.T) { if newStateCoin1.Name != "TEST2" || newStateCoin1.Symbol != coinTest2 || - newStateCoin1.Volume != helpers.BipToPip(big.NewInt(2)).String() || + newStateCoin1.Volume != helpers.BipToPip(big.NewInt(1002)).String() || newStateCoin1.Reserve != helpers.BipToPip(big.NewInt(200)).String() || newStateCoin1.MaxSupply != helpers.BipToPip(big.NewInt(200)).String() || newStateCoin1.Crr != 50 { From 35705e29f1cc71abe75d084ba8b9c5d041e4fe30 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 14 Oct 2020 14:34:36 +0300 Subject: [PATCH 398/426] Refactor --- core/minter/minter_test.go | 3 +-- core/state/candidates/candidates.go | 15 +++++---------- core/state/candidates/model.go | 10 +++++----- core/state/validators/model.go | 8 ++++---- core/state/validators/validators.go | 23 +++++++++++++++-------- core/state/validators/validators_test.go | 12 ++++++------ 6 files changed, 36 insertions(+), 35 deletions(-) diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index bd5349a05..1b8f2bee2 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -12,7 +12,6 @@ import ( "github.com/MinterTeam/minter-go-node/core/developers" eventsdb "github.com/MinterTeam/minter-go-node/core/events" candidates2 "github.com/MinterTeam/minter-go-node/core/state/candidates" - "github.com/MinterTeam/minter-go-node/core/state/validators" "github.com/MinterTeam/minter-go-node/core/statistics" "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/MinterTeam/minter-go-node/core/types" @@ -703,7 +702,7 @@ func TestBlockchain_RecalculateStakes_andRemoveValidator(t *testing.T) { t.Fatal(err) } - targetHeight := int64(123 + validators.ValidatorMaxAbsentTimes) + targetHeight := int64(123 + 12) // 12 = ValidatorMaxAbsentTimes for block := range blocks { if block.Data.(types2.EventDataNewBlock).Block.Height <= targetHeight { continue diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 9bb3299c4..9c341f30e 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -84,6 +84,7 @@ func NewCandidates(bus *bus.Bus, iavl tree.MTree) (*Candidates, error) { bus: bus, blockList: map[types.Pubkey]struct{}{}, pubKeyIDs: map[types.Pubkey]uint32{}, + list: map[uint32]*Candidate{}, } candidates.bus.SetCandidates(NewBus(candidates)) @@ -490,15 +491,13 @@ func (c *Candidates) IsDelegatorStakeSufficient(address types.Address, pubkey ty // Delegate adds a stake to a candidate func (c *Candidates) Delegate(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int, bipValue *big.Int) { - stake := &stake{ + candidate := c.GetCandidate(pubkey) + candidate.addUpdate(&stake{ Owner: address, Coin: coin, Value: big.NewInt(0).Set(value), BipValue: big.NewInt(0).Set(bipValue), - } - - candidate := c.GetCandidate(pubkey) - candidate.addUpdate(stake) + }) c.bus.Checker().AddCoin(coin, value) } @@ -523,8 +522,7 @@ func (c *Candidates) SetOffline(pubkey types.Pubkey) { // SubStake subs given value from delegator's stake func (c *Candidates) SubStake(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { - stake := c.GetStakeOfAddress(pubkey, address, coin) - stake.subValue(value) + c.GetStakeOfAddress(pubkey, address, coin).subValue(value) c.bus.Checker().AddCoin(coin, big.NewInt(0).Neg(value)) } @@ -930,9 +928,6 @@ func (c *Candidates) setToMap(pubkey types.Pubkey, model *Candidate) { c.lock.Lock() defer c.lock.Unlock() - if c.list == nil { - c.list = map[uint32]*Candidate{} - } c.list[id] = model } diff --git a/core/state/candidates/model.go b/core/state/candidates/model.go index 78c3e8ff0..359b8a7ac 100644 --- a/core/state/candidates/model.go +++ b/core/state/candidates/model.go @@ -120,7 +120,7 @@ func (candidate *Candidate) getFilteredUpdates() []*stake { merged := false for _, u := range updates { if u.Coin == update.Coin && u.Owner == update.Owner { - u.Value.Add(u.Value, update.Value) + u.Value = big.NewInt(0).Add(u.Value, update.Value) merged = true break } @@ -180,12 +180,12 @@ type stake struct { func (stake *stake) addValue(value *big.Int) { stake.markDirty(stake.index) - stake.Value.Add(stake.Value, value) + stake.Value = big.NewInt(0).Add(stake.Value, value) } func (stake *stake) subValue(value *big.Int) { stake.markDirty(stake.index) - stake.Value.Sub(stake.Value, value) + stake.Value = big.NewInt(0).Sub(stake.Value, value) } func (stake *stake) setBipValue(value *big.Int) { @@ -193,10 +193,10 @@ func (stake *stake) setBipValue(value *big.Int) { stake.markDirty(stake.index) } - stake.BipValue.Set(value) + stake.BipValue = big.NewInt(0).Set(value) } func (stake *stake) setValue(ret *big.Int) { stake.markDirty(stake.index) - stake.Value.Set(ret) + stake.Value = big.NewInt(0).Set(ret) } diff --git a/core/state/validators/model.go b/core/state/validators/model.go index 248c72777..1d5c0a510 100644 --- a/core/state/validators/model.go +++ b/core/state/validators/model.go @@ -71,7 +71,7 @@ func (v *Validator) SetTotalBipStake(value *big.Int) { return } v.isTotalStakeDirty = true - v.totalStake = value + v.totalStake = big.NewInt(0).Set(value) } func (v *Validator) AddAccumReward(amount *big.Int) { @@ -81,7 +81,7 @@ func (v *Validator) AddAccumReward(amount *big.Int) { func (v *Validator) CountAbsentTimes() int { count := 0 - for i := 0; i < ValidatorMaxAbsentWindow; i++ { + for i := 0; i < validatorMaxAbsentWindow; i++ { if v.AbsentTimes.GetIndex(i) { count++ } @@ -102,7 +102,7 @@ func (v *Validator) setTmAddress() { } func (v *Validator) SetPresent(height uint64) { - index := int(height) % ValidatorMaxAbsentWindow + index := int(height) % validatorMaxAbsentWindow if v.AbsentTimes.GetIndex(index) { v.isDirty = true } @@ -110,7 +110,7 @@ func (v *Validator) SetPresent(height uint64) { } func (v *Validator) SetAbsent(height uint64) { - index := int(height) % ValidatorMaxAbsentWindow + index := int(height) % validatorMaxAbsentWindow if !v.AbsentTimes.GetIndex(index) { v.isDirty = true } diff --git a/core/state/validators/validators.go b/core/state/validators/validators.go index 111fd201f..fd0dffc48 100644 --- a/core/state/validators/validators.go +++ b/core/state/validators/validators.go @@ -22,8 +22,8 @@ const ( ) const ( - ValidatorMaxAbsentWindow = 24 - ValidatorMaxAbsentTimes = 12 + validatorMaxAbsentWindow = 24 + validatorMaxAbsentTimes = 12 ) // Validators struct is a store of Validators state @@ -86,6 +86,7 @@ func (v *Validators) Commit() error { return nil } +// SetValidatorPresent marks validator as present at current height func (v *Validators) SetValidatorPresent(height uint64, address types.TmAddress) { validator := v.GetByTmAddress(address) if validator == nil { @@ -94,6 +95,8 @@ func (v *Validators) SetValidatorPresent(height uint64, address types.TmAddress) validator.SetPresent(height) } +// SetValidatorAbsent marks validator as absent at current height +// if validator misses signs of more than validatorMaxAbsentTimes, it will receive penalty and will be swithed off func (v *Validators) SetValidatorAbsent(height uint64, address types.TmAddress) { validator := v.GetByTmAddress(address) if validator == nil { @@ -101,7 +104,7 @@ func (v *Validators) SetValidatorAbsent(height uint64, address types.TmAddress) } validator.SetAbsent(height) - if validator.CountAbsentTimes() > ValidatorMaxAbsentTimes { + if validator.CountAbsentTimes() > validatorMaxAbsentTimes { if !upgrades.IsGraceBlock(height) { v.punishValidator(height, address) } @@ -115,13 +118,14 @@ func (v *Validators) GetValidators() []*Validator { return v.list } +// SetNewValidators updated validators list with new candidates func (v *Validators) SetNewValidators(candidates []candidates.Candidate) { old := v.GetValidators() var newVals []*Validator for _, candidate := range candidates { accumReward := big.NewInt(0) - absentTimes := types.NewBitArray(ValidatorMaxAbsentWindow) + absentTimes := types.NewBitArray(validatorMaxAbsentWindow) for _, oldVal := range old { if oldVal.GetAddress() == candidate.GetTmAddress() { @@ -162,8 +166,8 @@ func (v *Validators) PunishByzantineValidator(tmAddress [20]byte) { func (v *Validators) Create(pubkey types.Pubkey, stake *big.Int) { val := &Validator{ PubKey: pubkey, - AbsentTimes: types.NewBitArray(ValidatorMaxAbsentWindow), - totalStake: stake, + AbsentTimes: types.NewBitArray(validatorMaxAbsentWindow), + totalStake: big.NewInt(0).Set(stake), accumReward: big.NewInt(0), isDirty: true, isTotalStakeDirty: true, @@ -174,6 +178,7 @@ func (v *Validators) Create(pubkey types.Pubkey, stake *big.Int) { v.list = append(v.list, val) } +// PayRewards distributes accumulated rewards between validator, delegators, DAO and developers addresses func (v *Validators) PayRewards(height uint64) { vals := v.GetValidators() for _, validator := range vals { @@ -354,6 +359,7 @@ func (v *Validators) punishValidator(height uint64, tmAddress types.TmAddress) { validator.SetTotalBipStake(totalStake) } +// SetValidators updates validators list func (v *Validators) SetValidators(vals []*Validator) { v.list = vals } @@ -372,6 +378,7 @@ func (v *Validators) Export(state *types.AppState) { } } +// SetToDrop marks given validator as inactive for dropping it in the next block func (v *Validators) SetToDrop(pubkey types.Pubkey) { vals := v.GetValidators() for _, val := range vals { @@ -383,9 +390,9 @@ func (v *Validators) SetToDrop(pubkey types.Pubkey) { func (v *Validators) turnValidatorOff(tmAddress types.TmAddress) { validator := v.GetByTmAddress(tmAddress) - validator.AbsentTimes = types.NewBitArray(ValidatorMaxAbsentWindow) + validator.AbsentTimes = types.NewBitArray(validatorMaxAbsentWindow) validator.toDrop = true validator.isDirty = true - v.bus.Candidates().SetOffline(v.bus.Candidates().GetCandidateByTendermintAddress(tmAddress).PubKey) + v.bus.Candidates().SetOffline(validator.PubKey) } diff --git a/core/state/validators/validators_test.go b/core/state/validators/validators_test.go index 09908d1f7..abf2a2c8b 100644 --- a/core/state/validators/validators_test.go +++ b/core/state/validators/validators_test.go @@ -127,7 +127,7 @@ func TestValidators_LoadValidators(t *testing.T) { newValidator := NewValidator( [32]byte{1}, - types.NewBitArray(ValidatorMaxAbsentWindow), + types.NewBitArray(validatorMaxAbsentWindow), big.NewInt(1000000), big.NewInt(0), true, @@ -180,7 +180,7 @@ func TestValidators_SetValidators(t *testing.T) { newValidator := NewValidator( [32]byte{1}, - types.NewBitArray(ValidatorMaxAbsentWindow), + types.NewBitArray(validatorMaxAbsentWindow), big.NewInt(1000000), big.NewInt(0), true, @@ -222,7 +222,7 @@ func TestValidators_PayRewards(t *testing.T) { } newValidator := NewValidator( [32]byte{4}, - types.NewBitArray(ValidatorMaxAbsentWindow), + types.NewBitArray(validatorMaxAbsentWindow), big.NewInt(1000000), big.NewInt(10), true, @@ -290,7 +290,7 @@ func TestValidators_SetValidatorAbsent(t *testing.T) { } newValidator := NewValidator( [32]byte{4}, - types.NewBitArray(ValidatorMaxAbsentWindow), + types.NewBitArray(validatorMaxAbsentWindow), big.NewInt(1000000), big.NewInt(100), true, @@ -320,7 +320,7 @@ func TestValidators_SetValidatorAbsent(t *testing.T) { if validator == nil { t.Fatal("validator not found") } - for i := uint64(0); i < ValidatorMaxAbsentTimes+1; i++ { + for i := uint64(0); i < validatorMaxAbsentTimes+1; i++ { validators.SetValidatorAbsent(i, validator.tmAddress) } if !validator.IsToDrop() { @@ -402,7 +402,7 @@ func TestValidators_Export(t *testing.T) { } newValidator := NewValidator( [32]byte{4}, - types.NewBitArray(ValidatorMaxAbsentWindow), + types.NewBitArray(validatorMaxAbsentWindow), helpers.BipToPip(big.NewInt(1000000)), big.NewInt(100), true, From 674b9cf9386ec9fce88a44b55674f97ff976f70a Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 14 Oct 2020 14:55:04 +0300 Subject: [PATCH 399/426] Refactor --- core/state/accounts/accounts.go | 15 ++++++--------- core/state/accounts/accounts_test.go | 8 ++++---- core/state/state.go | 2 +- core/transaction/create_multisig.go | 2 +- core/transaction/create_multisig_test.go | 2 +- core/transaction/edit_multisig_test.go | 12 ++++++------ core/transaction/executor_test.go | 10 +++++----- core/transaction/send_test.go | 4 ++-- 8 files changed, 26 insertions(+), 29 deletions(-) diff --git a/core/state/accounts/accounts.go b/core/state/accounts/accounts.go index 2155d7ceb..405743805 100644 --- a/core/state/accounts/accounts.go +++ b/core/state/accounts/accounts.go @@ -190,15 +190,8 @@ func (a *Accounts) ExistsMultisig(msigAddress types.Address) bool { return false } -func (a *Accounts) CreateMultisig(weights []uint32, addresses []types.Address, threshold uint32, height uint64, address types.Address) types.Address { - msig := Multisig{ - Weights: weights, - Threshold: threshold, - Addresses: addresses, - } - +func (a *Accounts) CreateMultisig(weights []uint32, addresses []types.Address, threshold uint32, address types.Address) types.Address { account := a.get(address) - if account == nil { account = &Model{ Nonce: 0, @@ -211,7 +204,11 @@ func (a *Accounts) CreateMultisig(weights []uint32, addresses []types.Address, t } } - account.MultisigData = msig + account.MultisigData = Multisig{ + Weights: weights, + Threshold: threshold, + Addresses: addresses, + } account.markDirty(account.address) account.isDirty = true a.setToMap(address, account) diff --git a/core/state/accounts/accounts_test.go b/core/state/accounts/accounts_test.go index eefcde863..f7a591208 100644 --- a/core/state/accounts/accounts_test.go +++ b/core/state/accounts/accounts_test.go @@ -22,7 +22,7 @@ func TestAccounts_CreateMultisig(t *testing.T) { if err != nil { t.Fatal(err) } - multisigAddr := accounts.CreateMultisig([]uint32{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, 2, 0, [20]byte{4}) + multisigAddr := accounts.CreateMultisig([]uint32{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, 2, [20]byte{4}) account := accounts.GetAccount(multisigAddr) if account == nil { @@ -209,7 +209,7 @@ func TestAccounts_ExistsMultisig(t *testing.T) { accounts.SetNonce(msigAddress, 0) - _ = accounts.CreateMultisig([]uint32{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, 2, 0, msigAddress) + _ = accounts.CreateMultisig([]uint32{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, 2, msigAddress) if !accounts.ExistsMultisig(msigAddress) { t.Fatal("multisig address is free") @@ -265,7 +265,7 @@ func TestAccounts_EditMultisig(t *testing.T) { msigAddress := CreateMultisigAddress([20]byte{4}, 12) - _ = accounts.CreateMultisig([]uint32{3, 3, 6}, []types.Address{[20]byte{1, 1}, [20]byte{2, 3}, [20]byte{3, 3}}, 6, 0, msigAddress) + _ = accounts.CreateMultisig([]uint32{3, 3, 6}, []types.Address{[20]byte{1, 1}, [20]byte{2, 3}, [20]byte{3, 3}}, 6, msigAddress) _ = accounts.EditMultisig(2, []uint32{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, msigAddress) account := accounts.GetAccount(msigAddress) @@ -361,7 +361,7 @@ func TestAccounts_Export(t *testing.T) { } accounts.SetBalance([20]byte{4}, symbol.ID(), big.NewInt(1001)) - _ = accounts.CreateMultisig([]uint32{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, 2, 0, [20]byte{4}) + _ = accounts.CreateMultisig([]uint32{1, 1, 2}, []types.Address{[20]byte{1}, [20]byte{2}, [20]byte{3}}, 2, [20]byte{4}) err = accounts.Commit() if err != nil { diff --git a/core/state/state.go b/core/state/state.go index 734d521b5..cbf53cb60 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -300,7 +300,7 @@ func (s *State) Import(state types.AppState) error { for _, weight := range a.MultisigData.Weights { weights = append(weights, uint32(weight)) } - s.Accounts.CreateMultisig(weights, a.MultisigData.Addresses, uint32(a.MultisigData.Threshold), 1, a.Address) + s.Accounts.CreateMultisig(weights, a.MultisigData.Addresses, uint32(a.MultisigData.Threshold), a.Address) } s.Accounts.SetNonce(a.Address, a.Nonce) diff --git a/core/transaction/create_multisig.go b/core/transaction/create_multisig.go index 08c79c360..4b8da6b5c 100644 --- a/core/transaction/create_multisig.go +++ b/core/transaction/create_multisig.go @@ -128,7 +128,7 @@ func (data CreateMultisigData) Run(tx *Transaction, context state.Interface, rew deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) deliverState.Accounts.SetNonce(sender, tx.Nonce) - deliverState.Accounts.CreateMultisig(data.Weights, data.Addresses, data.Threshold, currentBlock, msigAddress) + deliverState.Accounts.CreateMultisig(data.Weights, data.Addresses, data.Threshold, msigAddress) } tags := kv.Pairs{ diff --git a/core/transaction/create_multisig_test.go b/core/transaction/create_multisig_test.go index eb341eb58..2050612ff 100644 --- a/core/transaction/create_multisig_test.go +++ b/core/transaction/create_multisig_test.go @@ -231,7 +231,7 @@ func TestCreateExistingMultisigTx(t *testing.T) { }, } - cState.Accounts.CreateMultisig(data.Weights, data.Addresses, data.Threshold, 1, accounts.CreateMultisigAddress(addr, 1)) + cState.Accounts.CreateMultisig(data.Weights, data.Addresses, data.Threshold, accounts.CreateMultisigAddress(addr, 1)) encodedData, err := rlp.EncodeToBytes(data) if err != nil { diff --git a/core/transaction/edit_multisig_test.go b/core/transaction/edit_multisig_test.go index 2647f330d..39be31419 100644 --- a/core/transaction/edit_multisig_test.go +++ b/core/transaction/edit_multisig_test.go @@ -31,7 +31,7 @@ func TestEditMultisigTx(t *testing.T) { privateKey4, _ := crypto.GenerateKey() addr4 := crypto.PubkeyToAddress(privateKey4.PublicKey) - cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, addr) coin := types.GetBaseCoinID() initialBalance := big.NewInt(1) @@ -156,7 +156,7 @@ func TestEditMultisigTxToTooLargeOwnersList(t *testing.T) { coin := types.GetBaseCoinID() - cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, addr) weights := make([]uint32, 33) for i := uint32(0); i <= 32; i++ { @@ -214,7 +214,7 @@ func TestEditMultisigTxIncorrectWeights(t *testing.T) { coin := types.GetBaseCoinID() - cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, addr) data := EditMultisigData{ Threshold: 3, @@ -310,7 +310,7 @@ func TestEditMultisigTxToAddressDuplication(t *testing.T) { coin := types.GetBaseCoinID() - cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, addr) data := EditMultisigData{ Threshold: 3, @@ -363,7 +363,7 @@ func TestEditMultisigTxToInsufficientFunds(t *testing.T) { coin := types.GetBaseCoinID() - cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, addr) data := EditMultisigData{ Threshold: 3, @@ -417,7 +417,7 @@ func TestEditMultisigTxToGasCoinReserveUnderflow(t *testing.T) { coin := createTestCoin(cState) cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) - cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, 1, addr) + cState.Accounts.CreateMultisig([]uint32{1, 2, 3}, []types.Address{addr1, addr2, addr3}, 3, addr) data := EditMultisigData{ Threshold: 3, diff --git a/core/transaction/executor_test.go b/core/transaction/executor_test.go index f376284a6..5b933cb20 100644 --- a/core/transaction/executor_test.go +++ b/core/transaction/executor_test.go @@ -232,7 +232,7 @@ func TestMultiSigTx(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - msigAddress := cState.Accounts.CreateMultisig([]uint32{1}, []types.Address{addr}, 1, 1, accounts.CreateMultisigAddress(addr, 1)) + msigAddress := cState.Accounts.CreateMultisig([]uint32{1}, []types.Address{addr}, 1, accounts.CreateMultisigAddress(addr, 1)) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ @@ -276,7 +276,7 @@ func TestMultiSigDoubleSignTx(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - msigAddress := cState.Accounts.CreateMultisig([]uint32{1, 1}, []types.Address{addr, {}}, 2, 1, accounts.CreateMultisigAddress(addr, 1)) + msigAddress := cState.Accounts.CreateMultisig([]uint32{1, 1}, []types.Address{addr, {}}, 2, accounts.CreateMultisigAddress(addr, 1)) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ @@ -324,7 +324,7 @@ func TestMultiSigTooManySignsTx(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - msigAddress := cState.Accounts.CreateMultisig([]uint32{1, 1}, []types.Address{addr, {}}, 2, 1, accounts.CreateMultisigAddress(addr, 1)) + msigAddress := cState.Accounts.CreateMultisig([]uint32{1, 1}, []types.Address{addr, {}}, 2, accounts.CreateMultisigAddress(addr, 1)) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ @@ -375,7 +375,7 @@ func TestMultiSigNotEnoughTx(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - msigAddress := cState.Accounts.CreateMultisig([]uint32{1}, []types.Address{addr}, 2, 1, accounts.CreateMultisigAddress(addr, 1)) + msigAddress := cState.Accounts.CreateMultisig([]uint32{1}, []types.Address{addr}, 2, accounts.CreateMultisigAddress(addr, 1)) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ @@ -419,7 +419,7 @@ func TestMultiSigIncorrectSignsTx(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.GetBaseCoinID() - msigAddress := cState.Accounts.CreateMultisig([]uint32{1}, []types.Address{addr}, 1, 1, accounts.CreateMultisigAddress(addr, 1)) + msigAddress := cState.Accounts.CreateMultisig([]uint32{1}, []types.Address{addr}, 1, accounts.CreateMultisigAddress(addr, 1)) cState.Accounts.AddBalance(msigAddress, coin, helpers.BipToPip(big.NewInt(1000000))) txData := SendData{ diff --git a/core/transaction/send_test.go b/core/transaction/send_test.go index 5d9538813..2039da85f 100644 --- a/core/transaction/send_test.go +++ b/core/transaction/send_test.go @@ -84,7 +84,7 @@ func TestSendMultisigTx(t *testing.T) { coin := types.GetBaseCoinID() - msig := cState.Accounts.CreateMultisig([]uint32{1, 1}, []types.Address{addr1, addr2}, 1, 1, accounts.CreateMultisigAddress(addr1, 1)) + msig := cState.Accounts.CreateMultisig([]uint32{1, 1}, []types.Address{addr1, addr2}, 1, accounts.CreateMultisigAddress(addr1, 1)) cState.Accounts.AddBalance(msig, coin, helpers.BipToPip(big.NewInt(1000000))) @@ -152,7 +152,7 @@ func TestSendFailedMultisigTx(t *testing.T) { coin := types.GetBaseCoinID() - msig := cState.Accounts.CreateMultisig([]uint32{1, 3}, []types.Address{addr1, addr2}, 3, 1, accounts.CreateMultisigAddress(addr1, 1)) + msig := cState.Accounts.CreateMultisig([]uint32{1, 3}, []types.Address{addr1, addr2}, 3, accounts.CreateMultisigAddress(addr1, 1)) cState.Accounts.AddBalance(msig, coin, helpers.BipToPip(big.NewInt(1000000))) From 221b66ed37cd1f419042be803ecca514a8645de0 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 14 Oct 2020 15:12:47 +0300 Subject: [PATCH 400/426] Refactor --- core/state/candidates/candidates.go | 10 +++++----- core/state/candidates/coins_cache.go | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 9c341f30e..2b55958b0 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -721,9 +721,9 @@ func (c *Candidates) calculateBipValue(coinID types.CoinID, amount *big.Int, inc coin := c.bus.Coins().GetCoin(coinID) - saleReturn, totalDelegatedValue := big.NewInt(0), big.NewInt(0) + totalDelegatedBasecoin, totalDelegatedValue := big.NewInt(0), big.NewInt(0) if coinsCache.Exists(coinID) { - saleReturn, totalDelegatedValue = coinsCache.Get(coinID) + totalDelegatedBasecoin, totalDelegatedValue = coinsCache.Get(coinID) } if includeSelf { @@ -749,11 +749,11 @@ func (c *Candidates) calculateBipValue(coinID types.CoinID, amount *big.Int, inc } nonLockedSupply := big.NewInt(0).Sub(coin.Volume, totalDelegatedValue) - saleReturn = formula.CalculateSaleReturn(coin.Volume, coin.Reserve, coin.Crr, nonLockedSupply) - coinsCache.Set(coinID, saleReturn, totalDelegatedValue) + totalDelegatedBasecoin = big.NewInt(0).Sub(coin.Reserve, formula.CalculateSaleReturn(coin.Volume, coin.Reserve, coin.Crr, nonLockedSupply)) + coinsCache.Set(coinID, totalDelegatedBasecoin, totalDelegatedValue) } - return big.NewInt(0).Div(big.NewInt(0).Mul(big.NewInt(0).Sub(coin.Reserve, saleReturn), amount), totalDelegatedValue) + return big.NewInt(0).Div(big.NewInt(0).Mul(totalDelegatedBasecoin, amount), totalDelegatedValue) } // Punish punished a candidate with given tendermint-address diff --git a/core/state/candidates/coins_cache.go b/core/state/candidates/coins_cache.go index d18961dd0..55140ce43 100644 --- a/core/state/candidates/coins_cache.go +++ b/core/state/candidates/coins_cache.go @@ -14,8 +14,8 @@ func newCoinsCache() *coinsCache { } type coinsCacheItem struct { - saleReturn *big.Int - totalAmount *big.Int + totalBasecoin *big.Int + totalAmount *big.Int } func (c *coinsCache) Exists(id types.CoinID) bool { @@ -28,11 +28,11 @@ func (c *coinsCache) Exists(id types.CoinID) bool { return exists } -func (c *coinsCache) Get(id types.CoinID) (saleReturn *big.Int, totalAmount *big.Int) { - return big.NewInt(0).Set(c.list[id].saleReturn), big.NewInt(0).Set(c.list[id].totalAmount) +func (c *coinsCache) Get(id types.CoinID) (totalBasecoin *big.Int, totalAmount *big.Int) { + return big.NewInt(0).Set(c.list[id].totalBasecoin), big.NewInt(0).Set(c.list[id].totalAmount) } -func (c *coinsCache) Set(id types.CoinID, saleReturn *big.Int, totalAmount *big.Int) { +func (c *coinsCache) Set(id types.CoinID, totalBasecoin *big.Int, totalAmount *big.Int) { if c == nil { return } @@ -42,5 +42,5 @@ func (c *coinsCache) Set(id types.CoinID, saleReturn *big.Int, totalAmount *big. } c.list[id].totalAmount = big.NewInt(0).Set(totalAmount) - c.list[id].saleReturn = big.NewInt(0).Set(saleReturn) + c.list[id].totalBasecoin = big.NewInt(0).Set(totalBasecoin) } From 2f0c6d3b9737053265dc9679b685f53d9fde831b Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 14 Oct 2020 16:39:10 +0300 Subject: [PATCH 401/426] Refactor --- core/state/coins/coins.go | 4 ++-- core/state/coins/model.go | 4 ++-- core/transaction/edit_coin_owner.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index 6fe1c6869..6fa7ce0f4 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -267,12 +267,12 @@ func (c *Coins) Recreate(newID types.CoinID, name string, symbol types.CoinSymbo func (c *Coins) ChangeOwner(symbol types.CoinSymbol, owner types.Address) { info := c.getSymbolInfo(symbol) - info.SetOwnerAddress(&owner) + info.setOwnerAddress(owner) coin := c.GetCoinBySymbol(symbol, 0) coin.symbolInfo = info - c.setToMap(coin.id, coin) + c.setToMap(coin.ID(), coin) c.markDirty(coin.ID()) } diff --git a/core/state/coins/model.go b/core/state/coins/model.go index 0e265716c..c38683a40 100644 --- a/core/state/coins/model.go +++ b/core/state/coins/model.go @@ -142,8 +142,8 @@ type SymbolInfo struct { isDirty bool } -func (i *SymbolInfo) SetOwnerAddress(address *types.Address) { - i.COwnerAddress = address +func (i *SymbolInfo) setOwnerAddress(address types.Address) { + i.COwnerAddress = &address i.isDirty = true } diff --git a/core/transaction/edit_coin_owner.go b/core/transaction/edit_coin_owner.go index 4cb7fa04f..e97a41475 100644 --- a/core/transaction/edit_coin_owner.go +++ b/core/transaction/edit_coin_owner.go @@ -29,7 +29,7 @@ func (data EditCoinOwnerData) BasicCheck(tx *Transaction, context *state.CheckSt } } - if info.OwnerAddress() == nil || info.OwnerAddress().Compare(sender) != 0 { + if info.OwnerAddress() == nil || *info.OwnerAddress() != sender { owner := info.OwnerAddress().String() return &Response{ Code: code.IsNotOwnerOfCoin, From b6571e93b3704b101ca5434daded024d403fe916 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Wed, 14 Oct 2020 16:40:51 +0300 Subject: [PATCH 402/426] Refactor --- core/transaction/recreate_coin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/transaction/recreate_coin.go b/core/transaction/recreate_coin.go index 355a4359b..4c2f4a87e 100644 --- a/core/transaction/recreate_coin.go +++ b/core/transaction/recreate_coin.go @@ -84,7 +84,7 @@ func (data RecreateCoinData) BasicCheck(tx *Transaction, context *state.CheckSta } symbolInfo := context.Coins().GetSymbolInfo(coin.Symbol()) - if symbolInfo == nil || symbolInfo.OwnerAddress() == nil || symbolInfo.OwnerAddress().Compare(sender) != 0 { + if symbolInfo == nil || symbolInfo.OwnerAddress() == nil || *symbolInfo.OwnerAddress() != sender { var owner *string if symbolInfo != nil && symbolInfo.OwnerAddress() != nil { own := symbolInfo.OwnerAddress().String() From 04e63c0eb18f4e7a9dbc3cca56c202cfb63ad7d3 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 14 Oct 2020 16:42:16 +0300 Subject: [PATCH 403/426] fix tests --- core/transaction/buy_coin_test.go | 2 + core/transaction/create_coin_test.go | 35 +++++++++++- core/transaction/create_multisig_test.go | 23 +++++++- core/transaction/declare_candidacy_test.go | 22 +++++++- core/transaction/delegate_test.go | 20 +++++++ .../edit_candidate_public_key_test.go | 17 ++++++ core/transaction/edit_candidate_test.go | 11 ++++ core/transaction/edit_coin_owner_test.go | 19 +++++++ core/transaction/edit_multisig_test.go | 16 ++++++ core/transaction/executor_test.go | 48 +++++++++++++---- core/transaction/multisend_test.go | 13 +++++ core/transaction/price_vote_test.go | 6 +++ core/transaction/recreate_coin_test.go | 27 ++++++++++ core/transaction/redeem_check_test.go | 29 ++++++++++ core/transaction/sell_all_coin_test.go | 27 ++++++++-- core/transaction/sell_coin_test.go | 54 +++++++++++++++++++ core/transaction/send_test.go | 16 +++++- core/transaction/set_halt_block_test.go | 16 ++++++ .../switch_candidate_status_test.go | 18 +++++++ core/transaction/unbond_test.go | 22 ++++++++ core/types/appstate.go | 6 +-- 21 files changed, 426 insertions(+), 21 deletions(-) diff --git a/core/transaction/buy_coin_test.go b/core/transaction/buy_coin_test.go index f17ebc517..661721463 100644 --- a/core/transaction/buy_coin_test.go +++ b/core/transaction/buy_coin_test.go @@ -60,9 +60,11 @@ func createTestCoinWithOwner(stateDB *state.State, owner types.Address) types.Co reserve := helpers.BipToPip(big.NewInt(100000)) id := stateDB.App.GetNextCoinID() + stateDB.Coins.Create(id, getTestCoinSymbol(), "TEST COIN", volume, 10, reserve, big.NewInt(0).Mul(volume, big.NewInt(10)), &owner) stateDB.App.SetCoinsCount(id.Uint32()) + stateDB.Accounts.AddBalance(types.Address{}, id, volume) err := stateDB.Coins.Commit() if err != nil { diff --git a/core/transaction/create_coin_test.go b/core/transaction/create_coin_test.go index 7fca31595..fd042ee0a 100644 --- a/core/transaction/create_coin_test.go +++ b/core/transaction/create_coin_test.go @@ -73,6 +73,8 @@ func TestCreateCoinTx(t *testing.T) { t.Fatalf("Commit coins failed. Error %s", err) } + checkState(t, cState) + targetBalance, _ := big.NewInt(0).SetString("989000000000000000000000", 10) balance := cState.Accounts.GetBalance(addr, coin) if balance.Cmp(targetBalance) != 0 { @@ -113,6 +115,8 @@ func TestCreateCoinTx(t *testing.T) { if *symbolInfo.OwnerAddress() != addr { t.Fatalf("Target owner address is not correct. Expected %s, got %s", addr.String(), symbolInfo.OwnerAddress().String()) } + + checkState(t, cState) } func TestCreateCoinWithIncorrectName(t *testing.T) { @@ -171,6 +175,8 @@ func TestCreateCoinWithIncorrectName(t *testing.T) { if response.Code != code.InvalidCoinName { t.Fatalf("Response code is not %d. Error %s", code.InvalidCoinName, response.Log) } + + checkState(t, cState) } func TestCreateCoinWithInvalidSymbol(t *testing.T) { @@ -227,6 +233,8 @@ func TestCreateCoinWithInvalidSymbol(t *testing.T) { if response.Code != code.InvalidCoinSymbol { t.Fatalf("Response code is not %d. Error %s", code.InvalidCoinSymbol, response.Log) } + + checkState(t, cState) } func TestCreateCoinWithExistingSymbol(t *testing.T) { @@ -284,6 +292,8 @@ func TestCreateCoinWithExistingSymbol(t *testing.T) { if response.Code != code.CoinAlreadyExists { t.Fatalf("Response code is not %d. Error %s", code.CoinAlreadyExists, response.Log) } + + checkState(t, cState) } func TestCreateCoinWithWrongCrr(t *testing.T) { @@ -339,6 +349,8 @@ func TestCreateCoinWithWrongCrr(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.WrongCrr, response.Log) } + checkState(t, cState) + data.ConstantReserveRatio = uint32(101) encodedData, err = rlp.EncodeToBytes(data) @@ -369,6 +381,8 @@ func TestCreateCoinWithWrongCrr(t *testing.T) { if response.Code != code.WrongCrr { t.Fatalf("Response code is not %d. Error %s", code.WrongCrr, response.Log) } + + checkState(t, cState) } func TestCreateCoinWithWrongCoinSupply(t *testing.T) { @@ -423,6 +437,8 @@ func TestCreateCoinWithWrongCoinSupply(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.WrongCoinSupply, response.Log) } + checkState(t, cState) + data.InitialAmount = helpers.BipToPip(big.NewInt(1000000)) encodedData, err = rlp.EncodeToBytes(data) if err != nil { @@ -453,6 +469,8 @@ func TestCreateCoinWithWrongCoinSupply(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.WrongCoinSupply, response.Log) } + checkState(t, cState) + data.MaxSupply = big.NewInt(0).Exp(big.NewInt(100), big.NewInt(15+18), nil) encodedData, err = rlp.EncodeToBytes(data) if err != nil { @@ -495,6 +513,8 @@ func TestCreateCoinWithWrongCoinSupply(t *testing.T) { if response.Code != code.WrongCoinSupply { t.Fatalf("Response code is not %d. Error %s", code.WrongCoinSupply, response.Log) } + + checkState(t, cState) } func TestCreateCoinGas(t *testing.T) { @@ -575,6 +595,8 @@ func TestCreateCoinWithInsufficientFundsForGas(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestCreateCoinTxToGasCoinReserveUnderflow(t *testing.T) { @@ -591,7 +613,8 @@ func TestCreateCoinTxToGasCoinReserveUnderflow(t *testing.T) { name := "My Test Coin" addr := crypto.PubkeyToAddress(privateKey.PublicKey) - cState.Accounts.AddBalance(addr, customCoin, helpers.BipToPip(big.NewInt(105))) + cState.Coins.AddVolume(customCoin, helpers.BipToPip(big.NewInt(1050))) + cState.Accounts.AddBalance(addr, customCoin, helpers.BipToPip(big.NewInt(1050))) cState.Accounts.AddBalance(addr, types.GetBaseCoinID(), helpers.BipToPip(big.NewInt(10000))) cState.Commit() @@ -632,6 +655,8 @@ func TestCreateCoinTxToGasCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } func TestCreateCoinToInsufficientFundsForGasCoin(t *testing.T) { @@ -684,6 +709,8 @@ func TestCreateCoinToInsufficientFundsForGasCoin(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestCreateCoinToInsufficientFundsForInitialReserve(t *testing.T) { @@ -736,6 +763,8 @@ func TestCreateCoinToInsufficientFundsForInitialReserve(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestCreateCoinToSameSymbolInOneBlock(t *testing.T) { @@ -794,6 +823,8 @@ func TestCreateCoinToSameSymbolInOneBlock(t *testing.T) { t.Fatalf("Response code is not success. Error %s", response.Log) } + checkState(t, cState) + if err := tx.Sign(privateKey2); err != nil { t.Fatal(err) } @@ -807,4 +838,6 @@ func TestCreateCoinToSameSymbolInOneBlock(t *testing.T) { if response.Code != code.CoinAlreadyExists { t.Fatalf("Response code is not %d. Error %s", code.CoinAlreadyExists, response.Log) } + + checkState(t, cState) } diff --git a/core/transaction/create_multisig_test.go b/core/transaction/create_multisig_test.go index 2050612ff..645d26866 100644 --- a/core/transaction/create_multisig_test.go +++ b/core/transaction/create_multisig_test.go @@ -106,6 +106,8 @@ func TestCreateMultisigTx(t *testing.T) { if msigData.Threshold != 1 { t.Fatalf("Threshold is not correct") } + + checkState(t, cState) } func TestCreateMultisigFromExistingAccountTx(t *testing.T) { @@ -207,6 +209,8 @@ func TestCreateMultisigFromExistingAccountTx(t *testing.T) { if cState.Accounts.GetBalance(msigAddr, types.GetBaseCoinID()).Cmp(initialBalance) != 0 { t.Fatalf("Msig balance was not persisted") } + + checkState(t, cState) } func TestCreateExistingMultisigTx(t *testing.T) { @@ -263,6 +267,8 @@ func TestCreateExistingMultisigTx(t *testing.T) { if response.Code != code.MultisigExists { t.Fatalf("Response code is not %d. Got %d", code.MultisigExists, response.Code) } + + checkState(t, cState) } func TestCreateMultisigOwnersTxToNonExistAddress(t *testing.T) { @@ -303,11 +309,12 @@ func TestCreateMultisigOwnersTxToNonExistAddress(t *testing.T) { t.Fatal(err) } - checkState := state.NewCheckState(cState) - response := data.BasicCheck(&tx, checkState) + response := data.BasicCheck(&tx, state.NewCheckState(cState)) if response.Code != code.MultisigNotExists { t.Fatalf("Response code is not %d. Error %s", code.MultisigNotExists, response.Log) } + + checkState(t, cState) } func TestCreateMultisigOwnersTxToTooLargeOwnersList(t *testing.T) { @@ -361,6 +368,8 @@ func TestCreateMultisigOwnersTxToTooLargeOwnersList(t *testing.T) { if response.Code != code.TooLargeOwnersList { t.Fatalf("Response code is not %d. Error %s", code.TooLargeOwnersList, response.Log) } + + checkState(t, cState) } func TestCreateMultisigOwnersTxIncorrectWeights(t *testing.T) { @@ -408,6 +417,8 @@ func TestCreateMultisigOwnersTxIncorrectWeights(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.DifferentCountAddressesAndWeights, response.Log) } + checkState(t, cState) + data.Weights = []uint32{1, 2, 1024} encodedData, err = rlp.EncodeToBytes(data) if err != nil { @@ -428,6 +439,8 @@ func TestCreateMultisigOwnersTxIncorrectWeights(t *testing.T) { if response.Code != code.IncorrectWeights { t.Fatalf("Response code is not %d. Error %s", code.IncorrectWeights, response.Log) } + + checkState(t, cState) } func TestCreateMultisigOwnersTxToAddressDuplication(t *testing.T) { @@ -472,6 +485,8 @@ func TestCreateMultisigOwnersTxToAddressDuplication(t *testing.T) { if response.Code != code.DuplicatedAddresses { t.Fatalf("Response code is not %d. Error %s", code.DuplicatedAddresses, response.Log) } + + checkState(t, cState) } func TestCreateMultisigOwnersTxToInsufficientFunds(t *testing.T) { @@ -518,6 +533,8 @@ func TestCreateMultisigOwnersTxToInsufficientFunds(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestCreateMultisigTxToGasCoinReserveUnderflow(t *testing.T) { @@ -569,4 +586,6 @@ func TestCreateMultisigTxToGasCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } diff --git a/core/transaction/declare_candidacy_test.go b/core/transaction/declare_candidacy_test.go index 6969cedb5..1373d8a51 100644 --- a/core/transaction/declare_candidacy_test.go +++ b/core/transaction/declare_candidacy_test.go @@ -67,7 +67,6 @@ func TestDeclareCandidacyTx(t *testing.T) { } response := RunTx(cState, encodedTx, big.NewInt(0), 0, &sync.Map{}, 0) - if response.Code != 0 { t.Fatalf("Response code is not 0. Error %s", response.Log) } @@ -107,6 +106,8 @@ func TestDeclareCandidacyTx(t *testing.T) { if candidate.Status != candidates.CandidateStatusOffline { t.Fatalf("Incorrect candidate status") } + + checkState(t, cState) } func TestDeclareCandidacyTxOverflow(t *testing.T) { @@ -172,6 +173,8 @@ func TestDeclareCandidacyTxOverflow(t *testing.T) { if response.Code != code.TooLowStake { t.Fatalf("Response code is not %d. Got %d", code.TooLowStake, response.Code) } + + checkState(t, cState) } func TestDeclareCandidacyTxWithBlockPybKey(t *testing.T) { @@ -260,6 +263,8 @@ func TestDeclareCandidacyTxWithBlockPybKey(t *testing.T) { if candidate.ControlAddress == addr { t.Fatalf("ControlAddress has changed") } + + checkState(t, cState) } func TestDeclareCandidacyToNonExistCoin(t *testing.T) { @@ -315,6 +320,8 @@ func TestDeclareCandidacyToNonExistCoin(t *testing.T) { if response.Code != code.CoinNotExists { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) } + + checkState(t, cState) } func TestDeclareCandidacyToExistCandidate(t *testing.T) { @@ -372,6 +379,8 @@ func TestDeclareCandidacyToExistCandidate(t *testing.T) { if response.Code != code.CandidateExists { t.Fatalf("Response code is not %d. Error %s", code.CandidateExists, response.Log) } + + checkState(t, cState) } func TestDeclareCandidacyToDecodeError(t *testing.T) { @@ -422,6 +431,8 @@ func TestDeclareCandidacyToDecodeError(t *testing.T) { if response.Code != code.DecodeError { t.Fatalf("Response code is not %d. Error %s", code.DecodeError, response.Log) } + + checkState(t, cState) } func TestDeclareCandidacyToWrongCommission(t *testing.T) { @@ -475,6 +486,8 @@ func TestDeclareCandidacyToWrongCommission(t *testing.T) { if response.Code != code.WrongCommission { t.Fatalf("Response code is not %d. Error %s", code.WrongCommission, response.Log) } + + checkState(t, cState) } func TestDeclareCandidacyToInsufficientFunds(t *testing.T) { @@ -526,6 +539,8 @@ func TestDeclareCandidacyToInsufficientFunds(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + checkState(t, cState) + cState.Accounts.AddBalance(addr, coin, stake) cState.Commit() @@ -571,6 +586,8 @@ func TestDeclareCandidacyToInsufficientFunds(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestDeclareCandidacyTxToGasCoinReserveUnderflow(t *testing.T) { @@ -580,6 +597,7 @@ func TestDeclareCandidacyTxToGasCoinReserveUnderflow(t *testing.T) { coin := createTestCoin(cState) stake := big.NewInt(1e18) + cState.Coins.AddVolume(coin, helpers.BipToPip(big.NewInt(1000000))) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) cState.Commit() @@ -625,4 +643,6 @@ func TestDeclareCandidacyTxToGasCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } diff --git a/core/transaction/delegate_test.go b/core/transaction/delegate_test.go index c2c2d6b70..24e76e725 100644 --- a/core/transaction/delegate_test.go +++ b/core/transaction/delegate_test.go @@ -94,6 +94,8 @@ func TestDelegateTx(t *testing.T) { if stake.Value.Cmp(value) != 0 { t.Fatalf("Stake value is not corrent. Expected %s, got %s", value, stake.Value) } + + checkState(t, cState) } func TestDelegateTxWithWatchlist(t *testing.T) { @@ -158,6 +160,8 @@ func TestDelegateTxWithWatchlist(t *testing.T) { if wl != nil { t.Fatalf("Waitlist is not deleted") } + + checkState(t, cState) } func TestDelegateTxToNonExistCoin(t *testing.T) { @@ -205,6 +209,8 @@ func TestDelegateTxToNonExistCoin(t *testing.T) { if response.Code != code.CoinNotExists { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) } + + checkState(t, cState) } func TestDelegateTxToPositiveStake(t *testing.T) { @@ -252,6 +258,8 @@ func TestDelegateTxToPositiveStake(t *testing.T) { if response.Code != code.StakeShouldBePositive { t.Fatalf("Response code is not %d. Error %s", code.StakeShouldBePositive, response.Log) } + + checkState(t, cState) } func TestDelegateTxToNonExistCandidate(t *testing.T) { @@ -299,6 +307,8 @@ func TestDelegateTxToNonExistCandidate(t *testing.T) { if response.Code != code.CandidateNotFound { t.Fatalf("Response code is not %d. Error %s", code.CandidateNotFound, response.Log) } + + checkState(t, cState) } func TestDelegateTxToLowStake(t *testing.T) { @@ -355,6 +365,8 @@ func TestDelegateTxToLowStake(t *testing.T) { if response.Code != code.TooLowStake { t.Fatalf("Response code is not %d. Error %s", code.TooLowStake, response.Log) } + + checkState(t, cState) } func TestDelegateTxToInsufficientFunds(t *testing.T) { @@ -402,6 +414,8 @@ func TestDelegateTxToInsufficientFunds(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + checkState(t, cState) + cState.Accounts.AddBalance(addr, coin, big.NewInt(2e17)) data.Coin = customCoin @@ -445,6 +459,8 @@ func TestDelegateTxToInsufficientFunds(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestDelegateTxToGasCoinReserveUnderflow(t *testing.T) { @@ -491,6 +507,8 @@ func TestDelegateTxToGasCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } func TestDelegateData_addFromWaitlist(t *testing.T) { @@ -547,4 +565,6 @@ func TestDelegateData_addFromWaitlist(t *testing.T) { if err != nil { t.Fatal(err) } + + checkState(t, cState) } diff --git a/core/transaction/edit_candidate_public_key_test.go b/core/transaction/edit_candidate_public_key_test.go index 8c6b68ede..f87b1d7dd 100644 --- a/core/transaction/edit_candidate_public_key_test.go +++ b/core/transaction/edit_candidate_public_key_test.go @@ -27,6 +27,7 @@ func TestEditCandidateNewPublicKeyTx(t *testing.T) { cState.Candidates.Create(addr, addr, addr, pubkey, 10) cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + cState.Commit() data := EditCandidatePublicKeyData{ PubKey: pubkey, @@ -80,6 +81,8 @@ func TestEditCandidateNewPublicKeyTx(t *testing.T) { if !candidate.PubKey.Equals(newpubkey) { t.Fatalf("Public key has not changed") } + + checkState(t, cState) } func TestEditCandidatePublicKeyTxToNewPublicKey(t *testing.T) { @@ -129,6 +132,8 @@ func TestEditCandidatePublicKeyTxToNewPublicKey(t *testing.T) { if response.Code != code.NewPublicKeyIsBad { t.Fatalf("Response code is not %d. Error %s", code.NewPublicKeyIsBad, response.Log) } + + checkState(t, cState) } func TestEditCandidatePublicKeyTxToNewPublicKeyInBlockList(t *testing.T) { @@ -181,6 +186,8 @@ func TestEditCandidatePublicKeyTxToNewPublicKeyInBlockList(t *testing.T) { if response.Code != code.PublicKeyInBlockList { t.Fatalf("Response code is not %d. Error %s", code.PublicKeyInBlockList, response.Log) } + + checkState(t, cState) } func TestEditCandidatePublicKeyTxToInsufficientFunds(t *testing.T) { @@ -229,6 +236,8 @@ func TestEditCandidatePublicKeyTxToInsufficientFunds(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestEditCandidatePublicKeyTxToGasCoinReserveUnderflow(t *testing.T) { @@ -238,6 +247,7 @@ func TestEditCandidatePublicKeyTxToGasCoinReserveUnderflow(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := createTestCoin(cState) cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) + cState.Coins.AddVolume(coin, helpers.BipToPip(big.NewInt(1000000))) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) pubkey := [32]byte{} @@ -279,6 +289,8 @@ func TestEditCandidatePublicKeyTxToGasCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } func TestEditCandidatePublicKeyToNotExistCandidate(t *testing.T) { @@ -325,6 +337,8 @@ func TestEditCandidatePublicKeyToNotExistCandidate(t *testing.T) { if response.Code != code.CandidateNotFound { t.Fatalf("Response code is not %d. Error %s", code.CandidateNotFound, response.Log) } + + checkState(t, cState) } func TestEditCandidatePublicKeyTxToCandidateOwnership(t *testing.T) { @@ -375,6 +389,8 @@ func TestEditCandidatePublicKeyTxToCandidateOwnership(t *testing.T) { if response.Code != code.IsNotOwnerOfCandidate { t.Fatalf("Response code is not %d. Error %s", code.IsNotOwnerOfCandidate, response.Log) } + + checkState(t, cState) } func TestEditCandidatePublicKeyData_Exists(t *testing.T) { @@ -443,4 +459,5 @@ func TestEditCandidatePublicKeyData_Exists(t *testing.T) { t.Fatalf("Candidates pulic keys are equal") } + checkState(t, cState) } diff --git a/core/transaction/edit_candidate_test.go b/core/transaction/edit_candidate_test.go index 18fefc994..1d6d59f50 100644 --- a/core/transaction/edit_candidate_test.go +++ b/core/transaction/edit_candidate_test.go @@ -93,6 +93,8 @@ func TestEditCandidateTx(t *testing.T) { if candidate.ControlAddress != newControlAddress { t.Fatalf("ControlAddress has not changed") } + + checkState(t, cState) } func TestEditCandidateTxToNonExistCandidate(t *testing.T) { @@ -145,6 +147,8 @@ func TestEditCandidateTxToNonExistCandidate(t *testing.T) { if response.Code != code.CandidateNotFound { t.Fatalf("Response code is not %d. Error %s", code.CandidateNotFound, response.Log) } + + checkState(t, cState) } func TestEditCandidateTxToCandidateOwnership(t *testing.T) { @@ -201,6 +205,8 @@ func TestEditCandidateTxToCandidateOwnership(t *testing.T) { if response.Code != code.IsNotOwnerOfCandidate { t.Fatalf("Response code is not %d. Error %s", code.IsNotOwnerOfCandidate, response.Log) } + + checkState(t, cState) } func TestEditCandidateTxToInsufficientFunds(t *testing.T) { @@ -255,6 +261,8 @@ func TestEditCandidateTxToInsufficientFunds(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestEditCandidateTxToGasCoinReserveUnderflow(t *testing.T) { @@ -264,6 +272,7 @@ func TestEditCandidateTxToGasCoinReserveUnderflow(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := createTestCoin(cState) cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) + cState.Coins.AddVolume(coin, helpers.BipToPip(big.NewInt(1000000))) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) pubkey := [32]byte{} @@ -311,4 +320,6 @@ func TestEditCandidateTxToGasCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } diff --git a/core/transaction/edit_coin_owner_test.go b/core/transaction/edit_coin_owner_test.go index cfd59fb51..33a7f613d 100644 --- a/core/transaction/edit_coin_owner_test.go +++ b/core/transaction/edit_coin_owner_test.go @@ -30,6 +30,7 @@ func TestEditOwnerTx(t *testing.T) { newOwner := crypto.PubkeyToAddress(newOwnerPrivateKey.PublicKey) createTestCoinWithOwner(cState, addr) + createDefaultValidator(cState) gasCoin := types.GetBaseCoinID() cState.Accounts.AddBalance(addr, gasCoin, helpers.BipToPip(big.NewInt(10000))) @@ -68,6 +69,8 @@ func TestEditOwnerTx(t *testing.T) { if *symbol.OwnerAddress() != newOwner { t.Fatalf("Target owner address is not correct. Excpected %s, got %s", newOwner.String(), symbol.OwnerAddress().String()) } + + checkState(t, cState) } func TestEditOwnerTxWithWrongOwner(t *testing.T) { @@ -82,6 +85,7 @@ func TestEditOwnerTxWithWrongOwner(t *testing.T) { newOwner := crypto.PubkeyToAddress(newOwnerPrivateKey.PublicKey) createTestCoinWithOwner(cState, newOwner) + createDefaultValidator(cState) data := EditCoinOwnerData{ Symbol: getTestCoinSymbol(), @@ -97,6 +101,8 @@ func TestEditOwnerTxWithWrongOwner(t *testing.T) { if response.Code != code.IsNotOwnerOfCoin { t.Fatalf("Response code is not 206. Error %s", response.Log) } + + checkState(t, cState) } func TestEditOwnerTxWithWrongSymbol(t *testing.T) { @@ -112,6 +118,7 @@ func TestEditOwnerTxWithWrongSymbol(t *testing.T) { newOwner := crypto.PubkeyToAddress(newOwnerPrivateKey.PublicKey) createTestCoinWithOwner(cState, addr) + createDefaultValidator(cState) data := EditCoinOwnerData{ Symbol: types.StrToCoinSymbol("UNKNOWN"), @@ -127,6 +134,8 @@ func TestEditOwnerTxWithWrongSymbol(t *testing.T) { if response.Code != code.CoinNotExists { t.Fatalf("Response code is not 102. Error %s", response.Log) } + + checkState(t, cState) } func TestEditCOwnerTxWithInsufficientFunds(t *testing.T) { @@ -142,6 +151,7 @@ func TestEditCOwnerTxWithInsufficientFunds(t *testing.T) { newOwner := crypto.PubkeyToAddress(newOwnerPrivateKey.PublicKey) createTestCoinWithOwner(cState, addr) + createDefaultValidator(cState) data := EditCoinOwnerData{ Symbol: getTestCoinSymbol(), @@ -157,6 +167,8 @@ func TestEditCOwnerTxWithInsufficientFunds(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestEditCoinOwnerTxToGasCoinReserveUnderflow(t *testing.T) { @@ -204,6 +216,8 @@ func TestEditCoinOwnerTxToGasCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } func makeTestEditOwnerTx(data EditCoinOwnerData, privateKey *ecdsa.PrivateKey) ([]byte, error) { @@ -233,3 +247,8 @@ func makeTestEditOwnerTx(data EditCoinOwnerData, privateKey *ecdsa.PrivateKey) ( return encodedTx, nil } + +func createDefaultValidator(cState *state.State) { + cState.Validators.Create(types.Pubkey{0}, big.NewInt(0)) + cState.Candidates.Create(types.Address{0}, types.Address{0}, types.Address{0}, types.Pubkey{0}, 0) +} diff --git a/core/transaction/edit_multisig_test.go b/core/transaction/edit_multisig_test.go index 39be31419..d52c6c688 100644 --- a/core/transaction/edit_multisig_test.go +++ b/core/transaction/edit_multisig_test.go @@ -96,6 +96,8 @@ func TestEditMultisigTx(t *testing.T) { if msigData.Threshold != 3 { t.Fatalf("Threshold is not correct") } + + checkState(t, cState) } func TestEditMultisigTxToNonExistAddress(t *testing.T) { @@ -199,6 +201,8 @@ func TestEditMultisigTxToTooLargeOwnersList(t *testing.T) { if response.Code != code.TooLargeOwnersList { t.Fatalf("Response code is not %d. Error %s", code.TooLargeOwnersList, response.Log) } + + checkState(t, cState) } func TestEditMultisigTxIncorrectWeights(t *testing.T) { @@ -253,6 +257,8 @@ func TestEditMultisigTxIncorrectWeights(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.DifferentCountAddressesAndWeights, response.Log) } + checkState(t, cState) + data.Weights = []uint32{1, 2, 1024} encodedData, err = rlp.EncodeToBytes(data) if err != nil { @@ -274,6 +280,8 @@ func TestEditMultisigTxIncorrectWeights(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.IncorrectWeights, response.Log) } + checkState(t, cState) + data.Weights = []uint32{1, 2, 3} data.Threshold = 7 encodedData, err = rlp.EncodeToBytes(data) @@ -295,6 +303,8 @@ func TestEditMultisigTxIncorrectWeights(t *testing.T) { if response.Code != code.IncorrectTotalWeights { t.Fatalf("Response code is not %d. Error %s", code.IncorrectTotalWeights, response.Log) } + + checkState(t, cState) } func TestEditMultisigTxToAddressDuplication(t *testing.T) { @@ -348,6 +358,8 @@ func TestEditMultisigTxToAddressDuplication(t *testing.T) { if response.Code != code.DuplicatedAddresses { t.Fatalf("Response code is not %d. Error %s", code.DuplicatedAddresses, response.Log) } + + checkState(t, cState) } func TestEditMultisigTxToInsufficientFunds(t *testing.T) { @@ -401,6 +413,8 @@ func TestEditMultisigTxToInsufficientFunds(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestEditMultisigTxToGasCoinReserveUnderflow(t *testing.T) { @@ -455,4 +469,6 @@ func TestEditMultisigTxToGasCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } diff --git a/core/transaction/executor_test.go b/core/transaction/executor_test.go index 5b933cb20..2794ebea9 100644 --- a/core/transaction/executor_test.go +++ b/core/transaction/executor_test.go @@ -16,22 +16,26 @@ import ( func TestTooLongTx(t *testing.T) { fakeTx := make([]byte, 10000) - response := RunTx(getState(), fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) - + cState := getState() + response := RunTx(cState, fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.TxTooLarge { t.Fatalf("Response code is not correct") } + + checkState(t, cState) } func TestIncorrectTx(t *testing.T) { fakeTx := make([]byte, 1) rand.Read(fakeTx) - response := RunTx(getState(), fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) - + cState := getState() + response := RunTx(cState, fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.DecodeError { t.Fatalf("Response code is not correct") } + + checkState(t, cState) } func TestTooLongPayloadTx(t *testing.T) { @@ -67,11 +71,14 @@ func TestTooLongPayloadTx(t *testing.T) { fakeTx, _ := rlp.EncodeToBytes(tx) - response := RunTx(getState(), fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) + cState := getState() + response := RunTx(cState, fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.TxPayloadTooLarge { t.Fatalf("Response code is not correct. Expected %d, got %d", code.TxPayloadTooLarge, response.Code) } + + checkState(t, cState) } func TestTooLongServiceDataTx(t *testing.T) { @@ -106,11 +113,14 @@ func TestTooLongServiceDataTx(t *testing.T) { fakeTx, _ := rlp.EncodeToBytes(tx) - response := RunTx(getState(), fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) + cState := getState() + response := RunTx(cState, fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.TxServiceDataTooLarge { t.Fatalf("Response code is not correct. Expected %d, got %d", code.TxServiceDataTooLarge, response.Code) } + + checkState(t, cState) } func TestUnexpectedNonceTx(t *testing.T) { @@ -141,11 +151,13 @@ func TestUnexpectedNonceTx(t *testing.T) { fakeTx, _ := rlp.EncodeToBytes(tx) - response := RunTx(getState(), fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) - + cState := getState() + response := RunTx(cState, fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.WrongNonce { t.Fatalf("Response code is not correct. Expected %d, got %d", code.WrongNonce, response.Code) } + + checkState(t, cState) } func TestInvalidSigTx(t *testing.T) { @@ -179,11 +191,14 @@ func TestInvalidSigTx(t *testing.T) { fakeTx, _ := rlp.EncodeToBytes(tx) - response := RunTx(getState(), fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) + cState := getState() + response := RunTx(cState, fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.DecodeError { t.Fatalf("Response code is not correct. Expected %d, got %d", code.DecodeError, response.Code) } + + checkState(t, cState) } func TestNotExistMultiSigTx(t *testing.T) { @@ -218,11 +233,14 @@ func TestNotExistMultiSigTx(t *testing.T) { fakeTx, _ := rlp.EncodeToBytes(tx) - response := RunTx(getState(), fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) + cState := getState() + response := RunTx(cState, fakeTx, big.NewInt(0), 0, &sync.Map{}, 0) if response.Code != code.MultisigNotExists { t.Fatalf("Response code is not correct. Expected %d, got %d", code.MultisigNotExists, response.Code) } + + checkState(t, cState) } func TestMultiSigTx(t *testing.T) { @@ -267,6 +285,8 @@ func TestMultiSigTx(t *testing.T) { if response.Code != 0 { t.Fatalf("Error code is not 0. Error: %s", response.Log) } + + checkState(t, cState) } func TestMultiSigDoubleSignTx(t *testing.T) { @@ -315,6 +335,8 @@ func TestMultiSigDoubleSignTx(t *testing.T) { if response.Code != code.DuplicatedAddresses { t.Fatalf("Error code is not %d, got %d", code.DuplicatedAddresses, response.Code) } + + checkState(t, cState) } func TestMultiSigTooManySignsTx(t *testing.T) { @@ -366,6 +388,8 @@ func TestMultiSigTooManySignsTx(t *testing.T) { if response.Code != code.IncorrectMultiSignature { t.Fatalf("Error code is not %d, got %d", code.IncorrectMultiSignature, response.Code) } + + checkState(t, cState) } func TestMultiSigNotEnoughTx(t *testing.T) { @@ -410,6 +434,8 @@ func TestMultiSigNotEnoughTx(t *testing.T) { if response.Code != code.NotEnoughMultisigVotes { t.Fatalf("Error code is not %d. Error: %d", code.NotEnoughMultisigVotes, response.Code) } + + checkState(t, cState) } func TestMultiSigIncorrectSignsTx(t *testing.T) { @@ -455,4 +481,6 @@ func TestMultiSigIncorrectSignsTx(t *testing.T) { if response.Code != code.IncorrectMultiSignature { t.Fatalf("Error code is not %d, got %d", code.IncorrectMultiSignature, response.Code) } + + checkState(t, cState) } diff --git a/core/transaction/multisend_test.go b/core/transaction/multisend_test.go index 9e82105b0..e981bdf48 100644 --- a/core/transaction/multisend_test.go +++ b/core/transaction/multisend_test.go @@ -77,6 +77,8 @@ func TestMultisendTx(t *testing.T) { if testBalance.Cmp(targetTestBalance) != 0 { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", to.String(), targetTestBalance, testBalance) } + + checkState(t, cState) } func TestMultisendTxToInvalidDataLength(t *testing.T) { @@ -147,6 +149,8 @@ func TestMultisendTxToInvalidDataLength(t *testing.T) { if response.Code != code.InvalidMultisendData { t.Fatalf("Response code is not %d. Error %s", code.InvalidMultisendData, response.Log) } + + checkState(t, cState) } func TestMultisendTxToInsufficientFunds(t *testing.T) { @@ -196,6 +200,8 @@ func TestMultisendTxToInsufficientFunds(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestMultisendToInvalidCoin(t *testing.T) { @@ -248,6 +254,8 @@ func TestMultisendToInvalidCoin(t *testing.T) { if response.Code != code.CoinNotExists { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) } + + checkState(t, cState) } func TestMultisendToInsufficientReserve(t *testing.T) { @@ -300,6 +308,8 @@ func TestMultisendToInsufficientReserve(t *testing.T) { if response.Code != code.CoinNotExists { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) } + + checkState(t, cState) } func TestMultisendTxToGasCoinReserveUnderflow(t *testing.T) { @@ -310,6 +320,7 @@ func TestMultisendTxToGasCoinReserveUnderflow(t *testing.T) { coin := createTestCoin(cState) cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) + cState.Coins.AddVolume(coin, helpers.BipToPip(big.NewInt(1000000))) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) cState.Commit() @@ -354,4 +365,6 @@ func TestMultisendTxToGasCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } diff --git a/core/transaction/price_vote_test.go b/core/transaction/price_vote_test.go index 2dc4d6137..05652ddbf 100644 --- a/core/transaction/price_vote_test.go +++ b/core/transaction/price_vote_test.go @@ -45,6 +45,8 @@ func TestPriceVoteTx(t *testing.T) { if response.Code != 0 { t.Fatalf("Response code is not 0. Error: %s", response.Log) } + + checkState(t, cState) } func TestPriceVoteTxToInsufficientFunds(t *testing.T) { @@ -80,6 +82,8 @@ func TestPriceVoteTxToInsufficientFunds(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error: %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestPriceVoteTxToCoinReserveUnderflow(t *testing.T) { @@ -118,4 +122,6 @@ func TestPriceVoteTxToCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error: %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } diff --git a/core/transaction/recreate_coin_test.go b/core/transaction/recreate_coin_test.go index b5f6eac2c..7759e6360 100644 --- a/core/transaction/recreate_coin_test.go +++ b/core/transaction/recreate_coin_test.go @@ -101,6 +101,8 @@ func TestRecreateCoinTx(t *testing.T) { if stateCoin.Version() != 1 { t.Fatalf("Version in state is not correct. Expected %d, got %d", 1, stateCoin.Version()) } + + checkState(t, cState) } func TestRecreateCoinTxWithWrongOwner(t *testing.T) { @@ -137,6 +139,8 @@ func TestRecreateCoinTxWithWrongOwner(t *testing.T) { if response.Code != code.IsNotOwnerOfCoin { t.Fatalf("Response code is not 206. Error %s", response.Log) } + + checkState(t, cState) } func TestRecreateCoinTxWithWrongSymbol(t *testing.T) { @@ -171,6 +175,8 @@ func TestRecreateCoinTxWithWrongSymbol(t *testing.T) { if response.Code != code.CoinNotExists { t.Fatalf("Response code is not 102. Error %s", response.Log) } + + checkState(t, cState) } func TestRecreateCoinWithIncorrectName(t *testing.T) { @@ -229,6 +235,8 @@ func TestRecreateCoinWithIncorrectName(t *testing.T) { if response.Code != code.InvalidCoinName { t.Fatalf("Response code is not %d. Error %s", code.InvalidCoinName, response.Log) } + + checkState(t, cState) } func TestRecreateCoinWithWrongCrr(t *testing.T) { @@ -284,6 +292,8 @@ func TestRecreateCoinWithWrongCrr(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.WrongCrr, response.Log) } + checkState(t, cState) + data.ConstantReserveRatio = uint32(101) encodedData, err = rlp.EncodeToBytes(data) if err != nil { @@ -313,6 +323,8 @@ func TestRecreateCoinWithWrongCrr(t *testing.T) { if response.Code != code.WrongCrr { t.Fatalf("Response code is not %d. Error %s", code.WrongCrr, response.Log) } + + checkState(t, cState) } func TestRecreateCoinWithWrongCoinSupply(t *testing.T) { @@ -367,6 +379,8 @@ func TestRecreateCoinWithWrongCoinSupply(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.WrongCoinSupply, response.Log) } + checkState(t, cState) + data.InitialAmount = helpers.BipToPip(big.NewInt(1000000)) encodedData, err = rlp.EncodeToBytes(data) if err != nil { @@ -418,6 +432,8 @@ func TestRecreateCoinWithWrongCoinSupply(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.WrongCoinSupply, response.Log) } + checkState(t, cState) + data.MaxSupply = maxCoinSupply data.InitialReserve = helpers.BipToPip(big.NewInt(1000)) encodedData, err = rlp.EncodeToBytes(data) @@ -439,6 +455,8 @@ func TestRecreateCoinWithWrongCoinSupply(t *testing.T) { if response.Code != code.WrongCoinSupply { t.Fatalf("Response code is not %d. Error %s", code.WrongCoinSupply, response.Log) } + + checkState(t, cState) } func TestRecreateCoinWithInsufficientFundsForGas(t *testing.T) { @@ -493,6 +511,8 @@ func TestRecreateCoinWithInsufficientFundsForGas(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + checkState(t, cState) + addr := crypto.PubkeyToAddress(privateKey.PublicKey) cState.Accounts.SetBalance(addr, types.GetBaseCoinID(), data.InitialReserve) cState.Commit() @@ -511,6 +531,8 @@ func TestRecreateCoinWithInsufficientFundsForGas(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestRecreateCoinToInsufficientFundsForInitialReserve(t *testing.T) { @@ -546,6 +568,8 @@ func TestRecreateCoinToInsufficientFundsForInitialReserve(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestRecreateCoinToGasCoinReserveUnderflow(t *testing.T) { @@ -557,6 +581,7 @@ func TestRecreateCoinToGasCoinReserveUnderflow(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) + cState.Coins.AddVolume(coin, helpers.BipToPip(big.NewInt(105))) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(105))) cState.Accounts.AddBalance(addr, types.GetBaseCoinID(), helpers.BipToPip(big.NewInt(10000))) cState.Commit() @@ -603,6 +628,8 @@ func TestRecreateCoinToGasCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } func makeTestRecreateCoinTx(data RecreateCoinData, privateKey *ecdsa.PrivateKey) ([]byte, error) { diff --git a/core/transaction/redeem_check_test.go b/core/transaction/redeem_check_test.go index a08fd6804..bd422bae7 100644 --- a/core/transaction/redeem_check_test.go +++ b/core/transaction/redeem_check_test.go @@ -118,6 +118,8 @@ func TestRedeemCheckTx(t *testing.T) { if balance.Cmp(checkValue) != 0 { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", coin, checkValue, balance) } + + checkState(t, cState) } func TestRedeemCheckTxToDecodeError(t *testing.T) { @@ -223,6 +225,8 @@ func TestRedeemCheckTxToDecodeError(t *testing.T) { if txResponse.Code != code.DecodeError { t.Fatalf("Response code is not %d. Error %s", code.DecodeError, response.Log) } + + checkState(t, cState) } func TestRedeemCheckTxToHighGasPrice(t *testing.T) { @@ -317,6 +321,8 @@ func TestRedeemCheckTxToHighGasPrice(t *testing.T) { if response.Code != code.TooHighGasPrice { t.Fatalf("Response code is not %d. Error %s", code.TooHighGasPrice, response.Log) } + + checkState(t, cState) } func TestRedeemCheckTxToWrongChainID(t *testing.T) { @@ -411,6 +417,8 @@ func TestRedeemCheckTxToWrongChainID(t *testing.T) { if response.Code != code.WrongChainID { t.Fatalf("Response code is not %d. Error %s", code.WrongChainID, response.Log) } + + checkState(t, cState) } func TestRedeemCheckTxToNonceLength(t *testing.T) { @@ -505,6 +513,8 @@ func TestRedeemCheckTxToNonceLength(t *testing.T) { if response.Code != code.TooLongNonce { t.Fatalf("Response code is not %d. Error %s", code.TooLongNonce, response.Log) } + + checkState(t, cState) } func TestRedeemCheckTxToCheckData(t *testing.T) { @@ -600,6 +610,8 @@ func TestRedeemCheckTxToCheckData(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) } + checkState(t, cState) + check.Coin = coin check.GasCoin = 5 lock, err = crypto.Sign(check.HashWithoutLock().Bytes(), passphrasePk) @@ -639,6 +651,8 @@ func TestRedeemCheckTxToCheckData(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) } + checkState(t, cState) + check.GasCoin = coin lock, err = crypto.Sign(check.HashWithoutLock().Bytes(), passphrasePk) if err != nil { @@ -675,6 +689,8 @@ func TestRedeemCheckTxToCheckData(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.WrongGasCoin, response.Log) } + checkState(t, cState) + check.DueBlock = 1 lock, err = crypto.Sign(check.HashWithoutLock().Bytes(), passphrasePk) if err != nil { @@ -709,6 +725,8 @@ func TestRedeemCheckTxToCheckData(t *testing.T) { if response.Code != code.CheckExpired { t.Fatalf("Response code is not %d. Error %s", code.CheckExpired, response.Log) } + + checkState(t, cState) } func TestRedeemCheckTxToUsed(t *testing.T) { @@ -805,6 +823,8 @@ func TestRedeemCheckTxToUsed(t *testing.T) { if response.Code != code.CheckUsed { t.Fatalf("Response code is not %d. Error %s", code.CheckUsed, response.Log) } + + checkState(t, cState) } func TestRedeemCheckTxToInsufficientFunds(t *testing.T) { @@ -897,6 +917,8 @@ func TestRedeemCheckTxToInsufficientFunds(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestRedeemCheckTxToCoinReserveUnderflow(t *testing.T) { @@ -990,6 +1012,8 @@ func TestRedeemCheckTxToCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } func TestRedeemCheckTxToInsufficientFundsForCheckCoin(t *testing.T) { @@ -1082,6 +1106,8 @@ func TestRedeemCheckTxToInsufficientFundsForCheckCoin(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestRedeemCheckTxToInsufficientFundsForCheckGasCoin(t *testing.T) { @@ -1097,6 +1123,7 @@ func TestRedeemCheckTxToInsufficientFundsForCheckGasCoin(t *testing.T) { passphraseHash := sha256.Sum256([]byte(passphrase)) passphrasePk, err := crypto.ToECDSA(passphraseHash[:]) + cState.Coins.AddVolume(coin, helpers.BipToPip(big.NewInt(100))) cState.Accounts.AddBalance(senderAddr, coin, helpers.BipToPip(big.NewInt(100))) if err != nil { @@ -1176,4 +1203,6 @@ func TestRedeemCheckTxToInsufficientFundsForCheckGasCoin(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } diff --git a/core/transaction/sell_all_coin_test.go b/core/transaction/sell_all_coin_test.go index 9208694ff..810c5674b 100644 --- a/core/transaction/sell_all_coin_test.go +++ b/core/transaction/sell_all_coin_test.go @@ -72,6 +72,8 @@ func TestSellAllCoinTx(t *testing.T) { if testBalance.Cmp(targetTestBalance) != 0 { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", getTestCoinSymbol(), targetTestBalance, testBalance) } + + checkState(t, cState) } func TestSellAllCoinTxWithSameCoins(t *testing.T) { @@ -118,17 +120,16 @@ func TestSellAllCoinTxWithSameCoins(t *testing.T) { if response.Code != code.CrossConvert { t.Fatalf("Response code is not %d. Error %s", code.CrossConvert, response.Log) } + + checkState(t, cState) } func TestSellAllCoinTxWithInvalidCoins(t *testing.T) { cState := getState() privateKey, _ := crypto.GenerateKey() - addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := types.CoinID(5) - cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) - minValToBuy, _ := big.NewInt(0).SetString("151191152412701306252", 10) data := SellAllCoinData{ CoinToSell: coin, @@ -165,6 +166,8 @@ func TestSellAllCoinTxWithInvalidCoins(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) } + checkState(t, cState) + data.CoinToSell = types.GetBaseCoinID() data.CoinToBuy = types.CoinID(5) encodedData, err = rlp.EncodeToBytes(data) @@ -186,6 +189,8 @@ func TestSellAllCoinTxWithInvalidCoins(t *testing.T) { if response.Code != code.CoinNotExists { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) } + + checkState(t, cState) } func TestSellAllCoinTxWithMinimumValueToBuy(t *testing.T) { @@ -231,6 +236,8 @@ func TestSellAllCoinTxWithMinimumValueToBuy(t *testing.T) { if response.Code != code.MinimumValueToBuyReached { t.Fatalf("Response code is not %d. Error %s", code.MinimumValueToBuyReached, response.Log) } + + checkState(t, cState) } func TestSellAllCoinTxWithInsufficientFunds(t *testing.T) { @@ -279,6 +286,8 @@ func TestSellAllCoinTxWithInsufficientFunds(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + checkState(t, cState) + cState.Coins.Create( cState.App.GetNextCoinID(), types.StrToCoinSymbol("TEST9"), @@ -318,6 +327,8 @@ func TestSellAllCoinTxWithInsufficientFunds(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestSellAllCoinTxToCoinSupplyOverflow(t *testing.T) { @@ -365,6 +376,8 @@ func TestSellAllCoinTxToCoinSupplyOverflow(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.CoinSupplyOverflow, response.Log) } + checkState(t, cState) + // custom buy and sell coins cState.Coins.Create( @@ -405,6 +418,8 @@ func TestSellAllCoinTxToCoinSupplyOverflow(t *testing.T) { if response.Code != code.CoinSupplyOverflow { t.Fatalf("Response code is not %d. Error %s", code.CoinSupplyOverflow, response.Log) } + + checkState(t, cState) } func TestSellAllCoinTxToMinimumValueToBuyReached(t *testing.T) { @@ -450,6 +465,8 @@ func TestSellAllCoinTxToMinimumValueToBuyReached(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.MinimumValueToBuyReached, response.Log) } + checkState(t, cState) + // coin to buy == base coin cState.Accounts.AddBalance(addr, coinToBuyID, big.NewInt(1)) @@ -477,6 +494,8 @@ func TestSellAllCoinTxToMinimumValueToBuyReached(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.MinimumValueToBuyReached, response.Log) } + checkState(t, cState) + // custom buy and sell coins cState.Coins.Create( @@ -518,4 +537,6 @@ func TestSellAllCoinTxToMinimumValueToBuyReached(t *testing.T) { if response.Code != code.MinimumValueToBuyReached { t.Fatalf("Response code is not %d. Error %s", code.MinimumValueToBuyReached, response.Log) } + + checkState(t, cState) } diff --git a/core/transaction/sell_coin_test.go b/core/transaction/sell_coin_test.go index 513f6bc57..312ca9024 100644 --- a/core/transaction/sell_coin_test.go +++ b/core/transaction/sell_coin_test.go @@ -75,6 +75,8 @@ func TestSellCoinTx(t *testing.T) { if testBalance.Cmp(targetTestBalance) != 0 { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", getTestCoinSymbol(), targetTestBalance, testBalance) } + + checkState(t, cState) } func TestSellCoinTxBaseToCustomBaseCommission(t *testing.T) { @@ -140,6 +142,8 @@ func TestSellCoinTxBaseToCustomBaseCommission(t *testing.T) { if coinData.Volume().Cmp(estimatedSupply) != 0 { t.Fatalf("Wrong coin supply") } + + checkState(t, cState) } func TestSellCoinTxCustomToBaseBaseCommission(t *testing.T) { @@ -158,6 +162,8 @@ func TestSellCoinTxCustomToBaseBaseCommission(t *testing.T) { coinToSellID, initialVolume, initialReserve, crr := createTestCoinWithSymbol(cState, coinToSell) privateKey, addr := getAccount() + cState.Coins.AddVolume(coinToSellID, initialBalance) + initialVolume.Add(initialVolume, initialBalance) cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) cState.Accounts.AddBalance(addr, gasCoin, initialGasBalance) @@ -208,6 +214,8 @@ func TestSellCoinTxCustomToBaseBaseCommission(t *testing.T) { if coinData.Volume().Cmp(estimatedSupply) != 0 { t.Fatalf("Wrong coin supply") } + + checkState(t, cState) } func TestSellCoinTxCustomToCustomBaseCommission(t *testing.T) { @@ -227,8 +235,10 @@ func TestSellCoinTxCustomToCustomBaseCommission(t *testing.T) { coinToBuyID, initialVolume2, initialReserve2, crr2 := createTestCoinWithSymbol(cState, coinToBuy) privateKey, addr := getAccount() + cState.Coins.AddVolume(coinToSellID, initialBalance) cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) cState.Accounts.AddBalance(addr, gasCoin, initialGasBalance) + initialVolume1.Add(initialVolume1, initialBalance) tx := createSellCoinTx(coinToSellID, coinToBuyID, gasCoin, toSell, 1) if err := tx.Sign(privateKey); err != nil { @@ -293,6 +303,8 @@ func TestSellCoinTxCustomToCustomBaseCommission(t *testing.T) { t.Fatalf("Wrong coin supply") } } + + checkState(t, cState) } func TestSellCoinTxBaseToCustomCustomCommission(t *testing.T) { @@ -312,6 +324,8 @@ func TestSellCoinTxBaseToCustomCustomCommission(t *testing.T) { privateKey, addr := getAccount() cState.Accounts.AddBalance(addr, coinToSell, initialBalance) cState.Accounts.AddBalance(addr, coinToBuyID, initialGasBalance) + cState.Coins.AddVolume(coinToBuyID, initialGasBalance) + initialVolume.Add(initialVolume, initialGasBalance) tx := createSellCoinTx(coinToSell, coinToBuyID, coinToBuyID, toSell, 1) if err := tx.Sign(privateKey); err != nil { @@ -363,6 +377,8 @@ func TestSellCoinTxBaseToCustomCustomCommission(t *testing.T) { if coinData.Volume().Cmp(estimatedSupply) != 0 { t.Fatalf("Wrong coin supply") } + + checkState(t, cState) } func TestSellCoinTxCustomToBaseCustomCommission(t *testing.T) { @@ -380,6 +396,8 @@ func TestSellCoinTxCustomToBaseCustomCommission(t *testing.T) { privateKey, addr := getAccount() cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) + cState.Coins.AddVolume(coinToSellID, initialBalance) + initialVolume.Add(initialVolume, initialBalance) tx := createSellCoinTx(coinToSellID, coinToBuy, coinToSellID, toSell, 1) if err := tx.Sign(privateKey); err != nil { @@ -430,6 +448,8 @@ func TestSellCoinTxCustomToBaseCustomCommission(t *testing.T) { if coinData.Volume().Cmp(estimatedSupply) != 0 { t.Fatalf("Wrong coin supply") } + + checkState(t, cState) } func TestSellCoinTxCustomToCustomCustom1Commission(t *testing.T) { @@ -448,6 +468,8 @@ func TestSellCoinTxCustomToCustomCustom1Commission(t *testing.T) { privateKey, addr := getAccount() cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) + cState.Coins.AddVolume(coinToSellID, initialBalance) + initialVolume1.Add(initialVolume1, initialBalance) tx := createSellCoinTx(coinToSellID, coinToBuyID, coinToSellID, toSell, 1) if err := tx.Sign(privateKey); err != nil { @@ -517,6 +539,8 @@ func TestSellCoinTxCustomToCustomCustom1Commission(t *testing.T) { t.Fatalf("Wrong coin supply") } } + + checkState(t, cState) } func TestSellCoinTxCustomToCustomCustom2Commission(t *testing.T) { @@ -536,7 +560,12 @@ func TestSellCoinTxCustomToCustomCustom2Commission(t *testing.T) { privateKey, addr := getAccount() cState.Accounts.AddBalance(addr, coinToSellID, initialBalance) + cState.Coins.AddVolume(coinToSellID, initialBalance) + initialVolume1.Add(initialVolume1, initialBalance) + cState.Accounts.AddBalance(addr, coinToBuyID, initialGasBalance) + cState.Coins.AddVolume(coinToBuyID, initialGasBalance) + initialVolume2.Add(initialVolume2, initialGasBalance) tx := createSellCoinTx(coinToSellID, coinToBuyID, coinToBuyID, toSell, 1) if err := tx.Sign(privateKey); err != nil { @@ -609,6 +638,8 @@ func TestSellCoinTxCustomToCustomCustom2Commission(t *testing.T) { t.Fatalf("Wrong coin supply") } } + + checkState(t, cState) } func TestSellCoinTxToCoinSupplyOverflow(t *testing.T) { @@ -636,6 +667,8 @@ func TestSellCoinTxToCoinSupplyOverflow(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.CoinSupplyOverflow, response.Log) } + checkState(t, cState) + // custom buy and sell coins cState.Coins.Create( @@ -666,6 +699,8 @@ func TestSellCoinTxToCoinSupplyOverflow(t *testing.T) { if response.Code != code.CoinSupplyOverflow { t.Fatalf("Response code is not %d. Error %s", code.CoinSupplyOverflow, response.Log) } + + checkState(t, cState) } func TestSellCoinTxToMinimumValueToBuyReached(t *testing.T) { @@ -713,6 +748,8 @@ func TestSellCoinTxToMinimumValueToBuyReached(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.MinimumValueToBuyReached, response.Log) } + checkState(t, cState) + // coin to buy == base coin cState.Accounts.AddBalance(addr, coinToBuyID, helpers.BipToPip(big.NewInt(100000))) @@ -741,6 +778,8 @@ func TestSellCoinTxToMinimumValueToBuyReached(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.MinimumValueToBuyReached, response.Log) } + checkState(t, cState) + // custom buy and sell coins cState.Coins.Create( @@ -781,6 +820,8 @@ func TestSellCoinTxToMinimumValueToBuyReached(t *testing.T) { if response.Code != code.MinimumValueToBuyReached { t.Fatalf("Response code is not %d. Error %s", code.MinimumValueToBuyReached, response.Log) } + + checkState(t, cState) } func TestSellCoinTxToCoinReserveNotSufficient(t *testing.T) { @@ -802,6 +843,7 @@ func TestSellCoinTxToCoinReserveNotSufficient(t *testing.T) { customCoinToSellID := cState.App.GetNextCoinID() cState.App.SetCoinsCount(customCoinToSellID.Uint32()) + cState.Accounts.AddBalance(types.Address{0}, customCoinToSellID, helpers.BipToPip(big.NewInt(100000))) cState.Accounts.AddBalance(addr, coinToSellID, helpers.BipToPip(big.NewInt(5000000))) tx := createSellCoinTx(coinToBuyID, coinToSellID, coinToBuyID, helpers.BipToPip(big.NewInt(100000)), 1) @@ -819,6 +861,8 @@ func TestSellCoinTxToCoinReserveNotSufficient(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveNotSufficient, response.Log) } + checkState(t, cState) + // gas coin == coin to sell cState.Coins.SubReserve(coinToBuyID, helpers.BipToPip(big.NewInt(100000))) @@ -837,6 +881,8 @@ func TestSellCoinTxToCoinReserveNotSufficient(t *testing.T) { if response.Code != code.CoinReserveNotSufficient { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveNotSufficient, response.Log) } + + checkState(t, cState) } func TestSellCoinTxInsufficientFunds(t *testing.T) { @@ -864,6 +910,8 @@ func TestSellCoinTxInsufficientFunds(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestSellCoinTxEqualCoins(t *testing.T) { @@ -885,6 +933,8 @@ func TestSellCoinTxEqualCoins(t *testing.T) { if response.Code != code.CrossConvert { t.Fatalf("Response code is not %d. Error %s", code.CrossConvert, response.Log) } + + checkState(t, cState) } func TestSellCoinTxToNonExistCoins(t *testing.T) { @@ -922,6 +972,8 @@ func TestSellCoinTxToNonExistCoins(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) } + checkState(t, cState) + tx = createSellCoinTx(coinID, types.GetBaseCoinID(), 5, big.NewInt(1), 1) if err := tx.Sign(privateKey); err != nil { t.Fatal(err) @@ -936,6 +988,8 @@ func TestSellCoinTxToNonExistCoins(t *testing.T) { if response.Code != code.CoinNotExists { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) } + + checkState(t, cState) } func createSellCoinTx(sellCoin, buyCoin, gasCoin types.CoinID, valueToSell *big.Int, nonce uint64) *Transaction { diff --git a/core/transaction/send_test.go b/core/transaction/send_test.go index 2039da85f..88fe8af1c 100644 --- a/core/transaction/send_test.go +++ b/core/transaction/send_test.go @@ -71,6 +71,8 @@ func TestSendTx(t *testing.T) { if testBalance.Cmp(targetTestBalance) != 0 { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", to.String(), targetTestBalance, testBalance) } + + checkState(t, cState) } func TestSendMultisigTx(t *testing.T) { @@ -139,6 +141,8 @@ func TestSendMultisigTx(t *testing.T) { if testBalance.Cmp(targetTestBalance) != 0 { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", to.String(), targetTestBalance, testBalance) } + + checkState(t, cState) } func TestSendFailedMultisigTx(t *testing.T) { @@ -207,6 +211,8 @@ func TestSendFailedMultisigTx(t *testing.T) { if testBalance.Cmp(targetTestBalance) != 0 { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", to.String(), targetTestBalance, testBalance) } + + checkState(t, cState) } func TestSendWithNotExistedCoin(t *testing.T) { @@ -252,6 +258,8 @@ func TestSendWithNotExistedCoin(t *testing.T) { if response.Code != code.CoinNotExists { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) } + + checkState(t, cState) } func TestSendTxWithCustomCoin(t *testing.T) { @@ -261,6 +269,7 @@ func TestSendTxWithCustomCoin(t *testing.T) { addr := crypto.PubkeyToAddress(privateKey.PublicKey) coin := createTestCoin(cState) + cState.Coins.AddVolume(coin, helpers.BipToPip(big.NewInt(1000000))) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) value := helpers.BipToPip(big.NewInt(10)) @@ -301,7 +310,7 @@ func TestSendTxWithCustomCoin(t *testing.T) { t.Fatalf("Response code is not 0. Error: %s", response.Log) } - targetBalance, _ := big.NewInt(0).SetString("999989998999999954999998", 10) + targetBalance, _ := big.NewInt(0).SetString("999989988999999504999969", 10) balance := cState.Accounts.GetBalance(addr, coin) if balance.Cmp(targetBalance) != 0 { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", addr.String(), targetBalance, balance) @@ -312,6 +321,8 @@ func TestSendTxWithCustomCoin(t *testing.T) { if testBalance.Cmp(targetTestBalance) != 0 { t.Fatalf("Target %s balance is not correct. Expected %s, got %s", to.String(), targetTestBalance, testBalance) } + + checkState(t, cState) } func TestSendTxToGasCoinReserveUnderflow(t *testing.T) { @@ -322,6 +333,7 @@ func TestSendTxToGasCoinReserveUnderflow(t *testing.T) { coin := createTestCoin(cState) cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) + cState.Coins.AddVolume(coin, helpers.BipToPip(big.NewInt(1000000))) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) value := helpers.BipToPip(big.NewInt(10)) @@ -361,4 +373,6 @@ func TestSendTxToGasCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error: %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } diff --git a/core/transaction/set_halt_block_test.go b/core/transaction/set_halt_block_test.go index 48432aa96..87ac4575d 100644 --- a/core/transaction/set_halt_block_test.go +++ b/core/transaction/set_halt_block_test.go @@ -89,6 +89,8 @@ func TestSetHaltBlockTx(t *testing.T) { if haltBlock.Pubkey != pubkey { t.Fatalf("Wront halt block pubkey. Expected pubkey: %s, got %s", pubkey, haltBlock.Pubkey.String()+"asd") } + + checkState(t, cState) } func TestSetHaltBlockTxWithWrongHeight(t *testing.T) { @@ -149,6 +151,8 @@ func TestSetHaltBlockTxWithWrongHeight(t *testing.T) { if halts != nil { t.Fatalf("Halts found at height: %d", haltHeight) } + + checkState(t, cState) } func TestSetHaltBlockTxWithWrongOwnership(t *testing.T) { @@ -210,6 +214,8 @@ func TestSetHaltBlockTxWithWrongOwnership(t *testing.T) { if halts != nil { t.Fatalf("Halts found at height: %d", haltHeight) } + + checkState(t, cState) } func TestSetHaltBlockTxToNonExistCandidate(t *testing.T) { @@ -218,6 +224,8 @@ func TestSetHaltBlockTxToNonExistCandidate(t *testing.T) { t.Fatalf("Cannot load state. Error %s", err) } + createDefaultValidator(cState) + haltHeight := 500000 + uint64(100) privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) @@ -262,6 +270,8 @@ func TestSetHaltBlockTxToNonExistCandidate(t *testing.T) { if response.Code != code.CandidateNotFound { t.Fatalf("Response code is not %d. Error %s", code.CandidateNotFound, response.Log) } + + checkState(t, cState) } func TestSetHaltBlockTxToInsufficientFunds(t *testing.T) { @@ -315,6 +325,8 @@ func TestSetHaltBlockTxToInsufficientFunds(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestSetHaltBlockTxToGasCoinReserveUnderflow(t *testing.T) { @@ -323,6 +335,8 @@ func TestSetHaltBlockTxToGasCoinReserveUnderflow(t *testing.T) { t.Fatalf("Cannot load state. Error %s", err) } + createDefaultValidator(cState) + haltHeight := 500000 + uint64(100) privateKey, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(privateKey.PublicKey) @@ -370,4 +384,6 @@ func TestSetHaltBlockTxToGasCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } diff --git a/core/transaction/switch_candidate_status_test.go b/core/transaction/switch_candidate_status_test.go index 6a205906e..e43622dfa 100644 --- a/core/transaction/switch_candidate_status_test.go +++ b/core/transaction/switch_candidate_status_test.go @@ -75,6 +75,8 @@ func TestSwitchCandidateStatusTx(t *testing.T) { if candidate.Status != candidates.CandidateStatusOnline { t.Fatalf("Status has not changed") } + + checkState(t, cState) } func TestSetCandidateOffTx(t *testing.T) { @@ -138,6 +140,8 @@ func TestSetCandidateOffTx(t *testing.T) { if candidate.Status != candidates.CandidateStatusOffline { t.Fatalf("Status has not changed") } + + checkState(t, cState) } func TestSwitchCandidateStatusTxToNonExistCandidate(t *testing.T) { @@ -183,6 +187,8 @@ func TestSwitchCandidateStatusTxToNonExistCandidate(t *testing.T) { if response.Code != code.CandidateNotFound { t.Fatalf("Response code is not %d. Error %s", code.CandidateNotFound, response.Log) } + + checkState(t, cState) } func TestSwitchCandidateStatusTxToCandidateOwnership(t *testing.T) { @@ -231,6 +237,8 @@ func TestSwitchCandidateStatusTxToCandidateOwnership(t *testing.T) { if response.Code != code.IsNotOwnerOfCandidate { t.Fatalf("Response code is not %d. Error %s", code.IsNotOwnerOfCandidate, response.Log) } + + checkState(t, cState) } func TestSwitchCandidateStatusToGasCoinReserveUnderflow(t *testing.T) { @@ -241,6 +249,7 @@ func TestSwitchCandidateStatusToGasCoinReserveUnderflow(t *testing.T) { coin := createTestCoin(cState) cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(90000))) + cState.Coins.AddVolume(coin, helpers.BipToPip(big.NewInt(1000000))) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) pubkey := types.Pubkey{} @@ -280,6 +289,8 @@ func TestSwitchCandidateStatusToGasCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } func TestSwitchCandidateStatusToInsufficientFundsForGas(t *testing.T) { @@ -326,6 +337,8 @@ func TestSwitchCandidateStatusToInsufficientFundsForGas(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + checkState(t, cState) + cState.Candidates.SetOnline(pubkey) tx.Type = TypeSetCandidateOffline @@ -342,6 +355,8 @@ func TestSwitchCandidateStatusToInsufficientFundsForGas(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestSwitchCandidateStatusToCoinReserveUnderflow(t *testing.T) { @@ -355,6 +370,7 @@ func TestSwitchCandidateStatusToCoinReserveUnderflow(t *testing.T) { rand.Read(pubkey[:]) cState.Candidates.Create(addr, addr, addr, pubkey, 10) cState.Candidates.SetOnline(pubkey) + cState.Coins.AddVolume(coin, helpers.BipToPip(big.NewInt(1000000))) cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1000000))) cState.Coins.SubReserve(coin, helpers.BipToPip(big.NewInt(100000))) @@ -390,4 +406,6 @@ func TestSwitchCandidateStatusToCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } diff --git a/core/transaction/unbond_test.go b/core/transaction/unbond_test.go index 9224255f8..da821436d 100644 --- a/core/transaction/unbond_test.go +++ b/core/transaction/unbond_test.go @@ -81,6 +81,8 @@ func TestUnbondTx(t *testing.T) { if stake.Value.Cmp(types.Big0) != 0 { t.Fatalf("Stake value is not corrent. Expected %s, got %s", types.Big0, stake.Value) } + + checkState(t, cState) } func TestFullUnbondTxWithWatchlist(t *testing.T) { @@ -151,6 +153,8 @@ func TestFullUnbondTxWithWatchlist(t *testing.T) { if wl != nil { t.Fatalf("Waitlist is not deleted") } + + checkState(t, cState) } func TestUnbondTxWithWatchlist(t *testing.T) { @@ -221,6 +225,8 @@ func TestUnbondTxWithWatchlist(t *testing.T) { if wl.Value.Cmp(amount) != 0 { t.Fatalf("Waitlist is not correct") } + + checkState(t, cState) } func TestUnbondTxToDecodeError(t *testing.T) { @@ -265,6 +271,8 @@ func TestUnbondTxToDecodeError(t *testing.T) { if response.Code != code.DecodeError { t.Fatalf("Response code is not %d. Error %s", code.DecodeError, response.Log) } + + checkState(t, cState) } func TestUnbondTxToNotExistCoin(t *testing.T) { @@ -308,6 +316,8 @@ func TestUnbondTxToNotExistCoin(t *testing.T) { if response.Code != code.CoinNotExists { t.Fatalf("Response code is not %d. Error %s", code.CoinNotExists, response.Log) } + + checkState(t, cState) } func TestUnbondTxToNotExistCandidate(t *testing.T) { @@ -351,6 +361,8 @@ func TestUnbondTxToNotExistCandidate(t *testing.T) { if response.Code != code.CandidateNotFound { t.Fatalf("Response code is not %d. Error %s", code.CandidateNotFound, response.Log) } + + checkState(t, cState) } func TestUnbondTxToNotExistStake(t *testing.T) { @@ -394,6 +406,8 @@ func TestUnbondTxToNotExistStake(t *testing.T) { if response.Code != code.StakeNotFound { t.Fatalf("Response code is not %d. Error %s", code.StakeNotFound, response.Log) } + + checkState(t, cState) } func TestUnbondTxToInsufficientStake(t *testing.T) { @@ -442,6 +456,8 @@ func TestUnbondTxToInsufficientStake(t *testing.T) { if response.Code != code.InsufficientStake { t.Fatalf("Response code is not %d. Error %s", code.InsufficientStake, response.Log) } + + checkState(t, cState) } func TestUnbondTxToInsufficientFunds(t *testing.T) { @@ -489,6 +505,8 @@ func TestUnbondTxToInsufficientFunds(t *testing.T) { if response.Code != code.InsufficientFunds { t.Fatalf("Response code is not %d. Error %s", code.InsufficientFunds, response.Log) } + + checkState(t, cState) } func TestUnbondTxToInsufficientAmountAtWaitlist(t *testing.T) { @@ -535,6 +553,8 @@ func TestUnbondTxToInsufficientAmountAtWaitlist(t *testing.T) { if response.Code != code.InsufficientWaitList { t.Fatalf("Response code is not %d. Error %s", code.InsufficientWaitList, response.Log) } + + checkState(t, cState) } func TestUnbondTxToGasCoinReserveUnderflow(t *testing.T) { @@ -585,4 +605,6 @@ func TestUnbondTxToGasCoinReserveUnderflow(t *testing.T) { if response.Code != code.CoinReserveUnderflow { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveUnderflow, response.Log) } + + checkState(t, cState) } diff --git a/core/types/appstate.go b/core/types/appstate.go index 9fc009844..dd6fb2906 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -130,18 +130,18 @@ func (s *AppState) Verify() error { } } - coins := map[CoinSymbol]struct{}{} + coins := map[uint64]struct{}{} for _, coin := range s.Coins { if coin.Symbol.IsBaseCoin() { return fmt.Errorf("base coin should not be declared") } // check duplicated coins - if _, exists := coins[coin.Symbol]; exists { + if _, exists := coins[coin.ID]; exists { return fmt.Errorf("duplicated coin %s", coin.Symbol) } - coins[coin.Symbol] = struct{}{} + coins[coin.ID] = struct{}{} // check coins' volume volume := big.NewInt(0) From 98a029e9dbaae220936deaff9aca6bde759d5429 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Wed, 14 Oct 2020 17:12:03 +0300 Subject: [PATCH 404/426] fix --- core/transaction/buy_coin_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/transaction/buy_coin_test.go b/core/transaction/buy_coin_test.go index 661721463..3d17ef510 100644 --- a/core/transaction/buy_coin_test.go +++ b/core/transaction/buy_coin_test.go @@ -1166,7 +1166,7 @@ func TestBuyCoinTxToMaximumValueToSellReached(t *testing.T) { coinToBuyID, sellCoinID := createTestCoin(cState), types.GetBaseCoinID() valueToBuy := big.NewInt(2e18) - cState.Accounts.AddBalance(addr, sellCoinID, valueToBuy) + //cState.Accounts.AddBalance(addr, sellCoinID, valueToBuy) cState.Coins.AddVolume(sellCoinID, valueToBuy) data := BuyCoinData{ @@ -1246,6 +1246,8 @@ func TestBuyCoinTxToMaximumValueToSellReached(t *testing.T) { coinToSellID := cState.App.GetNextCoinID() cState.App.SetCoinsCount(coinToSellID.Uint32()) + cState.Accounts.AddBalance(types.Address{0}, coinToSellID, helpers.BipToPip(big.NewInt(100000))) + data.CoinToBuy = coinToBuyID data.CoinToSell = coinToSellID data.MaximumValueToSell = big.NewInt(1) @@ -1269,7 +1271,7 @@ func TestBuyCoinTxToMaximumValueToSellReached(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.MaximumValueToSellReached, response.Log) } - data.MaximumValueToSell = big.NewInt(2000360064812986923) + data.MaximumValueToSell = big.NewInt(1000360064812986923) encodedData, err = rlp.EncodeToBytes(data) if err != nil { panic(err) From 1b1743d4fa4ed664349ef0b95e431389d5621d0f Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 15 Oct 2020 00:42:35 +0300 Subject: [PATCH 405/426] edit coin id to string represent in api v2 /events --- core/events/types.go | 18 +++++++++--------- core/minter/minter.go | 2 +- core/state/candidates/candidates.go | 6 +++--- core/state/frozenfunds/frozen_funds.go | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/core/events/types.go b/core/events/types.go index fd8404791..34b674477 100644 --- a/core/events/types.go +++ b/core/events/types.go @@ -155,7 +155,7 @@ func (s *slash) compile(pubKey [32]byte, address [20]byte) Event { event := new(SlashEvent) event.ValidatorPubKey = pubKey event.Address = address - event.Coin = types.CoinID(s.Coin) + event.Coin = uint64(s.Coin) event.Amount = big.NewInt(0).SetBytes(s.Amount).String() return event } @@ -171,7 +171,7 @@ func (s *slash) pubKeyID() uint16 { type SlashEvent struct { Address types.Address `json:"address"` Amount string `json:"amount"` - Coin types.CoinID `json:"coin"` + Coin uint64 `json:"coin"` ValidatorPubKey types.Pubkey `json:"validator_pub_key"` } @@ -198,7 +198,7 @@ func (se *SlashEvent) validatorPubKey() types.Pubkey { func (se *SlashEvent) convert(pubKeyID uint16, addressID uint32) compactEvent { result := new(slash) result.AddressID = addressID - result.Coin = se.Coin.Uint32() + result.Coin = uint32(se.Coin) bi, _ := big.NewInt(0).SetString(se.Amount, 10) result.Amount = bi.Bytes() result.PubKeyID = pubKeyID @@ -216,7 +216,7 @@ func (u *unbond) compile(pubKey [32]byte, address [20]byte) Event { event := new(UnbondEvent) event.ValidatorPubKey = pubKey event.Address = address - event.Coin = types.CoinID(u.Coin) + event.Coin = uint64(u.Coin) event.Amount = big.NewInt(0).SetBytes(u.Amount).String() return event } @@ -232,7 +232,7 @@ func (u *unbond) pubKeyID() uint16 { type UnbondEvent struct { Address types.Address `json:"address"` Amount string `json:"amount"` - Coin types.CoinID `json:"coin"` + Coin uint64 `json:"coin"` ValidatorPubKey types.Pubkey `json:"validator_pub_key"` } @@ -259,7 +259,7 @@ func (ue *UnbondEvent) validatorPubKey() types.Pubkey { func (ue *UnbondEvent) convert(pubKeyID uint16, addressID uint32) compactEvent { result := new(unbond) result.AddressID = addressID - result.Coin = ue.Coin.Uint32() + result.Coin = uint32(ue.Coin) bi, _ := big.NewInt(0).SetString(ue.Amount, 10) result.Amount = bi.Bytes() result.PubKeyID = pubKeyID @@ -277,7 +277,7 @@ func (u *stakeKick) compile(pubKey [32]byte, address [20]byte) Event { event := new(StakeKickEvent) event.ValidatorPubKey = pubKey event.Address = address - event.Coin = types.CoinID(u.Coin) + event.Coin = uint64(u.Coin) event.Amount = big.NewInt(0).SetBytes(u.Amount).String() return event } @@ -293,7 +293,7 @@ func (u *stakeKick) pubKeyID() uint16 { type StakeKickEvent struct { Address types.Address `json:"address"` Amount string `json:"amount"` - Coin types.CoinID `json:"coin"` + Coin uint64 `json:"coin"` ValidatorPubKey types.Pubkey `json:"validator_pub_key"` } @@ -320,7 +320,7 @@ func (ue *StakeKickEvent) validatorPubKey() types.Pubkey { func (ue *StakeKickEvent) convert(pubKeyID uint16, addressID uint32) compactEvent { result := new(stakeKick) result.AddressID = addressID - result.Coin = ue.Coin.Uint32() + result.Coin = uint32(ue.Coin) bi, _ := big.NewInt(0).SetString(ue.Amount, 10) result.Amount = bi.Bytes() result.PubKeyID = pubKeyID diff --git a/core/minter/minter.go b/core/minter/minter.go index 657a84ce8..aa5bea05b 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -200,7 +200,7 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res app.eventsDB.AddEvent(uint32(req.Header.Height), &eventsdb.UnbondEvent{ Address: item.Address, Amount: item.Value.String(), - Coin: item.Coin, + Coin: uint64(item.Coin), ValidatorPubKey: *item.CandidateKey, }) app.stateDeliver.Accounts.AddBalance(item.Address, item.Coin, item.Value) diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 2b55958b0..d5ef4aa18 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -296,7 +296,7 @@ func (c *Candidates) PunishByzantineCandidate(height uint64, tmAddress types.TmA c.bus.Events().AddEvent(uint32(height), &eventsdb.SlashEvent{ Address: stake.Owner, Amount: slashed.String(), - Coin: stake.Coin, + Coin: uint64(stake.Coin), ValidatorPubKey: candidate.PubKey, }) @@ -402,7 +402,7 @@ func (c *Candidates) stakeKick(owner types.Address, value *big.Int, coin types.C c.bus.Events().AddEvent(uint32(height), &eventsdb.StakeKickEvent{ Address: owner, Amount: value.String(), - Coin: coin, + Coin: uint64(coin), ValidatorPubKey: pubKey, }) c.bus.Checker().AddCoin(coin, big.NewInt(0).Neg(value)) @@ -789,7 +789,7 @@ func (c *Candidates) Punish(height uint64, address types.TmAddress) *big.Int { c.bus.Events().AddEvent(uint32(height), &eventsdb.SlashEvent{ Address: stake.Owner, Amount: slashed.String(), - Coin: stake.Coin, + Coin: uint64(stake.Coin), ValidatorPubKey: candidate.PubKey, }) diff --git a/core/state/frozenfunds/frozen_funds.go b/core/state/frozenfunds/frozen_funds.go index 8f9aa6264..dccf58b2b 100644 --- a/core/state/frozenfunds/frozen_funds.go +++ b/core/state/frozenfunds/frozen_funds.go @@ -113,7 +113,7 @@ func (f *FrozenFunds) PunishFrozenFundsWithAddress(fromHeight uint64, toHeight u f.bus.Events().AddEvent(uint32(fromHeight), &eventsdb.SlashEvent{ Address: item.Address, Amount: slashed.String(), - Coin: item.Coin, + Coin: uint64(item.Coin), ValidatorPubKey: *item.CandidateKey, }) From a089743a0edde75adbab7e8d6be93552624471e1 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 15 Oct 2020 09:24:18 +0300 Subject: [PATCH 406/426] fix buy coin test --- core/transaction/buy_coin_test.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/core/transaction/buy_coin_test.go b/core/transaction/buy_coin_test.go index 3d17ef510..56d7ea55a 100644 --- a/core/transaction/buy_coin_test.go +++ b/core/transaction/buy_coin_test.go @@ -1271,6 +1271,8 @@ func TestBuyCoinTxToMaximumValueToSellReached(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.MaximumValueToSellReached, response.Log) } + checkState(t, cState) + data.MaximumValueToSell = big.NewInt(1000360064812986923) encodedData, err = rlp.EncodeToBytes(data) if err != nil { @@ -1332,6 +1334,8 @@ func TestBuyCoinTxToCoinReserveNotSufficient(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveNotSufficient, response.Log) } + checkState(t, cState) + // gas coin == coin to buy cState.Coins.SubReserve(tx.GasCoin, helpers.BipToPip(big.NewInt(100000))) @@ -1351,10 +1355,9 @@ func TestBuyCoinTxToCoinReserveNotSufficient(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveNotSufficient, response.Log) } - // gas coin == coin to sell + checkState(t, cState) - cState.Coins.AddReserve(coinToBuyID, helpers.BipToPip(big.NewInt(11))) - cState.Coins.SubReserve(coinToBuyID, big.NewInt(9e17)) + // gas coin == coin to sell tx = createBuyCoinTx(coinToBuyID, coinToSellID, coinToBuyID, helpers.BipToPip(big.NewInt(1)), 1) if err := tx.Sign(privateKey); err != nil { @@ -1371,6 +1374,8 @@ func TestBuyCoinTxToCoinReserveNotSufficient(t *testing.T) { t.Fatalf("Response code is not %d. Error %s", code.CoinReserveNotSufficient, response.Log) } + checkState(t, cState) + // gas coin == coin to buy // sell coin == base coin From 5731aeda5f93769487433baadd5e54822078c777 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 15 Oct 2020 09:54:13 +0300 Subject: [PATCH 407/426] fix state coin --- core/state/coins/coins.go | 67 ++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index 6fa7ce0f4..4db57b3b1 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -31,9 +31,10 @@ type RCoins interface { } type Coins struct { - list map[types.CoinID]*Model - dirty map[types.CoinID]struct{} - symbolsList map[types.CoinSymbol]types.CoinID + list map[types.CoinID]*Model + dirty map[types.CoinID]struct{} + symbolsList map[types.CoinSymbol][]types.CoinID + symbolsInfoList map[types.CoinSymbol]*SymbolInfo bus *bus.Bus iavl tree.MTree @@ -44,9 +45,10 @@ type Coins struct { func NewCoins(stateBus *bus.Bus, iavl tree.MTree) (*Coins, error) { coins := &Coins{ bus: stateBus, iavl: iavl, - list: map[types.CoinID]*Model{}, - dirty: map[types.CoinID]struct{}{}, - symbolsList: map[types.CoinSymbol]types.CoinID{}, + list: map[types.CoinID]*Model{}, + dirty: map[types.CoinID]struct{}{}, + symbolsList: map[types.CoinSymbol][]types.CoinID{}, + symbolsInfoList: map[types.CoinSymbol]*SymbolInfo{}, } coins.bus.SetCoins(NewBus(coins)) @@ -106,7 +108,8 @@ func (c *Coins) Commit() error { } // clear list - c.symbolsList = make(map[types.CoinSymbol]types.CoinID) + c.symbolsList = make(map[types.CoinSymbol][]types.CoinID) + c.symbolsInfoList = make(map[types.CoinSymbol]*SymbolInfo) return nil } @@ -132,10 +135,6 @@ func (c *Coins) ExistsBySymbol(symbol types.CoinSymbol) bool { return true } - if _, ok := c.getSymbolFromMap(symbol); ok { - return true - } - return c.getBySymbol(symbol) != nil } @@ -144,10 +143,6 @@ func (c *Coins) GetCoinBySymbol(symbol types.CoinSymbol, version types.CoinVersi return c.get(types.GetBaseCoinID()) } - if id, ok := c.getSymbolFromMap(symbol); ok { - return c.getFromMap(id) - } - coins := c.getBySymbol(symbol) if len(coins) == 0 { return nil @@ -223,10 +218,12 @@ func (c *Coins) Create(id types.CoinID, symbol types.CoinSymbol, name string, COwnerAddress: owner, isDirty: true, } + + c.setSymbolInfoToMap(coin.symbolInfo, coin.Symbol()) } - c.setToMap(coin.id, coin) - c.setSymbolToMap(coin.id, coin.CSymbol) + c.setSymbolToMap([]types.CoinID{coin.ID()}, coin.Symbol()) + c.setToMap(coin.ID(), coin) coin.SetReserve(reserve) coin.SetVolume(volume) @@ -256,9 +253,11 @@ func (c *Coins) Recreate(newID types.CoinID, name string, symbol types.CoinSymbo } } + symbolCoins = append(symbolCoins, recreateCoin.id) recreateCoin.CVersion = lastVersion + 1 recreateCoin.isDirty = true + c.setSymbolToMap(symbolCoins, symbol) c.setToMap(recreateCoin.id, recreateCoin) c.markDirty(recreateCoin.id) @@ -272,6 +271,7 @@ func (c *Coins) ChangeOwner(symbol types.CoinSymbol, owner types.Address) { coin := c.GetCoinBySymbol(symbol, 0) coin.symbolInfo = info + c.setSymbolInfoToMap(coin.symbolInfo, coin.Symbol()) c.setToMap(coin.ID(), coin) c.markDirty(coin.ID()) } @@ -323,6 +323,10 @@ func (c *Coins) get(id types.CoinID) *Model { } func (c *Coins) getSymbolInfo(symbol types.CoinSymbol) *SymbolInfo { + if info, ok := c.getSymbolInfoFromMap(symbol); ok { + return info + } + info := &SymbolInfo{} _, enc := c.iavl.Get(getSymbolInfoPath(symbol)) @@ -338,6 +342,10 @@ func (c *Coins) getSymbolInfo(symbol types.CoinSymbol) *SymbolInfo { } func (c *Coins) getBySymbol(symbol types.CoinSymbol) []types.CoinID { + if coins, ok := c.getSymbolFromMap(symbol); ok { + return coins + } + var coins []types.CoinID _, enc := c.iavl.Get(getSymbolCoinsPath(symbol)) @@ -416,19 +424,34 @@ func (c *Coins) setToMap(id types.CoinID, model *Model) { c.list[id] = model } -func (c *Coins) getSymbolFromMap(symbol types.CoinSymbol) (types.CoinID, bool) { +func (c *Coins) getSymbolInfoFromMap(symbol types.CoinSymbol) (*SymbolInfo, bool) { + c.lock.RLock() + defer c.lock.RUnlock() + + info, ok := c.symbolsInfoList[symbol] + return info, ok +} + +func (c *Coins) setSymbolInfoToMap(info *SymbolInfo, symbol types.CoinSymbol) { + c.lock.Lock() + defer c.lock.Unlock() + + c.symbolsInfoList[symbol] = info +} + +func (c *Coins) getSymbolFromMap(symbol types.CoinSymbol) ([]types.CoinID, bool) { c.lock.RLock() defer c.lock.RUnlock() - id, ok := c.symbolsList[symbol] - return id, ok + coins, ok := c.symbolsList[symbol] + return coins, ok } -func (c *Coins) setSymbolToMap(id types.CoinID, symbol types.CoinSymbol) { +func (c *Coins) setSymbolToMap(coins []types.CoinID, symbol types.CoinSymbol) { c.lock.Lock() defer c.lock.Unlock() - c.symbolsList[symbol] = id + c.symbolsList[symbol] = coins } func getSymbolCoinsPath(symbol types.CoinSymbol) []byte { From 35a8aebeabeb4491b3b3f0007d71d42b8a14afa9 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 15 Oct 2020 10:19:23 +0300 Subject: [PATCH 408/426] fix recreate --- core/state/coins/coins.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index 4db57b3b1..d48bca3b1 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -65,8 +65,6 @@ func (c *Coins) Commit() error { if coin.IsCreated() { ids := c.getBySymbol(coin.Symbol()) - ids = append(ids, coin.ID()) - data, err := rlp.EncodeToBytes(ids) if err != nil { return fmt.Errorf("can't encode object at %d: %v", id, err) @@ -222,7 +220,10 @@ func (c *Coins) Create(id types.CoinID, symbol types.CoinSymbol, name string, c.setSymbolInfoToMap(coin.symbolInfo, coin.Symbol()) } - c.setSymbolToMap([]types.CoinID{coin.ID()}, coin.Symbol()) + ids := c.getBySymbol(coin.Symbol()) + ids = append(ids, coin.ID()) + + c.setSymbolToMap(ids, coin.Symbol()) c.setToMap(coin.ID(), coin) coin.SetReserve(reserve) @@ -253,11 +254,9 @@ func (c *Coins) Recreate(newID types.CoinID, name string, symbol types.CoinSymbo } } - symbolCoins = append(symbolCoins, recreateCoin.id) recreateCoin.CVersion = lastVersion + 1 recreateCoin.isDirty = true - c.setSymbolToMap(symbolCoins, symbol) c.setToMap(recreateCoin.id, recreateCoin) c.markDirty(recreateCoin.id) From f470d833451af80a81c9a7e64a3863e05c8c7162 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 15 Oct 2020 12:25:29 +0300 Subject: [PATCH 409/426] fix coins state --- core/state/coins/coins.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index d48bca3b1..58818d884 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -105,10 +105,6 @@ func (c *Coins) Commit() error { } } - // clear list - c.symbolsList = make(map[types.CoinSymbol][]types.CoinID) - c.symbolsInfoList = make(map[types.CoinSymbol]*SymbolInfo) - return nil } @@ -238,7 +234,7 @@ func (c *Coins) Create(id types.CoinID, symbol types.CoinSymbol, name string, func (c *Coins) Recreate(newID types.CoinID, name string, symbol types.CoinSymbol, volume *big.Int, crr uint32, reserve *big.Int, maxSupply *big.Int, ) { - recreateCoin := c.GetCoinBySymbol(symbol, 0) + recreateCoin := c.GetCoinBySymbol(symbol, BaseVersion) if recreateCoin == nil { panic("coin to recreate does not exists") } @@ -267,7 +263,7 @@ func (c *Coins) ChangeOwner(symbol types.CoinSymbol, owner types.Address) { info := c.getSymbolInfo(symbol) info.setOwnerAddress(owner) - coin := c.GetCoinBySymbol(symbol, 0) + coin := c.GetCoinBySymbol(symbol, BaseVersion) coin.symbolInfo = info c.setSymbolInfoToMap(coin.symbolInfo, coin.Symbol()) @@ -337,6 +333,8 @@ func (c *Coins) getSymbolInfo(symbol types.CoinSymbol) *SymbolInfo { panic(fmt.Sprintf("failed to decode coin symbol %s: %s", symbol.String(), err)) } + c.setSymbolInfoToMap(info, symbol) + return info } @@ -356,6 +354,8 @@ func (c *Coins) getBySymbol(symbol types.CoinSymbol) []types.CoinID { panic(fmt.Sprintf("failed to decode coins by symbol %s: %s", symbol, err)) } + c.setSymbolToMap(coins, symbol) + return coins } From c2327710a13fd37250f2972ec2f9d8e502e2d6de Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Thu, 15 Oct 2020 13:08:20 +0300 Subject: [PATCH 410/426] Update build script --- scripts/dist.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/dist.sh b/scripts/dist.sh index ac3eff751..d7595d04a 100644 --- a/scripts/dist.sh +++ b/scripts/dist.sh @@ -32,7 +32,7 @@ echo "==> Building for mac os..." CGO_ENABLED=1 go build -tags "minter gcc" -ldflags "-s -w -X ${GIT_IMPORT}.GitCommit=${GIT_COMMIT}" -o "build/pkg/darwin_amd64/minter" ./cmd/minter echo "==> Building for linux in docker" -docker run -t -v ${PWD}:/go/src/github.com/MinterTeam/minter-go-node/ -i minter-builder-1:latest sh -c 'CGO_ENABLED=1 go build -tags "minter gcc" -ldflags "-s -w -X ${GIT_IMPORT}.GitCommit=${GIT_COMMIT}" -o "build/pkg/linux_amd64/minter" ./cmd/minter/' +docker run -t -v ${PWD}:/go/src/github.com/MinterTeam/minter-go-node/ -i minter-builder-1:latest sh -c "CGO_ENABLED=1 go build -tags 'minter gcc' -ldflags '-s -w -X ${GIT_IMPORT}.GitCommit=${GIT_COMMIT}' -o 'build/pkg/linux_amd64/minter' ./cmd/minter/" # Zip all the files. echo "==> Packaging..." From b86854818bb9fca7f80e802bc5f69c42be37bc13 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Thu, 15 Oct 2020 13:18:24 +0300 Subject: [PATCH 411/426] no message --- core/state/coins/coins.go | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index 58818d884..f80d08558 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -30,6 +30,45 @@ type RCoins interface { GetSymbolInfo(symbol types.CoinSymbol) *SymbolInfo } +// Coins represents coins state in blockchain. +// +// When a coin is created with a CreateCoinTx transaction, such model is created: +// Model { +// id +// info +// symbolInfo +// +// Name +// Crr +// MaxSupply +// Version - is the version of the coin +// Symbol - is the base symbol of the coin +// } +// +// Also, SymbolInfo is created: +// SymbolInfo { +// OwnerAddress +// } +// +// It is a structure that retains the owner of the ticker (not the coin). +// coin.symbolInfo is saved in the symbolsInfoList map, in which the key is the symbol, +// and the value is the owner of the coin, and upon commit is written to the db by this key: +// mainPrefix + symbolPrefix + symbol + infoPrefix. +// +// Also, you need to save all coins for a particular ticker. That is, you need to associate +// the ticker with all the coins that refer to it. For this, there is a map symbolsList, +// in which the key is the ticker, and the value is an array of ids of coins that +// belong to this ticker (just with a different version). When you commit, this array is +// saved to db by this key: mainPrefix + symbolPrefix + symbol. +// +// The coin model is saved at: mainPrefix + id. +// +// When a coin is re-created with a RecreateCoinTx transaction, the state retrieves an array of +// coins that refer to this ticker (getBySymbol). Finds the current current version there, changes +// it to the new version. And the new coin is assigned version 0. The new coin is also added to symbolsList [ticker]. +// +// When changing the owner with a ChangeOwnerTx transaction, the state gets the current owner +// getSymbolInfo (ticker) and changes the owner there and saves it back. type Coins struct { list map[types.CoinID]*Model dirty map[types.CoinID]struct{} From eae900b9f3b4ac2c11ccd0eb89c1caf490bdcc30 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 15 Oct 2020 15:16:16 +0300 Subject: [PATCH 412/426] fix coin export --- core/state/coins/coins.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/state/coins/coins.go b/core/state/coins/coins.go index 58818d884..1bab21147 100644 --- a/core/state/coins/coins.go +++ b/core/state/coins/coins.go @@ -379,7 +379,7 @@ func (c *Coins) getOrderedDirtyCoins() []types.CoinID { func (c *Coins) Export(state *types.AppState) { c.iavl.Iterate(func(key []byte, value []byte) bool { if key[0] == mainPrefix { - if key[1] == symbolPrefix || key[len(key)-1] == infoPrefix { + if len(key) > 5 { return false } @@ -407,6 +407,10 @@ func (c *Coins) Export(state *types.AppState) { return false }) + + sort.Slice(state.Coins[:], func(i, j int) bool { + return helpers.StringToBigInt(state.Coins[i].Reserve).Cmp(helpers.StringToBigInt(state.Coins[j].Reserve)) == 1 + }) } func (c *Coins) getFromMap(id types.CoinID) *Model { From 1b03dcbcbcc20a5bf882c47bd585ccfeec74538c Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 15 Oct 2020 15:33:39 +0300 Subject: [PATCH 413/426] fix --- legacy/frozenfunds/frozen_funds.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/legacy/frozenfunds/frozen_funds.go b/legacy/frozenfunds/frozen_funds.go index 5f2ce931f..c13cbe289 100644 --- a/legacy/frozenfunds/frozen_funds.go +++ b/legacy/frozenfunds/frozen_funds.go @@ -82,7 +82,7 @@ func (f *FrozenFunds) Export(state *types.AppState, height uint64, coinsMap map[ for _, frozenFund := range frozenFunds.List { state.FrozenFunds = append(state.FrozenFunds, types.FrozenFund{ - Height: i, + Height: i - height, Address: frozenFund.Address, CandidateKey: frozenFund.CandidateKey, Coin: coinsMap[frozenFund.Coin].ID, From 3e3cc610ab5a2622ea3eca07714cf606f1cb2348 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Thu, 15 Oct 2020 15:57:39 +0300 Subject: [PATCH 414/426] fix state verify --- core/types/appstate.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/core/types/appstate.go b/core/types/appstate.go index dd6fb2906..1dfe452bf 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -173,11 +173,39 @@ func (s *AppState) Verify() error { } } + for _, wl := range s.Waitlist { + if wl.Coin == coin.ID { + volume.Add(volume, helpers.StringToBigInt(wl.Value)) + } + } + if volume.Cmp(helpers.StringToBigInt(coin.Volume)) != 0 { return fmt.Errorf("wrong coin %s volume (%s)", coin.Symbol.String(), big.NewInt(0).Sub(volume, helpers.StringToBigInt(coin.Volume))) } } + for _, wl := range s.Waitlist { + if !helpers.IsValidBigInt(wl.Value) { + return fmt.Errorf("wrong waitlist value: %s", wl.Value) + } + + // check not existing coins + coinID := CoinID(wl.Coin) + if !coinID.IsBaseCoin() { + foundCoin := false + for _, coin := range s.Coins { + if CoinID(coin.ID) == coinID { + foundCoin = true + break + } + } + + if !foundCoin { + return fmt.Errorf("coin %s not found", coinID) + } + } + } + for _, ff := range s.FrozenFunds { if !helpers.IsValidBigInt(ff.Value) { return fmt.Errorf("wrong frozen fund value: %s", ff.Value) From d10908471c677589a66c800c59ef3bca3129b00b Mon Sep 17 00:00:00 2001 From: klim0v Date: Thu, 15 Oct 2020 16:42:11 +0300 Subject: [PATCH 415/426] fix get block info without keep state --- api/block.go | 2 +- api/transaction.go | 2 +- api/transactions.go | 17 ++++++++------ api/v2/service/block.go | 43 +++++++++++++++++++--------------- api/v2/service/transaction.go | 6 ++--- api/v2/service/transactions.go | 10 ++++---- 6 files changed, 43 insertions(+), 37 deletions(-) diff --git a/api/block.go b/api/block.go index 71ff25aee..cc08ce71a 100644 --- a/api/block.go +++ b/api/block.go @@ -73,7 +73,7 @@ func Block(height int64) (*BlockResponse, error) { } totalValidators := tmValidators.Validators - cState, err := GetStateForHeight(int(height)) + cState, err := GetStateForHeight(0) if err != nil { return nil, err } diff --git a/api/transaction.go b/api/transaction.go index 913ad534e..4aafd4312 100644 --- a/api/transaction.go +++ b/api/transaction.go @@ -15,7 +15,7 @@ func Transaction(hash []byte) (json.RawMessage, error) { decodedTx, _ := transaction.TxDecoder.DecodeFromBytes(tx.Tx) - cState, err := GetStateForHeight(int(tx.Height)) + cState, err := GetStateForHeight(0) if err != nil { return nil, err } diff --git a/api/transactions.go b/api/transactions.go index b0943c3ed..ac8dc9bde 100644 --- a/api/transactions.go +++ b/api/transactions.go @@ -44,13 +44,16 @@ func Transactions(query string, page, perPage int) (*[]json.RawMessage, error) { return nil, err } - result := make([]json.RawMessage, len(rpcResult.Txs)) - for i, tx := range rpcResult.Txs { - cState, err := GetStateForHeight(int(tx.Height)) - if err != nil { - return nil, err - } + cState, err := GetStateForHeight(0) + if err != nil { + return nil, err + } + + cState.RLock() + defer cState.RUnlock() + result := make([]json.RawMessage, 0, len(rpcResult.Txs)) + for _, tx := range rpcResult.Txs { decodedTx, _ := transaction.TxDecoder.DecodeFromBytes(tx.Tx) txJsonEncoder := encoder.NewTxEncoderJSON(cState) response, err := txJsonEncoder.Encode(decodedTx, tx) @@ -58,7 +61,7 @@ func Transactions(query string, page, perPage int) (*[]json.RawMessage, error) { return nil, err } - result[i] = response + result = append(result, response) } return &result, nil diff --git a/api/v2/service/block.go b/api/v2/service/block.go index 88d86a048..9dab7526b 100644 --- a/api/v2/service/block.go +++ b/api/v2/service/block.go @@ -12,6 +12,7 @@ import ( "github.com/MinterTeam/minter-go-node/core/types" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" _struct "github.com/golang/protobuf/ptypes/struct" + "github.com/tendermint/iavl" core_types "github.com/tendermint/tendermint/rpc/core/types" tmTypes "github.com/tendermint/tendermint/types" "google.golang.org/grpc/codes" @@ -46,7 +47,6 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes } var totalValidators []*tmTypes.Validator - var cState *state.CheckState if len(req.Fields) == 0 { response.Size = uint64(len(s.cdc.MustMarshalBinaryLengthPrefixed(block))) @@ -56,12 +56,11 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes return nil, timeoutStatus.Err() } - cState, err = s.blockchain.GetStateForHeight(uint64(height)) - if err != nil { - return nil, status.Error(codes.NotFound, err.Error()) - } + currentState := s.blockchain.CurrentState() + currentState.RLock() + defer currentState.RUnlock() - response.Transactions, err = s.blockTransaction(block, blockResults, cState.Coins()) + response.Transactions, err = s.blockTransaction(block, blockResults, currentState.Coins()) if err != nil { return nil, err } @@ -104,7 +103,14 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes return nil, timeoutStatus.Err() } - response.Missed = missedBlockValidators(cState) + cStateOld, err := s.blockchain.GetStateForHeight(uint64(height)) + if err != iavl.ErrVersionDoesNotExist && err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + if err != iavl.ErrVersionDoesNotExist { + response.Missed = missedBlockValidators(cStateOld) + } return response, nil } @@ -118,23 +124,22 @@ func (s *Service) Block(ctx context.Context, req *pb.BlockRequest) (*pb.BlockRes response.Size = uint64(len(s.cdc.MustMarshalBinaryLengthPrefixed(block))) case pb.BlockRequest_block_reward: response.BlockReward = rewards.GetRewardForBlock(uint64(height)).String() - case pb.BlockRequest_transactions, pb.BlockRequest_missed: - if cState == nil { - cState, err = s.blockchain.GetStateForHeight(uint64(height)) - if err != nil { - return nil, status.Error(codes.NotFound, err.Error()) - } - } - - if pb.BlockRequest_missed == field { - response.Missed = missedBlockValidators(cState) - continue - } + case pb.BlockRequest_transactions: + cState := s.blockchain.CurrentState() response.Transactions, err = s.blockTransaction(block, blockResults, cState.Coins()) if err != nil { return nil, err } + case pb.BlockRequest_missed: + cStateOld, err := s.blockchain.GetStateForHeight(uint64(height)) + if err != iavl.ErrVersionDoesNotExist && err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + if err != iavl.ErrVersionDoesNotExist { + response.Missed = missedBlockValidators(cStateOld) + } case pb.BlockRequest_proposer, pb.BlockRequest_validators: if len(totalValidators) == 0 { diff --git a/api/v2/service/transaction.go b/api/v2/service/transaction.go index f166a551a..e88a76b2f 100644 --- a/api/v2/service/transaction.go +++ b/api/v2/service/transaction.go @@ -34,10 +34,7 @@ func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) ( tags[string(tag.Key)] = string(tag.Value) } - cState, err := s.blockchain.GetStateForHeight(uint64(tx.Height)) - if err != nil { - return nil, status.Error(codes.NotFound, err.Error()) - } + cState := s.blockchain.CurrentState() cState.RLock() defer cState.RUnlock() @@ -45,6 +42,7 @@ func (s *Service) Transaction(ctx context.Context, req *pb.TransactionRequest) ( if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { return nil, timeoutStatus.Err() } + dataStruct, err := encode(decodedTx.GetDecodedData(), cState.Coins()) if err != nil { return nil, status.Error(codes.Internal, err.Error()) diff --git a/api/v2/service/transactions.go b/api/v2/service/transactions.go index e3b9a92d4..bfe5cbd5d 100644 --- a/api/v2/service/transactions.go +++ b/api/v2/service/transactions.go @@ -22,10 +22,10 @@ func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) result := make([]*pb.TransactionResponse, 0, lenTx) if lenTx != 0 { - cState, err := s.blockchain.GetStateForHeight(uint64(rpcResult.Txs[0].Height)) - if err != nil { - return nil, status.Error(codes.NotFound, err.Error()) - } + cState := s.blockchain.CurrentState() + cState.RLock() + defer cState.RUnlock() + for _, tx := range rpcResult.Txs { if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { @@ -51,7 +51,7 @@ func (s *Service) Transactions(ctx context.Context, req *pb.TransactionsRequest) Height: uint64(tx.Height), Index: uint64(tx.Index), From: sender.String(), - Nonce: uint64(decodedTx.Nonce), + Nonce: decodedTx.Nonce, GasPrice: uint64(decodedTx.GasPrice), GasCoin: &pb.Coin{ Id: uint64(decodedTx.GasCoin), From ffc902f25993677e0aa6b3c6aadfef505437409e Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Thu, 15 Oct 2020 23:56:01 +0300 Subject: [PATCH 416/426] temp fix --- core/minter/minter.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/minter/minter.go b/core/minter/minter.go index 657a84ce8..74cc02a1f 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -634,6 +634,8 @@ func (app *Blockchain) isApplicationHalted(height uint64) bool { return true } + return false // todo: remove + halts := app.stateDeliver.Halts.GetHaltBlocks(height) if halts != nil { // calculate total power of validators From aeb68001cf1fc5e83df53a13783142e91636f4ad Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Fri, 16 Oct 2020 00:33:10 +0300 Subject: [PATCH 417/426] Refactor --- core/state/candidates/candidate_test.go | 2 +- core/state/candidates/candidates.go | 2 +- core/state/candidates/model.go | 4 ++-- core/transaction/delegate.go | 8 ++++---- core/transaction/delegate_test.go | 2 +- core/transaction/unbond.go | 4 ++-- core/transaction/unbond_test.go | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/core/state/candidates/candidate_test.go b/core/state/candidates/candidate_test.go index 25bda862f..ca233f309 100644 --- a/core/state/candidates/candidate_test.go +++ b/core/state/candidates/candidate_test.go @@ -1076,7 +1076,7 @@ func TestCandidate_GetFilteredUpdates(t *testing.T) { t.Fatal("candidate not found") } - candidate.FilterUpdates() + candidate.filterUpdates() if len(candidate.updates) != 1 { t.Fatal("updates not merged") diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 2b55958b0..8a7f7f785 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -347,7 +347,7 @@ func (c *Candidates) recalculateStakes(height uint64) { } } - candidate.FilterUpdates() + candidate.filterUpdates() for _, update := range candidate.updates { update.setBipValue(c.calculateBipValue(update.Coin, update.Value, false, true, coinsCache)) } diff --git a/core/state/candidates/model.go b/core/state/candidates/model.go index 359b8a7ac..b32f5edcf 100644 --- a/core/state/candidates/model.go +++ b/core/state/candidates/model.go @@ -134,8 +134,8 @@ func (candidate *Candidate) getFilteredUpdates() []*stake { return updates } -// FilterUpdates filters candidate updates: remove 0-valued updates and merge similar ones -func (candidate *Candidate) FilterUpdates() { +// filterUpdates filters candidate updates: remove 0-valued updates and merge similar ones +func (candidate *Candidate) filterUpdates() { if len(candidate.updates) == 0 { return } diff --git a/core/transaction/delegate.go b/core/transaction/delegate.go index 5c8836b5b..d48f186b6 100644 --- a/core/transaction/delegate.go +++ b/core/transaction/delegate.go @@ -46,8 +46,8 @@ func (data DelegateData) BasicCheck(tx *Transaction, context *state.CheckState) sender, _ := tx.Sender() value := big.NewInt(0).Set(data.Value) - if watchList := context.WaitList().Get(sender, data.PubKey, data.Coin); watchList != nil { - value.Add(value, watchList.Value) + if waitList := context.WaitList().Get(sender, data.PubKey, data.Coin); waitList != nil { + value.Add(value, waitList.Value) } if value.Cmp(types.Big0) < 1 { @@ -155,8 +155,8 @@ func (data DelegateData) Run(tx *Transaction, context state.Interface, rewardPoo deliverState.Accounts.SubBalance(sender, data.Coin, data.Value) value := big.NewInt(0).Set(data.Value) - if watchList := deliverState.Waitlist.Get(sender, data.PubKey, data.Coin); watchList != nil { - value.Add(value, watchList.Value) + if waitList := deliverState.Waitlist.Get(sender, data.PubKey, data.Coin); waitList != nil { + value.Add(value, waitList.Value) deliverState.Waitlist.Delete(sender, data.PubKey, data.Coin) } diff --git a/core/transaction/delegate_test.go b/core/transaction/delegate_test.go index 24e76e725..6e06c68bc 100644 --- a/core/transaction/delegate_test.go +++ b/core/transaction/delegate_test.go @@ -98,7 +98,7 @@ func TestDelegateTx(t *testing.T) { checkState(t, cState) } -func TestDelegateTxWithWatchlist(t *testing.T) { +func TestDelegateTxWithWaitlist(t *testing.T) { cState := getState() pubkey := createTestCandidate(cState) privateKey, _ := crypto.GenerateKey() diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 6fced0c3f..6b40f7652 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -137,8 +137,8 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool deliverState.Accounts.SubBalance(sender, tx.GasCoin, commission) - if watchList := deliverState.Waitlist.Get(sender, data.PubKey, data.Coin); watchList != nil { - diffValue := big.NewInt(0).Sub(data.Value, watchList.Value) + if waitList := deliverState.Waitlist.Get(sender, data.PubKey, data.Coin); waitList != nil { + diffValue := big.NewInt(0).Sub(data.Value, waitList.Value) deliverState.Waitlist.Delete(sender, data.PubKey, data.Coin) if diffValue.Sign() == -1 { deliverState.Waitlist.AddWaitList(sender, data.PubKey, data.Coin, big.NewInt(0).Neg(diffValue)) diff --git a/core/transaction/unbond_test.go b/core/transaction/unbond_test.go index da821436d..557d0d68e 100644 --- a/core/transaction/unbond_test.go +++ b/core/transaction/unbond_test.go @@ -85,7 +85,7 @@ func TestUnbondTx(t *testing.T) { checkState(t, cState) } -func TestFullUnbondTxWithWatchlist(t *testing.T) { +func TestFullUnbondTxWithWaitlist(t *testing.T) { cState := getState() pubkey := createTestCandidate(cState) @@ -157,7 +157,7 @@ func TestFullUnbondTxWithWatchlist(t *testing.T) { checkState(t, cState) } -func TestUnbondTxWithWatchlist(t *testing.T) { +func TestUnbondTxWithWaitlist(t *testing.T) { cState := getState() pubkey := createTestCandidate(cState) From 25ff66fb47b40e97cfe4bcd3ec2e5cd41555822c Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Fri, 16 Oct 2020 10:47:44 +0300 Subject: [PATCH 418/426] reject tx with already existen halt --- core/code/code.go | 10 +++-- core/state/halts/halts.go | 16 +++++++ core/state/state_test.go | 13 +++--- core/transaction/set_halt_block.go | 10 ++++- core/transaction/set_halt_block_test.go | 57 +++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 12 deletions(-) diff --git a/core/code/code.go b/core/code/code.go index 6cf8f0a09..b1f8fceae 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -23,6 +23,7 @@ const ( WrongChainID uint32 = 115 CoinReserveUnderflow uint32 = 116 WrongHaltHeight uint32 = 117 + HaltAlreadyExists uint32 = 118 // coin creation CoinAlreadyExists uint32 = 201 @@ -536,12 +537,13 @@ func NewStakeShouldBePositive(stake string) *stakeShouldBePositive { } type wrongHaltHeight struct { - Code string `json:"code,omitempty"` - Height string `json:"height,omitempty"` + Code string `json:"code,omitempty"` + PublicKey string `json:"public_key,omitempty"` + Height string `json:"height,omitempty"` } -func NewWrongHaltHeight(height string) *wrongHaltHeight { - return &wrongHaltHeight{Code: strconv.Itoa(int(WrongHaltHeight)), Height: height} +func NewWrongHaltHeight(height string, pubkey string) *wrongHaltHeight { + return &wrongHaltHeight{Code: strconv.Itoa(int(WrongHaltHeight)), Height: height, PublicKey: pubkey} } type tooLowStake struct { diff --git a/core/state/halts/halts.go b/core/state/halts/halts.go index 4439ec062..8f5bda9d9 100644 --- a/core/state/halts/halts.go +++ b/core/state/halts/halts.go @@ -16,6 +16,7 @@ const mainPrefix = byte('h') type RHalts interface { Export(state *types.AppState) GetHaltBlocks(height uint64) *Model + IsHaltExists(height uint64, pubkey types.Pubkey) bool } type HaltBlocks struct { @@ -128,6 +129,21 @@ func (hb *HaltBlocks) getOrderedDirty() []uint64 { return keys } +func (hb *HaltBlocks) IsHaltExists(height uint64, pubkey types.Pubkey) bool { + model := hb.get(height) + if model == nil { + return false + } + + for _, halt := range model.List { + if halt.Pubkey == pubkey { + return true + } + } + + return false +} + func (hb *HaltBlocks) AddHaltBlock(height uint64, pubkey types.Pubkey) { hb.GetOrNew(height).addHaltBlock(pubkey) } diff --git a/core/state/state_test.go b/core/state/state_test.go index 47b88f19b..cab77fd30 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -30,7 +30,7 @@ func TestStateExport(t *testing.T) { coinTestID, coinTest, "TEST", - helpers.BipToPip(big.NewInt(601)), + helpers.BipToPip(big.NewInt(602)), 10, helpers.BipToPip(big.NewInt(100)), helpers.BipToPip(big.NewInt(100)), @@ -41,7 +41,7 @@ func TestStateExport(t *testing.T) { coinTest2ID, coinTest2, "TEST2", - helpers.BipToPip(big.NewInt(1002)), + helpers.BipToPip(big.NewInt(1004)), 50, helpers.BipToPip(big.NewInt(200)), helpers.BipToPip(big.NewInt(200)), @@ -106,7 +106,6 @@ func TestStateExport(t *testing.T) { } newState := state.Export(height) - if err := newState.Verify(); err != nil { t.Error(err) } @@ -127,12 +126,12 @@ func TestStateExport(t *testing.T) { t.Fatalf("Wrong new state coins size. Expected %d, got %d", 2, len(newState.Coins)) } - newStateCoin := newState.Coins[0] - newStateCoin1 := newState.Coins[1] + newStateCoin := newState.Coins[1] + newStateCoin1 := newState.Coins[0] if newStateCoin.Name != "TEST" || newStateCoin.Symbol != coinTest || - newStateCoin.Volume != helpers.BipToPip(big.NewInt(601)).String() || + newStateCoin.Volume != helpers.BipToPip(big.NewInt(602)).String() || newStateCoin.Reserve != helpers.BipToPip(big.NewInt(100)).String() || newStateCoin.MaxSupply != helpers.BipToPip(big.NewInt(100)).String() || newStateCoin.Crr != 10 { @@ -141,7 +140,7 @@ func TestStateExport(t *testing.T) { if newStateCoin1.Name != "TEST2" || newStateCoin1.Symbol != coinTest2 || - newStateCoin1.Volume != helpers.BipToPip(big.NewInt(1002)).String() || + newStateCoin1.Volume != helpers.BipToPip(big.NewInt(1004)).String() || newStateCoin1.Reserve != helpers.BipToPip(big.NewInt(200)).String() || newStateCoin1.MaxSupply != helpers.BipToPip(big.NewInt(200)).String() || newStateCoin1.Crr != 50 { diff --git a/core/transaction/set_halt_block.go b/core/transaction/set_halt_block.go index 18469f61a..288a1da1b 100644 --- a/core/transaction/set_halt_block.go +++ b/core/transaction/set_halt_block.go @@ -33,6 +33,14 @@ func (data SetHaltBlockData) BasicCheck(tx *Transaction, context *state.CheckSta } } + if context.Halts().IsHaltExists(data.Height, data.PubKey) { + return &Response{ + Code: code.HaltAlreadyExists, + Log: "Halt with such public key and height already exists", + Info: EncodeError(code.NewWrongHaltHeight(strconv.FormatUint(data.Height, 10), data.GetPubKey().String())), + } + } + return checkCandidateOwnership(data, tx, context) } @@ -63,7 +71,7 @@ func (data SetHaltBlockData) Run(tx *Transaction, context state.Interface, rewar return Response{ Code: code.WrongHaltHeight, Log: fmt.Sprintf("Halt height should be equal or bigger than current: %d", currentBlock), - Info: EncodeError(code.NewWrongHaltHeight(strconv.FormatUint(data.Height, 10))), + Info: EncodeError(code.NewWrongHaltHeight(strconv.FormatUint(data.Height, 10), data.GetPubKey().String())), } } diff --git a/core/transaction/set_halt_block_test.go b/core/transaction/set_halt_block_test.go index 87ac4575d..a4bec088e 100644 --- a/core/transaction/set_halt_block_test.go +++ b/core/transaction/set_halt_block_test.go @@ -387,3 +387,60 @@ func TestSetHaltBlockTxToGasCoinReserveUnderflow(t *testing.T) { checkState(t, cState) } + +func TestSetHaltBlockTxToAlreadyExistenHalt(t *testing.T) { + cState, err := state.NewState(500000, db.NewMemDB(), nil, 1, 1) + if err != nil { + t.Fatalf("Cannot load state. Error %s", err) + } + + haltHeight := 500000 + uint64(100) + privateKey, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(privateKey.PublicKey) + coin := types.GetBaseCoinID() + + pubkey := [32]byte{} + rand.Read(pubkey[:]) + + cState.Candidates.Create(addr, addr, addr, pubkey, 10) + cState.Validators.Create(pubkey, helpers.BipToPip(big.NewInt(1))) + cState.Accounts.AddBalance(addr, coin, helpers.BipToPip(big.NewInt(1))) + cState.Halts.AddHaltBlock(haltHeight, pubkey) + + data := SetHaltBlockData{ + PubKey: pubkey, + Height: haltHeight, + } + + encodedData, err := rlp.EncodeToBytes(data) + + if err != nil { + t.Fatal(err) + } + + tx := Transaction{ + Nonce: 1, + GasPrice: 1, + ChainID: types.CurrentChainID, + GasCoin: coin, + Type: TypeSetHaltBlock, + Data: encodedData, + SignatureType: SigTypeSingle, + } + + if err := tx.Sign(privateKey); err != nil { + t.Fatal(err) + } + + encodedTx, err := rlp.EncodeToBytes(tx) + if err != nil { + t.Fatal(err) + } + + response := RunTx(cState, encodedTx, big.NewInt(0), 500000, &sync.Map{}, 0) + if response.Code != code.HaltAlreadyExists { + t.Fatalf("response code is not %d. Error %s", code.HaltAlreadyExists, response.Log) + } + + checkState(t, cState) +} From 55c5d2c143577143b539b1bd71429d257aba9362 Mon Sep 17 00:00:00 2001 From: Kamil Mukhametzyanov Date: Fri, 16 Oct 2020 10:55:08 +0300 Subject: [PATCH 419/426] fix --- core/minter/minter.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index 74cc02a1f..657a84ce8 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -634,8 +634,6 @@ func (app *Blockchain) isApplicationHalted(height uint64) bool { return true } - return false // todo: remove - halts := app.stateDeliver.Halts.GetHaltBlocks(height) if halts != nil { // calculate total power of validators From 3aa417b8f867f2adb5f57ebe4b016172922de011 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 16 Oct 2020 15:12:02 +0300 Subject: [PATCH 420/426] fix tests --- core/events/store_test.go | 8 ++++---- core/minter/minter_test.go | 32 ++++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/core/events/store_test.go b/core/events/store_test.go index 867676116..3b11f8045 100644 --- a/core/events/store_test.go +++ b/core/events/store_test.go @@ -103,7 +103,7 @@ func TestIEventsDB(t *testing.T) { if loadEvents[1].(*StakeKickEvent).ValidatorPubKey.String() != "Mp738da41ba6a7b7d69b7294afa158b89c5a1b410cbf0c2443c85c5fe24ad1dd1c" { t.Fatal("invalid PubKey") } - if loadEvents[1].(*StakeKickEvent).Coin.Uint32() != 1 { + if loadEvents[1].(*StakeKickEvent).Coin != 1 { t.Fatal("invalid Coin") } @@ -125,7 +125,7 @@ func TestIEventsDB(t *testing.T) { if loadEvents[0].(*UnbondEvent).ValidatorPubKey.String() != "Mp738da41ba6a7b7d69b7294afa158b89c5a1b410cbf0c2443c85c5fe24ad1dd11" { t.Fatal("invalid PubKey") } - if loadEvents[0].(*UnbondEvent).Coin.Uint32() != 1 { + if loadEvents[0].(*UnbondEvent).Coin != 1 { t.Fatal("invalid Coin") } @@ -141,7 +141,7 @@ func TestIEventsDB(t *testing.T) { if loadEvents[1].(*UnbondEvent).ValidatorPubKey.String() != "Mp738da41ba6a7b7d69b7294afa158b89c5a1b410cbf0c2443c85c5fe24ad1dd12" { t.Fatal("invalid PubKey") } - if loadEvents[1].(*UnbondEvent).Coin.Uint32() != 2 { + if loadEvents[1].(*UnbondEvent).Coin != 2 { t.Fatal("invalid Coin") } @@ -163,7 +163,7 @@ func TestIEventsDB(t *testing.T) { if loadEvents[0].(*SlashEvent).ValidatorPubKey.String() != "Mp738da41ba6a7b7d69b7294afa158b89c5a1b410cbf0c2443c85c5fe24ad1dd10" { t.Fatal("invalid PubKey") } - if loadEvents[0].(*SlashEvent).Coin.Uint32() != 10 { + if loadEvents[0].(*SlashEvent).Coin != 10 { t.Fatal("invalid Coin") } } diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index 279672a38..a60a9957f 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -245,12 +245,24 @@ func TestBlockchain_SetStatisticData(t *testing.T) { blockchain, tmCli, _ := initTestNode(t) defer blockchain.Stop() - ctx, _ := context.WithTimeout(context.Background(), time.Second*3) - blockchain.SetStatisticData(statistics.New()).Statistic(ctx) + ch := make(chan struct{}) + blockchain.stateDeliver.Lock() + go func() { + close(ch) + blockchain.SetStatisticData(statistics.New()).Statistic(context.Background()) + }() + <-ch + time.Sleep(time.Second) + blockchain.stateDeliver.Unlock() + blocks, err := tmCli.Subscribe(context.Background(), "test-client", "tm.event = 'NewBlock'") if err != nil { t.Fatal(err) } + + <-blocks + <-blocks + <-blocks block := <-blocks if block.Data.(types2.EventDataNewBlock).Block.Header.Time.Nanosecond() != blockchain.StatisticData().BlockEnd.LastBlockInfo.HeaderTimestamp.Nanosecond() { t.Fatal("statistic last block and event event last block header time not equal") @@ -258,6 +270,7 @@ func TestBlockchain_SetStatisticData(t *testing.T) { blockchain.lock.RLock() defer blockchain.lock.RUnlock() + exportedState := blockchain.CurrentState().Export(blockchain.Height() - 1) if err := exportedState.Verify(); err != nil { t.Fatal(err) @@ -474,15 +487,14 @@ func TestBlockchain_SendTx(t *testing.T) { func TestBlockchain_FrozenFunds(t *testing.T) { blockchain, tmCli, pv := initTestNode(t) - defer blockchain.Stop() targetHeight := uint64(10) - value := big.NewInt(1000) + value := helpers.BipToPip(big.NewInt(1000)) pubkey := types.BytesToPubkey(pv.Key.PubKey.Bytes()[5:]) - blockchain.stateDeliver.Lock() - blockchain.stateDeliver.Candidates.SubStake(developers.Address, pubkey, 0, value) - blockchain.stateDeliver.FrozenFunds.AddFund(targetHeight, developers.Address, pubkey, 0, value) - blockchain.stateDeliver.Unlock() + blockchain.stateDeliver.RLock() + blockchain.stateDeliver.Candidates.SubStake(developers.Address, pubkey, 0, big.NewInt(0).Set(value)) + blockchain.stateDeliver.FrozenFunds.AddFund(targetHeight, developers.Address, pubkey, 0, big.NewInt(0).Set(value)) + blockchain.stateDeliver.RUnlock() blocks, err := tmCli.Subscribe(context.Background(), "test-client", "tm.event = 'NewBlock'") if err != nil { @@ -497,8 +509,7 @@ func TestBlockchain_FrozenFunds(t *testing.T) { } blockchain.lock.RLock() - defer blockchain.lock.RLock() - + defer blockchain.lock.RUnlock() exportedState := blockchain.CurrentState().Export(blockchain.Height() - 1) if err := exportedState.Verify(); err != nil { t.Fatal(err) @@ -757,6 +768,7 @@ func TestBlockchain_RecalculateStakes_andRemoveValidator(t *testing.T) { blockchain.lock.RLock() defer blockchain.lock.RUnlock() + exportedState := blockchain.CurrentState().Export(blockchain.Height() - 1) if err := exportedState.Verify(); err != nil { t.Fatal(err) From 4a8619dec87bdc98bd9c7a82d97866c42e3ca9fc Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 16 Oct 2020 16:11:47 +0300 Subject: [PATCH 421/426] fix coin in v2/events --- api/v2/service/events.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/api/v2/service/events.go b/api/v2/service/events.go index 019c56292..022a7feb3 100644 --- a/api/v2/service/events.go +++ b/api/v2/service/events.go @@ -35,7 +35,12 @@ func (s *Service) Events(ctx context.Context, req *pb.EventsRequest) (*pb.Events continue } - data, err := toStruct(event) + marshalJSON, err := s.cdc.MarshalJSON(event) + if err != nil { + return nil, status.Errorf(codes.Internal, err.Error()) + } + + data, err := encodeToStruct(marshalJSON) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } From 6e8e1d6ea06e563e1130cc139829d2c20d183140 Mon Sep 17 00:00:00 2001 From: klim0v Date: Fri, 16 Oct 2020 17:06:10 +0300 Subject: [PATCH 422/426] fix events --- api/v2/service/events.go | 5 +++-- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/api/v2/service/events.go b/api/v2/service/events.go index 022a7feb3..6eb42c553 100644 --- a/api/v2/service/events.go +++ b/api/v2/service/events.go @@ -3,6 +3,7 @@ package service import ( "context" pb "github.com/MinterTeam/node-grpc-gateway/api_pb" + _struct "github.com/golang/protobuf/ptypes/struct" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -16,7 +17,7 @@ func (s *Service) Events(ctx context.Context, req *pb.EventsRequest) (*pb.Events height := uint32(req.Height) events := s.blockchain.GetEventsDB().LoadEvents(height) - resultEvents := make([]*pb.EventsResponse_Event, 0, len(events)) + resultEvents := make([]*_struct.Struct, 0, len(events)) for _, event := range events { if timeoutStatus := s.checkTimeout(ctx); timeoutStatus != nil { @@ -45,7 +46,7 @@ func (s *Service) Events(ctx context.Context, req *pb.EventsRequest) (*pb.Events return nil, status.Error(codes.Internal, err.Error()) } - resultEvents = append(resultEvents, &pb.EventsResponse_Event{Type: event.Type(), Value: data}) + resultEvents = append(resultEvents, data) } return &pb.EventsResponse{ Events: resultEvents, diff --git a/go.mod b/go.mod index cf6e74913..5ef4de407 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201013155331-4553afd65e47 + github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201016140502-48720810e1d0 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 5907d60a2..2c772d9c1 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201013155331-4553afd65e47 h1:QF4GtwN2nmudlctx8M1q08NmOYVAM8Pq4Idq283m0vg= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201013155331-4553afd65e47/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201016140502-48720810e1d0 h1:S48WwE3uOGfBMZzyDSgUeZ+zTvUbrxrT57FV4XQH8zo= +github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201016140502-48720810e1d0/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= From ef036f58617fea62927c3445f4b4f1c497094705 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:27:28 +0300 Subject: [PATCH 423/426] Fix byzantine punishment --- core/minter/minter.go | 2 +- core/minter/minter_test.go | 2 +- core/state/bus/frozenfunds.go | 2 +- core/state/candidates/candidate_test.go | 2 +- core/state/candidates/candidates.go | 2 +- core/state/candidates_test.go | 6 +++--- core/state/frozenfunds/bus.go | 4 ++-- core/state/frozenfunds/frozen_funds.go | 16 +++++----------- core/state/frozenfunds/frozen_funds_test.go | 4 ++-- core/state/frozenfunds/model.go | 4 +++- core/state/state.go | 6 +++--- core/state/state_test.go | 8 ++++---- core/transaction/unbond.go | 2 +- core/types/appstate.go | 1 + legacy/candidates/candidates.go | 6 +++++- legacy/frozenfunds/frozen_funds.go | 3 ++- 16 files changed, 36 insertions(+), 34 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index aa5bea05b..a595188c7 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -188,7 +188,7 @@ func (app *Blockchain) BeginBlock(req abciTypes.RequestBeginBlock) abciTypes.Res continue } - app.stateDeliver.FrozenFunds.PunishFrozenFundsWithAddress(height, height+candidates.UnbondPeriod, address) + app.stateDeliver.FrozenFunds.PunishFrozenFundsWithID(height, height+candidates.UnbondPeriod, candidate.ID) app.stateDeliver.Validators.PunishByzantineValidator(address) app.stateDeliver.Candidates.PunishByzantineCandidate(height, address) } diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index a60a9957f..e2dbf2355 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -493,7 +493,7 @@ func TestBlockchain_FrozenFunds(t *testing.T) { pubkey := types.BytesToPubkey(pv.Key.PubKey.Bytes()[5:]) blockchain.stateDeliver.RLock() blockchain.stateDeliver.Candidates.SubStake(developers.Address, pubkey, 0, big.NewInt(0).Set(value)) - blockchain.stateDeliver.FrozenFunds.AddFund(targetHeight, developers.Address, pubkey, 0, big.NewInt(0).Set(value)) + blockchain.stateDeliver.FrozenFunds.AddFund(targetHeight, developers.Address, pubkey, blockchain.stateDeliver.Candidates.ID(pubkey), 0, big.NewInt(0).Set(value)) blockchain.stateDeliver.RUnlock() blocks, err := tmCli.Subscribe(context.Background(), "test-client", "tm.event = 'NewBlock'") diff --git a/core/state/bus/frozenfunds.go b/core/state/bus/frozenfunds.go index ec3a1d1fa..250730505 100644 --- a/core/state/bus/frozenfunds.go +++ b/core/state/bus/frozenfunds.go @@ -6,5 +6,5 @@ import ( ) type FrozenFunds interface { - AddFrozenFund(uint64, types.Address, types.Pubkey, types.CoinID, *big.Int) + AddFrozenFund(uint64, types.Address, types.Pubkey, uint32, types.CoinID, *big.Int) } diff --git a/core/state/candidates/candidate_test.go b/core/state/candidates/candidate_test.go index ca233f309..6179cf063 100644 --- a/core/state/candidates/candidate_test.go +++ b/core/state/candidates/candidate_test.go @@ -739,7 +739,7 @@ type fr struct { unbounds []*big.Int } -func (fr *fr) AddFrozenFund(_ uint64, _ types.Address, _ types.Pubkey, _ types.CoinID, value *big.Int) { +func (fr *fr) AddFrozenFund(_ uint64, _ types.Address, _ types.Pubkey, _ uint32, _ types.CoinID, value *big.Int) { fr.unbounds = append(fr.unbounds, value) } func TestCandidates_PunishByzantineCandidate(t *testing.T) { diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index d403535f1..65703fba9 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -300,7 +300,7 @@ func (c *Candidates) PunishByzantineCandidate(height uint64, tmAddress types.TmA ValidatorPubKey: candidate.PubKey, }) - c.bus.FrozenFunds().AddFrozenFund(height+UnbondPeriod, stake.Owner, candidate.PubKey, stake.Coin, newValue) + c.bus.FrozenFunds().AddFrozenFund(height+UnbondPeriod, stake.Owner, candidate.PubKey, candidate.ID, stake.Coin, newValue) stake.setValue(big.NewInt(0)) } } diff --git a/core/state/candidates_test.go b/core/state/candidates_test.go index b3d572d0f..bd6770686 100644 --- a/core/state/candidates_test.go +++ b/core/state/candidates_test.go @@ -290,7 +290,7 @@ func TestDoubleSignPenalty(t *testing.T) { st.Candidates.RecalculateStakes(height) - st.FrozenFunds.AddFund(1, addr, pubkey, coin, amount) + st.FrozenFunds.AddFund(1, addr, pubkey, st.Candidates.ID(pubkey), coin, amount) var pk ed25519.PubKeyEd25519 copy(pk[:], pubkey[:]) @@ -299,7 +299,7 @@ func TestDoubleSignPenalty(t *testing.T) { copy(tmAddr[:], pk.Address().Bytes()) st.Validators.PunishByzantineValidator(tmAddr) - st.FrozenFunds.PunishFrozenFundsWithAddress(1, 1+candidates.UnbondPeriod, tmAddr) + st.FrozenFunds.PunishFrozenFundsWithID(1, 1+candidates.UnbondPeriod, st.Candidates.ID(pubkey)) st.Candidates.PunishByzantineCandidate(1, tmAddr) stake := st.Candidates.GetStakeValueOfAddress(pubkey, addr, coin) @@ -425,7 +425,7 @@ func TestZeroStakePenalty(t *testing.T) { st.Candidates.RecalculateStakes(height) st.Candidates.SubStake(addr, pubkey, coin, amount) - st.FrozenFunds.AddFund(518400, addr, pubkey, coin, amount) + st.FrozenFunds.AddFund(518400, addr, pubkey, st.Candidates.ID(pubkey), coin, amount) var pk ed25519.PubKeyEd25519 copy(pk[:], pubkey[:]) diff --git a/core/state/frozenfunds/bus.go b/core/state/frozenfunds/bus.go index aabe77314..e7bffbd05 100644 --- a/core/state/frozenfunds/bus.go +++ b/core/state/frozenfunds/bus.go @@ -9,8 +9,8 @@ type Bus struct { frozenfunds *FrozenFunds } -func (b *Bus) AddFrozenFund(height uint64, address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { - b.frozenfunds.AddFund(height, address, pubkey, coin, value) +func (b *Bus) AddFrozenFund(height uint64, address types.Address, pubkey types.Pubkey, candidateID uint32, coin types.CoinID, value *big.Int) { + b.frozenfunds.AddFund(height, address, pubkey, candidateID, coin, value) } func NewBus(frozenfunds *FrozenFunds) *Bus { diff --git a/core/state/frozenfunds/frozen_funds.go b/core/state/frozenfunds/frozen_funds.go index dccf58b2b..362dc0ed4 100644 --- a/core/state/frozenfunds/frozen_funds.go +++ b/core/state/frozenfunds/frozen_funds.go @@ -10,7 +10,6 @@ import ( "github.com/MinterTeam/minter-go-node/formula" "github.com/MinterTeam/minter-go-node/rlp" "github.com/MinterTeam/minter-go-node/tree" - "github.com/tendermint/tendermint/crypto/ed25519" "math/big" "sort" "sync" @@ -75,7 +74,7 @@ func (f *FrozenFunds) GetFrozenFunds(height uint64) *Model { return f.get(height) } -func (f *FrozenFunds) PunishFrozenFundsWithAddress(fromHeight uint64, toHeight uint64, tmAddress types.TmAddress) { +func (f *FrozenFunds) PunishFrozenFundsWithID(fromHeight uint64, toHeight uint64, candidateID uint32) { for cBlock := fromHeight; cBlock <= toHeight; cBlock++ { ff := f.get(cBlock) if ff == nil { @@ -84,13 +83,7 @@ func (f *FrozenFunds) PunishFrozenFundsWithAddress(fromHeight uint64, toHeight u newList := make([]Item, len(ff.List)) for i, item := range ff.List { - var pubkey ed25519.PubKeyEd25519 - copy(pubkey[:], item.CandidateKey[:]) - - var address [20]byte - copy(address[:], pubkey.Address().Bytes()) - - if tmAddress == address { + if item.CandidateID == candidateID { newValue := big.NewInt(0).Set(item.Value) newValue.Mul(newValue, big.NewInt(95)) newValue.Div(newValue, big.NewInt(100)) @@ -182,8 +175,8 @@ func (f *FrozenFunds) getOrderedDirty() []uint64 { return keys } -func (f *FrozenFunds) AddFund(height uint64, address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { - f.GetOrNew(height).addFund(address, pubkey, coin, value) +func (f *FrozenFunds) AddFund(height uint64, address types.Address, pubkey types.Pubkey, candidateId uint32, coin types.CoinID, value *big.Int) { + f.GetOrNew(height).addFund(address, pubkey, candidateId, coin, value) f.bus.Checker().AddCoin(coin, value) } @@ -212,6 +205,7 @@ func (f *FrozenFunds) Export(state *types.AppState, height uint64) { Height: i, Address: frozenFund.Address, CandidateKey: frozenFund.CandidateKey, + CandidateID: frozenFund.CandidateID, Coin: uint64(frozenFund.Coin), Value: frozenFund.Value.String(), }) diff --git a/core/state/frozenfunds/frozen_funds_test.go b/core/state/frozenfunds/frozen_funds_test.go index 974bf7702..803f92481 100644 --- a/core/state/frozenfunds/frozen_funds_test.go +++ b/core/state/frozenfunds/frozen_funds_test.go @@ -30,7 +30,7 @@ func TestFrozenFundsToAddModel(t *testing.T) { height, addr, pubkey, coin, val := uint64(1), types.Address{0}, types.Pubkey{0}, types.GetBaseCoinID(), big.NewInt(1e18) - ff.AddFund(height, addr, pubkey, coin, val) + ff.AddFund(height, addr, pubkey, 1, coin, val) if err := ff.Commit(); err != nil { t.Fatal(err) } @@ -77,7 +77,7 @@ func TestFrozenFundsToDeleteModel(t *testing.T) { height, addr, pubkey, coin, val := uint64(1), types.Address{0}, types.Pubkey{0}, types.GetBaseCoinID(), big.NewInt(1e18) - ff.AddFund(height, addr, pubkey, coin, val) + ff.AddFund(height, addr, pubkey, 1, coin, val) if err := ff.Commit(); err != nil { t.Fatal(err) } diff --git a/core/state/frozenfunds/model.go b/core/state/frozenfunds/model.go index a4e4a459e..bb9dd5281 100644 --- a/core/state/frozenfunds/model.go +++ b/core/state/frozenfunds/model.go @@ -8,6 +8,7 @@ import ( type Item struct { Address types.Address CandidateKey *types.Pubkey + CandidateID uint32 Coin types.CoinID Value *big.Int } @@ -25,10 +26,11 @@ func (m *Model) delete() { m.markDirty(m.height) } -func (m *Model) addFund(address types.Address, pubkey types.Pubkey, coin types.CoinID, value *big.Int) { +func (m *Model) addFund(address types.Address, pubkey types.Pubkey, candidateID uint32, coin types.CoinID, value *big.Int) { m.List = append(m.List, Item{ Address: address, CandidateKey: &pubkey, + CandidateID: candidateID, Coin: coin, Value: value, }) diff --git a/core/state/state.go b/core/state/state.go index cbf53cb60..ef21f9e86 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -137,8 +137,8 @@ func (cs *CheckState) Export11To12(height uint64) types.AppState { appState.Export(state, height) coinsMap := coinsState.Export(state) validatorsState.Export(state) - candidatesState.Export(state, coinsMap) - frozenFundsState.Export(state, height, coinsMap) + candidatesMap := candidatesState.Export(state, coinsMap) + frozenFundsState.Export(state, height, coinsMap, candidatesMap) accountsState.Export(state, coinsMap) checksState.Export(state) coinsState.Export(state) @@ -360,7 +360,7 @@ func (s *State) Import(state types.AppState) error { } for _, ff := range state.FrozenFunds { - s.FrozenFunds.AddFund(ff.Height, ff.Address, *ff.CandidateKey, types.CoinID(ff.Coin), helpers.StringToBigInt(ff.Value)) + s.FrozenFunds.AddFund(ff.Height, ff.Address, *ff.CandidateKey, ff.CandidateID, types.CoinID(ff.Coin), helpers.StringToBigInt(ff.Value)) } return nil diff --git a/core/state/state_test.go b/core/state/state_test.go index cab77fd30..f1c26d535 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -69,10 +69,10 @@ func TestStateExport(t *testing.T) { state.Candidates.Create(address1, address1, address1, candidatePubKey1, 10) state.Candidates.Create(address2, address2, address2, candidatePubKey2, 30) state.Validators.Create(candidatePubKey1, helpers.BipToPip(big.NewInt(1))) - state.FrozenFunds.AddFund(height, address1, candidatePubKey1, coinTestID, helpers.BipToPip(big.NewInt(100))) - state.FrozenFunds.AddFund(height+10, address1, candidatePubKey1, types.GetBaseCoinID(), helpers.BipToPip(big.NewInt(3))) - state.FrozenFunds.AddFund(height+100, address2, candidatePubKey1, coinTestID, helpers.BipToPip(big.NewInt(500))) - state.FrozenFunds.AddFund(height+150, address2, candidatePubKey1, coinTest2ID, helpers.BipToPip(big.NewInt(1000))) + state.FrozenFunds.AddFund(height, address1, candidatePubKey1, state.Candidates.ID(candidatePubKey1), coinTestID, helpers.BipToPip(big.NewInt(100))) + state.FrozenFunds.AddFund(height+10, address1, candidatePubKey1, state.Candidates.ID(candidatePubKey1), types.GetBaseCoinID(), helpers.BipToPip(big.NewInt(3))) + state.FrozenFunds.AddFund(height+100, address2, candidatePubKey1, state.Candidates.ID(candidatePubKey1), coinTestID, helpers.BipToPip(big.NewInt(500))) + state.FrozenFunds.AddFund(height+150, address2, candidatePubKey1, state.Candidates.ID(candidatePubKey1), coinTest2ID, helpers.BipToPip(big.NewInt(1000))) newCheck := &check.Check{ Nonce: []byte("test nonce"), diff --git a/core/transaction/unbond.go b/core/transaction/unbond.go index 6b40f7652..5cfd062cd 100644 --- a/core/transaction/unbond.go +++ b/core/transaction/unbond.go @@ -147,7 +147,7 @@ func (data UnbondData) Run(tx *Transaction, context state.Interface, rewardPool deliverState.Candidates.SubStake(sender, data.PubKey, data.Coin, data.Value) } - deliverState.FrozenFunds.AddFund(unbondAtBlock, sender, data.PubKey, data.Coin, data.Value) + deliverState.FrozenFunds.AddFund(unbondAtBlock, sender, data.PubKey, deliverState.Candidates.ID(data.PubKey), data.Coin, data.Value) deliverState.Accounts.SetNonce(sender, tx.Nonce) } diff --git a/core/types/appstate.go b/core/types/appstate.go index 1dfe452bf..2600cfc76 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -294,6 +294,7 @@ type FrozenFund struct { Height uint64 `json:"height"` Address Address `json:"address"` CandidateKey *Pubkey `json:"candidate_key,omitempty"` + CandidateID uint32 `json:"candidate_id"` Coin uint64 `json:"coin"` Value string `json:"value"` } diff --git a/legacy/candidates/candidates.go b/legacy/candidates/candidates.go index edfe8d3d9..5d9d05e8c 100644 --- a/legacy/candidates/candidates.go +++ b/legacy/candidates/candidates.go @@ -231,10 +231,12 @@ func (c *Candidates) LoadStakes() { } } -func (c *Candidates) Export(state *types.AppState, coinsMap map[types.CoinSymbol]types.Coin) { +func (c *Candidates) Export(state *types.AppState, coinsMap map[types.CoinSymbol]types.Coin) map[types.Pubkey]uint32 { c.LoadCandidates() c.LoadStakes() + candidatesMap := make(map[types.Pubkey]uint32) + candidates, maxID := c.GetCandidates(), uint32(1) for _, candidate := range candidates { candidateStakes := c.GetStakes(candidate.PubKey) @@ -270,10 +272,12 @@ func (c *Candidates) Export(state *types.AppState, coinsMap map[types.CoinSymbol Updates: updates, Stakes: stakes, }) + candidatesMap[candidate.PubKey] = maxID maxID++ } + return candidatesMap } func (c *Candidates) getOrderedCandidates() []types.Pubkey { diff --git a/legacy/frozenfunds/frozen_funds.go b/legacy/frozenfunds/frozen_funds.go index c13cbe289..f4a6610e6 100644 --- a/legacy/frozenfunds/frozen_funds.go +++ b/legacy/frozenfunds/frozen_funds.go @@ -73,7 +73,7 @@ func (f *FrozenFunds) getOrderedDirty() []uint64 { return keys } -func (f *FrozenFunds) Export(state *types.AppState, height uint64, coinsMap map[types.CoinSymbol]types.Coin) { +func (f *FrozenFunds) Export(state *types.AppState, height uint64, coinsMap map[types.CoinSymbol]types.Coin, candidatesMap map[types.Pubkey]uint32) { for i := height; i <= height+candidates.UnbondPeriod; i++ { frozenFunds := f.get(i) if frozenFunds == nil { @@ -85,6 +85,7 @@ func (f *FrozenFunds) Export(state *types.AppState, height uint64, coinsMap map[ Height: i - height, Address: frozenFund.Address, CandidateKey: frozenFund.CandidateKey, + CandidateID: candidatesMap[*frozenFund.CandidateKey], Coin: coinsMap[frozenFund.Coin].ID, Value: frozenFund.Value.String(), }) From 8d2344e0dbbb193b20332fdcc72359e167fb8687 Mon Sep 17 00:00:00 2001 From: Daniil Lashin <3121312+danil-lashin@users.noreply.github.com> Date: Sun, 18 Oct 2020 16:30:32 +0300 Subject: [PATCH 424/426] Fix test --- core/minter/minter_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/minter/minter_test.go b/core/minter/minter_test.go index e2dbf2355..f8de2b1a8 100644 --- a/core/minter/minter_test.go +++ b/core/minter/minter_test.go @@ -777,7 +777,7 @@ func TestBlockchain_RecalculateStakes_andRemoveValidator(t *testing.T) { func TestStopNetworkByHaltBlocks(t *testing.T) { blockchain, _, _ := initTestNode(t) - blockchain.Stop() + defer blockchain.Stop() haltHeight := uint64(50) From 1242cb545ac9b49e99520a433f4362624027e325 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 19 Oct 2020 05:04:50 +0300 Subject: [PATCH 425/426] update validators after change PubKey --- core/minter/minter.go | 8 +++++++- core/state/candidates/candidates.go | 13 +++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/core/minter/minter.go b/core/minter/minter.go index a595188c7..6d457e4e3 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -278,9 +278,15 @@ func (app *Blockchain) EndBlock(req abciTypes.RequestEndBlock) abciTypes.Respons app.stateDeliver.Validators.PayRewards(height) } + hasChangedPublicKeys := false + if app.stateDeliver.Candidates.IsChangedPublicKeys() { + app.stateDeliver.Candidates.ResetIsChangedPublicKeys() + hasChangedPublicKeys = true + } + // update validators var updates []abciTypes.ValidatorUpdate - if req.Height%120 == 0 || hasDroppedValidators { + if req.Height%120 == 0 || hasDroppedValidators || hasChangedPublicKeys { updates = app.updateValidators(height) } diff --git a/core/state/candidates/candidates.go b/core/state/candidates/candidates.go index 65703fba9..dd3627e08 100644 --- a/core/state/candidates/candidates.go +++ b/core/state/candidates/candidates.go @@ -73,8 +73,16 @@ type Candidates struct { iavl tree.MTree bus *bus.Bus - lock sync.RWMutex - loaded bool + lock sync.RWMutex + loaded bool + isChangedPublicKeys bool +} + +func (c *Candidates) IsChangedPublicKeys() bool { + return c.isChangedPublicKeys +} +func (c *Candidates) ResetIsChangedPublicKeys() { + c.isChangedPublicKeys = false } // NewCandidates returns newly created Candidates state with a given bus and iavl @@ -1027,6 +1035,7 @@ func (c *Candidates) ChangePubKey(old types.Pubkey, new types.Pubkey) { c.setBlockPubKey(old) c.setPubKeyID(new, c.pubKeyIDs[old]) delete(c.pubKeyIDs, old) + c.isChangedPublicKeys = true } func (c *Candidates) getOrNewID(pubKey types.Pubkey) uint32 { From b21c05ec2b876dadeee2549e9376201e6b852aa1 Mon Sep 17 00:00:00 2001 From: klim0v Date: Mon, 19 Oct 2020 10:30:11 +0300 Subject: [PATCH 426/426] genesis --- core/state/frozenfunds/frozen_funds.go | 2 +- core/state/state.go | 2 +- core/types/appstate.go | 2 +- go.mod | 2 +- go.sum | 4 ++-- legacy/frozenfunds/frozen_funds.go | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/state/frozenfunds/frozen_funds.go b/core/state/frozenfunds/frozen_funds.go index 362dc0ed4..540035bb4 100644 --- a/core/state/frozenfunds/frozen_funds.go +++ b/core/state/frozenfunds/frozen_funds.go @@ -205,7 +205,7 @@ func (f *FrozenFunds) Export(state *types.AppState, height uint64) { Height: i, Address: frozenFund.Address, CandidateKey: frozenFund.CandidateKey, - CandidateID: frozenFund.CandidateID, + CandidateID: uint64(frozenFund.CandidateID), Coin: uint64(frozenFund.Coin), Value: frozenFund.Value.String(), }) diff --git a/core/state/state.go b/core/state/state.go index ef21f9e86..71a366fb7 100644 --- a/core/state/state.go +++ b/core/state/state.go @@ -360,7 +360,7 @@ func (s *State) Import(state types.AppState) error { } for _, ff := range state.FrozenFunds { - s.FrozenFunds.AddFund(ff.Height, ff.Address, *ff.CandidateKey, ff.CandidateID, types.CoinID(ff.Coin), helpers.StringToBigInt(ff.Value)) + s.FrozenFunds.AddFund(ff.Height, ff.Address, *ff.CandidateKey, uint32(ff.CandidateID), types.CoinID(ff.Coin), helpers.StringToBigInt(ff.Value)) } return nil diff --git a/core/types/appstate.go b/core/types/appstate.go index 2600cfc76..2bfcbd518 100644 --- a/core/types/appstate.go +++ b/core/types/appstate.go @@ -294,7 +294,7 @@ type FrozenFund struct { Height uint64 `json:"height"` Address Address `json:"address"` CandidateKey *Pubkey `json:"candidate_key,omitempty"` - CandidateID uint32 `json:"candidate_id"` + CandidateID uint64 `json:"candidate_id"` Coin uint64 `json:"coin"` Value string `json:"value"` } diff --git a/go.mod b/go.mod index 5ef4de407..ce035a0c6 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/MinterTeam/minter-go-node go 1.15 require ( - github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201016140502-48720810e1d0 + github.com/MinterTeam/node-grpc-gateway v1.2.1-0.20201019072706-326f69c6e526 github.com/btcsuite/btcd v0.20.1-beta github.com/c-bata/go-prompt v0.2.3 github.com/go-kit/kit v0.10.0 diff --git a/go.sum b/go.sum index 2c772d9c1..e182965de 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201016140502-48720810e1d0 h1:S48WwE3uOGfBMZzyDSgUeZ+zTvUbrxrT57FV4XQH8zo= -github.com/MinterTeam/node-grpc-gateway v1.1.3-0.20201016140502-48720810e1d0/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= +github.com/MinterTeam/node-grpc-gateway v1.2.1-0.20201019072706-326f69c6e526 h1:GjPRupQehjcPy9WLhrr7+HgnsnaAaQUcWbpkiDSAmLk= +github.com/MinterTeam/node-grpc-gateway v1.2.1-0.20201019072706-326f69c6e526/go.mod h1:49888tivqufwv7KMC0QVZLGJP3wW2cQQazccvOYWCiE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= diff --git a/legacy/frozenfunds/frozen_funds.go b/legacy/frozenfunds/frozen_funds.go index f4a6610e6..d184c789c 100644 --- a/legacy/frozenfunds/frozen_funds.go +++ b/legacy/frozenfunds/frozen_funds.go @@ -85,7 +85,7 @@ func (f *FrozenFunds) Export(state *types.AppState, height uint64, coinsMap map[ Height: i - height, Address: frozenFund.Address, CandidateKey: frozenFund.CandidateKey, - CandidateID: candidatesMap[*frozenFund.CandidateKey], + CandidateID: uint64(candidatesMap[*frozenFund.CandidateKey]), Coin: coinsMap[frozenFund.Coin].ID, Value: frozenFund.Value.String(), })