added helper method for timelock, enabled signing of timelock #320

Merged
BrannonKing merged 1 commit from add_timelock_methods into master 2019-09-26 20:29:41 +02:00
3 changed files with 82 additions and 1 deletions

View file

@ -80,6 +80,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "scantxoutset", 1, "scanobjects" },
{ "addmultisigaddress", 0, "nrequired" },
{ "addmultisigaddress", 1, "keys" },
{ "addtimelockedaddress", 0, "timelock" },
{ "createmultisig", 0, "nrequired" },
{ "createmultisig", 1, "keys" },
{ "listunspent", 0, "minconf" },

View file

@ -87,6 +87,21 @@ static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdat
return false;
}
static CScript StripTimelockPrefix(const CScript& script) {
auto it = script.begin();
opcodetype op;
if (!script.GetOp(it, op))
return script;
if (!script.GetOp(it, op) || (op != OP_CHECKLOCKTIMEVERIFY && op != OP_CHECKSEQUENCEVERIFY))
bvbfan commented 2019-09-26 13:55:46 +02:00 (Migrated from github.com)
Review

Can we expect OP_CHECKSEQUENCEVERIFY since BIP112 is not enabled? I mean it should be filtered by interpreter and it shouldn't go here, no?

Can we expect OP_CHECKSEQUENCEVERIFY since BIP112 is not enabled? I mean it should be filtered by interpreter and it shouldn't go here, no?
BrannonKing commented 2019-09-26 19:04:04 +02:00 (Migrated from github.com)
Review

CSV is enabled. getblockchaininfo shows that it is active.

CSV is enabled. getblockchaininfo shows that it is active.
bvbfan commented 2019-09-26 19:35:25 +02:00 (Migrated from github.com)
Review
You're right i made assumption by bit value https://github.com/lbryio/lbrycrd/blob/master/src/chainparams.cpp#L159
return script;
if (!script.GetOp(it, op) || op != OP_DROP)
return script;
return CScript(it, script.end());
}
/**
* Sign scriptPubKey using signature made with creator.
* Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed),
@ -102,7 +117,9 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
std::vector<unsigned char> sig;
std::vector<valtype> vSolutions;
if (!Solver(StripClaimScriptPrefix(scriptPubKey), whichTypeRet, vSolutions))
auto stripped = StripClaimScriptPrefix(scriptPubKey);
stripped = StripTimelockPrefix(stripped);
if (!Solver(stripped, whichTypeRet, vSolutions))
return false;
switch (whichTypeRet)

View file

@ -1914,6 +1914,68 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request)
return result;
}
static UniValue addtimelockedaddress(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) {
std::string msg = "addtimelockedaddress timelock address ( \"label\" \"address_type\" )\n"
"\nAdd an address that can't be redeemed until timelock. Requires a new wallet backup.\n"
"See `importaddress` for watchonly p2sh address support.\n"
"If 'label' is specified, assign address to that label.\n"
"\nArguments:\n"
"1. timelock (numeric, required) Block height if < 500 million or unix timestamp if greater.\n"
"1. \"address\" (string, required) The destination wallet address.\n"
"2. \"label\" (string, optional) A label to assign the addresses to.\n"
"3. \"address_type\" (string, optional) The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\". Default is set by -addresstype.\n"
"\nResult:\n"
"{\n"
" \"address\":\"address\", (string) The value of the new P2SH address.\n"
" \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
"}\n"
;
throw std::runtime_error(msg);
}
auto timelock = request.params[0].get_int();
std::string label;
if (!request.params[2].isNull())
label = LabelFromValue(request.params[2]);
LOCK2(cs_main, pwallet->cs_wallet);
auto address = request.params[1].get_str();
CTxDestination destination = DecodeDestination(address);
if (!IsValidDestination(destination)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid LBRY address: ") + address);
}
auto destinationScript = GetScriptForDestination(destination);
OutputType output_type = pwallet->m_default_address_type;
if (!request.params[3].isNull()) {
if (!ParseOutputType(request.params[3].get_str(), output_type)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[3].get_str()));
}
}
// Construct using pay-to-script-hash:
CScript inner = (CScript() << CScriptNum(timelock) << OP_CHECKLOCKTIMEVERIFY << OP_DROP) + destinationScript;
CTxDestination dest = AddAndGetDestinationForScript(*pwallet, inner, output_type);
pwallet->SetAddressBook(dest, label, "timelock");
UniValue result(UniValue::VOBJ);
result.pushKV("address", EncodeDestination(dest));
result.pushKV("redeemScript", HexStr(inner.begin(), inner.end()));
return result;
}
class Witnessifier : public boost::static_visitor<bool>
{
public:
@ -5305,6 +5367,7 @@ static const CRPCCommand commands[] =
{ "wallet", "abandontransaction", &abandontransaction, {"txid"} },
{ "wallet", "abortrescan", &abortrescan, {} },
{ "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","label|account","address_type"} },
{ "wallet", "addtimelockedaddress", &addtimelockedaddress, {"timelock", "address", "label|account","address_type"} },
{ "hidden", "addwitnessaddress", &addwitnessaddress, {"address","p2sh"} },
{ "wallet", "backupwallet", &backupwallet, {"destination"} },
{ "wallet", "bumpfee", &bumpfee, {"txid", "options"} },