无法通过 JSON-RPC post GETBLOCKHASH 到比特币核心
Unable to post GETBLOCKHASH to Bitcoin Core via JSON-RPC
以下代码大部分工作正常:
public static string RequestServer(string methodName, List<string> parameters)
{
// Use the values you specified in the bitcoin server command line
string ServerIp = "http://localhost.:8332";
string UserName = "username";
string Password = "password";
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(ServerIp);
webRequest.Credentials = new NetworkCredential(UserName, Password);
webRequest.ContentType = "application/json-rpc";
webRequest.Method = "POST";
string responseValue = string.Empty;
// Configure request type
JObject joe = new JObject();
joe.Add(new JProperty("jsonrpc", "1.0"));
joe.Add(new JProperty("id", "1"));
joe.Add(new JProperty("method", methodName));
JArray props = new JArray();
foreach (var parameter in parameters)
{
props.Add(parameter);
}
joe.Add(new JProperty("params", props));
// serialize JSON for request
string s = JsonConvert.SerializeObject(joe);
byte[] byteArray = Encoding.UTF8.GetBytes(s);
webRequest.ContentLength = byteArray.Length;
Stream dataStream = webRequest.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
// deserialze the response
StreamReader sReader = null;
WebResponse webResponse = webRequest.GetResponse();
sReader = new StreamReader(webResponse.GetResponseStream(), true);
responseValue = sReader.ReadToEnd();
var data = JsonConvert.DeserializeObject(responseValue).ToString();
return data;
}
然后我可以使用 methodName
例如 getnewaddress
从服务器取回数据:
static void Main(string[] args)
{
Console.WriteLine(RequestServer("getnewaddress", new List<string>(){"","legacy"}));
}
那将 return 像这样:
{
"result": "1EWJkGrirdhXpduoNdccxaCx7syqWHuDcK",
"error": null,
"id": "1"
}
上述方法名称在使用终端时也能正常工作:
bitcoin@desktop:~/Downloads/bitcoin-0.20.0-x86_64-linux-gnu/bitcoin-0/bin$ ./bitcoin-cli getnewaddress "" "legacy"
1EWJkGrirdhXpduoNdccxaCx7syqWHuDcK
bitcoin@desktop:~/Downloads/bitcoin-0.20.0-x86_64-linux-gnu/bitcoin-0.20.0/bin$
我可以用相同的方式使用一些方法名称,它们工作正常。但是,当我使用 getblockhash
:
static void Main(string[] args)
{
Console.WriteLine(RequestServer("getblockhash", new List<string>(){"0"}));
}
它给我以下错误:
bitcoin@desktop:~/Code/blockchain-app$ dotnet run
Unhandled exception. System.Net.WebException: The remote server returned an error: (500) Internal Server Error.
at System.Net.HttpWebRequest.GetResponse()
at blockchain-app.Program.RequestServer(String methodName, List`1 parameters) in /home/bitcoin/Code/blockchain-app/Program.cs:line 72
at blockchain-app.Program.Main(String[] args) in /home/bitcoin/Code/blockchain-app/Program.cs:line 29
bitcoin@desktop:~/Code/blockchain-app$
调试时,错误发生在这一行:
WebResponse webResponse = webRequest.GetResponse();
如果我尝试在终端中使用该 methodName 手动检查输出,如下所示,它工作正常:
bitcoin@desktop:~/Downloads/bitcoin-0.20.0-x86_64-linux-gnu/bitcoin-0.20.0/bin$ ./bitcoin-cli getblockhash 0
000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
bitcoin@desktop:~/Downloads/bitcoin-0.20.0-x86_64-linux-gnu/bitcoin-0.20.0/bin$
除了 methodName 和发送的参数外,请求示例结构在我看来是一样的:
https://bitcoincore.org/en/doc/0.20.0/rpc/wallet/getnewaddress/
https://bitcoincore.org/en/doc/0.20.0/rpc/blockchain/getblockhash/
有人知道为什么会这样吗?
我 认为 问题是您在调用 getblockhash
时为高度索引传递了错误的参数类型。您链接到的文档说它应该是一个数字(整数)参数,但您传递的是一个字符串。相反,getnewaddress
方法使用字符串参数,因此您现有的代码适用于此。
如果您捕获由 RequestServer
方法生成的 JSON,它看起来像这样:
{"jsonrpc":"1.0","id":"1","method":"getblockhash","params":["0"]}
但是 getblockhash
文档中的示例如下所示:
{"jsonrpc":"1.0","id":"curltest","method":"getblockhash","params":[1000]}
请注意 params
数组中的值未在示例中引用,而在您的示例中引用。
要修复,请尝试以下操作:
更改现有 RequestServer
方法的方法签名:
public static string RequestServer(string methodName, List<string> parameters)
对此:
public static string RequestServer(string methodName, List<JToken> parameters)
使用旧签名创建 RequestServer
方法的新重载,调用您刚刚更改的现有签名。这将允许您已经工作的其他方法调用(例如 getnewaddress
)继续工作而无需更改。
public static string RequestServer(string methodName, List<string> parameters)
{
return RequestServer(methodName, parameters.Select(p => new JValue(p)).ToList<JToken>());
}
将调用getblockhash
的代码改成:
Console.WriteLine(RequestServer("getblockhash", new List<string>() { "0" }));
对此:
Console.WriteLine(RequestServer("getblockhash", new List<JToken>() { new JValue(0) }));
请注意,我在 2018 年为您回答了一个 ,其中我推荐了上面显示的相同步骤 1 和 2,因此您可能已经完成了该部分。如果是这样,您需要做的就是第 3 步。
以下代码大部分工作正常:
public static string RequestServer(string methodName, List<string> parameters)
{
// Use the values you specified in the bitcoin server command line
string ServerIp = "http://localhost.:8332";
string UserName = "username";
string Password = "password";
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(ServerIp);
webRequest.Credentials = new NetworkCredential(UserName, Password);
webRequest.ContentType = "application/json-rpc";
webRequest.Method = "POST";
string responseValue = string.Empty;
// Configure request type
JObject joe = new JObject();
joe.Add(new JProperty("jsonrpc", "1.0"));
joe.Add(new JProperty("id", "1"));
joe.Add(new JProperty("method", methodName));
JArray props = new JArray();
foreach (var parameter in parameters)
{
props.Add(parameter);
}
joe.Add(new JProperty("params", props));
// serialize JSON for request
string s = JsonConvert.SerializeObject(joe);
byte[] byteArray = Encoding.UTF8.GetBytes(s);
webRequest.ContentLength = byteArray.Length;
Stream dataStream = webRequest.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
// deserialze the response
StreamReader sReader = null;
WebResponse webResponse = webRequest.GetResponse();
sReader = new StreamReader(webResponse.GetResponseStream(), true);
responseValue = sReader.ReadToEnd();
var data = JsonConvert.DeserializeObject(responseValue).ToString();
return data;
}
然后我可以使用 methodName
例如 getnewaddress
从服务器取回数据:
static void Main(string[] args)
{
Console.WriteLine(RequestServer("getnewaddress", new List<string>(){"","legacy"}));
}
那将 return 像这样:
{
"result": "1EWJkGrirdhXpduoNdccxaCx7syqWHuDcK",
"error": null,
"id": "1"
}
上述方法名称在使用终端时也能正常工作:
bitcoin@desktop:~/Downloads/bitcoin-0.20.0-x86_64-linux-gnu/bitcoin-0/bin$ ./bitcoin-cli getnewaddress "" "legacy"
1EWJkGrirdhXpduoNdccxaCx7syqWHuDcK
bitcoin@desktop:~/Downloads/bitcoin-0.20.0-x86_64-linux-gnu/bitcoin-0.20.0/bin$
我可以用相同的方式使用一些方法名称,它们工作正常。但是,当我使用 getblockhash
:
static void Main(string[] args)
{
Console.WriteLine(RequestServer("getblockhash", new List<string>(){"0"}));
}
它给我以下错误:
bitcoin@desktop:~/Code/blockchain-app$ dotnet run
Unhandled exception. System.Net.WebException: The remote server returned an error: (500) Internal Server Error.
at System.Net.HttpWebRequest.GetResponse()
at blockchain-app.Program.RequestServer(String methodName, List`1 parameters) in /home/bitcoin/Code/blockchain-app/Program.cs:line 72
at blockchain-app.Program.Main(String[] args) in /home/bitcoin/Code/blockchain-app/Program.cs:line 29
bitcoin@desktop:~/Code/blockchain-app$
调试时,错误发生在这一行:
WebResponse webResponse = webRequest.GetResponse();
如果我尝试在终端中使用该 methodName 手动检查输出,如下所示,它工作正常:
bitcoin@desktop:~/Downloads/bitcoin-0.20.0-x86_64-linux-gnu/bitcoin-0.20.0/bin$ ./bitcoin-cli getblockhash 0
000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
bitcoin@desktop:~/Downloads/bitcoin-0.20.0-x86_64-linux-gnu/bitcoin-0.20.0/bin$
除了 methodName 和发送的参数外,请求示例结构在我看来是一样的:
https://bitcoincore.org/en/doc/0.20.0/rpc/wallet/getnewaddress/ https://bitcoincore.org/en/doc/0.20.0/rpc/blockchain/getblockhash/
有人知道为什么会这样吗?
我 认为 问题是您在调用 getblockhash
时为高度索引传递了错误的参数类型。您链接到的文档说它应该是一个数字(整数)参数,但您传递的是一个字符串。相反,getnewaddress
方法使用字符串参数,因此您现有的代码适用于此。
如果您捕获由 RequestServer
方法生成的 JSON,它看起来像这样:
{"jsonrpc":"1.0","id":"1","method":"getblockhash","params":["0"]}
但是 getblockhash
文档中的示例如下所示:
{"jsonrpc":"1.0","id":"curltest","method":"getblockhash","params":[1000]}
请注意 params
数组中的值未在示例中引用,而在您的示例中引用。
要修复,请尝试以下操作:
更改现有
RequestServer
方法的方法签名:public static string RequestServer(string methodName, List<string> parameters)
对此:
public static string RequestServer(string methodName, List<JToken> parameters)
使用旧签名创建
RequestServer
方法的新重载,调用您刚刚更改的现有签名。这将允许您已经工作的其他方法调用(例如getnewaddress
)继续工作而无需更改。public static string RequestServer(string methodName, List<string> parameters) { return RequestServer(methodName, parameters.Select(p => new JValue(p)).ToList<JToken>()); }
将调用
getblockhash
的代码改成:Console.WriteLine(RequestServer("getblockhash", new List<string>() { "0" }));
对此:
Console.WriteLine(RequestServer("getblockhash", new List<JToken>() { new JValue(0) }));
请注意,我在 2018 年为您回答了一个