示例#1
0
// Uses the txid of the target funding transaction and asks blockchain.info's
// api for information (in json) related to that transaction.
func lookupTxid(hash *chainhash.Hash) (*blockChainInfoTx, error) {
	url := "https://blockchain.info/rawtx/" + hash.String()
	resp, err := http.Get(url)
	if err != nil {
		return nil, fmt.Errorf("Tx Lookup failed: %v", err)
	}

	defer resp.Body.Close()

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

	txinfo := &blockChainInfoTx{}
	err = json.Unmarshal(b, txinfo)
	if err != nil {
		return nil, err
	}

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

	return txinfo, nil
}
示例#2
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 *chainhash.Hash, index uint32, mempool bool) FutureGetTxOutResult {
	hash := ""
	if txHash != nil {
		hash = txHash.String()
	}

	cmd := btcjson.NewGetTxOutCmd(hash, index, &mempool)
	return c.sendCmd(cmd)
}
示例#3
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 *chainhash.Hash) FutureGetBlockResult {
	hash := ""
	if blockHash != nil {
		hash = blockHash.String()
	}

	cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(false), nil)
	return c.sendCmd(cmd)
}
示例#4
0
// GetBlockHeaderVerboseAsync 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 GetBlockHeader for the blocking version and more details.
func (c *Client) GetBlockHeaderVerboseAsync(blockHash *chainhash.Hash) FutureGetBlockHeaderVerboseResult {
	hash := ""
	if blockHash != nil {
		hash = blockHash.String()
	}

	cmd := btcjson.NewGetBlockHeaderCmd(hash, btcjson.Bool(true))
	return c.sendCmd(cmd)
}
// 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 *chainhash.Hash) FutureGetRawTransactionResult {
	hash := ""
	if txHash != nil {
		hash = txHash.String()
	}

	cmd := btcjson.NewGetRawTransactionCmd(hash, btcjson.Int(0))
	return c.sendCmd(cmd)
}
// 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,
	txHash []byte, outpointIdx uint32) credit {
	var hash chainhash.Hash
	if err := hash.SetBytes(txHash); 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)
}
示例#7
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 *chainhash.Hash,
	addresses []btcutil.Address, outpoints []*wire.OutPoint,
	endBlock *chainhash.Hash) FutureRescanResult {

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

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

	// Convert block hashes to strings.
	var startBlockHashStr, endBlockHashStr string
	if startBlock != nil {
		startBlockHashStr = startBlock.String()
	}
	if endBlock != nil {
		endBlockHashStr = 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(startBlockHashStr, addrs, ops,
		&endBlockHashStr)
	return c.sendCmd(cmd)
}
示例#8
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 *chainhash.Hash) 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
}