OSDN Git Service

init version of edit block header (#389)
[bytom/bytom.git] / protocol / protocol.go
old mode 100644 (file)
new mode 100755 (executable)
index 5f29f5d..b859229
@@ -6,6 +6,7 @@ import (
        "time"
 
        "github.com/bytom/blockchain/txdb"
+       "github.com/bytom/blockchain/txdb/storage"
        "github.com/bytom/errors"
        "github.com/bytom/protocol/bc"
        "github.com/bytom/protocol/bc/legacy"
@@ -33,15 +34,16 @@ type Store interface {
 
        GetBlock(*bc.Hash) (*legacy.Block, error)
        GetMainchain(*bc.Hash) (map[uint64]*bc.Hash, error)
-       GetSnapshot(*bc.Hash) (*state.Snapshot, error)
        GetStoreStatus() txdb.BlockStoreStateJSON
+       GetTransactionStatus(*bc.Hash) (*bc.TransactionStatus, error)
+       GetTransactionsUtxo(*state.UtxoViewpoint, []*bc.Tx) error
+       GetUtxo(*bc.Hash) (*storage.UtxoEntry, error)
 
-       SaveBlock(*legacy.Block) error
-       SaveMainchain(map[uint64]*bc.Hash, *bc.Hash) error
-       SaveSnapshot(*state.Snapshot, *bc.Hash) error
-       SaveStoreStatus(uint64, *bc.Hash)
+       SaveBlock(*legacy.Block, *bc.TransactionStatus) error
+       SaveChainStatus(*legacy.Block, *state.UtxoViewpoint, map[uint64]*bc.Hash) error
 }
 
+// OrphanManage is use to handle all the orphan block
 type OrphanManage struct {
        //TODO: add orphan cached block limit
        orphan     map[bc.Hash]*legacy.Block
@@ -49,6 +51,7 @@ type OrphanManage struct {
        mtx        sync.RWMutex
 }
 
+// NewOrphanManage return a new orphan block
 func NewOrphanManage() *OrphanManage {
        return &OrphanManage{
                orphan:     make(map[bc.Hash]*legacy.Block),
@@ -56,6 +59,7 @@ func NewOrphanManage() *OrphanManage {
        }
 }
 
+// BlockExist check is the block in OrphanManage
 func (o *OrphanManage) BlockExist(hash *bc.Hash) bool {
        o.mtx.RLock()
        _, ok := o.orphan[*hash]
@@ -63,6 +67,7 @@ func (o *OrphanManage) BlockExist(hash *bc.Hash) bool {
        return ok
 }
 
+// Add will add the block to OrphanManage
 func (o *OrphanManage) Add(block *legacy.Block) {
        blockHash := block.Hash()
        o.mtx.Lock()
@@ -76,6 +81,7 @@ func (o *OrphanManage) Add(block *legacy.Block) {
        o.preOrphans[block.PreviousBlockHash] = append(o.preOrphans[block.PreviousBlockHash], &blockHash)
 }
 
+// Delete will delelte the block from OrphanManage
 func (o *OrphanManage) Delete(hash *bc.Hash) {
        o.mtx.Lock()
        defer o.mtx.Unlock()
@@ -99,6 +105,7 @@ func (o *OrphanManage) Delete(hash *bc.Hash) {
        }
 }
 
+// Get return the orphan block by hash
 func (o *OrphanManage) Get(hash *bc.Hash) (*legacy.Block, bool) {
        o.mtx.RLock()
        block, ok := o.orphan[*hash]
@@ -120,10 +127,8 @@ type Chain struct {
        state struct {
                cond      sync.Cond
                block     *legacy.Block
-               height    uint64
                hash      *bc.Hash
                mainChain map[uint64]*bc.Hash
-               snapshot  *state.Snapshot
        }
        store Store
 }
@@ -138,10 +143,8 @@ func NewChain(initialBlockHash bc.Hash, store Store, txPool *TxPool) (*Chain, er
        }
        c.state.cond.L = new(sync.Mutex)
        storeStatus := store.GetStoreStatus()
-       c.state.height = storeStatus.Height
 
-       if c.state.height == 0 {
-               c.state.snapshot = state.Empty()
+       if storeStatus.Hash == nil {
                c.state.mainChain = make(map[uint64]*bc.Hash)
                return c, nil
        }
@@ -151,9 +154,6 @@ func NewChain(initialBlockHash bc.Hash, store Store, txPool *TxPool) (*Chain, er
        if c.state.block, err = store.GetBlock(storeStatus.Hash); err != nil {
                return nil, err
        }
-       if c.state.snapshot, err = store.GetSnapshot(storeStatus.Hash); err != nil {
-               return nil, err
-       }
        if c.state.mainChain, err = store.GetMainchain(storeStatus.Hash); err != nil {
                return nil, err
        }
@@ -164,7 +164,17 @@ func NewChain(initialBlockHash bc.Hash, store Store, txPool *TxPool) (*Chain, er
 func (c *Chain) Height() uint64 {
        c.state.cond.L.Lock()
        defer c.state.cond.L.Unlock()
-       return c.state.height
+       if c.state.block == nil {
+               return 0
+       }
+       return c.state.block.Height
+}
+
+// BestBlockHash return the hash of the chain tail block
+func (c *Chain) BestBlockHash() *bc.Hash {
+       c.state.cond.L.Lock()
+       defer c.state.cond.L.Unlock()
+       return c.state.hash
 }
 
 func (c *Chain) inMainchain(block *legacy.Block) bool {
@@ -175,47 +185,62 @@ func (c *Chain) inMainchain(block *legacy.Block) bool {
        return *hash == block.Hash()
 }
 
-// TimestampMS returns the latest known block timestamp.
-func (c *Chain) TimestampMS() uint64 {
+// InMainChain checks wheather a block is in the main chain
+func (c *Chain) InMainChain(height uint64, hash bc.Hash) bool {
+       c.state.cond.L.Lock()
+       h, ok := c.state.mainChain[height]
+       c.state.cond.L.Unlock()
+       if !ok {
+               return false
+       }
+
+       return *h == hash
+}
+
+// Timestamp returns the latest known block timestamp.
+func (c *Chain) Timestamp() uint64 {
        c.state.cond.L.Lock()
        defer c.state.cond.L.Unlock()
        if c.state.block == nil {
                return 0
        }
-       return c.state.block.TimestampMS
+       return c.state.block.Timestamp
 }
 
-// State returns the most recent state available. It will not be current
-// unless the current process is the leader. Callers should examine the
-// returned block header's height if they need to verify the current state.
-func (c *Chain) State() (*legacy.Block, *state.Snapshot) {
+// BestBlock returns the chain tail block
+func (c *Chain) BestBlock() *legacy.Block {
        c.state.cond.L.Lock()
        defer c.state.cond.L.Unlock()
-       return c.state.block, c.state.snapshot
+       return c.state.block
 }
 
-// This function must be called with mu lock in above level
-func (c *Chain) setState(block *legacy.Block, s *state.Snapshot, m map[uint64]*bc.Hash) error {
-       if block.AssetsMerkleRoot != s.Tree.RootHash() {
-               return ErrBadStateRoot
-       }
+// GetUtxo try to find the utxo status in db
+func (c *Chain) GetUtxo(hash *bc.Hash) (*storage.UtxoEntry, error) {
+       return c.store.GetUtxo(hash)
+}
 
+// GetTransactionStatus return the transaction status of give block
+func (c *Chain) GetTransactionStatus(hash *bc.Hash) (*bc.TransactionStatus, error) {
+       return c.store.GetTransactionStatus(hash)
+}
+
+// GetTransactionsUtxo return all the utxos that related to the txs' inputs
+func (c *Chain) GetTransactionsUtxo(view *state.UtxoViewpoint, txs []*bc.Tx) error {
+       return c.store.GetTransactionsUtxo(view, txs)
+}
+
+// This function must be called with mu lock in above level
+func (c *Chain) setState(block *legacy.Block, view *state.UtxoViewpoint, m map[uint64]*bc.Hash) error {
        blockHash := block.Hash()
        c.state.block = block
-       c.state.height = block.Height
        c.state.hash = &blockHash
-       c.state.snapshot = s
        for k, v := range m {
                c.state.mainChain[k] = v
        }
 
-       if err := c.store.SaveSnapshot(c.state.snapshot, &blockHash); err != nil {
-               return err
-       }
-       if err := c.store.SaveMainchain(c.state.mainChain, &blockHash); err != nil {
+       if err := c.store.SaveChainStatus(block, view, c.state.mainChain); err != nil {
                return err
        }
-       c.store.SaveStoreStatus(block.Height, &blockHash)
 
        c.state.cond.Broadcast()
        return nil
@@ -254,7 +279,7 @@ func (c *Chain) BlockWaiter(height uint64) <-chan struct{} {
        go func() {
                c.state.cond.L.Lock()
                defer c.state.cond.L.Unlock()
-               for c.state.height < height {
+               for c.state.block.Height < height {
                        c.state.cond.Wait()
                }
                ch <- struct{}{}