jsonrpc: a new 'updatespend' RPC
This commit is contained in:
parent
cf45ba0fa5
commit
3dfc7261db
21
doc/API.md
21
doc/API.md
@ -109,3 +109,24 @@ This command will refuse to create any output worth less than 5k sats.
|
|||||||
| Field | Type | Description |
|
| Field | Type | Description |
|
||||||
| -------------- | --------- | ---------------------------------------------------- |
|
| -------------- | --------- | ---------------------------------------------------- |
|
||||||
| `psbt` | string | PSBT of the spending transaction, encoded as base64. |
|
| `psbt` | string | PSBT of the spending transaction, encoded as base64. |
|
||||||
|
|
||||||
|
|
||||||
|
### `updatespend`
|
||||||
|
|
||||||
|
Store the PSBT of a Spend transaction in database, updating it if it already exists.
|
||||||
|
|
||||||
|
Will merge the partial signatures for all inputs if a PSBT for a transaction with the same txid
|
||||||
|
exists in DB.
|
||||||
|
|
||||||
|
#### Request
|
||||||
|
|
||||||
|
| Field | Type | Description |
|
||||||
|
| --------- | ------ | ------------------------------------------- |
|
||||||
|
| `psbt` | string | Base64-encoded PSBT of a Spend transaction. |
|
||||||
|
|
||||||
|
#### Response
|
||||||
|
|
||||||
|
This command does not return anything for now.
|
||||||
|
|
||||||
|
| Field | Type | Description |
|
||||||
|
| -------------- | --------- | ---------------------------------------------------- |
|
||||||
|
|||||||
@ -5,7 +5,7 @@ use crate::{
|
|||||||
|
|
||||||
use std::{collections::HashMap, convert::TryInto, str::FromStr};
|
use std::{collections::HashMap, convert::TryInto, str::FromStr};
|
||||||
|
|
||||||
use miniscript::bitcoin;
|
use miniscript::bitcoin::{self, consensus, util::psbt::PartiallySignedTransaction as Psbt};
|
||||||
|
|
||||||
fn create_spend(control: &DaemonControl, params: Params) -> Result<serde_json::Value, Error> {
|
fn create_spend(control: &DaemonControl, params: Params) -> Result<serde_json::Value, Error> {
|
||||||
let outpoints = params
|
let outpoints = params
|
||||||
@ -47,6 +47,19 @@ fn create_spend(control: &DaemonControl, params: Params) -> Result<serde_json::V
|
|||||||
Ok(serde_json::json!(&res))
|
Ok(serde_json::json!(&res))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_spend(control: &DaemonControl, params: Params) -> Result<serde_json::Value, Error> {
|
||||||
|
let psbt: Psbt = params
|
||||||
|
.get(0, "psbt")
|
||||||
|
.ok_or(Error::invalid_params("Missing 'psbt' parameter."))?
|
||||||
|
.as_str()
|
||||||
|
.and_then(|s| base64::decode(&s).ok())
|
||||||
|
.and_then(|bytes| consensus::deserialize(&bytes).ok())
|
||||||
|
.ok_or(Error::invalid_params("Invalid 'feerate' parameter."))?;
|
||||||
|
control.update_spend(psbt)?;
|
||||||
|
|
||||||
|
Ok(serde_json::json!({}))
|
||||||
|
}
|
||||||
|
|
||||||
/// Handle an incoming JSONRPC2 request.
|
/// Handle an incoming JSONRPC2 request.
|
||||||
pub fn handle_request(control: &DaemonControl, req: Request) -> Result<Response, Error> {
|
pub fn handle_request(control: &DaemonControl, req: Request) -> Result<Response, Error> {
|
||||||
let result = match req.method.as_str() {
|
let result = match req.method.as_str() {
|
||||||
@ -60,6 +73,12 @@ pub fn handle_request(control: &DaemonControl, req: Request) -> Result<Response,
|
|||||||
"getnewaddress" => serde_json::json!(&control.get_new_address()),
|
"getnewaddress" => serde_json::json!(&control.get_new_address()),
|
||||||
"listcoins" => serde_json::json!(&control.list_coins()),
|
"listcoins" => serde_json::json!(&control.list_coins()),
|
||||||
"stop" => serde_json::json!({}),
|
"stop" => serde_json::json!({}),
|
||||||
|
"updatespend" => {
|
||||||
|
let params = req
|
||||||
|
.params
|
||||||
|
.ok_or(Error::invalid_params("Missing 'psbt' parameter."))?;
|
||||||
|
update_spend(control, params)?
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::method_not_found());
|
return Err(Error::method_not_found());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,3 +93,22 @@ def test_create_spend(minisafed, bitcoind):
|
|||||||
# We can sign it and broadcast it.
|
# We can sign it and broadcast it.
|
||||||
signed_tx_hex = minisafed.sign_psbt(spend_psbt)
|
signed_tx_hex = minisafed.sign_psbt(spend_psbt)
|
||||||
bitcoind.rpc.sendrawtransaction(signed_tx_hex)
|
bitcoind.rpc.sendrawtransaction(signed_tx_hex)
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_spend(minisafed, bitcoind):
|
||||||
|
# Start by creating a Spend PSBT
|
||||||
|
addr = minisafed.rpc.getnewaddress()["address"]
|
||||||
|
bitcoind.rpc.sendtoaddress(addr, 0.2567)
|
||||||
|
wait_for(lambda: len(minisafed.rpc.listcoins()["coins"]) > 0)
|
||||||
|
outpoints = [c["outpoint"] for c in minisafed.rpc.listcoins()["coins"]]
|
||||||
|
destinations = {
|
||||||
|
bitcoind.rpc.getnewaddress(): 200_000,
|
||||||
|
}
|
||||||
|
res = minisafed.rpc.createspend(outpoints, destinations, 6)
|
||||||
|
assert "psbt" in res
|
||||||
|
|
||||||
|
# Now update it
|
||||||
|
minisafed.rpc.updatespend(res["psbt"])
|
||||||
|
|
||||||
|
# TODO: check it's stored once we implement 'listspendtxs'
|
||||||
|
# TODO: check with added signatures once we implement 'listspendtxs'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user