OSDN Git Service

add consensus engine
authormars <mars@bytom.io>
Mon, 24 Dec 2018 02:03:12 +0000 (10:03 +0800)
committermars <mars@bytom.io>
Mon, 24 Dec 2018 02:03:12 +0000 (10:03 +0800)
config/config.go
mining/consensus/consensus.go [new file with mode: 0644]
mining/consensus/dpos/custom_tx.go [new file with mode: 0644]
mining/consensus/dpos/dpos.go [new file with mode: 0644]
mining/consensus/dpos/signer_queue.go [new file with mode: 0644]
mining/consensus/dpos/snapshot.go [new file with mode: 0644]
mining/consensus/errors.go [new file with mode: 0644]
protocol/bc/bc.pb.go
protocol/bc/bc.proto

index 98040b5..616704b 100644 (file)
@@ -1,12 +1,14 @@
 package config
 
 import (
+       "math/big"
        "os"
        "os/user"
        "path/filepath"
        "runtime"
 
        log "github.com/sirupsen/logrus"
+       "github.com/vapor/common"
 )
 
 var (
@@ -169,6 +171,15 @@ type WebsocketConfig struct {
        MaxNumConcurrentReqs int `mapstructure:"max_num_concurrent_reqs"`
 }
 
+type DposConfig struct {
+       Period           uint64           `json:"period"`            // Number of seconds between blocks to enforce
+       Epoch            uint64           `json:"epoch"`             // Epoch length to reset votes and checkpoint
+       MaxSignerCount   uint64           `json:"max_signers_count"` // Max count of signers
+       MinVoterBalance  *big.Int         `json:"min_boter_balance"` // Min voter balance to valid this vote
+       GenesisTimestamp uint64           `json:"genesis_timestamp"` // The LoopStartTime of first Block
+       SelfVoteSigners  []common.Address `json:"signers"`           // Signers vote by themselves to seal the block, make sure the signer accounts are pre-funded
+}
+
 // Default configurable rpc's auth parameters.
 func DefaultRPCAuthConfig() *RPCAuthConfig {
        return &RPCAuthConfig{
diff --git a/mining/consensus/consensus.go b/mining/consensus/consensus.go
new file mode 100644 (file)
index 0000000..cdabdf9
--- /dev/null
@@ -0,0 +1,82 @@
+package consensus
+
+import (
+       "math/big"
+
+       "github.com/vapor/common"
+       "github.com/vapor/protocol/bc"
+       "github.com/vapor/protocol/bc/types"
+)
+
+// ChainReader defines a small collection of methods needed to access the local
+// blockchain during header and/or uncle verification.
+type ChainReader interface {
+       // Config retrieves the blockchain's chain configuration.
+       //Config() *params.ChainConfig
+
+       // CurrentHeader retrieves the current header from the local chain.
+       CurrentHeader() *types.BlockHeader
+
+       // GetHeader retrieves a block header from the database by hash and number.
+       GetHeader(hash bc.Hash, number uint64) *types.BlockHeader
+
+       // GetHeaderByNumber retrieves a block header from the database by number.
+       GetHeaderByNumber(number uint64) *types.BlockHeader
+
+       // GetHeaderByHash retrieves a block header from the database by its hash.
+       GetHeaderByHash(hash bc.Hash) *types.BlockHeader
+
+       // GetBlock retrieves a block from the database by hash and number.
+       GetBlock(hash bc.Hash, number uint64) *types.Block
+}
+
+// Engine is an algorithm agnostic consensus engine.
+type Engine interface {
+       // Author retrieves the Ethereum address of the account that minted the given
+       // block, which may be different from the header's coinbase if a consensus
+       // engine is based on signatures.
+       Author(header *types.BlockHeader) (common.Address, error)
+
+       // VerifyHeader checks whether a header conforms to the consensus rules of a
+       // given engine. Verifying the seal may be done optionally here, or explicitly
+       // via the VerifySeal method.
+       VerifyHeader(chain ChainReader, header *types.BlockHeader, seal bool) error
+
+       // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers
+       // concurrently. The method returns a quit channel to abort the operations and
+       // a results channel to retrieve the async verifications (the order is that of
+       // the input slice).
+       VerifyHeaders(chain ChainReader, headers []*types.BlockHeader, seals []bool) (chan<- struct{}, <-chan error)
+
+       // VerifyUncles verifies that the given block's uncles conform to the consensus
+       // rules of a given engine.
+       VerifyUncles(chain ChainReader, block *types.Block) error
+
+       // VerifySeal checks whether the crypto seal on a header is valid according to
+       // the consensus rules of the given engine.
+       VerifySeal(chain ChainReader, header *types.BlockHeader) error
+
+       // Prepare initializes the consensus fields of a block header according to the
+       // rules of a particular engine. The changes are executed inline.
+       Prepare(chain ChainReader, header *types.BlockHeader) error
+
+       // Finalize runs any post-transaction state modifications (e.g. block rewards)
+       // and assembles the final block.
+       // Note: The block header and state database might be updated to reflect any
+       // consensus rules that happen at finalization (e.g. block rewards).
+       /*
+               Finalize(chain ChainReader, header *types.BlockHeader , state *state.StateDB, txs []*types.Transaction,
+                       uncles []*types.BlockHeader , receipts []*types.Receipt) (*types.Block, error)
+       */
+
+       // Seal generates a new block for the given input block with the local miner's
+       // seal place on top.
+       Seal(chain ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error)
+
+       // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
+       // that a new block should have.
+       CalcDifficulty(chain ChainReader, time uint64, parent *types.BlockHeader) *big.Int
+
+       // APIs returns the RPC APIs this consensus engine provides.
+       //APIs(chain ChainReader) []rpc.API
+}
diff --git a/mining/consensus/dpos/custom_tx.go b/mining/consensus/dpos/custom_tx.go
new file mode 100644 (file)
index 0000000..c0e7581
--- /dev/null
@@ -0,0 +1 @@
+package dpos
diff --git a/mining/consensus/dpos/dpos.go b/mining/consensus/dpos/dpos.go
new file mode 100644 (file)
index 0000000..7ab09d9
--- /dev/null
@@ -0,0 +1,198 @@
+package dpos
+
+import (
+       "errors"
+       "fmt"
+       "math/big"
+       "sync"
+       "time"
+
+       "github.com/go-loom/types"
+       lru "github.com/hashicorp/golang-lru"
+       log "github.com/sirupsen/logrus"
+       "github.com/vapor/common"
+       "github.com/vapor/config"
+       "github.com/vapor/protocol"
+       "github.com/vapor/protocol/bc"
+)
+
+const (
+       inMemorySnapshots  = 128             // Number of recent vote snapshots to keep in memory
+       inMemorySignatures = 4096            // Number of recent block signatures to keep in memory
+       secondsPerYear     = 365 * 24 * 3600 // Number of seconds for one year
+       checkpointInterval = 360             // About N hours if config.period is N
+       module             = "dpos"
+)
+
+//delegated-proof-of-stake protocol constants.
+var (
+       SignerBlockReward                = big.NewInt(5e+18) // Block reward in wei for successfully mining a block first year
+       defaultEpochLength               = uint64(3000000)   // Default number of blocks after which vote's period of validity
+       defaultBlockPeriod               = uint64(3)         // Default minimum difference between two consecutive block's timestamps
+       defaultMaxSignerCount            = uint64(21)        //
+       defaultMinVoterBalance           = new(big.Int).Mul(big.NewInt(10000), big.NewInt(1e+18))
+       extraVanity                      = 32            // Fixed number of extra-data prefix bytes reserved for signer vanity
+       extraSeal                        = 65            // Fixed number of extra-data suffix bytes reserved for signer seal
+       defaultDifficulty                = big.NewInt(1) // Default difficulty
+       defaultLoopCntRecalculateSigners = uint64(10)    // Default loop count to recreate signers from top tally
+       minerRewardPerThousand           = uint64(618)   // Default reward for miner in each block from block reward (618/1000)
+       candidateNeedPD                  = false         // is new candidate need Proposal & Declare process
+)
+
+var (
+       // errUnknownBlock is returned when the list of signers is requested for a block
+       // that is not part of the local blockchain.
+       errUnknownBlock = errors.New("unknown block")
+
+       // errMissingVanity is returned if a block's extra-data section is shorter than
+       // 32 bytes, which is required to store the signer vanity.
+       errMissingVanity = errors.New("extra-data 32 byte vanity prefix missing")
+
+       // errMissingSignature is returned if a block's extra-data section doesn't seem
+       // to contain a 65 byte secp256k1 signature.
+       errMissingSignature = errors.New("extra-data 65 byte suffix signature missing")
+
+       // errInvalidMixDigest is returned if a block's mix digest is non-zero.
+       errInvalidMixDigest = errors.New("non-zero mix digest")
+
+       // errInvalidUncleHash is returned if a block contains an non-empty uncle list.
+       errInvalidUncleHash = errors.New("non empty uncle hash")
+
+       // ErrInvalidTimestamp is returned if the timestamp of a block is lower than
+       // the previous block's timestamp + the minimum block period.
+       ErrInvalidTimestamp = errors.New("invalid timestamp")
+
+       // errInvalidVotingChain is returned if an authorization list is attempted to
+       // be modified via out-of-range or non-contiguous headers.
+       errInvalidVotingChain = errors.New("invalid voting chain")
+
+       // errUnauthorized is returned if a header is signed by a non-authorized entity.
+       errUnauthorized = errors.New("unauthorized")
+
+       // errPunishedMissing is returned if a header calculate punished signer is wrong.
+       errPunishedMissing = errors.New("punished signer missing")
+
+       // errWaitTransactions is returned if an empty block is attempted to be sealed
+       // on an instant chain (0 second period). It's important to refuse these as the
+       // block reward is zero, so an empty block just bloats the chain... fast.
+       errWaitTransactions = errors.New("waiting for transactions")
+
+       // errUnclesNotAllowed is returned if uncles exists
+       errUnclesNotAllowed = errors.New("uncles not allowed")
+
+       // errCreateSignerQueueNotAllowed is returned if called in (block number + 1) % maxSignerCount != 0
+       errCreateSignerQueueNotAllowed = errors.New("create signer queue not allowed")
+
+       // errInvalidSignerQueue is returned if verify SignerQueue fail
+       errInvalidSignerQueue = errors.New("invalid signer queue")
+
+       // errSignerQueueEmpty is returned if no signer when calculate
+       errSignerQueueEmpty = errors.New("signer queue is empty")
+)
+
+type Dpos struct {
+       config     *config.DposConfig // Consensus engine configuration parameters
+       store      protocol.Store     // Database to store and retrieve snapshot checkpoints
+       recents    *lru.ARCCache      // Snapshots for recent block to speed up reorgs
+       signatures *lru.ARCCache      // Signatures of recent blocks to speed up mining
+       signer     common.Address     // Ethereum address of the signing key
+       signFn     SignerFn           // Signer function to authorize hashes with
+       signTxFn   SignTxFn           // Sign transaction function to sign tx
+       lock       sync.RWMutex       // Protects the signer fields
+       lcsc       uint64             // Last confirmed side chain
+}
+
+// SignerFn is a signer callback function to request a hash to be signed by a backing account.
+type SignerFn func(common.Address, []byte) ([]byte, error)
+
+// SignTxFn is a signTx
+type SignTxFn func(common.Address, *types.Transaction, *big.Int) (*types.Transaction, error)
+
+//
+func ecrecover(header *types.BlockHeader, sigcache *lru.ARCCache) (common.Address, error) {
+       return nil, nil
+}
+
+func sigHash(header *types.BlockHeader) (hash bc.Hash) {
+       return bc.Hash{}
+}
+
+//
+func New(config *config.DposConfig, store protocol.Store) *Dpos {
+       conf := *config
+       if conf.Epoch == 0 {
+               conf.Epoch = defaultEpochLength
+       }
+       if conf.Period == 0 {
+               conf.Period = defaultBlockPeriod
+       }
+       if conf.MaxSignerCount == 0 {
+               conf.MaxSignerCount = defaultMaxSignerCount
+       }
+       if conf.MinVoterBalance.Uint64() == 0 {
+               conf.MinVoterBalance = defaultMinVoterBalance
+       }
+
+       // Allocate the snapshot caches and create the engine
+       recents, _ := lru.NewARC(inMemorySnapshots)
+       signatures, _ := lru.NewARC(inMemorySignatures)
+       return &Dpos{
+               config:     &conf,
+               store:      store,
+               recents:    recents,
+               signatures: signatures,
+       }
+}
+
+// 从BLockHeader中获取到地址
+func (d *Dpos) Author(header *types.BlockHeader) (common.Address, error) {
+       return ecrecover(header, d.signatures)
+}
+
+// Prepare implements consensus.Engine, preparing all the consensus fields of the header for running the transactions on top.
+func (d *Dpos) Prepare(c *protocol.Chain, header *bc.BlockHeader) error {
+       if d.config.GenesisTimestamp < uint64(time.Now().Unix()) {
+               return nil
+       }
+
+       if header.Height == 1 {
+               for {
+                       delay := time.Unix(int64(d.config.GenesisTimestamp-2), 0).Sub(time.Now())
+                       if delay <= time.Duration(0) {
+                               log.WithFields(log.Fields{"module": module, "time": time.Now()}).Info("Ready for seal block")
+                               break
+                       } else if delay > time.Duration(d.config.Period)*time.Second {
+                               delay = time.Duration(d.config.Period) * time.Second
+                       }
+                       log.WithFields(log.Fields{"module": module, "delay": time.Duration(time.Unix(int64(d.config.GenesisTimestamp-2), 0).Sub(time.Now()))}).Info("Waiting for seal block")
+                       select {
+                       case <-time.After(delay):
+                               continue
+                       }
+               }
+       }
+       return nil
+}
+
+func (d *Dpos) Finalize(c *protocol.Chain, header *bc.BlockHeader, txs []*types.Transaction) (*bc.Block, error) {
+       height := c.BestBlockHeight()
+       fmt.Println(height)
+       parent, err := c.GetHeaderByHeight(height - 1)
+       if parent == nil {
+               return nil, err
+       }
+       //header.Timestamp
+       t := new(big.Int).Add(new(big.Int).SetUint64(parent.Timestamp), new(big.Int).SetUint64(d.config.Period))
+       header.Timestamp = t.Uint64()
+
+       if header.Timestamp < uint64(time.Now().Unix()) {
+               header.Timestamp = uint64(time.Now().Unix())
+       }
+       
+
+       return nil, nil
+}
+
+func (d *Dpos) Seal() {
+
+}
diff --git a/mining/consensus/dpos/signer_queue.go b/mining/consensus/dpos/signer_queue.go
new file mode 100644 (file)
index 0000000..c0e7581
--- /dev/null
@@ -0,0 +1 @@
+package dpos
diff --git a/mining/consensus/dpos/snapshot.go b/mining/consensus/dpos/snapshot.go
new file mode 100644 (file)
index 0000000..c0e7581
--- /dev/null
@@ -0,0 +1 @@
+package dpos
diff --git a/mining/consensus/errors.go b/mining/consensus/errors.go
new file mode 100644 (file)
index 0000000..b9cb359
--- /dev/null
@@ -0,0 +1,21 @@
+package consensus
+
+import "errors"
+
+var (
+       // ErrUnknownAncestor is returned when validating a block requires an ancestor
+       // that is unknown.
+       ErrUnknownAncestor = errors.New("unknown ancestor")
+
+       // ErrPrunedAncestor is returned when validating a block requires an ancestor
+       // that is known, but the state of which is not available.
+       ErrPrunedAncestor = errors.New("pruned ancestor")
+
+       // ErrFutureBlock is returned when a block's timestamp is in the future according
+       // to the current node.
+       ErrFutureBlock = errors.New("block in the future")
+
+       // ErrInvalidNumber is returned if a block's number doesn't equal it's parent's
+       // plus one.
+       ErrInvalidNumber = errors.New("invalid block number")
+)
index 149789f..4f545e7 100644 (file)
@@ -301,6 +301,7 @@ type BytomBlockHeader struct {
        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"`
+       Extra                 []byte             `protobuf:"bytes,10,opt,name=extra,proto3" json:"extra,omitempty"`
 }
 
 func (m *BytomBlockHeader) Reset()                    { *m = BytomBlockHeader{} }
@@ -371,6 +372,13 @@ func (m *BytomBlockHeader) GetTransactionStatus() *TransactionStatus {
        return nil
 }
 
+func (m *BytomBlockHeader) GetExtra() []byte {
+       if m != nil {
+               return m.Extra
+       }
+       return nil
+}
+
 type BlockHeader struct {
        Version               uint64             `protobuf:"varint,1,opt,name=version" json:"version,omitempty"`
        Height                uint64             `protobuf:"varint,2,opt,name=height" json:"height,omitempty"`
@@ -829,68 +837,69 @@ func init() {
 func init() { proto.RegisterFile("bc.proto", fileDescriptor0) }
 
 var fileDescriptor0 = []byte{
-       // 999 bytes of a gzipped FileDescriptorProto
-       0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x57, 0xcb, 0x6e, 0x1b, 0x37,
-       0x14, 0x85, 0x34, 0xa3, 0xd7, 0x95, 0x63, 0xd9, 0xb4, 0x93, 0x0e, 0x82, 0x14, 0x09, 0x06, 0x48,
-       0xdc, 0xa2, 0x80, 0xe1, 0x47, 0xda, 0x6e, 0xba, 0xa8, 0x63, 0x37, 0x8d, 0x16, 0x46, 0x0c, 0xda,
-       0xf0, 0x76, 0x40, 0xcd, 0x50, 0x32, 0xd1, 0xd1, 0x50, 0x25, 0x39, 0xaa, 0xed, 0x5d, 0x3e, 0xa2,
-       0xcb, 0x7e, 0x47, 0x3f, 0xa1, 0xab, 0x7e, 0x49, 0x7f, 0xa2, 0xe0, 0x1d, 0x8e, 0x34, 0x92, 0x95,
-       0x17, 0x8a, 0xa2, 0x28, 0x90, 0x9d, 0xee, 0xe1, 0xe5, 0x7d, 0x1c, 0x5e, 0x9e, 0xa1, 0xa0, 0x3d,
-       0x88, 0x77, 0x27, 0x4a, 0x1a, 0x49, 0xea, 0x83, 0x38, 0x7c, 0x09, 0xfe, 0x2b, 0xa6, 0xaf, 0xc8,
-       0x3a, 0xd4, 0xa7, 0x7b, 0x41, 0xed, 0x49, 0xed, 0x8b, 0x26, 0xad, 0x4f, 0xf7, 0xd0, 0xde, 0x0f,
-       0xea, 0xce, 0xde, 0x47, 0xfb, 0x20, 0xf0, 0x9c, 0x7d, 0x80, 0xf6, 0x61, 0xe0, 0x3b, 0xfb, 0x30,
-       0xfc, 0x0e, 0x5a, 0x67, 0x4a, 0x8e, 0x14, 0x1b, 0x93, 0xcf, 0x01, 0xa6, 0xe3, 0x68, 0xca, 0x95,
-       0x16, 0x32, 0xc3, 0x90, 0x3e, 0xed, 0x4c, 0xc7, 0x97, 0x05, 0x40, 0x08, 0xf8, 0xb1, 0x4c, 0x38,
-       0xc6, 0x5e, 0xa3, 0xf8, 0x3b, 0xec, 0x43, 0xeb, 0x48, 0x6b, 0x6e, 0xfa, 0x27, 0xff, 0xb8, 0x90,
-       0x53, 0xe8, 0x62, 0xa8, 0xa3, 0xb1, 0xcc, 0x33, 0x43, 0x9e, 0x41, 0x9b, 0x59, 0x33, 0x12, 0x09,
-       0x06, 0xed, 0x1e, 0x74, 0x77, 0x07, 0xf1, 0xae, 0xcb, 0x46, 0x5b, 0xb8, 0xd8, 0x4f, 0xc8, 0x03,
-       0x68, 0x32, 0xdc, 0x81, 0xa9, 0x7c, 0xea, 0xac, 0x70, 0x04, 0x3d, 0xf4, 0x3d, 0xe1, 0x43, 0x91,
-       0x09, 0x63, 0x1b, 0xf8, 0x06, 0x36, 0x84, 0xd6, 0x39, 0xcb, 0x62, 0x1e, 0x4d, 0x8a, 0x9e, 0xab,
-       0xa1, 0x1d, 0x0d, 0xb4, 0x57, 0x3a, 0x95, 0xbc, 0x3c, 0x02, 0x3f, 0x61, 0x86, 0x61, 0x82, 0xee,
-       0x41, 0xdb, 0xfa, 0x5a, 0xea, 0x29, 0xa2, 0x61, 0x0a, 0xdd, 0x4b, 0x96, 0xe6, 0xfc, 0x5c, 0xe6,
-       0x2a, 0xe6, 0xe4, 0x21, 0x78, 0x8a, 0x0f, 0x5d, 0xdc, 0xb9, 0xaf, 0x05, 0xc9, 0x53, 0x68, 0x4c,
-       0xad, 0xab, 0x8b, 0xd4, 0x9b, 0x35, 0x54, 0xf4, 0x4c, 0x8b, 0x55, 0xf2, 0x10, 0xda, 0x13, 0xa9,
-       0xb1, 0x66, 0xe4, 0xcb, 0xa7, 0x33, 0x3b, 0xfc, 0x19, 0x36, 0x30, 0xdb, 0x09, 0xd7, 0x46, 0x64,
-       0x0c, 0xfb, 0xfa, 0x97, 0x53, 0x1e, 0x43, 0xe3, 0x4c, 0x49, 0x39, 0xb4, 0x03, 0xa0, 0xc5, 0xa8,
-       0x98, 0x8c, 0x35, 0x8a, 0xbf, 0xc9, 0x33, 0x58, 0x8f, 0x65, 0x66, 0x94, 0x4c, 0x1d, 0x5b, 0x6e,
-       0x3c, 0x96, 0xd0, 0xf0, 0x8d, 0x07, 0x1b, 0x2f, 0x6e, 0x8c, 0x1c, 0xbf, 0x48, 0x65, 0xfc, 0xd3,
-       0x2b, 0xce, 0x12, 0xae, 0x48, 0x00, 0xad, 0xc5, 0x69, 0x2b, 0x4d, 0x7b, 0xaa, 0x57, 0x5c, 0x8c,
-       0xae, 0x66, 0xa7, 0x5a, 0x58, 0xe4, 0x39, 0x6c, 0x4e, 0x14, 0x9f, 0x0a, 0x99, 0xeb, 0x68, 0x60,
-       0x23, 0xd9, 0xf1, 0xf0, 0x96, 0x1a, 0xef, 0x95, 0x2e, 0x98, 0xab, 0x9f, 0x90, 0x47, 0xd0, 0x31,
-       0x62, 0xcc, 0xb5, 0x61, 0xe3, 0x09, 0x4e, 0x9c, 0x4f, 0xe7, 0x00, 0xf9, 0x1a, 0x36, 0x8d, 0x62,
-       0x99, 0x66, 0xb1, 0x6d, 0x57, 0x47, 0x4a, 0x4a, 0x13, 0x34, 0x96, 0x62, 0x6e, 0x54, 0x5d, 0xa8,
-       0x94, 0x86, 0x7c, 0x0f, 0x9f, 0x55, 0xb0, 0x48, 0x1b, 0x66, 0x72, 0x1d, 0x5d, 0x31, 0x7d, 0x15,
-       0x34, 0x97, 0x36, 0xdf, 0xaf, 0x38, 0x9e, 0xa3, 0x1f, 0x5e, 0xdd, 0x6d, 0x68, 0x64, 0x32, 0x8b,
-       0x79, 0xd0, 0xc2, 0x92, 0x0a, 0xc3, 0xb2, 0x3c, 0x10, 0x46, 0x07, 0x6d, 0x04, 0xf1, 0x37, 0x39,
-       0x01, 0x72, 0x37, 0x57, 0xd0, 0xc1, 0x34, 0xf7, 0x6d, 0x9a, 0x8b, 0xe5, 0x04, 0x74, 0xf3, 0x4e,
-       0xce, 0xf0, 0x37, 0x0f, 0xba, 0x9f, 0xe8, 0xff, 0xaf, 0xe8, 0x27, 0x8f, 0xdd, 0x3d, 0x0a, 0x00,
-       0x37, 0x76, 0x9c, 0xe6, 0xc8, 0x21, 0x2d, 0xf0, 0xf0, 0xd7, 0x1a, 0xb4, 0x2f, 0xae, 0xdf, 0x7b,
-       0x38, 0x3b, 0xd0, 0xd3, 0x5c, 0x09, 0x96, 0x8a, 0x5b, 0x9e, 0x44, 0x5a, 0xdc, 0x72, 0x77, 0x4a,
-       0xeb, 0x73, 0xf8, 0x5c, 0xdc, 0x72, 0xab, 0xe7, 0x96, 0xe6, 0x48, 0xb1, 0x6c, 0xc4, 0xdd, 0xb5,
-       0x46, 0xe2, 0xa9, 0x05, 0xc8, 0x0e, 0x80, 0xe2, 0x3a, 0x4f, 0xad, 0xc4, 0xea, 0xc0, 0x7f, 0xe2,
-       0x2d, 0x90, 0xd6, 0x29, 0xd6, 0xfa, 0x89, 0x0e, 0xf7, 0x61, 0xfd, 0xe2, 0xfa, 0x92, 0x2b, 0x31,
-       0xbc, 0xa1, 0x08, 0x92, 0xc7, 0xd0, 0x75, 0x84, 0x0f, 0x99, 0x48, 0xb1, 0xc0, 0x36, 0x85, 0x02,
-       0x7a, 0xc9, 0x44, 0x1a, 0x0e, 0x61, 0xf3, 0x0e, 0x27, 0xef, 0x68, 0xe9, 0x5b, 0xb8, 0x37, 0xc5,
-       0xf8, 0x25, 0xb7, 0x75, 0xac, 0x86, 0x20, 0xb7, 0x0b, 0xa9, 0xe9, 0x5a, 0xe1, 0xe8, 0x46, 0xfa,
-       0xcf, 0x1a, 0x78, 0xa7, 0xf9, 0x35, 0xf9, 0x12, 0x5a, 0x1a, 0xf5, 0x57, 0x07, 0x35, 0xdc, 0x8a,
-       0x42, 0x57, 0xd1, 0x65, 0x5a, 0xae, 0x93, 0xa7, 0xd0, 0x9a, 0x54, 0xa4, 0x6a, 0x49, 0xfc, 0xcb,
-       0x35, 0xf2, 0x23, 0x6c, 0xff, 0x22, 0x4c, 0xc6, 0xb5, 0x8e, 0x92, 0xb9, 0xd6, 0xea, 0xc0, 0xc3,
-       0xf0, 0xdb, 0xb3, 0xf0, 0x15, 0x21, 0xa6, 0x5b, 0x6e, 0x47, 0x05, 0xd3, 0xe4, 0x2b, 0xd8, 0x2c,
-       0x03, 0x31, 0x35, 0xca, 0xc7, 0x3c, 0x33, 0x05, 0xdb, 0x6b, 0x74, 0xc3, 0x2d, 0x1c, 0x95, 0x78,
-       0x28, 0xa1, 0x7d, 0x2c, 0x45, 0x36, 0x60, 0x9a, 0x93, 0x1f, 0x60, 0x6b, 0x45, 0x05, 0x4e, 0xe6,
-       0x57, 0x17, 0x40, 0xee, 0x16, 0x60, 0x6f, 0x1f, 0x53, 0x03, 0x61, 0x14, 0x53, 0x37, 0x4e, 0x9c,
-       0xe7, 0x40, 0xf8, 0xa6, 0x06, 0xcd, 0xd7, 0xb9, 0x99, 0xe4, 0x86, 0xec, 0x40, 0xb3, 0xe0, 0xc8,
-       0xa5, 0xb8, 0x43, 0xa1, 0x5b, 0x26, 0xcf, 0xa1, 0xe7, 0xd4, 0x3d, 0x7a, 0x07, 0x93, 0x4b, 0x5f,
-       0x00, 0x7b, 0xfa, 0x52, 0x25, 0x22, 0x63, 0xa9, 0x1b, 0xc5, 0xd2, 0x0c, 0x5f, 0x03, 0x50, 0x6e,
-       0x84, 0xe2, 0x96, 0x83, 0x0f, 0x2f, 0xa3, 0x12, 0xb0, 0xbe, 0x18, 0xf0, 0xf7, 0x3a, 0xb4, 0xfb,
-       0xee, 0x23, 0x6e, 0xc7, 0x1c, 0x6f, 0x76, 0xa1, 0x0d, 0xcb, 0x1f, 0xc9, 0x0e, 0xae, 0xa1, 0x1e,
-       0x7c, 0xe0, 0xa7, 0xf2, 0x2d, 0xc7, 0xe2, 0x7d, 0xe4, 0xb1, 0x9c, 0x42, 0x30, 0x1b, 0x0b, 0x7c,
-       0xe7, 0x24, 0xb3, 0x87, 0x0a, 0x6a, 0x64, 0xf7, 0x60, 0x6b, 0x56, 0xc0, 0xfc, 0x0d, 0x43, 0x1f,
-       0x94, 0x23, 0xb3, 0xf4, 0xb6, 0x59, 0x39, 0x65, 0x8d, 0xd5, 0x53, 0x56, 0x65, 0xae, 0xb9, 0xc8,
-       0xdc, 0x1f, 0x35, 0x68, 0x9c, 0x4f, 0x78, 0x96, 0x90, 0x3d, 0xe8, 0xe9, 0x09, 0xcf, 0x4c, 0x24,
-       0x71, 0x3a, 0xe6, 0xcf, 0xb0, 0x39, 0x77, 0xf7, 0xd0, 0xa1, 0x98, 0x9e, 0x7e, 0xf2, 0x36, 0x62,
-       0xea, 0x1f, 0x49, 0xcc, 0xca, 0x4e, 0xbc, 0xf7, 0x77, 0xe2, 0x2f, 0x76, 0xf2, 0x57, 0x0d, 0x1a,
-       0xc7, 0x29, 0x13, 0xe3, 0xff, 0x7b, 0x27, 0x24, 0x84, 0xb5, 0x33, 0x3e, 0x12, 0x99, 0xdb, 0xe2,
-       0x4e, 0x75, 0x01, 0x1b, 0x34, 0xf1, 0x8f, 0xc1, 0xe1, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x9d,
-       0xe4, 0x01, 0xce, 0x24, 0x0c, 0x00, 0x00,
+       // 1011 bytes of a gzipped FileDescriptorProto
+       0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x57, 0xcd, 0x6e, 0x1b, 0x37,
+       0x10, 0x86, 0xb4, 0xab, 0xbf, 0x91, 0x63, 0xd9, 0xb4, 0x93, 0x2e, 0x82, 0x14, 0x09, 0x16, 0x48,
+       0xdc, 0xa2, 0x80, 0x61, 0xcb, 0x69, 0x7b, 0xe9, 0xa1, 0x8e, 0xdd, 0x34, 0x3a, 0x18, 0x31, 0x68,
+       0xc3, 0xd7, 0x05, 0xb5, 0x4b, 0xc9, 0x44, 0x57, 0x4b, 0x95, 0xe4, 0xaa, 0xb6, 0x6f, 0x7d, 0x88,
+       0xa2, 0xa7, 0x3e, 0x47, 0x1f, 0xa1, 0xa7, 0x3e, 0x49, 0x5f, 0xa2, 0xe0, 0x2c, 0x57, 0x5a, 0xc9,
+       0xce, 0x1f, 0x8a, 0xa2, 0x28, 0x90, 0xdb, 0xce, 0x70, 0xf8, 0xcd, 0xcc, 0x37, 0xc3, 0x21, 0x17,
+       0xda, 0xc3, 0x78, 0x77, 0xaa, 0xa4, 0x91, 0xa4, 0x3e, 0x8c, 0xc3, 0x97, 0xe0, 0xbf, 0x62, 0xfa,
+       0x92, 0xac, 0x43, 0x7d, 0xb6, 0x17, 0xd4, 0x9e, 0xd4, 0x3e, 0x6b, 0xd2, 0xfa, 0x6c, 0x0f, 0xe5,
+       0xfd, 0xa0, 0xee, 0xe4, 0x7d, 0x94, 0xfb, 0x81, 0xe7, 0xe4, 0x3e, 0xca, 0x07, 0x81, 0xef, 0xe4,
+       0x83, 0xf0, 0x1b, 0x68, 0x9d, 0x2a, 0x39, 0x56, 0x6c, 0x42, 0x3e, 0x05, 0x98, 0x4d, 0xa2, 0x19,
+       0x57, 0x5a, 0xc8, 0x0c, 0x21, 0x7d, 0xda, 0x99, 0x4d, 0x2e, 0x0a, 0x05, 0x21, 0xe0, 0xc7, 0x32,
+       0xe1, 0x88, 0xbd, 0x46, 0xf1, 0x3b, 0x1c, 0x40, 0xeb, 0x50, 0x6b, 0x6e, 0x06, 0xc7, 0xff, 0x38,
+       0x90, 0x13, 0xe8, 0x22, 0xd4, 0xe1, 0x44, 0xe6, 0x99, 0x21, 0xcf, 0xa0, 0xcd, 0xac, 0x18, 0x89,
+       0x04, 0x41, 0xbb, 0xfd, 0xee, 0xee, 0x30, 0xde, 0x75, 0xde, 0x68, 0x0b, 0x17, 0x07, 0x09, 0x79,
+       0x00, 0x4d, 0x86, 0x3b, 0xd0, 0x95, 0x4f, 0x9d, 0x14, 0x8e, 0xa1, 0x87, 0xb6, 0xc7, 0x7c, 0x24,
+       0x32, 0x61, 0x6c, 0x02, 0x5f, 0xc1, 0x86, 0xd0, 0x3a, 0x67, 0x59, 0xcc, 0xa3, 0x69, 0x91, 0x73,
+       0x15, 0xda, 0xd1, 0x40, 0x7b, 0xa5, 0x51, 0xc9, 0xcb, 0x23, 0xf0, 0x13, 0x66, 0x18, 0x3a, 0xe8,
+       0xf6, 0xdb, 0xd6, 0xd6, 0x52, 0x4f, 0x51, 0x1b, 0xa6, 0xd0, 0xbd, 0x60, 0x69, 0xce, 0xcf, 0x64,
+       0xae, 0x62, 0x4e, 0x1e, 0x82, 0xa7, 0xf8, 0xc8, 0xe1, 0x2e, 0x6c, 0xad, 0x92, 0x3c, 0x85, 0xc6,
+       0xcc, 0x9a, 0x3a, 0xa4, 0xde, 0x3c, 0xa1, 0x22, 0x67, 0x5a, 0xac, 0x92, 0x87, 0xd0, 0x9e, 0x4a,
+       0x8d, 0x31, 0x23, 0x5f, 0x3e, 0x9d, 0xcb, 0xe1, 0x8f, 0xb0, 0x81, 0xde, 0x8e, 0xb9, 0x36, 0x22,
+       0x63, 0x98, 0xd7, 0xbf, 0xec, 0xf2, 0x08, 0x1a, 0xa7, 0x4a, 0xca, 0x91, 0x6d, 0x00, 0x2d, 0xc6,
+       0x45, 0x67, 0xac, 0x51, 0xfc, 0x26, 0xcf, 0x60, 0x3d, 0x96, 0x99, 0x51, 0x32, 0x75, 0x6c, 0xb9,
+       0xf6, 0x58, 0xd1, 0x86, 0xbf, 0x7a, 0xb0, 0xf1, 0xe2, 0xda, 0xc8, 0xc9, 0x8b, 0x54, 0xc6, 0x3f,
+       0xbc, 0xe2, 0x2c, 0xe1, 0x8a, 0x04, 0xd0, 0x5a, 0xee, 0xb6, 0x52, 0xb4, 0x55, 0xbd, 0xe4, 0x62,
+       0x7c, 0x39, 0xaf, 0x6a, 0x21, 0x91, 0xe7, 0xb0, 0x39, 0x55, 0x7c, 0x26, 0x64, 0xae, 0xa3, 0xa1,
+       0x45, 0xb2, 0xed, 0xe1, 0xad, 0x24, 0xde, 0x2b, 0x4d, 0xd0, 0xd7, 0x20, 0x21, 0x8f, 0xa0, 0x63,
+       0xc4, 0x84, 0x6b, 0xc3, 0x26, 0x53, 0xec, 0x38, 0x9f, 0x2e, 0x14, 0xe4, 0x4b, 0xd8, 0x34, 0x8a,
+       0x65, 0x9a, 0xc5, 0x36, 0x5d, 0x1d, 0x29, 0x29, 0x4d, 0xd0, 0x58, 0xc1, 0xdc, 0xa8, 0x9a, 0x50,
+       0x29, 0x0d, 0xf9, 0x16, 0x3e, 0xa9, 0xe8, 0x22, 0x6d, 0x98, 0xc9, 0x75, 0x74, 0xc9, 0xf4, 0x65,
+       0xd0, 0x5c, 0xd9, 0x7c, 0xbf, 0x62, 0x78, 0x86, 0x76, 0x78, 0x74, 0xb7, 0xa1, 0x91, 0xc9, 0x2c,
+       0xe6, 0x41, 0x0b, 0x43, 0x2a, 0x04, 0xcb, 0xf2, 0x50, 0x18, 0x1d, 0xb4, 0x51, 0x89, 0xdf, 0xe4,
+       0x18, 0xc8, 0x6d, 0x5f, 0x41, 0x07, 0xdd, 0xdc, 0xb7, 0x6e, 0xce, 0x57, 0x1d, 0xd0, 0xcd, 0x5b,
+       0x3e, 0xad, 0x3f, 0x7e, 0x65, 0x14, 0x0b, 0x00, 0x4b, 0x54, 0x08, 0xe1, 0x6f, 0x1e, 0x74, 0x3f,
+       0x16, 0xe5, 0x3f, 0x2b, 0xca, 0x63, 0x77, 0xba, 0xb0, 0x28, 0xdd, 0x7e, 0xc7, 0x4d, 0x22, 0x39,
+       0xa2, 0x85, 0x3e, 0xfc, 0xa5, 0x06, 0xed, 0xf3, 0xab, 0x77, 0x16, 0x67, 0x07, 0x7a, 0x9a, 0x2b,
+       0xc1, 0x52, 0x71, 0xc3, 0x93, 0x48, 0x8b, 0x1b, 0xee, 0xaa, 0xb4, 0xbe, 0x50, 0x9f, 0x89, 0x1b,
+       0x6e, 0xa7, 0xbc, 0xa5, 0x39, 0x52, 0x2c, 0x1b, 0x73, 0x77, 0xd8, 0x91, 0x78, 0x6a, 0x15, 0x64,
+       0x07, 0x40, 0x71, 0x9d, 0xa7, 0x76, 0xf0, 0xea, 0xc0, 0x7f, 0xe2, 0x2d, 0x91, 0xd6, 0x29, 0xd6,
+       0x06, 0x89, 0x0e, 0xf7, 0x61, 0xfd, 0xfc, 0xea, 0x82, 0x2b, 0x31, 0xba, 0xa6, 0xa8, 0x24, 0x8f,
+       0xa1, 0xeb, 0x08, 0x1f, 0x31, 0x91, 0x62, 0x80, 0x6d, 0x0a, 0x85, 0xea, 0x25, 0x13, 0x69, 0x38,
+       0x82, 0xcd, 0x5b, 0x9c, 0xbc, 0x25, 0xa5, 0xaf, 0xe1, 0xde, 0x0c, 0xf1, 0x4b, 0x6e, 0xeb, 0x18,
+       0x0d, 0x41, 0x6e, 0x97, 0x5c, 0xd3, 0xb5, 0xc2, 0xb0, 0x80, 0x0c, 0xff, 0xac, 0x81, 0x77, 0x92,
+       0x5f, 0x91, 0xcf, 0xa1, 0xa5, 0x71, 0x2a, 0xeb, 0xa0, 0x86, 0x5b, 0x71, 0xfc, 0x55, 0xa6, 0x35,
+       0x2d, 0xd7, 0xc9, 0x53, 0x68, 0x4d, 0x2b, 0x03, 0x6c, 0xe5, 0x4a, 0x28, 0xd7, 0xc8, 0xf7, 0xb0,
+       0xfd, 0x93, 0x30, 0x19, 0xd7, 0x3a, 0x4a, 0x16, 0x13, 0x58, 0x07, 0x1e, 0xc2, 0x6f, 0xcf, 0xe1,
+       0x2b, 0xe3, 0x99, 0x6e, 0xb9, 0x1d, 0x15, 0x9d, 0x26, 0x5f, 0xc0, 0x66, 0x09, 0xc4, 0xd4, 0x38,
+       0x9f, 0xf0, 0xcc, 0x14, 0x6c, 0xaf, 0xd1, 0x0d, 0xb7, 0x70, 0x58, 0xea, 0x43, 0x09, 0xed, 0x23,
+       0x29, 0xb2, 0x21, 0xd3, 0x9c, 0x7c, 0x07, 0x5b, 0x77, 0x44, 0xe0, 0x86, 0xff, 0xdd, 0x01, 0x90,
+       0xdb, 0x01, 0xd8, 0xd3, 0xc7, 0xd4, 0x50, 0x18, 0xc5, 0xd4, 0xb5, 0x1b, 0xd9, 0x0b, 0x45, 0xf8,
+       0x73, 0x0d, 0x9a, 0xaf, 0x73, 0x33, 0xcd, 0x0d, 0xd9, 0x81, 0x66, 0xc1, 0x91, 0x73, 0x71, 0x8b,
+       0x42, 0xb7, 0x4c, 0x9e, 0x43, 0xcf, 0xcd, 0xfc, 0xe8, 0x2d, 0x4c, 0xae, 0xdc, 0x0b, 0xb6, 0xfa,
+       0x52, 0x25, 0x22, 0x63, 0xa9, 0x6b, 0xc5, 0x52, 0x0c, 0x5f, 0x03, 0x50, 0x6e, 0x84, 0xe2, 0x96,
+       0x83, 0xf7, 0x0f, 0xa3, 0x02, 0x58, 0x5f, 0x06, 0xfc, 0xbd, 0x0e, 0xed, 0x81, 0xbb, 0xda, 0x6d,
+       0x9b, 0xe3, 0xc9, 0x2e, 0x66, 0xc3, 0xea, 0xd5, 0xd9, 0xc1, 0x35, 0x9c, 0x07, 0xef, 0x79, 0x81,
+       0xbe, 0xa1, 0x2c, 0xde, 0x07, 0x96, 0xe5, 0x04, 0x82, 0x79, 0x5b, 0xe0, 0xeb, 0x27, 0x99, 0x3f,
+       0x5f, 0x70, 0x46, 0x76, 0xfb, 0x5b, 0xf3, 0x00, 0x16, 0x2f, 0x1b, 0xfa, 0xa0, 0x6c, 0x99, 0x95,
+       0x17, 0xcf, 0x9d, 0x5d, 0xd6, 0xb8, 0xbb, 0xcb, 0xaa, 0xcc, 0x35, 0x97, 0x99, 0xfb, 0xa3, 0x06,
+       0x8d, 0xb3, 0x29, 0xcf, 0x12, 0xb2, 0x07, 0x3d, 0x3d, 0xe5, 0x99, 0x89, 0x24, 0x76, 0xc7, 0xe2,
+       0x71, 0xb6, 0xe0, 0xee, 0x1e, 0x1a, 0x14, 0xdd, 0x33, 0x48, 0xde, 0x44, 0x4c, 0xfd, 0x03, 0x89,
+       0xb9, 0x33, 0x13, 0xef, 0xdd, 0x99, 0xf8, 0xcb, 0x99, 0xfc, 0x55, 0x83, 0xc6, 0x51, 0xca, 0xc4,
+       0xe4, 0xff, 0x9e, 0x09, 0x09, 0x61, 0xed, 0x94, 0x8f, 0x45, 0xe6, 0xb6, 0xb8, 0xaa, 0x2e, 0xe9,
+       0x86, 0x4d, 0xfc, 0x5d, 0x38, 0xf8, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x25, 0x3b, 0x75, 0x3a, 0x3a,
+       0x0c, 0x00, 0x00,
 }
index b12c67d..596f5bd 100644 (file)
@@ -63,6 +63,7 @@ message BytomBlockHeader {
   uint64            nonce                   = 7;
   uint64            bits                    = 8;
   TransactionStatus transaction_status      = 9;
+  bytes             extra                   = 10;
 }
 
 message BlockHeader {