OSDN Git Service

init version of charge tx size gas (#394)
authorPaladz <yzhu101@uottawa.ca>
Tue, 6 Mar 2018 06:32:32 +0000 (14:32 +0800)
committerGitHub <noreply@github.com>
Tue, 6 Mar 2018 06:32:32 +0000 (14:32 +0800)
* init version of charge tx size gas

* edit the code a little bit

* change the storage gate rate

* fix a tx size bug

* fix for code review

15 files changed:
blockchain/blockchain_reactor.go
blockchain/transact.go
blockchain/txbuilder/builder.go
blockchain/txbuilder/txbuilder.go
blockchain/txbuilder/txbuilder_test.go
blockchain/txbuilder/witness.go
consensus/general.go
mining/mining.go
protocol/bc/bc.pb.go
protocol/bc/bc.proto
protocol/bc/legacy/map.go
protocol/tx.go
protocol/validation/validation.go
protocol/validation/validation_test.go
test/integration/standard_transaction_test.go

index 0ba3a88..aa25ea5 100644 (file)
@@ -3,9 +3,9 @@ package blockchain
 import (
        log "github.com/sirupsen/logrus"
 
+       "github.com/bytom/consensus"
        "github.com/bytom/protocol/bc"
        "github.com/bytom/protocol/bc/legacy"
-       "github.com/bytom/protocol/validation"
 )
 
 // return network infomation
@@ -178,6 +178,6 @@ func (bcr *BlockchainReactor) isMining() Response {
 
 // return gasRate
 func (bcr *BlockchainReactor) gasRate() Response {
-       gasrate := map[string]int64{"gasRate": validation.GasRate}
+       gasrate := map[string]int64{"gasRate": consensus.VMGasRate}
        return NewSuccessResponse(gasrate)
 }
index 4f12776..3d21fa7 100644 (file)
@@ -144,9 +144,6 @@ func (bcr *BlockchainReactor) submitSingle(ctx context.Context, tpl *txbuilder.T
                return nil, errors.Wrap(txbuilder.ErrMissingRawTx)
        }
 
-       if err := txbuilder.MaterializeWitnesses(tpl); err != nil {
-               return nil, err
-       }
        if err := txbuilder.FinalizeTx(ctx, bcr.chain, tpl.Transaction); err != nil {
                return nil, errors.Wrapf(err, "tx %s", tpl.Transaction.ID.String())
        }
index d86ed21..420c0da 100755 (executable)
@@ -130,6 +130,13 @@ func (b *TemplateBuilder) Build() (*Template, *legacy.TxData, error) {
                tpl.SigningInstructions = append(tpl.SigningInstructions, instruction)
                tx.Inputs = append(tx.Inputs, in)
        }
+
+       txSerialized, err := tx.MarshalText()
+       if err != nil {
+               return nil, nil, err
+       }
+
+       tx.SerializedSize = uint64(len(txSerialized))
        tpl.Transaction = legacy.NewTx(*tx)
        return tpl, tx, nil
 }
index c8c6081..f856f8d 100755 (executable)
@@ -89,7 +89,7 @@ func Sign(ctx context.Context, tpl *Template, xpubs []chainkd.XPub, auth string,
                        }
                }
        }
-       return nil
+       return materializeWitnesses(tpl)
 }
 
 func checkBlankCheck(tx *legacy.TxData) error {
index c2ea088..21eea8f 100755 (executable)
@@ -61,7 +61,8 @@ func TestBuild(t *testing.T) {
 
        want := &Template{
                Transaction: legacy.NewTx(legacy.TxData{
-                       Version: 1,
+                       Version:        1,
+                       SerializedSize: 410,
                        Inputs: []*legacy.TxInput{
                                legacy.NewSpendInput(nil, bc.NewHash([32]byte{0xff}), assetID1, 5, 0, nil, bc.Hash{}, nil),
                        },
@@ -169,7 +170,7 @@ func TestSignatureWitnessMaterialize(t *testing.T) {
                        },
                },
        }}
-       err = MaterializeWitnesses(tpl)
+       err = materializeWitnesses(tpl)
        if err != nil {
                testutil.FatalErr(t, err)
        }
@@ -181,7 +182,7 @@ func TestSignatureWitnessMaterialize(t *testing.T) {
        // Test with exact amount of signatures required, in correct order
        component := tpl.SigningInstructions[0].WitnessComponents[0].(*SignatureWitness)
        component.Sigs = []json.HexBytes{sig1, sig2}
-       err = MaterializeWitnesses(tpl)
+       err = materializeWitnesses(tpl)
        if err != nil {
                testutil.FatalErr(t, err)
        }
index ed78b37..3efc546 100755 (executable)
@@ -15,7 +15,7 @@ type SignFunc func(context.Context, chainkd.XPub, [][]byte, [32]byte, string) ([
 // MaterializeWitnesses takes a filled in Template and "materializes"
 // each witness component, turning it into a vector of arguments for
 // the tx's input witness, creating a fully-signed transaction.
-func MaterializeWitnesses(txTemplate *Template) error {
+func materializeWitnesses(txTemplate *Template) error {
        msg := txTemplate.Transaction
 
        if msg == nil {
index 73d8f4b..76bec02 100644 (file)
@@ -9,8 +9,8 @@ import (
 //consensus variables
 const (
        // define the Max transaction size and Max block size
-       MaxTxSize    = uint64(1048576)
-       MaxBlockSzie = uint64(10485760)
+       MaxTxSize   = uint64(1048576)
+       MaxBlockGas = uint64(100000000)
 
        //config parameter for coinbase reward
        CoinbasePendingBlockNumber = uint64(6)
@@ -30,6 +30,11 @@ const (
        PayToWitnessScriptHashDataSize = 32
 
        CoinbaseArbitrarySizeLimit = 128
+
+       VMGasRate        = int64(1000)
+       StorageGasRate   = int64(10)
+       MaxGasAmount     = int64(100000)
+       DefaultGasCredit = int64(80000)
 )
 
 // BTMAssetID is BTM's asset id, the soul asset of Bytom
index 8ef0fba..3bc2ed2 100644 (file)
@@ -63,7 +63,7 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager
        view := state.NewUtxoViewpoint()
        txStatus := bc.NewTransactionStatus()
        txEntries := []*bc.Tx{nil}
-       blockWeight := uint64(0)
+       gasUsed := uint64(0)
        txFee := uint64(0)
 
        // get preblock info for generate next block
@@ -94,9 +94,6 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager
        for _, txDesc := range txs {
                tx := txDesc.Tx.Tx
                gasOnlyTx := false
-               if blockWeight+txDesc.Weight > consensus.MaxBlockSzie-consensus.MaxTxSize {
-                       break
-               }
 
                if err := c.GetTransactionsUtxo(view, []*bc.Tx{tx}); err != nil {
                        log.WithField("error", err).Error("mining block generate skip tx due to")
@@ -104,8 +101,9 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager
                        continue
                }
 
-               if _, gasVaild, err := validation.ValidateTx(tx, preBcBlock); err != nil {
-                       if !gasVaild {
+               gasStatus, err := validation.ValidateTx(tx, preBcBlock)
+               if err != nil {
+                       if !gasStatus.GasVaild {
                                log.WithField("error", err).Error("mining block generate skip tx due to")
                                txPool.RemoveTransaction(&tx.ID)
                                continue
@@ -113,6 +111,10 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager
                        gasOnlyTx = true
                }
 
+               if gasUsed+uint64(gasStatus.GasUsed) > consensus.MaxBlockGas {
+                       break
+               }
+
                if err := view.ApplyTransaction(bcBlock, tx, gasOnlyTx); err != nil {
                        log.WithField("error", err).Error("mining block generate skip tx due to")
                        txPool.RemoveTransaction(&tx.ID)
@@ -122,8 +124,12 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager
                txStatus.SetStatus(len(b.Transactions), gasOnlyTx)
                b.Transactions = append(b.Transactions, txDesc.Tx)
                txEntries = append(txEntries, tx)
-               blockWeight += txDesc.Weight
+               gasUsed += uint64(gasStatus.GasUsed)
                txFee += txDesc.Fee
+
+               if gasUsed == consensus.MaxBlockGas {
+                       break
+               }
        }
 
        // creater coinbase transaction
index e8dff58..db342b7 100644 (file)
@@ -274,15 +274,14 @@ func (m *ValueDestination) GetPosition() uint64 {
 
 type BlockHeader struct {
        Version               uint64             `protobuf:"varint,1,opt,name=version" json:"version,omitempty"`
-       SerializedSize        uint64             `protobuf:"varint,2,opt,name=serialized_size,json=serializedSize" json:"serialized_size,omitempty"`
-       Height                uint64             `protobuf:"varint,3,opt,name=height" json:"height,omitempty"`
-       PreviousBlockId       *Hash              `protobuf:"bytes,4,opt,name=previous_block_id,json=previousBlockId" json:"previous_block_id,omitempty"`
-       Timestamp             uint64             `protobuf:"varint,5,opt,name=timestamp" json:"timestamp,omitempty"`
-       TransactionsRoot      *Hash              `protobuf:"bytes,6,opt,name=transactions_root,json=transactionsRoot" json:"transactions_root,omitempty"`
-       TransactionStatusHash *Hash              `protobuf:"bytes,7,opt,name=transaction_status_hash,json=transactionStatusHash" json:"transaction_status_hash,omitempty"`
-       Nonce                 uint64             `protobuf:"varint,8,opt,name=nonce" json:"nonce,omitempty"`
-       Bits                  uint64             `protobuf:"varint,9,opt,name=bits" json:"bits,omitempty"`
-       TransactionStatus     *TransactionStatus `protobuf:"bytes,10,opt,name=transaction_status,json=transactionStatus" json:"transaction_status,omitempty"`
+       Height                uint64             `protobuf:"varint,2,opt,name=height" json:"height,omitempty"`
+       PreviousBlockId       *Hash              `protobuf:"bytes,3,opt,name=previous_block_id,json=previousBlockId" json:"previous_block_id,omitempty"`
+       Timestamp             uint64             `protobuf:"varint,4,opt,name=timestamp" json:"timestamp,omitempty"`
+       TransactionsRoot      *Hash              `protobuf:"bytes,5,opt,name=transactions_root,json=transactionsRoot" json:"transactions_root,omitempty"`
+       TransactionStatusHash *Hash              `protobuf:"bytes,6,opt,name=transaction_status_hash,json=transactionStatusHash" json:"transaction_status_hash,omitempty"`
+       Nonce                 uint64             `protobuf:"varint,7,opt,name=nonce" json:"nonce,omitempty"`
+       Bits                  uint64             `protobuf:"varint,8,opt,name=bits" json:"bits,omitempty"`
+       TransactionStatus     *TransactionStatus `protobuf:"bytes,9,opt,name=transaction_status,json=transactionStatus" json:"transaction_status,omitempty"`
 }
 
 func (m *BlockHeader) Reset()                    { *m = BlockHeader{} }
@@ -297,13 +296,6 @@ func (m *BlockHeader) GetVersion() uint64 {
        return 0
 }
 
-func (m *BlockHeader) GetSerializedSize() uint64 {
-       if m != nil {
-               return m.SerializedSize
-       }
-       return 0
-}
-
 func (m *BlockHeader) GetHeight() uint64 {
        if m != nil {
                return m.Height
@@ -799,67 +791,67 @@ func init() {
 func init() { proto.RegisterFile("bc.proto", fileDescriptor0) }
 
 var fileDescriptor0 = []byte{
-       // 984 bytes of a gzipped FileDescriptorProto
-       0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xcd, 0x6e, 0xdb, 0x46,
-       0x10, 0x06, 0x45, 0x4a, 0xa4, 0xc6, 0xae, 0x25, 0xad, 0x9d, 0x94, 0x08, 0x12, 0xc0, 0x60, 0xe1,
-       0x3a, 0x45, 0x00, 0xc3, 0xb1, 0xd3, 0xa2, 0x87, 0x1e, 0xea, 0xd6, 0x6d, 0xa3, 0x83, 0xdb, 0x82,
-       0x0e, 0x72, 0x25, 0x56, 0xe4, 0xc6, 0x5a, 0x54, 0xe2, 0xaa, 0xbb, 0x4b, 0xd5, 0xf5, 0x63, 0xf4,
-       0xda, 0x73, 0x5f, 0xa0, 0xc7, 0x9e, 0xf3, 0x10, 0x7d, 0x8e, 0x3e, 0x41, 0xc1, 0xe1, 0x92, 0xa2,
-       0xfe, 0x12, 0x09, 0x49, 0x6e, 0x9c, 0x1f, 0xce, 0xcf, 0x37, 0xf3, 0xed, 0x2e, 0x78, 0x83, 0xf8,
-       0x64, 0x22, 0x85, 0x16, 0xa4, 0x31, 0x88, 0x83, 0xef, 0xc1, 0x79, 0x4e, 0xd5, 0x90, 0xec, 0x41,
-       0x63, 0x7a, 0xea, 0x5b, 0x87, 0xd6, 0xe3, 0x56, 0xd8, 0x98, 0x9e, 0xa2, 0xfc, 0xd4, 0x6f, 0x18,
-       0xf9, 0x29, 0xca, 0x67, 0xbe, 0x6d, 0xe4, 0x33, 0x94, 0xcf, 0x7d, 0xc7, 0xc8, 0xe7, 0xc1, 0x57,
-       0xe0, 0xfe, 0x2c, 0xc5, 0x8d, 0xa4, 0x63, 0xf2, 0x08, 0x60, 0x3a, 0x8e, 0xa6, 0x4c, 0x2a, 0x2e,
-       0x52, 0x0c, 0xe9, 0x84, 0xed, 0xe9, 0xf8, 0x65, 0xa1, 0x20, 0x04, 0x9c, 0x58, 0x24, 0x0c, 0x63,
-       0xef, 0x86, 0xf8, 0x1d, 0xf4, 0xc1, 0xbd, 0x50, 0x8a, 0xe9, 0xfe, 0xe5, 0x3b, 0x17, 0x72, 0x05,
-       0x3b, 0x18, 0xea, 0x62, 0x2c, 0xb2, 0x54, 0x93, 0x4f, 0xc1, 0xa3, 0xb9, 0x18, 0xf1, 0x04, 0x83,
-       0xee, 0x9c, 0xed, 0x9c, 0x0c, 0xe2, 0x13, 0x93, 0x2d, 0x74, 0xd1, 0xd8, 0x4f, 0xc8, 0x7d, 0x68,
-       0x51, 0xfc, 0x03, 0x53, 0x39, 0xa1, 0x91, 0x82, 0x3f, 0x2d, 0xe8, 0xa0, 0xf3, 0x25, 0x7b, 0xc5,
-       0x53, 0xae, 0xf3, 0x0e, 0xce, 0xa0, 0x8b, 0x9f, 0x74, 0x14, 0x0d, 0x46, 0x22, 0xfe, 0x65, 0x16,
-       0xdb, 0xcb, 0x63, 0xe7, 0x78, 0x86, 0x7b, 0xc6, 0xe3, 0x9b, 0xdc, 0xa1, 0x9f, 0x90, 0x2f, 0xa0,
-       0xcb, 0x95, 0xca, 0x68, 0x1a, 0xb3, 0x68, 0x52, 0x00, 0x85, 0x99, 0x4c, 0x3d, 0x06, 0xbb, 0xb0,
-       0x53, 0x3a, 0x95, 0x60, 0x3e, 0x04, 0x27, 0xa1, 0x9a, 0x62, 0xc3, 0xf5, 0xf8, 0xa8, 0x0d, 0x46,
-       0xb0, 0xf3, 0x92, 0x8e, 0x32, 0x76, 0x2d, 0x32, 0x19, 0x33, 0xf2, 0x00, 0x6c, 0xc9, 0x5e, 0x2d,
-       0xd5, 0x92, 0x2b, 0xc9, 0x11, 0x34, 0xa7, 0xb9, 0xab, 0xc9, 0xda, 0xa9, 0x50, 0x28, 0x80, 0x0a,
-       0x0b, 0x2b, 0x79, 0x00, 0xde, 0x44, 0x28, 0xec, 0x13, 0x73, 0x3a, 0x61, 0x25, 0x07, 0xbf, 0x42,
-       0x17, 0xb3, 0x5d, 0x32, 0xa5, 0x79, 0x4a, 0x11, 0x8b, 0x0f, 0x9c, 0xf2, 0x2f, 0x1b, 0x76, 0x10,
-       0xc2, 0xe7, 0x8c, 0x26, 0x4c, 0x12, 0x1f, 0xdc, 0xf9, 0xc5, 0x2a, 0x45, 0x72, 0x0c, 0x1d, 0xc5,
-       0x24, 0xa7, 0x23, 0x7e, 0xc7, 0x92, 0x48, 0xf1, 0x3b, 0x66, 0x26, 0xb9, 0x37, 0x53, 0x5f, 0xf3,
-       0x3b, 0x96, 0x4f, 0x7a, 0xc8, 0xf8, 0xcd, 0x50, 0x9b, 0x64, 0x46, 0x22, 0xcf, 0xa0, 0x37, 0x91,
-       0x6c, 0xca, 0x45, 0xa6, 0x66, 0x63, 0x75, 0x16, 0xfa, 0xea, 0x94, 0x2e, 0xe5, 0x5c, 0x1f, 0x42,
-       0x5b, 0xf3, 0x31, 0x53, 0x9a, 0x8e, 0x27, 0x7e, 0xb3, 0xd8, 0xf5, 0x4a, 0x41, 0x3e, 0x87, 0x9e,
-       0x96, 0x34, 0x55, 0x34, 0xce, 0xbb, 0x51, 0x91, 0x14, 0x42, 0xfb, 0xad, 0x85, 0x98, 0xdd, 0xba,
-       0x4b, 0x28, 0x84, 0x26, 0x5f, 0xc3, 0xc7, 0x35, 0x5d, 0xa4, 0x34, 0xd5, 0x99, 0x8a, 0x86, 0x54,
-       0x0d, 0x7d, 0x77, 0xe1, 0xe7, 0x7b, 0x35, 0xc7, 0x6b, 0xf4, 0x43, 0x3a, 0x1f, 0x40, 0x33, 0x15,
-       0x69, 0xcc, 0x7c, 0x0f, 0x4b, 0x2a, 0x84, 0x9c, 0x7a, 0x03, 0xae, 0x95, 0xdf, 0x46, 0x25, 0x7e,
-       0x93, 0x4b, 0x20, 0xcb, 0xb9, 0x7c, 0xc0, 0x34, 0xf7, 0xf2, 0x34, 0x2f, 0x16, 0x13, 0x84, 0xbd,
-       0xa5, 0x9c, 0xc1, 0xbf, 0x16, 0x78, 0x2f, 0x6e, 0xdf, 0xdf, 0x90, 0x1e, 0x01, 0xe4, 0x28, 0x46,
-       0x92, 0xa6, 0x37, 0xcc, 0x0c, 0x0a, 0x71, 0x0d, 0x73, 0x05, 0x39, 0x06, 0x90, 0x4c, 0x65, 0xa3,
-       0x9c, 0xd6, 0xca, 0x77, 0x0e, 0xed, 0x39, 0x4c, 0xda, 0x85, 0xad, 0x9f, 0xa8, 0x8a, 0x3e, 0xcd,
-       0x55, 0xf4, 0x21, 0x9f, 0x80, 0xc7, 0x6e, 0x75, 0x01, 0xec, 0xe2, 0x54, 0x5c, 0x76, 0xab, 0xf3,
-       0x8f, 0xe0, 0x09, 0xf4, 0x96, 0x20, 0xc8, 0x97, 0x68, 0xc0, 0xf5, 0x98, 0x4e, 0xb0, 0xc3, 0xdd,
-       0xd0, 0x48, 0xc1, 0x7f, 0x16, 0xd8, 0x57, 0xd9, 0x2d, 0xf9, 0x0c, 0x5c, 0x85, 0x9c, 0x54, 0xbe,
-       0x85, 0xd5, 0xe1, 0xf2, 0xd7, 0xb8, 0x1a, 0x96, 0x76, 0x72, 0x04, 0xee, 0x1b, 0x0e, 0x84, 0xd2,
-       0x36, 0x57, 0xab, 0xbd, 0xa6, 0x56, 0xf2, 0x03, 0x1c, 0xfc, 0xc6, 0x75, 0xca, 0x94, 0x8a, 0x92,
-       0x19, 0x49, 0x4b, 0x84, 0x0e, 0xaa, 0x1a, 0x6a, 0x0c, 0x0e, 0xf7, 0xcd, 0x1f, 0x35, 0x9d, 0x22,
-       0x4f, 0xa0, 0x57, 0x06, 0xa2, 0xf2, 0x26, 0x1b, 0xb3, 0x54, 0x2b, 0xbf, 0x79, 0x68, 0x3f, 0xde,
-       0x0d, 0xbb, 0xc6, 0x70, 0x51, 0xea, 0x83, 0x7f, 0x2c, 0x68, 0xfe, 0x88, 0x0b, 0x56, 0xeb, 0xc5,
-       0xda, 0xb0, 0x97, 0xc6, 0xba, 0x5e, 0x56, 0x96, 0x60, 0xaf, 0x2e, 0x81, 0x7c, 0x09, 0xfb, 0x95,
-       0x73, 0x1a, 0x0f, 0x85, 0x64, 0xc9, 0x2a, 0xfa, 0x96, 0x11, 0x2f, 0x8c, 0x4f, 0x3f, 0x09, 0x04,
-       0x78, 0xdf, 0x0a, 0x9e, 0x0e, 0xa8, 0x62, 0xe4, 0xbb, 0x59, 0x94, 0x1a, 0x7c, 0xa6, 0x95, 0xd5,
-       0xe8, 0x91, 0x65, 0xf4, 0xf2, 0x33, 0x81, 0xca, 0x01, 0xd7, 0x92, 0xca, 0xdf, 0xcd, 0x35, 0x37,
-       0x53, 0x04, 0xaf, 0x2d, 0x68, 0xfd, 0x94, 0xe9, 0x49, 0xa6, 0xc9, 0x31, 0xb4, 0x8a, 0x2d, 0x30,
-       0x29, 0x96, 0x96, 0xc4, 0x98, 0xc9, 0x33, 0xe8, 0xc4, 0x22, 0xd5, 0x52, 0x8c, 0xde, 0x74, 0x79,
-       0xec, 0x19, 0x9f, 0x8d, 0xee, 0x8e, 0xb9, 0x21, 0x38, 0xeb, 0x86, 0xe0, 0x83, 0x2b, 0x64, 0xc2,
-       0x53, 0x3a, 0x32, 0x87, 0x5b, 0x29, 0x06, 0x7f, 0x58, 0x00, 0x21, 0xd3, 0x5c, 0xb2, 0x7c, 0x02,
-       0x9b, 0xb7, 0x52, 0x16, 0xd5, 0x78, 0x6b, 0x51, 0xf6, 0x06, 0x45, 0x39, 0xf3, 0x45, 0xfd, 0x6d,
-       0x83, 0xd7, 0x37, 0x37, 0x28, 0x39, 0x82, 0x76, 0xb1, 0x0b, 0xab, 0xee, 0x67, 0xaf, 0x30, 0xf5,
-       0x93, 0x4d, 0x6f, 0xa9, 0xf7, 0x00, 0xe6, 0x9a, 0xf5, 0x6a, 0x6e, 0xb9, 0x5e, 0x57, 0xe0, 0x57,
-       0xbb, 0x8e, 0x4f, 0x9b, 0xa4, 0x7a, 0x9a, 0x98, 0x53, 0x6c, 0xbf, 0xea, 0x61, 0xf6, 0x6a, 0x09,
-       0xef, 0x97, 0xbb, 0xbf, 0xf0, 0x9a, 0x59, 0xc9, 0x33, 0x77, 0x3b, 0x9e, 0x79, 0x6f, 0xe5, 0x59,
-       0x7d, 0x68, 0xed, 0xf9, 0xa1, 0xbd, 0x6e, 0x40, 0xf3, 0x7a, 0xc2, 0xd2, 0x84, 0x9c, 0x42, 0x47,
-       0x4d, 0x58, 0xaa, 0x23, 0x81, 0xfc, 0x58, 0x35, 0xb7, 0x8f, 0xd0, 0xa1, 0xe0, 0x0f, 0x5e, 0xbf,
-       0xef, 0xbc, 0x4d, 0x6b, 0xa6, 0xe2, 0x6c, 0x39, 0x95, 0x6d, 0x4e, 0xcc, 0x75, 0x30, 0xb6, 0xb6,
-       0x82, 0xd1, 0x9d, 0x83, 0x71, 0xd0, 0xc2, 0x47, 0xfd, 0xf9, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff,
-       0xd9, 0xb1, 0xcb, 0x7e, 0xe0, 0x0b, 0x00, 0x00,
+       // 983 bytes of a gzipped FileDescriptorProto
+       0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0x4f, 0x6f, 0x1b, 0x45,
+       0x14, 0xd7, 0xda, 0x6b, 0xef, 0xfa, 0x25, 0xc4, 0xc9, 0x24, 0x2d, 0xab, 0xaa, 0x48, 0xd1, 0xa2,
+       0x90, 0xa2, 0x4a, 0x51, 0x9a, 0x14, 0xc4, 0x81, 0x03, 0x81, 0x00, 0xf5, 0x21, 0x80, 0x26, 0x55,
+       0xaf, 0xab, 0xf1, 0xee, 0x34, 0x1e, 0x61, 0xef, 0x98, 0x99, 0x59, 0x13, 0xf2, 0x31, 0xb8, 0xf2,
+       0x2d, 0x38, 0x72, 0xee, 0x87, 0xe0, 0x73, 0x70, 0xe6, 0x80, 0xe6, 0xed, 0xac, 0xbd, 0xfe, 0xd7,
+       0x24, 0x2a, 0xbd, 0xed, 0xfb, 0xb3, 0xef, 0xcf, 0xef, 0xbd, 0xdf, 0xcc, 0x40, 0xd8, 0x4f, 0x8f,
+       0xc6, 0x4a, 0x1a, 0x49, 0x1a, 0xfd, 0x34, 0xfe, 0x0e, 0xfc, 0x17, 0x4c, 0x0f, 0xc8, 0x16, 0x34,
+       0x26, 0xc7, 0x91, 0xb7, 0xef, 0x3d, 0x69, 0xd3, 0xc6, 0xe4, 0x18, 0xe5, 0x67, 0x51, 0xc3, 0xc9,
+       0xcf, 0x50, 0x3e, 0x89, 0x9a, 0x4e, 0x3e, 0x41, 0xf9, 0x34, 0xf2, 0x9d, 0x7c, 0x1a, 0x7f, 0x09,
+       0xc1, 0x4f, 0x4a, 0x5e, 0x29, 0x36, 0x22, 0x1f, 0x01, 0x4c, 0x46, 0xc9, 0x84, 0x2b, 0x2d, 0x64,
+       0x8e, 0x21, 0x7d, 0xda, 0x99, 0x8c, 0x5e, 0x95, 0x0a, 0x42, 0xc0, 0x4f, 0x65, 0xc6, 0x31, 0xf6,
+       0x26, 0xc5, 0xef, 0xb8, 0x07, 0xc1, 0x99, 0xd6, 0xdc, 0xf4, 0xce, 0xdf, 0xb9, 0x90, 0x0b, 0xd8,
+       0xc0, 0x50, 0x67, 0x23, 0x59, 0xe4, 0x86, 0x7c, 0x02, 0x21, 0xb3, 0x62, 0x22, 0x32, 0x0c, 0xba,
+       0x71, 0xb2, 0x71, 0xd4, 0x4f, 0x8f, 0x5c, 0x36, 0x1a, 0xa0, 0xb1, 0x97, 0x91, 0x87, 0xd0, 0x66,
+       0xf8, 0x07, 0xa6, 0xf2, 0xa9, 0x93, 0xe2, 0x3f, 0x3c, 0xe8, 0xa2, 0xf3, 0x39, 0x7f, 0x2d, 0x72,
+       0x61, 0x6c, 0x07, 0x27, 0xb0, 0x8d, 0x9f, 0x6c, 0x98, 0xf4, 0x87, 0x32, 0xfd, 0x79, 0x16, 0x3b,
+       0xb4, 0xb1, 0x2d, 0x9e, 0x74, 0xcb, 0x79, 0x7c, 0x6d, 0x1d, 0x7a, 0x19, 0xf9, 0x1c, 0xb6, 0x85,
+       0xd6, 0x05, 0xcb, 0x53, 0x9e, 0x8c, 0x4b, 0xa0, 0x30, 0x93, 0xab, 0xc7, 0x61, 0x47, 0xbb, 0x95,
+       0x53, 0x05, 0xe6, 0x63, 0xf0, 0x33, 0x66, 0x18, 0x36, 0x5c, 0x8f, 0x8f, 0xda, 0x78, 0x08, 0x1b,
+       0xaf, 0xd8, 0xb0, 0xe0, 0x97, 0xb2, 0x50, 0x29, 0x27, 0x8f, 0xa0, 0xa9, 0xf8, 0xeb, 0xa5, 0x5a,
+       0xac, 0x92, 0x1c, 0x40, 0x6b, 0x62, 0x5d, 0x5d, 0xd6, 0xee, 0x14, 0x85, 0x12, 0x28, 0x5a, 0x5a,
+       0xc9, 0x23, 0x08, 0xc7, 0x52, 0x63, 0x9f, 0x98, 0xd3, 0xa7, 0x53, 0x39, 0xfe, 0x05, 0xb6, 0x31,
+       0xdb, 0x39, 0xd7, 0x46, 0xe4, 0x0c, 0xb1, 0x78, 0xcf, 0x29, 0xff, 0x6d, 0xc0, 0x06, 0x42, 0xf8,
+       0x82, 0xb3, 0x8c, 0x2b, 0x12, 0x41, 0x30, 0xbf, 0x58, 0x95, 0x68, 0x07, 0x38, 0xe0, 0xe2, 0x6a,
+       0x30, 0x1d, 0x60, 0x29, 0x91, 0xe7, 0xb0, 0x33, 0x56, 0x7c, 0x22, 0x64, 0xa1, 0x67, 0xd3, 0x5a,
+       0x44, 0xb3, 0x5b, 0xb9, 0x54, 0xe3, 0x7a, 0x0c, 0x1d, 0x23, 0x46, 0x5c, 0x1b, 0x36, 0x1a, 0xe3,
+       0x72, 0xf9, 0x74, 0xa6, 0x20, 0x9f, 0xc1, 0x8e, 0x51, 0x2c, 0xd7, 0x2c, 0xb5, 0x45, 0xea, 0x44,
+       0x49, 0x69, 0xa2, 0xd6, 0x42, 0xcc, 0xed, 0xba, 0x0b, 0x95, 0xd2, 0x90, 0xaf, 0xe0, 0xc3, 0x9a,
+       0x2e, 0xd1, 0x86, 0x99, 0x42, 0x27, 0x03, 0xa6, 0x07, 0x51, 0x7b, 0xe1, 0xe7, 0x07, 0x35, 0xc7,
+       0x4b, 0xf4, 0x43, 0x96, 0xee, 0x41, 0x2b, 0x97, 0x79, 0xca, 0xa3, 0x00, 0x4b, 0x2a, 0x05, 0xcb,
+       0xa8, 0xbe, 0x30, 0x3a, 0x0a, 0x51, 0x89, 0xdf, 0xe4, 0x1c, 0xc8, 0x72, 0xae, 0xa8, 0x83, 0x69,
+       0x1e, 0xd8, 0x34, 0x2f, 0x17, 0x13, 0xd0, 0x9d, 0xa5, 0x9c, 0xf1, 0xdf, 0x1e, 0x84, 0x2f, 0xaf,
+       0x6f, 0xc5, 0xfe, 0x10, 0xba, 0x9a, 0x2b, 0xc1, 0x86, 0xe2, 0x86, 0x67, 0x89, 0x16, 0x37, 0xdc,
+       0x0d, 0x61, 0x6b, 0xa6, 0xbe, 0x14, 0x37, 0xdc, 0x1e, 0x0d, 0x16, 0xc5, 0x44, 0xb1, 0xfc, 0x8a,
+       0xbb, 0x61, 0x23, 0xae, 0xd4, 0x2a, 0xc8, 0x21, 0x80, 0xe2, 0xba, 0x18, 0x5a, 0xb6, 0xea, 0xc8,
+       0xdf, 0x6f, 0xce, 0x61, 0xd2, 0x29, 0x6d, 0xbd, 0x4c, 0x4f, 0x59, 0xd1, 0x5a, 0xc5, 0x0a, 0xf2,
+       0x31, 0x84, 0xfc, 0xda, 0xac, 0x06, 0x36, 0xe0, 0xd7, 0xc6, 0x7e, 0xc4, 0x4f, 0x61, 0x67, 0x09,
+       0x02, 0xbb, 0x44, 0x7d, 0x61, 0x46, 0x6c, 0x8c, 0x1d, 0x6e, 0x52, 0x27, 0xc5, 0xff, 0x78, 0xd0,
+       0xbc, 0x28, 0xae, 0xc9, 0xa7, 0x10, 0x68, 0xa4, 0x9a, 0x8e, 0x3c, 0xac, 0x0e, 0x77, 0xba, 0x46,
+       0x41, 0x5a, 0xd9, 0xc9, 0x01, 0x04, 0x6f, 0xe1, 0x79, 0x65, 0x9b, 0xab, 0xb5, 0xb9, 0xa6, 0x56,
+       0xf2, 0x3d, 0xec, 0xfd, 0x2a, 0x4c, 0xce, 0xb5, 0x4e, 0xb2, 0x19, 0xf7, 0x2a, 0x84, 0xf6, 0xa6,
+       0x35, 0xd4, 0x88, 0x49, 0x77, 0xdd, 0x1f, 0x35, 0x9d, 0x26, 0x4f, 0x61, 0xa7, 0x0a, 0xc4, 0xd4,
+       0x55, 0x31, 0xe2, 0xb9, 0xd1, 0x51, 0x6b, 0xbf, 0xf9, 0x64, 0x93, 0x6e, 0x3b, 0xc3, 0x59, 0xa5,
+       0x8f, 0xff, 0xf2, 0xa0, 0xf5, 0x03, 0x2e, 0x58, 0xad, 0x17, 0xef, 0x8e, 0xbd, 0x34, 0xd6, 0xf5,
+       0xb2, 0xb2, 0x84, 0xe6, 0xea, 0x12, 0xc8, 0x17, 0xb0, 0x3b, 0x75, 0xce, 0xd3, 0x81, 0x54, 0x3c,
+       0xb3, 0xf4, 0xf5, 0x17, 0x82, 0x57, 0x11, 0xcf, 0x9c, 0x4f, 0x2f, 0x8b, 0x25, 0x84, 0xdf, 0x48,
+       0x91, 0xf7, 0x99, 0xe6, 0xe4, 0xdb, 0x59, 0x94, 0x1a, 0x7c, 0xae, 0x95, 0xd5, 0xe8, 0x91, 0x65,
+       0xf4, 0xec, 0x99, 0xc0, 0x54, 0x5f, 0x18, 0xc5, 0xd4, 0x6f, 0xee, 0xf6, 0x9a, 0x29, 0xe2, 0x37,
+       0x1e, 0xb4, 0x7f, 0x2c, 0xcc, 0xb8, 0x30, 0xe4, 0x10, 0xda, 0xe5, 0x16, 0xb8, 0x14, 0x4b, 0x4b,
+       0xe2, 0xcc, 0xe4, 0x39, 0x74, 0x53, 0x99, 0x1b, 0x25, 0x87, 0x6f, 0xbb, 0x13, 0xb6, 0x9c, 0xcf,
+       0x9d, 0xae, 0x84, 0xb9, 0x21, 0xf8, 0xeb, 0x86, 0x10, 0x41, 0x20, 0x55, 0x26, 0x72, 0x36, 0x44,
+       0x0a, 0xf9, 0xb4, 0x12, 0xe3, 0xdf, 0x3d, 0x00, 0xca, 0x8d, 0x50, 0xdc, 0x4e, 0xe0, 0xee, 0xad,
+       0x54, 0x45, 0x35, 0x6e, 0x2d, 0xaa, 0x79, 0x87, 0xa2, 0xfc, 0xf9, 0xa2, 0xfe, 0x6c, 0x42, 0xd8,
+       0x73, 0x17, 0x23, 0x39, 0x80, 0x4e, 0xb9, 0x0b, 0xab, 0xae, 0xdd, 0xb0, 0x34, 0xf5, 0xb2, 0xbb,
+       0x5e, 0x3e, 0xff, 0x03, 0x98, 0x6b, 0xd6, 0xab, 0x75, 0xcf, 0xf5, 0xba, 0x80, 0x68, 0xba, 0xeb,
+       0xf8, 0x62, 0xc9, 0xa6, 0x2f, 0x0e, 0x77, 0x8a, 0xed, 0x4e, 0x7b, 0x98, 0x3d, 0x46, 0xe8, 0xc3,
+       0x6a, 0xf7, 0x17, 0x1e, 0x29, 0x2b, 0x79, 0x16, 0xdc, 0x8f, 0x67, 0xe1, 0xad, 0x3c, 0xab, 0x0f,
+       0xad, 0x33, 0x3f, 0xb4, 0x37, 0x0d, 0x68, 0x5d, 0x8e, 0x79, 0x9e, 0x91, 0x63, 0xe8, 0xea, 0x31,
+       0xcf, 0x4d, 0x22, 0x91, 0x1f, 0xab, 0xe6, 0xf6, 0x01, 0x3a, 0x94, 0xfc, 0xc1, 0xeb, 0xf7, 0x9d,
+       0xb7, 0x69, 0xcd, 0x54, 0xfc, 0x7b, 0x4e, 0xe5, 0x3e, 0x27, 0xe6, 0x3a, 0x18, 0xdb, 0xf7, 0x82,
+       0x31, 0x98, 0x83, 0xb1, 0xdf, 0xc6, 0xb7, 0xfa, 0xe9, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbc,
+       0x0c, 0xd7, 0x36, 0xb7, 0x0b, 0x00, 0x00,
 }
index 74c6dc9..35ff765 100644 (file)
@@ -51,15 +51,14 @@ message ValueDestination {
 
 message BlockHeader {
   uint64            version                 = 1;
-  uint64            serialized_size         = 2;
-  uint64            height                  = 3;
-  Hash              previous_block_id       = 4;
-  uint64            timestamp               = 5;
-  Hash              transactions_root       = 6;
-  Hash              transaction_status_hash = 7;
-  uint64            nonce                   = 8;
-  uint64            bits                    = 9;
-  TransactionStatus transaction_status      = 10;
+  uint64            height                  = 2;
+  Hash              previous_block_id       = 3;
+  uint64            timestamp               = 4;
+  Hash              transactions_root       = 5;
+  Hash              transaction_status_hash = 6;
+  uint64            nonce                   = 7;
+  uint64            bits                    = 8;
+  TransactionStatus transaction_status      = 9;
 }
 
 message TxHeader {
index 4d165d9..81b4581 100644 (file)
@@ -255,7 +255,6 @@ func MapBlock(old *Block) *bc.Block {
        b.ID, b.BlockHeader = mapBlockHeader(&old.BlockHeader)
        for _, oldTx := range old.Transactions {
                b.Transactions = append(b.Transactions, oldTx.Tx)
-               b.BlockHeader.SerializedSize += oldTx.TxData.SerializedSize
        }
        return b
 }
index 00721ba..f833426 100644 (file)
@@ -33,15 +33,15 @@ func (c *Chain) ValidateTx(tx *legacy.Tx) error {
 
        // validate the BVM contract
        gasOnlyTx := false
-       fee, gasVaild, err := validation.ValidateTx(newTx, block)
+       gasStatus, err := validation.ValidateTx(newTx, block)
        if err != nil {
-               if !gasVaild {
+               if !gasStatus.GasVaild {
                        c.txPool.AddErrCache(&newTx.ID, err)
                        return err
                }
                gasOnlyTx = true
        }
 
-       _, err = c.txPool.AddTransaction(tx, gasOnlyTx, block.BlockHeader.Height, fee)
+       _, err = c.txPool.AddTransaction(tx, gasOnlyTx, block.BlockHeader.Height, gasStatus.BTMValue)
        return err
 }
index e03bc30..bd44003 100644 (file)
@@ -13,46 +13,71 @@ import (
        "github.com/bytom/protocol/vm"
 )
 
-const (
-       defaultGasLimit = int64(80000)
-       muxGasCost      = int64(10)
-       // GasRate indicates the current gas rate
-       GasRate = int64(1000)
-)
-
-type gasState struct {
-       gasLeft  int64
-       gasUsed  int64
-       BTMValue int64
+const muxGasCost = int64(10)
+
+type GasState struct {
+       BTMValue   uint64
+       GasLeft    int64
+       GasUsed    int64
+       GasVaild   bool
+       storageGas int64
 }
 
-func (g *gasState) setGas(BTMValue int64) error {
+func (g *GasState) setGas(BTMValue int64, txSize int64) error {
        if BTMValue < 0 {
-               return errGasCalculate
+               return errors.Wrap(errGasCalculate, "input BTM is negative")
        }
-       g.BTMValue = BTMValue
 
-       if gasAmount, ok := checked.DivInt64(BTMValue, GasRate); ok {
-               if gasAmount == 0 {
-                       g.gasLeft = muxGasCost
-               } else if gasAmount < defaultGasLimit {
-                       g.gasLeft = gasAmount
-               }
-       } else {
-               return errGasCalculate
+       g.BTMValue = uint64(BTMValue)
+
+       if BTMValue == 0 {
+               g.GasLeft = muxGasCost
+               return nil
+       }
+
+       var ok bool
+       if g.GasLeft, ok = checked.DivInt64(BTMValue, consensus.VMGasRate); !ok {
+               return errors.Wrap(errGasCalculate, "setGas calc gas amount")
+       }
+
+       if g.GasLeft > consensus.MaxGasAmount {
+               g.GasLeft = consensus.MaxGasAmount
+       }
+
+       if g.storageGas, ok = checked.MulInt64(txSize, consensus.StorageGasRate); !ok {
+               return errors.Wrap(errGasCalculate, "setGas calc tx storage gas")
+       }
+       return nil
+}
+
+func (g *GasState) setGasVaild() error {
+       var ok bool
+       if g.GasLeft, ok = checked.SubInt64(g.GasLeft, g.storageGas); !ok || g.GasLeft < 0 {
+               return errors.Wrap(errGasCalculate, "setGasVaild calc gasLeft")
        }
+
+       if g.GasUsed, ok = checked.AddInt64(g.GasUsed, g.storageGas); !ok {
+               return errors.Wrap(errGasCalculate, "setGasVaild calc gasUsed")
+       }
+
+       g.GasVaild = true
        return nil
 }
 
-func (g *gasState) updateUsage(gasLeft int64) error {
+func (g *GasState) updateUsage(gasLeft int64) error {
        if gasLeft < 0 {
-               return errGasCalculate
+               return errors.Wrap(errGasCalculate, "updateUsage input negative gas")
        }
-       if gasUsed, ok := checked.SubInt64(g.gasLeft, gasLeft); ok {
-               g.gasUsed += gasUsed
-               g.gasLeft = gasLeft
+
+       if gasUsed, ok := checked.SubInt64(g.GasLeft, gasLeft); ok {
+               g.GasUsed += gasUsed
+               g.GasLeft = gasLeft
        } else {
-               return errGasCalculate
+               return errors.Wrap(errGasCalculate, "updateUsage calc gas diff")
+       }
+
+       if !g.GasVaild && (g.GasUsed > consensus.DefaultGasCredit || g.storageGas > g.GasLeft) {
+               return errOverGasCredit
        }
        return nil
 }
@@ -78,9 +103,7 @@ type validationState struct {
        // Memoized per-entry validation results
        cache map[bc.Hash]error
 
-       gas *gasState
-
-       gasVaild *int
+       gasStatus *GasState
 }
 
 var (
@@ -102,6 +125,8 @@ var (
        errNoSource                 = errors.New("no source for value")
        errNonemptyExtHash          = errors.New("non-empty extension hash")
        errOverflow                 = errors.New("arithmetic overflow/underflow")
+       errOverGasCredit            = errors.New("all gas credit has been spend")
+       errOverBlockLimit           = errors.New("block's gas is over the limit")
        errPosition                 = errors.New("invalid source or destination position")
        errWorkProof                = errors.New("invalid difficulty proof of work")
        errTxVersion                = errors.New("invalid transaction version")
@@ -109,7 +134,7 @@ var (
        errUntimelyTransaction      = errors.New("block timestamp outside transaction time range")
        errVersionRegression        = errors.New("version regression")
        errWrongBlockSize           = errors.New("block size is too big")
-       errWrongTransactionSize     = errors.New("transaction size is too big")
+       errWrongTransactionSize     = errors.New("transaction size is not in vaild range")
        errWrongTransactionStatus   = errors.New("transaction status is wrong")
        errWrongCoinbaseTransaction = errors.New("wrong coinbase transaction")
        errWrongCoinbaseAsset       = errors.New("wrong coinbase asset id")
@@ -189,25 +214,21 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
                        parity[*dest.Value.AssetId] = diff
                }
 
-               if amount, ok := parity[*consensus.BTMAssetID]; ok {
-                       if err = vs.gas.setGas(amount); err != nil {
-                               return err
-                       }
-               } else {
-                       vs.gas.setGas(0)
-               }
-
                for assetID, amount := range parity {
-                       if amount != 0 && assetID != *consensus.BTMAssetID {
+                       if assetID == *consensus.BTMAssetID {
+                               if err = vs.gasStatus.setGas(amount, int64(vs.tx.SerializedSize)); err != nil {
+                                       return err
+                               }
+                       } else if amount != 0 {
                                return errors.WithDetailf(errUnbalanced, "asset %x sources - destinations = %d (should be 0)", assetID.Bytes(), amount)
                        }
                }
 
-               gasLeft, err := vm.Verify(NewTxVMContext(vs, e, e.Program, e.WitnessArguments), vs.gas.gasLeft)
+               gasLeft, err := vm.Verify(NewTxVMContext(vs, e, e.Program, e.WitnessArguments), vs.gasStatus.GasLeft)
                if err != nil {
                        return errors.Wrap(err, "checking mux program")
                }
-               if err = vs.gas.updateUsage(gasLeft); err != nil {
+               if err = vs.gasStatus.updateUsage(gasLeft); err != nil {
                        return err
                }
 
@@ -236,7 +257,10 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
                if vs.tx.Version == 1 && e.ExtHash != nil && !e.ExtHash.IsZero() {
                        return errNonemptyExtHash
                }
-               *vs.gasVaild = 1
+
+               if err := vs.gasStatus.setGasVaild(); err != nil {
+                       return err
+               }
 
                for i, src := range e.Sources {
                        vs2 := *vs
@@ -249,11 +273,11 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
 
        case *bc.Nonce:
                //TODO: add block heigh range check on the control program
-               gasLeft, err := vm.Verify(NewTxVMContext(vs, e, e.Program, e.WitnessArguments), vs.gas.gasLeft)
+               gasLeft, err := vm.Verify(NewTxVMContext(vs, e, e.Program, e.WitnessArguments), vs.gasStatus.GasLeft)
                if err != nil {
                        return errors.Wrap(err, "checking nonce program")
                }
-               if err = vs.gas.updateUsage(gasLeft); err != nil {
+               if err = vs.gasStatus.updateUsage(gasLeft); err != nil {
                        return err
                }
 
@@ -296,11 +320,11 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
                        return errors.Wrapf(bc.ErrMissingEntry, "entry for issuance anchor %x not found", e.AnchorId.Bytes())
                }
 
-               gasLeft, err := vm.Verify(NewTxVMContext(vs, e, e.WitnessAssetDefinition.IssuanceProgram, e.WitnessArguments), vs.gas.gasLeft)
+               gasLeft, err := vm.Verify(NewTxVMContext(vs, e, e.WitnessAssetDefinition.IssuanceProgram, e.WitnessArguments), vs.gasStatus.GasLeft)
                if err != nil {
                        return errors.Wrap(err, "checking issuance program")
                }
-               if err = vs.gas.updateUsage(gasLeft); err != nil {
+               if err = vs.gasStatus.updateUsage(gasLeft); err != nil {
                        return err
                }
 
@@ -349,11 +373,11 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
                if err != nil {
                        return errors.Wrap(err, "getting spend prevout")
                }
-               gasLeft, err := vm.Verify(NewTxVMContext(vs, e, spentOutput.ControlProgram, e.WitnessArguments), vs.gas.gasLeft)
+               gasLeft, err := vm.Verify(NewTxVMContext(vs, e, spentOutput.ControlProgram, e.WitnessArguments), vs.gasStatus.GasLeft)
                if err != nil {
                        return errors.Wrap(err, "checking control program")
                }
-               if err = vs.gas.updateUsage(gasLeft); err != nil {
+               if err = vs.gasStatus.updateUsage(gasLeft); err != nil {
                        return err
                }
 
@@ -534,16 +558,13 @@ func ValidateBlock(b, prev *bc.Block) error {
                return errBadTimestamp
        }
 
-       if b.BlockHeader.SerializedSize > consensus.MaxBlockSzie {
-               return errWrongBlockSize
-       }
-
        if !difficulty.CheckProofOfWork(&b.ID, b.BlockHeader.Bits) {
                return errWorkProof
        }
 
        b.TransactionStatus = bc.NewTransactionStatus()
        coinbaseValue := consensus.BlockSubsidy(b.BlockHeader.Height)
+       gasUsed := uint64(0)
        for i, tx := range b.Transactions {
                if b.Version == 1 && tx.Version != 1 {
                        return errors.WithDetailf(errTxVersion, "block version %d, transaction version %d", b.Version, tx.Version)
@@ -551,16 +572,21 @@ func ValidateBlock(b, prev *bc.Block) error {
                if tx.TimeRange > b.Timestamp {
                        return errors.New("invalid transaction time range")
                }
-               txBTMValue, gasVaild, err := ValidateTx(tx, b)
+               gasStatus, err := ValidateTx(tx, b)
                gasOnlyTx := false
                if err != nil {
-                       if !gasVaild {
+                       if gasStatus == nil || !gasStatus.GasVaild {
                                return errors.Wrapf(err, "validity of transaction %d of %d", i, len(b.Transactions))
                        }
                        gasOnlyTx = true
                }
                b.TransactionStatus.SetStatus(i, gasOnlyTx)
-               coinbaseValue += txBTMValue
+               coinbaseValue += gasStatus.BTMValue
+               gasUsed += uint64(gasStatus.GasUsed)
+       }
+
+       if gasUsed > consensus.MaxBlockGas {
+               return errOverBlockLimit
        }
 
        // check the coinbase output entry value
@@ -661,35 +687,32 @@ func validateStandardTx(tx *bc.Tx) error {
 }
 
 // ValidateTx validates a transaction.
-func ValidateTx(tx *bc.Tx, block *bc.Block) (uint64, bool, error) {
-       if tx.TxHeader.SerializedSize > consensus.MaxTxSize {
-               return 0, false, errWrongTransactionSize
+func ValidateTx(tx *bc.Tx, block *bc.Block) (*GasState, error) {
+       if tx.TxHeader.SerializedSize > consensus.MaxTxSize || tx.TxHeader.SerializedSize == 0 {
+               return nil, errWrongTransactionSize
        }
        if len(tx.ResultIds) == 0 {
-               return 0, false, errors.New("tx didn't have any output")
+               return nil, errors.New("tx didn't have any output")
        }
 
        if len(tx.GasInputIDs) == 0 && tx != block.Transactions[0] {
-               return 0, false, errors.New("tx didn't have gas input")
+               return nil, errors.New("tx didn't have gas input")
        }
 
        if err := validateStandardTx(tx); err != nil {
-               return 0, false, err
+               return nil, err
        }
 
-       //TODO: handle the gas limit
-       gasVaild := 0
        vs := &validationState{
                block:   block,
                tx:      tx,
                entryID: tx.ID,
-               gas: &gasState{
-                       gasLeft: defaultGasLimit,
+               gasStatus: &GasState{
+                       GasVaild: false,
                },
-               gasVaild: &gasVaild,
-               cache:    make(map[bc.Hash]error),
+               cache: make(map[bc.Hash]error),
        }
 
        err := checkValid(vs, tx.TxHeader)
-       return uint64(vs.gas.BTMValue), *vs.gasVaild == 1, err
+       return vs.gasStatus, err
 }
index 9e73d8d..967bc17 100644 (file)
@@ -26,100 +26,100 @@ func init() {
 
 func TestGasStatus(t *testing.T) {
        cases := []struct {
-               input  *gasState
-               output *gasState
-               f      func(*gasState) error
+               input  *GasState
+               output *GasState
+               f      func(*GasState) error
                err    error
        }{
                {
-                       input: &gasState{
-                               gasLeft:  10000,
-                               gasUsed:  0,
+                       input: &GasState{
+                               GasLeft:  10000,
+                               GasUsed:  0,
                                BTMValue: 0,
                        },
-                       output: &gasState{
-                               gasLeft:  10000 / GasRate,
-                               gasUsed:  0,
+                       output: &GasState{
+                               GasLeft:  10000 / consensus.VMGasRate,
+                               GasUsed:  0,
                                BTMValue: 10000,
                        },
-                       f: func(input *gasState) error {
-                               return input.setGas(10000)
+                       f: func(input *GasState) error {
+                               return input.setGas(10000, 0)
                        },
                        err: nil,
                },
                {
-                       input: &gasState{
-                               gasLeft:  10000,
-                               gasUsed:  0,
+                       input: &GasState{
+                               GasLeft:  10000,
+                               GasUsed:  0,
                                BTMValue: 0,
                        },
-                       output: &gasState{
-                               gasLeft:  10000,
-                               gasUsed:  0,
+                       output: &GasState{
+                               GasLeft:  10000,
+                               GasUsed:  0,
                                BTMValue: 0,
                        },
-                       f: func(input *gasState) error {
-                               return input.setGas(-10000)
+                       f: func(input *GasState) error {
+                               return input.setGas(-10000, 0)
                        },
                        err: errGasCalculate,
                },
                {
-                       input: &gasState{
-                               gasLeft:  defaultGasLimit,
-                               gasUsed:  0,
+                       input: &GasState{
+                               GasLeft:  consensus.DefaultGasCredit,
+                               GasUsed:  0,
                                BTMValue: 0,
                        },
-                       output: &gasState{
-                               gasLeft:  defaultGasLimit,
-                               gasUsed:  0,
+                       output: &GasState{
+                               GasLeft:  100000,
+                               GasUsed:  0,
                                BTMValue: 80000000000,
                        },
-                       f: func(input *gasState) error {
-                               return input.setGas(80000000000)
+                       f: func(input *GasState) error {
+                               return input.setGas(80000000000, 0)
                        },
                        err: nil,
                },
                {
-                       input: &gasState{
-                               gasLeft:  10000,
-                               gasUsed:  0,
+                       input: &GasState{
+                               GasLeft:  10000,
+                               GasUsed:  0,
                                BTMValue: 0,
                        },
-                       output: &gasState{
-                               gasLeft:  10000,
-                               gasUsed:  0,
+                       output: &GasState{
+                               GasLeft:  10000,
+                               GasUsed:  0,
                                BTMValue: 0,
                        },
-                       f: func(input *gasState) error {
+                       f: func(input *GasState) error {
                                return input.updateUsage(-1)
                        },
                        err: errGasCalculate,
                },
                {
-                       input: &gasState{
-                               gasLeft:  10000,
-                               gasUsed:  0,
+                       input: &GasState{
+                               GasLeft:  10000,
+                               GasUsed:  0,
                                BTMValue: 0,
                        },
-                       output: &gasState{
-                               gasLeft:  9999,
-                               gasUsed:  1,
+                       output: &GasState{
+                               GasLeft:  9999,
+                               GasUsed:  1,
                                BTMValue: 0,
                        },
-                       f: func(input *gasState) error {
+                       f: func(input *GasState) error {
                                return input.updateUsage(9999)
                        },
                        err: nil,
                },
        }
 
-       for _, c := range cases {
+       for i, c := range cases {
                err := c.f(c.input)
 
-               if err != c.err {
-                       t.Errorf("got error %s, want %s", err, c.err)
+               if rootErr(err) != c.err {
+                       t.Errorf("case %d: got error %s, want %s", i, err, c.err)
                } else if *c.input != *c.output {
-                       t.Errorf("got gasStatus %s, want %s;", c.input, c.output)
+                       t.Errorf("case %d: gasStatus %s, want %s;", i, c.input, c.output)
                }
        }
 }
@@ -378,7 +378,6 @@ func TestTxValidation(t *testing.T) {
        }
 
        for _, c := range cases {
-               gasVaild := 0
                t.Run(c.desc, func(t *testing.T) {
                        fixture = sample(t, nil)
                        tx = legacy.NewTx(*fixture.tx).Tx
@@ -386,12 +385,11 @@ func TestTxValidation(t *testing.T) {
                                block:   mockBlock(),
                                tx:      tx,
                                entryID: tx.ID,
-                               gas: &gasState{
-                                       gasLeft: int64(80000),
-                                       gasUsed: 0,
+                               gasStatus: &GasState{
+                                       GasLeft: int64(80000),
+                                       GasUsed: 0,
                                },
-                               cache:    make(map[bc.Hash]error),
-                               gasVaild: &gasVaild,
+                               cache: make(map[bc.Hash]error),
                        }
                        out := tx.Entries[*tx.ResultIds[0]].(*bc.Output)
                        muxID := out.Source.Ref
@@ -434,17 +432,6 @@ func TestValidateBlock(t *testing.T) {
                        },
                        err: errWrongCoinbaseTransaction,
                },
-               {
-                       block: &bc.Block{
-                               BlockHeader: &bc.BlockHeader{
-                                       Height:         0,
-                                       Bits:           2305843009230471167,
-                                       SerializedSize: 88888888,
-                               },
-                               Transactions: []*bc.Tx{mockCoinbaseTx(1)},
-                       },
-                       err: errWrongBlockSize,
-               },
        }
 
        txStatus := bc.NewTransactionStatus()
@@ -468,23 +455,10 @@ func TestValidateBlock(t *testing.T) {
 
 func TestCoinbase(t *testing.T) {
        CbTx := mockCoinbaseTx(5000000000)
-       errCbTx := legacy.MapTx(&legacy.TxData{
-               Inputs: []*legacy.TxInput{
-                       legacy.NewCoinbaseInput(nil, nil),
-               },
-               Outputs: []*legacy.TxOutput{
-                       legacy.NewTxOutput(bc.AssetID{
-                               V0: uint64(18446744073709551611),
-                               V1: uint64(18446744073709551615),
-                               V2: uint64(18446744073709551615),
-                               V3: uint64(18446744073709551615),
-                       }, 800000000000, []byte{1}, nil),
-               },
-       })
        cases := []struct {
                block    *bc.Block
                tx       *bc.Tx
-               gasVaild bool
+               GasVaild bool
                err      error
        }{
                {
@@ -495,30 +469,19 @@ func TestCoinbase(t *testing.T) {
                                Transactions: []*bc.Tx{CbTx},
                        },
                        tx:       CbTx,
-                       gasVaild: true,
+                       GasVaild: true,
                        err:      nil,
                },
-               {
-                       block: &bc.Block{
-                               BlockHeader: &bc.BlockHeader{
-                                       Height: 666,
-                               },
-                               Transactions: []*bc.Tx{errCbTx},
-                       },
-                       tx:       errCbTx,
-                       gasVaild: true,
-                       err:      errWrongCoinbaseAsset,
-               },
        }
 
        for i, c := range cases {
-               _, gasVaild, err := ValidateTx(c.tx, c.block)
+               gasStatus, err := ValidateTx(c.tx, c.block)
 
                if rootErr(err) != c.err {
                        t.Errorf("#%d got error %s, want %s", i, err, c.err)
                }
-               if c.gasVaild != gasVaild {
-                       t.Errorf("#%d got gasVaild %s, want %s", i, gasVaild, c.gasVaild)
+               if c.GasVaild != gasStatus.GasVaild {
+                       t.Errorf("#%d got GasVaild %s, want %s", i, gasStatus.GasVaild, c.GasVaild)
                }
        }
 }
@@ -679,6 +642,7 @@ func mockBlock() *bc.Block {
 func mockCoinbaseTx(amount uint64) *bc.Tx {
        cp, _ := vmutil.DefaultCoinbaseProgram()
        return legacy.MapTx(&legacy.TxData{
+               SerializedSize: 1,
                Inputs: []*legacy.TxInput{
                        legacy.NewCoinbaseInput(nil, nil),
                },
index 30ac774..1e72baa 100644 (file)
@@ -9,7 +9,6 @@ import (
 
        "github.com/bytom/blockchain/account"
        "github.com/bytom/blockchain/pseudohsm"
-       "github.com/bytom/blockchain/txbuilder"
        "github.com/bytom/crypto/ed25519/chainkd"
        "github.com/bytom/protocol/bc/legacy"
        "github.com/bytom/protocol/validation"
@@ -62,11 +61,7 @@ func TestP2PKH(t *testing.T) {
                t.Fatal(err)
        }
 
-       if err := txbuilder.MaterializeWitnesses(tpl); err != nil {
-               t.Fatal(err)
-       }
-
-       if _, _, err = validation.ValidateTx(legacy.MapTx(tx), test.MockBlock()); err != nil {
+       if _, err = validation.ValidateTx(legacy.MapTx(tx), test.MockBlock()); err != nil {
                t.Fatal(err)
        }
 }
@@ -122,11 +117,7 @@ func TestP2SH(t *testing.T) {
                t.Fatal(err)
        }
 
-       if err := txbuilder.MaterializeWitnesses(tpl); err != nil {
-               t.Fatal(err)
-       }
-
-       if _, _, err = validation.ValidateTx(legacy.MapTx(tx), test.MockBlock()); err != nil {
+       if _, err = validation.ValidateTx(legacy.MapTx(tx), test.MockBlock()); err != nil {
                t.Fatal(err)
        }
 }
@@ -196,10 +187,7 @@ func TestMutilNodeSign(t *testing.T) {
                t.Fatal("sign progress is not finish,  but both xpub1 and xpub2 is signed")
        }
 
-       if err := txbuilder.MaterializeWitnesses(tpl); err != nil {
-               t.Fatal(err)
-       }
-       if _, _, err = validation.ValidateTx(legacy.MapTx(tx), test.MockBlock()); err != nil {
+       if _, err = validation.ValidateTx(legacy.MapTx(tx), test.MockBlock()); err != nil {
                t.Fatal(err)
        }
 }