account_deposit command added which accepts time locked TXs
This commit is contained in:
parent
5777f3e15c
commit
0cbc514a8e
4 changed files with 65 additions and 20 deletions
|
@ -28,6 +28,7 @@ from lbry.wallet import (
|
||||||
from lbry.wallet.dewies import dewies_to_lbc, lbc_to_dewies, dict_values_to_lbc
|
from lbry.wallet.dewies import dewies_to_lbc, lbc_to_dewies, dict_values_to_lbc
|
||||||
from lbry.wallet.constants import TXO_TYPES, CLAIM_TYPE_NAMES
|
from lbry.wallet.constants import TXO_TYPES, CLAIM_TYPE_NAMES
|
||||||
from lbry.wallet.bip32 import PrivateKey
|
from lbry.wallet.bip32 import PrivateKey
|
||||||
|
from lbry.crypto.base58 import Base58
|
||||||
|
|
||||||
from lbry import utils
|
from lbry import utils
|
||||||
from lbry.conf import Config, Setting, NOT_SET
|
from lbry.conf import Config, Setting, NOT_SET
|
||||||
|
@ -1872,6 +1873,48 @@ class Daemon(metaclass=JSONRPCServerType):
|
||||||
outputs=outputs, broadcast=broadcast
|
outputs=outputs, broadcast=broadcast
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@requires("wallet")
|
||||||
|
async def jsonrpc_account_deposit(
|
||||||
|
self, txid, nout, redeem_script, private_key,
|
||||||
|
to_account=None, wallet_id=None, preview=False, blocking=False
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Spend a time locked transaction into your account.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
account_deposit <txid> <nout> <redeem_script> <private_key>
|
||||||
|
[<to_account> | --to_account=<to_account>]
|
||||||
|
[--wallet_id=<wallet_id>] [--preview] [--blocking]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--txid=<txid> : (str) id of the transaction
|
||||||
|
--nout=<nout> : (int) output number in the transaction
|
||||||
|
--redeem_script=<redeem_script> : (str) redeem script for output
|
||||||
|
--private_key=<private_key> : (str) private key to sign transaction
|
||||||
|
--to_account=<to_account> : (str) deposit to this account
|
||||||
|
--wallet_id=<wallet_id> : (str) limit operation to specific wallet.
|
||||||
|
--preview : (bool) do not broadcast the transaction
|
||||||
|
--blocking : (bool) wait until tx has synced
|
||||||
|
|
||||||
|
Returns: {Transaction}
|
||||||
|
"""
|
||||||
|
wallet = self.wallet_manager.get_wallet_or_default(wallet_id)
|
||||||
|
account = wallet.get_account_or_default(to_account)
|
||||||
|
other_tx = await self.wallet_manager.get_transaction(txid)
|
||||||
|
tx = await Transaction.spend_time_lock(
|
||||||
|
other_tx.outputs[nout], unhexlify(redeem_script), account
|
||||||
|
)
|
||||||
|
pk = PrivateKey.from_bytes(
|
||||||
|
account.ledger, Base58.decode_check(private_key)[1:-1]
|
||||||
|
)
|
||||||
|
tx.sign([account], {pk.address: pk})
|
||||||
|
if not preview:
|
||||||
|
await self.broadcast_or_release(tx, blocking)
|
||||||
|
self.component_manager.loop.create_task(self.analytics_manager.send_credits_sent())
|
||||||
|
else:
|
||||||
|
await self.ledger.release_tx(tx)
|
||||||
|
return tx
|
||||||
|
|
||||||
@requires(WALLET_COMPONENT)
|
@requires(WALLET_COMPONENT)
|
||||||
def jsonrpc_account_send(self, amount, addresses, account_id=None, wallet_id=None, preview=False, blocking=False):
|
def jsonrpc_account_send(self, amount, addresses, account_id=None, wallet_id=None, preview=False, blocking=False):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -215,6 +215,10 @@ class PrivateKey(_KeyBase):
|
||||||
private_key = cPrivateKey.from_int(key_int)
|
private_key = cPrivateKey.from_int(key_int)
|
||||||
return cls(ledger, private_key, bytes((0,)*32), 0, 0)
|
return cls(ledger, private_key, bytes((0,)*32), 0, 0)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_bytes(cls, ledger, key_bytes) -> 'PrivateKey':
|
||||||
|
return cls(ledger, cPrivateKey(key_bytes), bytes((0,)*32), 0, 0)
|
||||||
|
|
||||||
@cachedproperty
|
@cachedproperty
|
||||||
def private_key_bytes(self):
|
def private_key_bytes(self):
|
||||||
""" Return the serialized private key (no leading zero byte). """
|
""" Return the serialized private key (no leading zero byte). """
|
||||||
|
|
|
@ -860,7 +860,7 @@ class Transaction:
|
||||||
def signature_hash_type(hash_type):
|
def signature_hash_type(hash_type):
|
||||||
return hash_type
|
return hash_type
|
||||||
|
|
||||||
async def sign(self, funding_accounts: Iterable['Account']):
|
async def sign(self, funding_accounts: Iterable['Account'], extra_keys: dict = None):
|
||||||
self._reset()
|
self._reset()
|
||||||
ledger, wallet = self.ensure_all_have_same_ledger_and_wallet(funding_accounts)
|
ledger, wallet = self.ensure_all_have_same_ledger_and_wallet(funding_accounts)
|
||||||
for i, txi in enumerate(self._inputs):
|
for i, txi in enumerate(self._inputs):
|
||||||
|
@ -870,6 +870,8 @@ class Transaction:
|
||||||
if txo_script.is_pay_pubkey_hash:
|
if txo_script.is_pay_pubkey_hash:
|
||||||
address = ledger.hash160_to_address(txo_script.values['pubkey_hash'])
|
address = ledger.hash160_to_address(txo_script.values['pubkey_hash'])
|
||||||
private_key = await ledger.get_private_key_for_address(wallet, address)
|
private_key = await ledger.get_private_key_for_address(wallet, address)
|
||||||
|
if private_key is None and extra_keys:
|
||||||
|
private_key = extra_keys.get(address)
|
||||||
assert private_key is not None, 'Cannot find private key for signing output.'
|
assert private_key is not None, 'Cannot find private key for signing output.'
|
||||||
tx = self._serialize_for_signature(i)
|
tx = self._serialize_for_signature(i)
|
||||||
txi.script.values['signature'] = \
|
txi.script.values['signature'] = \
|
||||||
|
@ -944,14 +946,9 @@ class Transaction:
|
||||||
return cls.create([], [payment, data], funding_accounts, change_account)
|
return cls.create([], [payment, data], funding_accounts, change_account)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def spend_time_lock(
|
def spend_time_lock(cls, time_locked_txo: Output, script: bytes, account: 'Account'):
|
||||||
cls, time_locked_txo: Output, amount: int, holding_address: str, script_source: str,
|
txi = Input.spend_time_lock(time_locked_txo, script)
|
||||||
funding_accounts: List['Account'], change_account: 'Account'
|
return cls.create([txi], [], [account], account, sign=False)
|
||||||
):
|
|
||||||
ledger, _ = cls.ensure_all_have_same_ledger_and_wallet(funding_accounts, change_account)
|
|
||||||
txi = Input.spend_time_lock(time_locked_txo, unhexlify(script_source))
|
|
||||||
txo = Output.pay_pubkey_hash(amount, ledger.address_to_hash160(holding_address))
|
|
||||||
return cls.create([txi], [txo], funding_accounts, change_account)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def my_inputs(self):
|
def my_inputs(self):
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
from binascii import unhexlify
|
from binascii import unhexlify
|
||||||
|
|
||||||
from lbry.testcase import CommandTestCase
|
from lbry.testcase import CommandTestCase
|
||||||
from lbry.wallet.dewies import dewies_to_lbc, lbc_to_dewies
|
from lbry.wallet.dewies import dewies_to_lbc
|
||||||
from lbry.wallet.account import DeterministicChannelKeyManager
|
from lbry.wallet.account import DeterministicChannelKeyManager
|
||||||
from lbry.wallet.transaction import Transaction, Input, Output
|
from lbry.crypto.base58 import Base58
|
||||||
|
|
||||||
|
|
||||||
def extract(d, keys):
|
def extract(d, keys):
|
||||||
|
@ -291,16 +291,17 @@ class AccountManagement(CommandTestCase):
|
||||||
self.assertTrue(channel3c.has_private_key)
|
self.assertTrue(channel3c.has_private_key)
|
||||||
|
|
||||||
async def test_time_locked_transactions(self):
|
async def test_time_locked_transactions(self):
|
||||||
from lbry.wallet.script import InputScript
|
|
||||||
address = await self.account.receiving.get_or_create_usable_address()
|
address = await self.account.receiving.get_or_create_usable_address()
|
||||||
|
private_key = await self.ledger.get_private_key_for_address(self.wallet, address)
|
||||||
redeem = await self.blockchain.add_time_locked_address(210, address)
|
redeem = await self.blockchain.add_time_locked_address(210, address)
|
||||||
|
await self.assertBalance(self.account, '10.0')
|
||||||
tx = await self.daemon.jsonrpc_account_send('4.0', redeem['address'])
|
tx = await self.daemon.jsonrpc_account_send('4.0', redeem['address'])
|
||||||
await self.confirm_tx(tx.id)
|
await self.confirm_tx(tx.id)
|
||||||
await self.blockchain.generate(10)
|
await self.generate(510)
|
||||||
txi = Input.spend(tx.outputs[0])
|
await self.assertBalance(self.account, '5.999877')
|
||||||
txi.script.source = unhexlify(redeem['redeemScript'])
|
tx = await self.daemon.jsonrpc_account_deposit(
|
||||||
txo = Output.pay_pubkey_hash(lbc_to_dewies('3.9'), self.ledger.address_to_hash160(address))
|
tx.id, 0, redeem['redeemScript'],
|
||||||
new_tx = await Transaction.create([txi], [txo], self.wallet.accounts, self.wallet.default_account)
|
Base58.encode_check(self.ledger.private_key_to_wif(private_key.private_key_bytes))
|
||||||
src = new_tx.raw
|
)
|
||||||
print(new_tx.raw)
|
await self.confirm_tx(tx.id)
|
||||||
|
await self.assertBalance(self.account, '9.999877')
|
||||||
|
|
Loading…
Reference in a new issue