OSDN Git Service

Coinbase arbitrary (#1219)
authorHAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
Mon, 6 Aug 2018 10:33:55 +0000 (18:33 +0800)
committerPaladz <yzhu101@uottawa.ca>
Mon, 6 Aug 2018 10:33:55 +0000 (18:33 +0800)
* get mining address

* Set mining addr

* go fmt

* Fix CI

* Avoid mining to null addr

* Prevent mining to null addr for api

* clean vendor

* format get/setMiningAddress func

* Update if statements format

* Combine

* go fmt

* clean GetMiningAddress()

* compact IF statements

* compact IF statements

* revert

* SetMiningAddress for non-local address

* combine

* go fmt

* private getProgramByAddress()

* Avoid mining to nil addr for get-work

* Roll back

* Fix CI

* tweak func seq

* Add /get-coinbase-arbitrary api

* setCoinbaseArbitrary

* abHexStr

* re-construct code

* go fmt

* fix conflict

* go fmt

* re org code

* GetBlockTemplate

* rm get-coinbase-arbitrary

* go fmt

* RenewBlkTplWithArbitrary

* clean up

* CoinbaseArbitraryOversize check

* Iter to find CoinbaseArbitrary

* go fmt

* Change arbitrary json from string to chainjson

* Fix CI

* get/set-coinbase-arbitrary

* Fix

* go fmt

* Fix

* Fix

* Fix CI

* Disable test -v

* Fix coinbase arbitrary in get-work-json

* Fix arbitrary call

* Roll back (Ignore coinbase arbitrary in get-work-json)

* Rm block.CoinbaseArbitrary()

* Reformat

* Clean getBlockHelper()

* Add import

* Fix getBlockHelper() logic

* Clean up codes

Makefile
account/accounts.go
api/api.go
api/block_retrieve.go
api/miner.go
api/page_util.go
mining/cpuminer/cpuminer.go
mining/mining.go
protocol/bc/types/coinbase.go

index d62cb4b..929378a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -125,7 +125,7 @@ benchmark:
        @go test -bench $(PACKAGES)
 
 functional-tests:
-       @go test -v -timeout=5m -tags="functional" ./test 
+       @go test -timeout=5m -tags="functional" ./test 
 
 ci: test functional-tests
 
index 34858d1..b5da7e4 100644 (file)
@@ -35,6 +35,7 @@ var (
        contractIndexPrefix = []byte("ContractIndex")
        contractPrefix      = []byte("Contract:")
        miningAddressKey    = []byte("MiningAddress")
+       CoinbaseAbKey       = []byte("CoinbaseArbitrary")
 )
 
 // pre-define errors for supporting bytom errorFormatter
@@ -245,6 +246,13 @@ func (m *Manager) GetAliasByID(id string) string {
        return account.Alias
 }
 
+func (m *Manager) GetCoinbaseArbitrary() []byte {
+       if arbitrary := m.db.Get(CoinbaseAbKey); arbitrary != nil {
+               return arbitrary
+       }
+       return []byte{}
+}
+
 // GetCoinbaseControlProgram will return a coinbase script
 func (m *Manager) GetCoinbaseControlProgram() ([]byte, error) {
        cp, err := m.GetCoinbaseCtrlProgram()
@@ -405,6 +413,10 @@ func (m *Manager) SetMiningAddress(miningAddress string) (string, error) {
        return m.GetMiningAddress()
 }
 
+func (m *Manager) SetCoinbaseArbitrary(arbitrary []byte) {
+       m.db.Set(CoinbaseAbKey, arbitrary)
+}
+
 // CreateAddress generate an address for the select account
 func (m *Manager) createAddress(account *Account, change bool) (cp *CtrlProgram, err error) {
        if len(account.XPubs) == 1 {
index 41eaf8d..d26223e 100644 (file)
@@ -273,6 +273,9 @@ func (a *API) buildHandler() {
        m.Handle("/submit-work", jsonHandler(a.submitWork))
        m.Handle("/submit-work-json", jsonHandler(a.submitWorkJSON))
 
+       m.Handle("/get-coinbase-arbitrary", jsonHandler(a.getCoinbaseArbitrary))
+       m.Handle("/set-coinbase-arbitrary", jsonHandler(a.setCoinbaseArbitrary))
+
        m.Handle("/verify-message", jsonHandler(a.verifyMessage))
        m.Handle("/decode-program", jsonHandler(a.decodeProgram))
        m.Handle("/compile", jsonHandler(a.compileEquity))
index 6532c02..77e0cb2 100644 (file)
@@ -6,6 +6,7 @@ import (
        "github.com/bytom/blockchain/query"
        "github.com/bytom/consensus/difficulty"
        chainjson "github.com/bytom/encoding/json"
+       "github.com/bytom/errors"
        "github.com/bytom/protocol/bc"
        "github.com/bytom/protocol/bc/types"
 )
@@ -56,18 +57,9 @@ type GetBlockResp struct {
        Transactions           []*BlockTx `json:"transactions"`
 }
 
-// return block by hash
+// return block by hash/height
 func (a *API) getBlock(ins BlockReq) Response {
-       var err error
-       block := &types.Block{}
-       if len(ins.BlockHash) == 32 {
-               b32 := [32]byte{}
-               copy(b32[:], ins.BlockHash)
-               hash := bc.NewHash(b32)
-               block, err = a.chain.GetBlockByHash(&hash)
-       } else {
-               block, err = a.chain.GetBlockByHeight(ins.BlockHeight)
-       }
+       block, err := a.getBlockHelper(ins)
        if err != nil {
                return NewErrorResponse(err)
        }
@@ -135,16 +127,7 @@ type GetBlockHeaderResp struct {
 }
 
 func (a *API) getBlockHeader(ins BlockReq) Response {
-       var err error
-       block := &types.Block{}
-       if len(ins.BlockHash) == 32 {
-               b32 := [32]byte{}
-               copy(b32[:], ins.BlockHash)
-               hash := bc.NewHash(b32)
-               block, err = a.chain.GetBlockByHash(&hash)
-       } else {
-               block, err = a.chain.GetBlockByHeight(ins.BlockHeight)
-       }
+       block, err := a.getBlockHelper(ins)
        if err != nil {
                return NewErrorResponse(err)
        }
@@ -156,6 +139,17 @@ func (a *API) getBlockHeader(ins BlockReq) Response {
        return NewSuccessResponse(resp)
 }
 
+func (a *API) getBlockHelper(ins BlockReq) (*types.Block, error) {
+       if len(ins.BlockHash) == 32 {
+               b32 := [32]byte{}
+               copy(b32[:], ins.BlockHash)
+               hash := bc.NewHash(b32)
+               return a.chain.GetBlockByHash(&hash)
+       } else {
+               return a.chain.GetBlockByHeight(ins.BlockHeight)
+       }
+}
+
 // GetDifficultyResp is resp struct for getDifficulty API
 type GetDifficultyResp struct {
        BlockHash   *bc.Hash `json:"hash"`
@@ -164,22 +158,8 @@ type GetDifficultyResp struct {
        Difficulty  string   `json:"difficulty"`
 }
 
-func (a *API) getDifficulty(ins *BlockReq) Response {
-       var err error
-       block := &types.Block{}
-
-       if len(ins.BlockHash) == 32 && ins.BlockHash != nil {
-               b32 := [32]byte{}
-               copy(b32[:], ins.BlockHash)
-               hash := bc.NewHash(b32)
-               block, err = a.chain.GetBlockByHash(&hash)
-       } else if ins.BlockHeight > 0 {
-               block, err = a.chain.GetBlockByHeight(ins.BlockHeight)
-       } else {
-               hash := a.chain.BestBlockHash()
-               block, err = a.chain.GetBlockByHash(hash)
-       }
-
+func (a *API) getDifficulty(ins BlockReq) Response {
+       block, err := a.getBlockHelper(ins)
        if err != nil {
                return NewErrorResponse(err)
        }
@@ -202,21 +182,12 @@ type getHashRateResp struct {
 }
 
 func (a *API) getHashRate(ins BlockReq) Response {
-       var err error
-       block := &types.Block{}
-
-       if len(ins.BlockHash) == 32 && ins.BlockHash != nil {
-               b32 := [32]byte{}
-               copy(b32[:], ins.BlockHash)
-               hash := bc.NewHash(b32)
-               block, err = a.chain.GetBlockByHash(&hash)
-       } else if ins.BlockHeight > 0 {
-               block, err = a.chain.GetBlockByHeight(ins.BlockHeight)
-       } else {
-               hash := a.chain.BestBlockHash()
-               block, err = a.chain.GetBlockByHash(hash)
+       if len(ins.BlockHash) != 32 && ins.BlockHeight == 0 {
+               err := errors.New("Request format error.")
+               return NewErrorResponse(err)
        }
 
+       block, err := a.getBlockHelper(ins)
        if err != nil {
                return NewErrorResponse(err)
        }
index ece1386..6c300e4 100644 (file)
@@ -3,6 +3,7 @@ package api
 import (
        "context"
 
+       chainjson "github.com/bytom/encoding/json"
        "github.com/bytom/errors"
        "github.com/bytom/protocol/bc"
        "github.com/bytom/protocol/bc/types"
@@ -20,6 +21,23 @@ type BlockHeaderJSON struct {
        BlockCommitment   *types.BlockCommitment `json:"block_commitment"`    //Block commitment
 }
 
+type CoinbaseArbitrary struct {
+       Arbitrary chainjson.HexBytes `json:"arbitrary"`
+}
+
+func (a *API) getCoinbaseArbitrary() Response {
+       arbitrary := a.wallet.AccountMgr.GetCoinbaseArbitrary()
+       resp := &CoinbaseArbitrary{
+               Arbitrary: arbitrary,
+       }
+       return NewSuccessResponse(resp)
+}
+
+func (a *API) setCoinbaseArbitrary(ctx context.Context, req CoinbaseArbitrary) Response {
+       a.wallet.AccountMgr.SetCoinbaseArbitrary(req.Arbitrary)
+       return a.getCoinbaseArbitrary()
+}
+
 // getWork gets work in compressed protobuf format
 func (a *API) getWork() Response {
        work, err := a.GetWork()
index 4d2ec83..7bffbc0 100644 (file)
@@ -2,13 +2,17 @@ package api
 
 // Get the start and end of the page.
 func getPageRange(size int, from uint, count uint) (uint, uint) {
-       total := uint(size) 
+       total := uint(size)
        if from == 0 && count == 0 {
                return 0, total
        }
        start := from
        end := from + count
-       if start > total {start = total}
-       if end > total {end = total}
+       if start > total {
+               start = total
+       }
+       if end > total {
+               end = total
+       }
        return start, end
-}
\ No newline at end of file
+}
index 71f8ba6..5dfc579 100644 (file)
@@ -28,16 +28,16 @@ const (
 // a concurrency-safe manner.
 type CPUMiner struct {
        sync.Mutex
-       chain             *protocol.Chain
-       accountManager    *account.Manager
-       txPool            *protocol.TxPool
-       numWorkers        uint64
-       started           bool
-       discreteMining    bool
-       workerWg          sync.WaitGroup
-       updateNumWorkers  chan struct{}
-       quit              chan struct{}
-       newBlockCh        chan *bc.Hash
+       chain            *protocol.Chain
+       accountManager   *account.Manager
+       txPool           *protocol.TxPool
+       numWorkers       uint64
+       started          bool
+       discreteMining   bool
+       workerWg         sync.WaitGroup
+       updateNumWorkers chan struct{}
+       quit             chan struct{}
+       newBlockCh       chan *bc.Hash
 }
 
 // solveBlock attempts to find some combination of a nonce, extra nonce, and
@@ -268,11 +268,11 @@ func (m *CPUMiner) NumWorkers() int32 {
 // type for more details.
 func NewCPUMiner(c *protocol.Chain, accountManager *account.Manager, txPool *protocol.TxPool, newBlockCh chan *bc.Hash) *CPUMiner {
        return &CPUMiner{
-               chain:             c,
-               accountManager:    accountManager,
-               txPool:            txPool,
-               numWorkers:        defaultNumWorkers,
-               updateNumWorkers:  make(chan struct{}),
-               newBlockCh:        newBlockCh,
+               chain:            c,
+               accountManager:   accountManager,
+               txPool:           txPool,
+               numWorkers:       defaultNumWorkers,
+               updateNumWorkers: make(chan struct{}),
+               newBlockCh:       newBlockCh,
        }
 }
index b06417f..bb18122 100644 (file)
@@ -1,7 +1,3 @@
-// Copyright (c) 2014-2016 The btcsuite developers
-// Use of this source code is governed by an ISC
-// license that can be found in the LICENSE file.
-
 package mining
 
 import (
@@ -28,34 +24,38 @@ import (
 // is nil, the coinbase transaction will instead be redeemable by anyone.
 func createCoinbaseTx(accountManager *account.Manager, amount uint64, blockHeight uint64) (tx *types.Tx, err error) {
        amount += consensus.BlockSubsidy(blockHeight)
+       arbitrary := append([]byte{0x00}, []byte(strconv.FormatUint(blockHeight, 10))...)
 
        var script []byte
        if accountManager == nil {
                script, err = vmutil.DefaultCoinbaseProgram()
        } else {
                script, err = accountManager.GetCoinbaseControlProgram()
+               arbitrary = append(arbitrary, accountManager.GetCoinbaseArbitrary()...)
        }
        if err != nil {
-               return
+               return nil, err
+       }
+
+       if len(arbitrary) > consensus.CoinbaseArbitrarySizeLimit {
+               return nil, validation.ErrCoinbaseArbitraryOversize
        }
 
        builder := txbuilder.NewBuilder(time.Now())
-       if err = builder.AddInput(types.NewCoinbaseInput(
-               append([]byte{0x00}, []byte(strconv.FormatUint(blockHeight, 10))...),
-       ), &txbuilder.SigningInstruction{}); err != nil {
-               return
+       if err = builder.AddInput(types.NewCoinbaseInput(arbitrary), &txbuilder.SigningInstruction{}); err != nil {
+               return nil, err
        }
        if err = builder.AddOutput(types.NewTxOutput(*consensus.BTMAssetID, amount, script)); err != nil {
-               return
+               return nil, err
        }
        _, txData, err := builder.Build()
        if err != nil {
-               return
+               return nil, err
        }
 
        byteData, err := txData.MarshalText()
        if err != nil {
-               return
+               return nil, err
        }
        txData.SerializedSize = uint64(len(byteData))
 
@@ -63,7 +63,7 @@ func createCoinbaseTx(accountManager *account.Manager, amount uint64, blockHeigh
                TxData: *txData,
                Tx:     types.MapTx(txData),
        }
-       return
+       return tx, nil
 }
 
 // NewBlockTemplate returns a new block template that is ready to be solved
index 5dd7cf9..bf0797d 100644 (file)
@@ -1,11 +1,11 @@
 package types
 
-// CoinbaseInput is record the coinbase message
+// CoinbaseInput records the coinbase message
 type CoinbaseInput struct {
        Arbitrary []byte
 }
 
-// NewCoinbaseInput create a new coinbase input struct
+// NewCoinbaseInput creates a new coinbase input struct
 func NewCoinbaseInput(arbitrary []byte) *TxInput {
        return &TxInput{
                AssetVersion: 1,