osh*_*nen 5 c# json json-rpc json.net bitcoin
我试图通过发布到本地比特币全节点,json-rpc但是我从服务器收到错误.
遵循以下文档:https: //bitcoincore.org/en/doc/0.17.0/rpc/rawtransactions/createrawtransaction/
我可以看到以下createrawtransaction请求的示例结构:
{"jsonrpc": "1.0", "id":"curltest", "method": "createrawtransaction", "params": ["[{\"txid\":\"myid\",\"vout\":0}]", "[{\"address\":0.01}]"] }
Run Code Online (Sandbox Code Playgroud)
我的代码创建了以下结构,它似乎与bitcoincore.org中的示例结构相匹配:
{"jsonrpc":"1.0","id":"1","method":"createrawtransaction","params":["[{\"txid\":\"1a43a1f27c5837d5319a45217aa948a4d39c1d89faf497ce59de5bd570a64a26\",\"vout\":1}]","[{\"2NAZpRsvj9BstxxCDkKoe1FVjmPPxdmvqKj\":0.01}]"]}
Run Code Online (Sandbox Code Playgroud)
但它给出了一个错误:
System.Net.WebException
HResult=0x80131509
Message=The remote server returned an error: (500) Internal Server Error.
Source=RawTransactions
StackTrace:
at RawTransactions.Form1.RequestServer(String methodName, List`1 parameters) in C:\Users\userthree\Documents\Visual Studio 2017\Projects\RawTransactions\RawTransactions\Form1.cs:line 132
at RawTransactions.Form1.button1_Click(Object sender, EventArgs e) in C:\Users\userthree\Documents\Visual Studio 2017\Projects\RawTransactions\RawTransactions\Form1.cs:line 77
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at RawTransactions.Program.Main() in C:\Users\userthree\Documents\Visual Studio 2017\Projects\RawTransactions\RawTransactions\Program.cs:line 19
Run Code Online (Sandbox Code Playgroud)
下面是我用来发出RPC请求的方法,我从API参考中得到了这个方法:
https://en.bitcoin.it/wiki/API_reference_(JSON-RPC)#.NET_.28C.23.29
public static string RequestServer(string methodName, List<string> parameters)
{
string ServerIp = "http://localhost:18332";
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 respVal = string.Empty;
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 the 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();
StreamReader streamReader = null;
try
{
WebResponse webResponse = webRequest.GetResponse();
streamReader = new StreamReader(webResponse.GetResponseStream(), true);
respVal = streamReader.ReadToEnd();
var data = JsonConvert.DeserializeObject(respVal).ToString();
return data;
}
catch (Exception exp)
{
throw (exp);
}
finally
{
if (streamReader != null)
{
streamReader.Close();
}
}
return string.Empty;
}
Run Code Online (Sandbox Code Playgroud)
这是我尝试使用上述方法:
private void button1_Click(object sender, EventArgs e)
{
StringBuilder sb1 = new StringBuilder();
sb1.Append("[{\"");
sb1.Append("txid");
sb1.Append("\":\"");
sb1.Append(Convert.ToString(data["result"][Convert.ToInt32(txtFromJSON.Text)]["txid"]));
sb1.Append("\",\"");
sb1.Append("vout");
sb1.Append("\":");
sb1.Append(Convert.ToString(data["result"][Convert.ToInt32(txtFromJSON.Text)]["vout"]));
sb1.Append("}]");
StringBuilder sb2 = new StringBuilder();
sb2.Append("[{\"");
sb2.Append(Convert.ToString(data["result"][Convert.ToInt32(txtToJSON.Text)]["address"]));
sb2.Append("\":");
sb2.Append(txtAmountToSpend.Text);
sb2.Append("}]");
// {"jsonrpc":"1.0","id":"1","method":"createrawtransaction","params":["[{\"txid\":\"1a43a1f27c5837d5319a45217aa948a4d39c1d89faf497ce59de5bd570a64a26\",\"vout\":1}]","[{\"2NAZpRsvj9BstxxCDkKoe1FVjmPPxdmvqKj\":0.01}]"]}
data = JObject.Parse(RequestServer("createrawtransaction", new List<string>() { Convert.ToString(sb1), Convert.ToString(sb2) }));
MessageBox.Show(Convert.ToString(data));
}
Run Code Online (Sandbox Code Playgroud)
其他命令如下工作:
// {"jsonrpc":"1.0","id":"1","method":"sendtoaddress","params":["2N8hwP1WmJrFF5QWABn38y63uYLhnJYJYTF","0.1"]}
data = JObject.Parse(RequestServer("sendtoaddress", new List<string>() { "2N8hwP1WmJrFF5QWABn38y63uYLhnJYJYTF", Convert.ToString(0.1) } ));
Run Code Online (Sandbox Code Playgroud)
这也有效:
// {"jsonrpc":"1.0","id":"1","method":"listunspent","params":[]}
data = JObject.Parse(RequestServer("listunspent", new List<String>() { }));
Run Code Online (Sandbox Code Playgroud)
我的问题:
我做错了createrawtransaction什么?
更新1:
正如评论中所建议的那样,我已经改变了StringBuilder,现在正在使用对象,然后使用Newtonsoft.Json序列化对象.
这是我第二次尝试使用https://en.bitcoin.it/wiki/API_reference_(JSON-RPC)#.NET_.28C.23.29中的API参考代码:
private void button1_Click(object sender, EventArgs e)
{
JContainer jArray = new JArray();
JObject jFromTx = new JObject
{
{ "txid", data["result"][Convert.ToInt32(txtFromJSON.Text)]["txid"] },
{ "vout", data["result"][Convert.ToInt32(txtFromJSON.Text)]["vout"] }
};
jArray.Add(jFromTx);
JObject jToTx = new JObject
{
{ Convert.ToString(data["result"][Convert.ToInt32(txtToJSON.Text)]["address"]), Convert.ToDouble(txtAmountToSpend.Text) }
};
JContainer jArray2 = new JArray
{
jToTx
};
string strFrom = JsonConvert.SerializeObject(jArray);
string strTo = JsonConvert.SerializeObject(jArray2);
data = JObject.Parse(RequestServer("createrawtransaction", new List<string>() { strFrom, strTo }));
}
Run Code Online (Sandbox Code Playgroud)
这是新的序列化JSON:
{"jsonrpc":"1.0","id":"1","method":"createrawtransaction","params":["[{\"txid\":\"1a43a1f27c5837d5319a45217aa948a4d39c1d89faf497ce59de5bd570a64a26\",\"vout\":1}]","[{\"2NAZpRsvj9BstxxCDkKoe1FVjmPPxdmvqKj\":0.01}]"]}
Run Code Online (Sandbox Code Playgroud)
与我第一次尝试的旧StringBuilder JSON相比:
{"jsonrpc":"1.0","id":"1","method":"createrawtransaction","params":["[{\"txid\":\"1a43a1f27c5837d5319a45217aa948a4d39c1d89faf497ce59de5bd570a64a26\",\"vout\":1}]","[{\"2NAZpRsvj9BstxxCDkKoe1FVjmPPxdmvqKj\":0.01}]"]}
Run Code Online (Sandbox Code Playgroud)
我仍然收到与以前相同的错误消息(见上文).
我认为问题是你的params数组被双重序列化,所以服务器不知道如何解释请求。我确实意识到您的 JSON 看起来与示例相同,所以我很可能在这里错了;我绝对不是使用比特币核心 API 的专家。但是,我确实查看了应该与 Bitcoin Core 兼容的第三方库的源代码,它似乎没有对createrawtransation请求的参数进行双重序列化。这让我相信双序列化参数是问题所在。
要修复,请尝试以下操作:
RequestServer从此更改现有方法的方法签名:
public static string RequestServer(string methodName, List<string> parameters)
Run Code Online (Sandbox Code Playgroud)
对此:
public static string RequestServer(string methodName, List<JToken> parameters)
Run Code Online (Sandbox Code Playgroud)RequestServer使用旧签名创建该方法的新重载,该签名调用您刚刚更改的现有签名。这将允许您已经工作的其他方法(例如sendtoaddress和listunspent)继续工作而不做任何更改。
public static string RequestServer(string methodName, List<string> parameters)
{
return RequestServer(methodName, parameters.Select(p => new JValue(p)).ToList<JToken>());
}
Run Code Online (Sandbox Code Playgroud)最后,更改button1_Click方法中的代码,使其不会序列化jArrayand jArray2,而是将它们传递给 a List<JToken>to RequestServer。换句话说,更改此代码:
string strFrom = JsonConvert.SerializeObject(jArray);
string strTo = JsonConvert.SerializeObject(jArray2);
data = JObject.Parse(RequestServer("createrawtransaction", new List<string>() { strFrom, strTo }));
Run Code Online (Sandbox Code Playgroud)
对此:
data = JObject.Parse(RequestServer("createrawtransaction", new List<JToken>() { jArray, jArray2 }));
Run Code Online (Sandbox Code Playgroud)通过这些更改,RPC JSONcreaterawtransaction最终应如下所示:
{"jsonrpc":"1.0","id":"1","method":"createrawtransaction","params":[[{"txid":"1a43a1f27c5837d5319a45217aa948a4d39c1d89faf497ce59de5bd570a64a26","vout":1}],[{"2NAZpRsvj9BstxxCDkKoe1FVjmPPxdmvqKj":0.01}]]}
Run Code Online (Sandbox Code Playgroud)
请注意,params数组中多余的引号和反斜杠消失了。与您之前拥有的相比:
{"jsonrpc":"1.0","id":"1","method":"createrawtransaction","params":["[{\"txid\":\"1a43a1f27c5837d5319a45217aa948a4d39c1d89faf497ce59de5bd570a64a26\",\"vout\":1}]","[{\"2NAZpRsvj9BstxxCDkKoe1FVjmPPxdmvqKj\":0.01}]"]}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
175 次 |
| 最近记录: |