2018-07-12 05:18:59 +02:00
|
|
|
from twisted.internet import defer
|
2018-06-12 17:53:29 +02:00
|
|
|
from torba.basedatabase import BaseDatabase
|
2018-08-01 04:59:51 +02:00
|
|
|
from torba.hash import TXRefImmutable
|
2018-08-03 18:31:50 +02:00
|
|
|
from torba.basetransaction import TXORef
|
2018-07-12 05:18:59 +02:00
|
|
|
from .certificate import Certificate
|
2018-06-12 17:53:29 +02:00
|
|
|
|
|
|
|
|
|
|
|
class WalletDatabase(BaseDatabase):
|
|
|
|
|
2018-07-09 15:55:07 +02:00
|
|
|
CREATE_TXO_TABLE = """
|
|
|
|
create table if not exists txo (
|
2018-07-15 05:02:19 +02:00
|
|
|
txid text references tx,
|
|
|
|
txoid text primary key,
|
|
|
|
address text references pubkey_address,
|
2018-07-09 15:55:07 +02:00
|
|
|
position integer not null,
|
|
|
|
amount integer not null,
|
|
|
|
script blob not null,
|
|
|
|
is_reserved boolean not null default 0,
|
2018-07-12 05:18:59 +02:00
|
|
|
|
2018-07-15 05:02:19 +02:00
|
|
|
claim_id text,
|
2018-07-09 15:55:07 +02:00
|
|
|
claim_name text,
|
|
|
|
is_claim boolean not null default 0,
|
|
|
|
is_update boolean not null default 0,
|
2018-08-14 22:16:29 +02:00
|
|
|
is_support boolean not null default 0,
|
2018-08-23 05:47:37 +02:00
|
|
|
is_buy boolean not null default 0,
|
|
|
|
is_sell boolean not null default 0
|
2018-07-09 15:55:07 +02:00
|
|
|
);
|
|
|
|
"""
|
|
|
|
|
2018-06-12 17:53:29 +02:00
|
|
|
CREATE_TABLES_QUERY = (
|
|
|
|
BaseDatabase.CREATE_TX_TABLE +
|
|
|
|
BaseDatabase.CREATE_PUBKEY_ADDRESS_TABLE +
|
2018-07-09 15:55:07 +02:00
|
|
|
CREATE_TXO_TABLE +
|
2018-06-12 17:53:29 +02:00
|
|
|
BaseDatabase.CREATE_TXI_TABLE
|
|
|
|
)
|
2018-07-09 15:55:07 +02:00
|
|
|
|
|
|
|
def txo_to_row(self, tx, address, txo):
|
2018-07-22 00:34:59 +02:00
|
|
|
row = super().txo_to_row(tx, address, txo)
|
2018-07-09 15:55:07 +02:00
|
|
|
row.update({
|
|
|
|
'is_claim': txo.script.is_claim_name,
|
|
|
|
'is_update': txo.script.is_update_claim,
|
|
|
|
'is_support': txo.script.is_support_claim,
|
2018-08-23 05:47:37 +02:00
|
|
|
'is_buy': txo.script.is_buy_claim,
|
|
|
|
'is_sell': txo.script.is_sell_claim,
|
2018-07-09 15:55:07 +02:00
|
|
|
})
|
|
|
|
if txo.script.is_claim_involved:
|
2018-08-04 18:10:41 +02:00
|
|
|
row['claim_id'] = txo.claim_id
|
|
|
|
row['claim_name'] = txo.claim_name
|
2018-07-09 15:55:07 +02:00
|
|
|
return row
|
2018-07-12 05:18:59 +02:00
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
2018-09-19 04:29:28 +02:00
|
|
|
def get_certificates(self, name=None, channel_id=None, private_key_accounts=None, exclude_without_key=False):
|
2018-09-19 04:23:41 +02:00
|
|
|
if name is not None:
|
|
|
|
filter_sql = 'claim_name=?'
|
|
|
|
filter_value = name
|
2018-09-19 04:29:28 +02:00
|
|
|
elif channel_id is not None:
|
2018-09-19 04:23:41 +02:00
|
|
|
filter_sql = 'claim_id=?'
|
2018-09-19 04:29:28 +02:00
|
|
|
filter_value = channel_id
|
2018-09-19 04:23:41 +02:00
|
|
|
else:
|
|
|
|
raise ValueError("'name' or 'claim_id' is required")
|
|
|
|
|
2018-07-12 05:18:59 +02:00
|
|
|
txos = yield self.db.runQuery(
|
|
|
|
"""
|
2018-07-16 02:54:55 +02:00
|
|
|
SELECT tx.txid, txo.position, txo.claim_id
|
|
|
|
FROM txo JOIN tx ON tx.txid=txo.txid
|
2018-09-19 04:23:41 +02:00
|
|
|
WHERE {} AND (is_claim OR is_update)
|
2018-09-26 04:40:52 +02:00
|
|
|
GROUP BY txo.claim_id ORDER BY tx.height DESC, tx.position ASC;
|
2018-09-19 04:23:41 +02:00
|
|
|
""".format(filter_sql), (filter_value,)
|
2018-07-12 05:18:59 +02:00
|
|
|
)
|
|
|
|
|
2018-07-16 02:54:55 +02:00
|
|
|
certificates = []
|
2018-07-12 05:18:59 +02:00
|
|
|
# Lookup private keys for each certificate.
|
|
|
|
if private_key_accounts is not None:
|
2018-08-03 18:31:50 +02:00
|
|
|
for txid, nout, claim_id in txos:
|
2018-07-12 05:18:59 +02:00
|
|
|
for account in private_key_accounts:
|
|
|
|
private_key = account.get_certificate_private_key(
|
2018-08-03 18:31:50 +02:00
|
|
|
TXORef(TXRefImmutable.from_id(txid), nout)
|
2018-07-12 05:18:59 +02:00
|
|
|
)
|
2018-08-03 18:31:50 +02:00
|
|
|
certificates.append(Certificate(txid, nout, claim_id, name, private_key))
|
2018-07-12 05:18:59 +02:00
|
|
|
|
|
|
|
if exclude_without_key:
|
2018-09-19 04:23:41 +02:00
|
|
|
return [c for c in certificates if c.private_key is not None]
|
2018-07-12 05:18:59 +02:00
|
|
|
|
2018-09-19 04:23:41 +02:00
|
|
|
return certificates
|
2018-08-01 04:59:51 +02:00
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
2018-09-18 23:18:02 +02:00
|
|
|
def get_claim(self, account, claim_id=None, txid=None, nout=None):
|
|
|
|
if claim_id is not None:
|
2018-09-19 18:27:53 +02:00
|
|
|
filter_sql = "claim_id=?"
|
|
|
|
filter_value = (claim_id,)
|
2018-09-18 23:18:02 +02:00
|
|
|
else:
|
2018-09-26 04:40:52 +02:00
|
|
|
filter_sql = "txo.txid=? AND txo.position=?"
|
2018-09-19 18:27:53 +02:00
|
|
|
filter_value = (txid, nout)
|
|
|
|
utxos = yield self.db.runQuery(
|
|
|
|
"""
|
2018-09-26 04:40:52 +02:00
|
|
|
SELECT amount, script, txo.txid, txo.position, account
|
|
|
|
FROM txo
|
|
|
|
JOIN tx ON tx.txid=txo.txid
|
|
|
|
JOIN pubkey_address ON pubkey_address.address=txo.address
|
|
|
|
WHERE {}
|
|
|
|
AND (is_claim OR is_update)
|
|
|
|
AND txoid NOT IN (SELECT txoid FROM txi)
|
|
|
|
ORDER BY tx.height DESC, tx.position ASC LIMIT 1;
|
2018-09-19 18:27:53 +02:00
|
|
|
""".format(filter_sql), filter_value
|
|
|
|
)
|
2018-08-01 04:59:51 +02:00
|
|
|
output_class = account.ledger.transaction_class.output_class
|
2018-09-26 04:40:52 +02:00
|
|
|
account_id = account.public_key.address
|
2018-09-21 15:47:06 +02:00
|
|
|
return [
|
2018-08-01 04:59:51 +02:00
|
|
|
output_class(
|
|
|
|
values[0],
|
|
|
|
output_class.script_class(values[1]),
|
|
|
|
TXRefImmutable.from_id(values[2]),
|
2018-09-26 04:40:52 +02:00
|
|
|
position=values[3],
|
|
|
|
is_change=False,
|
|
|
|
is_my_account=values[4] == account_id
|
2018-08-01 04:59:51 +02:00
|
|
|
) for values in utxos
|
2018-09-21 15:47:06 +02:00
|
|
|
]
|
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
|
|
|
def get_claims(self, account):
|
|
|
|
utxos = yield self.db.runQuery(
|
|
|
|
"""
|
2018-09-26 04:40:52 +02:00
|
|
|
SELECT amount, script, txo.txid, txo.position
|
|
|
|
FROM txo
|
|
|
|
JOIN tx ON tx.txid=txo.txid
|
|
|
|
JOIN pubkey_address ON pubkey_address.address=txo.address
|
|
|
|
WHERE (is_claim OR is_update)
|
|
|
|
AND txoid NOT IN (SELECT txoid FROM txi)
|
|
|
|
AND account = :account
|
|
|
|
ORDER BY tx.height DESC, tx.position ASC;
|
|
|
|
""", {'account': account.public_key.address}
|
2018-09-21 15:47:06 +02:00
|
|
|
)
|
|
|
|
output_class = account.ledger.transaction_class.output_class
|
|
|
|
return [
|
|
|
|
output_class(
|
|
|
|
values[0],
|
|
|
|
output_class.script_class(values[1]),
|
|
|
|
TXRefImmutable.from_id(values[2]),
|
2018-09-26 04:40:52 +02:00
|
|
|
position=values[3],
|
|
|
|
is_change=False,
|
|
|
|
is_my_account=True
|
2018-09-21 15:47:06 +02:00
|
|
|
) for values in utxos
|
|
|
|
]
|