diff --git a/clear.py b/clear.py new file mode 100644 index 0000000..da16b8f --- /dev/null +++ b/clear.py @@ -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) diff --git a/restore.py b/restore.py new file mode 100644 index 0000000..71a7a37 --- /dev/null +++ b/restore.py @@ -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") diff --git a/session/ecc.py b/session/ecc.py index f05596e..557513f 100644 --- a/session/ecc.py +++ b/session/ecc.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): diff --git a/session/hash.py b/session/hash.py index e3ad49b..f816844 100644 --- a/session/hash.py +++ b/session/hash.py @@ -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): diff --git a/session/op.py b/session/op.py index 0c8631d..982ef8a 100644 --- a/session/op.py +++ b/session/op.py @@ -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): diff --git a/session/taproot.py b/session/taproot.py index 7505fc2..5baf469 100644 --- a/session/taproot.py +++ b/session/taproot.py @@ -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)