From 8df1e625485ca1ca6b0d38ebfeecfd6085313b01 Mon Sep 17 00:00:00 2001 From: Eduard Date: Wed, 27 Jun 2018 17:15:20 +0300 Subject: [PATCH 01/19] Typo fix LRP -> RLP encoded --- docs/transactions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/transactions.rst b/docs/transactions.rst index f3bfd96e4..5b437d02b 100755 --- a/docs/transactions.rst +++ b/docs/transactions.rst @@ -4,7 +4,7 @@ Transactions Semantic ^^^^^^^^ -Transactions in Minter are `LRP-encoded `__ structures. +Transactions in Minter are `RLP-encoded `__ structures. Example of a signed transaction: From aaa22a2b54c5f3b28062e6c0e2898395522b4871 Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Fri, 29 Jun 2018 12:08:04 +0300 Subject: [PATCH 02/19] add coins api errors --- api/coin_info.go | 27 +++++++++----- api/estimate_coin_exchange_return.go | 54 +++++++++++++++++++++++----- 2 files changed, 65 insertions(+), 16 deletions(-) diff --git a/api/coin_info.go b/api/coin_info.go index 326dfa5a3..26a0d8e21 100644 --- a/api/coin_info.go +++ b/api/coin_info.go @@ -28,21 +28,32 @@ func GetCoinInfo(w http.ResponseWriter, r *http.Request) { copy(coinSymbol[:], []byte(symbol)) - coin := cState.GetStateCoin(coinSymbol).Data() + coin := cState.GetStateCoin(coinSymbol) w.Header().Set("Content-Type", "application/json; charset=UTF-8") + + if coin == nil { + w.WriteHeader(http.StatusNotFound) + json.NewEncoder(w).Encode(Response{ + Code: 404, + Result: nil, + Log: "Coin not found", + }) + return + } + w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(Response{ Code: 0, Result: CoinInfoResponse{ - Name: coin.Name, - Symbol: coin.Symbol, - Volume: coin.Volume.String(), - Crr: coin.Crr, - ReserveCoin: coin.ReserveCoin, - ReserveBalance: coin.ReserveBalance.String(), - Creator: coin.Creator, + Name: coin.Data().Name, + Symbol: coin.Data().Symbol, + Volume: coin.Data().Volume.String(), + Crr: coin.Data().Crr, + ReserveCoin: coin.Data().ReserveCoin, + ReserveBalance: coin.Data().ReserveBalance.String(), + Creator: coin.Data().Creator, }, }) } diff --git a/api/estimate_coin_exchange_return.go b/api/estimate_coin_exchange_return.go index 5b9e7d192..e3a71faaa 100644 --- a/api/estimate_coin_exchange_return.go +++ b/api/estimate_coin_exchange_return.go @@ -26,17 +26,55 @@ func EstimateCoinExchangeReturn(w http.ResponseWriter, r *http.Request) { var result *big.Int if fromCoinSymbol == blockchain.BaseCoin { - coin := cState.GetStateCoin(toCoinSymbol).Data() - result = formula.CalculatePurchaseReturn(coin.Volume, coin.ReserveBalance, coin.Crr, value) + coin := cState.GetStateCoin(toCoinSymbol) + if coin == nil { + w.WriteHeader(http.StatusNotFound) + json.NewEncoder(w).Encode(Response{ + Code: 404, + Result: nil, + Log: "Coin not found", + }) + return + } + result = formula.CalculatePurchaseReturn(coin.Data().Volume, coin.Data().ReserveBalance, coin.Data().Crr, value) } else if toCoinSymbol == blockchain.BaseCoin { - coin := cState.GetStateCoin(fromCoinSymbol).Data() - result = formula.CalculateSaleReturn(coin.Volume, coin.ReserveBalance, coin.Crr, value) + coin := cState.GetStateCoin(fromCoinSymbol) + if coin == nil { + w.WriteHeader(http.StatusNotFound) + json.NewEncoder(w).Encode(Response{ + Code: 404, + Result: nil, + Log: "Coin not found", + }) + return + } + result = formula.CalculateSaleReturn(coin.Data().Volume, coin.Data().ReserveBalance, coin.Data().Crr, value) } else { - coinFrom := cState.GetStateCoin(fromCoinSymbol).Data() - coinTo := cState.GetStateCoin(toCoinSymbol).Data() + coinFrom := cState.GetStateCoin(fromCoinSymbol) + coinTo := cState.GetStateCoin(toCoinSymbol) - val := formula.CalculateSaleReturn(coinFrom.Volume, coinFrom.ReserveBalance, coinFrom.Crr, value) - result = formula.CalculatePurchaseReturn(coinTo.Volume, coinTo.ReserveBalance, coinTo.Crr, val) + if coinFrom == nil { + w.WriteHeader(http.StatusNotFound) + json.NewEncoder(w).Encode(Response{ + Code: 404, + Result: nil, + Log: "Coin not found", + }) + return + } + + if coinTo == nil { + w.WriteHeader(http.StatusNotFound) + json.NewEncoder(w).Encode(Response{ + Code: 404, + Result: nil, + Log: "Coin not found", + }) + return + } + + val := formula.CalculateSaleReturn(coinFrom.Data().Volume, coinFrom.Data().ReserveBalance, coinFrom.Data().Crr, value) + result = formula.CalculatePurchaseReturn(coinTo.Data().Volume, coinTo.Data().ReserveBalance, coinTo.Data().Crr, val) } w.Header().Set("Content-Type", "application/json; charset=UTF-8") From 33499abe01e345d0c7c71e3761506f3ec4e4fb01 Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Fri, 29 Jun 2018 12:17:05 +0300 Subject: [PATCH 03/19] update version --- CHANGELOG.md | 11 +++++++++++ docker-compose.yml | 2 +- networks/testnet/genesis.json | 2 +- version/version.go | 5 ++--- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab41a4311..fedec9844 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## 0.0.5 +*June 29th, 2018* + +BREAKING CHANGES + +- [testnet] New testnet chain id (minter-test-network-8) + +IMPROVEMENT + +- [api] Fix issue with not found coins + ## 0.0.4 *June 24th, 2018* diff --git a/docker-compose.yml b/docker-compose.yml index 1d141d3d3..303148325 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: "3.4" services: minter: - image: minterteam/minter:0.0.4 + image: minterteam/minter:0.0.5 command: --tendermint_addr=tcp://tendermint:46657 volumes: - ~/.minter:/minter diff --git a/networks/testnet/genesis.json b/networks/testnet/genesis.json index 68e7616fa..c3dc06be8 100644 --- a/networks/testnet/genesis.json +++ b/networks/testnet/genesis.json @@ -1,6 +1,6 @@ { "genesis_time": "2018-06-09T00:00:00Z", - "chain_id": "minter-test-network-7", + "chain_id": "minter-test-network-8", "validators": [ { "pub_key": { diff --git a/version/version.go b/version/version.go index 9fec7ece4..9691804c7 100755 --- a/version/version.go +++ b/version/version.go @@ -4,13 +4,12 @@ package version const ( Maj = "0" Min = "0" - Fix = "4" + Fix = "5" ) var ( - // Version is the current version of Tendermint // Must be a string because scripts like dist.sh read this file. - Version = "0.0.4" + Version = "0.0.5" // GitCommit is the current HEAD set using ldflags. GitCommit string From 342aa3324696529222e03ab0ee2c4f85cd3d6d8b Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Tue, 3 Jul 2018 11:28:11 +0300 Subject: [PATCH 04/19] transactions docs; --- docs/transactions.rst | 70 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/docs/transactions.rst b/docs/transactions.rst index 5b437d02b..4e5455e18 100755 --- a/docs/transactions.rst +++ b/docs/transactions.rst @@ -17,13 +17,13 @@ Example of a signed transaction: Each transaction has: -- **Nonce** - int, used for prevent transaction reply -- **Gas Price** - big int, used for -- **Type** - type of transaction (see below) -- **Data** - data of transaction -- **Payload** (arbitrary bytes) - arbitrary user-defined bytes -- **Service Data** - service data -- **ECDSA fields (R, S and V)** - digital signature of transaction +- **Nonce** - int, used for prevent transaction reply. +- **Gas Price** - big int, used for managing transaction fees. +- **Type** - type of transaction (see below). +- **Data** - data of transaction (depends on transaction type). +- **Payload** (arbitrary bytes) - arbitrary user-defined bytes. +- **Service Data** - reserved field. +- **ECDSA fields (R, S and V)** - digital signature of transaction. .. code-block:: go @@ -69,6 +69,8 @@ Type of transaction is determined by a single byte. Send transaction ^^^^^^^^^^^^^^^^ +Type: **0x01** + Transaction for sending arbitrary coin. *Data field contents:* @@ -81,9 +83,15 @@ Transaction for sending arbitrary coin. Value *big.Int } +| **Coin** - Symbol of a coin. +| **To** - Recipient address in Minter Network. +| **Value** - Amount of **Coin** to send. + Convert transaction ^^^^^^^^^^^^^^^^^^^ +Type: **0x02** + Transaction for converting one coin (owned by sender) to another coin in a system. *Data field contents:* @@ -96,9 +104,15 @@ Transaction for converting one coin (owned by sender) to another coin in a syste Value *big.Int } +| **FromCoinSymbol** - Symbol of a coin to give. +| **ToCoinSymbol** - Symbol of a coin to get. +| **Value** - Amount of **FromCoinSymbol** to convert. + Create coin transaction ^^^^^^^^^^^^^^^^^^^^^^^ +Type: **0x03** + Transaction for creating new coin in a system. *Data field contents:* @@ -113,9 +127,17 @@ Transaction for creating new coin in a system. ConstantReserveRatio uint } +| **Name** - Name of a coin. Arbitrary string. +| **Symbol** - Symbol of a coin. Must be unique, alphabetic, uppercase, 3 to 10 symbols length. +| **InitialAmount** - Amount of coins to issue. Issued coins will be available to sender account. +| **InitialReserve** - Initial reserve in BIP's. +| **ConstantReserveRatio** - CRR, uint, should be from 10 to 100. + Declare candidacy transaction ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Type: **0x04** + Transaction for declaring new validator candidacy. *Data field contents:* @@ -130,9 +152,17 @@ Transaction for declaring new validator candidacy. Stake *big.Int } +| **Address** - Address of candidate in Minter Network. This address would be able to control candidate. Also all rewards will be sent to this address. +| **PubKey** - Public key of a validator. +| **Commission** - Commission (from 0 to 100) from rewards which delegators will pay to validator. +| **Coin** - Symbol of coin to stake. +| **Stake** - Amount of coins to stake. + Delegate transaction ^^^^^^^^^^^^^^^^^^^^ +Type: **0x05** + Transaction for delegating funds to validator. *Data field contents:* @@ -145,9 +175,15 @@ Transaction for delegating funds to validator. Stake *big.Int } +| **PubKey** - Public key of a validator. +| **Coin** - Symbol of coin to stake. +| **Stake** - Amount of coins to stake. + Unbound transaction ^^^^^^^^^^^^^^^^^^^ +Type: **0x06** + Transaction for unbounding funds from validator's stake. *Data field contents:* @@ -160,9 +196,15 @@ Transaction for unbounding funds from validator's stake. Value *big.Int } +| **PubKey** - Public key of a validator. +| **Coin** - Symbol of coin to unbond. +| **Value** - Amount of coins to unbond. + Redeem check transaction ^^^^^^^^^^^^^^^^^^^^^^^^ +Type: **0x07** + Transaction for redeeming a check. *Data field contents:* @@ -174,10 +216,15 @@ Transaction for redeeming a check. Proof [65]byte } +| **RawCheck** - Raw check received from sender. +| **Proof** - Proof of owning a check. + Set candidate online transaction ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Transaction for turning candidate on. +Type: **0x08** + +Transaction for turning candidate on. This transaction should be sent from address which is set in the "Declare candidacy transaction". *Data field contents:* @@ -187,10 +234,14 @@ Transaction for turning candidate on. PubKey []byte } +| **PubKey** - Public key of a validator. + Set candidate offline transaction ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Transaction for turning candidate off. +Type: **0x09** + +Transaction for turning candidate off. This transaction should be sent from address which is set in the "Declare candidacy transaction". *Data field contents:* @@ -200,3 +251,4 @@ Transaction for turning candidate off. PubKey []byte } +| **PubKey** - Public key of a validator. From 569e968bb5e9ae29c9c2f5c5da741a2265f04dff Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Tue, 3 Jul 2018 11:33:13 +0300 Subject: [PATCH 05/19] add coin issuance fees docs --- docs/coins.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/coins.rst b/docs/coins.rst index 2bff75cdc..df45e48c4 100755 --- a/docs/coins.rst +++ b/docs/coins.rst @@ -20,6 +20,19 @@ Issue own coin is as simple as filling a form with given fields: After coin issued you can send is as ordinary coin using standard wallets. +Issuance Fees +^^^^^^^^^^^^^ + +To issue a coin Coiner should pay fee. Fee is depends on length of Coin Symbol. + +| 3 letters – 1 000 000 bips + standard transaction fee +| 4 letters – 100 000 bips + standard transaction fee +| 5 letters – 10 000 bips + standard transaction fee +| 6 letters – 1000 bips + standard transaction fee +| 7 letters – 100 bips + standard transaction fee +| 8 letters – 10 bips + standard transaction fee +| 9-10 letters - just standard transaction fee + Coin Exchange ^^^^^^^^^^^^^ From bfc1614012a5e64cf2bf36b662f8996f98cdb2b8 Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Tue, 3 Jul 2018 11:38:35 +0300 Subject: [PATCH 06/19] coin docs --- docs/coins.rst | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/coins.rst b/docs/coins.rst index df45e48c4..b461e4c2f 100755 --- a/docs/coins.rst +++ b/docs/coins.rst @@ -12,11 +12,14 @@ Coin Issuance Every user of Minter can issue own coin. Each coin is backed by base coin in some proportion. Issue own coin is as simple as filling a form with given fields: -- Coin name -- Coin symbol -- Initial supply -- Initial reserve -- Constant Reserve Ratio (CRR) +.. figure:: assets/coin-minter.png + :width: 300px + +- **Coin name** - Name of a coin. Arbitrary string. +- **Coin symbol** - Symbol of a coin. Must be unique, alphabetic, uppercase, 3 to 10 letters length. +- **Initial supply** - Amount of coins to issue. Issued coins will be available to sender account. +- **Initial reserve** - Initial reserve in base coin. +- **Constant Reserve Ratio (CRR)** - uint, should be from 10 to 100. After coin issued you can send is as ordinary coin using standard wallets. From 2bb70938aeabda33acc6070e13a1d6d3fbd5953a Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Tue, 3 Jul 2018 11:40:24 +0300 Subject: [PATCH 07/19] remove reserve coin from coin state object --- CHANGELOG.md | 1 + api/coin_info.go | 2 -- core/state/state_coin.go | 1 - core/state/statedb.go | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fedec9844..02be82a92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ BREAKING CHANGES +- [core] Remove Reserve Coin from coin object. All coins should be reserved with base coin. - [testnet] New testnet chain id (minter-test-network-8) IMPROVEMENT diff --git a/api/coin_info.go b/api/coin_info.go index 26a0d8e21..f3f5b49a2 100644 --- a/api/coin_info.go +++ b/api/coin_info.go @@ -12,7 +12,6 @@ type CoinInfoResponse struct { Symbol types.CoinSymbol `json:"symbol"` Volume string `json:"volume"` Crr uint `json:"crr"` - ReserveCoin types.CoinSymbol `json:"reserve_coin"` ReserveBalance string `json:"reserve_balance"` Creator types.Address `json:"creator"` } @@ -51,7 +50,6 @@ func GetCoinInfo(w http.ResponseWriter, r *http.Request) { Symbol: coin.Data().Symbol, Volume: coin.Data().Volume.String(), Crr: coin.Data().Crr, - ReserveCoin: coin.Data().ReserveCoin, ReserveBalance: coin.Data().ReserveBalance.String(), Creator: coin.Data().Creator, }, diff --git a/core/state/state_coin.go b/core/state/state_coin.go index 5cad8092e..0a6d0cf1f 100644 --- a/core/state/state_coin.go +++ b/core/state/state_coin.go @@ -54,7 +54,6 @@ type Coin struct { Symbol types.CoinSymbol Volume *big.Int Crr uint - ReserveCoin types.CoinSymbol ReserveBalance *big.Int Creator types.Address } diff --git a/core/state/statedb.go b/core/state/statedb.go index b7c30188e..b906fb148 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -470,7 +470,6 @@ func (s *StateDB) CreateCoin( Symbol: symbol, Volume: volume, Crr: crr, - ReserveCoin: types.GetBaseCoin(), ReserveBalance: reserve, Creator: creator, }, s.MarkStateCoinDirty) From db8331e9fc57e73d6b2231f951e0ef8af87db64b Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Tue, 3 Jul 2018 11:40:58 +0300 Subject: [PATCH 08/19] add coin minter image to docs --- docs/assets/coin-minter.png | Bin 0 -> 85350 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/assets/coin-minter.png diff --git a/docs/assets/coin-minter.png b/docs/assets/coin-minter.png new file mode 100644 index 0000000000000000000000000000000000000000..ac61ce7353401f9485bc335294e0407fe14abe5c GIT binary patch literal 85350 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%0A+m1q<`c#f58SBSiME@Rd2=I`{VwuI>DL} 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 z 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 z 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 literal 0 HcmV?d00001 From 6d2453d5e16de5557162105682444fae5cf17ebc Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Tue, 3 Jul 2018 12:00:10 +0300 Subject: [PATCH 09/19] update tendermint to v0.22.0 --- CHANGELOG.md | 1 + Gopkg.lock | 106 +++++++++++++++------ Gopkg.toml | 2 +- README.md | 2 +- api/block.go | 2 +- api/status.go | 2 +- api/transactions.go | 2 +- cmd/minter/main.go | 6 +- core/minter/minter.go | 2 +- core/state/statedb.go | 2 +- core/transaction/executor.go | 2 +- docker-compose.yml | 2 +- docs/install.rst | 2 +- tests/acceptance/docker/docker-compose.yml | 2 +- 14 files changed, 91 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02be82a92..76fedb490 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ BREAKING CHANGES - [core] Remove Reserve Coin from coin object. All coins should be reserved with base coin. - [testnet] New testnet chain id (minter-test-network-8) +- [tendermint] Switched to v0.22.0 IMPROVEMENT diff --git a/Gopkg.lock b/Gopkg.lock index 4445c4a24..0beebf87e 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -7,6 +7,12 @@ packages = ["."] revision = "b176f1e721fc5f9520ce35b8c68c90f78bda8d62" +[[projects]] + branch = "master" + name = "github.com/beorn7/perks" + packages = ["quantile"] + revision = "3a771d992973f24aa725d07868b467d1ddfceafb" + [[projects]] branch = "master" name = "github.com/btcsuite/btcd" @@ -41,7 +47,11 @@ packages = [ "log", "log/level", - "log/term" + "log/term", + "metrics", + "metrics/discard", + "metrics/internal/lv", + "metrics/prometheus" ] revision = "4dc7be5d2d12881735283bcab7352178e190fc71" version = "v0.6.0" @@ -128,12 +138,51 @@ packages = ["."] revision = "b84e30acd515aadc4b783ad4ff83aff3299bdfe0" +[[projects]] + name = "github.com/matttproud/golang_protobuf_extensions" + packages = ["pbutil"] + revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" + version = "v1.0.1" + [[projects]] name = "github.com/pkg/errors" packages = ["."] revision = "645ef00459ed84a119197bfb8d8205042c6df63d" version = "v0.8.0" +[[projects]] + name = "github.com/prometheus/client_golang" + packages = ["prometheus"] + revision = "c5b7fccd204277076155f10851dad72b76a49317" + version = "v0.8.0" + +[[projects]] + branch = "master" + name = "github.com/prometheus/client_model" + packages = ["go"] + revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c" + +[[projects]] + branch = "master" + name = "github.com/prometheus/common" + packages = [ + "expfmt", + "internal/bitbucket.org/ww/goautoneg", + "model" + ] + revision = "7600349dcfe1abd18d72d3a1770870d9800a7801" + +[[projects]] + branch = "master" + name = "github.com/prometheus/procfs" + packages = [ + ".", + "internal/util", + "nfs", + "xfs" + ] + revision = "40f013a808ec4fa79def444a1a56de4d1727efcb" + [[projects]] branch = "master" name = "github.com/rcrowley/go-metrics" @@ -168,18 +217,6 @@ ] revision = "5d6fca44a948d2be89a9702de7717f0168403d3d" -[[projects]] - name = "github.com/tendermint/abci" - packages = [ - "client", - "example/code", - "example/kvstore", - "server", - "types" - ] - revision = "198dccf0ddfd1bb176f87657e3286a05a6ed9540" - version = "v0.12.0" - [[projects]] branch = "master" name = "github.com/tendermint/ed25519" @@ -193,19 +230,25 @@ [[projects]] name = "github.com/tendermint/go-amino" packages = ["."] - revision = "ed62928576cfcaf887209dc96142cd79cdfff389" - version = "0.9.9" - -[[projects]] - name = "github.com/tendermint/go-crypto" - packages = ["."] - revision = "915416979bf70efa4bcbf1c6cd5d64c5fff9fc19" - version = "v0.6.2" + revision = "2106ca61d91029c931fd54968c2bb02dc96b1412" + version = "0.10.1" [[projects]] name = "github.com/tendermint/tendermint" packages = [ + "abci/client", + "abci/example/code", + "abci/example/kvstore", + "abci/server", + "abci/types", "config", + "crypto", + "crypto/merkle", + "crypto/tmhash", + "libs/common", + "libs/db", + "libs/flowrate", + "libs/log", "libs/pubsub", "libs/pubsub/query", "p2p", @@ -218,17 +261,14 @@ "state", "types" ] - revision = "46369a1ab76f274ab47179c4176221842b8207b4" - version = "v0.21.0" + revision = "dfa9a9a30a666132425b29454e90a472aa579a48" + version = "v0.22.0" [[projects]] name = "github.com/tendermint/tmlibs" packages = [ "common", - "db", - "flowrate", - "log", - "merkle" + "log" ] revision = "692f1d86a6e2c0efa698fd1e4541b68c74ffaf38" version = "v0.8.4" @@ -294,9 +334,13 @@ packages = [ ".", "balancer", + "balancer/base", + "balancer/roundrobin", "codes", "connectivity", "credentials", + "encoding", + "encoding/proto", "grpclb/grpc_lb_v1/messages", "grpclog", "internal", @@ -305,13 +349,15 @@ "naming", "peer", "resolver", + "resolver/dns", + "resolver/passthrough", "stats", "status", "tap", "transport" ] - revision = "5b3c4e850e90a4cf6a20ebd46c8b32a0a3afcb9e" - version = "v1.7.5" + revision = "d11072e7ca9811b1100b80ca0269ac831f06d024" + version = "v1.11.3" [[projects]] branch = "v1" @@ -328,6 +374,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "8ed38a47ca9d158715b1cb9869acd30f39903615a2ef1ae547a837a1b354e944" + inputs-digest = "5dc565d960a37820eecf571bb5de7fd224da44e3fe11c277fdb65f1fa4fddc89" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index e804743bd..555d8059c 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -59,7 +59,7 @@ [[constraint]] name = "github.com/tendermint/tendermint" - version = "0.21.0" + version = "0.22.0" [[constraint]] branch = "v2" diff --git a/README.md b/README.md index 78092b389..07670e606 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ $ docker-compose up You'll need **go** [installed](https://golang.org/doc/install) and the required [environment variables set](https://github.com/tendermint/tendermint/wiki/Setting-GOPATH) -1. Install [Tendermint 0.21.0](https://github.com/tendermint/tendermint/blob/master/docs/install.rst) +1. Install [Tendermint 0.22.0](https://github.com/tendermint/tendermint/blob/master/docs/install.rst) 2. Clone Minter to your machine ```bash diff --git a/api/block.go b/api/block.go index 6f6ad4054..5996c6af3 100644 --- a/api/block.go +++ b/api/block.go @@ -5,9 +5,9 @@ import ( "fmt" "github.com/MinterTeam/minter-go-node/core/transaction" "github.com/gorilla/mux" + "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/rpc/core/types" "github.com/tendermint/tendermint/types" - "github.com/tendermint/tmlibs/common" "math/big" "net/http" "strconv" diff --git a/api/status.go b/api/status.go index ecc8d7495..b3bc246c6 100644 --- a/api/status.go +++ b/api/status.go @@ -2,8 +2,8 @@ package api import ( "encoding/json" + "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/rpc/core/types" - "github.com/tendermint/tmlibs/common" "net/http" "time" ) diff --git a/api/transactions.go b/api/transactions.go index f8c4b828e..2a00620c2 100644 --- a/api/transactions.go +++ b/api/transactions.go @@ -3,8 +3,8 @@ package api import ( "encoding/json" "github.com/MinterTeam/minter-go-node/core/transaction" + "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/rpc/core/types" - "github.com/tendermint/tmlibs/common" "math/big" "net/http" ) diff --git a/cmd/minter/main.go b/cmd/minter/main.go index f9fb09201..43ad983f9 100644 --- a/cmd/minter/main.go +++ b/cmd/minter/main.go @@ -4,9 +4,9 @@ import ( "github.com/MinterTeam/minter-go-node/api" "github.com/MinterTeam/minter-go-node/cmd/utils" "github.com/MinterTeam/minter-go-node/core/minter" - "github.com/tendermint/abci/server" - "github.com/tendermint/tmlibs/common" - "github.com/tendermint/tmlibs/log" + "github.com/tendermint/tendermint/abci/server" + "github.com/tendermint/tendermint/libs/common" + "github.com/tendermint/tendermint/libs/log" "os" ) diff --git a/core/minter/minter.go b/core/minter/minter.go index 0c1a918f6..36eb620cc 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -15,7 +15,7 @@ import ( "github.com/MinterTeam/minter-go-node/genesis" "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/mintdb" - abciTypes "github.com/tendermint/abci/types" + abciTypes "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/rpc/core/types" "github.com/tendermint/tendermint/rpc/lib/client" "math/big" diff --git a/core/state/statedb.go b/core/state/statedb.go index b906fb148..b3eaa9f0b 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -30,7 +30,7 @@ import ( "encoding/binary" "github.com/MinterTeam/minter-go-node/core/check" "github.com/MinterTeam/minter-go-node/core/dao" - abci "github.com/tendermint/abci/types" + abci "github.com/tendermint/tendermint/abci/types" "sort" ) diff --git a/core/transaction/executor.go b/core/transaction/executor.go index 32bb7b78d..cd6250a9e 100644 --- a/core/transaction/executor.go +++ b/core/transaction/executor.go @@ -12,7 +12,7 @@ import ( "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/tmlibs/common" + "github.com/tendermint/tendermint/libs/common" "math/big" "regexp" ) diff --git a/docker-compose.yml b/docker-compose.yml index 303148325..9e26314bc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,7 +15,7 @@ services: retries: 3 start_period: 30s tendermint: - image: tendermint/tendermint:0.21.0 + image: tendermint/tendermint:0.22.0 command: node --proxy_app=tcp://minter:46658 volumes: - ~/.tendermint:/tendermint diff --git a/docs/install.rst b/docs/install.rst index ba587ccd3..67d9122ad 100755 --- a/docs/install.rst +++ b/docs/install.rst @@ -49,7 +49,7 @@ From Source You'll need ``go`` `installed `__ and the required `environment variables set `__ -Install Tendermint 0.21.0 +Install Tendermint 0.22.0 ^^^^^^^^^^^^^^^^^^^^^^^^^ `Read official instructions `__ diff --git a/tests/acceptance/docker/docker-compose.yml b/tests/acceptance/docker/docker-compose.yml index 6bc98e191..5f23a56e5 100644 --- a/tests/acceptance/docker/docker-compose.yml +++ b/tests/acceptance/docker/docker-compose.yml @@ -8,7 +8,7 @@ services: ports: - "8841:8841" tendermint: - image: tendermint/tendermint:0.21.0 + image: tendermint/tendermint:0.22.0 command: node --proxy_app=tcp://minter:46658 volumes: - ./data/.tendermint:/tendermint From 282ca53010838281e72668c4b7180ac756e72ff7 Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Tue, 3 Jul 2018 13:47:33 +0300 Subject: [PATCH 10/19] commissions docs --- docs/commissions.rst | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/docs/commissions.rst b/docs/commissions.rst index 0dcc5aa66..c32d2e1eb 100755 --- a/docs/commissions.rst +++ b/docs/commissions.rst @@ -1,3 +1,46 @@ Commissions =========== +For each transaction sender should pay fee. Fees are measured in "units". + +1 unit = 10^8 pip = 0.00000001 bip. + +Standard commissions +^^^^^^^^^^^^^^^^^^^^ + +Here is a list of current fees: + ++----------------------------------+--------------+ +| Type | Fee | ++==================================+==============+ +| **TypeSend** | 1000 units | ++----------------------------------+--------------+ +| **TypeConvert** | 10000 units | ++----------------------------------+--------------+ +| **TypeCreateCoin** | 100000 units | ++----------------------------------+--------------+ +| **TypeDeclareCandidacy** | 100000 units | ++----------------------------------+--------------+ +| **TypeDelegate** | 10000 units | ++----------------------------------+--------------+ +| **TypeUnbond** | 10000 units | ++----------------------------------+--------------+ +| **TypeRedeemCheck** | 1000 units | ++----------------------------------+--------------+ +| **TypeSetCandidateOnline** | 500 units | ++----------------------------------+--------------+ +| **TypeSetCandidateOffline** | 1000 units | ++----------------------------------+--------------+ + +Special fees +^^^^^^^^^^^^ + +To issue a coin with short name Coiner should pay extra fee. Fee is depends on length of Coin Symbol. + +| 3 letters – 1 000 000 bips + standard transaction fee +| 4 letters – 100 000 bips + standard transaction fee +| 5 letters – 10 000 bips + standard transaction fee +| 6 letters – 1000 bips + standard transaction fee +| 7 letters – 100 bips + standard transaction fee +| 8 letters – 10 bips + standard transaction fee +| 9-10 letters - just standard transaction fee From af5536962eb78391a2292ef727e83f51c41c5e8a Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Tue, 3 Jul 2018 13:57:04 +0300 Subject: [PATCH 11/19] documentation --- docs/delegator-faq.rst | 20 ++++++++++++++++++++ docs/index.rst | 1 + docs/install.rst | 7 +++++-- docs/validators.rst | 8 ++++++-- 4 files changed, 32 insertions(+), 4 deletions(-) create mode 100755 docs/delegator-faq.rst diff --git a/docs/delegator-faq.rst b/docs/delegator-faq.rst new file mode 100755 index 000000000..ddeec27e1 --- /dev/null +++ b/docs/delegator-faq.rst @@ -0,0 +1,20 @@ +Delegator FAQ +============= + +What is a delegator? +^^^^^^^^^^^^^^^^^^^^ + +Choosing a validator +^^^^^^^^^^^^^^^^^^^^ + +Directives of delegators +^^^^^^^^^^^^^^^^^^^^^^^^ + +Revenue +^^^^^^^ + +Validator's commission +^^^^^^^^^^^^^^^^^^^^^^ + +Risks +^^^^^ diff --git a/docs/index.rst b/docs/index.rst index 878f97052..b2e50750a 100755 --- a/docs/index.rst +++ b/docs/index.rst @@ -15,6 +15,7 @@ Minter 101 checks.rst commissions.rst validators.rst + delegator-faq.rst api.rst sdk.rst diff --git a/docs/install.rst b/docs/install.rst index 67d9122ad..6ad89c740 100755 --- a/docs/install.rst +++ b/docs/install.rst @@ -131,6 +131,9 @@ Troubleshooting Too many open files (24) ^^^^^^^^^^^^^^^^^^^^^^^^ -Tendermint sometimes is very resource-demanding in terms of "max open files limit". If your -instance is constantly shutting down after working couple minutes - try to increase open files limit: +The default number of files Linux can open (per-process) is 1024. Tendermint is known to open more than 1024 files. +This causes the process to crash. A quick fix is to run ulimit -n 4096 (increase the number of open files allowed) and +then restart the process with gaiad start. If you are using systemd or another process manager to launch gaiad this +may require some configuration at that level. + ``__ diff --git a/docs/validators.rst b/docs/validators.rst index 8b7c3318a..a19000ca3 100755 --- a/docs/validators.rst +++ b/docs/validators.rst @@ -53,8 +53,8 @@ Rules and fines ... -How to become validator in testnet -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Becoming validator in testnet +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1. Install and run Minter Full Node. See :ref:`install-minter`. Make sure your node successfully synchronized. @@ -103,3 +103,7 @@ How to become validator in testnet 5. Done. Now you will receive reward as long as your node is running and available. + + +DDOS protection. Sentry node architecture +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From b21175f5c98d465732c587d79cac9cba4f1e65a5 Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Tue, 3 Jul 2018 15:13:44 +0300 Subject: [PATCH 12/19] Limit tx payload and service data to 128 bytes --- CHANGELOG.md | 3 ++- core/code/code.go | 2 ++ core/minter/minter.go | 53 ++++++++++++++++++++++++++++++++----------- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76fedb490..624575470 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,8 @@ BREAKING CHANGES -- [core] Remove Reserve Coin from coin object. All coins should be reserved with base coin. +- [core] Remove Reserve Coin from coin object. All coins should be reserved with base coin +- [core] Limit tx payload and service data to 128 bytes - [testnet] New testnet chain id (minter-test-network-8) - [tendermint] Switched to v0.22.0 diff --git a/core/code/code.go b/core/code/code.go index 1afb80e4f..2bb97212a 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -11,6 +11,8 @@ const ( DecodeError uint32 = 106 InsufficientFunds uint32 = 107 UnknownTransactionType uint32 = 108 + TxPayloadTooLarge uint32 = 109 + TxServiceDataTooLarge uint32 = 110 // coin creation CoinAlreadyExists uint32 = 201 diff --git a/core/minter/minter.go b/core/minter/minter.go index 36eb620cc..dc6ac7b43 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -39,15 +39,18 @@ type Blockchain struct { const ( ValidatorPresent = 1 ValidatorAbsent = 2 + + stateTableId = "state" + appTableId = "app" + + maxTxLength = 1024 + maxPayloadLength = 128 + maxServiceDataLength = 128 ) var ( blockchain *Blockchain - stateTableId = "state" - appTableId = "app" - - maxTxLength = 1024 teamAddress = types.HexToAddress("Mxa93163fdf10724dc4785ff5cbfb9ac0b5949409f") airdropAddress = types.HexToAddress("Mxa93163fdf10724dc4785ff5cbfb9ac0b5949409f") ) @@ -230,15 +233,15 @@ func (app *Blockchain) Info(req abciTypes.RequestInfo) (resInfo abciTypes.Respon } } -func (app *Blockchain) DeliverTx(tx []byte) abciTypes.ResponseDeliverTx { +func (app *Blockchain) DeliverTx(rawTx []byte) abciTypes.ResponseDeliverTx { - if len(tx) > maxTxLength { + if len(rawTx) > maxTxLength { return abciTypes.ResponseDeliverTx{ Code: code.TxTooLarge, Log: "TX length is over 1024 bytes"} } - decodedTx, err := transaction.DecodeFromBytes(tx) + tx, err := transaction.DecodeFromBytes(rawTx) if err != nil { return abciTypes.ResponseDeliverTx{ @@ -246,9 +249,21 @@ func (app *Blockchain) DeliverTx(tx []byte) abciTypes.ResponseDeliverTx { Log: err.Error()} } - fmt.Println("deliver", decodedTx) + if len(tx.Payload) > maxPayloadLength { + return abciTypes.ResponseDeliverTx{ + Code: code.TxPayloadTooLarge, + Log: "TX payload length is over 128 bytes"} + } - response := transaction.RunTx(app.stateDeliver, false, decodedTx, app.rewards, app.height) + if len(tx.ServiceData) > maxServiceDataLength { + return abciTypes.ResponseDeliverTx{ + Code: code.TxServiceDataTooLarge, + Log: "TX service data length is over 128 bytes"} + } + + fmt.Println("deliver", tx) + + response := transaction.RunTx(app.stateDeliver, false, tx, app.rewards, app.height) return abciTypes.ResponseDeliverTx{ Code: response.Code, @@ -262,15 +277,15 @@ func (app *Blockchain) DeliverTx(tx []byte) abciTypes.ResponseDeliverTx { } } -func (app *Blockchain) CheckTx(tx []byte) abciTypes.ResponseCheckTx { +func (app *Blockchain) CheckTx(rawTx []byte) abciTypes.ResponseCheckTx { - if len(tx) > maxTxLength { + if len(rawTx) > maxTxLength { return abciTypes.ResponseCheckTx{ Code: code.TxTooLarge, Log: "TX length is over 1024 bytes"} } - decodedTx, err := transaction.DecodeFromBytes(tx) + tx, err := transaction.DecodeFromBytes(rawTx) if err != nil { return abciTypes.ResponseCheckTx{ @@ -278,7 +293,19 @@ func (app *Blockchain) CheckTx(tx []byte) abciTypes.ResponseCheckTx { Log: err.Error()} } - response := transaction.RunTx(app.stateCheck, true, decodedTx, nil, app.height) + if len(tx.Payload) > maxPayloadLength { + return abciTypes.ResponseCheckTx{ + Code: code.TxPayloadTooLarge, + Log: "TX payload length is over 128 bytes"} + } + + if len(tx.ServiceData) > maxServiceDataLength { + return abciTypes.ResponseCheckTx{ + Code: code.TxServiceDataTooLarge, + Log: "TX service data length is over 128 bytes"} + } + + response := transaction.RunTx(app.stateCheck, true, tx, nil, app.height) return abciTypes.ResponseCheckTx{ Code: response.Code, From c090d58c5e4c9e8c2174ec3247a82f4e072a3993 Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Tue, 3 Jul 2018 15:14:49 +0300 Subject: [PATCH 13/19] change changelog date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 624575470..389b1797c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog ## 0.0.5 -*June 29th, 2018* +*Jule 3rd, 2018* BREAKING CHANGES From ee71366dccf31d9f1d7fb961a5e989f7884930f5 Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Tue, 3 Jul 2018 15:45:28 +0300 Subject: [PATCH 14/19] add validators rules and fines --- docs/validators.rst | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/docs/validators.rst b/docs/validators.rst index a19000ca3..1bd86a51d 100755 --- a/docs/validators.rst +++ b/docs/validators.rst @@ -36,6 +36,13 @@ Recommended: - 200GB SSD - x64 2.0 GHz 4v CPU +Validators limitations +^^^^^^^^^^^^^^^^^^^^^^ + +Minter Network has limited number of available slots for validators. + +At genesis there will be just ``16`` of them. ``4`` slots will be added each ``518,400`` blocks. +Maximum validators count is ``256``. Rewards ^^^^^^^ @@ -51,7 +58,23 @@ Delegators receive their rewards at the same time after paying commission to the Rules and fines ^^^^^^^^^^^^^^^ -... +Validators have one main responsibility: + +- Be able to constantly run a correct version of the software: validators need to make sure that their + servers are always online and their private keys are not compromised. + + +If a validator misbehaves, its bonded stake along with its delegators' stake and will be slashed. +The severity of the punishment depends on the type of fault. There are 3 main faults that can result in slashing +of funds for a validator and its delegators: + +- **Double signing**: If someone reports on chain A that a validator signed two blocks at the same height on chain + A and chain B, this validator will get slashed on chain A +- **Unavailability**: If a validator's signature has not been included in the last X blocks, + 1% of stake will get slashed and validator will be turned off + +Note that even if a validator does not intentionally misbehave, it can still be slashed if its node crashes, +looses connectivity, gets DDOSed, or if its private key is compromised. Becoming validator in testnet ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From f948fdcb672eeedce50db1bfb288cfb4379698da Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Tue, 3 Jul 2018 15:55:57 +0300 Subject: [PATCH 15/19] fix docs --- docs/validators.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/validators.rst b/docs/validators.rst index 1bd86a51d..7c2b4b063 100755 --- a/docs/validators.rst +++ b/docs/validators.rst @@ -15,9 +15,8 @@ by token holders. The validators are determined by who has the most stake delega Validators and their delegators will earn BIP (MNT) as rewards for blocks and commissions. Note that validators can set commission on the rewards their delegators receive as additional incentive. -If validators double sign, are frequently offline or do not participate in governance, their -staked coins (including coins of users that delegated to them) can be slashed. The penalty -depends on the severity of the violation. +If validators double sign or frequently offline, their staked coins (including coins of users that +delegated to them) can be slashed. The penalty depends on the severity of the violation. Requirements ^^^^^^^^^^^^ @@ -48,12 +47,12 @@ Rewards ^^^^^^^ Rewards for blocks and commissions are accumulated and proportionally (based on stake value) -payed once per 12 blocks (approx 1 minute) to all active validators (and their delegators). +payed once per ``12 blocks`` (approx 1 minute) to all active validators (and their delegators). Delegators receive their rewards at the same time after paying commission to their validators (commission value is based on validator's settings). -5% from reward going to DAO account. +``5%`` from reward going to DAO account. Rules and fines ^^^^^^^^^^^^^^^ From 1a44369c9c08ca70c06a3902569b3b36489b585e Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Tue, 3 Jul 2018 17:25:32 +0300 Subject: [PATCH 16/19] update docs --- docs/api.rst | 98 +++++++++++++++++++++++++++++++++++++++++++++++--- docs/coins.rst | 7 ++-- 2 files changed, 98 insertions(+), 7 deletions(-) diff --git a/docs/api.rst b/docs/api.rst index 0982c29be..bac56ce00 100755 --- a/docs/api.rst +++ b/docs/api.rst @@ -4,6 +4,9 @@ Minter Node API Status ^^^^^^ +This endpoint shows current state of the node. You also can use it to check if node is running in +normal mode. + .. code-block:: bash curl -s 'localhost:8841/api/status' @@ -23,6 +26,9 @@ Status Volume of Base Coin in Blockchain ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +This endpoint shows amount of base coin (BIP or MNT) existing in the network. It counts block rewards, premine and +relayed rewards. + .. code-block:: bash curl -s 'localhost:8841/api/bipVolume?height={height}' @@ -37,6 +43,24 @@ Volume of Base Coin in Blockchain Candidate ^^^^^^^^^ +This endpoint shows candidate's info by provided public_key. It will respond with ``404`` code if candidate is not +found. + +- **candidate_address** - Address of a candidate in minter network. This address is used to manage + candidate and receive rewards. +- **total_stake** - Total stake calculated in base coin (MNT or BIP). +- **commission** - Commission for delerators. Measured in percents. Can be 0..100. +- **accumulated_reward** - Reward waiting to be sent to validator and his delegators. Reward is payed each 12 blocks. +- **stakes** - List of candidate's stakes. +- **created_at_block** - Height of block when candidate was created. +- **status** - Status of a candidate. + + - ``1`` - Offline + - ``2`` - Online + +- **absent_times** - How many blocks candidate missed. If this number reaches 12, then candidate's stake will be + slashed by 1% and candidate will be turned off. + .. code-block:: bash curl -s 'localhost:8841/api/candidate/{public_key}' @@ -69,6 +93,8 @@ Candidate Validators ^^^^^^^^^^ +Returns list of active validators. + .. code-block:: bash curl -s 'localhost:8841/api/validators' @@ -101,6 +127,8 @@ Validators Balance ^^^^^^^ +Returns balance of an account. + .. code-block:: bash curl -s 'localhost:8841/api/balance/{address}' @@ -117,6 +145,9 @@ Balance Transaction count ^^^^^^^^^^^^^^^^^ +Returns count of outgoing transactions from given account. This should be used for calculating nonce for the new +transaction. + .. code-block:: bash curl -s 'localhost:8841/api/transactionCount/{address}' @@ -131,6 +162,8 @@ Transaction count Send transaction ^^^^^^^^^^^^^^^^ +Sends transaction to the Minter Network. + .. code-block:: bash curl -X POST --data '{"transaction":"..."}' -s 'localhost:8841/api/sendTransaction' @@ -159,6 +192,8 @@ Transaction Block ^^^^^ +Returns block data at given height. + .. code-block:: bash curl -s 'localhost:8841/api/block/{height}' @@ -166,13 +201,58 @@ Block .. code-block:: json { - "code": 0, - "result": ... + "code":0, + "result":{ + "hash":"A83F3A3909C8B863305C5A444C8C34C514A03590", + "height":108805, + "time":"2018-07-03T09:46:54.359423195Z", + "num_txs":1, + "total_txs":1174135, + "transactions":[ + { + "hash":"Mt3f85c77911f058c9c2f79d73c5d68b2c7dd3c2cd", + "from":"Mxa93163fdF10724DC4785FF5cBfB9aC0B5949409F", + "nonce":81, + "gasPrice":1, + "type":5, + "data":{ + "PubKey":"Mp079138d379aaf423c911506a3ccbe1d590a7d4d9aecbc7eb05816d81b41848d6", + "Coin":"BLTCOIN", + "Stake":"2000000000000000000" + }, + "payload":"", + "serviceData":"", + "gas":10000 + } + ], + "precommits":[ + { + "validator_address":"04E5DCA0DFCF35605A3EB1292DBDBF7C97B476B8", + "validator_index":0, + "height":108804, + "round":0, + "timestamp":"2018-07-03T09:47:33.79209988Z", + "type":2, + "block_id":{ + "hash":"2222959DA3EEA441DB6D0E01C12F1546B210DA72", + "parts":{ + "total":1, + "hash":"3821D8B2A09A1C6932712523B8DEB588375D7BFA" + } + }, + "signature":[] + } + ] + } } Coin Info ^^^^^^^^^ +Returns information about coin. + +*Note*: this method **does not** return information about base coins (MNT and BIP). + .. code-block:: bash curl -s 'localhost:8841/api/coinInfo/{symbol}' @@ -180,6 +260,14 @@ Coin Info .. code-block:: json { - "code": 0, - "result": ... - } + "code":0, + "result":{ + "name":"BeltCoin", + "symbol":"BLTCOIN", + "volume":"3162375676992609621", + "crr":10, + "reserve_coin":"MNT", + "reserve_balance":"100030999965000000000000", + "creator":"Mxc07ec7cdcae90dea3999558f022aeb25dabbeea2" + } + } \ No newline at end of file diff --git a/docs/coins.rst b/docs/coins.rst index b461e4c2f..c54a3ebfd 100755 --- a/docs/coins.rst +++ b/docs/coins.rst @@ -3,8 +3,11 @@ Coins Minter Blockchain is multi-coin system. -Base coin in testnet is ``MNT``. -Base coin in mainnet is ``BIP``. +| Base coin in testnet is ``MNT``. +| Base coin in mainnet is ``BIP``. + +| Smallest part of a coin is called ``pip``. +| 1 pip = 1^-18 of any coin. In Blockchain and API we only operating with pips. Coin Issuance ^^^^^^^^^^^^^ From 4eb7ba0dc0ea4472c28e8377049a6349be2b9f5b Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Tue, 3 Jul 2018 17:42:09 +0300 Subject: [PATCH 17/19] Fix transaction endpoint --- CHANGELOG.md | 4 ++++ api/transaction.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 389b1797c..a86ef3095 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ IMPROVEMENT - [api] Fix issue with not found coins +BUG FIXES + +- [api] Fix transaction endpoint + ## 0.0.4 *June 24th, 2018* diff --git a/api/transaction.go b/api/transaction.go index 307721ef8..f54824347 100644 --- a/api/transaction.go +++ b/api/transaction.go @@ -12,7 +12,7 @@ import ( func Transaction(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) - hash := strings.TrimRight(vars["hash"], "Mt") + hash := strings.TrimLeft(vars["hash"], "Mt") decoded, err := hex.DecodeString(hash) result := new(types.TxResult) From 23e02cda202e0b386f24da0a59e5b42237db5496 Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Wed, 4 Jul 2018 09:45:16 +0300 Subject: [PATCH 18/19] Fix critical issue with instant convert of 2 custom coins --- CHANGELOG.md | 1 + core/transaction/executor.go | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a86ef3095..9b84b4339 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ BREAKING CHANGES - [core] Remove Reserve Coin from coin object. All coins should be reserved with base coin - [core] Limit tx payload and service data to 128 bytes +- [core] Fix critical issue with instant convert of 2 custom coins - [testnet] New testnet chain id (minter-test-network-8) - [tendermint] Switched to v0.22.0 diff --git a/core/transaction/executor.go b/core/transaction/executor.go index cd6250a9e..bc1bad757 100644 --- a/core/transaction/executor.go +++ b/core/transaction/executor.go @@ -535,15 +535,15 @@ func RunTx(context *state.StateDB, isCheck bool, tx *Transaction, rewardPull *bi coinFrom := context.GetStateCoin(data.FromCoinSymbol).Data() coinTo := context.GetStateCoin(data.ToCoinSymbol).Data() - val := formula.CalculateSaleReturn(coinFrom.Volume, coinFrom.ReserveBalance, coinFrom.Crr, data.Value) - value = formula.CalculatePurchaseReturn(coinTo.Volume, coinTo.ReserveBalance, coinTo.Crr, val) + basecoinValue := formula.CalculateSaleReturn(coinFrom.Volume, coinFrom.ReserveBalance, coinFrom.Crr, data.Value) + value = formula.CalculatePurchaseReturn(coinTo.Volume, coinTo.ReserveBalance, coinTo.Crr, basecoinValue) if !isCheck { - context.AddCoinVolume(data.ToCoinSymbol, data.Value) - context.SubCoinVolume(data.FromCoinSymbol, value) + context.AddCoinVolume(data.ToCoinSymbol, value) + context.SubCoinVolume(data.FromCoinSymbol, data.Value) - context.AddCoinReserve(data.ToCoinSymbol, data.Value) - context.SubCoinReserve(data.ToCoinSymbol, value) + context.AddCoinReserve(data.ToCoinSymbol, basecoinValue) + context.SubCoinReserve(data.FromCoinSymbol, basecoinValue) } } From bcf9bb7adf3d6e0b0cb0a9290bbc6eb71aa06dba Mon Sep 17 00:00:00 2001 From: Daniil Lashin Date: Wed, 4 Jul 2018 10:04:07 +0300 Subject: [PATCH 19/19] prettify logs and prepare new version --- CHANGELOG.md | 2 +- cmd/minter/main.go | 2 +- core/minter/minter.go | 8 +++++--- networks/testnet/genesis.json | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b84b4339..9fed4ffc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog ## 0.0.5 -*Jule 3rd, 2018* +*Jule 4rd, 2018* BREAKING CHANGES diff --git a/cmd/minter/main.go b/cmd/minter/main.go index 43ad983f9..97c7c1f11 100644 --- a/cmd/minter/main.go +++ b/cmd/minter/main.go @@ -13,7 +13,7 @@ import ( func main() { logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) - app := minter.NewMinterBlockchain() + app := minter.NewMinterBlockchain(logger) // Start the listener srv, err := server.NewServer(*utils.MinterAppAddrFlag, "socket", app) diff --git a/core/minter/minter.go b/core/minter/minter.go index dc6ac7b43..74b29ea0f 100644 --- a/core/minter/minter.go +++ b/core/minter/minter.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/binary" "encoding/json" - "fmt" "github.com/MinterTeam/minter-go-node/cmd/utils" "github.com/MinterTeam/minter-go-node/core/code" "github.com/MinterTeam/minter-go-node/core/rewards" @@ -16,6 +15,7 @@ import ( "github.com/MinterTeam/minter-go-node/helpers" "github.com/MinterTeam/minter-go-node/mintdb" abciTypes "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/rpc/core/types" "github.com/tendermint/tendermint/rpc/lib/client" "math/big" @@ -32,6 +32,7 @@ type Blockchain struct { rewards *big.Int activeValidators abciTypes.Validators validatorsStatuses map[string]int8 + logger log.Logger BaseCoin types.CoinSymbol } @@ -55,7 +56,7 @@ var ( airdropAddress = types.HexToAddress("Mxa93163fdf10724dc4785ff5cbfb9ac0b5949409f") ) -func NewMinterBlockchain() *Blockchain { +func NewMinterBlockchain(logger log.Logger) *Blockchain { db, err := mintdb.NewLDBDatabase(utils.GetMinterHome()+"/data", 1000, 1000) @@ -66,6 +67,7 @@ func NewMinterBlockchain() *Blockchain { blockchain = &Blockchain{ db: db, BaseCoin: types.GetBaseCoin(), + logger: logger, } blockchain.updateCurrentRootHash() @@ -261,7 +263,7 @@ func (app *Blockchain) DeliverTx(rawTx []byte) abciTypes.ResponseDeliverTx { Log: "TX service data length is over 128 bytes"} } - fmt.Println("deliver", tx) + app.logger.Info("Deliver tx", "tx", tx.String()) response := transaction.RunTx(app.stateDeliver, false, tx, app.rewards, app.height) diff --git a/networks/testnet/genesis.json b/networks/testnet/genesis.json index c3dc06be8..c074f16b5 100644 --- a/networks/testnet/genesis.json +++ b/networks/testnet/genesis.json @@ -4,10 +4,10 @@ "validators": [ { "pub_key": { - "type": "AC26791624DE60", + "type": "tendermint/PubKeyEd25519", "value": "qu4d3zD/VMkHFdkotWZS/FEb7Tci5Ylz6O+Ub12uOXk=" }, - "power": 100, + "power": "100", "name": "" } ],