"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"`
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)
}
)
var (
- blockStoreKey = []byte("blockStore")
- txStatusPrefix = []byte("txStatus:")
+ blockStoreKey = []byte("blockStore")
+ blockSeedPrefix = []byte("blockSeed:")
+ txStatusPrefix = []byte("txStatus:")
)
// BlockStoreStateJSON represents the core's db status
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()...)
}
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)
}
// 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")
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
}
"github.com/bytom/blockchain"
"github.com/bytom/consensus/difficulty"
+ "github.com/bytom/protocol/bc"
"github.com/bytom/protocol/bc/legacy"
"github.com/bytom/util"
)
)
// 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
}
os.Exit(1)
}
- if doWork(resp.BlockHeader) {
+ if doWork(resp.BlockHeader, resp.Seed) {
util.ClientCall("/submitwork", resp.BlockHeader)
}
BlockHeader: legacy.BlockHeader{
Version: 1,
Height: 0,
- Nonce: 4216076,
+ Nonce: 4216077,
Timestamp: 1516788453,
BlockCommitment: legacy.BlockCommitment{
TransactionsMerkleRoot: merkleRoot,
import (
"testing"
+ "github.com/bytom/consensus"
"github.com/bytom/consensus/difficulty"
)
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++
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)
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
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,
// 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 {
header.Nonce = i
headerHash := header.Hash()
- if difficulty.CheckProofOfWork(&headerHash, &header.PreviousBlockHash, header.Bits) {
+ if difficulty.CheckProofOfWork(&headerHash, seed, header.Bits) {
return true
}
}
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
}
package protocol
import (
+ "blockchain/consensus"
"context"
"sync"
"time"
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
}
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)
const muxGasCost = int64(10)
+// GasState record the gas usage status
type GasState struct {
BTMValue uint64
GasLeft int64
// 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)
return errBadTimestamp
}
- if !difficulty.CheckProofOfWork(&b.ID, b.PreviousBlockId, b.BlockHeader.Bits) {
+ if !difficulty.CheckProofOfWork(&b.ID, seed, b.BlockHeader.Bits) {
return errWorkProof
}
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)
}
}