diff --git a/block/block.go b/block/block.go index bfa8c28f4..bb5e3d41f 100644 --- a/block/block.go +++ b/block/block.go @@ -107,12 +107,16 @@ type Header struct { Height uint Time time.Time Fees uint64 + GasPrice uint64 NumTxs uint LastBlockHash []byte LastBlockParts PartSetHeader StateHash []byte } +// possible for actual gas price to be less than 1 +var GasPriceDivisor = 1000000 + func (h *Header) Hash() []byte { buf := new(bytes.Buffer) hasher, n, err := sha256.New(), new(int64), new(error) diff --git a/block/tx.go b/block/tx.go index 0958dcb2e..5bf5dfc59 100644 --- a/block/tx.go +++ b/block/tx.go @@ -10,14 +10,15 @@ import ( ) var ( - ErrTxInvalidAddress = errors.New("Error invalid address") - ErrTxDuplicateAddress = errors.New("Error duplicate address") - ErrTxInvalidAmount = errors.New("Error invalid amount") - ErrTxInsufficientFunds = errors.New("Error insufficient funds") - ErrTxUnknownPubKey = errors.New("Error unknown pubkey") - ErrTxInvalidPubKey = errors.New("Error invalid pubkey") - ErrTxInvalidSignature = errors.New("Error invalid signature") - ErrTxInvalidSequence = errors.New("Error invalid sequence") + ErrTxInvalidAddress = errors.New("Error invalid address") + ErrTxDuplicateAddress = errors.New("Error duplicate address") + ErrTxInvalidAmount = errors.New("Error invalid amount") + ErrTxInsufficientFunds = errors.New("Error insufficient funds") + ErrTxInsufficientGasPrice = errors.New("Error insufficient gas price") + ErrTxUnknownPubKey = errors.New("Error unknown pubkey") + ErrTxInvalidPubKey = errors.New("Error invalid pubkey") + ErrTxInvalidSignature = errors.New("Error invalid signature") + ErrTxInvalidSequence = errors.New("Error invalid sequence") ) /* diff --git a/state/state.go b/state/state.go index a3d98d05c..48420befa 100644 --- a/state/state.go +++ b/state/state.go @@ -4,6 +4,7 @@ import ( "bytes" "errors" "fmt" + "math/big" "time" "github.com/tendermint/tendermint/account" @@ -234,7 +235,7 @@ func (s *State) AdjustByOutputs(accounts map[string]*account.Account, outs []*bl // If the tx is invalid, an error will be returned. // Unlike AppendBlock(), state will not be altered. -func (s *State) ExecTx(tx_ blk.Tx) error { +func (s *State) ExecTx(tx_ blk.Tx, blk_ *blk.Block) error { // TODO: do something with fees fees := uint64(0) @@ -296,8 +297,15 @@ func (s *State) ExecTx(tx_ blk.Tx) error { } accounts[string(tx.Address)] = outAcc - // TODO: fees - // inTotal -= fees + // ensure sufficient gas price + // we multiply to avoid dividing + bigProvidedFee := new(big.Int).Mul(big.NewInt(int64(tx.FeeLimit)), big.NewInt(int64(blk.GasPriceDivisor))) + bigMinFee := new(big.Int).Mul(big.NewInt(int64(blk_.GasPrice)), big.NewInt(int64(tx.GasLimit))) + if bigProvidedFee.Cmp(bigMinFee) < 0 { + return blk.ErrTxInsufficientGasPrice + } + + inTotal -= tx.FeeLimit // Good! Adjust accounts s.AdjustByInputs(accounts, []*blk.TxInput{tx.Input}) @@ -306,6 +314,8 @@ func (s *State) ExecTx(tx_ blk.Tx) error { // TODO: Run the contract call! + // TODO: refund some gas + return nil case *blk.BondTx: @@ -640,7 +650,7 @@ func (s *State) appendBlock(block *blk.Block, blockPartsHeader blk.PartSetHeader // Commit each tx for _, tx := range block.Data.Txs { - err := s.ExecTx(tx) + err := s.ExecTx(tx, block) if err != nil { return InvalidTxError{tx, err} } diff --git a/state/state_test.go b/state/state_test.go index f719df075..b9b900300 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -183,7 +183,7 @@ func TestTxSequence(t *testing.T) { tx := makeSendTx(sequence) tx.Inputs[0].Signature = privAccounts[0].Sign(tx) stateCopy := state.Copy() - err := stateCopy.ExecTx(tx) + err := stateCopy.ExecTx(tx, &blk.Block{}) if i == 1 { // Sequence is good. if err != nil { @@ -242,7 +242,7 @@ func TestTxs(t *testing.T) { } tx.Inputs[0].Signature = privAccounts[0].Sign(tx) - err := state.ExecTx(tx) + err := state.ExecTx(tx, &blk.Block{}) if err != nil { t.Errorf("Got error in executing send transaction, %v", err) } @@ -279,7 +279,7 @@ func TestTxs(t *testing.T) { }, } tx.Inputs[0].Signature = privAccounts[0].Sign(tx) - err := state.ExecTx(tx) + err := state.ExecTx(tx, &blk.Block{}) if err != nil { t.Errorf("Got error in executing bond transaction, %v", err) }