mirror of
https://github.com/aljazceru/nutshell.git
synced 2025-12-21 11:04:19 +01:00
isort
This commit is contained in:
@@ -1,49 +1,38 @@
|
||||
import hashlib
|
||||
import base64
|
||||
import hashlib
|
||||
import random
|
||||
|
||||
COIN = 100_000_000
|
||||
TXID = "bff785da9f8169f49be92fa95e31f0890c385bfb1bd24d6b94d7900057c617ae"
|
||||
SEED = b"__not__used"
|
||||
|
||||
from bitcoin.core import (
|
||||
lx,
|
||||
COutPoint,
|
||||
CMutableTxOut,
|
||||
CMutableTxIn,
|
||||
CMutableTransaction,
|
||||
)
|
||||
from bitcoin.core import (CMutableTxIn, CMutableTxOut, COutPoint, CTransaction,
|
||||
lx)
|
||||
from bitcoin.core.script import *
|
||||
from bitcoin.core.scripteval import VerifyScript
|
||||
from bitcoin.wallet import CBitcoinAddress, CBitcoinSecret
|
||||
from bitcoin.core.scripteval import (SCRIPT_VERIFY_P2SH, EvalScriptError,
|
||||
VerifyScript, VerifyScriptError)
|
||||
from bitcoin.wallet import CBitcoinSecret, P2SHBitcoinAddress
|
||||
|
||||
|
||||
def step0_carol_privkey():
|
||||
"""Private key"""
|
||||
h = hashlib.sha256(b"correct horse battery staple").digest()
|
||||
# h = hashlib.sha256(SEED).digest()
|
||||
h = hashlib.sha256(str(random.getrandbits(256)).encode()).digest()
|
||||
seckey = CBitcoinSecret.from_secret_bytes(h)
|
||||
return seckey
|
||||
|
||||
|
||||
def step0_carolt_checksig_redeemscrip(carol_pubkey):
|
||||
def step0_carol_checksig_redeemscrip(carol_pubkey):
|
||||
"""Create script"""
|
||||
txin_redeemScript = CScript([carol_pubkey, OP_CHECKSIG])
|
||||
# txin_redeemScript = CScript(
|
||||
# [
|
||||
# 3,
|
||||
# 3,
|
||||
# OP_LESSTHANOREQUAL,
|
||||
# OP_VERIFY,
|
||||
# ]
|
||||
# )
|
||||
# txin_redeemScript = CScript([-123, OP_CHECKLOCKTIMEVERIFY])
|
||||
# txin_redeemScript = CScript([3, 3, OP_LESSTHAN, OP_VERIFY])
|
||||
return txin_redeemScript
|
||||
|
||||
|
||||
def step1_carol_create_p2sh_address(txin_redeemScript):
|
||||
"""Create address (serialized scriptPubKey) to share with Alice"""
|
||||
# print("Script:", b2x(txin_redeemScript))
|
||||
# returns [OP_HASH160, bitcointx.core.Hash160(self), OP_EQUAL]
|
||||
txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()
|
||||
txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
|
||||
# print("Pay to:", str(txin_p2sh_address))
|
||||
txin_p2sh_address = P2SHBitcoinAddress.from_redeemScript(txin_redeemScript)
|
||||
return txin_p2sh_address
|
||||
|
||||
|
||||
@@ -54,49 +43,81 @@ def step1_bob_carol_create_tx(txin_p2sh_address):
|
||||
txin = CMutableTxIn(COutPoint(txid, vout))
|
||||
txout = CMutableTxOut(
|
||||
int(0.0005 * COIN),
|
||||
CBitcoinAddress(str(txin_p2sh_address)).to_scriptPubKey(),
|
||||
P2SHBitcoinAddress(str(txin_p2sh_address)).to_scriptPubKey(),
|
||||
)
|
||||
tx = CMutableTransaction([txin], [txout])
|
||||
tx = CTransaction([txin], [txout])
|
||||
return tx, txin
|
||||
|
||||
|
||||
def step2_carol_sign_tx(txin_redeemScript):
|
||||
def step2_carol_sign_tx(txin_redeemScript, privatekey):
|
||||
"""Sign transaction with private key"""
|
||||
seckey = step0_carol_privkey()
|
||||
txin_p2sh_address = step1_carol_create_p2sh_address(txin_redeemScript)
|
||||
tx, txin = step1_bob_carol_create_tx(txin_p2sh_address)
|
||||
sighash = SignatureHash(txin_redeemScript, tx, 0, SIGHASH_ALL)
|
||||
sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])
|
||||
sig = privatekey.sign(sighash) + bytes([SIGHASH_ALL])
|
||||
txin.scriptSig = CScript([sig, txin_redeemScript])
|
||||
return txin
|
||||
|
||||
|
||||
def step3_bob_verify_script(txin_signature, txin_redeemScript):
|
||||
def step3_bob_verify_script(txin_signature, txin_redeemScript, tx):
|
||||
txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()
|
||||
|
||||
try:
|
||||
VerifyScript(txin_signature, txin_scriptPubKey, tx, 0)
|
||||
VerifyScript(
|
||||
txin_signature, txin_scriptPubKey, tx, 0, flags=[SCRIPT_VERIFY_P2SH]
|
||||
)
|
||||
return True
|
||||
except VerifyScriptError as e:
|
||||
print("Could not verify script:", e)
|
||||
except EvalScriptError as e:
|
||||
print("Script did not evaluate:", e)
|
||||
print(f"Script: {txin_scriptPubKey.__repr__()}")
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
def verify_script(txin_redeemScript_b64, txin_signature_b64):
|
||||
txin_redeemScript = CScript(base64.urlsafe_b64decode(txin_redeemScript_b64))
|
||||
print("Redeem script:", txin_redeemScript.__repr__())
|
||||
# txin_redeemScript = CScript([2, 3, OP_LESSTHAN, OP_VERIFY])
|
||||
txin_signature = CScript(value=base64.urlsafe_b64decode(txin_signature_b64))
|
||||
|
||||
txin_p2sh_address = step1_carol_create_p2sh_address(txin_redeemScript)
|
||||
print(f"Bob recreates secret: P2SH:{txin_p2sh_address}")
|
||||
# MINT checks that P2SH:txin_p2sh_address has not been spent yet
|
||||
# ...
|
||||
tx, _ = step1_bob_carol_create_tx(txin_p2sh_address)
|
||||
|
||||
print(
|
||||
f"Bob verifies:\nscript: {txin_redeemScript_b64}\nsignature: {txin_signature_b64}\n"
|
||||
)
|
||||
script_valid = step3_bob_verify_script(txin_signature, txin_redeemScript, tx)
|
||||
# MINT redeems tokens and stores P2SH:txin_p2sh_address
|
||||
# ...
|
||||
if script_valid:
|
||||
print("Successfull.")
|
||||
else:
|
||||
print("Error.")
|
||||
return txin_p2sh_address, script_valid
|
||||
|
||||
|
||||
# simple test case
|
||||
if __name__ == "__main__":
|
||||
# https://github.com/romanz/python-bitcointx/blob/master/examples/spend-p2sh-txout.py
|
||||
# CAROL shares txin_p2sh_address with ALICE:
|
||||
|
||||
# ---------
|
||||
# CAROL defines scripthash and ALICE mints them
|
||||
|
||||
txin_redeemScript = step0_carolt_checksig_redeemscrip(step0_carol_privkey().pub)
|
||||
alice_privkey = step0_carol_privkey()
|
||||
txin_redeemScript = step0_carol_checksig_redeemscrip(alice_privkey.pub)
|
||||
print("Script:", txin_redeemScript.__repr__())
|
||||
txin_p2sh_address = step1_carol_create_p2sh_address(txin_redeemScript)
|
||||
print(f"Carol sends Alice secret = P2SH:{txin_p2sh_address}")
|
||||
print("")
|
||||
|
||||
# ---------
|
||||
|
||||
# ALICE: mint tokens with secret SCRIPT:txin_p2sh_address
|
||||
# ALICE: mint tokens with secret P2SH:txin_p2sh_address
|
||||
print(f"Alice mints tokens with secret = P2SH:{txin_p2sh_address}")
|
||||
print("")
|
||||
# ...
|
||||
@@ -105,13 +126,13 @@ if __name__ == "__main__":
|
||||
# CAROL redeems with MINT
|
||||
|
||||
# CAROL PRODUCES txin_redeemScript and txin_signature to send to MINT
|
||||
txin_redeemScript = step0_carolt_checksig_redeemscrip(step0_carol_privkey().pub)
|
||||
txin_signature = step2_carol_sign_tx(txin_redeemScript).scriptSig
|
||||
txin_redeemScript = step0_carol_checksig_redeemscrip(alice_privkey.pub)
|
||||
txin_signature = step2_carol_sign_tx(txin_redeemScript, alice_privkey).scriptSig
|
||||
|
||||
txin_redeemScript_b64 = base64.urlsafe_b64encode(txin_redeemScript).decode()
|
||||
txin_signature_b64 = base64.urlsafe_b64encode(txin_signature).decode()
|
||||
print(
|
||||
f"Carol to Bob:\nscript: {txin_redeemScript_b64}\nsignature: {txin_signature_b64}\n"
|
||||
f"Carol to Bob:\nscript: {txin_redeemScript.__repr__()}\nscript: {txin_redeemScript_b64}\nsignature: {txin_signature_b64}\n"
|
||||
)
|
||||
print("")
|
||||
# ---------
|
||||
@@ -119,20 +140,25 @@ if __name__ == "__main__":
|
||||
|
||||
# MINT receives txin_redeemScript_b64 and txin_signature_b64 fom CAROL:
|
||||
txin_redeemScript = CScript(base64.urlsafe_b64decode(txin_redeemScript_b64))
|
||||
txin_signature = CScript(base64.urlsafe_b64decode(txin_signature_b64))
|
||||
txin_redeemScript_p2sh = txin_p2sh_address.to_redeemScript()
|
||||
print("Redeem script:", txin_redeemScript.__repr__())
|
||||
print("P2SH:", txin_redeemScript_p2sh.__repr__())
|
||||
# txin_redeemScript = CScript([2, 3, OP_LESSTHAN, OP_VERIFY])
|
||||
txin_signature = CScript(value=base64.urlsafe_b64decode(txin_signature_b64))
|
||||
|
||||
txin_p2sh_address = step1_carol_create_p2sh_address(txin_redeemScript)
|
||||
print(f"Bob recreates secret: P2SH:{txin_p2sh_address}")
|
||||
# MINT checks that SCRIPT:txin_p2sh_address has not been spent yet
|
||||
# MINT checks that P2SH:txin_p2sh_address has not been spent yet
|
||||
# ...
|
||||
tx, _ = step1_bob_carol_create_tx(txin_p2sh_address)
|
||||
|
||||
print(
|
||||
f"Bob verifies:\nscript: {txin_redeemScript_b64}\nsignature: {txin_signature_b64}\n"
|
||||
)
|
||||
script_valid = step3_bob_verify_script(txin_signature, txin_redeemScript)
|
||||
# MINT redeems tokens and stores SCRIPT:txin_p2sh_address
|
||||
script_valid = step3_bob_verify_script(txin_signature, txin_redeemScript, tx)
|
||||
# MINT redeems tokens and stores P2SH:txin_p2sh_address
|
||||
# ...
|
||||
|
||||
print("Successfull.")
|
||||
# print("Transaction:", b2x(tx.serialize()))
|
||||
if script_valid:
|
||||
print("Successfull.")
|
||||
else:
|
||||
print("Error.")
|
||||
|
||||
Reference in New Issue
Block a user