|
|
@ -30,6 +30,7 @@ Anything coin-specific should go in this file and be subclassed where |
|
|
|
necessary for appropriate handling. |
|
|
|
''' |
|
|
|
|
|
|
|
from collections import namedtuple |
|
|
|
import re |
|
|
|
import struct |
|
|
|
from decimal import Decimal |
|
|
@ -40,6 +41,8 @@ from lib.hash import Base58, hash160, double_sha256, hash_to_str |
|
|
|
from lib.script import ScriptPubKey |
|
|
|
from lib.tx import Deserializer, DeserializerSegWit |
|
|
|
|
|
|
|
Block = namedtuple("Block", "header transactions") |
|
|
|
|
|
|
|
|
|
|
|
class CoinError(Exception): |
|
|
|
'''Exception raised for coin-related errors.''' |
|
|
@ -53,6 +56,8 @@ class Coin(object): |
|
|
|
RPC_URL_REGEX = re.compile('.+@(\[[0-9a-fA-F:]+\]|[^:]+)(:[0-9]+)?') |
|
|
|
VALUE_PER_COIN = 100000000 |
|
|
|
CHUNK_SIZE = 2016 |
|
|
|
BASIC_HEADER_SIZE = 80 |
|
|
|
STATIC_BLOCK_HEADERS = True |
|
|
|
IRC_PREFIX = None |
|
|
|
IRC_SERVER = "irc.freenode.net" |
|
|
|
IRC_PORT = 6667 |
|
|
@ -232,29 +237,33 @@ class Coin(object): |
|
|
|
return header[4:36] |
|
|
|
|
|
|
|
@classmethod |
|
|
|
def header_offset(cls, height): |
|
|
|
def static_header_offset(cls, height): |
|
|
|
'''Given a header height return its offset in the headers file. |
|
|
|
|
|
|
|
If header sizes change at some point, this is the only code |
|
|
|
that needs updating.''' |
|
|
|
return height * 80 |
|
|
|
assert cls.STATIC_BLOCK_HEADERS |
|
|
|
return height * cls.BASIC_HEADER_SIZE |
|
|
|
|
|
|
|
@classmethod |
|
|
|
def header_len(cls, height): |
|
|
|
def static_header_len(cls, height): |
|
|
|
'''Given a header height return its length.''' |
|
|
|
return cls.header_offset(height + 1) - cls.header_offset(height) |
|
|
|
return cls.static_header_offset(height + 1) \ |
|
|
|
- cls.static_header_offset(height) |
|
|
|
|
|
|
|
@classmethod |
|
|
|
def block_header(cls, block, height): |
|
|
|
'''Returns the block header given a block and its height.''' |
|
|
|
return block[:cls.header_len(height)] |
|
|
|
return block[:cls.static_header_len(height)] |
|
|
|
|
|
|
|
@classmethod |
|
|
|
def block_txs(cls, block, height): |
|
|
|
'''Returns a list of (deserialized_tx, tx_hash) pairs given a |
|
|
|
def block_full(cls, block, height): |
|
|
|
'''Returns (header, [(deserialized_tx, tx_hash), ...]) given a |
|
|
|
block and its height.''' |
|
|
|
header = cls.block_header(block, height) |
|
|
|
deserializer = cls.deserializer() |
|
|
|
return deserializer(block[cls.header_len(height):]).read_block() |
|
|
|
txs = deserializer(block[len(header):]).read_tx_block() |
|
|
|
return Block(header, txs) |
|
|
|
|
|
|
|
@classmethod |
|
|
|
def decimal_value(cls, value): |
|
|
@ -635,8 +644,9 @@ class FairCoin(Coin): |
|
|
|
P2PKH_VERBYTE = bytes.fromhex("5f") |
|
|
|
P2SH_VERBYTE = bytes.fromhex("24") |
|
|
|
WIF_BYTE = bytes.fromhex("df") |
|
|
|
GENESIS_HASH=('1f701f2b8de1339dc0ec908f3fb6e9b0' |
|
|
|
'b870b6f20ba893e120427e42bbc048d7') |
|
|
|
GENESIS_HASH = ('1f701f2b8de1339dc0ec908f3fb6e9b0' |
|
|
|
'b870b6f20ba893e120427e42bbc048d7') |
|
|
|
BASIC_HEADER_SIZE = 108 |
|
|
|
TX_COUNT = 1000 |
|
|
|
TX_COUNT_HEIGHT = 1000 |
|
|
|
TX_PER_BLOCK = 1 |
|
|
@ -650,22 +660,14 @@ class FairCoin(Coin): |
|
|
|
] |
|
|
|
|
|
|
|
@classmethod |
|
|
|
def header_offset(cls, height): |
|
|
|
'''Given a header height return its offset in the headers file. |
|
|
|
If header sizes change at some point, this is the only code |
|
|
|
that needs updating.''' |
|
|
|
return height * 108 |
|
|
|
|
|
|
|
@classmethod |
|
|
|
def block_txs(cls, block, height): |
|
|
|
'''Returns a list of (deserialized_tx, tx_hash) pairs given a |
|
|
|
def block_full(cls, block, height): |
|
|
|
'''Returns (header, [(deserialized_tx, tx_hash), ...]) given a |
|
|
|
block and its height.''' |
|
|
|
|
|
|
|
if height == 0: |
|
|
|
return [] |
|
|
|
|
|
|
|
deserializer = cls.deserializer() |
|
|
|
return deserializer(block[cls.header_len(height):]).read_block() |
|
|
|
if height > 0: |
|
|
|
return cls.block_full(block, height) |
|
|
|
else: |
|
|
|
return Block(cls.block_header(block, height), []) |
|
|
|
|
|
|
|
@classmethod |
|
|
|
def electrum_header(cls, header, height): |
|
|
|