本文整理匯總了Golang中github.com/decred/dcrd/wire.BlockHeader類的典型用法代碼示例。如果您正苦於以下問題:Golang BlockHeader類的具體用法?Golang BlockHeader怎麽用?Golang BlockHeader使用的例子?那麽, 這裏精選的類代碼示例或許可以為您提供幫助。
在下文中一共展示了BlockHeader類的13個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: extendMainChain
func (w *Wallet) extendMainChain(dbtx walletdb.ReadWriteTx, block *wtxmgr.BlockHeaderData, transactions [][]byte) error {
txmgrNs := dbtx.ReadWriteBucket(wtxmgrNamespaceKey)
log.Infof("Connecting block %v, height %v", block.BlockHash,
block.SerializedHeader.Height())
err := w.TxStore.ExtendMainChain(txmgrNs, block)
if err != nil {
return err
}
// Notify interested clients of the connected block.
var header wire.BlockHeader
header.Deserialize(bytes.NewReader(block.SerializedHeader[:]))
w.NtfnServer.notifyAttachedBlock(dbtx, &header, &block.BlockHash)
blockMeta, err := w.TxStore.GetBlockMetaForHash(txmgrNs, &block.BlockHash)
if err != nil {
return err
}
for _, serializedTx := range transactions {
err = w.processTransaction(dbtx, serializedTx,
&block.SerializedHeader, &blockMeta)
if err != nil {
return err
}
}
return nil
}
示例2: makeBlockMeta
func makeBlockMeta(h *wire.BlockHeader) *BlockMeta {
return &BlockMeta{
Block: Block{
Hash: h.BlockSha(),
Height: int32(h.Height),
},
Time: time.Time{},
}
}
示例3: makeHeaderData
func makeHeaderData(h *wire.BlockHeader) BlockHeaderData {
var b bytes.Buffer
err := h.Serialize(&b)
if err != nil {
panic(err)
}
d := BlockHeaderData{BlockHash: h.BlockSha()}
copy(d.SerializedHeader[:], b.Bytes())
return d
}
示例4: FetchBlockHeaderBySha
// FetchBlockHeaderBySha - return a ShaHash
func (db *LevelDb) FetchBlockHeaderBySha(sha *chainhash.Hash) (bh *wire.BlockHeader, err error) {
db.dbLock.Lock()
defer db.dbLock.Unlock()
// Read the raw block from the database.
buf, _, err := db.fetchSha(sha)
if err != nil {
return nil, err
}
// Only deserialize the header portion and ensure the transaction count
// is zero since this is a standalone header.
var blockHeader wire.BlockHeader
err = blockHeader.Deserialize(bytes.NewReader(buf))
if err != nil {
return nil, err
}
bh = &blockHeader
return bh, err
}
示例5: TestBlockHeaderHashing
func TestBlockHeaderHashing(t *testing.T) {
dummyHeader := "0000000049e0b48ade043f729d60095ed92642d96096fe6aba42f2eda" +
"632d461591a152267dc840ff27602ce1968a81eb30a43423517207617a0150b56c4f72" +
"b803e497f00000000000000000000000000000000000000000000000000000000000000" +
"00010000000000000000000000b7000000ffff7f20204e0000000000005800000060010" +
"0008b990956000000000000000000000000000000000000000000000000000000000000" +
"0000000000000000ABCD"
// This hash has reversed endianness compared to what chainhash spits out.
hashStr := "0d40d58703482d81d711be0ffc1b313788d3c3937e1617e4876661d33a8c4c41"
hashB, _ := hex.DecodeString(hashStr)
hash, _ := chainhash.NewHash(hashB)
vecH, _ := hex.DecodeString(dummyHeader)
r := bytes.NewReader(vecH)
var bh wire.BlockHeader
bh.Deserialize(r)
hash2 := bh.BlockSha()
if !hash2.IsEqual(hash) {
t.Errorf("wrong block sha returned (want %v, got %v)",
hash,
hash2)
}
}
示例6: TestBlockHeaderSerialize
// TestBlockHeaderSerialize tests BlockHeader serialize and deserialize.
func TestBlockHeaderSerialize(t *testing.T) {
nonce := uint32(123123) // 0x1e0f3
// baseBlockHdr is used in the various tests as a baseline BlockHeader.
bits := uint32(0x1d00ffff)
baseBlockHdr := &wire.BlockHeader{
Version: 1,
PrevBlock: mainNetGenesisHash,
MerkleRoot: mainNetGenesisMerkleRoot,
StakeRoot: mainNetGenesisMerkleRoot,
VoteBits: uint16(0x0000),
FinalState: [6]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Voters: uint16(0x0000),
FreshStake: uint8(0x00),
Revocations: uint8(0x00),
Timestamp: time.Unix(0x495fab29, 0), // 2009-01-03 12:15:05 -0600 CST
Bits: bits,
SBits: int64(0x0000000000000000),
Nonce: nonce,
Height: uint32(0),
Size: uint32(0),
}
// baseBlockHdrEncoded is the wire encoded bytes of baseBlockHdr.
baseBlockHdrEncoded := []byte{
0x01, 0x00, 0x00, 0x00, // Version 1
0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72,
0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f,
0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c,
0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, // PrevBlock
0x3b, 0xa3, 0xed, 0xfd, 0x7a, 0x7b, 0x12, 0xb2,
0x7a, 0xc7, 0x2c, 0x3e, 0x67, 0x76, 0x8f, 0x61,
0x7f, 0xc8, 0x1b, 0xc3, 0x88, 0x8a, 0x51, 0x32,
0x3a, 0x9f, 0xb8, 0xaa, 0x4b, 0x1e, 0x5e, 0x4a, // MerkleRoot
0x3b, 0xa3, 0xed, 0xfd, 0x7a, 0x7b, 0x12, 0xb2,
0x7a, 0xc7, 0x2c, 0x3e, 0x67, 0x76, 0x8f, 0x61,
0x7f, 0xc8, 0x1b, 0xc3, 0x88, 0x8a, 0x51, 0x32,
0x3a, 0x9f, 0xb8, 0xaa, 0x4b, 0x1e, 0x5e, 0x4a, // StakeRoot
0x00, 0x00, // VoteBits
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FinalState
0x00, 0x00, // Voters
0x00, // FreshStake
0x00, // Revocations
0x00, 0x00, 0x00, 0x00, //Poolsize
0xff, 0xff, 0x00, 0x1d, // Bits
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // SBits
0x00, 0x00, 0x00, 0x00, // Height
0x00, 0x00, 0x00, 0x00, // Size
0x29, 0xab, 0x5f, 0x49, // Timestamp
0xf3, 0xe0, 0x01, 0x00, // Nonce
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ExtraData
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
}
tests := []struct {
in *wire.BlockHeader // Data to encode
out *wire.BlockHeader // Expected decoded data
buf []byte // Serialized data
}{
{
baseBlockHdr,
baseBlockHdr,
baseBlockHdrEncoded,
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
// Serialize the block header.
var buf bytes.Buffer
err := test.in.Serialize(&buf)
if err != nil {
t.Errorf("Serialize #%d error %v", i, err)
continue
}
if !bytes.Equal(buf.Bytes(), test.buf) {
t.Errorf("Serialize #%d\n got: %s want: %s", i,
spew.Sdump(buf.Bytes()), spew.Sdump(test.buf))
continue
}
// Deserialize the block header.
var bh wire.BlockHeader
rbuf := bytes.NewReader(test.buf)
err = bh.Deserialize(rbuf)
if err != nil {
t.Errorf("Deserialize #%d error %v", i, err)
continue
}
if !reflect.DeepEqual(&bh, test.out) {
t.Errorf("Deserialize #%d\n got: %s want: %s", i,
spew.Sdump(&bh), spew.Sdump(test.out))
continue
}
}
}
示例7: onBlockConnected
// onBlockConnected is the entry point for processing chain server
// blockconnected notifications.
func (w *Wallet) onBlockConnected(dbtx walletdb.ReadWriteTx, serializedBlockHeader []byte, transactions [][]byte) error {
var blockHeader wire.BlockHeader
err := blockHeader.Deserialize(bytes.NewReader(serializedBlockHeader))
if err != nil {
return err
}
block := wtxmgr.BlockHeaderData{BlockHash: blockHeader.BlockSha()}
err = copyHeaderSliceToArray(&block.SerializedHeader, serializedBlockHeader)
if err != nil {
return err
}
w.reorganizingLock.Lock()
reorg, reorgToHash := w.reorganizing, w.reorganizeToHash
w.reorganizingLock.Unlock()
if reorg {
// add to side chain
scBlock := sideChainBlock{
transactions: transactions,
headerData: block,
}
w.sideChain = append(w.sideChain, scBlock)
log.Infof("Adding block %v (height %v) to sidechain",
block.BlockHash, block.SerializedHeader.Height())
if block.BlockHash != reorgToHash {
// Nothing left to do until the later blocks are
// received.
return nil
}
err = w.switchToSideChain(dbtx)
if err != nil {
return err
}
w.sideChain = nil
w.reorganizingLock.Lock()
w.reorganizing = false
w.reorganizingLock.Unlock()
log.Infof("Wallet reorganization to block %v complete", reorgToHash)
} else {
err = w.extendMainChain(dbtx, &block, transactions)
if err != nil {
return err
}
}
height := int32(blockHeader.Height)
// Handle automatic ticket purchasing if enabled. This function should
// not error due to an error purchasing tickets (several tickets may be
// have been purhcased and successfully published, as well as addresses
// created and used), so just log it instead.
err = w.handleTicketPurchases(dbtx, height)
switch err.(type) {
case nil:
case txauthor.InsufficientFundsError:
log.Debugf("Insufficient funds to auto-purchase maximum number " +
"of tickets")
default:
log.Errorf("Failed to perform automatic picket purchasing: %v", err)
}
// Prune all expired transactions and all stake tickets that no longer
// meet the minimum stake difficulty.
txmgrNs := dbtx.ReadWriteBucket(wtxmgrNamespaceKey)
err = w.TxStore.PruneUnconfirmed(txmgrNs, height, blockHeader.SBits)
if err != nil {
log.Errorf("Failed to prune unconfirmed transactions when "+
"connecting block height %v: %s", height, err.Error())
}
return nil
}
示例8: Test_dupTx
//.........這裏部分代碼省略.........
}
}
}
newheight, err := db.InsertBlock(block)
if err != nil {
t.Errorf("failed to insert block %v err %v", height, err)
break out
}
if newheight != height {
t.Errorf("height mismatch expect %v returned %v", height, newheight)
break out
}
newSha, blkid, err := db.NewestSha()
if err != nil {
t.Errorf("failed to obtain latest sha %v %v", height, err)
}
if blkid != height {
t.Errorf("height doe not match latest block height %v %v %v", blkid, height, err)
}
blkSha := block.Sha()
if *newSha != *blkSha {
t.Errorf("Newest block sha does not match freshly inserted one %v %v %v ", newSha, blkSha, err)
}
lastSha = blkSha
}
// generate a new block based on the last sha
// these block are not verified, so there are a bunch of garbage fields
// in the 'generated' block.
var bh wire.BlockHeader
bh.Version = 0
bh.PrevBlock = *lastSha
// Bits, Nonce are not filled in
mblk := wire.NewMsgBlock(&bh)
hash, _ := chainhash.NewHashFromStr("c23953c56cb2ef8e4698e3ed3b0fc4c837754d3cd16485192d893e35f32626b4")
po := wire.NewOutPoint(hash, 0, dcrutil.TxTreeRegular)
txI := wire.NewTxIn(po, []byte("garbage"))
txO := wire.NewTxOut(50000000, []byte("garbageout"))
var tx wire.MsgTx
tx.AddTxIn(txI)
tx.AddTxOut(txO)
mblk.AddTransaction(&tx)
blk := dcrutil.NewBlock(mblk)
fetchList := []*chainhash.Hash{hash}
listReply := db.FetchUnSpentTxByShaList(fetchList)
for _, lr := range listReply {
if lr.Err != nil {
t.Errorf("sha %v spent %v err %v\n", lr.Sha,
lr.TxSpent, lr.Err)
}
}
_, err = db.InsertBlock(blk)
if err != nil {
示例9: TestBlockHeaderWire
// TestBlockHeaderWire tests the BlockHeader wire encode and decode for various
// protocol versions.
func TestBlockHeaderWire(t *testing.T) {
nonce := uint32(123123) // 0x1e0f3
pver := uint32(70001)
/*bh := dcrwire.NewBlockHeader(
&hash,
&merkleHash,
&merkleHash, // stakeRoot
votebits,
winner,
overflow,
voters,
freshstake,
revocations,
bits,
sbits,
nonce,
height,
size)*/
// baseBlockHdr is used in the various tests as a baseline BlockHeader.
bits := uint32(0x1d00ffff)
baseBlockHdr := &wire.BlockHeader{
Version: 1,
PrevBlock: mainNetGenesisHash,
MerkleRoot: mainNetGenesisMerkleRoot,
StakeRoot: mainNetGenesisMerkleRoot,
VoteBits: uint16(0x0000),
FinalState: [6]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
Voters: uint16(0x0000),
FreshStake: uint8(0x00),
Revocations: uint8(0x00),
PoolSize: uint32(0x00000000),
Timestamp: time.Unix(0x495fab29, 0), // 2009-01-03 12:15:05 -0600 CST
Bits: bits,
SBits: int64(0x0000000000000000),
Nonce: nonce,
Height: uint32(0),
Size: uint32(0),
}
// baseBlockHdrEncoded is the wire encoded bytes of baseBlockHdr.
baseBlockHdrEncoded := []byte{
0x01, 0x00, 0x00, 0x00, // Version 1
0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72,
0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f,
0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c,
0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, // PrevBlock
0x3b, 0xa3, 0xed, 0xfd, 0x7a, 0x7b, 0x12, 0xb2,
0x7a, 0xc7, 0x2c, 0x3e, 0x67, 0x76, 0x8f, 0x61,
0x7f, 0xc8, 0x1b, 0xc3, 0x88, 0x8a, 0x51, 0x32,
0x3a, 0x9f, 0xb8, 0xaa, 0x4b, 0x1e, 0x5e, 0x4a, // MerkleRoot
0x3b, 0xa3, 0xed, 0xfd, 0x7a, 0x7b, 0x12, 0xb2,
0x7a, 0xc7, 0x2c, 0x3e, 0x67, 0x76, 0x8f, 0x61,
0x7f, 0xc8, 0x1b, 0xc3, 0x88, 0x8a, 0x51, 0x32,
0x3a, 0x9f, 0xb8, 0xaa, 0x4b, 0x1e, 0x5e, 0x4a, // StakeRoot
0x00, 0x00, // VoteBits
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FinalState
0x00, 0x00, // Voters
0x00, // FreshStake
0x00, // Revocations
0x00, 0x00, 0x00, 0x00, //Poolsize
0xff, 0xff, 0x00, 0x1d, // Bits
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // SBits
0x00, 0x00, 0x00, 0x00, // Height
0x00, 0x00, 0x00, 0x00, // Size
0x29, 0xab, 0x5f, 0x49, // Timestamp
0xf3, 0xe0, 0x01, 0x00, // Nonce
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ExtraData
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
}
tests := []struct {
in *wire.BlockHeader // Data to encode
out *wire.BlockHeader // Expected decoded data
buf []byte // Wire encoding
pver uint32 // Protocol version for wire encoding
}{
// Latest protocol version.
{
baseBlockHdr,
baseBlockHdr,
baseBlockHdrEncoded,
wire.ProtocolVersion,
},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
// Encode to wire format.
// Former test (doesn't work because of capacity error)
var buf bytes.Buffer
err := wire.TstWriteBlockHeader(&buf, test.pver, test.in)
if err != nil {
t.Errorf("writeBlockHeader #%d error %v", i, err)
//.........這裏部分代碼省略.........
示例10: disconnectNode
// disconnectNode disconnects a stake node from itself and returns the state of
// the parent node. The database transaction should be included if the
// UndoTicketDataSlice or tickets are nil in order to look up the undo data or
// tickets from the database.
func disconnectNode(node *Node, parentHeader wire.BlockHeader, parentUtds UndoTicketDataSlice, parentTickets []chainhash.Hash, dbTx database.Tx) (*Node, error) {
// Edge case for the parent being the genesis block.
if node.height == 1 {
return genesisNode(node.params), nil
}
if node == nil {
return nil, fmt.Errorf("missing stake node pointer input when " +
"disconnecting")
}
// The undo ticket slice is normally stored in memory for the most
// recent blocks and the sidechain, but it may be the case that it
// is missing because it's in the mainchain and very old (thus
// outside the node cache). In this case, restore this data from
// disk.
if parentUtds == nil || parentTickets == nil {
if dbTx == nil {
return nil, stakeRuleError(ErrMissingDatabaseTx, "needed to "+
"look up undo data in the database, but no dbtx passed")
}
var err error
parentUtds, err = ticketdb.DbFetchBlockUndoData(dbTx, node.height-1)
if err != nil {
return nil, err
}
parentTickets, err = ticketdb.DbFetchNewTickets(dbTx, node.height-1)
if err != nil {
return nil, err
}
}
restoredNode := &Node{
height: node.height - 1,
liveTickets: node.liveTickets,
missedTickets: node.missedTickets,
revokedTickets: node.revokedTickets,
databaseUndoUpdate: parentUtds,
databaseBlockTickets: parentTickets,
nextWinners: make([]chainhash.Hash, 0),
params: node.params,
}
// Iterate through the block undo data and write all database
// changes to the respective treap, reversing all the changes
// added when the child block was added to the chain.
stateBuffer := make([]byte, 0,
(node.params.TicketsPerBlock+1)*chainhash.HashSize)
for _, undo := range node.databaseUndoUpdate {
var err error
k := tickettreap.Key(undo.TicketHash)
v := &tickettreap.Value{
Height: undo.TicketHeight,
Missed: undo.Missed,
Revoked: undo.Revoked,
Spent: undo.Spent,
Expired: undo.Expired,
}
switch {
// All flags are unset; this is a newly added ticket.
// Remove it from the list of live tickets.
case !undo.Missed && !undo.Revoked && !undo.Spent:
restoredNode.liveTickets, err =
safeDelete(restoredNode.liveTickets, k)
if err != nil {
return nil, err
}
// The ticket was missed and revoked. It needs to
// be moved from the revoked ticket treap to the
// missed ticket treap.
case undo.Missed && undo.Revoked:
v.Revoked = false
restoredNode.revokedTickets, err =
safeDelete(restoredNode.revokedTickets, k)
if err != nil {
return nil, err
}
restoredNode.missedTickets, err =
safePut(restoredNode.missedTickets, k, v)
if err != nil {
return nil, err
}
// The ticket was missed and was previously live.
// Remove it from the missed tickets bucket and
// move it to the live tickets bucket.
case undo.Missed && !undo.Revoked:
// Expired tickets could never have been
// winners.
if !undo.Expired {
restoredNode.nextWinners = append(restoredNode.nextWinners,
undo.TicketHash)
//.........這裏部分代碼省略.........
示例11: connectNode
// connectNode connects a child to a parent stake node, returning the
// modified stake node for the child. It is important to keep in mind that
// the argument node is the parent node, and that the child stake node is
// returned after subsequent modification of the parent node's immutable
// data.
func connectNode(node *Node, header wire.BlockHeader, ticketsSpentInBlock, revokedTickets, newTickets []chainhash.Hash) (*Node, error) {
if node == nil {
return nil, fmt.Errorf("missing stake node pointer input when connecting")
}
connectedNode := &Node{
height: node.height + 1,
liveTickets: node.liveTickets,
missedTickets: node.missedTickets,
revokedTickets: node.revokedTickets,
databaseUndoUpdate: make(UndoTicketDataSlice, 0),
databaseBlockTickets: newTickets,
nextWinners: make([]chainhash.Hash, 0),
params: node.params,
}
// We only have to deal with voted related issues and expiry after
// StakeEnabledHeight.
var err error
if connectedNode.height >= uint32(connectedNode.params.StakeEnabledHeight) {
// Basic sanity check.
for i := range ticketsSpentInBlock {
if !hashInSlice(ticketsSpentInBlock[i], node.nextWinners) {
return nil, stakeRuleError(ErrUnknownTicketSpent,
fmt.Sprintf("unknown ticket %v spent in block",
ticketsSpentInBlock[i]))
}
}
// Iterate through all possible winners and construct the undo data,
// updating the live and missed ticket treaps as necessary. We need
// to copy the value here so we don't modify it in the previous treap.
for _, ticket := range node.nextWinners {
k := tickettreap.Key(ticket)
v, err := safeGet(connectedNode.liveTickets, k)
if err != nil {
return nil, err
}
// If it's spent in this block, mark it as being spent. Otherwise,
// it was missed. Spent tickets are dropped from the live ticket
// bucket, while missed tickets are pushed to the missed ticket
// bucket. Because we already know from the above check that the
// ticket should still be in the live tickets treap, we probably
// do not have to use the safe delete functions, but do so anyway
// just to be safe.
if hashInSlice(ticket, ticketsSpentInBlock) {
v.Spent = true
v.Missed = false
connectedNode.liveTickets, err =
safeDelete(connectedNode.liveTickets, k)
if err != nil {
return nil, err
}
} else {
v.Spent = false
v.Missed = true
connectedNode.liveTickets, err =
safeDelete(connectedNode.liveTickets, k)
if err != nil {
return nil, err
}
connectedNode.missedTickets, err =
safePut(connectedNode.missedTickets, k, v)
if err != nil {
return nil, err
}
}
connectedNode.databaseUndoUpdate =
append(connectedNode.databaseUndoUpdate, ticketdb.UndoTicketData{
TicketHash: ticket,
TicketHeight: v.Height,
Missed: v.Missed,
Revoked: v.Revoked,
Spent: v.Spent,
Expired: v.Expired,
})
}
// Find the expiring tickets and drop them as well. We already know what
// the winners are from the cached information in the previous block, so
// no drop the results of that here.
toExpireHeight := uint32(0)
if connectedNode.height > uint32(connectedNode.params.TicketExpiry) {
toExpireHeight = connectedNode.height -
uint32(connectedNode.params.TicketExpiry)
}
expired := fetchExpired(toExpireHeight, connectedNode.liveTickets)
for _, treapKey := range expired {
v, err := safeGet(connectedNode.liveTickets, *treapKey)
if err != nil {
return nil, err
}
v.Missed = true
//.........這裏部分代碼省略.........
示例12: LoadBestNode
// LoadBestNode is used when the blockchain is initialized, to get the initial
// stake node from the database bucket. The blockchain must pass the height
// and the blockHash to confirm that the ticket database is on the same
// location in the blockchain as the blockchain itself. This function also
// checks to ensure that the database has not failed the upgrade process and
// reports the current version. Upgrades are also handled by this function,
// when they become applicable.
func LoadBestNode(dbTx database.Tx, height uint32, blockHash chainhash.Hash, header wire.BlockHeader, params *chaincfg.Params) (*Node, error) {
info, err := ticketdb.DbFetchDatabaseInfo(dbTx)
if err != nil {
return nil, err
}
// Compare the tip and make sure it matches.
state, err := ticketdb.DbFetchBestState(dbTx)
if err != nil {
return nil, err
}
if state.Hash != blockHash || state.Height != height {
return nil, stakeRuleError(ErrDatabaseCorrupt, "best state corruption")
}
// Restore the best node treaps form the database.
node := new(Node)
node.height = height
node.params = params
node.liveTickets, err = ticketdb.DbLoadAllTickets(dbTx,
dbnamespace.LiveTicketsBucketName)
if err != nil {
return nil, err
}
if node.liveTickets.Len() != int(state.Live) {
return nil, stakeRuleError(ErrDatabaseCorrupt,
fmt.Sprintf("live tickets corruption (got "+
"%v in state but loaded %v)", int(state.Live),
node.liveTickets.Len()))
}
node.missedTickets, err = ticketdb.DbLoadAllTickets(dbTx,
dbnamespace.MissedTicketsBucketName)
if err != nil {
return nil, err
}
if node.missedTickets.Len() != int(state.Missed) {
return nil, stakeRuleError(ErrDatabaseCorrupt,
fmt.Sprintf("missed tickets corruption (got "+
"%v in state but loaded %v)", int(state.Missed),
node.missedTickets.Len()))
}
node.revokedTickets, err = ticketdb.DbLoadAllTickets(dbTx,
dbnamespace.RevokedTicketsBucketName)
if err != nil {
return nil, err
}
if node.revokedTickets.Len() != int(state.Revoked) {
return nil, stakeRuleError(ErrDatabaseCorrupt,
fmt.Sprintf("revoked tickets corruption (got "+
"%v in state but loaded %v)", int(state.Revoked),
node.revokedTickets.Len()))
}
// Restore the node undo and new tickets data.
node.databaseUndoUpdate, err = ticketdb.DbFetchBlockUndoData(dbTx, height)
if err != nil {
return nil, err
}
node.databaseBlockTickets, err = ticketdb.DbFetchNewTickets(dbTx, height)
if err != nil {
return nil, err
}
// Restore the next winners for the node.
node.nextWinners = make([]chainhash.Hash, 0)
if node.height >= uint32(node.params.StakeValidationHeight-1) {
node.nextWinners = make([]chainhash.Hash, len(state.NextWinners))
for i := range state.NextWinners {
node.nextWinners[i] = state.NextWinners[i]
}
// Calculate the final state from the block header.
stateBuffer := make([]byte, 0,
(node.params.TicketsPerBlock+1)*chainhash.HashSize)
for _, ticketHash := range node.nextWinners {
stateBuffer = append(stateBuffer, ticketHash[:]...)
}
hB, err := header.Bytes()
if err != nil {
return nil, err
}
prng := NewHash256PRNG(hB)
_, err = findTicketIdxs(int64(node.liveTickets.Len()),
int(node.params.TicketsPerBlock), prng)
if err != nil {
return nil, err
}
lastHash := prng.StateHash()
stateBuffer = append(stateBuffer, lastHash[:]...)
copy(node.finalState[:], chainhash.HashFuncB(stateBuffer)[0:6])
}
log.Infof("Stake database version %v loaded", info.Version)
//.........這裏部分代碼省略.........
示例13: estimateNextStakeDifficulty
// estimateNextStakeDifficulty returns a user-specified estimate for the next
// stake difficulty, with the passed ticketsInWindow indicating the number of
// fresh stake to pretend exists within this window. Optionally the user can
// also override this variable with useMaxTickets, which simply plugs in the
// maximum number of tickets the user can try.
func (b *BlockChain) estimateNextStakeDifficulty(curNode *blockNode,
ticketsInWindow int64, useMaxTickets bool) (int64, error) {
alpha := b.chainParams.StakeDiffAlpha
stakeDiffStartHeight := int64(b.chainParams.CoinbaseMaturity) +
1
maxRetarget := int64(b.chainParams.RetargetAdjustmentFactor)
TicketPoolWeight := int64(b.chainParams.TicketPoolSizeWeight)
// Number of nodes to traverse while calculating difficulty.
nodesToTraverse := (b.chainParams.StakeDiffWindowSize *
b.chainParams.StakeDiffWindows)
// Genesis block. Block at height 1 has these parameters.
if curNode == nil ||
curNode.height < stakeDiffStartHeight {
return b.chainParams.MinimumStakeDiff, nil
}
// Create a fake blockchain on top of the current best node with
// the number of freshly purchased tickets as indicated by the
// user.
oldDiff := curNode.header.SBits
topNode := curNode
if (curNode.height+1)%b.chainParams.StakeDiffWindowSize != 0 {
nextAdjHeight := ((curNode.height /
b.chainParams.StakeDiffWindowSize) + 1) *
b.chainParams.StakeDiffWindowSize
maxTickets := (nextAdjHeight - curNode.height) *
int64(b.chainParams.MaxFreshStakePerBlock)
// If the user has indicated that the automatically
// calculated maximum amount of tickets should be
// used, plug that in here.
if useMaxTickets {
ticketsInWindow = maxTickets
}
// Double check to make sure there isn't too much.
if ticketsInWindow > maxTickets {
return 0, fmt.Errorf("too much fresh stake to be used "+
"in evaluation requested; max %v, got %v", maxTickets,
ticketsInWindow)
}
// Insert all the tickets into bogus nodes that will be
// used to calculate the next difficulty below.
ticketsToInsert := ticketsInWindow
for i := curNode.height + 1; i < nextAdjHeight; i++ {
emptyHeader := new(wire.BlockHeader)
emptyHeader.Height = uint32(i)
// User a constant pool size for estimate, since
// this has much less fluctuation than freshStake.
// TODO Use a better pool size estimate?
emptyHeader.PoolSize = curNode.header.PoolSize
// Insert the fake fresh stake into each block,
// decrementing the amount we need to use each
// time until we hit 0.
freshStake := b.chainParams.MaxFreshStakePerBlock
if int64(freshStake) > ticketsToInsert {
freshStake = uint8(ticketsToInsert)
ticketsToInsert -= ticketsToInsert
} else {
ticketsToInsert -= int64(b.chainParams.MaxFreshStakePerBlock)
}
emptyHeader.FreshStake = freshStake
// Connect the header.
emptyHeader.PrevBlock = topNode.hash
// Make up a node hash.
hB, err := emptyHeader.Bytes()
if err != nil {
return 0, err
}
emptyHeaderHash := chainhash.HashFuncH(hB)
thisNode := new(blockNode)
thisNode.header = *emptyHeader
thisNode.hash = emptyHeaderHash
thisNode.height = i
thisNode.parent = topNode
topNode = thisNode
}
}
// The target size of the ticketPool in live tickets. Recast these as int64
// to avoid possible overflows for large sizes of either variable in
// params.
targetForTicketPool := int64(b.chainParams.TicketsPerBlock) *
int64(b.chainParams.TicketPoolSize)
// Initialize bigInt slice for the percentage changes for each window period
// above or below the target.
//.........這裏部分代碼省略.........