database: allow for coinbase transactions to change addresses
`is_change` is `true` for a coin if its address is derived from our change descriptor and could in principle be used for a coinbase transaction. The functional test was provided by darosior in a PR comment: https://github.com/wizardsardine/liana/pull/1001#pullrequestreview-1948564150
This commit is contained in:
parent
cde2adbdce
commit
3a7c151674
@ -1457,7 +1457,7 @@ CREATE TABLE spend_transactions (
|
||||
block_info: None,
|
||||
amount: bitcoin::Amount::from_sat(424242),
|
||||
derivation_index: bip32::ChildNumber::from_normal_idx(4103).unwrap(),
|
||||
is_change: false, // Cannot be both a coinbase deposit and change.
|
||||
is_change: false,
|
||||
spend_txid: None,
|
||||
spend_block: None,
|
||||
};
|
||||
|
||||
@ -39,8 +39,8 @@ CREATE TABLE wallets (
|
||||
* transaction for this coin exists and was confirmed.
|
||||
*
|
||||
* The 'is_immature' field is for coinbase deposits that are not yet buried under 100
|
||||
* blocks. Note coinbase deposits can't be change. They also technically can't be
|
||||
* unconfirmed but we keep them as such until they become mature.
|
||||
* blocks. Note coinbase deposits can't technically be unconfirmed but we keep them
|
||||
* as such until they become mature.
|
||||
*/
|
||||
CREATE TABLE coins (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
@ -56,7 +56,6 @@ CREATE TABLE coins (
|
||||
spend_block_height INTEGER,
|
||||
spend_block_time INTEGER,
|
||||
is_immature BOOLEAN NOT NULL CHECK (is_immature IN (0,1)),
|
||||
CHECK (is_change IS 0 OR is_immature IS 0),
|
||||
UNIQUE (txid, vout),
|
||||
FOREIGN KEY (wallet_id) REFERENCES wallets (id)
|
||||
ON UPDATE RESTRICT
|
||||
@ -217,10 +216,6 @@ impl TryFrom<&rusqlite::Row<'_>> for DbCoin {
|
||||
});
|
||||
|
||||
let is_immature: bool = row.get(12)?;
|
||||
assert!(
|
||||
!is_immature || !is_change,
|
||||
"A coin cannot be both created in a coinbase and be change"
|
||||
);
|
||||
|
||||
Ok(DbCoin {
|
||||
id,
|
||||
|
||||
@ -239,6 +239,20 @@ def test_coinbase_deposit(lianad, bitcoind):
|
||||
and coin["spend_info"] is not None
|
||||
)
|
||||
|
||||
# We must also properly detect coinbase deposits to a change address. We used to have
|
||||
# an assertion that a coin cannot both be change and a coinbase deposit. Since change
|
||||
# is determined by the address... Technically we can.
|
||||
change_desc = lianad.multi_desc.singlepath_descriptors()[1]
|
||||
change_addr = bitcoind.rpc.deriveaddresses(str(change_desc), [0, 0])[0]
|
||||
bitcoind.rpc.generatetoaddress(1, change_addr)
|
||||
wait_for(lambda: any(c["is_immature"] for c in lianad.rpc.listcoins()["coins"]))
|
||||
coin = next(c for c in lianad.rpc.listcoins()["coins"] if c["is_immature"])
|
||||
assert coin["is_change"]
|
||||
bitcoind.generate_block(100)
|
||||
wait_for_sync()
|
||||
coin = next(c for c in lianad.rpc.listcoins()["coins"] if c["outpoint"] == coin["outpoint"])
|
||||
assert not coin["is_immature"] and coin["block_height"] is not None
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
OLD_LIANAD_PATH is None or USE_TAPROOT, reason="Need the old lianad binary to create the datadir."
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user