pax_global_header 0000666 0000000 0000000 00000000064 13630543745 0014524 g ustar 00root root 0000000 0000000 52 comment=3fa0a4480d17dbd0e11c704fecdda1496d3125a1
python-bitcoinlib-python-bitcoinlib-v0.11.0/ 0000775 0000000 0000000 00000000000 13630543745 0021061 5 ustar 00root root 0000000 0000000 python-bitcoinlib-python-bitcoinlib-v0.11.0/.gitignore 0000664 0000000 0000000 00000000133 13630543745 0023046 0 ustar 00root root 0000000 0000000 *.sw?
*.pyc
local*.cfg
.coverage
.tox/
build/
htmlcov/
python_bitcoinlib.egg-info/
dist/
python-bitcoinlib-python-bitcoinlib-v0.11.0/.travis.yml 0000664 0000000 0000000 00000000226 13630543745 0023172 0 ustar 00root root 0000000 0000000 git:
depth: 9999999
language: python
python:
- "3.4"
- "3.5"
- "3.6"
- "3.7"
# command to run tests
script: python3 -m unittest discover -v
python-bitcoinlib-python-bitcoinlib-v0.11.0/LICENSE 0000664 0000000 0000000 00000017737 13630543745 0022105 0 ustar 00root root 0000000 0000000 python-bitcoinlib is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your option)
any later version.
python-bitcoinlib is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
below for more details.
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
python-bitcoinlib-python-bitcoinlib-v0.11.0/MANIFEST.in 0000664 0000000 0000000 00000000064 13630543745 0022617 0 ustar 00root root 0000000 0000000 include LICENSE README.md
graft bitcoin/tests/data/
python-bitcoinlib-python-bitcoinlib-v0.11.0/README.md 0000664 0000000 0000000 00000007712 13630543745 0022347 0 ustar 00root root 0000000 0000000 # python-bitcoinlib
This Python3 library provides an easy interface to the bitcoin data
structures and protocol. The approach is low-level and "ground up", with a
focus on providing tools to manipulate the internals of how Bitcoin works.
"The Swiss Army Knife of the Bitcoin protocol." - Wladimir J. van der Laan
## Requirements
sudo apt-get install libssl-dev
The RPC interface, `bitcoin.rpc`, is designed to work with Bitcoin Core v0.16.0.
Older versions may work but there do exist some incompatibilities.
## Structure
Everything consensus critical is found in the modules under bitcoin.core. This
rule is followed pretty strictly, for instance chain parameters are split into
consensus critical and non-consensus-critical.
bitcoin.core - Basic core definitions, datastructures, and
(context-independent) validation
bitcoin.core.key - ECC pubkeys
bitcoin.core.script - Scripts and opcodes
bitcoin.core.scripteval - Script evaluation/verification
bitcoin.core.serialize - Serialization
In the future the bitcoin.core may use the Satoshi sourcecode directly as a
library. Non-consensus critical modules include the following:
bitcoin - Chain selection
bitcoin.base58 - Base58 encoding
bitcoin.bloom - Bloom filters (incomplete)
bitcoin.net - Network communication (in flux)
bitcoin.messages - Network messages (in flux)
bitcoin.rpc - Bitcoin Core RPC interface support
bitcoin.wallet - Wallet-related code, currently Bitcoin address and
private key support
Effort has been made to follow the Satoshi source relatively closely, for
instance Python code and classes that duplicate the functionality of
corresponding Satoshi C++ code uses the same naming conventions: CTransaction,
CBlockHeader, nValue etc. Otherwise Python naming conventions are followed.
## Mutable vs. Immutable objects
Like the Bitcoin Core codebase CTransaction is immutable and
CMutableTransaction is mutable; unlike the Bitcoin Core codebase this
distinction also applies to COutPoint, CTxIn, CTxOut, and CBlock.
## Endianness Gotchas
Rather confusingly Bitcoin Core shows transaction and block hashes as
little-endian hex rather than the big-endian the rest of the world uses for
SHA256. python-bitcoinlib provides the convenience functions x() and lx() in
bitcoin.core to convert from big-endian and little-endian hex to raw bytes to
accomodate this. In addition see b2x() and b2lx() for conversion from bytes to
big/little-endian hex.
## Module import style
While not always good style, it's often convenient for quick scripts if
`import *` can be used. To support that all the modules have `__all__` defined
appropriately.
# Example Code
See `examples/` directory. For instance this example creates a transaction
spending a pay-to-script-hash transaction output:
$ PYTHONPATH=. examples/spend-pay-to-script-hash-txout.py
## Selecting the chain to use
Do the following:
import bitcoin
bitcoin.SelectParams(NAME)
Where NAME is one of 'testnet', 'mainnet', or 'regtest'. The chain currently
selected is a global variable that changes behavior everywhere, just like in
the Satoshi codebase.
## Unit tests
Under bitcoin/tests using test data from Bitcoin Core. To run them:
python3 -m unittest discover
Alternately, if Tox (see https://tox.readthedocs.org/) is available on your
system, you can run unit tests for multiple Python versions:
./runtests.sh
HTML coverage reports can then be found in the htmlcov/ subdirectory.
## Documentation
Sphinx documentation is in the "doc" subdirectory. Run "make help" from there
to see how to build. You will need the Python "sphinx" package installed.
Currently this is just API documentation generated from the code and
docstrings. Higher level written docs would be useful, perhaps starting with
much of this README. Pages are written in reStructuredText and linked from
index.rst.
python-bitcoinlib-python-bitcoinlib-v0.11.0/bitcoin/ 0000775 0000000 0000000 00000000000 13630543745 0022510 5 ustar 00root root 0000000 0000000 python-bitcoinlib-python-bitcoinlib-v0.11.0/bitcoin/__init__.py 0000664 0000000 0000000 00000006010 13630543745 0024616 0 ustar 00root root 0000000 0000000 # Copyright (C) 2012-2018 The python-bitcoinlib developers
#
# This file is part of python-bitcoinlib.
#
# It is subject to the license terms in the LICENSE file found in the top-level
# directory of this distribution.
#
# No part of python-bitcoinlib, including this file, may be copied, modified,
# propagated, or distributed except according to the terms contained in the
# LICENSE file.
from __future__ import absolute_import, division, print_function, unicode_literals
import bitcoin.core
# Note that setup.py can break if __init__.py imports any external
# dependencies, as these might not be installed when setup.py runs. In this
# case __version__ could be moved to a separate version.py and imported here.
__version__ = '0.11.0'
class MainParams(bitcoin.core.CoreMainParams):
MESSAGE_START = b'\xf9\xbe\xb4\xd9'
DEFAULT_PORT = 8333
RPC_PORT = 8332
DNS_SEEDS = (('bitcoin.sipa.be', 'seed.bitcoin.sipa.be'),
('bluematt.me', 'dnsseed.bluematt.me'),
('dashjr.org', 'dnsseed.bitcoin.dashjr.org'),
('bitcoinstats.com', 'seed.bitcoinstats.com'),
('xf2.org', 'bitseed.xf2.org'),
('bitcoin.jonasschnelli.ch', 'seed.bitcoin.jonasschnelli.ch'))
BASE58_PREFIXES = {'PUBKEY_ADDR':0,
'SCRIPT_ADDR':5,
'SECRET_KEY' :128}
BECH32_HRP = 'bc'
class TestNetParams(bitcoin.core.CoreTestNetParams):
MESSAGE_START = b'\x0b\x11\x09\x07'
DEFAULT_PORT = 18333
RPC_PORT = 18332
DNS_SEEDS = (('testnetbitcoin.jonasschnelli.ch', 'testnet-seed.bitcoin.jonasschnelli.ch'),
('petertodd.org', 'seed.tbtc.petertodd.org'),
('bluematt.me', 'testnet-seed.bluematt.me'),
('bitcoin.schildbach.de', 'testnet-seed.bitcoin.schildbach.de'))
BASE58_PREFIXES = {'PUBKEY_ADDR':111,
'SCRIPT_ADDR':196,
'SECRET_KEY' :239}
BECH32_HRP = 'tb'
class RegTestParams(bitcoin.core.CoreRegTestParams):
MESSAGE_START = b'\xfa\xbf\xb5\xda'
DEFAULT_PORT = 18444
RPC_PORT = 18443
DNS_SEEDS = ()
BASE58_PREFIXES = {'PUBKEY_ADDR':111,
'SCRIPT_ADDR':196,
'SECRET_KEY' :239}
BECH32_HRP = 'bcrt'
"""Master global setting for what chain params we're using.
However, don't set this directly, use SelectParams() instead so as to set the
bitcoin.core.params correctly too.
"""
#params = bitcoin.core.coreparams = MainParams()
params = MainParams()
def SelectParams(name):
"""Select the chain parameters to use
name is one of 'mainnet', 'testnet', or 'regtest'
Default chain is 'mainnet'
"""
global params
bitcoin.core._SelectCoreParams(name)
if name == 'mainnet':
params = bitcoin.core.coreparams = MainParams()
elif name == 'testnet':
params = bitcoin.core.coreparams = TestNetParams()
elif name == 'regtest':
params = bitcoin.core.coreparams = RegTestParams()
else:
raise ValueError('Unknown chain %r' % name)
python-bitcoinlib-python-bitcoinlib-v0.11.0/bitcoin/base58.py 0000664 0000000 0000000 00000010072 13630543745 0024151 0 ustar 00root root 0000000 0000000 # Copyright (C) 2011 Sam Rushing
# Copyright (C) 2013-2014 The python-bitcoinlib developers
#
# This file is part of python-bitcoinlib.
#
# It is subject to the license terms in the LICENSE file found in the top-level
# directory of this distribution.
#
# No part of python-bitcoinlib, including this file, may be copied, modified,
# propagated, or distributed except according to the terms contained in the
# LICENSE file.
"""Base58 encoding and decoding"""
from __future__ import absolute_import, division, print_function, unicode_literals
import sys
_bchr = chr
_bord = ord
if sys.version > '3':
long = int
_bchr = lambda x: bytes([x])
_bord = lambda x: x
import binascii
import bitcoin.core
B58_DIGITS = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
class Base58Error(Exception):
pass
class InvalidBase58Error(Base58Error):
"""Raised on generic invalid base58 data, such as bad characters.
Checksum failures raise Base58ChecksumError specifically.
"""
pass
def encode(b):
"""Encode bytes to a base58-encoded string"""
# Convert big-endian bytes to integer
n = int('0x0' + binascii.hexlify(b).decode('utf8'), 16)
# Divide that integer into bas58
res = []
while n > 0:
n, r = divmod(n, 58)
res.append(B58_DIGITS[r])
res = ''.join(res[::-1])
# Encode leading zeros as base58 zeros
czero = b'\x00'
if sys.version > '3':
# In Python3 indexing a bytes returns numbers, not characters.
czero = 0
pad = 0
for c in b:
if c == czero:
pad += 1
else:
break
return B58_DIGITS[0] * pad + res
def decode(s):
"""Decode a base58-encoding string, returning bytes"""
if not s:
return b''
# Convert the string to an integer
n = 0
for c in s:
n *= 58
if c not in B58_DIGITS:
raise InvalidBase58Error('Character %r is not a valid base58 character' % c)
digit = B58_DIGITS.index(c)
n += digit
# Convert the integer to bytes
h = '%x' % n
if len(h) % 2:
h = '0' + h
res = binascii.unhexlify(h.encode('utf8'))
# Add padding back.
pad = 0
for c in s[:-1]:
if c == B58_DIGITS[0]: pad += 1
else: break
return b'\x00' * pad + res
class Base58ChecksumError(Base58Error):
"""Raised on Base58 checksum errors"""
pass
class CBase58Data(bytes):
"""Base58-encoded data
Includes a version and checksum.
"""
def __new__(cls, s):
k = decode(s)
verbyte, data, check0 = k[0:1], k[1:-4], k[-4:]
check1 = bitcoin.core.Hash(verbyte + data)[:4]
if check0 != check1:
raise Base58ChecksumError('Checksum mismatch: expected %r, calculated %r' % (check0, check1))
return cls.from_bytes(data, _bord(verbyte[0]))
def __init__(self, s):
"""Initialize from base58-encoded string
Note: subclasses put your initialization routines here, but ignore the
argument - that's handled by __new__(), and .from_bytes() will call
__init__() with None in place of the string.
"""
@classmethod
def from_bytes(cls, data, nVersion):
"""Instantiate from data and nVersion"""
if not (0 <= nVersion <= 255):
raise ValueError('nVersion must be in range 0 to 255 inclusive; got %d' % nVersion)
self = bytes.__new__(cls, data)
self.nVersion = nVersion
return self
def to_bytes(self):
"""Convert to bytes instance
Note that it's the data represented that is converted; the checkum and
nVersion is not included.
"""
return b'' + self
def __str__(self):
"""Convert to string"""
vs = _bchr(self.nVersion) + self
check = bitcoin.core.Hash(vs)[0:4]
return encode(vs + check)
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, str(self))
__all__ = (
'B58_DIGITS',
'Base58Error',
'InvalidBase58Error',
'encode',
'decode',
'Base58ChecksumError',
'CBase58Data',
)
python-bitcoinlib-python-bitcoinlib-v0.11.0/bitcoin/bech32.py 0000664 0000000 0000000 00000004225 13630543745 0024133 0 ustar 00root root 0000000 0000000 # Copyright (C) 2017 The python-bitcoinlib developers
#
# This file is part of python-bitcoinlib.
#
# It is subject to the license terms in the LICENSE file found in the top-level
# directory of this distribution.
#
# No part of python-bitcoinlib, including this file, may be copied, modified,
# propagated, or distributed except according to the terms contained in the
# LICENSE file.
"""Bech32 encoding and decoding"""
import sys
_bchr = chr
_bord = ord
if sys.version > '3':
long = int
_bchr = lambda x: bytes([x])
_bord = lambda x: x
from bitcoin.segwit_addr import encode, decode
import bitcoin
class Bech32Error(Exception):
pass
class Bech32ChecksumError(Bech32Error):
pass
class CBech32Data(bytes):
"""Bech32-encoded data
Includes a witver and checksum.
"""
def __new__(cls, s):
"""from bech32 addr to """
witver, data = decode(bitcoin.params.BECH32_HRP, s)
if witver is None and data is None:
raise Bech32Error('Bech32 decoding error')
return cls.from_bytes(witver, data)
def __init__(self, s):
"""Initialize from bech32-encoded string
Note: subclasses put your initialization routines here, but ignore the
argument - that's handled by __new__(), and .from_bytes() will call
__init__() with None in place of the string.
"""
@classmethod
def from_bytes(cls, witver, witprog):
"""Instantiate from witver and data"""
if not (0 <= witver <= 16):
raise ValueError('witver must be in range 0 to 16 inclusive; got %d' % witver)
self = bytes.__new__(cls, witprog)
self.witver = witver
return self
def to_bytes(self):
"""Convert to bytes instance
Note that it's the data represented that is converted; the checkum and
witver is not included.
"""
return b'' + self
def __str__(self):
"""Convert to string"""
return encode(bitcoin.params.BECH32_HRP, self.witver, self)
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, str(self))
__all__ = (
'Bech32Error',
'Bech32ChecksumError',
'CBech32Data',
)
python-bitcoinlib-python-bitcoinlib-v0.11.0/bitcoin/bloom.py 0000664 0000000 0000000 00000014203 13630543745 0024172 0 ustar 00root root 0000000 0000000 # Copyright (C) 2013-2014 The python-bitcoinlib developers
#
# This file is part of python-bitcoinlib.
#
# It is subject to the license terms in the LICENSE file found in the top-level
# directory of this distribution.
#
# No part of python-bitcoinlib, including this file, may be copied, modified,
# propagated, or distributed except according to the terms contained in the
# LICENSE file.
"""Bloom filter support"""
from __future__ import absolute_import, division, print_function, unicode_literals
import struct
import sys
import math
import bitcoin.core
import bitcoin.core.serialize
def _ROTL32(x, r):
assert x <= 0xFFFFFFFF
return ((x << r) & 0xFFFFFFFF) | (x >> (32 - r))
def MurmurHash3(nHashSeed, vDataToHash):
"""MurmurHash3 (x86_32)
Used for bloom filters. See http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
"""
assert nHashSeed <= 0xFFFFFFFF
h1 = nHashSeed
c1 = 0xcc9e2d51
c2 = 0x1b873593
# body
i = 0
while (i < len(vDataToHash) - len(vDataToHash) % 4
and len(vDataToHash) - i >= 4):
k1 = struct.unpack(b" '3':
# In Py3 indexing bytes returns numbers, not characters
bord = lambda x: x
if len(vDataToHash) & 3 >= 3:
k1 ^= bord(vDataToHash[j+2]) << 16
if len(vDataToHash) & 3 >= 2:
k1 ^= bord(vDataToHash[j+1]) << 8
if len(vDataToHash) & 3 >= 1:
k1 ^= bord(vDataToHash[j])
k1 &= 0xFFFFFFFF
k1 = (k1 * c1) & 0xFFFFFFFF
k1 = _ROTL32(k1, 15)
k1 = (k1 * c2) & 0xFFFFFFFF
h1 ^= k1
# finalization
h1 ^= len(vDataToHash) & 0xFFFFFFFF
h1 ^= (h1 & 0xFFFFFFFF) >> 16
h1 *= 0x85ebca6b
h1 ^= (h1 & 0xFFFFFFFF) >> 13
h1 *= 0xc2b2ae35
h1 ^= (h1 & 0xFFFFFFFF) >> 16
return h1 & 0xFFFFFFFF
class CBloomFilter(bitcoin.core.serialize.Serializable):
# 20,000 items with fp rate < 0.1% or 10,000 items and <0.0001%
MAX_BLOOM_FILTER_SIZE = 36000
MAX_HASH_FUNCS = 50
UPDATE_NONE = 0
UPDATE_ALL = 1
UPDATE_P2PUBKEY_ONLY = 2
UPDATE_MASK = 3
def __init__(self, nElements, nFPRate, nTweak, nFlags):
"""Create a new bloom filter
The filter will have a given false-positive rate when filled with the
given number of elements.
Note that if the given parameters will result in a filter outside the
bounds of the protocol limits, the filter created will be as close to
the given parameters as possible within the protocol limits. This will
apply if nFPRate is very low or nElements is unreasonably high.
nTweak is a constant which is added to the seed value passed to the
hash function It should generally always be a random value (and is
largely only exposed for unit testing)
nFlags should be one of the UPDATE_* enums (but not _MASK)
"""
LN2SQUARED = 0.4804530139182014246671025263266649717305529515945455
LN2 = 0.6931471805599453094172321214581765680755001343602552
self.vData = bytearray(int(min(-1 / LN2SQUARED * nElements * math.log(nFPRate), self.MAX_BLOOM_FILTER_SIZE * 8) / 8))
self.nHashFuncs = int(min(len(self.vData) * 8 / nElements * LN2, self.MAX_HASH_FUNCS))
self.nTweak = nTweak
self.nFlags = nFlags
def bloom_hash(self, nHashNum, vDataToHash):
return MurmurHash3(((nHashNum * 0xFBA4C795) + self.nTweak) & 0xFFFFFFFF, vDataToHash) % (len(self.vData) * 8)
__bit_mask = bytearray([0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80])
def insert(self, elem):
"""Insert an element in the filter.
elem may be a COutPoint or bytes
"""
if isinstance(elem, bitcoin.core.COutPoint):
elem = elem.serialize()
if len(self.vData) == 1 and self.vData[0] == 0xff:
return
for i in range(0, self.nHashFuncs):
nIndex = self.bloom_hash(i, elem)
# Sets bit nIndex of vData
self.vData[nIndex >> 3] |= self.__bit_mask[7 & nIndex]
def contains(self, elem):
"""Test if the filter contains an element
elem may be a COutPoint or bytes
"""
if isinstance(elem, bitcoin.core.COutPoint):
elem = elem.serialize()
if len(self.vData) == 1 and self.vData[0] == 0xff:
return True
for i in range(0, self.nHashFuncs):
nIndex = self.bloom_hash(i, elem)
if not (self.vData[nIndex >> 3] & self.__bit_mask[7 & nIndex]):
return False
return True
def IsWithinSizeConstraints(self):
return len(self.vData) <= self.MAX_BLOOM_FILTER_SIZE and self.nHashFuncs <= self.MAX_HASH_FUNCS
def IsRelevantAndUpdate(tx, tx_hash):
# Not useful for a client, so not implemented yet.
raise NotImplementedError
__struct = struct.Struct(b' '3':
bitcoin.core.serialize.BytesSerializer.stream_serialize(self.vData, f)
else:
# 2.7 has problems with f.write(bytearray())
bitcoin.core.serialize.BytesSerializer.stream_serialize(bytes(self.vData), f)
f.write(self.__struct.pack(self.nHashFuncs, self.nTweak, self.nFlags))
__all__ = (
'MurmurHash3',
'CBloomFilter',
)
python-bitcoinlib-python-bitcoinlib-v0.11.0/bitcoin/core/ 0000775 0000000 0000000 00000000000 13630543745 0023440 5 ustar 00root root 0000000 0000000 python-bitcoinlib-python-bitcoinlib-v0.11.0/bitcoin/core/__init__.py 0000664 0000000 0000000 00000106565 13630543745 0025566 0 ustar 00root root 0000000 0000000 # Copyright (C) 2012-2017 The python-bitcoinlib developers
#
# This file is part of python-bitcoinlib.
#
# It is subject to the license terms in the LICENSE file found in the top-level
# directory of this distribution.
#
# No part of python-bitcoinlib, including this file, may be copied, modified,
# propagated, or distributed except according to the terms contained in the
# LICENSE file.
from __future__ import absolute_import, division, print_function
import binascii
import struct
import sys
import time
from .script import CScript, CScriptWitness, CScriptOp, OP_RETURN
from .serialize import *
if sys.version > '3':
_bytes = bytes
else:
_bytes = lambda x: bytes(bytearray(x))
# Core definitions
COIN = 100000000
MAX_BLOCK_SIZE = 1000000
MAX_BLOCK_WEIGHT = 4000000
MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50
WITNESS_COINBASE_SCRIPTPUBKEY_MAGIC = _bytes([OP_RETURN, 0x24, 0xaa, 0x21, 0xa9, 0xed])
def MoneyRange(nValue, params=None):
global coreparams
if not params:
params = coreparams
return 0 <= nValue <= params.MAX_MONEY
def _py2_x(h):
"""Convert a hex string to bytes"""
return binascii.unhexlify(h)
def x(h):
"""Convert a hex string to bytes"""
return binascii.unhexlify(h.encode('utf8'))
def _py2_b2x(b):
"""Convert bytes to a hex string"""
return binascii.hexlify(b)
def b2x(b):
"""Convert bytes to a hex string"""
return binascii.hexlify(b).decode('utf8')
def _py2_lx(h):
"""Convert a little-endian hex string to bytes
Lets you write uint256's and uint160's the way the Satoshi codebase shows
them.
"""
return binascii.unhexlify(h)[::-1]
def lx(h):
"""Convert a little-endian hex string to bytes
Lets you write uint256's and uint160's the way the Satoshi codebase shows
them.
"""
return binascii.unhexlify(h.encode('utf8'))[::-1]
def _py2_b2lx(b):
"""Convert bytes to a little-endian hex string
Lets you show uint256's and uint160's the way the Satoshi codebase shows
them.
"""
return binascii.hexlify(b[::-1])
def b2lx(b):
"""Convert bytes to a little-endian hex string
Lets you show uint256's and uint160's the way the Satoshi codebase shows
them.
"""
return binascii.hexlify(b[::-1]).decode('utf8')
if not (sys.version > '3'):
x = _py2_x
b2x = _py2_b2x
lx = _py2_lx
b2lx = _py2_b2lx
del _py2_x
del _py2_b2x
del _py2_lx
del _py2_b2lx
def str_money_value(value):
"""Convert an integer money value to a fixed point string"""
r = '%i.%08i' % (value // COIN, value % COIN)
r = r.rstrip('0')
if r[-1] == '.':
r += '0'
return r
class ValidationError(Exception):
"""Base class for all blockchain validation errors
Everything that is related to validating the blockchain, blocks,
transactions, scripts, etc. is derived from this class.
"""
def __make_mutable(cls):
# For speed we use a class decorator that removes the immutable
# restrictions directly. In addition the modified behavior of GetHash() and
# hash() is undone.
cls.__setattr__ = object.__setattr__
cls.__delattr__ = object.__delattr__
cls.GetHash = Serializable.GetHash
cls.__hash__ = Serializable.__hash__
return cls
class COutPoint(ImmutableSerializable):
"""The combination of a transaction hash and an index n into its vout"""
__slots__ = ['hash', 'n']
def __init__(self, hash=b'\x00'*32, n=0xffffffff):
if not len(hash) == 32:
raise ValueError('COutPoint: hash must be exactly 32 bytes; got %d bytes' % len(hash))
object.__setattr__(self, 'hash', hash)
if not (0 <= n <= 0xffffffff):
raise ValueError('COutPoint: n must be in range 0x0 to 0xffffffff; got %x' % n)
object.__setattr__(self, 'n', n)
@classmethod
def stream_deserialize(cls, f):
hash = ser_read(f,32)
n = struct.unpack(b"= 0:
return "CTxOut(%s*COIN, %r)" % (str_money_value(self.nValue), self.scriptPubKey)
else:
return "CTxOut(%d, %r)" % (self.nValue, self.scriptPubKey)
@classmethod
def from_txout(cls, txout):
"""Create an immutable copy of an existing TxOut
If txout is already immutable (txout.__class__ is CTxOut) then it will
be returned directly.
"""
if txout.__class__ is CTxOut:
return txout
else:
return cls(txout.nValue, txout.scriptPubKey)
@__make_mutable
class CMutableTxOut(CTxOut):
"""A mutable CTxOut"""
__slots__ = []
@classmethod
def from_txout(cls, txout):
"""Create a fullly mutable copy of an existing TxOut"""
return cls(txout.nValue, txout.scriptPubKey)
class CTxInWitness(ImmutableSerializable):
"""Witness data for a single transaction input"""
__slots__ = ['scriptWitness']
def __init__(self, scriptWitness=CScriptWitness()):
object.__setattr__(self, 'scriptWitness', scriptWitness)
def is_null(self):
return self.scriptWitness.is_null()
@classmethod
def stream_deserialize(cls, f):
scriptWitness = CScriptWitness.stream_deserialize(f)
return cls(scriptWitness)
def stream_serialize(self, f):
self.scriptWitness.stream_serialize(f)
def __repr__(self):
return "CTxInWitness(%s)" % (repr(self.scriptWitness))
@classmethod
def from_txinwitness(cls, txinwitness):
"""Create an immutable copy of an existing TxInWitness
If txin is already immutable (txin.__class__ is CTxIn) it is returned
directly.
"""
if txinwitness.__class__ is CTxInWitness:
return txinwitness
else:
return cls(txinwitness.scriptWitness)
class CTxWitness(ImmutableSerializable):
"""Witness data for all inputs to a transaction"""
__slots__ = ['vtxinwit']
def __init__(self, vtxinwit=()):
object.__setattr__(self, 'vtxinwit', vtxinwit)
def is_null(self):
for n in range(len(self.vtxinwit)):
if not self.vtxinwit[n].is_null(): return False
return True
# FIXME this cannot be a @classmethod like the others because we need to
# know how many items to deserialize, which comes from len(vin)
def stream_deserialize(self, f):
vtxinwit = tuple(CTxInWitness.stream_deserialize(f) for dummy in
range(len(self.vtxinwit)))
return CTxWitness(vtxinwit)
def stream_serialize(self, f):
for i in range(len(self.vtxinwit)):
self.vtxinwit[i].stream_serialize(f)
def __repr__(self):
return "CTxWitness(%s)" % (','.join(repr(w) for w in self.vtxinwit))
@classmethod
def from_txwitness(cls, txwitness):
"""Create an immutable copy of an existing TxWitness
If txwitness is already immutable (txwitness.__class__ is CTxWitness) it is returned
directly.
"""
if txwitness.__class__ is CTxWitness:
return txwitness
else:
return cls(txwitness.vtxinwit)
class CTransaction(ImmutableSerializable):
"""A transaction"""
__slots__ = ['nVersion', 'vin', 'vout', 'nLockTime', 'wit']
def __init__(self, vin=(), vout=(), nLockTime=0, nVersion=1, witness=CTxWitness()):
"""Create a new transaction
vin and vout are iterables of transaction inputs and outputs
respectively. If their contents are not already immutable, immutable
copies will be made.
"""
if not (0 <= nLockTime <= 0xffffffff):
raise ValueError('CTransaction: nLockTime must be in range 0x0 to 0xffffffff; got %x' % nLockTime)
object.__setattr__(self, 'nLockTime', nLockTime)
object.__setattr__(self, 'nVersion', nVersion)
object.__setattr__(self, 'vin', tuple(CTxIn.from_txin(txin) for txin in vin))
object.__setattr__(self, 'vout', tuple(CTxOut.from_txout(txout) for txout in vout))
object.__setattr__(self, 'wit', CTxWitness.from_txwitness(witness))
@classmethod
def stream_deserialize(cls, f):
"""Deserialize transaction
This implementation corresponds to Bitcoin's SerializeTransaction() and
consensus behavior. Note that Bitcoin's DecodeHexTx() also has the
option to attempt deserializing as a non-witness transaction first,
falling back to the consensus behavior if it fails. The difference lies
in transactions which have zero inputs: they are invalid but may be
(de)serialized anyway for the purpose of signing them and adding
inputs. If the behavior of DecodeHexTx() is needed it could be added,
but not here.
"""
# FIXME can't assume f is seekable
nVersion = struct.unpack(b"> 24) & 0xff
dDiff = float(0x0000ffff) / float(nBits & 0x00ffffff)
while nShift < 29:
dDiff *= 256.0
nShift += 1
while nShift > 29:
dDiff /= 256.0
nShift -= 1
return dDiff
difficulty = property(lambda self: CBlockHeader.calc_difficulty(self.nBits))
def __repr__(self):
return "%s(%i, lx(%s), lx(%s), %s, 0x%08x, 0x%08x)" % \
(self.__class__.__name__, self.nVersion, b2lx(self.hashPrevBlock), b2lx(self.hashMerkleRoot),
self.nTime, self.nBits, self.nNonce)
class NoWitnessData(Exception):
"""The block does not have witness data"""
class CBlock(CBlockHeader):
"""A block including all transactions in it"""
__slots__ = ['vtx', 'vMerkleTree', 'vWitnessMerkleTree']
@staticmethod
def build_merkle_tree_from_txids(txids):
"""Build a full CBlock merkle tree from txids
txids - iterable of txids
Returns a new merkle tree in deepest first order. The last element is
the merkle root.
WARNING! If you're reading this because you're learning about crypto
and/or designing a new system that will use merkle trees, keep in mind
that the following merkle tree algorithm has a serious flaw related to
duplicate txids, resulting in a vulnerability. (CVE-2012-2459) Bitcoin
has since worked around the flaw, but for new applications you should
use something different; don't just copy-and-paste this code without
understanding the problem first.
"""
merkle_tree = list(txids)
size = len(txids)
j = 0
while size > 1:
for i in range(0, size, 2):
i2 = min(i+1, size-1)
merkle_tree.append(Hash(merkle_tree[j+i] + merkle_tree[j+i2]))
j += size
size = (size + 1) // 2
return merkle_tree
@staticmethod
def build_merkle_tree_from_txs(txs):
"""Build a full merkle tree from transactions"""
txids = [tx.GetTxid() for tx in txs]
return CBlock.build_merkle_tree_from_txids(txids)
def calc_merkle_root(self):
"""Calculate the merkle root
The calculated merkle root is not cached; every invocation
re-calculates it from scratch.
"""
if not len(self.vtx):
raise ValueError('Block contains no transactions')
return self.build_merkle_tree_from_txs(self.vtx)[-1]
@staticmethod
def build_witness_merkle_tree_from_txs(txs):
"""Calculate the witness merkle tree from transactions"""
has_witness = False
hashes = []
for tx in txs:
hashes.append(tx.GetHash())
has_witness |= tx.has_witness()
if not has_witness:
raise NoWitnessData
hashes[0] = b'\x00' * 32
return CBlock.build_merkle_tree_from_txids(hashes)
def calc_witness_merkle_root(self):
"""Calculate the witness merkle root
The calculated merkle root is not cached; every invocation
re-calculates it from scratch.
"""
if not len(self.vtx):
raise ValueError('Block contains no transactions')
return self.build_witness_merkle_tree_from_txs(self.vtx)[-1]
def get_witness_commitment_index(self):
"""Find txout # of witness commitment in coinbase
Return None or an index
"""
if not len(self.vtx):
raise ValueError('Block contains no transactions')
commit_pos = None
for index, out in enumerate(self.vtx[0].vout):
script = out.scriptPubKey
if len(script) >= 38 and script[:6] == WITNESS_COINBASE_SCRIPTPUBKEY_MAGIC:
commit_pos = index
if commit_pos is None:
raise ValueError('The witness commitment is missed')
return commit_pos
def __init__(self, nVersion=2, hashPrevBlock=b'\x00'*32, hashMerkleRoot=b'\x00'*32, nTime=0, nBits=0, nNonce=0, vtx=()):
"""Create a new block"""
if vtx:
vMerkleTree = tuple(CBlock.build_merkle_tree_from_txs(vtx))
if hashMerkleRoot == b'\x00'*32:
hashMerkleRoot = vMerkleTree[-1]
elif hashMerkleRoot != vMerkleTree[-1]:
raise CheckBlockError("CBlock : hashMerkleRoot is not compatible with vtx")
else:
vMerkleTree = ()
super(CBlock, self).__init__(nVersion, hashPrevBlock, hashMerkleRoot, nTime, nBits, nNonce)
object.__setattr__(self, 'vMerkleTree', vMerkleTree)
try:
vWitnessMerkleTree = tuple(CBlock.build_witness_merkle_tree_from_txs(vtx))
except NoWitnessData:
vWitnessMerkleTree = ()
object.__setattr__(self, 'vWitnessMerkleTree', vWitnessMerkleTree)
object.__setattr__(self, 'vtx', tuple(CTransaction.from_tx(tx) for tx in vtx))
@classmethod
def stream_deserialize(cls, f):
self = super(CBlock, cls).stream_deserialize(f)
vtx = VectorSerializer.stream_deserialize(CTransaction, f)
vMerkleTree = tuple(CBlock.build_merkle_tree_from_txs(vtx))
object.__setattr__(self, 'vMerkleTree', vMerkleTree)
try:
vWitnessMerkleTree = tuple(CBlock.build_witness_merkle_tree_from_txs(vtx))
except NoWitnessData:
vWitnessMerkleTree = ()
object.__setattr__(self, 'vWitnessMerkleTree', vWitnessMerkleTree)
object.__setattr__(self, 'vtx', tuple(vtx))
return self
def stream_serialize(self, f, include_witness=True):
super(CBlock, self).stream_serialize(f)
VectorSerializer.stream_serialize(CTransaction, self.vtx, f, dict(include_witness=include_witness))
def get_header(self):
"""Return the block header
Returned header is a new object.
"""
return CBlockHeader(nVersion=self.nVersion,
hashPrevBlock=self.hashPrevBlock,
hashMerkleRoot=self.hashMerkleRoot,
nTime=self.nTime,
nBits=self.nBits,
nNonce=self.nNonce)
def GetHash(self):
"""Return the block hash
Note that this is the hash of the header, not the entire serialized
block.
"""
try:
return self._cached_GetHash
except AttributeError:
_cached_GetHash = self.get_header().GetHash()
object.__setattr__(self, '_cached_GetHash', _cached_GetHash)
return _cached_GetHash
def GetWeight(self):
"""Return the block weight: (stripped_size * 3) + total_size"""
return len(self.serialize(dict(include_witness=False))) * 3 + len(self.serialize())
class CoreChainParams(object):
"""Define consensus-critical parameters of a given instance of the Bitcoin system"""
MAX_MONEY = None
GENESIS_BLOCK = None
PROOF_OF_WORK_LIMIT = None
SUBSIDY_HALVING_INTERVAL = None
NAME = None
class CoreMainParams(CoreChainParams):
MAX_MONEY = 21000000 * COIN
NAME = 'mainnet'
GENESIS_BLOCK = CBlock.deserialize(x('0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000'))
SUBSIDY_HALVING_INTERVAL = 210000
PROOF_OF_WORK_LIMIT = 2**256-1 >> 32
class CoreTestNetParams(CoreMainParams):
NAME = 'testnet'
GENESIS_BLOCK = CBlock.deserialize(x('0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff001d1aa4ae180101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000'))
class CoreRegTestParams(CoreTestNetParams):
NAME = 'regtest'
GENESIS_BLOCK = CBlock.deserialize(x('0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff7f20020000000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000'))
SUBSIDY_HALVING_INTERVAL = 150
PROOF_OF_WORK_LIMIT = 2**256-1 >> 1
"""Master global setting for what core chain params we're using"""
coreparams = CoreMainParams()
def _SelectCoreParams(name):
"""Select the core chain parameters to use
Don't use this directly, use bitcoin.SelectParams() instead so both
consensus-critical and general parameters are set properly.
"""
global coreparams
if name == 'mainnet':
coreparams = CoreMainParams()
elif name == 'testnet':
coreparams = CoreTestNetParams()
elif name == 'regtest':
coreparams = CoreRegTestParams()
else:
raise ValueError('Unknown chain %r' % name)
class CheckTransactionError(ValidationError):
pass
def CheckTransaction(tx):
"""Basic transaction checks that don't depend on any context.
Raises CheckTransactionError
"""
global coreparams
if not tx.vin:
raise CheckTransactionError("CheckTransaction() : vin empty")
if not tx.vout:
raise CheckTransactionError("CheckTransaction() : vout empty")
# Size limits
base_tx = CTransaction(tx.vin, tx.vout, tx.nLockTime, tx.nVersion)
if len(base_tx.serialize()) > MAX_BLOCK_SIZE:
raise CheckTransactionError("CheckTransaction() : size limits failed")
# Check for negative or overflow output values
nValueOut = 0
for txout in tx.vout:
if txout.nValue < 0:
raise CheckTransactionError("CheckTransaction() : txout.nValue negative")
if txout.nValue > coreparams.MAX_MONEY:
raise CheckTransactionError("CheckTransaction() : txout.nValue too high")
nValueOut += txout.nValue
if not MoneyRange(nValueOut):
raise CheckTransactionError("CheckTransaction() : txout total out of range")
# Check for duplicate inputs
vin_outpoints = set()
for txin in tx.vin:
if txin.prevout in vin_outpoints:
raise CheckTransactionError("CheckTransaction() : duplicate inputs")
vin_outpoints.add(txin.prevout)
if tx.is_coinbase():
if not (2 <= len(tx.vin[0].scriptSig) <= 100):
raise CheckTransactionError("CheckTransaction() : coinbase script size")
else:
for txin in tx.vin:
if txin.prevout.is_null():
raise CheckTransactionError("CheckTransaction() : prevout is null")
class CheckBlockHeaderError(ValidationError):
pass
class CheckProofOfWorkError(CheckBlockHeaderError):
pass
def CheckProofOfWork(hash, nBits):
"""Check a proof-of-work
Raises CheckProofOfWorkError
"""
target = uint256_from_compact(nBits)
# Check range
if not (0 < target <= coreparams.PROOF_OF_WORK_LIMIT):
raise CheckProofOfWorkError("CheckProofOfWork() : nBits below minimum work")
# Check proof of work matches claimed amount
hash = uint256_from_str(hash)
if hash > target:
raise CheckProofOfWorkError("CheckProofOfWork() : hash doesn't match nBits")
def CheckBlockHeader(block_header, fCheckPoW = True, cur_time=None):
"""Context independent CBlockHeader checks.
fCheckPoW - Check proof-of-work.
cur_time - Current time. Defaults to time.time()
Raises CBlockHeaderError if block header is invalid.
"""
if cur_time is None:
cur_time = time.time()
# Check proof-of-work matches claimed amount
if fCheckPoW:
CheckProofOfWork(block_header.GetHash(), block_header.nBits)
# Check timestamp
if block_header.nTime > cur_time + 2 * 60 * 60:
raise CheckBlockHeaderError("CheckBlockHeader() : block timestamp too far in the future")
class CheckBlockError(CheckBlockHeaderError):
pass
def GetLegacySigOpCount(tx):
nSigOps = 0
for txin in tx.vin:
nSigOps += txin.scriptSig.GetSigOpCount(False)
for txout in tx.vout:
nSigOps += txout.scriptPubKey.GetSigOpCount(False)
return nSigOps
def CheckBlock(block, fCheckPoW = True, fCheckMerkleRoot = True, cur_time=None):
"""Context independent CBlock checks.
CheckBlockHeader() is called first, which may raise a CheckBlockHeader
exception, followed the block tests. CheckTransaction() is called for every
transaction.
fCheckPoW - Check proof-of-work.
fCheckMerkleRoot - Check merkle root and witness merkle root matches transactions.
- Check witness commitment in coinbase
cur_time - Current time. Defaults to time.time()
"""
# Block header checks
CheckBlockHeader(block.get_header(), fCheckPoW=fCheckPoW, cur_time=cur_time)
# Size limits
if not block.vtx:
raise CheckBlockError("CheckBlock() : vtx empty")
if len(block.serialize(dict(include_witness=False))) > MAX_BLOCK_SIZE:
raise CheckBlockError("CheckBlock() : block larger than MAX_BLOCK_SIZE")
if block.GetWeight() > MAX_BLOCK_WEIGHT:
raise CheckBlockError("CheckBlock() : block larger than MAX_BLOCK_WEIGHT")
# First transaction must be coinbase
if not block.vtx[0].is_coinbase():
raise CheckBlockError("CheckBlock() : first tx is not coinbase")
# Check rest of transactions. Note how we do things "all at once", which
# could potentially be a consensus failure if there was some obscure bug.
# For unique txid uniqueness testing. If coinbase tx is included twice
# it'll be caught by the "more than one coinbase" test.
unique_txids = set()
nSigOps = 0
for tx in block.vtx[1:]:
if tx.is_coinbase():
raise CheckBlockError("CheckBlock() : more than one coinbase")
CheckTransaction(tx)
txid = tx.GetTxid()
if txid in unique_txids:
raise CheckBlockError("CheckBlock() : duplicate transaction")
unique_txids.add(txid)
nSigOps += GetLegacySigOpCount(tx)
if nSigOps > MAX_BLOCK_SIGOPS:
raise CheckBlockError("CheckBlock() : out-of-bounds SigOpCount")
# Check merkle root
if fCheckMerkleRoot:
if block.hashMerkleRoot != block.calc_merkle_root():
raise CheckBlockError("CheckBlock() : hashMerkleRoot mismatch")
if len(block.vWitnessMerkleTree):
# At least 1 tx has witness: check witness merkle tree
root = block.vWitnessMerkleTree[-1]
# vtx[0]: coinbase
# vtxinwit[0]: first input
nonce_script = block.vtx[0].wit.vtxinwit[0].scriptWitness
nonce = nonce_script.stack[0]
if len(nonce_script.stack) != 1 or len(nonce) != 32:
raise CheckBlockError("CheckBlock() : invalid coinbase witnessScript")
try:
index = block.get_witness_commitment_index()
except ValueError as e:
raise CheckBlockError("CheckBlock() : " + str(e))
commit_script = block.vtx[0].vout[index].scriptPubKey
if not (6 + 32 <= len(commit_script) <= 6 + 32 + 1):
raise CheckBlockError("CheckBlock() : invalid segwit commitment length")
commitment = commit_script[6:6 + 32]
commit = commit_script[6:6 + 32]
if commit != Hash(root + nonce):
raise CheckBlockError("CheckBlock() : invalid segwit commitment")
__all__ = (
'Hash',
'Hash160',
'COIN',
'MAX_BLOCK_SIZE',
'MAX_BLOCK_SIGOPS',
'MoneyRange',
'x',
'b2x',
'lx',
'b2lx',
'str_money_value',
'ValidationError',
'COutPoint',
'CMutableOutPoint',
'CTxIn',
'CMutableTxIn',
'CTxOut',
'CMutableTxOut',
'CTransaction',
'CMutableTransaction',
'CTxWitness',
'CTxInWitness',
'CBlockHeader',
'CBlock',
'CoreChainParams',
'CoreMainParams',
'CoreTestNetParams',
'CoreRegTestParams',
'CheckTransactionError',
'CheckTransaction',
'CheckBlockHeaderError',
'CheckProofOfWorkError',
'CheckProofOfWork',
'CheckBlockHeader',
'CheckBlockError',
'GetLegacySigOpCount',
'CheckBlock',
)
python-bitcoinlib-python-bitcoinlib-v0.11.0/bitcoin/core/_bignum.py 0000664 0000000 0000000 00000004311 13630543745 0025431 0 ustar 00root root 0000000 0000000 # Copyright (C) 2012-2014 The python-bitcoinlib developers
#
# This file is part of python-bitcoinlib.
#
# It is subject to the license terms in the LICENSE file found in the top-level
# directory of this distribution.
#
# No part of python-bitcoinlib, including this file, may be copied, modified,
# propagated, or distributed except according to the terms contained in the
# LICENSE file.
# Bignum routines
#
# Internally used for script evaluation; not to be used externally.
from __future__ import absolute_import, division, print_function, unicode_literals
import struct
# generic big endian MPI format
def bn_bytes(v, have_ext=False):
ext = 0
if have_ext:
ext = 1
return ((v.bit_length() + 7) // 8) + ext
def bn2bin(v):
s = bytearray()
i = bn_bytes(v)
while i > 0:
s.append((v >> ((i - 1) * 8)) & 0xff)
i -= 1
return s
def bin2bn(s):
l = 0
for ch in s:
l = (l << 8) | ch
return l
def bn2mpi(v):
have_ext = False
if v.bit_length() > 0:
have_ext = (v.bit_length() & 0x07) == 0
neg = False
if v < 0:
neg = True
v = -v
s = struct.pack(b">I", bn_bytes(v, have_ext))
ext = bytearray()
if have_ext:
ext.append(0)
v_bin = bn2bin(v)
if neg:
if have_ext:
ext[0] |= 0x80
else:
v_bin[0] |= 0x80
return s + ext + v_bin
def mpi2bn(s):
if len(s) < 4:
return None
s_size = bytes(s[:4])
v_len = struct.unpack(b">I", s_size)[0]
if len(s) != (v_len + 4):
return None
if v_len == 0:
return 0
v_str = bytearray(s[4:])
neg = False
i = v_str[0]
if i & 0x80:
neg = True
i &= ~0x80
v_str[0] = i
v = bin2bn(v_str)
if neg:
return -v
return v
# bitcoin-specific little endian format, with implicit size
def mpi2vch(s):
r = s[4:] # strip size
r = r[::-1] # reverse string, converting BE->LE
return r
def bn2vch(v):
return bytes(mpi2vch(bn2mpi(v)))
def vch2mpi(s):
r = struct.pack(b">I", len(s)) # size
r += s[::-1] # reverse string, converting LE->BE
return r
def vch2bn(s):
return mpi2bn(vch2mpi(s))
python-bitcoinlib-python-bitcoinlib-v0.11.0/bitcoin/core/key.py 0000664 0000000 0000000 00000053347 13630543745 0024616 0 ustar 00root root 0000000 0000000 # Copyright (C) 2011 Sam Rushing
# Copyright (C) 2012-2015 The python-bitcoinlib developers
#
# This file is part of python-bitcoinlib.
#
# It is subject to the license terms in the LICENSE file found in the top-level
# directory of this distribution.
#
# No part of python-bitcoinlib, including this file, may be copied, modified,
# propagated, or distributed except according to the terms contained in the
# LICENSE file.
"""ECC secp256k1 crypto routines
WARNING: This module does not mlock() secrets; your private keys may end up on
disk in swap! Use with caution!
"""
import ctypes
import ctypes.util
import hashlib
import sys
from os import urandom
import bitcoin
import bitcoin.signature
_bchr = chr
_bord = ord
if sys.version > '3':
_bchr = lambda x: bytes([x])
_bord = lambda x: x
import bitcoin.core.script
_ssl = ctypes.cdll.LoadLibrary(ctypes.util.find_library('ssl') or 'libeay32')
_libsecp256k1_path = ctypes.util.find_library('secp256k1')
_libsecp256k1_enable_signing = False
_libsecp256k1_context = None
_libsecp256k1 = None
class OpenSSLException(EnvironmentError):
pass
# Thx to Sam Devlin for the ctypes magic 64-bit fix (FIXME: should this
# be applied to every OpenSSL call whose return type is a pointer?)
def _check_res_void_p(val, func, args): # pylint: disable=unused-argument
if val == 0:
errno = _ssl.ERR_get_error()
errmsg = ctypes.create_string_buffer(120)
_ssl.ERR_error_string_n(errno, errmsg, 120)
raise OpenSSLException(errno, str(errmsg.value))
return ctypes.c_void_p(val)
_ssl.BN_add.restype = ctypes.c_int
_ssl.BN_add.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
_ssl.BN_bin2bn.restype = ctypes.c_void_p
_ssl.BN_bin2bn.argtypes = [ctypes.c_char_p, ctypes.c_int, ctypes.c_void_p]
_ssl.BN_cmp.restype = ctypes.c_int
_ssl.BN_cmp.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
_ssl.BN_copy.restype = ctypes.c_void_p
_ssl.BN_copy.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
_ssl.BN_free.restype = None
_ssl.BN_free.argtypes = [ctypes.c_void_p]
_ssl.BN_mod_inverse.restype = ctypes.c_void_p
_ssl.BN_mod_inverse.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
_ssl.BN_mod_mul.restype = ctypes.c_int
_ssl.BN_mod_mul.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
_ssl.BN_mod_sub.restype = ctypes.c_int
_ssl.BN_mod_sub.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
_ssl.BN_mul_word.restype = ctypes.c_int
_ssl.BN_mul_word.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
_ssl.BN_new.errcheck = _check_res_void_p
_ssl.BN_new.restype = ctypes.c_void_p
_ssl.BN_new.argtypes = []
_ssl.BN_rshift.restype = ctypes.c_int
_ssl.BN_rshift.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int]
_ssl.BN_rshift1.restype = ctypes.c_int
_ssl.BN_rshift1.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
_ssl.BN_sub.restype = ctypes.c_int
_ssl.BN_sub.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
# _ssl.BN_zero.restype = ctypes.c_int
# _ssl.BN_zero.argtypes = [ctypes.c_void_p]
_ssl.BN_CTX_free.restype = None
_ssl.BN_CTX_free.argtypes = [ctypes.c_void_p]
_ssl.BN_CTX_get.restype = ctypes.c_void_p
_ssl.BN_CTX_get.argtypes = [ctypes.c_void_p]
_ssl.BN_CTX_new.errcheck = _check_res_void_p
_ssl.BN_CTX_new.restype = ctypes.c_void_p
_ssl.BN_CTX_new.argtypes = []
_ssl.EC_GROUP_get_curve_GFp.restype = ctypes.c_int
_ssl.EC_GROUP_get_curve_GFp.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
_ssl.EC_GROUP_get_degree.restype = ctypes.c_int
_ssl.EC_GROUP_get_degree.argtypes = [ctypes.c_void_p]
_ssl.EC_GROUP_get_order.restype = ctypes.c_int
_ssl.EC_GROUP_get_order.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
_ssl.EC_KEY_free.restype = None
_ssl.EC_KEY_free.argtypes = [ctypes.c_void_p]
_ssl.EC_KEY_new_by_curve_name.errcheck = _check_res_void_p
_ssl.EC_KEY_new_by_curve_name.restype = ctypes.c_void_p
_ssl.EC_KEY_new_by_curve_name.argtypes = [ctypes.c_int]
_ssl.EC_KEY_get0_group.restype = ctypes.c_void_p
_ssl.EC_KEY_get0_group.argtypes = [ctypes.c_void_p]
_ssl.EC_KEY_get0_public_key.restype = ctypes.c_void_p
_ssl.EC_KEY_get0_public_key.argtypes = [ctypes.c_void_p]
_ssl.EC_KEY_set_conv_form.restype = None
_ssl.EC_KEY_set_conv_form.argtypes = [ctypes.c_void_p, ctypes.c_int]
_ssl.EC_KEY_set_private_key.restype = ctypes.c_int
_ssl.EC_KEY_set_private_key.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
_ssl.EC_KEY_set_public_key.restype = ctypes.c_int
_ssl.EC_KEY_set_public_key.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
_ssl.EC_POINT_free.restype = None
_ssl.EC_POINT_free.argtypes = [ctypes.c_void_p]
_ssl.EC_POINT_is_at_infinity.restype = ctypes.c_int
_ssl.EC_POINT_is_at_infinity.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
_ssl.EC_POINT_new.errcheck = _check_res_void_p
_ssl.EC_POINT_new.restype = ctypes.c_void_p
_ssl.EC_POINT_new.argtypes = [ctypes.c_void_p]
_ssl.EC_POINT_mul.restype = ctypes.c_int
_ssl.EC_POINT_mul.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
_ssl.EC_POINT_set_compressed_coordinates_GFp.restype = ctypes.c_int
_ssl.EC_POINT_set_compressed_coordinates_GFp.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p]
_ssl.ECDSA_sign.restype = ctypes.c_int
_ssl.ECDSA_sign.argtypes = [ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
_ssl.ECDSA_size.restype = ctypes.c_int
_ssl.ECDSA_size.argtypes = [ctypes.c_void_p]
_ssl.ECDSA_verify.restype = ctypes.c_int
_ssl.ECDSA_verify.argtypes = [ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p]
_ssl.ECDSA_SIG_free.restype = None
_ssl.ECDSA_SIG_free.argtypes = [ctypes.c_void_p]
_ssl.ECDH_compute_key.restype = ctypes.c_int
_ssl.ECDH_compute_key.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p]
_ssl.ERR_error_string_n.restype = None
_ssl.ERR_error_string_n.argtypes = [ctypes.c_ulong, ctypes.c_char_p, ctypes.c_size_t]
_ssl.ERR_get_error.restype = ctypes.c_ulong
_ssl.ERR_get_error.argtypes = []
_ssl.d2i_ECDSA_SIG.restype = ctypes.c_void_p
_ssl.d2i_ECDSA_SIG.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_long]
_ssl.d2i_ECPrivateKey.restype = ctypes.c_void_p
_ssl.d2i_ECPrivateKey.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_long]
_ssl.i2d_ECDSA_SIG.restype = ctypes.c_int
_ssl.i2d_ECDSA_SIG.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
_ssl.i2d_ECPrivateKey.restype = ctypes.c_int
_ssl.i2d_ECPrivateKey.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
_ssl.i2o_ECPublicKey.restype = ctypes.c_void_p
_ssl.i2o_ECPublicKey.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
_ssl.o2i_ECPublicKey.restype = ctypes.c_void_p
_ssl.o2i_ECPublicKey.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_long]
_ssl.BN_num_bits.restype = ctypes.c_int
_ssl.BN_num_bits.argtypes = [ctypes.c_void_p]
_ssl.EC_KEY_get0_private_key.restype = ctypes.c_void_p
# this specifies the curve used with ECDSA.
_NID_secp256k1 = 714 # from openssl/obj_mac.h
# test that OpenSSL supports secp256k1
_ssl.EC_KEY_new_by_curve_name(_NID_secp256k1)
SECP256K1_FLAGS_TYPE_CONTEXT = (1 << 0)
SECP256K1_FLAGS_BIT_CONTEXT_SIGN = (1 << 9)
SECP256K1_CONTEXT_SIGN = \
(SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN)
def is_libsec256k1_available():
return _libsecp256k1_path is not None
def use_libsecp256k1_for_signing(do_use):
global _libsecp256k1
global _libsecp256k1_context
global _libsecp256k1_enable_signing
if not do_use:
_libsecp256k1_enable_signing = False
return
if not is_libsec256k1_available():
raise ImportError("unable to locate libsecp256k1")
if _libsecp256k1_context is None:
_libsecp256k1 = ctypes.cdll.LoadLibrary(_libsecp256k1_path)
_libsecp256k1.secp256k1_context_create.restype = ctypes.c_void_p
_libsecp256k1.secp256k1_context_create.errcheck = _check_res_void_p
_libsecp256k1.secp256k1_context_randomize.restype = ctypes.c_int
_libsecp256k1.secp256k1_context_randomize.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
_libsecp256k1_context = _libsecp256k1.secp256k1_context_create(SECP256K1_CONTEXT_SIGN)
assert(_libsecp256k1_context is not None)
seed = urandom(32)
result = _libsecp256k1.secp256k1_context_randomize(_libsecp256k1_context, seed)
assert 1 == result
_libsecp256k1_enable_signing = True
# From openssl/ecdsa.h
class ECDSA_SIG_st(ctypes.Structure):
_fields_ = [("r", ctypes.c_void_p),
("s", ctypes.c_void_p)]
class CECKey:
"""Wrapper around OpenSSL's EC_KEY"""
POINT_CONVERSION_COMPRESSED = 2
POINT_CONVERSION_UNCOMPRESSED = 4
def __init__(self):
self.k = _ssl.EC_KEY_new_by_curve_name(_NID_secp256k1)
def __del__(self):
if _ssl:
_ssl.EC_KEY_free(self.k)
self.k = None
def set_secretbytes(self, secret):
priv_key = _ssl.BN_bin2bn(secret, 32, None)
group = _ssl.EC_KEY_get0_group(self.k)
pub_key = _ssl.EC_POINT_new(group)
ctx = _ssl.BN_CTX_new()
if not _ssl.EC_POINT_mul(group, pub_key, priv_key, None, None, ctx):
raise ValueError("Could not derive public key from the supplied secret.")
_ssl.EC_KEY_set_private_key(self.k, priv_key)
_ssl.EC_KEY_set_public_key(self.k, pub_key)
_ssl.EC_POINT_free(pub_key)
_ssl.BN_free(priv_key)
_ssl.BN_CTX_free(ctx)
return self.k
def set_privkey(self, key):
self.mb = ctypes.create_string_buffer(key)
return _ssl.d2i_ECPrivateKey(ctypes.byref(self.k), ctypes.byref(ctypes.pointer(self.mb)), len(key))
def set_pubkey(self, key):
self.mb = ctypes.create_string_buffer(key)
return _ssl.o2i_ECPublicKey(ctypes.byref(self.k), ctypes.byref(ctypes.pointer(self.mb)), len(key))
def get_privkey(self):
size = _ssl.i2d_ECPrivateKey(self.k, 0)
mb_pri = ctypes.create_string_buffer(size)
_ssl.i2d_ECPrivateKey(self.k, ctypes.byref(ctypes.pointer(mb_pri)))
return mb_pri.raw
def get_pubkey(self):
size = _ssl.i2o_ECPublicKey(self.k, 0)
mb = ctypes.create_string_buffer(size)
_ssl.i2o_ECPublicKey(self.k, ctypes.byref(ctypes.pointer(mb)))
return mb.raw
def get_raw_ecdh_key(self, other_pubkey):
ecdh_keybuffer = ctypes.create_string_buffer(32)
r = _ssl.ECDH_compute_key(ctypes.pointer(ecdh_keybuffer), 32,
_ssl.EC_KEY_get0_public_key(other_pubkey.k),
self.k, 0)
if r != 32:
raise Exception('CKey.get_ecdh_key(): ECDH_compute_key() failed')
return ecdh_keybuffer.raw
def get_ecdh_key(self, other_pubkey, kdf=lambda k: hashlib.sha256(k).digest()):
# FIXME: be warned it's not clear what the kdf should be as a default
r = self.get_raw_ecdh_key(other_pubkey)
return kdf(r)
def get_raw_privkey(self):
bn = _ssl.EC_KEY_get0_private_key(self.k)
bn = ctypes.c_void_p(bn)
size = (_ssl.BN_num_bits(bn) + 7) / 8
mb = ctypes.create_string_buffer(int(size))
_ssl.BN_bn2bin(bn, mb)
return mb.raw.rjust(32, b'\x00')
def _sign_with_libsecp256k1(self, hash):
raw_sig = ctypes.create_string_buffer(64)
result = _libsecp256k1.secp256k1_ecdsa_sign(
_libsecp256k1_context, raw_sig, hash, self.get_raw_privkey(), None, None)
assert 1 == result
sig_size0 = ctypes.c_size_t()
sig_size0.value = 75
mb_sig = ctypes.create_string_buffer(sig_size0.value)
result = _libsecp256k1.secp256k1_ecdsa_signature_serialize_der(
_libsecp256k1_context, mb_sig, ctypes.byref(sig_size0), raw_sig)
assert 1 == result
# libsecp256k1 creates signatures already in lower-S form, no further
# conversion needed.
return mb_sig.raw[:sig_size0.value]
def sign(self, hash): # pylint: disable=redefined-builtin
if not isinstance(hash, bytes):
raise TypeError('Hash must be bytes instance; got %r' % hash.__class__)
if len(hash) != 32:
raise ValueError('Hash must be exactly 32 bytes long')
if _libsecp256k1_enable_signing:
return self._sign_with_libsecp256k1(hash)
sig_size0 = ctypes.c_uint32()
sig_size0.value = _ssl.ECDSA_size(self.k)
mb_sig = ctypes.create_string_buffer(sig_size0.value)
result = _ssl.ECDSA_sign(0, hash, len(hash), mb_sig, ctypes.byref(sig_size0), self.k)
assert 1 == result
if bitcoin.core.script.IsLowDERSignature(mb_sig.raw[:sig_size0.value]):
return mb_sig.raw[:sig_size0.value]
else:
return self.signature_to_low_s(mb_sig.raw[:sig_size0.value])
def sign_compact(self, hash): # pylint: disable=redefined-builtin
if not isinstance(hash, bytes):
raise TypeError('Hash must be bytes instance; got %r' % hash.__class__)
if len(hash) != 32:
raise ValueError('Hash must be exactly 32 bytes long')
sig_size0 = ctypes.c_uint32()
sig_size0.value = _ssl.ECDSA_size(self.k)
mb_sig = ctypes.create_string_buffer(sig_size0.value)
result = _ssl.ECDSA_sign(0, hash, len(hash), mb_sig, ctypes.byref(sig_size0), self.k)
assert 1 == result
if bitcoin.core.script.IsLowDERSignature(mb_sig.raw[:sig_size0.value]):
sig = mb_sig.raw[:sig_size0.value]
else:
sig = self.signature_to_low_s(mb_sig.raw[:sig_size0.value])
sig = bitcoin.signature.DERSignature.deserialize(sig)
r_val = sig.r
s_val = sig.s
# assert that the r and s are less than 32 long, excluding leading 0s
assert len(r_val) <= 32 or r_val[0:-32] == b'\x00'
assert len(s_val) <= 32 or s_val[0:-32] == b'\x00'
# ensure r and s are always 32 chars long by 0padding
r_val = ((b'\x00' * 32) + r_val)[-32:]
s_val = ((b'\x00' * 32) + s_val)[-32:]
# tmp pubkey of self, but always compressed
pubkey = CECKey()
pubkey.set_pubkey(self.get_pubkey())
pubkey.set_compressed(True)
# bitcoin core does <4, but I've seen other places do <2 and I've never seen a i > 1 so far
for i in range(0, 4):
cec_key = CECKey()
cec_key.set_compressed(True)
result = cec_key.recover(r_val, s_val, hash, len(hash), i, 1)
if result == 1:
if cec_key.get_pubkey() == pubkey.get_pubkey():
return r_val + s_val, i
raise ValueError
def signature_to_low_s(self, sig):
der_sig = ECDSA_SIG_st()
_ssl.d2i_ECDSA_SIG(ctypes.byref(ctypes.pointer(der_sig)), ctypes.byref(ctypes.c_char_p(sig)), len(sig))
group = _ssl.EC_KEY_get0_group(self.k)
order = _ssl.BN_new()
halforder = _ssl.BN_new()
ctx = _ssl.BN_CTX_new()
_ssl.EC_GROUP_get_order(group, order, ctx)
_ssl.BN_rshift1(halforder, order)
# Verify that s is over half the order of the curve before we actually subtract anything from it
if _ssl.BN_cmp(der_sig.s, halforder) > 0:
_ssl.BN_sub(der_sig.s, order, der_sig.s)
_ssl.BN_free(halforder)
_ssl.BN_free(order)
_ssl.BN_CTX_free(ctx)
derlen = _ssl.i2d_ECDSA_SIG(ctypes.pointer(der_sig), 0)
if derlen == 0:
_ssl.ECDSA_SIG_free(der_sig)
return None
new_sig = ctypes.create_string_buffer(derlen)
_ssl.i2d_ECDSA_SIG(ctypes.pointer(der_sig), ctypes.byref(ctypes.pointer(new_sig)))
_ssl.BN_free(der_sig.r)
_ssl.BN_free(der_sig.s)
return new_sig.raw
def verify(self, hash, sig): # pylint: disable=redefined-builtin
"""Verify a DER signature"""
if not sig:
return False
# New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first.
norm_sig = ctypes.c_void_p(0)
_ssl.d2i_ECDSA_SIG(ctypes.byref(norm_sig), ctypes.byref(ctypes.c_char_p(sig)), len(sig))
derlen = _ssl.i2d_ECDSA_SIG(norm_sig, 0)
if derlen == 0:
_ssl.ECDSA_SIG_free(norm_sig)
return False
norm_der = ctypes.create_string_buffer(derlen)
_ssl.i2d_ECDSA_SIG(norm_sig, ctypes.byref(ctypes.pointer(norm_der)))
_ssl.ECDSA_SIG_free(norm_sig)
# -1 = error, 0 = bad sig, 1 = good
return _ssl.ECDSA_verify(0, hash, len(hash), norm_der, derlen, self.k) == 1
def set_compressed(self, compressed):
if compressed:
form = self.POINT_CONVERSION_COMPRESSED
else:
form = self.POINT_CONVERSION_UNCOMPRESSED
_ssl.EC_KEY_set_conv_form(self.k, form)
def recover(self, sigR, sigS, msg, msglen, recid, check):
"""
Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
recid selects which key is recovered
if check is non-zero, additional checks are performed
"""
i = int(recid / 2)
r = None
s = None
ctx = None
R = None
O = None
Q = None
assert len(sigR) == 32, len(sigR)
assert len(sigS) == 32, len(sigS)
try:
r = _ssl.BN_bin2bn(bytes(sigR), len(sigR), _ssl.BN_new())
s = _ssl.BN_bin2bn(bytes( sigS), len(sigS), _ssl.BN_new())
group = _ssl.EC_KEY_get0_group(self.k)
ctx = _ssl.BN_CTX_new()
order = _ssl.BN_CTX_get(ctx)
ctx = _ssl.BN_CTX_new()
if not _ssl.EC_GROUP_get_order(group, order, ctx):
return -2
x = _ssl.BN_CTX_get(ctx)
if not _ssl.BN_copy(x, order):
return -1
if not _ssl.BN_mul_word(x, i):
return -1
if not _ssl.BN_add(x, x, r):
return -1
field = _ssl.BN_CTX_get(ctx)
if not _ssl.EC_GROUP_get_curve_GFp(group, field, None, None, ctx):
return -2
if _ssl.BN_cmp(x, field) >= 0:
return 0
R = _ssl.EC_POINT_new(group)
if R is None:
return -2
if not _ssl.EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx):
return 0
if check:
O = _ssl.EC_POINT_new(group)
if O is None:
return -2
if not _ssl.EC_POINT_mul(group, O, None, R, order, ctx):
return -2
if not _ssl.EC_POINT_is_at_infinity(group, O):
return 0
Q = _ssl.EC_POINT_new(group)
if Q is None:
return -2
n = _ssl.EC_GROUP_get_degree(group)
e = _ssl.BN_CTX_get(ctx)
if not _ssl.BN_bin2bn(msg, msglen, e):
return -1
if 8 * msglen > n:
_ssl.BN_rshift(e, e, 8 - (n & 7))
zero = _ssl.BN_CTX_get(ctx)
# if not _ssl.BN_zero(zero):
# return -1
if not _ssl.BN_mod_sub(e, zero, e, order, ctx):
return -1
rr = _ssl.BN_CTX_get(ctx)
if not _ssl.BN_mod_inverse(rr, r, order, ctx):
return -1
sor = _ssl.BN_CTX_get(ctx)
if not _ssl.BN_mod_mul(sor, s, rr, order, ctx):
return -1
eor = _ssl.BN_CTX_get(ctx)
if not _ssl.BN_mod_mul(eor, e, rr, order, ctx):
return -1
if not _ssl.EC_POINT_mul(group, Q, eor, R, sor, ctx):
return -2
if not _ssl.EC_KEY_set_public_key(self.k, Q):
return -2
return 1
finally:
if r: _ssl.BN_free(r)
if s: _ssl.BN_free(s)
if ctx: _ssl.BN_CTX_free(ctx)
if R: _ssl.EC_POINT_free(R)
if O: _ssl.EC_POINT_free(O)
if Q: _ssl.EC_POINT_free(Q)
class CPubKey(bytes):
"""An encapsulated public key
Attributes:
is_valid - Corresponds to CPubKey.IsValid()
is_fullyvalid - Corresponds to CPubKey.IsFullyValid()
is_compressed - Corresponds to CPubKey.IsCompressed()
"""
def __new__(cls, buf, _cec_key=None):
self = super(CPubKey, cls).__new__(cls, buf)
if _cec_key is None:
_cec_key = CECKey()
self._cec_key = _cec_key
self.is_fullyvalid = _cec_key.set_pubkey(self) is not None
return self
@classmethod
def recover_compact(cls, hash, sig): # pylint: disable=redefined-builtin
"""Recover a public key from a compact signature."""
if len(sig) != 65:
raise ValueError("Signature should be 65 characters, not [%d]" % (len(sig), ))
recid = (_bord(sig[0]) - 27) & 3
compressed = (_bord(sig[0]) - 27) & 4 != 0
cec_key = CECKey()
cec_key.set_compressed(compressed)
sigR = sig[1:33]
sigS = sig[33:65]
result = cec_key.recover(sigR, sigS, hash, len(hash), recid, 0)
if result < 1:
return False
pubkey = cec_key.get_pubkey()
return CPubKey(pubkey, _cec_key=cec_key)
@property
def is_valid(self):
return len(self) > 0
@property
def is_compressed(self):
return len(self) == 33
def verify(self, hash, sig): # pylint: disable=redefined-builtin
return self._cec_key.verify(hash, sig)
def __str__(self):
return repr(self)
def __repr__(self):
# Always have represent as b'' so test cases don't have to
# change for py2/3
if sys.version > '3':
return '%s(%s)' % (self.__class__.__name__, super(CPubKey, self).__repr__())
else:
return '%s(b%s)' % (self.__class__.__name__, super(CPubKey, self).__repr__())
__all__ = (
'CECKey',
'CPubKey',
)
python-bitcoinlib-python-bitcoinlib-v0.11.0/bitcoin/core/script.py 0000664 0000000 0000000 00000104463 13630543745 0025326 0 ustar 00root root 0000000 0000000 # Copyright (C) 2012-2015 The python-bitcoinlib developers
#
# This file is part of python-bitcoinlib.
#
# It is subject to the license terms in the LICENSE file found in the top-level
# directory of this distribution.
#
# No part of python-bitcoinlib, including this file, may be copied, modified,
# propagated, or distributed except according to the terms contained in the
# LICENSE file.
"""Scripts
Functionality to build scripts, as well as SignatureHash(). Script evaluation
is in bitcoin.core.scripteval
"""
from __future__ import absolute_import, division, print_function
import sys
_bchr = chr
_bord = ord
if sys.version > '3':
long = int
_bchr = lambda x: bytes([x])
_bord = lambda x: x
from io import BytesIO as _BytesIO
else:
from cStringIO import StringIO as _BytesIO
import struct
import bitcoin.core
import bitcoin.core._bignum
from .serialize import *
MAX_SCRIPT_SIZE = 10000
MAX_SCRIPT_ELEMENT_SIZE = 520
MAX_SCRIPT_OPCODES = 201
OPCODE_NAMES = {}
_opcode_instances = []
class CScriptOp(int):
"""A single script opcode"""
__slots__ = []
@staticmethod
def encode_op_pushdata(d):
"""Encode a PUSHDATA op, returning bytes"""
if len(d) < 0x4c:
return b'' + _bchr(len(d)) + d # OP_PUSHDATA
elif len(d) <= 0xff:
return b'\x4c' + _bchr(len(d)) + d # OP_PUSHDATA1
elif len(d) <= 0xffff:
return b'\x4d' + struct.pack(b' OP_PUSHDATA4:
yield (opcode, None, sop_idx)
else:
datasize = None
pushdata_type = None
if opcode < OP_PUSHDATA1:
pushdata_type = 'PUSHDATA(%d)' % opcode
datasize = opcode
elif opcode == OP_PUSHDATA1:
pushdata_type = 'PUSHDATA1'
if i >= len(self):
raise CScriptInvalidError('PUSHDATA1: missing data length')
datasize = _bord(self[i])
i += 1
elif opcode == OP_PUSHDATA2:
pushdata_type = 'PUSHDATA2'
if i + 1 >= len(self):
raise CScriptInvalidError('PUSHDATA2: missing data length')
datasize = _bord(self[i]) + (_bord(self[i+1]) << 8)
i += 2
elif opcode == OP_PUSHDATA4:
pushdata_type = 'PUSHDATA4'
if i + 3 >= len(self):
raise CScriptInvalidError('PUSHDATA4: missing data length')
datasize = _bord(self[i]) + (_bord(self[i+1]) << 8) + (_bord(self[i+2]) << 16) + (_bord(self[i+3]) << 24)
i += 4
else:
assert False # shouldn't happen
data = bytes(self[i:i+datasize])
# Check for truncation
if len(data) < datasize:
raise CScriptTruncatedPushDataError('%s: truncated data' % pushdata_type, data)
i += datasize
yield (opcode, data, sop_idx)
def __iter__(self):
"""'Cooked' iteration
Returns either a CScriptOP instance, an integer, or bytes, as
appropriate.
See raw_iter() if you need to distinguish the different possible
PUSHDATA encodings.
"""
for (opcode, data, sop_idx) in self.raw_iter():
if opcode == 0:
yield 0
elif data is not None:
yield data
else:
opcode = CScriptOp(opcode)
if opcode.is_small_int():
yield opcode.decode_op_n()
else:
yield CScriptOp(opcode)
def __repr__(self):
# For Python3 compatibility add b before strings so testcases don't
# need to change
def _repr(o):
if isinstance(o, bytes):
return "x('%s')" % bitcoin.core.b2x(o)
else:
return repr(o)
ops = []
i = iter(self)
while True:
op = None
try:
op = _repr(next(i))
except CScriptTruncatedPushDataError as err:
op = '%s...' % (_repr(err.data), err)
break
except CScriptInvalidError as err:
op = '' % err
break
except StopIteration:
break
finally:
if op is not None:
ops.append(op)
return "CScript([%s])" % ', '.join(ops)
def is_p2sh(self):
"""Test if the script is a p2sh scriptPubKey
Note that this test is consensus-critical.
"""
return (len(self) == 23 and
_bord(self[0]) == OP_HASH160 and
_bord(self[1]) == 0x14 and
_bord(self[22]) == OP_EQUAL)
def is_witness_scriptpubkey(self):
"""Returns true if this is a scriptpubkey signaling segregated witness data.
A witness program is any valid CScript that consists of a 1-byte push opcode
followed by a data push between 2 and 40 bytes.
"""
size = len(self)
if size < 4 or size > 42:
return False
head = struct.unpack(' OP_16:
return False
except CScriptInvalidError:
return False
return True
def has_canonical_pushes(self):
"""Test if script only uses canonical pushes
Not yet consensus critical; may be in the future.
"""
try:
for (op, data, idx) in self.raw_iter():
if op > OP_16:
continue
elif op < OP_PUSHDATA1 and op > OP_0 and len(data) == 1 and _bord(data[0]) <= 16:
# Could have used an OP_n code, rather than a 1-byte push.
return False
elif op == OP_PUSHDATA1 and len(data) < OP_PUSHDATA1:
# Could have used a normal n-byte push, rather than OP_PUSHDATA1.
return False
elif op == OP_PUSHDATA2 and len(data) <= 0xFF:
# Could have used a OP_PUSHDATA1.
return False
elif op == OP_PUSHDATA4 and len(data) <= 0xFFFF:
# Could have used a OP_PUSHDATA2.
return False
except CScriptInvalidError: # Invalid pushdata
return False
return True
def is_unspendable(self):
"""Test if the script is provably unspendable"""
return (len(self) > 0 and
_bord(self[0]) == OP_RETURN)
def is_valid(self):
"""Return True if the script is valid, False otherwise
The script is valid if all PUSHDATA's are valid; invalid opcodes do not
make is_valid() return False.
"""
try:
list(self)
except CScriptInvalidError:
return False
return True
def to_p2sh_scriptPubKey(self, checksize=True):
"""Create P2SH scriptPubKey from this redeemScript
That is, create the P2SH scriptPubKey that requires this script as a
redeemScript to spend.
checksize - Check if the redeemScript is larger than the 520-byte max
pushdata limit; raise ValueError if limit exceeded.
Since a >520-byte PUSHDATA makes EvalScript() fail, it's not actually
possible to redeem P2SH outputs with redeem scripts >520 bytes.
"""
if checksize and len(self) > MAX_SCRIPT_ELEMENT_SIZE:
raise ValueError("redeemScript exceeds max allowed size; P2SH output would be unspendable")
return CScript([OP_HASH160, bitcoin.core.Hash160(self), OP_EQUAL])
def GetSigOpCount(self, fAccurate):
"""Get the SigOp count.
fAccurate - Accurately count CHECKMULTISIG, see BIP16 for details.
Note that this is consensus-critical.
"""
n = 0
lastOpcode = OP_INVALIDOPCODE
for (opcode, data, sop_idx) in self.raw_iter():
if opcode in (OP_CHECKSIG, OP_CHECKSIGVERIFY):
n += 1
elif opcode in (OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY):
if fAccurate and (OP_1 <= lastOpcode <= OP_16):
n += opcode.decode_op_n()
else:
n += 20
lastOpcode = opcode
return n
class CScriptWitness(ImmutableSerializable):
"""An encoding of the data elements on the initial stack for (segregated
witness)
"""
__slots__ = ['stack']
def __init__(self, stack=()):
object.__setattr__(self, 'stack', stack)
def __len__(self):
return len(self.stack)
def __iter__(self):
return iter(self.stack)
def __repr__(self):
return 'CScriptWitness(' + ','.join("x('%s')" % bitcoin.core.b2x(s) for s in self.stack) + ')'
def is_null(self):
return len(self.stack) == 0
@classmethod
def stream_deserialize(cls, f):
n = VarIntSerializer.stream_deserialize(f)
stack = tuple(BytesSerializer.stream_deserialize(f) for i in range(n))
return cls(stack)
def stream_serialize(self, f):
VarIntSerializer.stream_serialize(len(self.stack), f)
for s in self.stack:
BytesSerializer.stream_serialize(s, f)
SIGHASH_ALL = 1
SIGHASH_NONE = 2
SIGHASH_SINGLE = 3
SIGHASH_ANYONECANPAY = 0x80
def FindAndDelete(script, sig):
"""Consensus critical, see FindAndDelete() in Satoshi codebase"""
r = b''
last_sop_idx = sop_idx = 0
skip = True
for (opcode, data, sop_idx) in script.raw_iter():
if not skip:
r += script[last_sop_idx:sop_idx]
last_sop_idx = sop_idx
if script[sop_idx:sop_idx + len(sig)] == sig:
skip = True
else:
skip = False
if not skip:
r += script[last_sop_idx:]
return CScript(r)
def IsLowDERSignature(sig):
"""
Loosely correlates with IsLowDERSignature() from script/interpreter.cpp
Verifies that the S value in a DER signature is the lowest possible value.
Used by BIP62 malleability fixes.
"""
length_r = sig[3]
if isinstance(length_r, str):
length_r = int(struct.unpack('B', length_r)[0])
length_s = sig[5 + length_r]
if isinstance(length_s, str):
length_s = int(struct.unpack('B', length_s)[0])
s_val = list(struct.unpack(str(length_s) + 'B', sig[6 + length_r:6 + length_r + length_s]))
# If the S value is above the order of the curve divided by two, its
# complement modulo the order could have been used instead, which is
# one byte shorter when encoded correctly.
max_mod_half_order = [
0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x5d,0x57,0x6e,0x73,0x57,0xa4,0x50,0x1d,
0xdf,0xe9,0x2f,0x46,0x68,0x1b,0x20,0xa0]
return CompareBigEndian(s_val, [0]) > 0 and \
CompareBigEndian(s_val, max_mod_half_order) <= 0
def CompareBigEndian(c1, c2):
"""
Loosely matches CompareBigEndian() from eccryptoverify.cpp
Compares two arrays of bytes, and returns a negative value if the first is
less than the second, 0 if they're equal, and a positive value if the
first is greater than the second.
"""
c1 = list(c1)
c2 = list(c2)
# Adjust starting positions until remaining lengths of the two arrays match
while len(c1) > len(c2):
if c1.pop(0) > 0:
return 1
while len(c2) > len(c1):
if c2.pop(0) > 0:
return -1
while len(c1) > 0:
diff = c1.pop(0) - c2.pop(0)
if diff != 0:
return diff
return 0
def RawSignatureHash(script, txTo, inIdx, hashtype):
"""Consensus-correct SignatureHash
Returns (hash, err) to precisely match the consensus-critical behavior of
the SIGHASH_SINGLE bug. (inIdx is *not* checked for validity)
If you're just writing wallet software you probably want SignatureHash()
instead.
"""
HASH_ONE = b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
if inIdx >= len(txTo.vin):
return (HASH_ONE, "inIdx %d out of range (%d)" % (inIdx, len(txTo.vin)))
txtmp = bitcoin.core.CMutableTransaction.from_tx(txTo)
for txin in txtmp.vin:
txin.scriptSig = b''
txtmp.vin[inIdx].scriptSig = FindAndDelete(script, CScript([OP_CODESEPARATOR]))
if (hashtype & 0x1f) == SIGHASH_NONE:
txtmp.vout = []
for i in range(len(txtmp.vin)):
if i != inIdx:
txtmp.vin[i].nSequence = 0
elif (hashtype & 0x1f) == SIGHASH_SINGLE:
outIdx = inIdx
if outIdx >= len(txtmp.vout):
return (HASH_ONE, "outIdx %d out of range (%d)" % (outIdx, len(txtmp.vout)))
tmp = txtmp.vout[outIdx]
txtmp.vout = []
for i in range(outIdx):
txtmp.vout.append(bitcoin.core.CTxOut())
txtmp.vout.append(tmp)
for i in range(len(txtmp.vin)):
if i != inIdx:
txtmp.vin[i].nSequence = 0
if hashtype & SIGHASH_ANYONECANPAY:
tmp = txtmp.vin[inIdx]
txtmp.vin = []
txtmp.vin.append(tmp)
txtmp.wit = bitcoin.core.CTxWitness()
s = txtmp.serialize()
s += struct.pack(b"