ready for takeoff
This commit is contained in:
parent
8fb382449c
commit
aaf9e7b4db
|
@ -0,0 +1,92 @@
|
|||
raw_items = """ecc.S256Point.xonly
|
||||
ecc.S256Point.verify_schnorr
|
||||
ecc.PrivateKey.sign_schnorr
|
||||
ecc.S256Point.tweak
|
||||
ecc.S256Point.tweaked_key
|
||||
ecc.S256Point.p2tr_script
|
||||
ecc.PrivateKey.tweaked_key
|
||||
taproot.TapLeaf.hash
|
||||
taproot.TapBranch.hash
|
||||
taproot.ControlBlock.merkle_root
|
||||
taproot.ControlBlock.external_pubkey
|
||||
"""
|
||||
|
||||
|
||||
def chop_word(s):
|
||||
for i, _ in enumerate(s):
|
||||
letter = s[i:i+1]
|
||||
if letter not in "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_":
|
||||
return s[:i]
|
||||
|
||||
raw_items_2 = """hash.tagged_hash
|
||||
op.op_checksigadd_schnorr
|
||||
"""
|
||||
|
||||
to_clear = {}
|
||||
files = {}
|
||||
for item in raw_items_2.split():
|
||||
components = item.split('.')
|
||||
files[components[0]] = 1
|
||||
to_clear[item] = 1
|
||||
|
||||
for filename in files.keys():
|
||||
modified_file = ""
|
||||
with open(f"session/{filename}.py", "r") as file:
|
||||
current_func = None
|
||||
active = False
|
||||
for line in file:
|
||||
if line == "\n":
|
||||
if active:
|
||||
modified_file += " raise NotImplementedError\n"
|
||||
active = False
|
||||
if current_func:
|
||||
current_func = None
|
||||
if active:
|
||||
if line.lstrip().startswith("#") or line.lstrip().startswith("\"\"\""):
|
||||
modified_file += line
|
||||
else:
|
||||
modified_file += line
|
||||
if line.startswith("def "):
|
||||
current_func = chop_word(line.lstrip()[4:])
|
||||
key = f"{filename}.{current_func}"
|
||||
if to_clear.get(key):
|
||||
active = True
|
||||
with open(f"session/{filename}.py", "w") as file:
|
||||
file.write(modified_file)
|
||||
|
||||
to_clear = {}
|
||||
files = {}
|
||||
for item in raw_items.split():
|
||||
components = item.split('.')
|
||||
files[components[0]] = 1
|
||||
to_clear[item] = 1
|
||||
|
||||
for filename in files.keys():
|
||||
modified_file = ""
|
||||
with open(f"session/{filename}.py", "r") as file:
|
||||
current_class = None
|
||||
current_func = None
|
||||
active = False
|
||||
for line in file:
|
||||
if line == "\n":
|
||||
if active:
|
||||
modified_file += " raise NotImplementedError\n"
|
||||
active = False
|
||||
if current_func:
|
||||
current_func = None
|
||||
elif current_class:
|
||||
current_class = None
|
||||
if active:
|
||||
if line.lstrip().startswith("#") or line.lstrip().startswith("\"\"\""):
|
||||
modified_file += line
|
||||
else:
|
||||
modified_file += line
|
||||
if line.startswith("class "):
|
||||
current_class = chop_word(line[6:])
|
||||
if line.startswith(" def "):
|
||||
current_func = chop_word(line.lstrip()[4:])
|
||||
key = f"{filename}.{current_class}.{current_func}"
|
||||
if to_clear.get(key):
|
||||
active = True
|
||||
with open(f"session/{filename}.py", "w") as file:
|
||||
file.write(modified_file)
|
|
@ -0,0 +1,31 @@
|
|||
from shutil import copy
|
||||
|
||||
raw_items = """ecc.S256Point.xonly
|
||||
ecc.S256Point.verify_schnorr
|
||||
ecc.PrivateKey.sign_schnorr
|
||||
ecc.S256Point.tweak
|
||||
ecc.S256Point.tweaked_key
|
||||
ecc.S256Point.p2tr_script
|
||||
ecc.PrivateKey.tweaked_key
|
||||
taproot.TapLeaf.hash
|
||||
taproot.TapBranch.hash
|
||||
taproot.ControlBlock.merkle_root
|
||||
taproot.ControlBlock.external_pubkey
|
||||
"""
|
||||
|
||||
raw_items_2 = """hash.tagged_hash
|
||||
op.op_checksigadd_schnorr
|
||||
"""
|
||||
|
||||
files = {}
|
||||
|
||||
for item in raw_items.split():
|
||||
components = item.split('.')
|
||||
files[components[0]] = 1
|
||||
|
||||
for item in raw_items_2.split():
|
||||
components = item.split('.')
|
||||
files[components[0]] = 1
|
||||
|
||||
for filename in files.keys():
|
||||
copy(f"session/complete/{filename}.py", f"session/{filename}.py")
|
|
@ -271,27 +271,21 @@ class S256Point(Point):
|
|||
def xonly(self):
|
||||
"""returns the binary version of X-only pubkey"""
|
||||
# if x is None, return 32 0 bytes
|
||||
if self.x is None:
|
||||
return b"\x00" * 32
|
||||
# otherwise, convert the x coordinate to Big Endian 32 bytes
|
||||
return int_to_big_endian(self.x.num, 32)
|
||||
raise NotImplementedError
|
||||
|
||||
def tweak(self, merkle_root=b""):
|
||||
"""returns the tweak for use in p2tr if there's no script path"""
|
||||
# take the hash_taptweak of the xonly and the merkle root
|
||||
tweak = hash_taptweak(self.xonly() + merkle_root)
|
||||
return tweak
|
||||
raise NotImplementedError
|
||||
|
||||
def tweaked_key(self, merkle_root=b""):
|
||||
"""Creates the tweaked external key for a particular tweak."""
|
||||
# Get the tweak from the merkle root
|
||||
tweak = self.tweak(merkle_root)
|
||||
# t is the tweak interpreted as big endian
|
||||
t = big_endian_to_int(tweak)
|
||||
# Q = P + tG
|
||||
external_key = self + t * G
|
||||
# return the external key
|
||||
return external_key
|
||||
raise NotImplementedError
|
||||
|
||||
def hash160(self, compressed=True):
|
||||
# get the sec
|
||||
|
@ -634,42 +628,20 @@ class PrivateKey:
|
|||
# to a known value to make k deterministic
|
||||
# the idea of k generation here is to mix in the private key
|
||||
# and the msg to ensure it's unique and not reused
|
||||
if aux is None:
|
||||
aux = b"\x00" * 32
|
||||
if self.point.parity:
|
||||
d = N - self.secret
|
||||
else:
|
||||
d = self.secret
|
||||
if len(msg) != 32:
|
||||
raise ValueError("msg needs to be 32 bytes")
|
||||
if len(aux) != 32:
|
||||
raise ValueError("aux needs to be 32 bytes")
|
||||
# t contains the secret, msg is added so it's unique to the
|
||||
# message and private key
|
||||
t = xor_bytes(int_to_big_endian(d, 32), hash_aux(aux))
|
||||
k = big_endian_to_int(hash_nonce(t + self.point.xonly() + msg)) % N
|
||||
# get the resulting R=kG point
|
||||
r = k * G
|
||||
# if R's y coordinate is odd, flip the k
|
||||
if r.parity:
|
||||
# set k to N - k
|
||||
k = N - k
|
||||
# recalculate R
|
||||
r = k * G
|
||||
# calculate the commitment which is: R || P || msg
|
||||
commitment = r.xonly() + self.point.xonly() + msg
|
||||
# hash_challenge the result and interpret as a big endian integer
|
||||
# mod the result by N and this is your e
|
||||
e = big_endian_to_int(hash_challenge(commitment)) % N
|
||||
# calculate s which is (k+ed) mod N
|
||||
s = (k + e * d) % N
|
||||
# create a SchnorrSignature object using the R and s
|
||||
sig = SchnorrSignature(r, s)
|
||||
# check that this schnorr signature verifies
|
||||
if not self.point.verify_schnorr(msg, sig):
|
||||
raise RuntimeError("Bad Signature")
|
||||
# return the signature
|
||||
return sig
|
||||
raise NotImplementedError
|
||||
|
||||
def deterministic_k(self, z):
|
||||
k = b"\x00" * 32
|
||||
|
@ -720,13 +692,10 @@ class PrivateKey:
|
|||
|
||||
def tweaked_key(self, merkle_root=b""):
|
||||
# get the tweak from the point's tweak method
|
||||
tweak = self.point.tweak(merkle_root)
|
||||
# t is the tweak interpreted as big endian
|
||||
t = big_endian_to_int(tweak)
|
||||
# new secret is the secret plus t (make sure to mod by N)
|
||||
new_secret = (self.secret + t) % N
|
||||
# create a new instance of this class using self.__class__
|
||||
return self.__class__(new_secret)
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def parse(cls, wif):
|
||||
|
|
|
@ -9,9 +9,8 @@ def sha256(x):
|
|||
|
||||
def tagged_hash(tag, msg):
|
||||
# compute the sha256 of the tag using hashlib.sha256
|
||||
tag_hash = sha256(tag)
|
||||
# compute the tagged hash by getting the sha256 of the tag hash + tag hash + message
|
||||
return sha256(tag_hash + tag_hash + msg)
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def hash_aux(msg):
|
||||
|
|
|
@ -775,38 +775,18 @@ def op_checksigverify_schnorr(stack, tx_obj, input_index):
|
|||
|
||||
def op_checksigadd_schnorr(stack, tx_obj, input_index):
|
||||
# check to see if there's at least 3 elements
|
||||
if len(stack) < 3:
|
||||
return False
|
||||
# pop off the pubkey
|
||||
pubkey = stack.pop()
|
||||
# pop off the n
|
||||
n = decode_num(stack.pop())
|
||||
# pop off the signature
|
||||
signature = stack.pop()
|
||||
# parse the pubkey
|
||||
point = S256Point.parse_xonly(pubkey)
|
||||
# if the signature has 0 length, it's not valid
|
||||
if len(signature) == 0:
|
||||
stack.append(encode_num(n))
|
||||
return True
|
||||
# we handle the hash type here
|
||||
if len(signature) == 65:
|
||||
hash_type = signature[-1]
|
||||
signature = signature[:-1]
|
||||
else:
|
||||
hash_type = None
|
||||
# parse the Schnorr signature
|
||||
sig = SchnorrSignature.parse(signature)
|
||||
# get the message from the tx_obj.sig_hash
|
||||
msg = tx_obj.sig_hash(input_index, hash_type)
|
||||
# verify the Schnorr signature
|
||||
if point.verify_schnorr(msg, sig):
|
||||
# if valid, increment the n and push back on stack
|
||||
stack.append(encode_num(n + 1))
|
||||
else:
|
||||
# if invalid, push back n on stack
|
||||
stack.append(encode_num(n))
|
||||
return True
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def op_checkmultisig(stack, tx_obj, input_index):
|
||||
|
|
|
@ -41,9 +41,8 @@ class TapLeaf:
|
|||
|
||||
def hash(self):
|
||||
# calculate what's getting hashed
|
||||
content = int_to_byte(self.tapleaf_version) + self.tap_script.serialize()
|
||||
# return the hash_tapleaf of the content
|
||||
return hash_tapleaf(content)
|
||||
raise NotImplementedError
|
||||
|
||||
def leaves(self):
|
||||
return [self]
|
||||
|
@ -79,13 +78,8 @@ class TapBranch:
|
|||
|
||||
def hash(self):
|
||||
# get the left and right hashes
|
||||
left_hash = self.left.hash()
|
||||
right_hash = self.right.hash()
|
||||
# use hash_tapbranch on them in alphabetical order
|
||||
if left_hash < right_hash:
|
||||
return hash_tapbranch(left_hash + right_hash)
|
||||
else:
|
||||
return hash_tapbranch(right_hash + left_hash)
|
||||
raise NotImplementedError
|
||||
|
||||
def leaves(self):
|
||||
if self._leaves is None:
|
||||
|
@ -143,24 +137,16 @@ class ControlBlock:
|
|||
|
||||
def merkle_root(self, tap_script):
|
||||
# create a TapLeaf from the tap_script and the tapleaf version in the control block
|
||||
leaf = TapLeaf(tap_script, self.tapleaf_version)
|
||||
# initialize the hash with the leaf's hash
|
||||
current = leaf.hash()
|
||||
# go through the hashes in self.hashes
|
||||
for h in self.hashes:
|
||||
# set the current hash as the hash_tapbranch of the sorted hashes
|
||||
if current < h:
|
||||
current = hash_tapbranch(current + h)
|
||||
else:
|
||||
current = hash_tapbranch(h + current)
|
||||
# return the current hash
|
||||
return current
|
||||
raise NotImplementedError
|
||||
|
||||
def external_pubkey(self, tap_script):
|
||||
# get the Merkle Root using self.merkle_root
|
||||
merkle_root = self.merkle_root(tap_script)
|
||||
# return the external pubkey using the tweaked_key method of internal pubkey
|
||||
return self.internal_pubkey.tweaked_key(merkle_root)
|
||||
raise NotImplementedError
|
||||
|
||||
def serialize(self):
|
||||
s = int_to_byte(self.tapleaf_version + self.parity)
|
||||
|
|
Loading…
Reference in New Issue