2021-02-19 19:19:58 +01:00
|
|
|
import typing
|
|
|
|
import struct
|
2021-07-14 18:53:56 +02:00
|
|
|
import array
|
|
|
|
import base64
|
2021-08-14 02:02:42 +02:00
|
|
|
from typing import Union, Tuple, NamedTuple, Optional
|
2021-02-19 19:19:58 +01:00
|
|
|
from lbry.wallet.server.db import DB_PREFIXES
|
2022-01-31 21:48:04 +01:00
|
|
|
from lbry.wallet.server.db.interface import BasePrefixDB
|
2021-12-01 22:47:29 +01:00
|
|
|
from lbry.wallet.server.db.common import TrendingNotification
|
2021-08-14 02:02:42 +02:00
|
|
|
from lbry.wallet.server.db.revertable import RevertableOpStack, RevertablePut, RevertableDelete
|
2021-08-12 22:08:52 +02:00
|
|
|
from lbry.schema.url import normalize_name
|
2022-01-15 19:45:41 +01:00
|
|
|
if typing.TYPE_CHECKING:
|
|
|
|
import rocksdb
|
2021-02-19 19:19:58 +01:00
|
|
|
|
2021-05-20 19:31:40 +02:00
|
|
|
ACTIVATED_CLAIM_TXO_TYPE = 1
|
|
|
|
ACTIVATED_SUPPORT_TXO_TYPE = 2
|
|
|
|
|
|
|
|
|
2021-02-19 19:19:58 +01:00
|
|
|
def length_encoded_name(name: str) -> bytes:
|
|
|
|
encoded = name.encode('utf-8')
|
|
|
|
return len(encoded).to_bytes(2, byteorder='big') + encoded
|
|
|
|
|
|
|
|
|
2021-07-18 04:22:14 +02:00
|
|
|
def length_prefix(key: str) -> bytes:
|
|
|
|
return len(key).to_bytes(1, byteorder='big') + key.encode()
|
|
|
|
|
|
|
|
|
2021-08-14 02:02:42 +02:00
|
|
|
ROW_TYPES = {}
|
2021-08-12 22:08:52 +02:00
|
|
|
|
|
|
|
|
|
|
|
class PrefixRowType(type):
|
|
|
|
def __new__(cls, name, bases, kwargs):
|
|
|
|
klass = super().__new__(cls, name, bases, kwargs)
|
|
|
|
if name != "PrefixRow":
|
2021-08-14 02:02:42 +02:00
|
|
|
ROW_TYPES[klass.prefix] = klass
|
2021-08-12 22:08:52 +02:00
|
|
|
return klass
|
|
|
|
|
|
|
|
|
|
|
|
class PrefixRow(metaclass=PrefixRowType):
|
2021-02-19 19:19:58 +01:00
|
|
|
prefix: bytes
|
|
|
|
key_struct: struct.Struct
|
|
|
|
value_struct: struct.Struct
|
2021-05-20 19:31:40 +02:00
|
|
|
key_part_lambdas = []
|
|
|
|
|
2022-01-15 19:45:41 +01:00
|
|
|
def __init__(self, db: 'rocksdb.DB', op_stack: RevertableOpStack):
|
2021-08-14 02:02:42 +02:00
|
|
|
self._db = db
|
|
|
|
self._op_stack = op_stack
|
2022-01-15 19:45:41 +01:00
|
|
|
self._column_family = self._db.get_column_family(self.prefix)
|
|
|
|
if not self._column_family.is_valid:
|
|
|
|
raise RuntimeError('column family is not valid')
|
2021-08-14 02:02:42 +02:00
|
|
|
|
2022-01-15 19:45:41 +01:00
|
|
|
def iterate(self, prefix=None, start=None, stop=None, reverse: bool = False, include_key: bool = True,
|
|
|
|
include_value: bool = True, fill_cache: bool = True, deserialize_key: bool = True,
|
|
|
|
deserialize_value: bool = True):
|
2021-09-21 18:22:26 +02:00
|
|
|
if not prefix and not start and not stop:
|
|
|
|
prefix = ()
|
2021-08-14 02:02:42 +02:00
|
|
|
if prefix is not None:
|
|
|
|
prefix = self.pack_partial_key(*prefix)
|
2022-01-15 19:45:41 +01:00
|
|
|
if stop is None:
|
|
|
|
try:
|
|
|
|
stop = (int.from_bytes(prefix, byteorder='big') + 1).to_bytes(len(prefix), byteorder='big')
|
|
|
|
except OverflowError:
|
|
|
|
stop = (int.from_bytes(prefix, byteorder='big') + 1).to_bytes(len(prefix) + 1, byteorder='big')
|
|
|
|
else:
|
|
|
|
stop = self.pack_partial_key(*stop)
|
|
|
|
else:
|
|
|
|
if start is not None:
|
|
|
|
start = self.pack_partial_key(*start)
|
|
|
|
if stop is not None:
|
|
|
|
stop = self.pack_partial_key(*stop)
|
2021-08-14 02:02:42 +02:00
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
if deserialize_key:
|
|
|
|
key_getter = lambda k: self.unpack_key(k)
|
|
|
|
else:
|
|
|
|
key_getter = lambda k: k
|
|
|
|
if deserialize_value:
|
|
|
|
value_getter = lambda v: self.unpack_value(v)
|
|
|
|
else:
|
|
|
|
value_getter = lambda v: v
|
|
|
|
|
2022-01-15 19:45:41 +01:00
|
|
|
it = self._db.iterator(
|
2022-01-26 17:18:50 +01:00
|
|
|
start or prefix, self._column_family, iterate_lower_bound=(start or prefix),
|
2022-01-15 19:45:41 +01:00
|
|
|
iterate_upper_bound=stop, reverse=reverse, include_key=include_key,
|
2022-01-25 05:17:07 +01:00
|
|
|
include_value=include_value, fill_cache=fill_cache, prefix_same_as_start=False
|
2022-01-15 19:45:41 +01:00
|
|
|
)
|
|
|
|
|
2021-08-14 02:02:42 +02:00
|
|
|
if include_key and include_value:
|
2022-01-15 19:45:41 +01:00
|
|
|
for k, v in it:
|
|
|
|
yield key_getter(k[1]), value_getter(v)
|
2021-08-14 02:02:42 +02:00
|
|
|
elif include_key:
|
2022-01-15 19:45:41 +01:00
|
|
|
for k in it:
|
|
|
|
yield key_getter(k[1])
|
2021-08-14 02:02:42 +02:00
|
|
|
elif include_value:
|
2022-01-15 19:45:41 +01:00
|
|
|
for v in it:
|
2021-10-04 22:38:28 +02:00
|
|
|
yield value_getter(v)
|
2021-08-14 02:02:42 +02:00
|
|
|
else:
|
2022-01-15 19:45:41 +01:00
|
|
|
for _ in it:
|
2021-10-04 22:38:28 +02:00
|
|
|
yield None
|
2021-08-14 02:02:42 +02:00
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
def get(self, *key_args, fill_cache=True, deserialize_value=True):
|
2022-01-15 19:45:41 +01:00
|
|
|
v = self._db.get((self._column_family, self.pack_key(*key_args)), fill_cache=fill_cache)
|
2021-08-14 02:02:42 +02:00
|
|
|
if v:
|
2021-10-04 22:38:28 +02:00
|
|
|
return v if not deserialize_value else self.unpack_value(v)
|
2021-08-14 02:02:42 +02:00
|
|
|
|
2021-10-19 19:29:13 +02:00
|
|
|
def get_pending(self, *key_args, fill_cache=True, deserialize_value=True):
|
|
|
|
packed_key = self.pack_key(*key_args)
|
|
|
|
last_op = self._op_stack.get_last_op_for_key(packed_key)
|
|
|
|
if last_op:
|
|
|
|
if last_op.is_put:
|
|
|
|
return last_op.value if not deserialize_value else self.unpack_value(last_op.value)
|
|
|
|
else: # it's a delete
|
|
|
|
return
|
2022-01-15 19:45:41 +01:00
|
|
|
v = self._db.get((self._column_family, packed_key), fill_cache=fill_cache)
|
2021-10-19 19:29:13 +02:00
|
|
|
if v:
|
|
|
|
return v if not deserialize_value else self.unpack_value(v)
|
|
|
|
|
2021-08-14 02:02:42 +02:00
|
|
|
def stage_put(self, key_args=(), value_args=()):
|
|
|
|
self._op_stack.append_op(RevertablePut(self.pack_key(*key_args), self.pack_value(*value_args)))
|
|
|
|
|
|
|
|
def stage_delete(self, key_args=(), value_args=()):
|
|
|
|
self._op_stack.append_op(RevertableDelete(self.pack_key(*key_args), self.pack_value(*value_args)))
|
|
|
|
|
2021-05-20 19:31:40 +02:00
|
|
|
@classmethod
|
|
|
|
def pack_partial_key(cls, *args) -> bytes:
|
|
|
|
return cls.prefix + cls.key_part_lambdas[len(args)](*args)
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, *args) -> bytes:
|
|
|
|
return cls.prefix + cls.key_struct.pack(*args)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, *args) -> bytes:
|
|
|
|
return cls.value_struct.pack(*args)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes):
|
2022-01-15 19:45:41 +01:00
|
|
|
assert key[:1] == cls.prefix, f"prefix should be {cls.prefix}, got {key[:1]}"
|
2021-02-19 19:19:58 +01:00
|
|
|
return cls.key_struct.unpack(key[1:])
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes):
|
|
|
|
return cls.value_struct.unpack(data)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_item(cls, key: bytes, value: bytes):
|
|
|
|
return cls.unpack_key(key), cls.unpack_value(value)
|
|
|
|
|
|
|
|
|
2021-07-14 18:53:56 +02:00
|
|
|
class UTXOKey(NamedTuple):
|
|
|
|
hashX: bytes
|
|
|
|
tx_num: int
|
|
|
|
nout: int
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(hashX={self.hashX.hex()}, tx_num={self.tx_num}, nout={self.nout})"
|
|
|
|
|
|
|
|
|
|
|
|
class UTXOValue(NamedTuple):
|
|
|
|
amount: int
|
|
|
|
|
|
|
|
|
|
|
|
class HashXUTXOKey(NamedTuple):
|
|
|
|
short_tx_hash: bytes
|
|
|
|
tx_num: int
|
|
|
|
nout: int
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(short_tx_hash={self.short_tx_hash.hex()}, tx_num={self.tx_num}, nout={self.nout})"
|
|
|
|
|
|
|
|
|
|
|
|
class HashXUTXOValue(NamedTuple):
|
|
|
|
hashX: bytes
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(hashX={self.hashX.hex()})"
|
|
|
|
|
|
|
|
|
|
|
|
class HashXHistoryKey(NamedTuple):
|
|
|
|
hashX: bytes
|
|
|
|
height: int
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(hashX={self.hashX.hex()}, height={self.height})"
|
|
|
|
|
|
|
|
|
|
|
|
class HashXHistoryValue(NamedTuple):
|
|
|
|
hashXes: typing.List[int]
|
|
|
|
|
|
|
|
|
|
|
|
class BlockHashKey(NamedTuple):
|
|
|
|
height: int
|
|
|
|
|
|
|
|
|
|
|
|
class BlockHashValue(NamedTuple):
|
|
|
|
block_hash: bytes
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(block_hash={self.block_hash.hex()})"
|
|
|
|
|
|
|
|
|
2021-10-12 06:03:11 +02:00
|
|
|
class BlockTxsKey(NamedTuple):
|
|
|
|
height: int
|
|
|
|
|
|
|
|
|
|
|
|
class BlockTxsValue(NamedTuple):
|
|
|
|
tx_hashes: typing.List[bytes]
|
|
|
|
|
|
|
|
|
2021-07-14 18:53:56 +02:00
|
|
|
class TxCountKey(NamedTuple):
|
|
|
|
height: int
|
|
|
|
|
|
|
|
|
|
|
|
class TxCountValue(NamedTuple):
|
|
|
|
tx_count: int
|
|
|
|
|
|
|
|
|
|
|
|
class TxHashKey(NamedTuple):
|
|
|
|
tx_num: int
|
|
|
|
|
|
|
|
|
|
|
|
class TxHashValue(NamedTuple):
|
|
|
|
tx_hash: bytes
|
|
|
|
|
|
|
|
def __str__(self):
|
2022-01-06 18:28:15 +01:00
|
|
|
return f"{self.__class__.__name__}(tx_hash={self.tx_hash[::-1].hex()})"
|
2021-07-14 18:53:56 +02:00
|
|
|
|
|
|
|
|
|
|
|
class TxNumKey(NamedTuple):
|
|
|
|
tx_hash: bytes
|
|
|
|
|
|
|
|
def __str__(self):
|
2022-01-06 18:28:15 +01:00
|
|
|
return f"{self.__class__.__name__}(tx_hash={self.tx_hash[::-1].hex()})"
|
2021-07-14 18:53:56 +02:00
|
|
|
|
|
|
|
|
|
|
|
class TxNumValue(NamedTuple):
|
|
|
|
tx_num: int
|
|
|
|
|
|
|
|
|
|
|
|
class TxKey(NamedTuple):
|
|
|
|
tx_hash: bytes
|
|
|
|
|
|
|
|
def __str__(self):
|
2022-01-06 18:28:15 +01:00
|
|
|
return f"{self.__class__.__name__}(tx_hash={self.tx_hash[::-1].hex()})"
|
2021-07-14 18:53:56 +02:00
|
|
|
|
|
|
|
|
|
|
|
class TxValue(NamedTuple):
|
|
|
|
raw_tx: bytes
|
|
|
|
|
|
|
|
def __str__(self):
|
2021-12-01 22:47:29 +01:00
|
|
|
return f"{self.__class__.__name__}(raw_tx={base64.b64encode(self.raw_tx).decode()})"
|
2021-07-14 18:53:56 +02:00
|
|
|
|
|
|
|
|
|
|
|
class BlockHeaderKey(NamedTuple):
|
|
|
|
height: int
|
|
|
|
|
|
|
|
|
|
|
|
class BlockHeaderValue(NamedTuple):
|
|
|
|
header: bytes
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(header={base64.b64encode(self.header)})"
|
|
|
|
|
|
|
|
|
2021-02-19 19:19:58 +01:00
|
|
|
class ClaimToTXOKey(typing.NamedTuple):
|
|
|
|
claim_hash: bytes
|
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(claim_hash={self.claim_hash.hex()})"
|
|
|
|
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
class ClaimToTXOValue(typing.NamedTuple):
|
2021-06-09 22:29:16 +02:00
|
|
|
tx_num: int
|
|
|
|
position: int
|
2021-02-19 19:19:58 +01:00
|
|
|
root_tx_num: int
|
|
|
|
root_position: int
|
|
|
|
amount: int
|
2021-05-20 19:31:40 +02:00
|
|
|
# activation: int
|
2021-06-04 22:50:37 +02:00
|
|
|
channel_signature_is_valid: bool
|
2021-02-19 19:19:58 +01:00
|
|
|
name: str
|
|
|
|
|
2021-08-12 22:08:52 +02:00
|
|
|
@property
|
|
|
|
def normalized_name(self) -> str:
|
|
|
|
try:
|
|
|
|
return normalize_name(self.name)
|
|
|
|
except UnicodeDecodeError:
|
|
|
|
return self.name
|
|
|
|
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
class TXOToClaimKey(typing.NamedTuple):
|
|
|
|
tx_num: int
|
|
|
|
position: int
|
|
|
|
|
|
|
|
|
|
|
|
class TXOToClaimValue(typing.NamedTuple):
|
|
|
|
claim_hash: bytes
|
|
|
|
name: str
|
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(claim_hash={self.claim_hash.hex()}, name={self.name})"
|
|
|
|
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
class ClaimShortIDKey(typing.NamedTuple):
|
2021-08-12 22:08:52 +02:00
|
|
|
normalized_name: str
|
2021-07-18 04:22:14 +02:00
|
|
|
partial_claim_id: str
|
2021-02-19 19:19:58 +01:00
|
|
|
root_tx_num: int
|
|
|
|
root_position: int
|
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
2021-08-12 22:08:52 +02:00
|
|
|
return f"{self.__class__.__name__}(normalized_name={self.normalized_name}, " \
|
|
|
|
f"partial_claim_id={self.partial_claim_id}, " \
|
2021-07-01 02:07:19 +02:00
|
|
|
f"root_tx_num={self.root_tx_num}, root_position={self.root_position})"
|
|
|
|
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
class ClaimShortIDValue(typing.NamedTuple):
|
|
|
|
tx_num: int
|
|
|
|
position: int
|
|
|
|
|
|
|
|
|
|
|
|
class ClaimToChannelKey(typing.NamedTuple):
|
|
|
|
claim_hash: bytes
|
2021-06-22 23:25:23 +02:00
|
|
|
tx_num: int
|
|
|
|
position: int
|
2021-02-19 19:19:58 +01:00
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(claim_hash={self.claim_hash.hex()}, " \
|
|
|
|
f"tx_num={self.tx_num}, position={self.position})"
|
|
|
|
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
class ClaimToChannelValue(typing.NamedTuple):
|
|
|
|
signing_hash: bytes
|
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(signing_hash={self.signing_hash.hex()})"
|
|
|
|
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
class ChannelToClaimKey(typing.NamedTuple):
|
|
|
|
signing_hash: bytes
|
|
|
|
name: str
|
|
|
|
tx_num: int
|
|
|
|
position: int
|
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(signing_hash={self.signing_hash.hex()}, name={self.name}, " \
|
|
|
|
f"tx_num={self.tx_num}, position={self.position})"
|
|
|
|
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
class ChannelToClaimValue(typing.NamedTuple):
|
|
|
|
claim_hash: bytes
|
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(claim_hash={self.claim_hash.hex()})"
|
|
|
|
|
2021-02-19 19:19:58 +01:00
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
class ChannelCountKey(typing.NamedTuple):
|
|
|
|
channel_hash: bytes
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(channel_hash={self.channel_hash.hex()})"
|
|
|
|
|
|
|
|
|
|
|
|
class ChannelCountValue(typing.NamedTuple):
|
|
|
|
count: int
|
|
|
|
|
|
|
|
|
|
|
|
class SupportAmountKey(typing.NamedTuple):
|
|
|
|
claim_hash: bytes
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(claim_hash={self.claim_hash.hex()})"
|
|
|
|
|
|
|
|
|
|
|
|
class SupportAmountValue(typing.NamedTuple):
|
|
|
|
amount: int
|
|
|
|
|
|
|
|
|
2021-02-19 19:19:58 +01:00
|
|
|
class ClaimToSupportKey(typing.NamedTuple):
|
|
|
|
claim_hash: bytes
|
|
|
|
tx_num: int
|
|
|
|
position: int
|
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(claim_hash={self.claim_hash.hex()}, tx_num={self.tx_num}, " \
|
|
|
|
f"position={self.position})"
|
|
|
|
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
class ClaimToSupportValue(typing.NamedTuple):
|
|
|
|
amount: int
|
|
|
|
|
|
|
|
|
|
|
|
class SupportToClaimKey(typing.NamedTuple):
|
|
|
|
tx_num: int
|
|
|
|
position: int
|
|
|
|
|
|
|
|
|
|
|
|
class SupportToClaimValue(typing.NamedTuple):
|
|
|
|
claim_hash: bytes
|
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(claim_hash={self.claim_hash.hex()})"
|
|
|
|
|
2021-02-19 19:19:58 +01:00
|
|
|
|
2021-02-21 23:26:13 +01:00
|
|
|
class ClaimExpirationKey(typing.NamedTuple):
|
|
|
|
expiration: int
|
|
|
|
tx_num: int
|
|
|
|
position: int
|
|
|
|
|
|
|
|
|
|
|
|
class ClaimExpirationValue(typing.NamedTuple):
|
|
|
|
claim_hash: bytes
|
2021-08-12 22:08:52 +02:00
|
|
|
normalized_name: str
|
2021-02-21 23:26:13 +01:00
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
2021-08-12 22:08:52 +02:00
|
|
|
return f"{self.__class__.__name__}(claim_hash={self.claim_hash.hex()}, normalized_name={self.normalized_name})"
|
2021-07-01 02:07:19 +02:00
|
|
|
|
2021-02-21 23:26:13 +01:00
|
|
|
|
2021-05-05 22:17:32 +02:00
|
|
|
class ClaimTakeoverKey(typing.NamedTuple):
|
2021-08-12 22:08:52 +02:00
|
|
|
normalized_name: str
|
2021-05-05 22:17:32 +02:00
|
|
|
|
|
|
|
|
|
|
|
class ClaimTakeoverValue(typing.NamedTuple):
|
|
|
|
claim_hash: bytes
|
|
|
|
height: int
|
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(claim_hash={self.claim_hash.hex()}, height={self.height})"
|
|
|
|
|
2021-05-05 22:17:32 +02:00
|
|
|
|
|
|
|
class PendingActivationKey(typing.NamedTuple):
|
|
|
|
height: int
|
2021-05-20 19:31:40 +02:00
|
|
|
txo_type: int
|
2021-05-05 22:17:32 +02:00
|
|
|
tx_num: int
|
|
|
|
position: int
|
|
|
|
|
2021-05-20 19:31:40 +02:00
|
|
|
@property
|
|
|
|
def is_support(self) -> bool:
|
|
|
|
return self.txo_type == ACTIVATED_SUPPORT_TXO_TYPE
|
|
|
|
|
|
|
|
@property
|
|
|
|
def is_claim(self) -> bool:
|
|
|
|
return self.txo_type == ACTIVATED_CLAIM_TXO_TYPE
|
|
|
|
|
2021-05-05 22:17:32 +02:00
|
|
|
|
|
|
|
class PendingActivationValue(typing.NamedTuple):
|
|
|
|
claim_hash: bytes
|
2021-08-12 22:08:52 +02:00
|
|
|
normalized_name: str
|
2021-05-05 22:17:32 +02:00
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
2021-08-12 22:08:52 +02:00
|
|
|
return f"{self.__class__.__name__}(claim_hash={self.claim_hash.hex()}, normalized_name={self.normalized_name})"
|
2021-07-01 02:07:19 +02:00
|
|
|
|
2021-05-05 22:17:32 +02:00
|
|
|
|
2021-05-20 19:31:40 +02:00
|
|
|
class ActivationKey(typing.NamedTuple):
|
|
|
|
txo_type: int
|
|
|
|
tx_num: int
|
|
|
|
position: int
|
|
|
|
|
|
|
|
|
|
|
|
class ActivationValue(typing.NamedTuple):
|
|
|
|
height: int
|
|
|
|
claim_hash: bytes
|
2021-08-12 22:08:52 +02:00
|
|
|
normalized_name: str
|
2021-05-20 19:31:40 +02:00
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
2021-08-12 22:08:52 +02:00
|
|
|
return f"{self.__class__.__name__}(height={self.height}, claim_hash={self.claim_hash.hex()}, " \
|
|
|
|
f"normalized_name={self.normalized_name})"
|
2021-07-01 02:07:19 +02:00
|
|
|
|
2021-05-20 19:31:40 +02:00
|
|
|
|
|
|
|
class ActiveAmountKey(typing.NamedTuple):
|
|
|
|
claim_hash: bytes
|
|
|
|
txo_type: int
|
|
|
|
activation_height: int
|
|
|
|
tx_num: int
|
|
|
|
position: int
|
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(claim_hash={self.claim_hash.hex()}, txo_type={self.txo_type}, " \
|
|
|
|
f"activation_height={self.activation_height}, tx_num={self.tx_num}, position={self.position})"
|
|
|
|
|
2021-05-20 19:31:40 +02:00
|
|
|
|
|
|
|
class ActiveAmountValue(typing.NamedTuple):
|
|
|
|
amount: int
|
|
|
|
|
|
|
|
|
2021-05-24 18:35:26 +02:00
|
|
|
class EffectiveAmountKey(typing.NamedTuple):
|
2021-08-12 22:08:52 +02:00
|
|
|
normalized_name: str
|
2021-05-24 18:35:26 +02:00
|
|
|
effective_amount: int
|
|
|
|
tx_num: int
|
|
|
|
position: int
|
|
|
|
|
|
|
|
|
|
|
|
class EffectiveAmountValue(typing.NamedTuple):
|
|
|
|
claim_hash: bytes
|
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(claim_hash={self.claim_hash.hex()})"
|
|
|
|
|
2021-05-24 18:35:26 +02:00
|
|
|
|
2021-06-02 17:00:27 +02:00
|
|
|
class RepostKey(typing.NamedTuple):
|
|
|
|
claim_hash: bytes
|
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(claim_hash={self.claim_hash.hex()})"
|
|
|
|
|
2021-06-02 17:00:27 +02:00
|
|
|
|
|
|
|
class RepostValue(typing.NamedTuple):
|
|
|
|
reposted_claim_hash: bytes
|
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(reposted_claim_hash={self.reposted_claim_hash.hex()})"
|
|
|
|
|
2021-06-02 17:00:27 +02:00
|
|
|
|
|
|
|
class RepostedKey(typing.NamedTuple):
|
|
|
|
reposted_claim_hash: bytes
|
|
|
|
tx_num: int
|
|
|
|
position: int
|
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(reposted_claim_hash={self.reposted_claim_hash.hex()}, " \
|
|
|
|
f"tx_num={self.tx_num}, position={self.position})"
|
|
|
|
|
2021-06-02 17:00:27 +02:00
|
|
|
|
|
|
|
class RepostedValue(typing.NamedTuple):
|
|
|
|
claim_hash: bytes
|
|
|
|
|
2021-07-01 02:07:19 +02:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(claim_hash={self.claim_hash.hex()})"
|
|
|
|
|
2021-06-02 17:00:27 +02:00
|
|
|
|
2021-07-16 20:46:46 +02:00
|
|
|
class TouchedOrDeletedClaimKey(typing.NamedTuple):
|
|
|
|
height: int
|
|
|
|
|
|
|
|
|
|
|
|
class TouchedOrDeletedClaimValue(typing.NamedTuple):
|
|
|
|
touched_claims: typing.Set[bytes]
|
|
|
|
deleted_claims: typing.Set[bytes]
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(" \
|
|
|
|
f"touched_claims={','.join(map(lambda x: x.hex(), self.touched_claims))}," \
|
|
|
|
f"deleted_claims={','.join(map(lambda x: x.hex(), self.deleted_claims))})"
|
|
|
|
|
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
class DBState(typing.NamedTuple):
|
|
|
|
genesis: bytes
|
|
|
|
height: int
|
|
|
|
tx_count: int
|
|
|
|
tip: bytes
|
|
|
|
utxo_flush_count: int
|
|
|
|
wall_time: int
|
|
|
|
first_sync: bool
|
|
|
|
db_version: int
|
|
|
|
hist_flush_count: int
|
|
|
|
comp_flush_count: int
|
|
|
|
comp_cursor: int
|
2021-10-21 01:34:55 +02:00
|
|
|
es_sync_height: int
|
2021-10-04 22:38:28 +02:00
|
|
|
|
|
|
|
|
2021-05-20 19:31:40 +02:00
|
|
|
class ActiveAmountPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.active_amount.value
|
|
|
|
key_struct = struct.Struct(b'>20sBLLH')
|
|
|
|
value_struct = struct.Struct(b'>Q')
|
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>20s').pack,
|
|
|
|
struct.Struct(b'>20sB').pack,
|
|
|
|
struct.Struct(b'>20sBL').pack,
|
|
|
|
struct.Struct(b'>20sBLL').pack,
|
|
|
|
struct.Struct(b'>20sBLLH').pack
|
|
|
|
]
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
2021-05-20 19:31:40 +02:00
|
|
|
def pack_key(cls, claim_hash: bytes, txo_type: int, activation_height: int, tx_num: int, position: int):
|
|
|
|
return super().pack_key(claim_hash, txo_type, activation_height, tx_num, position)
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
2021-05-20 19:31:40 +02:00
|
|
|
def unpack_key(cls, key: bytes) -> ActiveAmountKey:
|
|
|
|
return ActiveAmountKey(*super().unpack_key(key))
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
2021-05-20 19:31:40 +02:00
|
|
|
def unpack_value(cls, data: bytes) -> ActiveAmountValue:
|
|
|
|
return ActiveAmountValue(*super().unpack_value(data))
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
2021-05-20 19:31:40 +02:00
|
|
|
def pack_value(cls, amount: int) -> bytes:
|
|
|
|
return cls.value_struct.pack(amount)
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
2021-05-20 19:31:40 +02:00
|
|
|
def pack_item(cls, claim_hash: bytes, txo_type: int, activation_height: int, tx_num: int, position: int, amount: int):
|
|
|
|
return cls.pack_key(claim_hash, txo_type, activation_height, tx_num, position), cls.pack_value(amount)
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
|
|
|
|
class ClaimToTXOPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.claim_to_txo.value
|
2021-06-09 22:29:16 +02:00
|
|
|
key_struct = struct.Struct(b'>20s')
|
|
|
|
value_struct = struct.Struct(b'>LHLHQB')
|
2021-05-20 19:31:40 +02:00
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
2021-06-09 22:29:16 +02:00
|
|
|
struct.Struct(b'>20s').pack
|
2021-05-20 19:31:40 +02:00
|
|
|
]
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
2021-06-09 22:29:16 +02:00
|
|
|
def pack_key(cls, claim_hash: bytes):
|
2021-10-04 22:38:28 +02:00
|
|
|
return super().pack_key(claim_hash)
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> ClaimToTXOKey:
|
2021-06-09 22:29:16 +02:00
|
|
|
assert key[:1] == cls.prefix and len(key) == 21
|
|
|
|
return ClaimToTXOKey(key[1:])
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
2021-05-05 22:17:32 +02:00
|
|
|
def unpack_value(cls, data: bytes) -> ClaimToTXOValue:
|
2021-06-09 22:29:16 +02:00
|
|
|
tx_num, position, root_tx_num, root_position, amount, channel_signature_is_valid = cls.value_struct.unpack(
|
|
|
|
data[:21]
|
|
|
|
)
|
|
|
|
name_len = int.from_bytes(data[21:23], byteorder='big')
|
|
|
|
name = data[23:23 + name_len].decode()
|
|
|
|
return ClaimToTXOValue(
|
|
|
|
tx_num, position, root_tx_num, root_position, amount, bool(channel_signature_is_valid), name
|
|
|
|
)
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
2021-06-09 22:29:16 +02:00
|
|
|
def pack_value(cls, tx_num: int, position: int, root_tx_num: int, root_position: int, amount: int,
|
2021-06-04 22:50:37 +02:00
|
|
|
channel_signature_is_valid: bool, name: str) -> bytes:
|
|
|
|
return cls.value_struct.pack(
|
2021-06-09 22:29:16 +02:00
|
|
|
tx_num, position, root_tx_num, root_position, amount, int(channel_signature_is_valid)
|
2021-06-04 22:50:37 +02:00
|
|
|
) + length_encoded_name(name)
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, claim_hash: bytes, tx_num: int, position: int, root_tx_num: int, root_position: int,
|
2021-06-04 22:50:37 +02:00
|
|
|
amount: int, channel_signature_is_valid: bool, name: str):
|
2021-06-09 22:29:16 +02:00
|
|
|
return cls.pack_key(claim_hash), \
|
|
|
|
cls.pack_value(tx_num, position, root_tx_num, root_position, amount, channel_signature_is_valid, name)
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
|
|
|
|
class TXOToClaimPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.txo_to_claim.value
|
|
|
|
key_struct = struct.Struct(b'>LH')
|
|
|
|
value_struct = struct.Struct(b'>20s')
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, tx_num: int, position: int):
|
|
|
|
return super().pack_key(tx_num, position)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> TXOToClaimKey:
|
|
|
|
return TXOToClaimKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> TXOToClaimValue:
|
|
|
|
claim_hash, = cls.value_struct.unpack(data[:20])
|
|
|
|
name_len = int.from_bytes(data[20:22], byteorder='big')
|
|
|
|
name = data[22:22 + name_len].decode()
|
|
|
|
return TXOToClaimValue(claim_hash, name)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, claim_hash: bytes, name: str) -> bytes:
|
|
|
|
return cls.value_struct.pack(claim_hash) + length_encoded_name(name)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, tx_num: int, position: int, claim_hash: bytes, name: str):
|
|
|
|
return cls.pack_key(tx_num, position), \
|
|
|
|
cls.pack_value(claim_hash, name)
|
|
|
|
|
|
|
|
|
2021-05-20 19:31:40 +02:00
|
|
|
def shortid_key_helper(struct_fmt):
|
|
|
|
packer = struct.Struct(struct_fmt).pack
|
|
|
|
def wrapper(name, *args):
|
|
|
|
return length_encoded_name(name) + packer(*args)
|
|
|
|
return wrapper
|
|
|
|
|
|
|
|
|
2021-07-18 04:22:14 +02:00
|
|
|
def shortid_key_partial_claim_helper(name: str, partial_claim_id: str):
|
|
|
|
assert len(partial_claim_id) < 40
|
|
|
|
return length_encoded_name(name) + length_prefix(partial_claim_id)
|
2021-05-24 18:35:26 +02:00
|
|
|
|
|
|
|
|
2021-02-19 19:19:58 +01:00
|
|
|
class ClaimShortIDPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.claim_short_id_prefix.value
|
2021-07-18 04:22:14 +02:00
|
|
|
key_struct = struct.Struct(b'>LH')
|
2021-05-20 19:31:40 +02:00
|
|
|
value_struct = struct.Struct(b'>LH')
|
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
length_encoded_name,
|
2021-07-18 04:22:14 +02:00
|
|
|
shortid_key_partial_claim_helper
|
2021-05-20 19:31:40 +02:00
|
|
|
]
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
2021-07-18 04:22:14 +02:00
|
|
|
def pack_key(cls, name: str, short_claim_id: str, root_tx_num: int, root_position: int):
|
|
|
|
return cls.prefix + length_encoded_name(name) + length_prefix(short_claim_id) +\
|
|
|
|
cls.key_struct.pack(root_tx_num, root_position)
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
2021-05-20 19:31:40 +02:00
|
|
|
def pack_value(cls, tx_num: int, position: int):
|
|
|
|
return super().pack_value(tx_num, position)
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> ClaimShortIDKey:
|
|
|
|
assert key[:1] == cls.prefix
|
|
|
|
name_len = int.from_bytes(key[1:3], byteorder='big')
|
|
|
|
name = key[3:3 + name_len].decode()
|
2021-07-18 04:22:14 +02:00
|
|
|
claim_id_len = int.from_bytes(key[3+name_len:4+name_len], byteorder='big')
|
|
|
|
partial_claim_id = key[4+name_len:4+name_len+claim_id_len].decode()
|
|
|
|
return ClaimShortIDKey(name, partial_claim_id, *cls.key_struct.unpack(key[4 + name_len + claim_id_len:]))
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> ClaimShortIDValue:
|
|
|
|
return ClaimShortIDValue(*super().unpack_value(data))
|
|
|
|
|
|
|
|
@classmethod
|
2021-07-18 04:22:14 +02:00
|
|
|
def pack_item(cls, name: str, partial_claim_id: str, root_tx_num: int, root_position: int,
|
2021-05-20 19:31:40 +02:00
|
|
|
tx_num: int, position: int):
|
2021-07-18 04:22:14 +02:00
|
|
|
return cls.pack_key(name, partial_claim_id, root_tx_num, root_position), \
|
2021-05-20 19:31:40 +02:00
|
|
|
cls.pack_value(tx_num, position)
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
|
|
|
|
class ClaimToChannelPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.claim_to_channel.value
|
2021-06-22 23:25:23 +02:00
|
|
|
key_struct = struct.Struct(b'>20sLH')
|
2021-02-19 19:19:58 +01:00
|
|
|
value_struct = struct.Struct(b'>20s')
|
|
|
|
|
2021-06-22 23:25:23 +02:00
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>20s').pack,
|
|
|
|
struct.Struct(b'>20sL').pack,
|
|
|
|
struct.Struct(b'>20sLH').pack
|
|
|
|
]
|
|
|
|
|
2021-02-19 19:19:58 +01:00
|
|
|
@classmethod
|
2021-06-22 23:25:23 +02:00
|
|
|
def pack_key(cls, claim_hash: bytes, tx_num: int, position: int):
|
|
|
|
return super().pack_key(claim_hash, tx_num, position)
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, signing_hash: bytes):
|
|
|
|
return super().pack_value(signing_hash)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> ClaimToChannelKey:
|
|
|
|
return ClaimToChannelKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> ClaimToChannelValue:
|
|
|
|
return ClaimToChannelValue(*super().unpack_value(data))
|
|
|
|
|
|
|
|
@classmethod
|
2021-06-22 23:25:23 +02:00
|
|
|
def pack_item(cls, claim_hash: bytes, tx_num: int, position: int, signing_hash: bytes):
|
|
|
|
return cls.pack_key(claim_hash, tx_num, position), cls.pack_value(signing_hash)
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
|
2021-05-20 19:31:40 +02:00
|
|
|
def channel_to_claim_helper(struct_fmt):
|
|
|
|
packer = struct.Struct(struct_fmt).pack
|
|
|
|
|
|
|
|
def wrapper(signing_hash: bytes, name: str, *args):
|
|
|
|
return signing_hash + length_encoded_name(name) + packer(*args)
|
|
|
|
|
|
|
|
return wrapper
|
|
|
|
|
|
|
|
|
2021-02-19 19:19:58 +01:00
|
|
|
class ChannelToClaimPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.channel_to_claim.value
|
2021-05-20 19:31:40 +02:00
|
|
|
key_struct = struct.Struct(b'>LH')
|
|
|
|
value_struct = struct.Struct(b'>20s')
|
|
|
|
|
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>20s').pack,
|
|
|
|
channel_to_claim_helper(b''),
|
|
|
|
channel_to_claim_helper(b'>s'),
|
|
|
|
channel_to_claim_helper(b'>L'),
|
|
|
|
channel_to_claim_helper(b'>LH'),
|
|
|
|
]
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
2021-05-20 19:31:40 +02:00
|
|
|
def pack_key(cls, signing_hash: bytes, name: str, tx_num: int, position: int):
|
2021-02-19 19:19:58 +01:00
|
|
|
return cls.prefix + signing_hash + length_encoded_name(name) + cls.key_struct.pack(
|
2021-05-20 19:31:40 +02:00
|
|
|
tx_num, position
|
2021-02-19 19:19:58 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> ChannelToClaimKey:
|
|
|
|
assert key[:1] == cls.prefix
|
|
|
|
signing_hash = key[1:21]
|
|
|
|
name_len = int.from_bytes(key[21:23], byteorder='big')
|
|
|
|
name = key[23:23 + name_len].decode()
|
2021-05-20 19:31:40 +02:00
|
|
|
tx_num, position = cls.key_struct.unpack(key[23 + name_len:])
|
2021-02-19 19:19:58 +01:00
|
|
|
return ChannelToClaimKey(
|
2021-05-20 19:31:40 +02:00
|
|
|
signing_hash, name, tx_num, position
|
2021-02-19 19:19:58 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
@classmethod
|
2021-05-20 19:31:40 +02:00
|
|
|
def pack_value(cls, claim_hash: bytes) -> bytes:
|
|
|
|
return super().pack_value(claim_hash)
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> ChannelToClaimValue:
|
|
|
|
return ChannelToClaimValue(*cls.value_struct.unpack(data))
|
|
|
|
|
|
|
|
@classmethod
|
2021-05-20 19:31:40 +02:00
|
|
|
def pack_item(cls, signing_hash: bytes, name: str, tx_num: int, position: int,
|
|
|
|
claim_hash: bytes):
|
|
|
|
return cls.pack_key(signing_hash, name, tx_num, position), \
|
|
|
|
cls.pack_value(claim_hash)
|
2021-02-19 19:19:58 +01:00
|
|
|
|
|
|
|
|
|
|
|
class ClaimToSupportPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.claim_to_support.value
|
|
|
|
key_struct = struct.Struct(b'>20sLH')
|
|
|
|
value_struct = struct.Struct(b'>Q')
|
|
|
|
|
2021-07-29 18:36:30 +02:00
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>20s').pack,
|
|
|
|
struct.Struct(b'>20sL').pack,
|
|
|
|
struct.Struct(b'>20sLH').pack
|
|
|
|
]
|
|
|
|
|
2021-02-19 19:19:58 +01:00
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, claim_hash: bytes, tx_num: int, position: int):
|
|
|
|
return super().pack_key(claim_hash, tx_num, position)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> ClaimToSupportKey:
|
|
|
|
return ClaimToSupportKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, amount: int) -> bytes:
|
|
|
|
return super().pack_value(amount)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> ClaimToSupportValue:
|
|
|
|
return ClaimToSupportValue(*super().unpack_value(data))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, claim_hash: bytes, tx_num: int, position: int, amount: int):
|
|
|
|
return cls.pack_key(claim_hash, tx_num, position), \
|
|
|
|
cls.pack_value(amount)
|
|
|
|
|
|
|
|
|
|
|
|
class SupportToClaimPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.support_to_claim.value
|
|
|
|
key_struct = struct.Struct(b'>LH')
|
|
|
|
value_struct = struct.Struct(b'>20s')
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, tx_num: int, position: int):
|
|
|
|
return super().pack_key(tx_num, position)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> SupportToClaimKey:
|
|
|
|
return SupportToClaimKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, claim_hash: bytes) -> bytes:
|
|
|
|
return super().pack_value(claim_hash)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> SupportToClaimValue:
|
|
|
|
return SupportToClaimValue(*super().unpack_value(data))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, tx_num: int, position: int, claim_hash: bytes):
|
|
|
|
return cls.pack_key(tx_num, position), \
|
|
|
|
cls.pack_value(claim_hash)
|
|
|
|
|
|
|
|
|
2021-02-21 23:26:13 +01:00
|
|
|
class ClaimExpirationPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.claim_expiration.value
|
|
|
|
key_struct = struct.Struct(b'>LLH')
|
|
|
|
value_struct = struct.Struct(b'>20s')
|
2021-05-20 19:31:40 +02:00
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>L').pack,
|
|
|
|
struct.Struct(b'>LL').pack,
|
|
|
|
struct.Struct(b'>LLH').pack,
|
|
|
|
]
|
2021-02-21 23:26:13 +01:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, expiration: int, tx_num: int, position: int) -> bytes:
|
|
|
|
return super().pack_key(expiration, tx_num, position)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, claim_hash: bytes, name: str) -> bytes:
|
|
|
|
return cls.value_struct.pack(claim_hash) + length_encoded_name(name)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, expiration: int, tx_num: int, position: int, claim_hash: bytes, name: str) -> typing.Tuple[bytes, bytes]:
|
|
|
|
return cls.pack_key(expiration, tx_num, position), cls.pack_value(claim_hash, name)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> ClaimExpirationKey:
|
|
|
|
return ClaimExpirationKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> ClaimExpirationValue:
|
|
|
|
name_len = int.from_bytes(data[20:22], byteorder='big')
|
|
|
|
name = data[22:22 + name_len].decode()
|
|
|
|
claim_id, = cls.value_struct.unpack(data[:20])
|
|
|
|
return ClaimExpirationValue(claim_id, name)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_item(cls, key: bytes, value: bytes) -> typing.Tuple[ClaimExpirationKey, ClaimExpirationValue]:
|
|
|
|
return cls.unpack_key(key), cls.unpack_value(value)
|
|
|
|
|
|
|
|
|
2021-05-05 22:17:32 +02:00
|
|
|
class ClaimTakeoverPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.claim_takeover.value
|
|
|
|
value_struct = struct.Struct(b'>20sL')
|
|
|
|
|
2021-10-05 20:24:46 +02:00
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
length_encoded_name
|
|
|
|
]
|
|
|
|
|
2021-05-05 22:17:32 +02:00
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, name: str):
|
|
|
|
return cls.prefix + length_encoded_name(name)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, claim_hash: bytes, takeover_height: int):
|
|
|
|
return super().pack_value(claim_hash, takeover_height)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> ClaimTakeoverKey:
|
|
|
|
assert key[:1] == cls.prefix
|
|
|
|
name_len = int.from_bytes(key[1:3], byteorder='big')
|
|
|
|
name = key[3:3 + name_len].decode()
|
|
|
|
return ClaimTakeoverKey(name)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> ClaimTakeoverValue:
|
|
|
|
return ClaimTakeoverValue(*super().unpack_value(data))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, name: str, claim_hash: bytes, takeover_height: int):
|
|
|
|
return cls.pack_key(name), cls.pack_value(claim_hash, takeover_height)
|
|
|
|
|
|
|
|
|
2021-05-20 19:31:40 +02:00
|
|
|
class PendingActivationPrefixRow(PrefixRow):
|
2021-05-05 22:17:32 +02:00
|
|
|
prefix = DB_PREFIXES.pending_activation.value
|
2021-05-20 19:31:40 +02:00
|
|
|
key_struct = struct.Struct(b'>LBLH')
|
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>L').pack,
|
|
|
|
struct.Struct(b'>LB').pack,
|
|
|
|
struct.Struct(b'>LBL').pack,
|
|
|
|
struct.Struct(b'>LBLH').pack
|
|
|
|
]
|
2021-05-05 22:17:32 +02:00
|
|
|
|
|
|
|
@classmethod
|
2021-05-20 19:31:40 +02:00
|
|
|
def pack_key(cls, height: int, txo_type: int, tx_num: int, position: int):
|
|
|
|
return super().pack_key(height, txo_type, tx_num, position)
|
2021-05-05 22:17:32 +02:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> PendingActivationKey:
|
|
|
|
return PendingActivationKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, claim_hash: bytes, name: str) -> bytes:
|
|
|
|
return claim_hash + length_encoded_name(name)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> PendingActivationValue:
|
|
|
|
claim_hash = data[:20]
|
|
|
|
name_len = int.from_bytes(data[20:22], byteorder='big')
|
|
|
|
name = data[22:22 + name_len].decode()
|
|
|
|
return PendingActivationValue(claim_hash, name)
|
|
|
|
|
|
|
|
@classmethod
|
2021-05-20 19:31:40 +02:00
|
|
|
def pack_item(cls, height: int, txo_type: int, tx_num: int, position: int, claim_hash: bytes, name: str):
|
|
|
|
return cls.pack_key(height, txo_type, tx_num, position), \
|
2021-05-05 22:17:32 +02:00
|
|
|
cls.pack_value(claim_hash, name)
|
|
|
|
|
|
|
|
|
2021-05-20 19:31:40 +02:00
|
|
|
class ActivatedPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.activated_claim_and_support.value
|
|
|
|
key_struct = struct.Struct(b'>BLH')
|
|
|
|
value_struct = struct.Struct(b'>L20s')
|
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>B').pack,
|
|
|
|
struct.Struct(b'>BL').pack,
|
|
|
|
struct.Struct(b'>BLH').pack
|
|
|
|
]
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, txo_type: int, tx_num: int, position: int):
|
|
|
|
return super().pack_key(txo_type, tx_num, position)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> ActivationKey:
|
|
|
|
return ActivationKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, height: int, claim_hash: bytes, name: str) -> bytes:
|
|
|
|
return cls.value_struct.pack(height, claim_hash) + length_encoded_name(name)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> ActivationValue:
|
|
|
|
height, claim_hash = cls.value_struct.unpack(data[:24])
|
|
|
|
name_len = int.from_bytes(data[24:26], byteorder='big')
|
|
|
|
name = data[26:26 + name_len].decode()
|
|
|
|
return ActivationValue(height, claim_hash, name)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, txo_type: int, tx_num: int, position: int, height: int, claim_hash: bytes, name: str):
|
|
|
|
return cls.pack_key(txo_type, tx_num, position), \
|
|
|
|
cls.pack_value(height, claim_hash, name)
|
|
|
|
|
|
|
|
|
2021-05-24 18:35:26 +02:00
|
|
|
def effective_amount_helper(struct_fmt):
|
|
|
|
packer = struct.Struct(struct_fmt).pack
|
|
|
|
|
|
|
|
def wrapper(name, *args):
|
|
|
|
if not args:
|
|
|
|
return length_encoded_name(name)
|
|
|
|
if len(args) == 1:
|
|
|
|
return length_encoded_name(name) + packer(0xffffffffffffffff - args[0])
|
|
|
|
return length_encoded_name(name) + packer(0xffffffffffffffff - args[0], *args[1:])
|
|
|
|
|
|
|
|
return wrapper
|
|
|
|
|
|
|
|
|
|
|
|
class EffectiveAmountPrefixRow(PrefixRow):
|
2021-07-03 17:48:22 +02:00
|
|
|
prefix = DB_PREFIXES.effective_amount.value
|
2021-05-24 18:35:26 +02:00
|
|
|
key_struct = struct.Struct(b'>QLH')
|
|
|
|
value_struct = struct.Struct(b'>20s')
|
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
length_encoded_name,
|
|
|
|
shortid_key_helper(b'>Q'),
|
|
|
|
shortid_key_helper(b'>QL'),
|
|
|
|
shortid_key_helper(b'>QLH'),
|
|
|
|
]
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, name: str, effective_amount: int, tx_num: int, position: int):
|
|
|
|
return cls.prefix + length_encoded_name(name) + cls.key_struct.pack(
|
|
|
|
0xffffffffffffffff - effective_amount, tx_num, position
|
|
|
|
)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> EffectiveAmountKey:
|
|
|
|
assert key[:1] == cls.prefix
|
|
|
|
name_len = int.from_bytes(key[1:3], byteorder='big')
|
|
|
|
name = key[3:3 + name_len].decode()
|
|
|
|
ones_comp_effective_amount, tx_num, position = cls.key_struct.unpack(key[3 + name_len:])
|
|
|
|
return EffectiveAmountKey(name, 0xffffffffffffffff - ones_comp_effective_amount, tx_num, position)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> EffectiveAmountValue:
|
|
|
|
return EffectiveAmountValue(*super().unpack_value(data))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, claim_hash: bytes) -> bytes:
|
|
|
|
return super().pack_value(claim_hash)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, name: str, effective_amount: int, tx_num: int, position: int, claim_hash: bytes):
|
|
|
|
return cls.pack_key(name, effective_amount, tx_num, position), cls.pack_value(claim_hash)
|
|
|
|
|
|
|
|
|
2021-06-02 17:00:27 +02:00
|
|
|
class RepostPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.repost.value
|
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>20s').pack
|
|
|
|
]
|
|
|
|
|
2021-06-02 17:00:27 +02:00
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, claim_hash: bytes):
|
|
|
|
return cls.prefix + claim_hash
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> RepostKey:
|
2021-07-05 16:02:52 +02:00
|
|
|
assert key[:1] == cls.prefix
|
2021-06-02 17:00:27 +02:00
|
|
|
assert len(key) == 21
|
2021-07-05 16:02:52 +02:00
|
|
|
return RepostKey(key[1:])
|
2021-06-02 17:00:27 +02:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, reposted_claim_hash: bytes) -> bytes:
|
|
|
|
return reposted_claim_hash
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> RepostValue:
|
|
|
|
return RepostValue(data)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, claim_hash: bytes, reposted_claim_hash: bytes):
|
|
|
|
return cls.pack_key(claim_hash), cls.pack_value(reposted_claim_hash)
|
|
|
|
|
|
|
|
|
|
|
|
class RepostedPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.reposted_claim.value
|
|
|
|
key_struct = struct.Struct(b'>20sLH')
|
|
|
|
value_struct = struct.Struct(b'>20s')
|
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>20s').pack,
|
|
|
|
struct.Struct(b'>20sL').pack,
|
|
|
|
struct.Struct(b'>20sLH').pack
|
|
|
|
]
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, reposted_claim_hash: bytes, tx_num: int, position: int):
|
|
|
|
return super().pack_key(reposted_claim_hash, tx_num, position)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> RepostedKey:
|
|
|
|
return RepostedKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, claim_hash: bytes) -> bytes:
|
|
|
|
return super().pack_value(claim_hash)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> RepostedValue:
|
|
|
|
return RepostedValue(*super().unpack_value(data))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, reposted_claim_hash: bytes, tx_num: int, position: int, claim_hash: bytes):
|
|
|
|
return cls.pack_key(reposted_claim_hash, tx_num, position), cls.pack_value(claim_hash)
|
|
|
|
|
|
|
|
|
2022-01-06 18:36:33 +01:00
|
|
|
class UndoKey(NamedTuple):
|
|
|
|
height: int
|
|
|
|
block_hash: bytes
|
|
|
|
|
|
|
|
|
2021-06-22 23:25:23 +02:00
|
|
|
class UndoPrefixRow(PrefixRow):
|
2021-07-14 19:39:06 +02:00
|
|
|
prefix = DB_PREFIXES.undo.value
|
2022-01-06 18:36:33 +01:00
|
|
|
key_struct = struct.Struct(b'>Q32s')
|
2021-06-22 23:25:23 +02:00
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
2022-01-06 18:36:33 +01:00
|
|
|
struct.Struct(b'>Q').pack,
|
|
|
|
struct.Struct(b'>Q32s').pack
|
2021-10-04 22:38:28 +02:00
|
|
|
]
|
|
|
|
|
2021-06-22 23:25:23 +02:00
|
|
|
@classmethod
|
2022-01-06 18:36:33 +01:00
|
|
|
def pack_key(cls, height: int, block_hash: bytes):
|
|
|
|
return super().pack_key(height, block_hash)
|
2021-06-22 23:25:23 +02:00
|
|
|
|
|
|
|
@classmethod
|
2022-01-06 18:36:33 +01:00
|
|
|
def unpack_key(cls, key: bytes) -> UndoKey:
|
|
|
|
return UndoKey(*super().unpack_key(key))
|
2021-06-22 23:25:23 +02:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, undo_ops: bytes) -> bytes:
|
|
|
|
return undo_ops
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> bytes:
|
|
|
|
return data
|
|
|
|
|
|
|
|
@classmethod
|
2022-01-06 18:36:33 +01:00
|
|
|
def pack_item(cls, height: int, block_hash: bytes, undo_ops: bytes):
|
|
|
|
return cls.pack_key(height, block_hash), cls.pack_value(undo_ops)
|
2021-06-22 23:25:23 +02:00
|
|
|
|
|
|
|
|
2021-07-14 18:53:56 +02:00
|
|
|
class BlockHashPrefixRow(PrefixRow):
|
2021-07-14 19:39:06 +02:00
|
|
|
prefix = DB_PREFIXES.block_hash.value
|
2021-07-14 18:53:56 +02:00
|
|
|
key_struct = struct.Struct(b'>L')
|
|
|
|
value_struct = struct.Struct(b'>32s')
|
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>L').pack
|
|
|
|
]
|
|
|
|
|
2021-07-14 18:53:56 +02:00
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, height: int) -> bytes:
|
|
|
|
return super().pack_key(height)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> BlockHashKey:
|
|
|
|
return BlockHashKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, block_hash: bytes) -> bytes:
|
|
|
|
return super().pack_value(block_hash)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> BlockHashValue:
|
|
|
|
return BlockHashValue(*super().unpack_value(data))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, height: int, block_hash: bytes):
|
|
|
|
return cls.pack_key(height), cls.pack_value(block_hash)
|
|
|
|
|
|
|
|
|
|
|
|
class BlockHeaderPrefixRow(PrefixRow):
|
2021-07-14 19:39:06 +02:00
|
|
|
prefix = DB_PREFIXES.header.value
|
2021-07-14 18:53:56 +02:00
|
|
|
key_struct = struct.Struct(b'>L')
|
|
|
|
value_struct = struct.Struct(b'>112s')
|
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>L').pack
|
|
|
|
]
|
|
|
|
|
2021-07-14 18:53:56 +02:00
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, height: int) -> bytes:
|
|
|
|
return super().pack_key(height)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> BlockHeaderKey:
|
|
|
|
return BlockHeaderKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, header: bytes) -> bytes:
|
|
|
|
return super().pack_value(header)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> BlockHeaderValue:
|
|
|
|
return BlockHeaderValue(*super().unpack_value(data))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, height: int, header: bytes):
|
|
|
|
return cls.pack_key(height), cls.pack_value(header)
|
|
|
|
|
|
|
|
|
|
|
|
class TXNumPrefixRow(PrefixRow):
|
2021-07-14 19:39:06 +02:00
|
|
|
prefix = DB_PREFIXES.tx_num.value
|
2021-07-14 18:53:56 +02:00
|
|
|
key_struct = struct.Struct(b'>32s')
|
|
|
|
value_struct = struct.Struct(b'>L')
|
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>32s').pack
|
|
|
|
]
|
|
|
|
|
2021-07-14 18:53:56 +02:00
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, tx_hash: bytes) -> bytes:
|
|
|
|
return super().pack_key(tx_hash)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, tx_hash: bytes) -> TxNumKey:
|
|
|
|
return TxNumKey(*super().unpack_key(tx_hash))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, tx_num: int) -> bytes:
|
|
|
|
return super().pack_value(tx_num)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> TxNumValue:
|
|
|
|
return TxNumValue(*super().unpack_value(data))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, tx_hash: bytes, tx_num: int):
|
|
|
|
return cls.pack_key(tx_hash), cls.pack_value(tx_num)
|
|
|
|
|
|
|
|
|
|
|
|
class TxCountPrefixRow(PrefixRow):
|
2021-07-14 19:39:06 +02:00
|
|
|
prefix = DB_PREFIXES.tx_count.value
|
2021-07-14 18:53:56 +02:00
|
|
|
key_struct = struct.Struct(b'>L')
|
|
|
|
value_struct = struct.Struct(b'>L')
|
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>L').pack
|
|
|
|
]
|
|
|
|
|
2021-07-14 18:53:56 +02:00
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, height: int) -> bytes:
|
|
|
|
return super().pack_key(height)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> TxCountKey:
|
|
|
|
return TxCountKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, tx_count: int) -> bytes:
|
|
|
|
return super().pack_value(tx_count)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> TxCountValue:
|
|
|
|
return TxCountValue(*super().unpack_value(data))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, height: int, tx_count: int):
|
|
|
|
return cls.pack_key(height), cls.pack_value(tx_count)
|
|
|
|
|
|
|
|
|
|
|
|
class TXHashPrefixRow(PrefixRow):
|
2021-07-14 19:39:06 +02:00
|
|
|
prefix = DB_PREFIXES.tx_hash.value
|
2021-07-14 18:53:56 +02:00
|
|
|
key_struct = struct.Struct(b'>L')
|
|
|
|
value_struct = struct.Struct(b'>32s')
|
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>L').pack
|
|
|
|
]
|
|
|
|
|
2021-07-14 18:53:56 +02:00
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, tx_num: int) -> bytes:
|
|
|
|
return super().pack_key(tx_num)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> TxHashKey:
|
|
|
|
return TxHashKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, tx_hash: bytes) -> bytes:
|
|
|
|
return super().pack_value(tx_hash)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> TxHashValue:
|
|
|
|
return TxHashValue(*super().unpack_value(data))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, tx_num: int, tx_hash: bytes):
|
|
|
|
return cls.pack_key(tx_num), cls.pack_value(tx_hash)
|
|
|
|
|
|
|
|
|
|
|
|
class TXPrefixRow(PrefixRow):
|
2021-07-14 19:39:06 +02:00
|
|
|
prefix = DB_PREFIXES.tx.value
|
2021-07-14 18:53:56 +02:00
|
|
|
key_struct = struct.Struct(b'>32s')
|
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>32s').pack
|
|
|
|
]
|
|
|
|
|
2021-07-14 18:53:56 +02:00
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, tx_hash: bytes) -> bytes:
|
|
|
|
return super().pack_key(tx_hash)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, tx_hash: bytes) -> TxKey:
|
|
|
|
return TxKey(*super().unpack_key(tx_hash))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, tx: bytes) -> bytes:
|
|
|
|
return tx
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> TxValue:
|
|
|
|
return TxValue(data)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, tx_hash: bytes, raw_tx: bytes):
|
|
|
|
return cls.pack_key(tx_hash), cls.pack_value(raw_tx)
|
|
|
|
|
|
|
|
|
|
|
|
class UTXOPrefixRow(PrefixRow):
|
2021-07-14 19:39:06 +02:00
|
|
|
prefix = DB_PREFIXES.utxo.value
|
2021-07-14 18:53:56 +02:00
|
|
|
key_struct = struct.Struct(b'>11sLH')
|
|
|
|
value_struct = struct.Struct(b'>Q')
|
|
|
|
|
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>11s').pack,
|
|
|
|
struct.Struct(b'>11sL').pack,
|
|
|
|
struct.Struct(b'>11sLH').pack
|
|
|
|
]
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, hashX: bytes, tx_num, nout: int):
|
|
|
|
return super().pack_key(hashX, tx_num, nout)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> UTXOKey:
|
|
|
|
return UTXOKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, amount: int) -> bytes:
|
|
|
|
return super().pack_value(amount)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> UTXOValue:
|
|
|
|
return UTXOValue(*cls.value_struct.unpack(data))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, hashX: bytes, tx_num: int, nout: int, amount: int):
|
|
|
|
return cls.pack_key(hashX, tx_num, nout), cls.pack_value(amount)
|
|
|
|
|
|
|
|
|
|
|
|
class HashXUTXOPrefixRow(PrefixRow):
|
2021-07-14 19:39:06 +02:00
|
|
|
prefix = DB_PREFIXES.hashx_utxo.value
|
2021-07-14 18:53:56 +02:00
|
|
|
key_struct = struct.Struct(b'>4sLH')
|
|
|
|
value_struct = struct.Struct(b'>11s')
|
|
|
|
|
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>4s').pack,
|
|
|
|
struct.Struct(b'>4sL').pack,
|
|
|
|
struct.Struct(b'>4sLH').pack
|
|
|
|
]
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, short_tx_hash: bytes, tx_num, nout: int):
|
|
|
|
return super().pack_key(short_tx_hash, tx_num, nout)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> HashXUTXOKey:
|
|
|
|
return HashXUTXOKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, hashX: bytes) -> bytes:
|
|
|
|
return super().pack_value(hashX)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> HashXUTXOValue:
|
|
|
|
return HashXUTXOValue(*cls.value_struct.unpack(data))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, short_tx_hash: bytes, tx_num: int, nout: int, hashX: bytes):
|
|
|
|
return cls.pack_key(short_tx_hash, tx_num, nout), cls.pack_value(hashX)
|
|
|
|
|
|
|
|
|
|
|
|
class HashXHistoryPrefixRow(PrefixRow):
|
2021-07-14 19:39:06 +02:00
|
|
|
prefix = DB_PREFIXES.hashx_history.value
|
2021-07-14 18:53:56 +02:00
|
|
|
key_struct = struct.Struct(b'>11sL')
|
|
|
|
|
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
2021-10-07 06:37:55 +02:00
|
|
|
struct.Struct(b'>11s').pack,
|
|
|
|
struct.Struct(b'>11sL').pack
|
2021-07-14 18:53:56 +02:00
|
|
|
]
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, hashX: bytes, height: int):
|
|
|
|
return super().pack_key(hashX, height)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> HashXHistoryKey:
|
|
|
|
return HashXHistoryKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, history: typing.List[int]) -> bytes:
|
|
|
|
a = array.array('I')
|
|
|
|
a.fromlist(history)
|
|
|
|
return a.tobytes()
|
|
|
|
|
|
|
|
@classmethod
|
2021-09-25 20:59:42 +02:00
|
|
|
def unpack_value(cls, data: bytes) -> array.array:
|
2021-07-14 18:53:56 +02:00
|
|
|
a = array.array('I')
|
|
|
|
a.frombytes(data)
|
2021-09-25 20:59:42 +02:00
|
|
|
return a
|
2021-07-14 18:53:56 +02:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, hashX: bytes, height: int, history: typing.List[int]):
|
|
|
|
return cls.pack_key(hashX, height), cls.pack_value(history)
|
|
|
|
|
|
|
|
|
2021-07-16 20:46:46 +02:00
|
|
|
class TouchedOrDeletedPrefixRow(PrefixRow):
|
2022-01-06 18:28:15 +01:00
|
|
|
prefix = DB_PREFIXES.touched_or_deleted.value
|
2021-07-16 20:46:46 +02:00
|
|
|
key_struct = struct.Struct(b'>L')
|
|
|
|
value_struct = struct.Struct(b'>LL')
|
2021-10-04 22:38:28 +02:00
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>L').pack
|
|
|
|
]
|
2021-07-16 20:46:46 +02:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, height: int):
|
|
|
|
return super().pack_key(height)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> TouchedOrDeletedClaimKey:
|
|
|
|
return TouchedOrDeletedClaimKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
2021-10-05 20:24:46 +02:00
|
|
|
def pack_value(cls, touched: typing.Set[bytes], deleted: typing.Set[bytes]) -> bytes:
|
2021-10-04 22:38:28 +02:00
|
|
|
assert True if not touched else all(len(item) == 20 for item in touched)
|
|
|
|
assert True if not deleted else all(len(item) == 20 for item in deleted)
|
2021-10-05 20:24:46 +02:00
|
|
|
return cls.value_struct.pack(len(touched), len(deleted)) + b''.join(sorted(touched)) + b''.join(sorted(deleted))
|
2021-07-16 20:46:46 +02:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> TouchedOrDeletedClaimValue:
|
|
|
|
touched_len, deleted_len = cls.value_struct.unpack(data[:8])
|
2021-10-04 22:38:28 +02:00
|
|
|
data = data[8:]
|
|
|
|
assert len(data) == 20 * (touched_len + deleted_len)
|
|
|
|
touched_bytes, deleted_bytes = data[:touched_len*20], data[touched_len*20:]
|
2021-07-16 20:46:46 +02:00
|
|
|
return TouchedOrDeletedClaimValue(
|
2021-10-04 22:38:28 +02:00
|
|
|
{touched_bytes[20*i:20*(i+1)] for i in range(touched_len)},
|
|
|
|
{deleted_bytes[20*i:20*(i+1)] for i in range(deleted_len)}
|
2021-07-16 20:46:46 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, height, touched, deleted):
|
|
|
|
return cls.pack_key(height), cls.pack_value(touched, deleted)
|
|
|
|
|
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
class ChannelCountPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.channel_count.value
|
|
|
|
key_struct = struct.Struct(b'>20s')
|
|
|
|
value_struct = struct.Struct(b'>L')
|
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>20s').pack
|
|
|
|
]
|
2021-02-19 19:19:58 +01:00
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
@classmethod
|
2021-11-13 20:29:43 +01:00
|
|
|
def pack_key(cls, channel_hash: bytes):
|
2021-10-04 22:38:28 +02:00
|
|
|
return super().pack_key(channel_hash)
|
2021-02-19 19:19:58 +01:00
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> ChannelCountKey:
|
|
|
|
return ChannelCountKey(*super().unpack_key(key))
|
2021-02-19 19:19:58 +01:00
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, count: int) -> bytes:
|
|
|
|
return super().pack_value(count)
|
2021-02-19 19:19:58 +01:00
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> ChannelCountValue:
|
|
|
|
return ChannelCountValue(*super().unpack_value(data))
|
2021-05-05 22:17:32 +02:00
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, channel_hash, count):
|
|
|
|
return cls.pack_key(channel_hash), cls.pack_value(count)
|
2021-05-24 18:35:26 +02:00
|
|
|
|
2021-06-02 17:00:27 +02:00
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
class SupportAmountPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.support_amount.value
|
|
|
|
key_struct = struct.Struct(b'>20s')
|
|
|
|
value_struct = struct.Struct(b'>Q')
|
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>20s').pack
|
|
|
|
]
|
2021-07-16 20:46:46 +02:00
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, claim_hash: bytes):
|
|
|
|
return super().pack_key(claim_hash)
|
2021-06-22 23:25:23 +02:00
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> SupportAmountKey:
|
|
|
|
return SupportAmountKey(*super().unpack_key(key))
|
2021-08-14 02:02:42 +02:00
|
|
|
|
2021-10-04 22:38:28 +02:00
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, amount: int) -> bytes:
|
|
|
|
return super().pack_value(amount)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> SupportAmountValue:
|
|
|
|
return SupportAmountValue(*super().unpack_value(data))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, claim_hash, amount):
|
|
|
|
return cls.pack_key(claim_hash), cls.pack_value(amount)
|
|
|
|
|
|
|
|
|
|
|
|
class DBStatePrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.db_state.value
|
2021-10-21 01:34:55 +02:00
|
|
|
value_struct = struct.Struct(b'>32sLL32sLLBBlllL')
|
2021-10-04 22:38:28 +02:00
|
|
|
key_struct = struct.Struct(b'')
|
|
|
|
|
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b''
|
|
|
|
]
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_key(cls) -> bytes:
|
|
|
|
return cls.prefix
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes):
|
|
|
|
return
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, genesis: bytes, height: int, tx_count: int, tip: bytes, utxo_flush_count: int, wall_time: int,
|
|
|
|
first_sync: bool, db_version: int, hist_flush_count: int, comp_flush_count: int,
|
2021-10-21 01:34:55 +02:00
|
|
|
comp_cursor: int, es_sync_height: int) -> bytes:
|
2021-10-04 22:38:28 +02:00
|
|
|
return super().pack_value(
|
|
|
|
genesis, height, tx_count, tip, utxo_flush_count,
|
|
|
|
wall_time, 1 if first_sync else 0, db_version, hist_flush_count,
|
2021-10-21 01:34:55 +02:00
|
|
|
comp_flush_count, comp_cursor, es_sync_height
|
2021-10-04 22:38:28 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> DBState:
|
2021-10-21 01:34:55 +02:00
|
|
|
if len(data) == 94:
|
|
|
|
# TODO: delete this after making a new snapshot - 10/20/21
|
|
|
|
# migrate in the es_sync_height if it doesnt exist
|
|
|
|
data += data[32:36]
|
2021-10-04 22:38:28 +02:00
|
|
|
return DBState(*super().unpack_value(data))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, genesis: bytes, height: int, tx_count: int, tip: bytes, utxo_flush_count: int, wall_time: int,
|
|
|
|
first_sync: bool, db_version: int, hist_flush_count: int, comp_flush_count: int,
|
2021-11-13 20:29:43 +01:00
|
|
|
comp_cursor: int, es_sync_height: int):
|
2021-10-04 22:38:28 +02:00
|
|
|
return cls.pack_key(), cls.pack_value(
|
|
|
|
genesis, height, tx_count, tip, utxo_flush_count, wall_time, first_sync, db_version, hist_flush_count,
|
2021-11-13 20:29:43 +01:00
|
|
|
comp_flush_count, comp_cursor, es_sync_height
|
2021-10-04 22:38:28 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
2021-10-12 06:03:11 +02:00
|
|
|
class BlockTxsPrefixRow(PrefixRow):
|
2022-01-15 19:45:41 +01:00
|
|
|
prefix = DB_PREFIXES.block_tx.value
|
2021-10-12 06:03:11 +02:00
|
|
|
key_struct = struct.Struct(b'>L')
|
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>L').pack
|
|
|
|
]
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, height: int):
|
|
|
|
return super().pack_key(height)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> BlockTxsKey:
|
|
|
|
return BlockTxsKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, tx_hashes: typing.List[bytes]) -> bytes:
|
|
|
|
assert all(len(tx_hash) == 32 for tx_hash in tx_hashes)
|
|
|
|
return b''.join(tx_hashes)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> BlockTxsValue:
|
|
|
|
return BlockTxsValue([data[i*32:(i+1)*32] for i in range(len(data) // 32)])
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, height, tx_hashes):
|
|
|
|
return cls.pack_key(height), cls.pack_value(tx_hashes)
|
|
|
|
|
|
|
|
|
2022-01-15 19:45:41 +01:00
|
|
|
class MempoolTxKey(NamedTuple):
|
|
|
|
tx_hash: bytes
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(tx_hash={self.tx_hash[::-1].hex()})"
|
|
|
|
|
2021-12-01 22:47:29 +01:00
|
|
|
|
2022-01-15 19:45:41 +01:00
|
|
|
class MempoolTxValue(NamedTuple):
|
|
|
|
raw_tx: bytes
|
2021-12-01 22:47:29 +01:00
|
|
|
|
2022-01-15 19:45:41 +01:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(raw_tx={base64.b64encode(self.raw_tx).decode()})"
|
2021-12-01 22:47:29 +01:00
|
|
|
|
|
|
|
|
|
|
|
class MempoolTXPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.mempool_tx.value
|
|
|
|
key_struct = struct.Struct(b'>32s')
|
|
|
|
|
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>32s').pack
|
|
|
|
]
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, tx_hash: bytes) -> bytes:
|
|
|
|
return super().pack_key(tx_hash)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, tx_hash: bytes) -> MempoolTxKey:
|
|
|
|
return MempoolTxKey(*super().unpack_key(tx_hash))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, tx: bytes) -> bytes:
|
|
|
|
return tx
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> MempoolTxValue:
|
|
|
|
return MempoolTxValue(data)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, tx_hash: bytes, raw_tx: bytes):
|
|
|
|
return cls.pack_key(tx_hash), cls.pack_value(raw_tx)
|
|
|
|
|
|
|
|
|
|
|
|
class TrendingNotificationKey(typing.NamedTuple):
|
|
|
|
height: int
|
|
|
|
claim_hash: bytes
|
|
|
|
|
|
|
|
|
|
|
|
class TrendingNotificationValue(typing.NamedTuple):
|
|
|
|
previous_amount: int
|
|
|
|
new_amount: int
|
|
|
|
|
|
|
|
|
|
|
|
class TrendingNotificationPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.trending_notifications.value
|
|
|
|
key_struct = struct.Struct(b'>L20s')
|
|
|
|
value_struct = struct.Struct(b'>QQ')
|
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>L').pack,
|
|
|
|
struct.Struct(b'>L20s').pack
|
|
|
|
]
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, height: int, claim_hash: bytes):
|
|
|
|
return super().pack_key(height, claim_hash)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> TrendingNotificationKey:
|
|
|
|
return TrendingNotificationKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, previous_amount: int, new_amount: int) -> bytes:
|
|
|
|
return super().pack_value(previous_amount, new_amount)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> TrendingNotificationValue:
|
|
|
|
return TrendingNotificationValue(*super().unpack_value(data))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, height, claim_hash, previous_amount, new_amount):
|
|
|
|
return cls.pack_key(height, claim_hash), cls.pack_value(previous_amount, new_amount)
|
|
|
|
|
|
|
|
|
|
|
|
class TouchedHashXKey(NamedTuple):
|
|
|
|
height: int
|
|
|
|
|
|
|
|
|
|
|
|
class TouchedHashXValue(NamedTuple):
|
|
|
|
touched_hashXs: typing.List[bytes]
|
|
|
|
|
2022-01-06 18:28:15 +01:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.__class__.__name__}(touched_hashXs=[{', '.join(map(lambda x: x.hex(), self.touched_hashXs))}])"
|
|
|
|
|
2021-12-01 22:47:29 +01:00
|
|
|
|
|
|
|
class TouchedHashXPrefixRow(PrefixRow):
|
|
|
|
prefix = DB_PREFIXES.touched_hashX.value
|
|
|
|
key_struct = struct.Struct(b'>L')
|
|
|
|
|
|
|
|
key_part_lambdas = [
|
|
|
|
lambda: b'',
|
|
|
|
struct.Struct(b'>L').pack
|
|
|
|
]
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_key(cls, height: int):
|
|
|
|
return super().pack_key(height)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_key(cls, key: bytes) -> TouchedHashXKey:
|
|
|
|
return TouchedHashXKey(*super().unpack_key(key))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_value(cls, touched: typing.List[bytes]) -> bytes:
|
|
|
|
assert all(map(lambda item: len(item) == 11, touched))
|
|
|
|
return b''.join(touched)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def unpack_value(cls, data: bytes) -> TouchedHashXValue:
|
|
|
|
return TouchedHashXValue([data[idx*11:(idx*11)+11] for idx in range(len(data) // 11)])
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def pack_item(cls, height: int, touched: typing.List[bytes]):
|
|
|
|
return cls.pack_key(height), cls.pack_value(touched)
|
|
|
|
|
|
|
|
|
2022-01-31 21:48:04 +01:00
|
|
|
class PrefixDB(BasePrefixDB):
|
2021-10-06 18:07:42 +02:00
|
|
|
def __init__(self, path: str, cache_mb: int = 128, reorg_limit: int = 200, max_open_files: int = 512,
|
2021-11-08 20:18:22 +01:00
|
|
|
secondary_path: str = '', unsafe_prefixes: Optional[typing.Set[bytes]] = None):
|
2022-01-15 19:45:41 +01:00
|
|
|
super().__init__(path, max_open_files=max_open_files, secondary_path=secondary_path,
|
|
|
|
max_undo_depth=reorg_limit, unsafe_prefixes=unsafe_prefixes)
|
|
|
|
db = self._db
|
2021-10-04 22:38:28 +02:00
|
|
|
self.claim_to_support = ClaimToSupportPrefixRow(db, self._op_stack)
|
|
|
|
self.support_to_claim = SupportToClaimPrefixRow(db, self._op_stack)
|
|
|
|
self.claim_to_txo = ClaimToTXOPrefixRow(db, self._op_stack)
|
|
|
|
self.txo_to_claim = TXOToClaimPrefixRow(db, self._op_stack)
|
|
|
|
self.claim_to_channel = ClaimToChannelPrefixRow(db, self._op_stack)
|
|
|
|
self.channel_to_claim = ChannelToClaimPrefixRow(db, self._op_stack)
|
|
|
|
self.claim_short_id = ClaimShortIDPrefixRow(db, self._op_stack)
|
|
|
|
self.claim_expiration = ClaimExpirationPrefixRow(db, self._op_stack)
|
|
|
|
self.claim_takeover = ClaimTakeoverPrefixRow(db, self._op_stack)
|
|
|
|
self.pending_activation = PendingActivationPrefixRow(db, self._op_stack)
|
|
|
|
self.activated = ActivatedPrefixRow(db, self._op_stack)
|
|
|
|
self.active_amount = ActiveAmountPrefixRow(db, self._op_stack)
|
|
|
|
self.effective_amount = EffectiveAmountPrefixRow(db, self._op_stack)
|
|
|
|
self.repost = RepostPrefixRow(db, self._op_stack)
|
|
|
|
self.reposted_claim = RepostedPrefixRow(db, self._op_stack)
|
|
|
|
self.undo = UndoPrefixRow(db, self._op_stack)
|
|
|
|
self.utxo = UTXOPrefixRow(db, self._op_stack)
|
|
|
|
self.hashX_utxo = HashXUTXOPrefixRow(db, self._op_stack)
|
|
|
|
self.hashX_history = HashXHistoryPrefixRow(db, self._op_stack)
|
|
|
|
self.block_hash = BlockHashPrefixRow(db, self._op_stack)
|
|
|
|
self.tx_count = TxCountPrefixRow(db, self._op_stack)
|
|
|
|
self.tx_hash = TXHashPrefixRow(db, self._op_stack)
|
|
|
|
self.tx_num = TXNumPrefixRow(db, self._op_stack)
|
|
|
|
self.tx = TXPrefixRow(db, self._op_stack)
|
|
|
|
self.header = BlockHeaderPrefixRow(db, self._op_stack)
|
|
|
|
self.touched_or_deleted = TouchedOrDeletedPrefixRow(db, self._op_stack)
|
|
|
|
self.channel_count = ChannelCountPrefixRow(db, self._op_stack)
|
|
|
|
self.db_state = DBStatePrefixRow(db, self._op_stack)
|
|
|
|
self.support_amount = SupportAmountPrefixRow(db, self._op_stack)
|
2021-10-12 06:03:11 +02:00
|
|
|
self.block_txs = BlockTxsPrefixRow(db, self._op_stack)
|
2021-12-01 22:47:29 +01:00
|
|
|
self.mempool_tx = MempoolTXPrefixRow(db, self._op_stack)
|
|
|
|
self.trending_notification = TrendingNotificationPrefixRow(db, self._op_stack)
|
|
|
|
self.touched_hashX = TouchedHashXPrefixRow(db, self._op_stack)
|
2021-06-22 23:25:23 +02:00
|
|
|
|
|
|
|
|
2021-06-28 20:20:33 +02:00
|
|
|
def auto_decode_item(key: bytes, value: bytes) -> Union[Tuple[NamedTuple, NamedTuple], Tuple[bytes, bytes]]:
|
|
|
|
try:
|
2021-08-14 02:02:42 +02:00
|
|
|
return ROW_TYPES[key[:1]].unpack_item(key, value)
|
2021-06-28 20:20:33 +02:00
|
|
|
except KeyError:
|
|
|
|
return key, value
|