OSDN Git Service

Bytom spv client implement
authorYahtoo Ma <yahtoo.ma@gmail.com>
Tue, 21 Aug 2018 06:55:58 +0000 (14:55 +0800)
committerYahtoo Ma <yahtoo.ma@gmail.com>
Wed, 22 Aug 2018 07:30:17 +0000 (15:30 +0800)
consensus/general.go
netsync/block_keeper.go
netsync/message.go
test/block_test.go

index 3c5453d..041b9c2 100644 (file)
@@ -126,6 +126,7 @@ var TestNetParams = Params{
                {1000, bc.NewHash([32]byte{0x28, 0x29, 0xc9, 0xe2, 0x19, 0x0f, 0xfe, 0xb6, 0xf2, 0x73, 0xde, 0x1a, 0xe8, 0x1f, 0xa6, 0xbc, 0x15, 0xaa, 0x08, 0xa9, 0xb8, 0x4c, 0x43, 0x25, 0x9a, 0xa0, 0x24, 0x8a, 0xd8, 0x55, 0x73, 0xca})},
                {1500, bc.NewHash([32]byte{0xc2, 0x94, 0x02, 0xd1, 0x6c, 0xa8, 0x18, 0xc4, 0x95, 0x67, 0x48, 0xb8, 0xa8, 0x42, 0xa2, 0x69, 0x8e, 0xdd, 0xb2, 0xa9, 0xb6, 0xd9, 0x30, 0xf4, 0x12, 0xdb, 0x0f, 0x1e, 0x58, 0xc9, 0x69, 0x3b})},
                {10303, bc.NewHash([32]byte{0x3e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c})},
+               {21920, bc.NewHash([32]byte{0x3c, 0x5f, 0xb2, 0x7d, 0xb9, 0x97, 0xfe, 0x6f, 0xfa, 0x85, 0x4a, 0xfc, 0x2f, 0x01, 0x63, 0x8b, 0x5e, 0xbb, 0xcf, 0x2e, 0x41, 0x89, 0x88, 0xf7, 0x0d, 0xf0, 0xfe, 0xdd, 0x4d, 0x68, 0x4e, 0x13})},
        },
 }
 
index ecda353..7433ff5 100644 (file)
@@ -14,10 +14,11 @@ import (
 )
 
 const (
-       syncCycle            = 5 * time.Second
-       blockProcessChSize   = 1024
-       blocksProcessChSize  = 128
-       headersProcessChSize = 1024
+       syncCycle                 = 5 * time.Second
+       blockProcessChSize        = 1024
+       blocksProcessChSize       = 128
+       headersProcessChSize      = 1024
+       merkleBlocksProcessChSize = 128
 )
 
 var (
@@ -67,12 +68,14 @@ type blockKeeper struct {
 
 func newBlockKeeper(chain Chain, peers *peerSet) *blockKeeper {
        bk := &blockKeeper{
-               chain:            chain,
-               peers:            peers,
-               blockProcessCh:   make(chan *blockMsg, blockProcessChSize),
-               blocksProcessCh:  make(chan *blocksMsg, blocksProcessChSize),
-               headersProcessCh: make(chan *headersMsg, headersProcessChSize),
-               headerList:       list.New(),
+               chain:                chain,
+               peers:                peers,
+               blockProcessCh:       make(chan *blockMsg, blockProcessChSize),
+               blocksProcessCh:      make(chan *blocksMsg, blocksProcessChSize),
+               headersProcessCh:     make(chan *headersMsg, headersProcessChSize),
+               merkleBlockProcessCh: make(chan *merkleBlockMsg, merkleBlocksProcessChSize),
+
+               headerList: list.New(),
        }
        bk.resetHeaderState()
        go bk.syncWorker()
@@ -157,7 +160,7 @@ func (bk *blockKeeper) fastBlockSync(checkPoint *consensus.Checkpoint) error {
        }
 
        fastHeader := bk.headerList.Front()
-       for bk.chain.BestBlockHeight() < checkPoint.Height {
+       for bk.chain.BestBlockHeight() <= checkPoint.Height {
                hash := fastHeader.Value.(*types.BlockHeader).Hash()
                merkleBlock, err := bk.requireMerkleBlock(fastHeader.Value.(*types.BlockHeader).Height, &hash)
                if err != nil {
@@ -165,9 +168,9 @@ func (bk *blockKeeper) fastBlockSync(checkPoint *consensus.Checkpoint) error {
                }
                bk.VerifyMerkleBlock(fastHeader.Value.(*types.BlockHeader), merkleBlock)
                blockHash := merkleBlock.Hash()
-               //if blockHash != fastHeader.Value.(*types.BlockHeader).Hash() {
-               //      return errPeerMisbehave
-               //}
+               if blockHash != fastHeader.Value.(*types.BlockHeader).Hash() {
+                       return errPeerMisbehave
+               }
                seed, err := bk.chain.CalcNextSeed(&merkleBlock.PreviousBlockHash)
                if err != nil {
                        return errors.Wrap(err, "fail on fastBlockSync calculate seed")
@@ -178,46 +181,10 @@ func (bk *blockKeeper) fastBlockSync(checkPoint *consensus.Checkpoint) error {
                if err != nil {
                        return errors.Wrap(err, "fail on fastBlockSync process block")
                }
+               if fastHeader = fastHeader.Next(); fastHeader == nil {
+                       return nil
+               }
        }
-       //locator := bk.blockLocator()
-       //blocks, err := bk.requireBlocks(locator, &checkPoint.Hash)
-       //if err != nil {
-       //      return err
-       //}
-       //
-       //if len(blocks) == 0 {
-       //      return errors.Wrap(errPeerMisbehave, "requireBlocks return empty list")
-       //}
-       //      for ;fastHeader = fastHeader.Next(); fastHeader == nil {
-       //      blocks, err := bk.requireMerkleBlock(fastHeader.Value.(*types.BlockHeader).Height, fastHeader.Value.(*types.BlockHeader).Hash())
-       //      if err != nil {
-       //      return err
-       //}
-
-       //}
-       //for _, block := range blocks {
-       //      if fastHeader = fastHeader.Next(); fastHeader == nil {
-       //              return errors.New("get block than is higher than checkpoint")
-       //      }
-       //
-       //      blockHash := block.Hash()
-       //      if blockHash != fastHeader.Value.(*types.BlockHeader).Hash() {
-       //              return errPeerMisbehave
-       //      }
-       //
-       //      seed, err := bk.chain.CalcNextSeed(&block.PreviousBlockHash)
-       //      if err != nil {
-       //              return errors.Wrap(err, "fail on fastBlockSync calculate seed")
-       //      }
-       //
-       //      tensority.AIHash.AddCache(&blockHash, seed, &bc.Hash{})
-       //      _, err = bk.chain.ProcessBlock(block)
-       //      tensority.AIHash.RemoveCache(&blockHash, seed)
-       //      if err != nil {
-       //              return errors.Wrap(err, "fail on fastBlockSync process block")
-       //      }
-       //}
-       //}
        return nil
 }
 
index 8431dca..8d1021b 100644 (file)
@@ -27,8 +27,8 @@ const (
        NewTransactionByte  = byte(0x30)
        NewMineBlockByte    = byte(0x40)
        FilterLoadByte      = byte(0x50)
-       FilterClearByte     = byte(0x51)
-       FilterAddByte       = byte(0x52)
+       FilterAddByte       = byte(0x51)
+       FilterClearByte     = byte(0x52)
        MerkleRequestByte   = byte(0x60)
        MerkleResponseByte  = byte(0x61)
 
@@ -51,8 +51,8 @@ var _ = wire.RegisterInterface(
        wire.ConcreteType{&TransactionMessage{}, NewTransactionByte},
        wire.ConcreteType{&MineBlockMessage{}, NewMineBlockByte},
        wire.ConcreteType{&FilterLoadMessage{}, FilterLoadByte},
-       wire.ConcreteType{&FilterClearMessage{}, FilterClearByte},
        wire.ConcreteType{&FilterAddMessage{}, FilterAddByte},
+       wire.ConcreteType{&FilterClearMessage{}, FilterClearByte},
        wire.ConcreteType{&GetMerkleBlockMessage{}, MerkleRequestByte},
        wire.ConcreteType{&MerkleBlockMessage{}, MerkleResponseByte},
 )
@@ -362,12 +362,12 @@ func NewFilterLoadMessage(addresses [][]byte) (*FilterLoadMessage, error) {
 
 //FilterLoadMessage new load addresses msg
 type FilterAddMessage struct {
-       Addresse []byte
+       Address []byte
 }
 
 //NewMinedBlockMessage construct new mined block msg
 func NewFilterAddMessage(addresse []byte) (*FilterAddMessage, error) {
-       return &FilterAddMessage{Addresse: addresse}, nil
+       return &FilterAddMessage{Address: addresse}, nil
 }
 
 //FilterClearMessage tells the receiving peer to remove a previously-set filter.
index 3953c96..0fc1c62 100644 (file)
@@ -13,6 +13,9 @@ import (
        "github.com/bytom/protocol/bc"
        "github.com/bytom/protocol/bc/types"
        "github.com/bytom/protocol/vm"
+       "github.com/bytom/protocol"
+       "github.com/bytom/protocol/validation"
+       "fmt"
 )
 
 func TestBlockHeader(t *testing.T) {
@@ -195,3 +198,108 @@ func TestMaxBlockGas(t *testing.T) {
                t.Fatalf("test max block gas failed")
        }
 }
+
+// NewBlock create block according to the current status of chain
+func NewMerkleBlock(chain *protocol.Chain, txs []*types.Tx, controlProgram []byte) (*types.Block, error) {
+       gasUsed := uint64(0)
+       txsFee := uint64(0)
+       txEntries := []*bc.Tx{nil}
+       txStatus := bc.NewTransactionStatus()
+       txStatus.SetStatus(0, false)
+
+       preBlockHeader := chain.BestBlockHeader()
+       preBlockHash := preBlockHeader.Hash()
+       nextBits, err := chain.CalcNextBits(&preBlockHash)
+       if err != nil {
+               return nil, err
+       }
+
+       b := &types.Block{
+               BlockHeader: types.BlockHeader{
+                       Version:           1,
+                       Height:            preBlockHeader.Height + 1,
+                       PreviousBlockHash: preBlockHeader.Hash(),
+                       Timestamp:         preBlockHeader.Timestamp + 1,
+                       BlockCommitment:   types.BlockCommitment{},
+                       Bits:              nextBits,
+               },
+               Transactions: []*types.Tx{nil},
+       }
+
+       bcBlock := &bc.Block{BlockHeader: &bc.BlockHeader{Height: preBlockHeader.Height + 1}}
+       for _, tx := range txs {
+               gasOnlyTx := false
+               gasStatus, err := validation.ValidateTx(tx.Tx, bcBlock)
+               if err != nil {
+                       if !gasStatus.GasValid {
+                               continue
+                       }
+                       gasOnlyTx = true
+               }
+
+               txStatus.SetStatus(len(b.Transactions), gasOnlyTx)
+               b.Transactions = append(b.Transactions, tx)
+               txEntries = append(txEntries, tx.Tx)
+               gasUsed += uint64(gasStatus.GasUsed)
+               txsFee += txFee(tx)
+       }
+
+       coinbaseTx, err := CreateCoinbaseTx(controlProgram, preBlockHeader.Height+1, txsFee)
+       if err != nil {
+               return nil, err
+       }
+
+       b.Transactions[0] = coinbaseTx
+       txEntries[0] = coinbaseTx.Tx
+       b.TransactionsMerkleRoot, err = bc.TxMerkleRoot(txEntries)
+       if err != nil {
+               return nil, err
+       }
+
+       b.TransactionStatusHash, err = bc.TxStatusMerkleRoot(txStatus.VerifyStatus)
+       b.Transactions = b.Transactions[1:len(b.Transactions)/2]
+       return b, err
+}
+
+func TestMerkleBlock(t *testing.T) {
+       chainDB := dbm.NewDB("test_block_db", "leveldb", "test_block_db")
+       defer os.RemoveAll("test_block_db")
+       chain, _, _, err := MockChain(chainDB)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       if err := AppendBlocks(chain, 7); err != nil {
+               t.Fatal(err)
+       }
+
+       block, err := chain.GetBlockByHeight(1)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       tx, err := CreateTxFromTx(block.Transactions[0], 0, 600000000000, []byte{byte(vm.OP_TRUE)})
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       outputAmount := uint64(600000000000)
+       txs := []*types.Tx{tx}
+       for i := 1; i < 50000; i++ {
+               outputAmount -= 10000000
+               tx, err := CreateTxFromTx(txs[i-1], 0, outputAmount, []byte{byte(vm.OP_TRUE)})
+               if err != nil {
+                       t.Fatal(err)
+               }
+               txs = append(txs, tx)
+       }
+
+       block, err = NewMerkleBlock(chain, txs, []byte{byte(vm.OP_TRUE)})
+       if err != nil {
+               t.Fatal(err)
+       }
+       fmt.Println(len(block.Transactions))
+       if err := SolveAndUpdate(chain, block); err == nil {
+               t.Fatalf("test max block gas failed")
+       }
+}
\ No newline at end of file