func makeBlockMeta(h *wire.BlockHeader) *BlockMeta { return &BlockMeta{ Block: Block{ Hash: h.BlockSha(), Height: int32(h.Height), }, Time: time.Time{}, } }
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 }
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) } }
// 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 }