// blockExists determines whether a block with the given hash exists either in // the main chain or any side chains. func (b *BlockChain) blockExists(hash *wire.ShaHash) (bool, error) { // Check memory chain first (could be main chain or side chain blocks). if _, ok := b.index[*hash]; ok { return true, nil } // Check if it's the latest checkpoint block if hash.IsEqual(b.chainParams.Checkpoints[len(b.chainParams.Checkpoints)-1].Hash) { return true, nil } // Check in database (rest of main chain not in memory). return b.db.ExistsSha(hash) }
func (db *LevelDb) getBlkLoc(sha *wire.ShaHash) (int32, error) { key := shaBlkToKey(sha) checkpointSha, _ := wire.NewShaHashFromStr("00000000000000000a8dc6ed5b133d0eb2fd6af56203e4159789b092defd8ab2") if sha.IsEqual(checkpointSha) { return 382320, nil } data, err := db.lDb.Get(key, db.ro) if err != nil { if err == leveldb.ErrNotFound { err = database.ErrBlockShaMissing } return 0, err } // deserialize blkHeight := binary.LittleEndian.Uint64(data) return int32(blkHeight), nil }
func MakeMerkleParent(left *wire.ShaHash, right *wire.ShaHash) *wire.ShaHash { // dupes can screw things up; CVE-2012-2459. check for them if left != nil && right != nil && left.IsEqual(right) { fmt.Printf("DUP HASH CRASH") return nil } // if left child is nil, output nil. Need this for hard mode. if left == nil { return nil } // if right is nil, hash left with itself if right == nil { right = left } // Concatenate the left and right nodes var sha [64]byte copy(sha[:32], left[:]) copy(sha[32:], right[:]) newSha := wire.DoubleSha256SH(sha[:]) return &newSha }
// MakeMerkleParent ... func MakeMerkleParent(left *wire.ShaHash, right *wire.ShaHash) *wire.ShaHash { // this can screw things up; CVE-2012-2459 if left != nil && right != nil && left.IsEqual(right) { fmt.Printf("DUP HASH CRASH") return nil } // if left chils is nil, output nil. Shouldn't need this? if left == nil { fmt.Printf("L CRASH") return nil } // if right is nil, has left with itself if right == nil { right = left } // Concatenate the left and right nodes var sha [wire.HashSize * 2]byte copy(sha[:wire.HashSize], left[:]) copy(sha[wire.HashSize:], right[:]) newSha := wire.DoubleSha256SH(sha[:]) return &newSha }
// blockLocatorFromHash returns a block locator for the passed block hash. // See BlockLocator for details on the algotirhm used to create a block locator. // // In addition to the general algorithm referenced above, there are a couple of // special cases which are handled: // // - If the genesis hash is passed, there are no previous hashes to add and // therefore the block locator will only consist of the genesis hash // - If the passed hash is not currently known, the block locator will only // consist of the passed hash // // This function MUST be called with the chain state lock held (for reads). func (b *BlockChain) blockLocatorFromHash(hash *wire.ShaHash) BlockLocator { // The locator contains the requested hash at the very least. locator := make(BlockLocator, 0, wire.MaxBlockLocatorsPerMsg) locator = append(locator, hash) // Nothing more to do if a locator for the genesis hash was requested. if hash.IsEqual(b.chainParams.GenesisHash) { return locator } // Attempt to find the height of the block that corresponds to the // passed hash, and if it's on a side chain, also find the height at // which it forks from the main chain. blockHeight := int32(-1) forkHeight := int32(-1) node, exists := b.index[*hash] if !exists { // Try to look up the height for passed block hash. Assume an // error means it doesn't exist and just return the locator for // the block itself. var height int32 err := b.db.View(func(dbTx database.Tx) error { var err error height, err = dbFetchHeightByHash(dbTx, hash) return err }) if err != nil { return locator } blockHeight = height } else { blockHeight = node.height // Find the height at which this node forks from the main chain // if the node is on a side chain. if !node.inMainChain { for n := node; n.parent != nil; n = n.parent { if n.inMainChain { forkHeight = n.height break } } } } // Generate the block locators according to the algorithm described in // in the BlockLocator comment and make sure to leave room for the final // genesis hash. // // The error is intentionally ignored here since the only way the code // could fail is if there is something wrong with the database which // will be caught in short order anyways and it's also safe to ignore // block locators. _ = b.db.View(func(dbTx database.Tx) error { iterNode := node increment := int32(1) for len(locator) < wire.MaxBlockLocatorsPerMsg-1 { // Once there are 10 locators, exponentially increase // the distance between each block locator. if len(locator) > 10 { increment *= 2 } blockHeight -= increment if blockHeight < 1 { break } // As long as this is still on the side chain, walk // backwards along the side chain nodes to each block // height. if forkHeight != -1 && blockHeight > forkHeight { // Intentionally use parent field instead of the // getPrevNodeFromNode function since we don't // want to dynamically load nodes when building // block locators. Side chain blocks should // always be in memory already, and if they // aren't for some reason it's ok to skip them. for iterNode != nil && blockHeight > iterNode.height { iterNode = iterNode.parent } if iterNode != nil && iterNode.height == blockHeight { locator = append(locator, iterNode.hash) } continue } // The desired block height is in the main chain, so // look it up from the main chain database. h, err := dbFetchHashByHeight(dbTx, blockHeight) if err != nil { // This shouldn't happen and it's ok to ignore // block locators, so just continue to the next // one. log.Warnf("Lookup of known valid height failed %v", blockHeight) continue } locator = append(locator, h) } return nil }) // Append the appropriate genesis block. locator = append(locator, b.chainParams.GenesisHash) return locator }
// BlockLocatorFromHash returns a block locator for the passed block hash. // See BlockLocator for details on the algotirhm used to create a block locator. // // In addition to the general algorithm referenced above, there are a couple of // special cases which are handled: // // - If the genesis hash is passed, there are no previous hashes to add and // therefore the block locator will only consist of the genesis hash // - If the passed hash is not currently known, the block locator will only // consist of the passed hash func (b *BlockChain) BlockLocatorFromHash(hash *wire.ShaHash) BlockLocator { // The locator contains the requested hash at the very least. locator := make(BlockLocator, 0, wire.MaxBlockLocatorsPerMsg) locator = append(locator, hash) // Nothing more to do if a locator for the genesis hash was requested. if hash.IsEqual(b.chainParams.GenesisHash) { return locator } // Nothing more to do if a locator for the latest checkpoint hash was requested if hash.IsEqual(b.chainParams.Checkpoints[len(b.chainParams.Checkpoints)-1].Hash) { return locator } // Attempt to find the height of the block that corresponds to the // passed hash, and if it's on a side chain, also find the height at // which it forks from the main chain. blockHeight := int32(-1) forkHeight := int32(-1) node, exists := b.index[*hash] if !exists { // Try to look up the height for passed block hash. Assume an // error means it doesn't exist and just return the locator for // the block itself. height, err := b.db.FetchBlockHeightBySha(hash) if err != nil { return locator } blockHeight = height } else { blockHeight = node.height // Find the height at which this node forks from the main chain // if the node is on a side chain. if !node.inMainChain { for n := node; n.parent != nil; n = n.parent { if n.inMainChain { forkHeight = n.height break } } } } // Generate the block locators according to the algorithm described in // in the BlockLocator comment and make sure to leave room for the // final genesis hash. iterNode := node increment := int32(1) for len(locator) < wire.MaxBlockLocatorsPerMsg-1 { // Once there are 10 locators, exponentially increase the // distance between each block locator. if len(locator) > 10 { increment *= 2 } blockHeight -= increment if blockHeight < 1 { break } // As long as this is still on the side chain, walk backwards // along the side chain nodes to each block height. if forkHeight != -1 && blockHeight > forkHeight { // Intentionally use parent field instead of the // getPrevNodeFromNode function since we don't want to // dynamically load nodes when building block locators. // Side chain blocks should always be in memory already, // and if they aren't for some reason it's ok to skip // them. for iterNode != nil && blockHeight > iterNode.height { iterNode = iterNode.parent } if iterNode != nil && iterNode.height == blockHeight { locator = append(locator, iterNode.hash) } continue } // The desired block height is in the main chain, so look it up // from the main chain database. h, err := b.db.FetchBlockShaByHeight(blockHeight) if err != nil { // This shouldn't happen and it's ok to ignore block // locators, so just continue to the next one. // PRUNING: We've hit the end of the stored nodes, so return what we have return locator /*log.Warnf("Lookup of known valid height failed %v", blockHeight) continue*/ } locator = append(locator, h) } // Append the appropriate genesis block. locator = append(locator, b.chainParams.GenesisHash) return locator }