Beispiel #1
0
// 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)
}
Beispiel #2
0
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
}
Beispiel #3
0
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
}
Beispiel #4
0
// 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
}
Beispiel #5
0
// 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
}
Beispiel #6
0
// 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
}