From 1715c0aeba09d156714cc583fd7502fcad914833 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 3 Aug 2017 19:27:06 +0200 Subject: [PATCH] Handlers and middlewares add gas prices --- TODO.md | 26 ++++++++++++++++++++++++-- handler.go | 9 +++++++++ modules/coin/handler.go | 17 +++++++++++++---- modules/fee/handler.go | 13 +++++++++++-- modules/nonce/replaycheck.go | 5 ++++- modules/roles/handler.go | 11 +++++++++-- modules/roles/middleware.go | 5 ++++- 7 files changed, 74 insertions(+), 12 deletions(-) diff --git a/TODO.md b/TODO.md index bff7c68fd7..eb4a4ab39d 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,28 @@ # TODO for rewrite -* FeeTx and CheckTx changes logic to estimate, not validate * Add tests for new CheckTx -* Test EndBlock validator set changes * Test Multiplexer + + +Alexis: + +* merkle - proof (non-existence - maybe range) +* intro to light-client and proofs +light-client proofs: +* make this sensible -> very tied to merkle proofs and API +* support new proof types + +* abci add range suppprt + + + +* merkle - api cleanup (also Bonsai) +* later: C bindings (to Bonsai?) + + +* crypto-ledger (while ethan gone) + +light-client provider: +* caching checkpoint on Verify +* cleanup (trim old node) + diff --git a/handler.go b/handler.go index 0e4e16c8a5..32689b3a42 100644 --- a/handler.go +++ b/handler.go @@ -95,6 +95,15 @@ type CheckResult struct { GasPayment uint } +// NewCheck sets the gas used and the response data but no more info +// these are the most common info needed to be set by the Handler +func NewCheck(gasAllocated uint, log string) CheckResult { + return CheckResult{ + GasAllocated: gasAllocated, + Log: log, + } +} + var _ Dataer = CheckResult{} func (r CheckResult) ToABCI() abci.Result { diff --git a/modules/coin/handler.go b/modules/coin/handler.go index 52fa820b09..c02460cbd4 100644 --- a/modules/coin/handler.go +++ b/modules/coin/handler.go @@ -12,8 +12,14 @@ import ( "github.com/tendermint/basecoin/state" ) -//NameCoin - name space of the coin module -const NameCoin = "coin" +const ( + //NameCoin - name space of the coin module + NameCoin = "coin" + // CostSend is GasAllocation per input/output + CostSend = 10 + // CostCredit is GasAllocation of a credit allocation + CostCredit = 20 +) // Handler includes an accountant type Handler struct { @@ -46,9 +52,12 @@ func (h Handler) CheckTx(ctx basecoin.Context, store state.SimpleDB, switch t := tx.Unwrap().(type) { case SendTx: - return res, h.checkSendTx(ctx, store, t) + // price based on inputs and outputs + used := uint(len(t.Inputs) + len(t.Outputs)) + return basecoin.NewCheck(used*CostSend, ""), h.checkSendTx(ctx, store, t) case CreditTx: - return res, h.creditTx(ctx, store, t) + // default price of 20, constant work + return basecoin.NewCheck(CostCredit, ""), h.creditTx(ctx, store, t) } return res, errors.ErrUnknownTxType(tx.Unwrap()) } diff --git a/modules/fee/handler.go b/modules/fee/handler.go index 536131648f..d1eca64bb2 100644 --- a/modules/fee/handler.go +++ b/modules/fee/handler.go @@ -55,15 +55,24 @@ func (h SimpleFeeMiddleware) CheckTx(ctx basecoin.Context, store state.SimpleDB, return res, err } + var paid, used uint if !fee.Fee.IsZero() { // now, try to make a IPC call to coins... send := coin.NewSendOneTx(fee.Payer, h.Collector, coin.Coins{fee.Fee}) - _, err = next.CheckTx(ctx, store, send) + sendRes, err := next.CheckTx(ctx, store, send) if err != nil { return res, err } + paid = uint(fee.Fee.Amount) + used = sendRes.GasAllocated } - return next.CheckTx(ctx, store, fee.Tx) + res, err = next.CheckTx(ctx, store, fee.Tx) + // add the given fee to the price for gas, plus one query + if err == nil { + res.GasPayment += paid + res.GasAllocated += used + } + return res, err } // DeliverTx - send the fee handler transaction diff --git a/modules/nonce/replaycheck.go b/modules/nonce/replaycheck.go index 742cd348f7..2d532a1c2c 100644 --- a/modules/nonce/replaycheck.go +++ b/modules/nonce/replaycheck.go @@ -9,6 +9,7 @@ import ( //nolint const ( NameNonce = "nonce" + CostNonce = 10 ) // ReplayCheck uses the sequence to check for replay attacks @@ -33,7 +34,9 @@ func (r ReplayCheck) CheckTx(ctx basecoin.Context, store state.SimpleDB, return res, err } - return next.CheckTx(ctx, store, stx) + res, err = next.CheckTx(ctx, store, stx) + res.GasAllocated += CostNonce + return res, err } // DeliverTx verifies tx is not being replayed - fulfills Middlware interface diff --git a/modules/roles/handler.go b/modules/roles/handler.go index a3d4161bb9..e7073d0344 100644 --- a/modules/roles/handler.go +++ b/modules/roles/handler.go @@ -6,8 +6,14 @@ import ( "github.com/tendermint/basecoin/state" ) -//NameRole - name space of the roles module -const NameRole = "role" +const ( + //NameRole - name space of the roles module + NameRole = "role" + // CostCreate is the cost to create a new role + CostCreate = 40 + // CostAssume is the cost to assume a role as part of a tx + CostAssume = 5 +) // Handler allows us to create new roles type Handler struct { @@ -34,6 +40,7 @@ func (h Handler) CheckTx(ctx basecoin.Context, store state.SimpleDB, tx basecoin if err != nil { return } + res = basecoin.NewCheck(CostCreate, "") err = checkNoRole(store, cr.Role) return } diff --git a/modules/roles/middleware.go b/modules/roles/middleware.go index 229eb0a55e..6266db8e42 100644 --- a/modules/roles/middleware.go +++ b/modules/roles/middleware.go @@ -41,7 +41,10 @@ func (m Middleware) CheckTx(ctx basecoin.Context, store state.SimpleDB, tx basec } // one could add multiple role statements, repeat as needed - return m.CheckTx(ctx, store, assume.Tx, next) + // charging for each level + res, err = m.CheckTx(ctx, store, assume.Tx, next) + res.GasAllocated += CostAssume + return } // DeliverTx tries to assume the named role if requested.