Compare commits
4 commits
master
...
signed_sup
Author | SHA1 | Date | |
---|---|---|---|
|
82cdc8c86a | ||
|
3f6493dc5c | ||
|
fb4d60f02f | ||
|
df60fa7ab2 |
9 changed files with 72 additions and 168 deletions
132
.travis.yml
132
.travis.yml
|
@ -5,137 +5,13 @@ python: "3.7"
|
||||||
jobs:
|
jobs:
|
||||||
include:
|
include:
|
||||||
|
|
||||||
- stage: code quality
|
- stage: build
|
||||||
name: "pylint & mypy"
|
name: "Wallet Server Docker Image - Segwit Fix"
|
||||||
install:
|
|
||||||
- make install
|
|
||||||
script: make lint
|
|
||||||
|
|
||||||
- stage: test
|
|
||||||
name: "LBRY Unit Tests"
|
|
||||||
install:
|
|
||||||
- make install
|
|
||||||
script:
|
|
||||||
- cd lbry && HOME=/tmp coverage run -p --source=lbry -m unittest discover -vv tests.unit
|
|
||||||
after_success:
|
|
||||||
- coverage combine lbry/
|
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
|
||||||
|
|
||||||
- name: "LBRY Integration Tests"
|
|
||||||
install:
|
|
||||||
- pip install coverage tox-travis
|
|
||||||
- sudo mount -o mode=1777,nosuid,nodev -t tmpfs tmpfs /tmp
|
|
||||||
script: cd lbry && tox
|
|
||||||
after_success:
|
|
||||||
- coverage combine lbry
|
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
|
||||||
|
|
||||||
- &torba-tests
|
|
||||||
name: "Torba Unit Tests"
|
|
||||||
env: TESTTYPE=unit
|
|
||||||
install:
|
|
||||||
- pip install coverage tox-travis
|
|
||||||
script: cd torba && tox
|
|
||||||
after_success:
|
|
||||||
- coverage combine torba/tests
|
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
|
||||||
|
|
||||||
- <<: *torba-tests
|
|
||||||
name: "Torba Integration Tests"
|
|
||||||
env: TESTTYPE=integration
|
|
||||||
|
|
||||||
- name: "Run Examples"
|
|
||||||
install:
|
|
||||||
- make install
|
|
||||||
script:
|
|
||||||
- cd lbry && HOME=/tmp coverage run -p --source=lbry scripts/generate_json_api.py
|
|
||||||
after_success:
|
|
||||||
- coverage combine lbry
|
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
|
||||||
|
|
||||||
- &build
|
|
||||||
stage: build
|
|
||||||
name: "Linux"
|
|
||||||
env: OS=linux
|
|
||||||
install:
|
|
||||||
- pip install pyinstaller awscli
|
|
||||||
- cd torba && pip install -e . && cd ..
|
|
||||||
- cd lbry
|
|
||||||
- python scripts/set_build.py
|
|
||||||
- pip install -e .
|
|
||||||
script:
|
|
||||||
- pyinstaller -F -n lbrynet lbry/extras/cli.py
|
|
||||||
- cd dist
|
|
||||||
- chmod +x lbrynet
|
|
||||||
- zip -j lbrynet-${OS}.zip lbrynet
|
|
||||||
- shasum -a 256 -b lbrynet-${OS}.zip
|
|
||||||
- ./lbrynet --version
|
|
||||||
after_success:
|
|
||||||
- aws configure set aws_access_key_id $ARTIFACTS_KEY
|
|
||||||
- aws configure set aws_secret_access_key $ARTIFACTS_SECRET
|
|
||||||
- aws configure set region us-east-1
|
|
||||||
- export S3_PATH="daemon/build-${TRAVIS_BUILD_NUMBER}_commit-${TRAVIS_COMMIT:0:7}_branch-${TRAVIS_BRANCH}$([ ! -z ${TRAVIS_TAG} ] && echo _tag-${TRAVIS_TAG})"
|
|
||||||
- aws s3 cp lbrynet-${OS}.zip s3://build.lbry.io/${S3_PATH}/lbrynet-${OS}.zip
|
|
||||||
deploy:
|
|
||||||
provider: releases
|
|
||||||
api_key:
|
|
||||||
secure: "unnR+aSJ1937Cl1PyBBZzGuZvV5W5TGcXELhXTgyOeeI6FgO/j80qmbNxJDA7qdFH/hvVicQFWoflhZu2dxN5rYP5BQJW3q3XoOLY3XAc1s1vicFkwqn3TIfdFiJTz+/D9eBUBBhHKeYFxm3M+thvklTLgjKl6fflh14NfGuNTevK9yQke8wewW3f9UmFTo1qNOPF1OsTZRbwua6oQYa59P+KukoPt4Dsu1VtILtTkj7hfEsUL79cjotwO3gkhYftxbl/xeDSZWOt+9Nhb8ZKmQG/uDx4JiTMm5lWRk4QB7pUujZ1CftxCYWz/lJx9nuJpdCOgP624tcHymErNlD+vGLwMTNslcXGYkAJH6xvGyxBJ+Obc8vRVnZbRM26BfH34TcPK1ueRxHSrDUbzMIIUsgcoZAxBuim8uDPp+K7bGqiygzSs2vQfr9U5Jhe9/F8sPdtNctfJZEfgmthNTeVFjyNsGIfIt754uGSfACqM7wDLh6fbKx7M+FHlNyOdvYCrbKUOAYXmTikYIpVDvlaaeMO+N+uW8Rhvm1j+JU7CVwhMavLySaPVc6Dt5OxiMMmxw9mVrjW9bBPjS5AkrS5MOA13T5wapoLzH6+gE92U4HzA6ilMcwRaQPSFnK2JU7tzyt2Wy1PH4MjHowXI2WyICG1x510dD3tX1P/1px8ro="
|
|
||||||
file: lbrynet-${OS}.zip
|
|
||||||
skip_cleanup: true
|
|
||||||
overwrite: true
|
|
||||||
draft: true
|
|
||||||
on:
|
|
||||||
tags: true
|
|
||||||
|
|
||||||
- <<: *build
|
|
||||||
name: "Mac"
|
|
||||||
os: osx
|
|
||||||
osx_image: xcode8.3
|
|
||||||
language: shell
|
|
||||||
env: OS=mac
|
|
||||||
before_install:
|
|
||||||
- brew uninstall mercurial
|
|
||||||
- brew upgrade python || true
|
|
||||||
- pip3 install --user --upgrade pip virtualenv
|
|
||||||
- /Users/travis/Library/Python/3.7/bin/virtualenv --clear $HOME/venv
|
|
||||||
- source $HOME/venv/bin/activate
|
|
||||||
before_cache:
|
|
||||||
- brew cleanup
|
|
||||||
|
|
||||||
- <<: *build
|
|
||||||
name: "Windows"
|
|
||||||
os: windows
|
|
||||||
language: shell
|
|
||||||
env:
|
|
||||||
- OS=windows
|
|
||||||
- PATH=/c/Python37:/c/Python37/Scripts:/C/Windows/System32/downlevel:$PATH
|
|
||||||
before_install:
|
|
||||||
- choco install python --version=3.7.4 --x86
|
|
||||||
- python -m pip install --upgrade pip
|
|
||||||
- pip install pywin32
|
|
||||||
script:
|
|
||||||
- pyinstaller --additional-hooks-dir=scripts/. --icon=icons/lbry256.ico -F -n lbrynet lbry/extras/cli.py
|
|
||||||
- cd dist
|
|
||||||
- 7z a -tzip lbrynet-windows.zip lbrynet.exe
|
|
||||||
- sha256sum -b lbrynet-windows.zip
|
|
||||||
- ./lbrynet.exe --version
|
|
||||||
- if: tag IS present
|
|
||||||
stage: build
|
|
||||||
name: "Wallet Server Docker Image - Tagged Release"
|
|
||||||
script:
|
script:
|
||||||
- set -e
|
- set -e
|
||||||
- echo "$DOCKER_PASSWORD" | docker login --username "$DOCKER_USERNAME" --password-stdin
|
- echo "$DOCKER_PASSWORD" | docker login --username "$DOCKER_USERNAME" --password-stdin
|
||||||
- travis_retry docker build -t lbry/wallet-server:$TRAVIS_TAG -f lbry/scripts/Dockerfile.wallet_server .
|
- travis_retry docker build -t lbry/wallet-server:segwit -f lbry/scripts/Dockerfile.wallet_server .
|
||||||
- docker push lbry/wallet-server:$TRAVIS_TAG
|
- docker push lbry/wallet-server:segwit
|
||||||
|
|
||||||
- if: tag IS blank AND branch = master AND NOT type IN (pull_request)
|
|
||||||
stage: build
|
|
||||||
name: "Wallet Server Docker Image - Master"
|
|
||||||
script:
|
|
||||||
- set -e
|
|
||||||
- echo "$DOCKER_PASSWORD" | docker login --username "$DOCKER_USERNAME" --password-stdin
|
|
||||||
- travis_retry docker build -t lbry/wallet-server:master -f lbry/scripts/Dockerfile.wallet_server .
|
|
||||||
- docker push lbry/wallet-server:master
|
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
|
|
|
@ -3277,7 +3277,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
||||||
@requires(WALLET_COMPONENT)
|
@requires(WALLET_COMPONENT)
|
||||||
async def jsonrpc_support_create(
|
async def jsonrpc_support_create(
|
||||||
self, claim_id, amount, tip=False, account_id=None, wallet_id=None, funding_account_ids=None,
|
self, claim_id, amount, tip=False, account_id=None, wallet_id=None, funding_account_ids=None,
|
||||||
preview=False, blocking=False):
|
channel_id=None, preview=False, blocking=False):
|
||||||
"""
|
"""
|
||||||
Create a support or a tip for name claim.
|
Create a support or a tip for name claim.
|
||||||
|
|
||||||
|
@ -3301,6 +3301,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
||||||
wallet = self.wallet_manager.get_wallet_or_default(wallet_id)
|
wallet = self.wallet_manager.get_wallet_or_default(wallet_id)
|
||||||
assert not wallet.is_locked, "Cannot spend funds with locked wallet, unlock first."
|
assert not wallet.is_locked, "Cannot spend funds with locked wallet, unlock first."
|
||||||
funding_accounts = wallet.get_accounts_or_all(funding_account_ids)
|
funding_accounts = wallet.get_accounts_or_all(funding_account_ids)
|
||||||
|
channel = await self.get_channel_or_none(wallet, None, channel_id, None, for_signing=True)
|
||||||
amount = self.get_dewies_or_error("amount", amount)
|
amount = self.get_dewies_or_error("amount", amount)
|
||||||
claim = await self.ledger.get_claim_by_claim_id(wallet.accounts, claim_id)
|
claim = await self.ledger.get_claim_by_claim_id(wallet.accounts, claim_id)
|
||||||
claim_address = claim.get_address(self.ledger)
|
claim_address = claim.get_address(self.ledger)
|
||||||
|
@ -3309,7 +3310,7 @@ class Daemon(metaclass=JSONRPCServerType):
|
||||||
claim_address = await account.receiving.get_or_create_usable_address()
|
claim_address = await account.receiving.get_or_create_usable_address()
|
||||||
|
|
||||||
tx = await Transaction.support(
|
tx = await Transaction.support(
|
||||||
claim.claim_name, claim_id, amount, claim_address, funding_accounts, funding_accounts[0]
|
claim.claim_name, claim_id, amount, claim_address, funding_accounts, funding_accounts[0], channel
|
||||||
)
|
)
|
||||||
|
|
||||||
if not preview:
|
if not preview:
|
||||||
|
|
|
@ -42,6 +42,17 @@ class OutputScript(BaseOutputScript):
|
||||||
SUPPORT_CLAIM_OPCODES + BaseOutputScript.PAY_SCRIPT_HASH.opcodes
|
SUPPORT_CLAIM_OPCODES + BaseOutputScript.PAY_SCRIPT_HASH.opcodes
|
||||||
))
|
))
|
||||||
|
|
||||||
|
SUPPORT_CLAIM_DATA_OPCODES = (
|
||||||
|
OP_SUPPORT_CLAIM, PUSH_SINGLE('claim_name'), PUSH_SINGLE('claim_id'), PUSH_SINGLE('support'),
|
||||||
|
OP_2DROP, OP_2DROP
|
||||||
|
)
|
||||||
|
SUPPORT_CLAIM_DATA_PUBKEY = Template('support_claim+data+pay_pubkey_hash', (
|
||||||
|
SUPPORT_CLAIM_DATA_OPCODES + BaseOutputScript.PAY_PUBKEY_HASH.opcodes
|
||||||
|
))
|
||||||
|
SUPPORT_CLAIM_DATA_SCRIPT = Template('support_claim+data+pay_script_hash', (
|
||||||
|
SUPPORT_CLAIM_DATA_OPCODES + BaseOutputScript.PAY_SCRIPT_HASH.opcodes
|
||||||
|
))
|
||||||
|
|
||||||
UPDATE_CLAIM_OPCODES = (
|
UPDATE_CLAIM_OPCODES = (
|
||||||
OP_UPDATE_CLAIM, PUSH_SINGLE('claim_name'), PUSH_SINGLE('claim_id'), PUSH_SINGLE('claim'),
|
OP_UPDATE_CLAIM, PUSH_SINGLE('claim_name'), PUSH_SINGLE('claim_id'), PUSH_SINGLE('claim'),
|
||||||
OP_2DROP, OP_2DROP
|
OP_2DROP, OP_2DROP
|
||||||
|
@ -73,6 +84,8 @@ class OutputScript(BaseOutputScript):
|
||||||
CLAIM_NAME_SCRIPT,
|
CLAIM_NAME_SCRIPT,
|
||||||
SUPPORT_CLAIM_PUBKEY,
|
SUPPORT_CLAIM_PUBKEY,
|
||||||
SUPPORT_CLAIM_SCRIPT,
|
SUPPORT_CLAIM_SCRIPT,
|
||||||
|
SUPPORT_CLAIM_DATA_PUBKEY,
|
||||||
|
SUPPORT_CLAIM_DATA_SCRIPT,
|
||||||
UPDATE_CLAIM_PUBKEY,
|
UPDATE_CLAIM_PUBKEY,
|
||||||
UPDATE_CLAIM_SCRIPT,
|
UPDATE_CLAIM_SCRIPT,
|
||||||
SELL_CLAIM, SELL_SCRIPT,
|
SELL_CLAIM, SELL_SCRIPT,
|
||||||
|
@ -104,6 +117,16 @@ class OutputScript(BaseOutputScript):
|
||||||
'pubkey_hash': pubkey_hash
|
'pubkey_hash': pubkey_hash
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def pay_support_data_pubkey_hash(
|
||||||
|
cls, claim_name: bytes, claim_id: bytes, support: bytes, pubkey_hash: bytes):
|
||||||
|
return cls(template=cls.SUPPORT_CLAIM_DATA_PUBKEY, values={
|
||||||
|
'claim_name': claim_name,
|
||||||
|
'claim_id': claim_id,
|
||||||
|
'support': support,
|
||||||
|
'pubkey_hash': pubkey_hash
|
||||||
|
})
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def sell_script(cls, price):
|
def sell_script(cls, price):
|
||||||
return cls(template=cls.SELL_SCRIPT, values={
|
return cls(template=cls.SELL_SCRIPT, values={
|
||||||
|
|
|
@ -5,6 +5,7 @@ from torba.server.script import ScriptPubKey, OpCodes
|
||||||
from torba.server.util import cachedproperty
|
from torba.server.util import cachedproperty
|
||||||
from torba.server.hash import hash_to_hex_str, HASHX_LEN
|
from torba.server.hash import hash_to_hex_str, HASHX_LEN
|
||||||
from torba.server.coins import Coin, CoinError
|
from torba.server.coins import Coin, CoinError
|
||||||
|
from torba.server.tx import DeserializerSegWit
|
||||||
|
|
||||||
from lbry.wallet.script import OutputScript
|
from lbry.wallet.script import OutputScript
|
||||||
from .session import LBRYElectrumX, LBRYSessionManager
|
from .session import LBRYElectrumX, LBRYSessionManager
|
||||||
|
@ -18,6 +19,7 @@ class LBC(Coin):
|
||||||
SESSIONCLS = LBRYElectrumX
|
SESSIONCLS = LBRYElectrumX
|
||||||
BLOCK_PROCESSOR = LBRYBlockProcessor
|
BLOCK_PROCESSOR = LBRYBlockProcessor
|
||||||
SESSION_MANAGER = LBRYSessionManager
|
SESSION_MANAGER = LBRYSessionManager
|
||||||
|
DESERIALIZER = DeserializerSegWit
|
||||||
DB = LBRYDB
|
DB = LBRYDB
|
||||||
NAME = "LBRY"
|
NAME = "LBRY"
|
||||||
SHORTNAME = "LBC"
|
SHORTNAME = "LBC"
|
||||||
|
|
|
@ -649,7 +649,7 @@ class SQLDB:
|
||||||
body_timer = timer.add_timer('body')
|
body_timer = timer.add_timer('body')
|
||||||
for position, (etx, txid) in enumerate(all_txs):
|
for position, (etx, txid) in enumerate(all_txs):
|
||||||
tx = timer.run(
|
tx = timer.run(
|
||||||
Transaction, etx.serialize(), height=height, position=position
|
Transaction, etx.raw, height=height, position=position
|
||||||
)
|
)
|
||||||
# Inputs
|
# Inputs
|
||||||
spent_claims, spent_supports, spent_others = timer.run(
|
spent_claims, spent_supports, spent_others = timer.run(
|
||||||
|
|
|
@ -194,6 +194,14 @@ class Output(BaseOutput):
|
||||||
script = cls.script_class.pay_support_pubkey_hash(claim_name.encode(), unhexlify(claim_id)[::-1], pubkey_hash)
|
script = cls.script_class.pay_support_pubkey_hash(claim_name.encode(), unhexlify(claim_id)[::-1], pubkey_hash)
|
||||||
return cls(amount, script)
|
return cls(amount, script)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def pay_support_data_pubkey_hash(
|
||||||
|
cls, amount: int, claim_name: str, claim_id: str, support: bytes, pubkey_hash: bytes) -> 'Output':
|
||||||
|
script = OutputScript.pay_support_data_pubkey_hash(
|
||||||
|
claim_name.encode(), unhexlify(claim_id)[::-1], support, pubkey_hash
|
||||||
|
)
|
||||||
|
return cls(amount, script)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def add_purchase_data(cls, purchase: Purchase) -> 'Output':
|
def add_purchase_data(cls, purchase: Purchase) -> 'Output':
|
||||||
script = cls.script_class.return_data(purchase)
|
script = cls.script_class.return_data(purchase)
|
||||||
|
@ -287,8 +295,13 @@ class Transaction(BaseTransaction):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def support(cls, claim_name: str, claim_id: str, amount: int, holding_address: str,
|
def support(cls, claim_name: str, claim_id: str, amount: int, holding_address: str,
|
||||||
funding_accounts: List[Account], change_account: Account):
|
funding_accounts: List[Account], change_account: Account, signing_channel: Output = None):
|
||||||
ledger, wallet = cls.ensure_all_have_same_ledger_and_wallet(funding_accounts, change_account)
|
ledger, wallet = cls.ensure_all_have_same_ledger_and_wallet(funding_accounts, change_account)
|
||||||
|
if signing_channel:
|
||||||
|
support_output = Output.pay_support_data_pubkey_hash(
|
||||||
|
amount, claim_name, claim_id, b'beef', ledger.address_to_hash160(holding_address)
|
||||||
|
)
|
||||||
|
else:
|
||||||
support_output = Output.pay_support_pubkey_hash(
|
support_output = Output.pay_support_pubkey_hash(
|
||||||
amount, claim_name, claim_id, ledger.address_to_hash160(holding_address)
|
amount, claim_name, claim_id, ledger.address_to_hash160(holding_address)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1211,3 +1211,11 @@ class SupportCommands(CommandTestCase):
|
||||||
self.assertFalse(txs2[0]['support_info'][0]['is_tip'])
|
self.assertFalse(txs2[0]['support_info'][0]['is_tip'])
|
||||||
self.assertEqual(txs2[0]['value'], '0.0')
|
self.assertEqual(txs2[0]['value'], '0.0')
|
||||||
self.assertEqual(txs2[0]['fee'], '-0.0001415')
|
self.assertEqual(txs2[0]['fee'], '-0.0001415')
|
||||||
|
|
||||||
|
async def test_signed_supports(self):
|
||||||
|
channel_id = self.get_claim_id(await self.channel_create())
|
||||||
|
stream_id = self.get_claim_id(await self.stream_create())
|
||||||
|
await self.support_create(stream_id, '0.3', channel_id=channel_id)
|
||||||
|
supports = await self.daemon.jsonrpc_support_list()
|
||||||
|
self.assertEqual(1, len(supports['items']))
|
||||||
|
self.assertEqual(supports['items'][0].script.values['support'], b'beef')
|
||||||
|
|
|
@ -400,6 +400,9 @@ class BaseOutputScript(Script):
|
||||||
PAY_SCRIPT_HASH = Template('pay_script_hash', (
|
PAY_SCRIPT_HASH = Template('pay_script_hash', (
|
||||||
OP_HASH160, PUSH_SINGLE('script_hash'), OP_EQUAL
|
OP_HASH160, PUSH_SINGLE('script_hash'), OP_EQUAL
|
||||||
))
|
))
|
||||||
|
PAY_SEGWIT = Template('pay_script_hash+segwit', (
|
||||||
|
OP_0, PUSH_SINGLE('script_hash')
|
||||||
|
))
|
||||||
RETURN_DATA = Template('return_data', (
|
RETURN_DATA = Template('return_data', (
|
||||||
OP_RETURN, PUSH_SINGLE('data')
|
OP_RETURN, PUSH_SINGLE('data')
|
||||||
))
|
))
|
||||||
|
@ -408,6 +411,7 @@ class BaseOutputScript(Script):
|
||||||
PAY_PUBKEY_FULL,
|
PAY_PUBKEY_FULL,
|
||||||
PAY_PUBKEY_HASH,
|
PAY_PUBKEY_HASH,
|
||||||
PAY_SCRIPT_HASH,
|
PAY_SCRIPT_HASH,
|
||||||
|
PAY_SEGWIT,
|
||||||
RETURN_DATA
|
RETURN_DATA
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -41,19 +41,9 @@ ZERO = bytes(32)
|
||||||
MINUS_1 = 4294967295
|
MINUS_1 = 4294967295
|
||||||
|
|
||||||
|
|
||||||
class Tx(namedtuple("Tx", "version inputs outputs locktime")):
|
class Tx(namedtuple("Tx", "version inputs outputs locktime raw")):
|
||||||
"""Class representing a transaction."""
|
"""Class representing a transaction."""
|
||||||
|
|
||||||
def serialize(self):
|
|
||||||
return b''.join((
|
|
||||||
pack_le_int32(self.version),
|
|
||||||
pack_varint(len(self.inputs)),
|
|
||||||
b''.join(tx_in.serialize() for tx_in in self.inputs),
|
|
||||||
pack_varint(len(self.outputs)),
|
|
||||||
b''.join(tx_out.serialize() for tx_out in self.outputs),
|
|
||||||
pack_le_uint32(self.locktime)
|
|
||||||
))
|
|
||||||
|
|
||||||
|
|
||||||
class TxInput(namedtuple("TxInput", "prev_hash prev_idx script sequence")):
|
class TxInput(namedtuple("TxInput", "prev_hash prev_idx script sequence")):
|
||||||
"""Class representing a transaction input."""
|
"""Class representing a transaction input."""
|
||||||
|
@ -105,22 +95,13 @@ class Deserializer:
|
||||||
|
|
||||||
def read_tx(self):
|
def read_tx(self):
|
||||||
"""Return a deserialized transaction."""
|
"""Return a deserialized transaction."""
|
||||||
version = self._read_le_int32()
|
start = self.cursor
|
||||||
inputs = self._read_inputs()
|
|
||||||
outputs = self._read_outputs()
|
|
||||||
if self.flags == 1:
|
|
||||||
# drain witness portion of transaction
|
|
||||||
# too many witnesses for no crime
|
|
||||||
for i in range(len(inputs)):
|
|
||||||
for v in range(self._read_varint()):
|
|
||||||
self._read_varbytes()
|
|
||||||
self.flags = 0
|
|
||||||
locktime = self._read_le_uint32()
|
|
||||||
return Tx(
|
return Tx(
|
||||||
version,
|
self._read_le_int32(), # version
|
||||||
inputs,
|
self._read_inputs(), # inputs
|
||||||
outputs,
|
self._read_outputs(), # outputs
|
||||||
locktime
|
self._read_le_uint32(), # locktime
|
||||||
|
self.binary[start:self.cursor],
|
||||||
)
|
)
|
||||||
|
|
||||||
def read_tx_and_hash(self):
|
def read_tx_and_hash(self):
|
||||||
|
@ -144,11 +125,7 @@ class Deserializer:
|
||||||
|
|
||||||
def _read_inputs(self):
|
def _read_inputs(self):
|
||||||
read_input = self._read_input
|
read_input = self._read_input
|
||||||
num_inputs = self._read_varint()
|
return [read_input() for i in range(self._read_varint())]
|
||||||
if num_inputs == 0:
|
|
||||||
self.flags = self._read_byte()
|
|
||||||
num_inputs = self._read_varint()
|
|
||||||
return [read_input() for i in range(num_inputs)]
|
|
||||||
|
|
||||||
def _read_input(self):
|
def _read_input(self):
|
||||||
return TxInput(
|
return TxInput(
|
||||||
|
@ -220,7 +197,7 @@ class Deserializer:
|
||||||
|
|
||||||
|
|
||||||
class TxSegWit(namedtuple("Tx", "version marker flag inputs outputs "
|
class TxSegWit(namedtuple("Tx", "version marker flag inputs outputs "
|
||||||
"witness locktime")):
|
"witness locktime raw")):
|
||||||
"""Class representing a SegWit transaction."""
|
"""Class representing a SegWit transaction."""
|
||||||
|
|
||||||
|
|
||||||
|
@ -266,7 +243,7 @@ class DeserializerSegWit(Deserializer):
|
||||||
vsize = (3 * base_size + self.binary_length) // 4
|
vsize = (3 * base_size + self.binary_length) // 4
|
||||||
|
|
||||||
return TxSegWit(version, marker, flag, inputs, outputs, witness,
|
return TxSegWit(version, marker, flag, inputs, outputs, witness,
|
||||||
locktime), self.TX_HASH_FN(orig_ser), vsize
|
locktime, orig_ser), self.TX_HASH_FN(orig_ser), vsize
|
||||||
|
|
||||||
def read_tx(self):
|
def read_tx(self):
|
||||||
return self._read_tx_parts()[0]
|
return self._read_tx_parts()[0]
|
||||||
|
|
Loading…
Add table
Reference in a new issue