// ShaHashToBig converts a btcwire.ShaHash into a big.Int that can be used to // perform math comparisons. func ShaHashToBig(hash *btcwire.ShaHash) *big.Int { // A ShaHash is in little-endian, but the big package wants the bytes // in big-endian. Reverse them. ShaHash.Bytes makes a copy, so it // is safe to modify the returned buffer. buf := hash.Bytes() blen := len(buf) for i := 0; i < blen/2; i++ { buf[i], buf[blen-1-i] = buf[blen-1-i], buf[i] } return new(big.Int).SetBytes(buf) }
// HashMerkleBranches takes two hashes, treated as the left and right tree // nodes, and returns the hash of their concatenation. This is a helper // function used to aid in the generation of a merkle tree. func HashMerkleBranches(left *btcwire.ShaHash, right *btcwire.ShaHash) *btcwire.ShaHash { // Concatenate the left and right nodes. var sha [btcwire.HashSize * 2]byte copy(sha[:btcwire.HashSize], left.Bytes()) copy(sha[btcwire.HashSize:], right.Bytes()) // Create a new sha hash from the double sha 256. Ignore the error // here since SetBytes can't fail here due to the fact DoubleSha256 // always returns a []byte of the right size regardless of input. newSha, _ := btcwire.NewShaHash(btcwire.DoubleSha256(sha[:])) return newSha }
func (db *LevelDb) setBlk(sha *btcwire.ShaHash, blkHeight int64, buf []byte) { // serialize var lw [8]byte binary.LittleEndian.PutUint64(lw[0:8], uint64(blkHeight)) shaKey := shaBlkToKey(sha) blkKey := int64ToKey(blkHeight) shaB := sha.Bytes() blkVal := make([]byte, len(shaB)+len(buf)) copy(blkVal[0:], shaB) copy(blkVal[len(shaB):], buf) db.lBatch().Put(shaKey, lw[:]) db.lBatch().Put(blkKey, blkVal) }
// UpdateAddrIndexForBlock updates the stored addrindex with passed // index information for a particular block height. Additionally, it // will update the stored meta-data related to the curent tip of the // addr index. These two operations are performed in an atomic // transaction which is commited before the function returns. // Transactions indexed by address are stored with the following format: // * prefix || hash160 || blockHeight || txoffset || txlen // Indexes are stored purely in the key, with blank data for the actual value // in order to facilitate ease of iteration by their shared prefix and // also to allow limiting the number of returned transactions (RPC). // Alternatively, indexes for each address could be stored as an // append-only list for the stored value. However, this add unnecessary // overhead when storing and retrieving since the entire list must // be fetched each time. func (db *LevelDb) UpdateAddrIndexForBlock(blkSha *btcwire.ShaHash, blkHeight int64, addrIndex database.BlockAddrIndex) error { db.dbLock.Lock() defer db.dbLock.Unlock() var blankData []byte batch := db.lBatch() defer db.lbatch.Reset() // Write all data for the new address indexes in a single batch // transaction. for addrKey, indexes := range addrIndex { for _, txLoc := range indexes { index := &txAddrIndex{ hash160: addrKey, blkHeight: blkHeight, txoffset: txLoc.TxStart, txlen: txLoc.TxLen, } // The index is stored purely in the key. packedIndex := addrIndexToKey(index) batch.Put(packedIndex, blankData) } } // Update tip of addrindex. newIndexTip := make([]byte, 40, 40) copy(newIndexTip[:32], blkSha.Bytes()) binary.LittleEndian.PutUint64(newIndexTip[32:], uint64(blkHeight)) batch.Put(addrIndexMetaDataKey, newIndexTip) if err := db.lDb.Write(batch, db.wo); err != nil { return err } db.lastAddrIndexBlkIdx = blkHeight db.lastAddrIndexBlkSha = *blkSha return nil }
func shaSpentTxToKey(sha *btcwire.ShaHash) []byte { shaB := sha.Bytes() shaB = append(shaB, "sx"...) return shaB }
func shaBlkToKey(sha *btcwire.ShaHash) []byte { shaB := sha.Bytes() return shaB }