1
0
pbcabi/pbcabi/data.py
2023-06-20 11:15:13 +02:00

209 lines
4.2 KiB
Python

'''
Definitions of several useful types commonly seen on Partisia Blockchain.
Follows the ABI specification quite closely. The full ABI specification can be found at:
https://partisiablockchain.gitlab.io/documentation/abiv.html
'''
import datetime
import dataclasses
from typing import Mapping, Collection, Optional, Union
from enum import Enum
import enforce_typing
def hexformat(bts: bytes, sep=''):
return sep.join('{:02X}'.format(c) for c in bts)
class AddressType(Enum):
'''
Type of a PBC BlockchainAddress.
'''
ACCOUNT = 0x00
CONTRACT_SYSTEM = 0x01
CONTRACT_PUBLIC = 0x02
CONTRACT_ZK = 0x03
CONTRACT_GOVERANCE = 0x04
def human_name(self):
'''
Produces a human-readable name for self.
'''
return ADDRESS_TYPES[self]
ADDRESS_TYPES = {
AddressType.ACCOUNT: 'Account',
AddressType.CONTRACT_SYSTEM: 'System Contract',
AddressType.CONTRACT_PUBLIC: 'Public Contract',
AddressType.CONTRACT_ZK: 'ZK Contract',
AddressType.CONTRACT_GOVERANCE: 'Governance Contract',
}
@enforce_typing.enforce_types
@dataclasses.dataclass(frozen=True, order=True)
class ByteData(object):
'''
Supertype for several built-in PBC types.
'''
data: bytes
def to_hex(self):
'''
Formats this byte data as a hex string.
'''
return hexformat(self.data)
def short_str(self):
'''
Formats this byte data as a short hex string.
'''
long = str(self)
return '{}..{}'.format(long[:4], long[-4:])
@enforce_typing.enforce_types
@dataclasses.dataclass(frozen=True, order=True)
class BlockchainAddress(ByteData):
'''
Address on PBC.
'''
BYTE_LEN = 21
def __post_init__(self):
assert len(self.data) == BlockchainAddress.BYTE_LEN
assert self.type()
@staticmethod
def read_from(reader):
return BlockchainAddress(reader.readBytes(BlockchainAddress.BYTE_LEN))
@staticmethod
def from_hex_hash(s):
return BlockchainAddress(bytes.fromhex(s))
def type(self) -> AddressType:
return AddressType(self.data[0])
def __repr__(self):
return self.to_hex()
def __str__(self):
return repr(self)
@enforce_typing.enforce_types
@dataclasses.dataclass(frozen=True, order=True)
class Hash(ByteData):
'''
Hash.
'''
data: bytes
BYTE_LEN = 32
@staticmethod
def read_from(reader):
return Hash(reader.readBytes(Hash.BYTE_LEN))
@classmethod
def from_hex(cls, s):
return Hash(bytes.fromhex(s))
def __repr__(self):
return self.to_hex()
def __str__(self):
return repr(self)
@enforce_typing.enforce_types
@dataclasses.dataclass(frozen=True, order=True)
class PublicKey(ByteData):
'''
PBC public key.
'''
data: bytes
BYTE_LEN = 33
@staticmethod
def read_from(reader):
return PublicKey(reader.readBytes(PublicKey.BYTE_LEN))
def __repr__(self):
return self.to_hex()
def __str__(self):
return repr(self)
@enforce_typing.enforce_types
@dataclasses.dataclass(frozen=True, order=True)
class Signature(ByteData):
'''
Message signature on PBC.
'''
data: bytes
BYTE_LEN = 65
@staticmethod
def read_from(reader):
return Signature(reader.readBytes(Signature.BYTE_LEN))
def __repr__(self):
return self.to_hex()
def __str__(self):
return repr(self)
@enforce_typing.enforce_types
@dataclasses.dataclass(frozen=True, order=True)
class BlsPublicKey(ByteData):
'''
BLS Public Key.
'''
data: bytes
BYTE_LEN = 96
@staticmethod
def read_from(reader):
return BlsPublicKey(reader.readBytes(BlsPublicKey.BYTE_LEN))
def __repr__(self):
return self.to_hex()
def __str__(self):
return repr(self)
@enforce_typing.enforce_types
@dataclasses.dataclass(frozen=True, order=True)
class BlsSignature(ByteData):
'''
BLS signature.
'''
data: bytes
BYTE_LEN = 48
@staticmethod
def read_from(reader):
return BlsSignature(reader.readBytes(BlsSignature.BYTE_LEN))
def __repr__(self):
return self.to_hex()
def __str__(self):
return repr(self)