forked from spesmilo/electrumx
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add zcash v5 (nu5) transactions support (draft)
Issue: spesmilo#181 Todo: clean-up mininode and other unused code in electrumx/lib/zcash, rewrite zcash_txid_v5 using only bytes object operations and hashes computation, probably, without full tx (re)construct.
- Loading branch information
Showing
9 changed files
with
4,720 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
#!/usr/bin/env python3 | ||
# | ||
# bignum.py | ||
# | ||
# This file is copied from python-bitcoinlib. | ||
# | ||
# Distributed under the MIT software license, see the accompanying | ||
# file COPYING or https://www.opensource.org/licenses/mit-license.php . | ||
# | ||
|
||
"""Bignum routines""" | ||
|
||
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)) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
#!/usr/bin/env python3 | ||
# Copyright (c) 2015-2016 The Bitcoin Core developers | ||
# Copyright (c) 2020-2022 The Zcash developers | ||
# Distributed under the MIT software license, see the accompanying | ||
# file COPYING or https://www.opensource.org/licenses/mit-license.php . | ||
|
||
""" | ||
This module contains utilities for doing coverage analysis on the RPC | ||
interface. | ||
It provides a way to track which RPC commands are exercised during | ||
testing. | ||
""" | ||
import os | ||
|
||
|
||
REFERENCE_FILENAME = 'rpc_interface.txt' | ||
|
||
|
||
class AuthServiceProxyWrapper(object): | ||
""" | ||
An object that wraps AuthServiceProxy to record specific RPC calls. | ||
""" | ||
def __init__(self, auth_service_proxy_instance, coverage_logfile=None): | ||
""" | ||
Kwargs: | ||
auth_service_proxy_instance (AuthServiceProxy): the instance | ||
being wrapped. | ||
coverage_logfile (str): if specified, write each service_name | ||
out to a file when called. | ||
""" | ||
self.auth_service_proxy_instance = auth_service_proxy_instance | ||
self.coverage_logfile = coverage_logfile | ||
|
||
def __getattr__(self, *args, **kwargs): | ||
return_val = self.auth_service_proxy_instance.__getattr__( | ||
*args, **kwargs) | ||
|
||
return AuthServiceProxyWrapper(return_val, self.coverage_logfile) | ||
|
||
def __call__(self, *args, **kwargs): | ||
""" | ||
Delegates to AuthServiceProxy, then writes the particular RPC method | ||
called to a file. | ||
""" | ||
return_val = self.auth_service_proxy_instance.__call__(*args, **kwargs) | ||
rpc_method = self.auth_service_proxy_instance._service_name | ||
|
||
if self.coverage_logfile: | ||
with open(self.coverage_logfile, 'a+', encoding='utf8') as f: | ||
f.write("%s\n" % rpc_method) | ||
|
||
return return_val | ||
|
||
@property | ||
def url(self): | ||
return self.auth_service_proxy_instance.url | ||
|
||
|
||
def get_filename(dirname, n_node): | ||
""" | ||
Get a filename unique to the test process ID and node. | ||
This file will contain a list of RPC commands covered. | ||
""" | ||
pid = str(os.getpid()) | ||
return os.path.join( | ||
dirname, "coverage.pid%s.node%s.txt" % (pid, str(n_node))) | ||
|
||
|
||
def write_all_rpc_commands(dirname, node): | ||
""" | ||
Write out a list of all RPC functions available in `bitcoin-cli` for | ||
coverage comparison. This will only happen once per coverage | ||
directory. | ||
Args: | ||
dirname (str): temporary test dir | ||
node (AuthServiceProxy): client | ||
Returns: | ||
bool. if the RPC interface file was written. | ||
""" | ||
filename = os.path.join(dirname, REFERENCE_FILENAME) | ||
|
||
if os.path.isfile(filename): | ||
return False | ||
|
||
help_output = node.help().split('\n') | ||
commands = set() | ||
|
||
for line in help_output: | ||
line = line.strip() | ||
|
||
# Ignore blanks and headers | ||
if line and not line.startswith('='): | ||
commands.add("%s\n" % line.split()[0]) | ||
|
||
with open(filename, 'w', encoding='utf8') as f: | ||
f.writelines(list(commands)) | ||
|
||
return True |
Oops, something went wrong.