// 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 }
// 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) }
// 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) }
// 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) }
// 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) }
// 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 }