OSDN Git Service

Seed (#415)
authorPaladz <yzhu101@uottawa.ca>
Tue, 13 Mar 2018 01:42:38 +0000 (09:42 +0800)
committerGitHub <noreply@github.com>
Tue, 13 Mar 2018 01:42:38 +0000 (09:42 +0800)
* add seed generate rule

* edit the getWork resp

* add golint

blockchain/miner.go
blockchain/txdb/store.go
cmd/miner/main.go
config/genesis.go
config/genesis_test.go
consensus/general.go
mining/cpuminer/cpuminer.go
protocol/block.go
protocol/protocol.go
protocol/validation/validation.go
protocol/validation/validation_test.go

index 6477dcd..8cc13da 100644 (file)
@@ -7,11 +7,13 @@ import (
        "github.com/bytom/protocol/bc/legacy"
 )
 
+// BlockHeaderByHeight is resp struct for API
 type BlockHeaderByHeight struct {
        BlockHeader *legacy.BlockHeader `json:"block_header"`
        Reward      uint64              `json:"reward"`
 }
 
+// GetWorkResp is resp struct for API
 type GetWorkResp struct {
        BlockHeader *legacy.BlockHeader `json:"block_header"`
        Seed        *bc.Hash            `json:"seed"`
@@ -23,9 +25,14 @@ func (bcr *BlockchainReactor) getWork() Response {
                return NewErrorResponse(err)
        }
 
+       seed, err := bcr.chain.GetSeed(bh.Height, &bh.PreviousBlockHash)
+       if err != nil {
+               return NewErrorResponse(err)
+       }
+
        resp := &GetWorkResp{
                BlockHeader: bh,
-               Seed:        &bh.PreviousBlockHash,
+               Seed:        seed,
        }
        return NewSuccessResponse(resp)
 }
index e5442da..b5f1c8f 100644 (file)
@@ -16,8 +16,9 @@ import (
 )
 
 var (
-       blockStoreKey  = []byte("blockStore")
-       txStatusPrefix = []byte("txStatus:")
+       blockStoreKey   = []byte("blockStore")
+       blockSeedPrefix = []byte("blockSeed:")
+       txStatusPrefix  = []byte("txStatus:")
 )
 
 // BlockStoreStateJSON represents the core's db status
@@ -60,6 +61,10 @@ func calcBlockKey(hash *bc.Hash) []byte {
        return []byte(fmt.Sprintf("B:%v", hash.String()))
 }
 
+func calcSeedKey(hash *bc.Hash) []byte {
+       return append(blockSeedPrefix, hash.Bytes()...)
+}
+
 func calcTxStatusKey(hash *bc.Hash) []byte {
        return append(txStatusPrefix, hash.Bytes()...)
 }
@@ -103,6 +108,20 @@ func (s *Store) GetBlock(hash *bc.Hash) (*legacy.Block, error) {
        return s.cache.lookup(hash)
 }
 
+// GetSeed will return the seed of given block
+func (s *Store) GetSeed(hash *bc.Hash) (*bc.Hash, error) {
+       data := s.db.Get(calcSeedKey(hash))
+       if data == nil {
+               return nil, errors.New("can't find the seed by given hash")
+       }
+
+       seed := &bc.Hash{}
+       if err := proto.Unmarshal(data, seed); err != nil {
+               return nil, errors.Wrap(err, "unmarshaling seed")
+       }
+       return seed, nil
+}
+
 // GetTransactionsUtxo will return all the utxo that related to the input txs
 func (s *Store) GetTransactionsUtxo(view *state.UtxoViewpoint, txs []*bc.Tx) error {
        return getTransactionsUtxo(s.db, view, txs)
@@ -133,7 +152,7 @@ func (s *Store) GetMainchain(hash *bc.Hash) (map[uint64]*bc.Hash, error) {
 }
 
 // SaveBlock persists a new block in the database.
-func (s *Store) SaveBlock(block *legacy.Block, ts *bc.TransactionStatus) error {
+func (s *Store) SaveBlock(block *legacy.Block, ts *bc.TransactionStatus, seed *bc.Hash) error {
        binaryBlock, err := block.MarshalText()
        if err != nil {
                return errors.Wrap(err, "Marshal block meta")
@@ -144,10 +163,16 @@ func (s *Store) SaveBlock(block *legacy.Block, ts *bc.TransactionStatus) error {
                return errors.Wrap(err, "marshal block transaction status")
        }
 
+       binarySeed, err := proto.Marshal(seed)
+       if err != nil {
+               return errors.Wrap(err, "marshal block seed")
+       }
+
        blockHash := block.Hash()
        batch := s.db.NewBatch()
        batch.Set(calcBlockKey(&blockHash), binaryBlock)
        batch.Set(calcTxStatusKey(&blockHash), binaryTxStatus)
+       batch.Set(calcSeedKey(&blockHash), binarySeed)
        batch.Write()
        return nil
 }
index fde1db9..91abc9d 100644 (file)
@@ -7,6 +7,7 @@ import (
 
        "github.com/bytom/blockchain"
        "github.com/bytom/consensus/difficulty"
+       "github.com/bytom/protocol/bc"
        "github.com/bytom/protocol/bc/legacy"
        "github.com/bytom/util"
 )
@@ -16,11 +17,11 @@ const (
 )
 
 // do proof of work
-func doWork(bh *legacy.BlockHeader) bool {
+func doWork(bh *legacy.BlockHeader, seed *bc.Hash) bool {
        for i := uint64(0); i <= maxNonce; i++ {
                bh.Nonce = i
                headerHash := bh.Hash()
-               if difficulty.CheckProofOfWork(&headerHash, &bh.PreviousBlockHash, bh.Bits) {
+               if difficulty.CheckProofOfWork(&headerHash, seed, bh.Bits) {
                        fmt.Printf("Mining: successful-----proof hash:%v\n", headerHash.String())
                        return true
                }
@@ -66,7 +67,7 @@ func main() {
                os.Exit(1)
        }
 
-       if doWork(resp.BlockHeader) {
+       if doWork(resp.BlockHeader, resp.Seed) {
                util.ClientCall("/submitwork", resp.BlockHeader)
        }
 
index 53cc407..c260bf5 100644 (file)
@@ -47,7 +47,7 @@ func GenerateGenesisBlock() *legacy.Block {
                BlockHeader: legacy.BlockHeader{
                        Version:   1,
                        Height:    0,
-                       Nonce:     4216076,
+                       Nonce:     4216077,
                        Timestamp: 1516788453,
                        BlockCommitment: legacy.BlockCommitment{
                                TransactionsMerkleRoot: merkleRoot,
index 22dee5a..cb4f3a2 100644 (file)
@@ -3,6 +3,7 @@ package config
 import (
        "testing"
 
+       "github.com/bytom/consensus"
        "github.com/bytom/consensus/difficulty"
 )
 
@@ -18,7 +19,7 @@ func TestGenerateGenesisBlock(t *testing.T) {
        nonce := block.Nonce
        for {
                hash := block.Hash()
-               if difficulty.CheckProofOfWork(&hash, &block.PreviousBlockHash, block.Bits) {
+               if difficulty.CheckProofOfWork(&hash, consensus.InitialSeed, block.Bits) {
                        break
                }
                block.Nonce++
index 76bec02..65d7dca 100644 (file)
@@ -22,6 +22,7 @@ const (
        PowMinBits            = uint64(2161727821138738707)
        BlocksPerRetarget     = uint64(1024)
        TargetSecondsPerBlock = uint64(60)
+       SeedPerRetarget       = uint64(128)
 
        // MaxTimeOffsetSeconds is the maximum number of seconds a block time is allowed to be ahead of the current time
        MaxTimeOffsetSeconds = uint64(60 * 60)
@@ -35,6 +36,11 @@ const (
        StorageGasRate   = int64(10)
        MaxGasAmount     = int64(100000)
        DefaultGasCredit = int64(80000)
+
+       BTMAlias       = "btm"
+       BTMSymbol      = "btm"
+       BTMDecimals    = 8
+       BTMDescription = `Bytom Official Issue`
 )
 
 // BTMAssetID is BTM's asset id, the soul asset of Bytom
@@ -45,19 +51,15 @@ var BTMAssetID = &bc.AssetID{
        V3: uint64(18446744073709551615),
 }
 
-//BTMAlias is default btm
-var BTMAlias = "btm"
-
-//BTMSymbol
-var BTMSymbol = "btm"
-
-//BTMDecimals
-var BTMDecimals = 8
-
-//BTMDescription
-var BTMDescription = `Bytom Official Issue`
+// InitialSeed is SHA3-256 of Byte[0^32]
+var InitialSeed = &bc.Hash{
+       V0: uint64(11412844483649490393),
+       V1: uint64(4614157290180302959),
+       V2: uint64(1780246333311066183),
+       V3: uint64(9357197556716379726),
+}
 
-//BTMDefinitionMap
+// BTMDefinitionMap is the ....
 var BTMDefinitionMap = map[string]interface{}{
        "name":        BTMAlias,
        "symbol":      BTMSymbol,
index facb440..2687361 100644 (file)
@@ -47,6 +47,10 @@ type CPUMiner struct {
 // target difficulty.
 func (m *CPUMiner) solveBlock(block *legacy.Block, ticker *time.Ticker, quit chan struct{}) bool {
        header := &block.BlockHeader
+       seed, err := m.chain.GetSeed(header.Height, &header.PreviousBlockHash)
+       if err != nil {
+               return false
+       }
 
        for i := uint64(0); i <= maxNonce; i++ {
                select {
@@ -61,7 +65,7 @@ func (m *CPUMiner) solveBlock(block *legacy.Block, ticker *time.Ticker, quit cha
 
                header.Nonce = i
                headerHash := header.Hash()
-               if difficulty.CheckProofOfWork(&headerHash, &header.PreviousBlockHash, header.Bits) {
+               if difficulty.CheckProofOfWork(&headerHash, seed, header.Bits) {
                        return true
                }
        }
index 92b6349..3b7a6ca 100755 (executable)
@@ -134,11 +134,16 @@ func (c *Chain) SaveBlock(block *legacy.Block) error {
        blockEnts := legacy.MapBlock(block)
        prevEnts := legacy.MapBlock(preBlock)
 
-       if err := validation.ValidateBlock(blockEnts, prevEnts); err != nil {
+       seed, err := c.GetSeed(block.Height, &block.PreviousBlockHash)
+       if err != nil {
+               return err
+       }
+
+       if err := validation.ValidateBlock(blockEnts, prevEnts, seed); err != nil {
                return errors.Sub(ErrBadBlock, err)
        }
 
-       if err := c.store.SaveBlock(block, blockEnts.TransactionStatus); err != nil {
+       if err := c.store.SaveBlock(block, blockEnts.TransactionStatus, seed); err != nil {
                return err
        }
 
index b859229..ee077a0 100755 (executable)
@@ -1,6 +1,7 @@
 package protocol
 
 import (
+       "blockchain/consensus"
        "context"
        "sync"
        "time"
@@ -35,11 +36,12 @@ type Store interface {
        GetBlock(*bc.Hash) (*legacy.Block, error)
        GetMainchain(*bc.Hash) (map[uint64]*bc.Hash, error)
        GetStoreStatus() txdb.BlockStoreStateJSON
+       GetSeed(*bc.Hash) (*bc.Hash, error)
        GetTransactionStatus(*bc.Hash) (*bc.TransactionStatus, error)
        GetTransactionsUtxo(*state.UtxoViewpoint, []*bc.Tx) error
        GetUtxo(*bc.Hash) (*storage.UtxoEntry, error)
 
-       SaveBlock(*legacy.Block, *bc.TransactionStatus) error
+       SaveBlock(*legacy.Block, *bc.TransactionStatus, *bc.Hash) error
        SaveChainStatus(*legacy.Block, *state.UtxoViewpoint, map[uint64]*bc.Hash) error
 }
 
@@ -219,6 +221,16 @@ func (c *Chain) GetUtxo(hash *bc.Hash) (*storage.UtxoEntry, error) {
        return c.store.GetUtxo(hash)
 }
 
+// GetSeed return the seed for the given block
+func (c *Chain) GetSeed(height uint64, preBlock *bc.Hash) (*bc.Hash, error) {
+       if height == 0 {
+               return consensus.InitialSeed, nil
+       } else if height%consensus.SeedPerRetarget == 0 {
+               return preBlock, nil
+       }
+       return c.store.GetSeed(preBlock)
+}
+
 // GetTransactionStatus return the transaction status of give block
 func (c *Chain) GetTransactionStatus(hash *bc.Hash) (*bc.TransactionStatus, error) {
        return c.store.GetTransactionStatus(hash)
index ca769c6..8f25baf 100644 (file)
@@ -15,6 +15,7 @@ import (
 
 const muxGasCost = int64(10)
 
+// GasState record the gas usage status
 type GasState struct {
        BTMValue   uint64
        GasLeft    int64
@@ -544,7 +545,7 @@ func checkValidDest(vs *validationState, vd *bc.ValueDestination) error {
 
 // ValidateBlock validates a block and the transactions within.
 // It does not run the consensus program; for that, see ValidateBlockSig.
-func ValidateBlock(b, prev *bc.Block) error {
+func ValidateBlock(b, prev *bc.Block, seed *bc.Hash) error {
        if b.Height > 0 {
                if prev == nil {
                        return errors.WithDetailf(errNoPrevBlock, "height %d", b.Height)
@@ -559,7 +560,7 @@ func ValidateBlock(b, prev *bc.Block) error {
                return errBadTimestamp
        }
 
-       if !difficulty.CheckProofOfWork(&b.ID, b.PreviousBlockId, b.BlockHeader.Bits) {
+       if !difficulty.CheckProofOfWork(&b.ID, seed, b.BlockHeader.Bits) {
                return errWorkProof
        }
 
index ee0eff7..1c7ea8b 100644 (file)
@@ -449,7 +449,7 @@ func TestValidateBlock(t *testing.T) {
                c.block.TransactionsRoot = &txRoot
                c.block.TransactionStatusHash = &txStatusHash
 
-               if err = ValidateBlock(c.block, nil); rootErr(err) != c.err {
+               if err = ValidateBlock(c.block, nil, &bc.Hash{}); rootErr(err) != c.err {
                        t.Errorf("got error %s, want %s", err, c.err)
                }
        }