merge data_layer_types into data_layer_util

This commit is contained in:
Kyle Altendorf
2022-07-12 19:14:57 -04:00
parent 9e1e7a3e95
commit 2e1646d009
3 changed files with 199 additions and 200 deletions
-197
View File
@@ -1,197 +0,0 @@
from dataclasses import dataclass, field
from enum import IntEnum
from typing import Dict, List, Optional, Tuple, Type, Union
import aiosqlite as aiosqlite
from chia.types.blockchain_format.program import Program
from chia.types.blockchain_format.sized_bytes import bytes32
from chia.util.byte_types import hexstr_to_bytes
from chia.util.streamable import Streamable, streamable
class Status(IntEnum):
PENDING = 1
COMMITTED = 2
class NodeType(IntEnum):
# EMPTY = 0
INTERNAL = 1
TERMINAL = 2
class Side(IntEnum):
LEFT = 0
RIGHT = 1
class OperationType(IntEnum):
INSERT = 0
DELETE = 1
class CommitState(IntEnum):
OPEN = 0
FINALIZED = 1
ROLLED_BACK = 2
Node = Union["TerminalNode", "InternalNode"]
@dataclass(frozen=True)
class TerminalNode:
hash: bytes32
# generation: int
key: bytes
value: bytes
atom: None = field(init=False, default=None)
@property
def pair(self) -> Tuple[bytes32, bytes32]:
return Program.to(self.key), Program.to(self.value)
# It is unclear how to properly satisfy the generic Row normally, let alone for
# dict-like rows. https://github.com/python/typeshed/issues/8027
@classmethod
def from_row(cls, row: aiosqlite.Row) -> "TerminalNode": # type: ignore[type-arg]
return cls(
hash=bytes32.fromhex(row["hash"]),
# generation=row["generation"],
key=bytes.fromhex(row["key"]),
value=bytes.fromhex(row["value"]),
)
@dataclass(frozen=True)
class ProofOfInclusionLayer:
other_hash_side: Side
other_hash: bytes32
combined_hash: bytes32
@classmethod
def from_internal_node(
cls,
internal_node: "InternalNode",
traversal_child_hash: bytes32,
) -> "ProofOfInclusionLayer":
return ProofOfInclusionLayer(
other_hash_side=internal_node.other_child_side(hash=traversal_child_hash),
other_hash=internal_node.other_child_hash(hash=traversal_child_hash),
combined_hash=internal_node.hash,
)
other_side_to_bit = {Side.LEFT: 1, Side.RIGHT: 0}
@dataclass(frozen=True)
class ProofOfInclusion:
node_hash: bytes32
root_hash: bytes32
# children before parents
layers: List[ProofOfInclusionLayer]
def as_program(self) -> Program:
sibling_sides = sum(
other_side_to_bit[layer.other_hash_side] << index for index, layer in enumerate(self.layers)
)
sibling_hashes = [layer.other_hash for layer in self.layers]
# https://github.com/Chia-Network/clvm/pull/102
# https://github.com/Chia-Network/clvm/pull/106
return Program.to([sibling_sides, sibling_hashes]) # type: ignore[no-any-return]
@dataclass(frozen=True)
class InternalNode:
hash: bytes32
# generation: int
left_hash: bytes32
right_hash: bytes32
pair: Optional[Tuple[Node, Node]] = None
atom: None = None
# It is unclear how to properly satisfy the generic Row normally, let alone for
# dict-like rows. https://github.com/python/typeshed/issues/8027
@classmethod
def from_row(cls, row: aiosqlite.Row) -> "InternalNode": # type: ignore[type-arg]
return cls(
hash=bytes32(hexstr_to_bytes(row["hash"])),
# generation=row["generation"],
left_hash=bytes32(hexstr_to_bytes(row["left"])),
right_hash=bytes32(hexstr_to_bytes(row["right"])),
)
def other_child_hash(self, hash: bytes32) -> bytes32:
if self.left_hash == hash:
return self.right_hash
elif self.right_hash == hash:
return self.left_hash
# TODO: real exception considerations
raise Exception("provided hash not present")
def other_child_side(self, hash: bytes32) -> Side:
if self.left_hash == hash:
return Side.RIGHT
elif self.right_hash == hash:
return Side.LEFT
# TODO: real exception considerations
raise Exception("provided hash not present")
@dataclass(frozen=True)
class Root:
tree_id: bytes32
node_hash: Optional[bytes32]
generation: int
status: Status
# It is unclear how to properly satisfy the generic Row normally, let alone for
# dict-like rows. https://github.com/python/typeshed/issues/8027
@classmethod
def from_row(cls, row: aiosqlite.Row) -> "Root": # type: ignore[type-arg]
raw_node_hash = row["node_hash"]
if raw_node_hash is None:
node_hash = None
else:
node_hash = bytes32(hexstr_to_bytes(raw_node_hash))
return cls(
tree_id=bytes32(hexstr_to_bytes(row["tree_id"])),
node_hash=node_hash,
generation=row["generation"],
status=Status(row["status"]),
)
node_type_to_class: Dict[NodeType, Union[Type[InternalNode], Type[TerminalNode]]] = {
NodeType.INTERNAL: InternalNode,
NodeType.TERMINAL: TerminalNode,
}
@dataclass(frozen=True)
class Subscription:
tree_id: bytes32
urls: List[str]
@dataclass(frozen=True)
class DiffData:
type: OperationType
key: bytes
value: bytes
@streamable
@dataclass(frozen=True)
class SerializedNode(Streamable):
is_terminal: bool
value1: bytes
value2: bytes
+195 -1
View File
@@ -1,9 +1,16 @@
from __future__ import annotations
from dataclasses import dataclass, field
from enum import IntEnum
from typing import Dict, List, Optional, Tuple, Type, Union
# TODO: remove or formalize this
import aiosqlite as aiosqlite
from chia.data_layer.data_layer_types import Node, node_type_to_class
from chia.types.blockchain_format.program import Program
from chia.types.blockchain_format.sized_bytes import bytes32
from chia.util.byte_types import hexstr_to_bytes
from chia.util.streamable import Streamable, streamable
def internal_hash(left_hash: bytes32, right_hash: bytes32) -> bytes32:
@@ -35,3 +42,190 @@ async def _debug_dump(db: aiosqlite.Connection, description: str = "") -> None:
def row_to_node(row: aiosqlite.Row) -> Node: # type: ignore[type-arg]
cls = node_type_to_class[row["node_type"]]
return cls.from_row(row=row)
class Status(IntEnum):
PENDING = 1
COMMITTED = 2
class NodeType(IntEnum):
# EMPTY = 0
INTERNAL = 1
TERMINAL = 2
class Side(IntEnum):
LEFT = 0
RIGHT = 1
class OperationType(IntEnum):
INSERT = 0
DELETE = 1
class CommitState(IntEnum):
OPEN = 0
FINALIZED = 1
ROLLED_BACK = 2
Node = Union["TerminalNode", "InternalNode"]
@dataclass(frozen=True)
class TerminalNode:
hash: bytes32
# generation: int
key: bytes
value: bytes
atom: None = field(init=False, default=None)
@property
def pair(self) -> Tuple[bytes32, bytes32]:
return Program.to(self.key), Program.to(self.value)
# It is unclear how to properly satisfy the generic Row normally, let alone for
# dict-like rows. https://github.com/python/typeshed/issues/8027
@classmethod
def from_row(cls, row: aiosqlite.Row) -> "TerminalNode": # type: ignore[type-arg]
return cls(
hash=bytes32.fromhex(row["hash"]),
# generation=row["generation"],
key=bytes.fromhex(row["key"]),
value=bytes.fromhex(row["value"]),
)
@dataclass(frozen=True)
class ProofOfInclusionLayer:
other_hash_side: Side
other_hash: bytes32
combined_hash: bytes32
@classmethod
def from_internal_node(
cls,
internal_node: "InternalNode",
traversal_child_hash: bytes32,
) -> "ProofOfInclusionLayer":
return ProofOfInclusionLayer(
other_hash_side=internal_node.other_child_side(hash=traversal_child_hash),
other_hash=internal_node.other_child_hash(hash=traversal_child_hash),
combined_hash=internal_node.hash,
)
other_side_to_bit = {Side.LEFT: 1, Side.RIGHT: 0}
@dataclass(frozen=True)
class ProofOfInclusion:
node_hash: bytes32
root_hash: bytes32
# children before parents
layers: List[ProofOfInclusionLayer]
def as_program(self) -> Program:
sibling_sides = sum(
other_side_to_bit[layer.other_hash_side] << index for index, layer in enumerate(self.layers)
)
sibling_hashes = [layer.other_hash for layer in self.layers]
# https://github.com/Chia-Network/clvm/pull/102
# https://github.com/Chia-Network/clvm/pull/106
return Program.to([sibling_sides, sibling_hashes]) # type: ignore[no-any-return]
@dataclass(frozen=True)
class InternalNode:
hash: bytes32
# generation: int
left_hash: bytes32
right_hash: bytes32
pair: Optional[Tuple[Node, Node]] = None
atom: None = None
# It is unclear how to properly satisfy the generic Row normally, let alone for
# dict-like rows. https://github.com/python/typeshed/issues/8027
@classmethod
def from_row(cls, row: aiosqlite.Row) -> "InternalNode": # type: ignore[type-arg]
return cls(
hash=bytes32(hexstr_to_bytes(row["hash"])),
# generation=row["generation"],
left_hash=bytes32(hexstr_to_bytes(row["left"])),
right_hash=bytes32(hexstr_to_bytes(row["right"])),
)
def other_child_hash(self, hash: bytes32) -> bytes32:
if self.left_hash == hash:
return self.right_hash
elif self.right_hash == hash:
return self.left_hash
# TODO: real exception considerations
raise Exception("provided hash not present")
def other_child_side(self, hash: bytes32) -> Side:
if self.left_hash == hash:
return Side.RIGHT
elif self.right_hash == hash:
return Side.LEFT
# TODO: real exception considerations
raise Exception("provided hash not present")
@dataclass(frozen=True)
class Root:
tree_id: bytes32
node_hash: Optional[bytes32]
generation: int
status: Status
# It is unclear how to properly satisfy the generic Row normally, let alone for
# dict-like rows. https://github.com/python/typeshed/issues/8027
@classmethod
def from_row(cls, row: aiosqlite.Row) -> "Root": # type: ignore[type-arg]
raw_node_hash = row["node_hash"]
if raw_node_hash is None:
node_hash = None
else:
node_hash = bytes32(hexstr_to_bytes(raw_node_hash))
return cls(
tree_id=bytes32(hexstr_to_bytes(row["tree_id"])),
node_hash=node_hash,
generation=row["generation"],
status=Status(row["status"]),
)
node_type_to_class: Dict[NodeType, Union[Type[InternalNode], Type[TerminalNode]]] = {
NodeType.INTERNAL: InternalNode,
NodeType.TERMINAL: TerminalNode,
}
@dataclass(frozen=True)
class Subscription:
tree_id: bytes32
urls: List[str]
@dataclass(frozen=True)
class DiffData:
type: OperationType
key: bytes
value: bytes
@streamable
@dataclass(frozen=True)
class SerializedNode(Streamable):
is_terminal: bool
value1: bytes
value2: bytes
+4 -2
View File
@@ -12,7 +12,7 @@ from chia.data_layer.data_layer_errors import (
TerminalLeftRightError,
TreeGenerationIncrementingError,
)
from chia.data_layer.data_layer_types import (
from chia.data_layer.data_layer_util import (
InternalNode,
Node,
NodeType,
@@ -26,8 +26,10 @@ from chia.data_layer.data_layer_types import (
DiffData,
OperationType,
SerializedNode,
internal_hash,
leaf_hash,
row_to_node,
)
from chia.data_layer.data_layer_util import internal_hash, leaf_hash, row_to_node
from chia.types.blockchain_format.program import Program
from chia.types.blockchain_format.sized_bytes import bytes32
from chia.util.byte_types import hexstr_to_bytes