This package is now a sub-package in the rpcclient directory of the btcd repository.
btcsuite / btcrpcclient Goto Github PK
View Code? Open in Web Editor NEWImplements a robust and easy to use websocket-enabled Bitcoin JSON-RPC client.
Implements a robust and easy to use websocket-enabled Bitcoin JSON-RPC client.
With segwit activation just around the corner, it's probably a good time to support this rpc command
If the connection config's DisableConnectOnNew option is true, the client will still log that it established a connection to the remote server in New even though no connection attempt was made yet.
The (*Client).disconnect
channel is used by (*Client).sendMessage
to unblock when the client disconnects. This is done by closing the channel, which unblocks all channel reads. However, when the client reconnects, the channel is reassigned with a new value (infrastructure.go:622), since the closed channel cannot be reopened. This introduces a data race where a client may read the channel while it is being reassigned during a reconnect.
There are a couple ways to fix this. Either the disconnect channel can be protected by the client mutex (meaning that sendMessage
should take a copy of the channel, unlock the mutex, and select on the copy), or every client can run another goroutine that sends empty structs manually when disconnected, and stops sending when connected. The latter option is easier to get right (the channel never changes and does not need to be protected by the client mutex) but may be a little less efficient since another goroutine must run and multiple client sends cannot be aborted at the same time since this introduces an unnecessary synchronization point.
Now, this should work as supposedly the blockchain RPC API is Bitcoind compatible. However, I'm getting:
json: cannot unmarshal string into Go value of type float64
when using client.GetBalanceMinConf. I only get this when I try to do this against blockchain.info. Works fine when running against a local bitcoind client. So, what is going on here? I noticed blockchain returns a JSONArray, but standard client returns just a string? Am I missing something?
Thanks!
I have been trying to connect my application via a local SOCKS 5 proxy, but I'm getting errors when I do so.
I have bitcoind running on a network at address 192.168.1.10 (example). The RPC server is running on the default port of 8332. On my local machine, outside of that network, I have an SSH tunnel with my SOCKS 5 proxy, listening on port 1080, as per the SOCKS default.
My ConnConfig setup looks like;
Conf := &btcrpcclient.ConnConfig{
Host: "192.168.1.10:8332",
User: "sturd",
Pass: "sturd's password",
HTTPPostMode: true,
DisableTLS: true,
Proxy: "127.0.0.1",
}
With this configuration, attempting to execute a RPC command results in the error;
Post http://192.168.1.10:8332: proxyconnect tcp: dial tcp :0: connectex: The requested address is not valid in its context.
Is there a correct way to format the Proxy string which I'm missing?
I have code that needs to do something like:
var asyncResult btcrpcclient.FutureFooResult
for {
select {
case <-beginAsyncRequest:
asyncResult = client.FooAsync()
case result := <-asyncResult:
// Use the result
}
}
This can't be done since the result returned by each *Async function is a channel of the unexported btcrpcclient result type. More specifically, while receiving on the channel works, the result is unusable.
The FutureFooResult.Receive function is not an option here as it can not be used in a select statement.
As long as only the error is needed, and not the RPC result (which is saved as a byte slice), this quick and dirty hack works:
func (r *result) Err() error {
return r.err
}
This has its own downsides as well since it declares an exported function with an unexported receiver type (essentially, this would be undocumented by godoc). There is also no equivalent function that could be added for the result since it would leave the result JSON marshalled.
Without being able to specify a generic result type (grmbl), I don't see any good way to solve this problem for every case.
In order to help maintain the connection during periods of inactivity, the client should periodically send a websocket ping control message to the server and ensure a pong is received within a reasonable time frame.
Hi,
Lately I've been trying to use btcrpcclient and the btcsuite to make transactions with an OP_RETURN script. It seems impossible to implement with the provided CreateRawTransaction if I'm correct, so I wanted to ask if there is any way to implement this ?
Thanks :)
Edit: I'm using Bitcoin core (bitcoind) on the testnet chain
A call to GetBlock() where the block has not been confirmed yet returns a raw json error instead of an RPCError:
{"result":null,"error":{"code":-5,"message":"Block not found"},"id":2}
Not sure but briefly looking through the code, if status code isn't between 200 and 300 then it just returns raw json. Here's my config:
connCfg := &btcrpcclient.ConnConfig{
Host: config.Host,
Endpoint: "ws",
User: config.User,
Pass: config.Pass,
HTTPPostMode: true,
//Certificates: certs,
DisableTLS: true,
}
I was looking into your code and I see that this method is not implemented, could you add this in future updates?
If i use SetGenerate(true, 0)
or SetGenerate(false, [whatever])
, cpu mining will naturally stop but the rpc will never return. The stuff happening in btcd
seem super correct so i think it's an issue for the rpc client or the btcjson
package.
Two new commands i.e. CreateNewAccount
, RenameAccount
were added #22. Need to add async versions of these.
When I try to install/get btcrpcclient, the following error occurs immediately
$ go get github.com/btcsuite/btcrpcclient
../goprojects/src/github.com/btcsuite/btcrpcclient/rawtransactions.go:247: not enough arguments in call to btcjson.NewCreateRawTransactionCmd
../goprojects/src/github.com/btcsuite/btcrpcclient/rawtransactions.go:555: not enough arguments in call to btcjson.NewSearchRawTransactionsCmd
../goprojects/src/github.com/btcsuite/btcrpcclient/rawtransactions.go:601: not enough arguments in call to btcjson.NewSearchRawTransactionsCmd
hello , i want to get the address which send to my address , how can i get it by api ?
i get txid by ListTransactionsResult .
thanks ~
Sample transaction output for bitcoin-cli listsinceblock
{
"account": "",
"address": "n3sEWENqFxKhg34bzjxeTBCTdsdwuitbW6",
"category": "receive",
"amount": 0.00050000,
"label": "",
"vout": 1,
"confirmations": 890,
"blockhash": "00000000000002a098cdb26dc03d3543ef778c0d7ec2b8ccc530ef0f8babbd2e",
"blockindex": 3,
"blocktime": 1484721269,
"txid": "e0554991c84d22e1f3f781b75c320aa255c8fec8c5af5ebc72a015d18553b2f1",
"walletconflicts": [
],
"time": 1484721213,
"timereceived": 1484721213,
"bip125-replaceable": "no"
}
Notice how there's a "bip125-replaceable". Would you be able to expose that in ListTransactionsResult
?
Thanks!
This makes backwards compatibility impossible when it could be since it prevents the addition of other parameters passed in the notification in later versions of the API. Instead, it should check that there are at least the expected number of parameters.
The unit tests for this package should include a mock RPC server with known good static JSON-RPC replies to various RPC requests. The static replies can ignore the actual RPC request params as the intention of these unit tests will be to prove the client properly marshals, unmarshals, and routes messages of the underlying JSON-RPC messages.
I have need to access watch only transactions but the GetTransaction function currently passes nil into the btcjson NewGetTransactionCmd constructor (meaning do not return watch only). Is there any objection to a PR exposing the the bool in the GetTransaction and GetTransactionAsync parameters?
With some commands like ListUnspentMinMaxAddresses, the Receive call occasionally never returns. Any idea why?
CreateRawTransaction (and possibly other methods, I haven't done an exhaustive check) are currently using the type map[string]int64 to describe the address->amount pairings for the created transaction. This would be better expressed using btcutil.Amount instead of int64.
For example take this code:
amounts := make(map[btcutil.Address]btcutil.Amount)
for _, p := range paymentsToMake {
addr, _ := btcutil.DecodeAddress(p.Address, net)
amounts[addr] = amounts[addr] + p.amount
}
client.SendMany("", amounts)
There is a subtle problem that looking up in amounts will never work, because despite btcutil.Address being comparable, it's not a logic comparison. When it's finally sent over rpc, one of the payments can be silently be dropped
This should return an error to the caller rather than panicing.
Here's a sample call:
getmempoolentry abed2bc7cc77a4bc342a67e29da974b9cc69d47afa6279463d916009b1bcb6a3

{
"size": 372,
"fee": 0.00008280,
"modifiedfee": 0.00008280,
"time": 1484977137,
"height": 1085243,
"startingpriority": 541889.8421052631,
"currentpriority": 568809.6710526316,
"descendantcount": 1,
"descendantsize": 372,
"descendantfees": 8280,
"ancestorcount": 1,
"ancestorsize": 372,
"ancestorfees": 8280,
"depends": [
]
}
In my particular use-case, the fields I need are `ancestorsize` and `ancestorfees` as I'm trying to compute the feerate to guestimate if it'll confirm. I notice these fields are also missing from btcjson.GetRawMempoolVerboseResult. So it'd be nice if they were also made complete
Currently client.ListAccounts() returns a balance amount with the symbol "BTC" hard coded in as a suffix.
Please add the ability to substitute in a different symbol, perhaps as a field in chaincfg.Params, in order to add additional flexibility in supporting other cybercoins.
It's currently not possible to distinguish HTTP response codes during the initial connection setup with the go.net websockets package. This means it's not possible for the client to know if an actual authentication failure occurred versus an invalid path, etc.
There are also other issues with the go.net websockets package such as the lack of support for ping/pong websocket protocol messages to help keep the connection alive and the requirement to cast between strings and []byte (causing extra allocations and mem copies) to determine the frame type.
In practice, these issues don't prevent the current code from working, but the client will be more robust, efficient, and be able to expose better connection errors to the caller by switching to the Gorilla websocket package.
GetBlock
takes a hash and returns a raw block, but that doesn't come with height. So this means if I want to get a raw block along with its height, I have to:
GetBlockVerbose
to get a verbose blockGetBlock
to get a raw blockSetHeight()
to set the height from the verbose block to the raw blockIs this a bug? I haven't dug into the code yet.
While writing a long-running application that sends many requests to btcd, I noticed that eventually API calls would block forever.
I am able to reproduce the issue with a small example program, which I've uploaded together with the relevant logs. After running for little over an hour and making roughly 250,000 1,000,000 requests, calls to the API methods of btcrpcclient.Client
block, stalling the program. However, the connection to btcd does not appear to be lost as the notification handlers are still being called. Also, btcd still responds to requests made with btcctl.
The complete btcd log was too large for Gist, but if necessary I can upload it somewhere else. I am using the latest versions of btcd (btcsuite/btcd@6e64485) and btcrpcclient (6492255).
I will continue to try to narrow down the problem, but I thought I'd ask in the meantime in case I'm just making some silly mistake. Am I using btcrpcclient incorrectly? Should I be rate limiting my requests to btcd perhaps? Any help would be greatly appreciated!
Here's a simple test script I'm running:
https://gist.github.com/tuxcanfly/84a66a35bf4b32904415
2014/07/01 11:48:34 Starting btcd on simnet...
11:48:34 2014-07-01 [ERR] BTCW: Cannot open default account: wallet file does not exist
11:48:34 2014-07-01 [INF] BTCW: RPCS: RPC server listening on 0.0.0.0:18557
11:48:34 2014-07-01 [INF] BTCW: RPCS: RPC server listening on [::]:18557
11:48:34 2014-07-01 [WRN] BTCW: Unable to open chain server client connection: dial tcp 127.0.0.1:18556: connection refused
11:48:34 2014-07-01 [INF] BTCW: New websocket client 127.0.0.1:59196
11:48:39 2014-07-01 [INF] BTCW: Established connection to btcd
2014/07/01 11:48:40 addr: %!(EXTRA *btcutil.AddressPubKeyHash=SgTNRfXZh4oH6D6Y6JSQtaeYAZyamKcsFZ)
11:48:40 2014-07-01 [INF] BTCW: Received SIGINT (Ctrl+C). Shutting down...
11:48:40 2014-07-01 [WRN] BTCW: Server shutting down
11:48:40 2014-07-01 [WRN] BTCW: Disconnecting chain server client connection
11:48:40 2014-07-01 [INF] BTCW: Disconnected websocket client 127.0.0.1:59196
*hangs*
I was expecting the second API call to raise an error because the btcwallet
is shutdown and no longer connected.
Great job. But I found a problem here, it can't support other coins, while it should. cause btcutil would validated data only belong to bitcoin, like address, etc. I have to add a method SendCmd in infrastructure.go, and override every api I need in my code. could you just make api return a map result, or don't validate data? Thanks
GetBlockVerbose takes an argument verboseTx bool
, and make the rpc call
{"jsonrpc":"1.0","method":"getblock","params":["0000000000000000023ce2ceba757ccca3d3ee4938608f37f1e73cd4ec3d6d59",true,verboseTx],"id":1}
However bitcoin core's getblock
only takes one argument, so this gives an error
@davecgh I have two bitcoind
nodes in regtest
mode, both connecting with each other locally. I am using rpcclient
to get the information about block with GetBlockVerbose
command.
I caused chain reorganisation by removing the data directory and restarting one of the nodes, this caused bitcoind
to return -1
in confirmation number, which caused GetBlockVerbose
fail with json: cannot unmarshal number -1 into Go struct field GetBlockVerboseResult.confirmations of type uint64
.
Do you think that we could change uint64
to int64
, to avoid such error, so that I could handle chain reorganisation properly in my service?
Hi,
I love this project, but I am now at a point where I need the "move" command to be able to move bitcoins between accounts. According to a search I found this in "wallet.go":
// move (NYI in btcwallet)
So, I guess it's somewhere in the plans to implement. Question is when? Thing is, this is suppose to be pretty much complaint with the Bitcoin RPC API, right? And I find this command quite important. How else will I be able to move bitcoins between user accounts? Keeping track of it externally and doing such solution is just messy. I noticed blockchain.info has support for it as well.
I think I will look at the code and see if I might be able to implement this myself in the meantime.
Does this work for sitting on top of Bitcoinj, so I can interface with Bitcoinj in Go?
getblockheader
is an important RPC call that is not exposed. At first glance it looks the same as getblock
and dropping the tx
array, but there's an important difference:
elsa@winter:~$ bitcoin-cli getblockheader 000000000000000000f37fddab6ae59b06d55c9949c4bf35151b7776ff551897
{
"hash": "000000000000000000f37fddab6ae59b06d55c9949c4bf35151b7776ff551897",
"confirmations": 100001,
"height": 329936,
"version": 2,
"versionHex": "00000002",
"merkleroot": "48786f412860f93607fd2b67bfc32d1c905c83da12efd35f5718b38da44b296b",
"time": 1415947066,
"mediantime": 1415942411,
"nonce": 1327336627,
"bits": "181bc330",
"difficulty": 39603666252.41841,
"chainwork": "00000000000000000000000000000000000000000002ba5d1b2f3f765cff293c",
"previousblockhash": "00000000000000000b954ce608c45c9229c3d8e0f8f710e5663e0bb9091d33e1",
"nextblockhash": "000000000000000000657614104babe20c0f76066c288c0b849504ea11f7af6e"
}
elsa@winter:~$ bitcoin-cli getblock 000000000000000000f37fddab6ae59b06d55c9949c4bf35151b7776ff551897
error code: -32603
error message:
Block not available (pruned data)
Would be nice to support this rpc command
func main() {
// Connect to local bitcoin core RPC server using HTTP POST mode.
connCfg := &rpcclient.ConnConfig{
Host: "192.168.1.100:8332",
User: "bitcoinrpc",
Pass: "somehardhash",
HTTPPostMode: true, // Bitcoin core only supports HTTP POST mode
DisableTLS: true, // Bitcoin core does not provide TLS by default
}
log.SetFlags(log.LstdFlags | log.Lshortfile)
var err error
// Notice the notification parameter is nil since notifications are
// not supported in HTTP POST mode.
client, err := rpcclient.New(connCfg, nil)
if err != nil {
log.Fatal(err)
}
defer client.Shutdown()
//scanDeep(client, 1)
// Get the current block count.
blockCount, err := client.GetBlockCount()
if err != nil {
log.Fatal(err)
}
log.Printf("Block count: %d", blockCount)
var hash chainhash.Hash
chainhash.Decode(&hash, "0000000000000000015ed7a2934f8ecb39eda15459376fff64284e1a87688d5d")
result, e := client.GetBlockVerboseTx(&hash)
if e != nil {
log.Fatal(e)
}
}
This ends with:
2017/12/04 17:49:44 bitcoind-client.go:47: Block count: 497578
2017/12/04 17:49:44 bitcoind-client.go:54: -1: getblock "blockhash" ( verbosity )
If verbosity is 0, returns a string that is serialized, hex-encoded data for block 'hash'.
If verbosity is 1, returns an Object with information about block <hash>.
If verbosity is 2, returns an Object with information about block <hash> and information about each transaction.
Arguments:
1. "blockhash" (string, required) The block hash
2. verbosity (numeric, optional, default=1) 0 for hex encoded data, 1 for a json object, and 2 for json object with transaction data
Result (for verbosity = 0):
"data" (string) A string that is serialized, hex-encoded data for block 'hash'.
Result (for verbosity = 1):
{
"hash" : "hash", (string) the block hash (same as provided)
"confirmations" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain
"size" : n, (numeric) The block size
"strippedsize" : n, (numeric) The block size excluding witness data
"weight" : n (numeric) The block weight as defined in BIP 141
"height" : n, (numeric) The block height or index
"version" : n, (numeric) The block version
"versionHex" : "00000000", (string) The block version formatted in hexadecimal
"merkleroot" : "xxxx", (string) The merkle root
"tx" : [ (array of string) The transaction ids
"transactionid" (string) The transaction id
,...
],
"time" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)
"mediantime" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)
"nonce" : n, (numeric) The nonce
"bits" : "1d00ffff", (string) The bits
"difficulty" : x.xxx, (numeric) The difficulty
"chainwork" : "xxxx", (string) Expected number of hashes required to produce the chain up to this block (in hex)
"previousblockhash" : "hash", (string) The hash of the previous block
"nextblockhash" : "hash" (string) The hash of the next block
}
Result (for verbosity = 2):
{
..., Same output as verbosity = 1.
"tx" : [ (array of Objects) The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 "tx" result.
,...
],
,... Same output as verbosity = 1.
}
Examples:
> bitcoin-cli getblock "00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"
> curl --user myusername --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getblock", "params": ["00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/
Process finished with exit code 0
Hey guys,
Has this been updated to support the new RPC commands in Core v0.14.0?
I've done some digging around but can't find certain RPC calls as part of the package, namely: getnetworkinfo().
Is this something that has been adding but I'm missing or are there plans to add this in?
I see it implemented in Godoc (http://localhost:6060/src/pkg/btcrpcclient/wallet.go?s=64545:64632#L1873) but it doesn't appear on master. Is it okay to use?
When doing createrawtransaction
each transaction input should allow you to specify a sequence number. This is important to be able to create a bip-125 compatible transaction
This line : https://github.com/btcsuite/btcrpcclient/blob/master/chain.go#L143
SYMPTONS
Calling function getBlockVerbose or GetBlockVerboseAsync returns an error, no matter which parameters are used. Error message at the end
HOW TO REPRODUCE
hash, err := client.GetBlockHash(100)
if err != nil {
log.Fatal(err)
}
block, err := client.GetBlock(hash)
if err != nil { // err is nil
log.Fatal(err)
}
blockverbose, err := client.GetBlockVerbose(hash, true) //no matter is true or false is used, error is triggered always
if err != nil {
log.Fatal(err) // this is triggered
}
NOTE
Same error message is achieved directly with bitcoin-cli if a second bool parameter (verboseTx) is used
All of these fails
bitcoin-cli getblock 000000007bc154e0fa7ea32218a72fe2c1bb9f86cf8c9ebf9a715ed27fdb229a true true
bitcoin-cli getblock 000000007bc154e0fa7ea32218a72fe2c1bb9f86cf8c9ebf9a715ed27fdb229a true false
bitcoin-cli getblock 000000007bc154e0fa7ea32218a72fe2c1bb9f86cf8c9ebf9a715ed27fdb229a false true
bitcoin-cli getblock 000000007bc154e0fa7ea32218a72fe2c1bb9f86cf8c9ebf9a715ed27fdb229a false false
These works
bitcoin-cli getblock 000000007bc154e0fa7ea32218a72fe2c1bb9f86cf8c9ebf9a715ed27fdb229a true
bitcoin-cli getblock 000000007bc154e0fa7ea32218a72fe2c1bb9f86cf8c9ebf9a715ed27fdb229a false
Thus forcing verboseTx to nil, "fix" the issue, but verboseTx is still in the code. I'm still reviewing the code so I'm not sure about the consequences of this change.
ERROR MESSAGE
error: {"code":-1,"message":"getblock "hash" ( verbose )
If verbose is false, returns a string that is serialized, hex-encoded data for block 'hash'.
If verbose is true, returns an Object with information about block .
Arguments:
Result (for verbose = true):
{
"hash" : "hash", (string) the block hash (same as provided)
"confirmations" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain
"size" : n, (numeric) The block size
"height" : n, (numeric) The block height or index
"version" : n, (numeric) The block version
"merkleroot" : "xxxx", (string) The merkle root
"tx" : [ (array of string) The transaction ids
"transactionid" (string) The transaction id
,...
],
"time" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)
"nonce" : n, (numeric) The nonce
"bits" : "1d00ffff", (string) The bits
"difficulty" : x.xxx, (numeric) The difficulty
"previousblockhash" : "hash", (string) The hash of the previous block
"nextblockhash" : "hash" (string) The hash of the next block
}
Result (for verbose=false):
"data" (string) A string that is serialized, hex-encoded data for block 'hash'.
Examples:
bitcoin-cli getblock "00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"
curl --user myusername --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getblock", "params": ["00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/
"}
Tried making a CreateNewAccount call but after reading the code a little bit it seems the call only works with btcd's custom wallet server running.
I don't understand too much about btcd yet, but maybe it should be documented in the code that some RPC calls don't work with the default Bitcoin protocol / bitcoind daemon?
ListSinceBlock
// ListSinceBlock returns all transactions added in blocks since the specified
// block hash, or all transactions if it is nil, using the default number of
// minimum confirmations as a filter.
and
ListSinceBlockMinConf
// ListSinceBlockMinConf returns all transactions added in blocks since the
// specified block hash, or all transactions if it is nil, using the specified
// number of minimum confirmations as a filter.
However, that is wrong. The target-confirmation
argument in to listsinceblock
in bitcoin core does not affect the list of returned transactions, and is not a filter. What it does is only affect the field "lastblock" which btcrpcclient does not expose.
So actually ListSinceBlock and ListSinceBlockMinConf are both identical in btcrpcclient, and incorrectly say they filter the list.
I suggest that the docs get fixed, and the return type of ListSinceBlock
and ListSinceBlockMinConf
return a struct with a list of transaction and the last block (e.g. bitcoin core:
{
"transactions": [],
"lastblock": "0000000000000000018539df4038f99778b61a18310bb7ba108ac240cd62eb9f"
}
The reason I say it's dangerously wrong, as this can very easily lead to people accepting 0-conf transactions when they intended to filter to X confirmations.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.