Example #1
0
// Uses the txid of the target funding transaction and asks blockchain.info's
// api for information (in json) relaated to that transaction.
func lookupTxid(hash *wire.ShaHash) *blockChainInfoTx {

	url := "https://blockchain.info/rawtx/" + hash.String()
	resp, err := http.Get(url)
	if err != nil {
		log.Fatal(fmt.Errorf("Tx Lookup failed: %v", err))
	}

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(fmt.Errorf("TxInfo read failed: %s", err))
	}

	//fmt.Printf("%s\n", b)
	txinfo := &blockChainInfoTx{}
	err = json.Unmarshal(b, txinfo)
	if err != nil {
		log.Fatal(err)
	}

	if txinfo.Ver != 1 {
		log.Fatal(fmt.Errorf("Blockchain.info's response seems bad: %v", txinfo))
	}

	return txinfo
}
Example #2
0
// FetchHeightRange looks up a range of blocks by the start and ending
// heights.  Fetch is inclusive of the start height and exclusive of the
// ending height. To fetch all hashes from the start height until no
// more are present, use the special id `AllShas'.
func (db *LevelDb) FetchHeightRange(startHeight, endHeight int64) (rshalist []wire.ShaHash, err error) {
	db.dbLock.Lock()
	defer db.dbLock.Unlock()

	var endidx int64
	if endHeight == database.AllShas {
		endidx = startHeight + 500
	} else {
		endidx = endHeight
	}

	shalist := make([]wire.ShaHash, 0, endidx-startHeight)
	for height := startHeight; height < endidx; height++ {
		// TODO(drahn) fix blkFile from height

		key := int64ToKey(height)
		blkVal, lerr := db.lDb.Get(key, db.ro)
		if lerr != nil {
			break
		}

		var sha wire.ShaHash
		sha.SetBytes(blkVal[0:32])
		shalist = append(shalist, sha)
	}

	if err != nil {
		return
	}
	//log.Tracef("FetchIdxRange idx %v %v returned %v shas err %v", startHeight, endHeight, len(shalist), err)

	return shalist, nil
}
Example #3
0
func parsesha(argstr string) (argtype int, height int64, psha *wire.ShaHash, err error) {
	var sha wire.ShaHash

	var hashbuf string

	switch len(argstr) {
	case 64:
		hashbuf = argstr
	case 66:
		if argstr[0:2] != "0x" {
			log.Infof("prefix is %v", argstr[0:2])
			err = errBadShaPrefix
			return
		}
		hashbuf = argstr[2:]
	default:
		if len(argstr) <= 16 {
			// assume value is height
			argtype = argHeight
			var h int
			h, err = strconv.Atoi(argstr)
			if err == nil {
				height = int64(h)
				return
			}
			log.Infof("Unable to parse height %v, err %v", height, err)
		}
		err = errBadShaLen
		return
	}

	var buf [32]byte
	for idx, ch := range hashbuf {
		var val rune

		switch {
		case ch >= '0' && ch <= '9':
			val = ch - '0'
		case ch >= 'a' && ch <= 'f':
			val = ch - 'a' + rune(10)
		case ch >= 'A' && ch <= 'F':
			val = ch - 'A' + rune(10)
		default:
			err = errBadShaChar
			return
		}
		b := buf[31-idx/2]
		if idx&1 == 1 {
			b |= byte(val)
		} else {
			b |= (byte(val) << 4)
		}
		buf[31-idx/2] = b
	}
	sha.SetBytes(buf[0:32])
	psha = &sha
	return
}
Example #4
0
// GetBlockAsync returns an instance of a type that can be used to get the
// result of the RPC at some future time by invoking the Receive function on the
// returned instance.
//
// See GetBlock for the blocking version and more details.
func (c *Client) GetBlockAsync(blockHash *wire.ShaHash) FutureGetBlockResult {
	hash := ""
	if blockHash != nil {
		hash = blockHash.String()
	}

	cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(false), nil)
	return c.sendCmd(cmd)
}
Example #5
0
// GetRawTransactionAsync returns an instance of a type that can be used to get
// the result of the RPC at some future time by invoking the Receive function on
// the returned instance.
//
// See GetRawTransaction for the blocking version and more details.
func (c *Client) GetRawTransactionAsync(txHash *wire.ShaHash) FutureGetRawTransactionResult {
	hash := ""
	if txHash != nil {
		hash = txHash.String()
	}

	cmd := btcjson.NewGetRawTransactionCmd(hash, btcjson.Int(0))
	return c.sendCmd(cmd)
}
Example #6
0
// GetTxOutAsync returns an instance of a type that can be used to get
// the result of the RPC at some future time by invoking the Receive function on
// the returned instance.
//
// See GetTxOut for the blocking version and more details.
func (c *Client) GetTxOutAsync(txHash *wire.ShaHash, index uint32, mempool bool) FutureGetTxOutResult {
	hash := ""
	if txHash != nil {
		hash = txHash.String()
	}

	cmd := btcjson.NewGetTxOutCmd(hash, index, &mempool)
	return c.sendCmd(cmd)
}
Example #7
0
// GetBlockVerboseAsync returns an instance of a type that can be used to get
// the result of the RPC at some future time by invoking the Receive function on
// the returned instance.
//
// See GetBlockVerbose for the blocking version and more details.
func (c *Client) GetBlockVerboseAsync(blockHash *wire.ShaHash, verboseTx bool) FutureGetBlockVerboseResult {
	hash := ""
	if blockHash != nil {
		hash = blockHash.String()
	}

	cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(true), &verboseTx)
	return c.sendCmd(cmd)
}
Example #8
0
// add txid of interest
func (t *TxStore) AddTxid(txid *wire.ShaHash, height int32) error {
	if txid == nil {
		return fmt.Errorf("tried to add nil txid")
	}
	log.Printf("added %s to OKTxids at height %d\n", txid.String(), height)
	t.OKMutex.Lock()
	t.OKTxids[*txid] = height
	t.OKMutex.Unlock()
	return nil
}
Example #9
0
// ShaHashToBig converts a wire.ShaHash into a big.Int that can be used to
// perform math comparisons.
func ShaHashToBig(hash *wire.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)
}
Example #10
0
func assertAddrIndexTipIsUpdated(db database.Db, t *testing.T, newestSha *wire.ShaHash, newestBlockIdx int32) {
	// Safe to ignore error, since height will be < 0 in "error" case.
	sha, height, _ := db.FetchAddrIndexTip()
	if newestBlockIdx != height {
		t.Fatalf("Height of address index tip failed to update, "+
			"expected %v, got %v", newestBlockIdx, height)
	}
	if !bytes.Equal(newestSha.Bytes(), sha.Bytes()) {
		t.Fatalf("Sha of address index tip failed to update, "+
			"expected %v, got %v", newestSha, sha)
	}
}
Example #11
0
// 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 *wire.ShaHash, right *wire.ShaHash) *wire.ShaHash {
	// Concatenate the left and right nodes.
	var sha [wire.HashSize * 2]byte
	copy(sha[:wire.HashSize], left.Bytes())
	copy(sha[wire.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, _ := wire.NewShaHash(wire.DoubleSha256(sha[:]))
	return newSha
}
Example #12
0
// fetchBlockShaByHeight returns a block hash based on its height in the
// block chain.
func (db *LevelDb) fetchBlockShaByHeight(height int64) (rsha *wire.ShaHash, err error) {
	key := int64ToKey(height)

	blkVal, err := db.lDb.Get(key, db.ro)
	if err != nil {
		log.Tracef("failed to find height %v", height)
		return // exists ???
	}

	var sha wire.ShaHash
	sha.SetBytes(blkVal[0:32])

	return &sha, nil
}
Example #13
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)
}
Example #14
0
func (db *LevelDb) setBlk(sha *wire.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)
}
Example #15
0
// fetchAddrIndexTip returns the last block height and block sha to be indexed.
// Meta-data about the address tip is currently cached in memory, and will be
// updated accordingly by functions that modify the state. This function is
// used on start up to load the info into memory. Callers will use the public
// version of this function below, which returns our cached copy.
func (db *LevelDb) fetchAddrIndexTip() (*wire.ShaHash, int64, error) {
	db.dbLock.Lock()
	defer db.dbLock.Unlock()

	data, err := db.lDb.Get(addrIndexMetaDataKey, db.ro)
	if err != nil {
		return &wire.ShaHash{}, -1, database.ErrAddrIndexDoesNotExist
	}

	var blkSha wire.ShaHash
	blkSha.SetBytes(data[0:32])

	blkHeight := binary.LittleEndian.Uint64(data[32:])

	return &blkSha, int64(blkHeight), nil
}
// newDummyCredit creates a new credit with the given hash and outpointIdx,
// locked to the votingpool address identified by the given
// series/index/branch.
func newDummyCredit(t *testing.T, pool *Pool, series uint32, index Index, branch Branch,
	txSha []byte, outpointIdx uint32) credit {
	var hash wire.ShaHash
	if err := hash.SetBytes(txSha); err != nil {
		t.Fatal(err)
	}
	// Ensure the address defined by the given series/branch/index is present on
	// the set of used addresses as that's a requirement of WithdrawalAddress.
	TstEnsureUsedAddr(t, pool, series, branch, index)
	addr := TstNewWithdrawalAddress(t, pool, series, branch, index)
	c := wtxmgr.Credit{
		OutPoint: wire.OutPoint{
			Hash:  hash,
			Index: outpointIdx,
		},
	}
	return newCredit(c, *addr)
}
Example #17
0
// GetTx takes a txid and returns the transaction.  If we have it.
func (ts *TxStore) GetTx(txid *wire.ShaHash) (*wire.MsgTx, error) {
	rtx := wire.NewMsgTx()

	err := ts.StateDB.View(func(btx *bolt.Tx) error {
		txns := btx.Bucket(BKTTxns)
		if txns == nil {
			return fmt.Errorf("no transactions in db")
		}
		txbytes := txns.Get(txid.Bytes())
		if txbytes == nil {
			return fmt.Errorf("tx %x not in db", txid.String())
		}
		buf := bytes.NewBuffer(txbytes)
		return rtx.Deserialize(buf)
	})
	if err != nil {
		return nil, err
	}
	return rtx, nil
}
Example #18
0
func (db *LevelDb) getBlkByHeight(blkHeight int64) (rsha *wire.ShaHash, rbuf []byte, err error) {
	var blkVal []byte

	key := int64ToKey(blkHeight)

	blkVal, err = db.lDb.Get(key, db.ro)
	if err != nil {
		log.Tracef("failed to find height %v", blkHeight)
		return // exists ???
	}

	var sha wire.ShaHash

	sha.SetBytes(blkVal[0:32])

	blockdata := make([]byte, len(blkVal[32:]))
	copy(blockdata[:], blkVal[32:])

	return &sha, blockdata, nil
}
Example #19
0
// RescanEndBlockAsync returns an instance of a type that can be used to get
// the result of the RPC at some future time by invoking the Receive function on
// the returned instance.
//
// See RescanEndBlock for the blocking version and more details.
//
// NOTE: This is a btcd extension and requires a websocket connection.
func (c *Client) RescanEndBlockAsync(startBlock *wire.ShaHash,
	addresses []btcutil.Address, outpoints []*wire.OutPoint,
	endBlock *wire.ShaHash) FutureRescanResult {

	// Not supported in HTTP POST mode.
	if c.config.HTTPPostMode {
		return newFutureError(ErrNotificationsNotSupported)
	}

	// Ignore the notification if the client is not interested in
	// notifications.
	if c.ntfnHandlers == nil {
		return newNilFutureResult()
	}

	// Convert block hashes to strings.
	var startBlockShaStr, endBlockShaStr string
	if startBlock != nil {
		startBlockShaStr = startBlock.String()
	}
	if endBlock != nil {
		endBlockShaStr = endBlock.String()
	}

	// Convert addresses to strings.
	addrs := make([]string, 0, len(addresses))
	for _, addr := range addresses {
		addrs = append(addrs, addr.String())
	}

	// Convert outpoints.
	ops := make([]btcjson.OutPoint, 0, len(outpoints))
	for _, op := range outpoints {
		ops = append(ops, newOutPointFromWire(op))
	}

	cmd := btcjson.NewRescanCmd(startBlockShaStr, addrs, ops,
		&endBlockShaStr)
	return c.sendCmd(cmd)
}
Example #20
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
}
Example #21
0
File: tx.go Project: jimmysong/btcd
// 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 *wire.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
}
Example #22
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
}
Example #23
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
}
Example #24
0
func testBasicWalletReservationWorkFlow(lnwallet *LightningWallet, t *testing.T) {
	// Create our test wallet, will have a total of 20 BTC available for
	bobNode, err := newBobNode()
	if err != nil {
		t.Fatalf("unable to create bob node: %v", err)
	}

	// Bob initiates a channel funded with 5 BTC for each side, so 10
	// BTC total. He also generates 2 BTC in change.
	fundingAmount := btcutil.Amount(5 * 1e8)
	chanReservation, err := lnwallet.InitChannelReservation(fundingAmount,
		SIGHASH, bobNode.id, 4)
	if err != nil {
		t.Fatalf("unable to initialize funding reservation: %v", err)
	}

	// The channel reservation should now be populated with a multi-sig key
	// from our HD chain, a change output with 3 BTC, and 2 outputs selected
	// of 4 BTC each. Additionally, the rest of the items needed to fufill a
	// funding contribution should also have been filled in.
	ourContribution := chanReservation.OurContribution()
	if len(ourContribution.Inputs) != 2 {
		t.Fatalf("outputs for funding tx not properly selected, have %v "+
			"outputs should have 2", len(ourContribution.Inputs))
	}
	if ourContribution.ChangeOutputs[0].Value != 3e8 {
		t.Fatalf("coin selection failed, change output should be 3e8 "+
			"satoshis, is instead %v", ourContribution.ChangeOutputs[0].Value)
	}
	if ourContribution.MultiSigKey == nil {
		t.Fatalf("alice's key for multi-sig not found")
	}
	if ourContribution.CommitKey == nil {
		t.Fatalf("alice's key for commit not found")
	}
	if ourContribution.DeliveryAddress == nil {
		t.Fatalf("alice's final delivery address not found")
	}
	if bytes.Equal(ourContribution.RevocationHash[:], zeroHash) {
		t.Fatalf("alice's revocation hash not found")
	}
	if ourContribution.CsvDelay == 0 {
		t.Fatalf("csv delay not set")
	}

	// Bob sends over his output, change addr, pub keys, initial revocation,
	// final delivery address, and his accepted csv delay for the commitmen
	// t transactions.
	if err := chanReservation.ProcessContribution(bobNode.Contribution()); err != nil {
		t.Fatalf("unable to add bob's funds to the funding tx: %v", err)
	}

	// At this point, the reservation should have our signatures, and a
	// partial funding transaction (missing bob's sigs).
	theirContribution := chanReservation.TheirContribution()
	ourFundingSigs, ourCommitSig := chanReservation.OurSignatures()
	if len(ourFundingSigs) != 2 {
		t.Fatalf("only %v of our sigs present, should have 2",
			len(ourFundingSigs))
	}
	if ourCommitSig == nil {
		t.Fatalf("commitment sig not found")
	}
	// Additionally, the funding tx should have been populated.
	if chanReservation.partialState.FundingTx == nil {
		t.Fatalf("funding transaction never created!")
	}
	// Their funds should also be filled in.
	if len(theirContribution.Inputs) != 1 {
		t.Fatalf("bob's outputs for funding tx not properly selected, have %v "+
			"outputs should have 2", len(theirContribution.Inputs))
	}
	if theirContribution.ChangeOutputs[0].Value != 2e8 {
		t.Fatalf("bob should have one change output with value 2e8"+
			"satoshis, is instead %v",
			theirContribution.ChangeOutputs[0].Value)
	}
	if theirContribution.MultiSigKey == nil {
		t.Fatalf("bob's key for multi-sig not found")
	}
	if theirContribution.CommitKey == nil {
		t.Fatalf("bob's key for commit tx not found")
	}
	if theirContribution.DeliveryAddress == nil {
		t.Fatalf("bob's final delivery address not found")
	}
	if bytes.Equal(theirContribution.RevocationHash[:], zeroHash) {
		t.Fatalf("bob's revocaiton hash not found")
	}

	// Alice responds with her output, change addr, multi-sig key and signatures.
	// Bob then responds with his signatures.
	bobsSigs, err := bobNode.signFundingTx(chanReservation.partialState.FundingTx)
	if err != nil {
		t.Fatalf("unable to sign inputs for bob: %v", err)
	}
	commitSig, err := bobNode.signCommitTx(
		chanReservation.partialState.OurCommitTx,
		chanReservation.partialState.FundingRedeemScript)
	if err != nil {
		t.Fatalf("bob is unable to sign alice's commit tx: %v", err)
	}
	if err := chanReservation.CompleteReservation(bobsSigs, commitSig); err != nil {
		t.Fatalf("unable to complete funding tx: %v", err)
	}

	// At this point, the channel can be considered "open" when the funding
	// txn hits a "comfortable" depth.

	fundingTx := chanReservation.FinalFundingTx()

	// The resulting active channel state should have been persisted to the DB.
	channel, err := lnwallet.ChannelDB.FetchOpenChannel(bobNode.id)
	if err != nil {
		t.Fatalf("unable to retrieve channel from DB: %v", err)
	}
	if channel.FundingTx.TxSha() != fundingTx.TxSha() {
		t.Fatalf("channel state not properly saved")
	}

	// The funding tx should now be valid and complete.
	// Check each input and ensure all scripts are fully valid.
	// TODO(roasbeef): remove this loop after nodetest hooked up.
	var zeroHash wire.ShaHash
	for i, input := range fundingTx.TxIn {
		var pkscript []byte
		// Bob's txin
		if bytes.Equal(input.PreviousOutPoint.Hash.Bytes(),
			zeroHash.Bytes()) {
			pkscript = bobNode.changeOutputs[0].PkScript
		} else {
			// Does the wallet know about the txin?
			txDetail, err := lnwallet.TxStore.TxDetails(&input.PreviousOutPoint.Hash)
			if txDetail == nil || err != nil {
				t.Fatalf("txstore can't find tx detail, err: %v", err)
			}
			prevIndex := input.PreviousOutPoint.Index
			pkscript = txDetail.TxRecord.MsgTx.TxOut[prevIndex].PkScript
		}

		vm, err := txscript.NewEngine(pkscript,
			fundingTx, i, txscript.StandardVerifyFlags, nil)
		if err != nil {
			// TODO(roasbeef): cancel at this stage if invalid sigs?
			t.Fatalf("cannot create script engine: %s", err)
		}
		if err = vm.Execute(); err != nil {
			t.Fatalf("cannot validate transaction: %s", err)
		}
	}
}
Example #25
0
// RightSha ...
func RightSha(in wire.ShaHash) wire.ShaHash {
	return wire.DoubleSha256SH(append(in.Bytes(), 0x01)) // sha(sha(in, 1))
}
Example #26
0
// LeftSha ...
func LeftSha(in wire.ShaHash) wire.ShaHash {
	return wire.DoubleSha256SH(in.Bytes()) // left is sha(sha(in))
}
Example #27
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
}
Example #28
0
func shaBlkToKey(sha *wire.ShaHash) []byte {
	shaB := sha.Bytes()
	return shaB
}
Example #29
0
func shaSpentTxToKey(sha *wire.ShaHash) []byte {
	shaB := sha.Bytes()
	shaB = append(shaB, "sx"...)
	return shaB
}
Example #30
0
func toHash(txHash *wire.ShaHash) *common.Hash {
	h := new(common.Hash)
	h.SetBytes(txHash.Bytes())
	return h
}