mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-20 15:44:21 +01:00
daemon: have user supply UTXO for enchor input.
This lets us ensure that anchor tx has witness scripts for inputs, and thus is immalleable. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -438,149 +438,6 @@ void bitcoind_send_tx(struct lightningd_state *dstate,
|
|||||||
tal_free(raw);
|
tal_free(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct funding_process {
|
|
||||||
struct peer *peer;
|
|
||||||
void (*cb)(struct lightningd_state *state,
|
|
||||||
const struct bitcoin_tx *tx,
|
|
||||||
int change_output,
|
|
||||||
struct peer *peer);
|
|
||||||
int change_output;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void process_signrawtransaction(struct bitcoin_cli *bcli)
|
|
||||||
{
|
|
||||||
const jsmntok_t *tokens, *hex, *complete;
|
|
||||||
bool valid;
|
|
||||||
struct bitcoin_tx *tx;
|
|
||||||
struct funding_process *f = bcli->cb_arg;
|
|
||||||
|
|
||||||
/* Output:
|
|
||||||
"{\n"
|
|
||||||
" \"hex\" : \"value\", (string) The hex-encoded raw transaction with signature(s)\n"
|
|
||||||
" \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
|
|
||||||
...*/
|
|
||||||
if (!bcli->output)
|
|
||||||
fatal("%s signrawtransaction %s: failed",
|
|
||||||
bcli->args[0], bcli->args[3]);
|
|
||||||
|
|
||||||
tokens = json_parse_input(bcli->output, bcli->output_bytes, &valid);
|
|
||||||
if (!tokens)
|
|
||||||
fatal("%s signrawtransaction %s: %s response (%.*s)?",
|
|
||||||
bcli->args[0], bcli->args[2],
|
|
||||||
valid ? "partial" : "invalid",
|
|
||||||
(int)bcli->output_bytes, bcli->output);
|
|
||||||
if (tokens[0].type != JSMN_OBJECT)
|
|
||||||
fatal("%s signrawtransaction %s: gave non-object (%.*s)?",
|
|
||||||
bcli->args[0], bcli->args[2],
|
|
||||||
(int)bcli->output_bytes, bcli->output);
|
|
||||||
|
|
||||||
complete = json_get_member(bcli->output, tokens, "complete");
|
|
||||||
if (!complete)
|
|
||||||
fatal("%s signrawtransaction %s had no complete member (%.*s)?",
|
|
||||||
bcli->args[0], bcli->args[2],
|
|
||||||
(int)bcli->output_bytes, bcli->output);
|
|
||||||
if (complete->end - complete->start != strlen("true")
|
|
||||||
|| strncmp(bcli->output + complete->start, "true", strlen("true")))
|
|
||||||
fatal("%s signrawtransaction %s not complete (%.*s)?",
|
|
||||||
bcli->args[0], bcli->args[2],
|
|
||||||
complete->end - complete->start,
|
|
||||||
bcli->output + complete->start);
|
|
||||||
|
|
||||||
hex = json_get_member(bcli->output, tokens, "hex");
|
|
||||||
if (!hex)
|
|
||||||
fatal("%s signrawtransaction %s had no hex member (%.*s)?",
|
|
||||||
bcli->args[0], bcli->args[2],
|
|
||||||
(int)bcli->output_bytes, bcli->output);
|
|
||||||
|
|
||||||
tx = bitcoin_tx_from_hex(bcli, bcli->output + hex->start,
|
|
||||||
hex->end - hex->start);
|
|
||||||
if (!tx)
|
|
||||||
fatal("%s signrawtransaction %s had bad hex member (%.*s)?",
|
|
||||||
bcli->args[0], bcli->args[2],
|
|
||||||
hex->end - hex->start, bcli->output + hex->start);
|
|
||||||
|
|
||||||
f->cb(bcli->dstate, tx, f->change_output, f->peer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: handle lack of funds! */
|
|
||||||
static void process_fundrawtransaction(struct bitcoin_cli *bcli)
|
|
||||||
{
|
|
||||||
const jsmntok_t *tokens, *hex, *changepos;
|
|
||||||
char *hexstr, *end;
|
|
||||||
bool valid;
|
|
||||||
struct funding_process *f = bcli->cb_arg;
|
|
||||||
|
|
||||||
/* Output:
|
|
||||||
"{\n"
|
|
||||||
" \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
|
|
||||||
" \"fee\": n, (numeric) Fee the resulting transaction pays\n"
|
|
||||||
" \"changepos\": n (numeric) The position of the added change output, or -1\n"
|
|
||||||
"}\n"
|
|
||||||
*/
|
|
||||||
if (!bcli->output)
|
|
||||||
fatal("%s fundrawtransaction %s: failed",
|
|
||||||
bcli->args[0], bcli->args[3]);
|
|
||||||
|
|
||||||
tokens = json_parse_input(bcli->output, bcli->output_bytes, &valid);
|
|
||||||
if (!tokens)
|
|
||||||
fatal("%s fundrawtransaction %s: %s response (%.*s)?",
|
|
||||||
bcli->args[0], bcli->args[2],
|
|
||||||
valid ? "partial" : "invalid",
|
|
||||||
(int)bcli->output_bytes, bcli->output);
|
|
||||||
if (tokens[0].type != JSMN_OBJECT)
|
|
||||||
fatal("%s fundrawtransaction %s: gave non-object (%.*s)?",
|
|
||||||
bcli->args[0], bcli->args[2],
|
|
||||||
(int)bcli->output_bytes, bcli->output);
|
|
||||||
hex = json_get_member(bcli->output, tokens, "hex");
|
|
||||||
if (!hex)
|
|
||||||
fatal("%s fundrawtransaction %s had no hex member (%.*s)?",
|
|
||||||
bcli->args[0], bcli->args[2],
|
|
||||||
(int)bcli->output_bytes, bcli->output);
|
|
||||||
|
|
||||||
changepos = json_get_member(bcli->output, tokens, "changepos");
|
|
||||||
if (!changepos)
|
|
||||||
fatal("%s fundrawtransaction %s had no changepos member (%.*s)?",
|
|
||||||
bcli->args[0], bcli->args[2],
|
|
||||||
(int)bcli->output_bytes, bcli->output);
|
|
||||||
f->change_output = strtol(bcli->output + changepos->start, &end, 0);
|
|
||||||
if (end != bcli->output + changepos->end)
|
|
||||||
fatal("%s fundrawtransaction %s had bad changepos (%.*s)?",
|
|
||||||
bcli->args[0], bcli->args[2],
|
|
||||||
changepos->end - changepos->start,
|
|
||||||
bcli->output + changepos->start);
|
|
||||||
|
|
||||||
/* We need a nul-terminated string. */
|
|
||||||
hexstr = tal_strndup(bcli, bcli->output + hex->start,
|
|
||||||
hex->end - hex->start);
|
|
||||||
/* Now we need to sign those inputs! */
|
|
||||||
start_bitcoin_cli(bcli->dstate, process_signrawtransaction, NULL,
|
|
||||||
f, "signrawtransaction", hexstr, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adds and signs inputs to this tx from wallet. */
|
|
||||||
void bitcoind_fund_transaction(struct lightningd_state *dstate,
|
|
||||||
struct bitcoin_tx *tx_no_inputs,
|
|
||||||
void (*cb)(struct lightningd_state *dstate,
|
|
||||||
const struct bitcoin_tx *tx,
|
|
||||||
int change_output,
|
|
||||||
struct peer *peer),
|
|
||||||
struct peer *peer)
|
|
||||||
{
|
|
||||||
struct funding_process *f = tal(peer, struct funding_process);
|
|
||||||
u8 *raw = linearize_tx_force_extended(dstate, tx_no_inputs);
|
|
||||||
char *hex = tal_arr(raw, char, hex_str_size(tal_count(raw)));
|
|
||||||
|
|
||||||
assert(tx_no_inputs->input_count == 0);
|
|
||||||
|
|
||||||
hex_encode(raw, tal_count(raw), hex, tal_count(hex));
|
|
||||||
|
|
||||||
f->peer = peer;
|
|
||||||
f->cb = cb;
|
|
||||||
start_bitcoin_cli(dstate, process_fundrawtransaction, NULL, f,
|
|
||||||
"fundrawtransaction", hex, NULL);
|
|
||||||
tal_free(raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void process_getblock(struct bitcoin_cli *bcli)
|
static void process_getblock(struct bitcoin_cli *bcli)
|
||||||
{
|
{
|
||||||
const jsmntok_t *tokens, *mediantime;
|
const jsmntok_t *tokens, *mediantime;
|
||||||
|
|||||||
@@ -53,14 +53,6 @@ void bitcoind_estimate_fee_(struct lightningd_state *dstate,
|
|||||||
void bitcoind_send_tx(struct lightningd_state *dstate,
|
void bitcoind_send_tx(struct lightningd_state *dstate,
|
||||||
const struct bitcoin_tx *tx);
|
const struct bitcoin_tx *tx);
|
||||||
|
|
||||||
void bitcoind_fund_transaction(struct lightningd_state *dstate,
|
|
||||||
struct bitcoin_tx *tx_no_inputs,
|
|
||||||
void (*cb)(struct lightningd_state *dstate,
|
|
||||||
const struct bitcoin_tx *tx,
|
|
||||||
int change_output,
|
|
||||||
struct peer *peer),
|
|
||||||
struct peer *peer);
|
|
||||||
|
|
||||||
void bitcoind_get_mediantime(struct lightningd_state *dstate,
|
void bitcoind_get_mediantime(struct lightningd_state *dstate,
|
||||||
const struct sha256_double *blockid,
|
const struct sha256_double *blockid,
|
||||||
u32 *mediantime);
|
u32 *mediantime);
|
||||||
|
|||||||
105
daemon/peer.c
105
daemon/peer.c
@@ -14,6 +14,7 @@
|
|||||||
#include "secrets.h"
|
#include "secrets.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
#include "timeout.h"
|
#include "timeout.h"
|
||||||
|
#include "wallet.h"
|
||||||
#include <bitcoin/base58.h>
|
#include <bitcoin/base58.h>
|
||||||
#include <bitcoin/script.h>
|
#include <bitcoin/script.h>
|
||||||
#include <bitcoin/tx.h>
|
#include <bitcoin/tx.h>
|
||||||
@@ -39,7 +40,7 @@ struct json_connecting {
|
|||||||
/* This owns us, so we're freed after command_fail or command_success */
|
/* This owns us, so we're freed after command_fail or command_success */
|
||||||
struct command *cmd;
|
struct command *cmd;
|
||||||
const char *name, *port;
|
const char *name, *port;
|
||||||
u64 satoshis;
|
struct anchor_input *input;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pending_cmd {
|
struct pending_cmd {
|
||||||
@@ -450,7 +451,8 @@ static struct io_plan *peer_connected_out(struct io_conn *conn,
|
|||||||
}
|
}
|
||||||
log_info(peer->log, "Connected out to %s:%s",
|
log_info(peer->log, "Connected out to %s:%s",
|
||||||
connect->name, connect->port);
|
connect->name, connect->port);
|
||||||
peer->anchor.satoshis = connect->satoshis;
|
|
||||||
|
peer->anchor.input = tal_steal(peer, connect->input);
|
||||||
|
|
||||||
command_success(connect->cmd, null_response(connect));
|
command_success(connect->cmd, null_response(connect));
|
||||||
return peer_crypto_setup(conn, peer, peer_crypto_on);
|
return peer_crypto_setup(conn, peer, peer_crypto_on);
|
||||||
@@ -565,14 +567,17 @@ static void json_connect(struct command *cmd,
|
|||||||
const char *buffer, const jsmntok_t *params)
|
const char *buffer, const jsmntok_t *params)
|
||||||
{
|
{
|
||||||
struct json_connecting *connect;
|
struct json_connecting *connect;
|
||||||
jsmntok_t *host, *port, *satoshis;
|
jsmntok_t *host, *port, *txtok;
|
||||||
|
struct bitcoin_tx *tx;
|
||||||
|
int output;
|
||||||
|
size_t txhexlen;
|
||||||
|
|
||||||
if (!json_get_params(buffer, params,
|
if (!json_get_params(buffer, params,
|
||||||
"host", &host,
|
"host", &host,
|
||||||
"port", &port,
|
"port", &port,
|
||||||
"satoshis", &satoshis,
|
"tx", &txtok,
|
||||||
NULL)) {
|
NULL)) {
|
||||||
command_fail(cmd, "Need host, port and satoshis");
|
command_fail(cmd, "Need host, port and tx to a wallet address");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,10 +587,35 @@ static void json_connect(struct command *cmd,
|
|||||||
host->end - host->start);
|
host->end - host->start);
|
||||||
connect->port = tal_strndup(connect, buffer + port->start,
|
connect->port = tal_strndup(connect, buffer + port->start,
|
||||||
port->end - port->start);
|
port->end - port->start);
|
||||||
if (!json_tok_u64(buffer, satoshis, &connect->satoshis))
|
connect->input = tal(connect, struct anchor_input);
|
||||||
command_fail(cmd, "'%.*s' is not a valid number",
|
|
||||||
(int)(satoshis->end - satoshis->start),
|
txhexlen = txtok->end - txtok->start;
|
||||||
buffer + satoshis->start);
|
tx = bitcoin_tx_from_hex(connect->input, buffer + txtok->start,
|
||||||
|
txhexlen);
|
||||||
|
if (!tx) {
|
||||||
|
command_fail(cmd, "'%.*s' is not a valid transaction",
|
||||||
|
txtok->end - txtok->start,
|
||||||
|
buffer + txtok->start);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitcoin_txid(tx, &connect->input->txid);
|
||||||
|
|
||||||
|
/* Find an output we know how to spend. */
|
||||||
|
connect->input->w = NULL;
|
||||||
|
for (output = 0; output < tx->output_count; output++) {
|
||||||
|
connect->input->w
|
||||||
|
= wallet_can_spend(cmd->dstate, &tx->output[output]);
|
||||||
|
if (connect->input->w)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!connect->input->w) {
|
||||||
|
command_fail(cmd, "Tx doesn't send to wallet address");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect->input->index = output;
|
||||||
|
connect->input->amount = tx->output[output].amount;
|
||||||
if (!dns_resolve_and_connect(cmd->dstate, connect->name, connect->port,
|
if (!dns_resolve_and_connect(cmd->dstate, connect->name, connect->port,
|
||||||
peer_connected_out, peer_failed, connect)) {
|
peer_connected_out, peer_failed, connect)) {
|
||||||
command_fail(cmd, "DNS failed");
|
command_fail(cmd, "DNS failed");
|
||||||
@@ -1219,45 +1249,52 @@ const struct bitcoin_tx *bitcoin_htlc_spend(const struct peer *peer,
|
|||||||
FIXME_STUB(peer);
|
FIXME_STUB(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void created_anchor(struct lightningd_state *dstate,
|
/* Now we can create anchor tx. */
|
||||||
const struct bitcoin_tx *tx,
|
static void got_feerate(struct lightningd_state *dstate,
|
||||||
int change_output,
|
u64 rate, struct peer *peer)
|
||||||
struct peer *peer)
|
|
||||||
{
|
{
|
||||||
size_t real_out;
|
u64 fee;
|
||||||
|
struct bitcoin_tx *tx = bitcoin_tx(peer, 1, 1);
|
||||||
|
|
||||||
|
tx->output[0].script = scriptpubkey_p2sh(tx, peer->anchor.redeemscript);
|
||||||
|
tx->output[0].script_length = tal_count(tx->output[0].script);
|
||||||
|
|
||||||
|
/* Add input script length. FIXME: This is normal case, not exact. */
|
||||||
|
fee = fee_by_feerate(measure_tx_len(tx) + 1+73 + 1+33 + 1, rate);
|
||||||
|
if (fee >= peer->anchor.input->amount)
|
||||||
|
/* FIXME: Report an error here!
|
||||||
|
* We really should set this when they do command, but
|
||||||
|
* we need to modify state to allow immediate anchor
|
||||||
|
* creation: using estimate_fee is a convenient workaround. */
|
||||||
|
fatal("Amount %"PRIu64" below fee %"PRIu64,
|
||||||
|
peer->anchor.input->amount, fee);
|
||||||
|
|
||||||
|
tx->output[0].amount = peer->anchor.input->amount - fee;
|
||||||
|
|
||||||
|
tx->input[0].txid = peer->anchor.input->txid;
|
||||||
|
tx->input[0].index = peer->anchor.input->index;
|
||||||
|
tx->input[0].amount = tal_dup(tx->input, u64,
|
||||||
|
&peer->anchor.input->amount);
|
||||||
|
|
||||||
|
wallet_add_signed_input(peer->dstate, peer->anchor.input->w, tx, 0);
|
||||||
|
|
||||||
bitcoin_txid(tx, &peer->anchor.txid);
|
bitcoin_txid(tx, &peer->anchor.txid);
|
||||||
if (change_output == -1)
|
peer->anchor.tx = tx;
|
||||||
real_out = 0;
|
peer->anchor.index = 0;
|
||||||
else
|
|
||||||
real_out = !change_output;
|
|
||||||
|
|
||||||
assert(find_p2sh_out(tx, peer->anchor.redeemscript) == real_out);
|
|
||||||
peer->anchor.index = real_out;
|
|
||||||
assert(peer->anchor.satoshis == tx->output[peer->anchor.index].amount);
|
|
||||||
/* We'll need this later, when we're told to broadcast it. */
|
/* We'll need this later, when we're told to broadcast it. */
|
||||||
peer->anchor.tx = tal_steal(peer, tx);
|
peer->anchor.satoshis = tx->output[0].amount;
|
||||||
|
|
||||||
state_event(peer, BITCOIN_ANCHOR_CREATED, NULL);
|
state_event(peer, BITCOIN_ANCHOR_CREATED, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start creation of the bitcoin anchor tx. */
|
/* Creation the bitcoin anchor tx, spending output user provided. */
|
||||||
void bitcoin_create_anchor(struct peer *peer, enum state_input done)
|
void bitcoin_create_anchor(struct peer *peer, enum state_input done)
|
||||||
{
|
{
|
||||||
struct bitcoin_tx *template = bitcoin_tx(peer, 0, 1);
|
|
||||||
|
|
||||||
/* We must be offering anchor for us to try creating it */
|
/* We must be offering anchor for us to try creating it */
|
||||||
assert(peer->us.offer_anchor);
|
assert(peer->us.offer_anchor);
|
||||||
|
|
||||||
template->output[0].amount = peer->anchor.satoshis;
|
|
||||||
template->output[0].script
|
|
||||||
= scriptpubkey_p2sh(template, peer->anchor.redeemscript);
|
|
||||||
template->output[0].script_length
|
|
||||||
= tal_count(template->output[0].script);
|
|
||||||
|
|
||||||
assert(done == BITCOIN_ANCHOR_CREATED);
|
assert(done == BITCOIN_ANCHOR_CREATED);
|
||||||
|
bitcoind_estimate_fee(peer->dstate, got_feerate, peer);
|
||||||
bitcoind_fund_transaction(peer->dstate, template, created_anchor, peer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We didn't end up broadcasting the anchor: release the utxos.
|
/* We didn't end up broadcasting the anchor: release the utxos.
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define LIGHTNING_DAEMON_PEER_H
|
#define LIGHTNING_DAEMON_PEER_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "bitcoin/locktime.h"
|
#include "bitcoin/locktime.h"
|
||||||
|
#include "bitcoin/privkey.h"
|
||||||
#include "bitcoin/pubkey.h"
|
#include "bitcoin/pubkey.h"
|
||||||
#include "bitcoin/script.h"
|
#include "bitcoin/script.h"
|
||||||
#include "bitcoin/shadouble.h"
|
#include "bitcoin/shadouble.h"
|
||||||
@@ -42,6 +43,15 @@ union htlc_staging {
|
|||||||
struct htlc_fail fail;
|
struct htlc_fail fail;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct anchor_input {
|
||||||
|
struct sha256_double txid;
|
||||||
|
unsigned int index;
|
||||||
|
/* Amount of input (satoshis) */
|
||||||
|
u64 amount;
|
||||||
|
/* Wallet entry to use to spend. */
|
||||||
|
struct wallet *w;
|
||||||
|
};
|
||||||
|
|
||||||
struct commit_info {
|
struct commit_info {
|
||||||
/* Previous one, if any. */
|
/* Previous one, if any. */
|
||||||
struct commit_info *prev;
|
struct commit_info *prev;
|
||||||
@@ -131,6 +141,10 @@ struct peer {
|
|||||||
unsigned int index;
|
unsigned int index;
|
||||||
u64 satoshis;
|
u64 satoshis;
|
||||||
u8 *redeemscript;
|
u8 *redeemscript;
|
||||||
|
|
||||||
|
/* If we're creating anchor, this tells us where to source it */
|
||||||
|
struct anchor_input *input;
|
||||||
|
|
||||||
/* If we created it, we keep entire tx. */
|
/* If we created it, we keep entire tx. */
|
||||||
const struct bitcoin_tx *tx;
|
const struct bitcoin_tx *tx;
|
||||||
struct anchor_watch *watches;
|
struct anchor_watch *watches;
|
||||||
|
|||||||
@@ -16,8 +16,9 @@ REDIRERR1="$DIR1/errors"
|
|||||||
REDIRERR2="$DIR2/errors"
|
REDIRERR2="$DIR2/errors"
|
||||||
FGREP="fgrep -q"
|
FGREP="fgrep -q"
|
||||||
|
|
||||||
# setup.sh gives us 0.00999999 bitcoin, = 999999 satoshi = 999999000 millisatoshi
|
# We inject 0.01 bitcoin, but then fees (estimatefee fails and we use a
|
||||||
AMOUNT=999999000
|
# fee rate as per the close tx).
|
||||||
|
AMOUNT=996160000
|
||||||
|
|
||||||
# Default fee rate per kb.
|
# Default fee rate per kb.
|
||||||
FEE_RATE=200000
|
FEE_RATE=200000
|
||||||
@@ -129,7 +130,7 @@ check_staged()
|
|||||||
check_tx_spend()
|
check_tx_spend()
|
||||||
{
|
{
|
||||||
$CLI generate 1
|
$CLI generate 1
|
||||||
if [ $($CLI getblock $($CLI getbestblockhash) | grep -c '^ "') = 2 ]; then
|
if [ $($CLI getblock $($CLI getbestblockhash) | grep -c '^ "') -gt 1 ]; then
|
||||||
:
|
:
|
||||||
else
|
else
|
||||||
echo "Block didn't include tx:" >&2
|
echo "Block didn't include tx:" >&2
|
||||||
@@ -189,7 +190,12 @@ ID2=`$LCLI2 getlog | sed -n 's/.*"ID: \([0-9a-f]*\)".*/\1/p'`
|
|||||||
|
|
||||||
PORT2=`$LCLI2 getlog | sed -n 's/.*on port \([0-9]*\).*/\1/p'`
|
PORT2=`$LCLI2 getlog | sed -n 's/.*on port \([0-9]*\).*/\1/p'`
|
||||||
|
|
||||||
lcli1 connect localhost $PORT2 999999
|
# Make a payment into a P2SH for anchor.
|
||||||
|
P2SHADDR=`$LCLI1 newaddr | sed -n 's/{ "address" : "\(.*\)" }/\1/p'`
|
||||||
|
TXID=`$CLI sendtoaddress $P2SHADDR 0.01`
|
||||||
|
TX=`$CLI getrawtransaction $TXID`
|
||||||
|
|
||||||
|
lcli1 connect localhost $PORT2 $TX
|
||||||
sleep 2
|
sleep 2
|
||||||
|
|
||||||
# Expect them to be waiting for anchor.
|
# Expect them to be waiting for anchor.
|
||||||
|
|||||||
Reference in New Issue
Block a user