Exemplo n.º 1
0
    amount=700
)

print("Unsigned Claim Transaction Fee:", unsigned_claim_transaction.fee)
print("Unsigned Claim Transaction Hash:", unsigned_claim_transaction.hash())
print("Unsigned Claim Transaction Raw:", unsigned_claim_transaction.raw())
# print("Unsigned Claim Transaction Json:", json.dumps(unsigned_claim_transaction.json(), indent=4))

unsigned_claim_raw = unsigned_claim_transaction.unsigned_raw()
print("Unsigned Claim Transaction Unsigned Raw:", unsigned_claim_raw)

print("=" * 10, "Signed Claim Transaction")

# Claiming HTLC solver
claim_solver = ClaimSolver(
    secret="Hello Meheret!",
    private_key=recipient_private_key
)

signed_claim_transaction = unsigned_claim_transaction.sign(claim_solver)

print("Signed Claim Transaction Fee:", signed_claim_transaction.fee)
print("Signed Claim Transaction Hash:", signed_claim_transaction.hash())
print("Signed Claim Transaction Raw:", signed_claim_transaction.raw())
# print("Signed Claim Transaction Json:", json.dumps(signed_claim_transaction.json(), indent=4))

print("=" * 10, "Claim Signature")

# Singing Hash Time Lock Contract (HTLC)
claim_signature = ClaimSignature(network=network)\
    .sign(unsigned_raw=unsigned_claim_raw, solver=claim_solver)
Exemplo n.º 2
0
def test_bitcoin_claim():
    # Initialization claim transaction
    unsigned_claim_transaction = ClaimTransaction(version=2, network=network)
    # Building claim transaction
    unsigned_claim_transaction.build_transaction(
        transaction_id=fund_transaction_id,
        wallet=recipient_wallet,
        amount=2000)

    assert unsigned_claim_transaction.fee == 576
    assert unsigned_claim_transaction.hash(
    ) == "726e390af02215d346be089dff566ae070f7332e8927d83acbb40b0e9105a787"
    assert unsigned_claim_transaction.raw() == \
           "0200000001888be7ec065097d95664763f276d425552d735fb1d974ae78bf72106dca0f3910000000000ffffffff019005000" \
           "0000000001976a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac00000000"
    assert unsigned_claim_transaction.json()

    unsigned_claim_raw = unsigned_claim_transaction.unsigned_raw()
    assert unsigned_claim_raw == \
           "eyJmZWUiOiA1NzYsICJyYXciOiAiMDIwMDAwMDAwMTg4OGJlN2VjMDY1MDk3ZDk1NjY0NzYzZjI3NmQ0MjU1NTJkNzM1ZmIxZDk3N" \
           "GFlNzhiZjcyMTA2ZGNhMGYzOTEwMDAwMDAwMDAwZmZmZmZmZmYwMTkwMDUwMDAwMDAwMDAwMDAxOTc2YTkxNDk4Zjg3OWZiN2Y4Yj" \
           "Q5NTFkZWU5YmM4YTAzMjdiNzkyZmJlMzMyYjg4OGFjMDAwMDAwMDAiLCAib3V0cHV0cyI6IFt7ImFtb3VudCI6IDIwMDAsICJuIjo" \
           "gMCwgInNjcmlwdCI6ICJhOTE0NmYwOGIyNTRlNGM1OGRjNjVmNmYzOTljM2JlNzE3N2I5MDFmNGE2Njg3In1dLCAicmVjaXBpZW50" \
           "X2FkZHJlc3MiOiAibXVUbmZmTERSNUx0RmVMUjJpM1dzS1ZmZHl2emZ5UG5WQiIsICJzZW5kZXJfYWRkcmVzcyI6ICJtcGhCUFpmM" \
           "TVjUkZjTDV0VXE2bUNiRTg0WG9iWjF2ZzdRIiwgInNlY3JldCI6IG51bGwsICJuZXR3b3JrIjogInRlc3RuZXQiLCAidHlwZSI6IC" \
           "JiaXRjb2luX2NsYWltX3Vuc2lnbmVkIn0="

    # Claiming HTLC solver
    claim_solver = ClaimSolver(secret="Hello Meheret!",
                               private_key=recipient_private_key)

    signed_claim_transaction = unsigned_claim_transaction.sign(claim_solver)

    assert signed_claim_transaction.fee
    assert signed_claim_transaction.hash()
    assert signed_claim_transaction.raw()
    assert signed_claim_transaction.json()

    # Singing Hash Time Lock Contract (HTLC)
    claim_signature = ClaimSignature(network=network)\
        .sign(unsigned_raw=unsigned_claim_raw, solver=claim_solver)

    signature = Signature(network=network) \
        .sign(unsigned_raw=unsigned_claim_raw, solver=claim_solver)

    assert signature.fee == claim_signature.fee == signed_claim_transaction.fee == 576
    assert signature.hash() == claim_signature.hash() == signed_claim_transaction.hash() == \
           "910a173757d59492a6e807bf270650e950dde7949d540e70cc0ce5123008a52c"
    assert signature.raw() == claim_signature.raw() == signed_claim_transaction.raw() == \
           "0200000001888be7ec065097d95664763f276d425552d735fb1d974ae78bf72106dca0f39100000000d847304402204e20eeb" \
           "3cb82dbe51f7929cd4e819891102d2d7a280919013ae31f12aa49212602206fbce96d734823579e6a4bb4b517d618dca47606" \
           "2f54d9df06aee4b73d08eae20121039213ebcaefdd3e109720c17867ce1bd6d076b0e65e3b6390e6e38548a65e76af0e48656" \
           "c6c6f204d65686572657421514c5c63aa20821124b554d13f247b1e5d10b84e44fb1296f18f38bbaa1bea34a12c843e015888" \
           "76a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac670164b27576a91464a8390b0b1685fcbf2d4b457118dc8da92" \
           "d553488ac68ffffffff0190050000000000001976a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac00000000"
    assert signature.json() == claim_signature.json(
    ) == signed_claim_transaction.json()

    signed_claim_raw = claim_signature.signed_raw()
    assert signature.signed_raw() == signed_claim_raw == \
           "eyJyYXciOiAiMDIwMDAwMDAwMTg4OGJlN2VjMDY1MDk3ZDk1NjY0NzYzZjI3NmQ0MjU1NTJkNzM1ZmIxZDk3NGFlNzhiZjcyMTA2Z" \
           "GNhMGYzOTEwMDAwMDAwMGQ4NDczMDQ0MDIyMDRlMjBlZWIzY2I4MmRiZTUxZjc5MjljZDRlODE5ODkxMTAyZDJkN2EyODA5MTkwMT" \
           "NhZTMxZjEyYWE0OTIxMjYwMjIwNmZiY2U5NmQ3MzQ4MjM1NzllNmE0YmI0YjUxN2Q2MThkY2E0NzYwNjJmNTRkOWRmMDZhZWU0Yjc" \
           "zZDA4ZWFlMjAxMjEwMzkyMTNlYmNhZWZkZDNlMTA5NzIwYzE3ODY3Y2UxYmQ2ZDA3NmIwZTY1ZTNiNjM5MGU2ZTM4NTQ4YTY1ZTc2" \
           "YWYwZTQ4NjU2YzZjNmYyMDRkNjU2ODY1NzI2NTc0MjE1MTRjNWM2M2FhMjA4MjExMjRiNTU0ZDEzZjI0N2IxZTVkMTBiODRlNDRmY" \
           "jEyOTZmMThmMzhiYmFhMWJlYTM0YTEyYzg0M2UwMTU4ODg3NmE5MTQ5OGY4NzlmYjdmOGI0OTUxZGVlOWJjOGEwMzI3Yjc5MmZiZT" \
           "MzMmI4ODhhYzY3MDE2NGIyNzU3NmE5MTQ2NGE4MzkwYjBiMTY4NWZjYmYyZDRiNDU3MTE4ZGM4ZGE5MmQ1NTM0ODhhYzY4ZmZmZmZ" \
           "mZmYwMTkwMDUwMDAwMDAwMDAwMDAxOTc2YTkxNDk4Zjg3OWZiN2Y4YjQ5NTFkZWU5YmM4YTAzMjdiNzkyZmJlMzMyYjg4OGFjMDAw" \
           "MDAwMDAiLCAiZmVlIjogNTc2LCAibmV0d29yayI6ICJ0ZXN0bmV0IiwgInR5cGUiOiAiYml0Y29pbl9jbGFpbV9zaWduZWQifQ=="
Exemplo n.º 3
0
def sign(private, raw, bytecode, secret, sequence, version):
    if len(private) != 64:
        click.echo(
            click.style("Error: {}").format("invalid Bitcoin private key"),
            err=True)
        sys.exit()

    # Cleaning unsigned raw
    unsigned_raw = str(raw + "=" * (-len(raw) % 4))
    try:
        transaction = json.loads(b64decode(unsigned_raw.encode()).decode())
    except (binascii.Error, json.decoder.JSONDecodeError) as exception:
        click.echo(click.style("Error: {}").format(
            "invalid Bitcoin unsigned transaction raw"),
                   err=True)
        sys.exit()
    if "type" not in transaction or "network" not in transaction:
        click.echo(click.style("Warning: {}", fg="yellow").format(
            "there is no type & network provided in Bitcoin unsigned transaction raw"
        ),
                   err=True)
        click.echo(click.style("Error: {}").format(
            "invalid Bitcoin unsigned transaction raw"),
                   err=True)
        sys.exit()

    try:
        if transaction["type"] == "bitcoin_fund_unsigned":
            # Fund HTLC solver
            fund_solver = FundSolver(private_key=private)
            # Fund signature
            fund_signature = FundSignature(network=transaction["network"],
                                           version=version)
            fund_signature.sign(unsigned_raw=unsigned_raw, solver=fund_solver)
            click.echo(fund_signature.signed_raw())

        elif transaction["type"] == "bitcoin_claim_unsigned":
            if secret is None:
                click.echo(click.style("Error: {}").format(
                    "secret key is required for claim, use -s or --secret \"Hello Meheret!\""
                ),
                           err=True)
                sys.exit()
            if bytecode is None:
                click.echo(click.style("Error: {}").format(
                    "witness bytecode is required for claim, use -b or --bytecode \"016...\""
                ),
                           err=True)
                sys.exit()

            # Claim HTLC solver
            claim_solver = ClaimSolver(private_key=private,
                                       secret=secret,
                                       bytecode=bytecode)
            # Claim signature
            claim_signature = ClaimSignature(network=transaction["network"],
                                             version=version)
            claim_signature.sign(unsigned_raw=unsigned_raw,
                                 solver=claim_solver)
            click.echo(claim_signature.signed_raw())

        elif transaction["type"] == "bitcoin_refund_unsigned":
            if bytecode is None:
                click.echo(click.style("Error: {}").format(
                    "witness bytecode is required for refund, use -b or --bytecode \"016...\""
                ),
                           err=True)
                sys.exit()

            # Refunding HTLC solver
            refund_solver = RefundSolver(private_key=private,
                                         sequence=int(sequence),
                                         bytecode=bytecode)
            # Refund signature
            refund_signature = RefundSignature(network=transaction["network"],
                                               version=version)
            refund_signature.sign(unsigned_raw=unsigned_raw,
                                  solver=refund_solver)
            click.echo(refund_signature.signed_raw())
        else:
            click.echo(click.style("Error: {}").format(
                "unknown Bitcoin unsigned transaction raw type"),
                       err=True)
            sys.exit()
    except Exception as exception:
        click.echo(click.style("Error: {}").format(str(exception)), err=True)
        sys.exit()
Exemplo n.º 4
0
print("Unsigned Claim Transaction Fee:", unsigned_claim_transaction.fee())
print("Unsigned Claim Transaction Hash:", unsigned_claim_transaction.hash())
print("Unsigned Claim Transaction Raw:", unsigned_claim_transaction.raw())
# print("Unsigned Claim Transaction Json:", json.dumps(unsigned_claim_transaction.json(), indent=4))
print("Unsigned Claim Transaction Type:", unsigned_claim_transaction.type())

unsigned_claim_raw = unsigned_claim_transaction.unsigned_raw()
print("Unsigned Claim Transaction Unsigned Raw:", unsigned_claim_raw)

print("=" * 10, "Signed Claim Transaction")

# Initializing claim solver
claim_solver = ClaimSolver(private_key=recipient_private_key,
                           secret="Hello Meheret!",
                           secret_hash=sha256("Hello Meheret!".encode()).hex(),
                           recipient_address=recipient_address,
                           sender_address=sender_address,
                           sequence=1000)

# Singing unsigned claim transaction
signed_claim_transaction = unsigned_claim_transaction.sign(solver=claim_solver)

print("Signed Claim Transaction Fee:", signed_claim_transaction.fee())
print("Signed Claim Transaction Hash:", signed_claim_transaction.hash())
print("Signed Claim Transaction Raw:", signed_claim_transaction.raw())
# print("Signed Claim Transaction Json:", json.dumps(signed_claim_transaction.json(), indent=4))
print("Signed Claim Transaction Type:", signed_claim_transaction.type())

print("=" * 10, "Claim Signature")

# Initializing claim signature
Exemplo n.º 5
0
def test_bitcoin_claim_signature():

    unsigned_claim_transaction_raw = "eyJmZWUiOiA1NzYsICJyYXciOiAiMDIwMDAwMDAwMWVjMzEyZTkyZDgzODdiMTVmNjIzOGQ0OTE4MzQ0YjYyYWIxNDdkN2YzODQ0ZGM4MWU2NTM3NzZmZThiODRlZjMwMDAwMDAwMDAwZmZmZmZmZmYwMWQwMjQwMDAwMDAwMDAwMDAxOTc2YTkxNDk4Zjg3OWZiN2Y4YjQ5NTFkZWU5YmM4YTAzMjdiNzkyZmJlMzMyYjg4OGFjMDAwMDAwMDAiLCAib3V0cHV0cyI6IHsiYW1vdW50IjogMTAwMDAsICJuIjogMCwgInNjcmlwdCI6ICJhOTE0MmJiMDEzYzNlNGJlYjA4NDIxZGVkY2Y4MTVjYjY1YTVjMzg4MTc4Yjg3In0sICJuZXR3b3JrIjogInRlc3RuZXQiLCAidHlwZSI6ICJiaXRjb2luX2NsYWltX3Vuc2lnbmVkIn0="

    signature = Signature(version=2, network=network).sign(
        unsigned_raw=unsigned_claim_transaction_raw,
        solver=ClaimSolver(private_key=recipient_wallet.private_key(),
                           secret="Hello Meheret!",
                           secret_hash=sha256("Hello Meheret!".encode()).hex(),
                           recipient_address=recipient_wallet.address(),
                           sender_address=sender_wallet.address(),
                           sequence=1000))

    claim_signature = ClaimSignature(version=2, network=network).sign(
        unsigned_raw=unsigned_claim_transaction_raw,
        solver=ClaimSolver(private_key=recipient_wallet.private_key(),
                           secret="Hello Meheret!",
                           secret_hash=sha256("Hello Meheret!".encode()).hex(),
                           recipient_address=recipient_wallet.address(),
                           sender_address=sender_wallet.address(),
                           sequence=1000))

    assert signature.fee() == claim_signature.fee() == 576
    assert signature.hash() == claim_signature.hash(
    ) == "8f98079b6257d65abc2c1c1a14c3bff50a6be949e75a30c127b3a2c0618012e1"
    assert signature.raw() == claim_signature.raw(
    ) == "0200000001ec312e92d8387b15f6238d4918344b62ab147d7f3844dc81e653776fe8b84ef300000000d9473044022060291b5a87474f775dda5c244b21fc2716bfa09c4636ea4c707918c9f759374e02201ef5e768af10d01a1031294e952f6a8ed5c0a75e23f58aee062a89fed2134af70121039213ebcaefdd3e109720c17867ce1bd6d076b0e65e3b6390e6e38548a65e76af0e48656c6c6f204d65686572657421514c5d63aa20821124b554d13f247b1e5d10b84e44fb1296f18f38bbaa1bea34a12c843e01588876a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac6702e803b27576a91464a8390b0b1685fcbf2d4b457118dc8da92d553488ac68ffffffff01d0240000000000001976a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac00000000"
    assert signature.json() == claim_signature.json() == {
        'hex':
        '0200000001ec312e92d8387b15f6238d4918344b62ab147d7f3844dc81e653776fe8b84ef300000000d9473044022060291b5a87474f775dda5c244b21fc2716bfa09c4636ea4c707918c9f759374e02201ef5e768af10d01a1031294e952f6a8ed5c0a75e23f58aee062a89fed2134af70121039213ebcaefdd3e109720c17867ce1bd6d076b0e65e3b6390e6e38548a65e76af0e48656c6c6f204d65686572657421514c5d63aa20821124b554d13f247b1e5d10b84e44fb1296f18f38bbaa1bea34a12c843e01588876a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac6702e803b27576a91464a8390b0b1685fcbf2d4b457118dc8da92d553488ac68ffffffff01d0240000000000001976a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac00000000',
        'txid':
        '8f98079b6257d65abc2c1c1a14c3bff50a6be949e75a30c127b3a2c0618012e1',
        'hash':
        '8f98079b6257d65abc2c1c1a14c3bff50a6be949e75a30c127b3a2c0618012e1',
        'size':
        302,
        'vsize':
        302,
        'version':
        2,
        'locktime':
        0,
        'vin': [{
            'txid':
            'f34eb8e86f7753e681dc44387f7d14ab624b3418498d23f6157b38d8922e31ec',
            'vout': 0,
            'scriptSig': {
                'asm':
                '3044022060291b5a87474f775dda5c244b21fc2716bfa09c4636ea4c707918c9f759374e02201ef5e768af10d01a1031294e952f6a8ed5c0a75e23f58aee062a89fed2134af701 039213ebcaefdd3e109720c17867ce1bd6d076b0e65e3b6390e6e38548a65e76af 48656c6c6f204d65686572657421 OP_1 63aa20821124b554d13f247b1e5d10b84e44fb1296f18f38bbaa1bea34a12c843e01588876a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac6702e803b27576a91464a8390b0b1685fcbf2d4b457118dc8da92d553488ac68',
                'hex':
                '473044022060291b5a87474f775dda5c244b21fc2716bfa09c4636ea4c707918c9f759374e02201ef5e768af10d01a1031294e952f6a8ed5c0a75e23f58aee062a89fed2134af70121039213ebcaefdd3e109720c17867ce1bd6d076b0e65e3b6390e6e38548a65e76af0e48656c6c6f204d65686572657421514c5d63aa20821124b554d13f247b1e5d10b84e44fb1296f18f38bbaa1bea34a12c843e01588876a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac6702e803b27576a91464a8390b0b1685fcbf2d4b457118dc8da92d553488ac68'
            },
            'sequence': '4294967295'
        }],
        'vout': [{
            'value': '0.00009424',
            'n': 0,
            'scriptPubKey': {
                'asm':
                'OP_DUP OP_HASH160 98f879fb7f8b4951dee9bc8a0327b792fbe332b8 OP_EQUALVERIFY OP_CHECKSIG',
                'hex': '76a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac',
                'type': 'p2pkh',
                'address': 'muTnffLDR5LtFeLR2i3WsKVfdyvzfyPnVB'
            }
        }]
    }
    assert signature.type() == claim_signature.type() == "bitcoin_claim_signed"
    assert signature.signed_raw() == claim_signature.signed_raw(
    ) == "eyJyYXciOiAiMDIwMDAwMDAwMWVjMzEyZTkyZDgzODdiMTVmNjIzOGQ0OTE4MzQ0YjYyYWIxNDdkN2YzODQ0ZGM4MWU2NTM3NzZmZThiODRlZjMwMDAwMDAwMGQ5NDczMDQ0MDIyMDYwMjkxYjVhODc0NzRmNzc1ZGRhNWMyNDRiMjFmYzI3MTZiZmEwOWM0NjM2ZWE0YzcwNzkxOGM5Zjc1OTM3NGUwMjIwMWVmNWU3NjhhZjEwZDAxYTEwMzEyOTRlOTUyZjZhOGVkNWMwYTc1ZTIzZjU4YWVlMDYyYTg5ZmVkMjEzNGFmNzAxMjEwMzkyMTNlYmNhZWZkZDNlMTA5NzIwYzE3ODY3Y2UxYmQ2ZDA3NmIwZTY1ZTNiNjM5MGU2ZTM4NTQ4YTY1ZTc2YWYwZTQ4NjU2YzZjNmYyMDRkNjU2ODY1NzI2NTc0MjE1MTRjNWQ2M2FhMjA4MjExMjRiNTU0ZDEzZjI0N2IxZTVkMTBiODRlNDRmYjEyOTZmMThmMzhiYmFhMWJlYTM0YTEyYzg0M2UwMTU4ODg3NmE5MTQ5OGY4NzlmYjdmOGI0OTUxZGVlOWJjOGEwMzI3Yjc5MmZiZTMzMmI4ODhhYzY3MDJlODAzYjI3NTc2YTkxNDY0YTgzOTBiMGIxNjg1ZmNiZjJkNGI0NTcxMThkYzhkYTkyZDU1MzQ4OGFjNjhmZmZmZmZmZjAxZDAyNDAwMDAwMDAwMDAwMDE5NzZhOTE0OThmODc5ZmI3ZjhiNDk1MWRlZTliYzhhMDMyN2I3OTJmYmUzMzJiODg4YWMwMDAwMDAwMCIsICJmZWUiOiA1NzYsICJuZXR3b3JrIjogInRlc3RuZXQiLCAidHlwZSI6ICJiaXRjb2luX2NsYWltX3NpZ25lZCJ9"
Exemplo n.º 6
0
def test_signature_exceptions():

    with pytest.raises(
            ValueError,
            match=
            "invalid network, please choose only mainnet or testnet networks"):
        Signature(network="solonet")

    with pytest.raises(ValueError,
                       match="transaction script is none, sign first"):
        Signature().hash()

    with pytest.raises(ValueError,
                       match="transaction script is none, sign first"):
        Signature().json()

    with pytest.raises(
            ValueError,
            match="transaction script is none, build transaction first"):
        Signature().raw()

    with pytest.raises(ValueError, match="not found type, sign first"):
        Signature().type()

    with pytest.raises(ValueError,
                       match="there is no signed data, sign first"):
        Signature().signed_raw()

    with pytest.raises(
            TypeError,
            match=r"invalid Bitcoin fund unsigned transaction type, .*"):
        FundSignature().sign(
            unsigned_raw=
            "eyJmZWUiOiA1NzYsICJyYXciOiAiMDIwMDAwMDAwMWVjMzEyZTkyZDgzODdiMTVmNjIzOGQ0OTE4MzQ0YjYyYWIxNDdkN2YzODQ0ZGM4MWU2NTM3NzZmZThiODRlZjMwMDAwMDAwMDAwZmZmZmZmZmYwMWQwMjQwMDAwMDAwMDAwMDAxOTc2YTkxNDY0YTgzOTBiMGIxNjg1ZmNiZjJkNGI0NTcxMThkYzhkYTkyZDU1MzQ4OGFjMDAwMDAwMDAiLCAib3V0cHV0cyI6IHsidmFsdWUiOiAxMDAwMCwgIm4iOiAwLCAic2NyaXB0X3B1YmtleSI6ICJhOTE0MmJiMDEzYzNlNGJlYjA4NDIxZGVkY2Y4MTVjYjY1YTVjMzg4MTc4Yjg3In0sICJuZXR3b3JrIjogInRlc3RuZXQiLCAidHlwZSI6ICJiaXRjb2luX3JlZnVuZF91bnNpZ25lZCJ9",
            solver=FundSolver(private_key=sender_wallet.private_key()))

    with pytest.raises(
            TypeError,
            match=r"invalid Bitcoin claim unsigned transaction type, .*"):
        ClaimSignature().sign(
            unsigned_raw=
            "eyJmZWUiOiA2NzgsICJyYXciOiAiMDIwMDAwMDAwMWVjMzEyZTkyZDgzODdiMTVmNjIzOGQ0OTE4MzQ0YjYyYWIxNDdkN2YzODQ0ZGM4MWU2NTM3NzZmZThiODRlZjMwMTAwMDAwMDAwZmZmZmZmZmYwMjEwMjcwMDAwMDAwMDAwMDAxN2E5MTQyYmIwMTNjM2U0YmViMDg0MjFkZWRjZjgxNWNiNjVhNWMzODgxNzhiODc1MDhhMGUwMDAwMDAwMDAwMTk3NmE5MTQ2NGE4MzkwYjBiMTY4NWZjYmYyZDRiNDU3MTE4ZGM4ZGE5MmQ1NTM0ODhhYzAwMDAwMDAwIiwgIm91dHB1dHMiOiBbeyJhbW91bnQiOiA5NjM1OTAsICJuIjogMSwgInNjcmlwdCI6ICI3NmE5MTQ2NGE4MzkwYjBiMTY4NWZjYmYyZDRiNDU3MTE4ZGM4ZGE5MmQ1NTM0ODhhYyJ9XSwgIm5ldHdvcmsiOiAidGVzdG5ldCIsICJ0eXBlIjogImJpdGNvaW5fZnVuZF91bnNpZ25lZCJ9",
            solver=ClaimSolver(private_key=recipient_wallet.private_key(),
                               secret="Hello Meheret!",
                               secret_hash=sha256(
                                   "Hello Meheret!".encode()).hex(),
                               recipient_address=recipient_wallet.address(),
                               sender_address=sender_wallet.address(),
                               sequence=1000))

    with pytest.raises(
            TypeError,
            match=r"invalid Bitcoin refund unsigned transaction type, .*"):
        RefundSignature().sign(
            unsigned_raw=
            "eyJmZWUiOiA1NzYsICJyYXciOiAiMDIwMDAwMDAwMWVjMzEyZTkyZDgzODdiMTVmNjIzOGQ0OTE4MzQ0YjYyYWIxNDdkN2YzODQ0ZGM4MWU2NTM3NzZmZThiODRlZjMwMDAwMDAwMDAwZmZmZmZmZmYwMWQwMjQwMDAwMDAwMDAwMDAxOTc2YTkxNDk4Zjg3OWZiN2Y4YjQ5NTFkZWU5YmM4YTAzMjdiNzkyZmJlMzMyYjg4OGFjMDAwMDAwMDAiLCAib3V0cHV0cyI6IHsiYW1vdW50IjogMTAwMDAsICJuIjogMCwgInNjcmlwdCI6ICJhOTE0MmJiMDEzYzNlNGJlYjA4NDIxZGVkY2Y4MTVjYjY1YTVjMzg4MTc4Yjg3In0sICJuZXR3b3JrIjogInRlc3RuZXQiLCAidHlwZSI6ICJiaXRjb2luX2NsYWltX3Vuc2lnbmVkIn0",
            solver=RefundSolver(private_key=sender_wallet.private_key(),
                                secret_hash=sha256(
                                    "Hello Meheret!".encode()).hex(),
                                recipient_address=recipient_wallet.address(),
                                sender_address=sender_wallet.address(),
                                sequence=1000))

    with pytest.raises(ValueError,
                       match="invalid Bitcoin unsigned transaction raw"):
        Signature().sign("eyJtIjogImFzZCJ9", "")

    with pytest.raises(ValueError,
                       match="invalid Bitcoin unsigned fund transaction raw"):
        FundSignature().sign("eyJtIjogImFzZCJ9", "")

    with pytest.raises(ValueError,
                       match="invalid Bitcoin unsigned claim transaction raw"):
        ClaimSignature().sign("eyJtIjogImFzZCJ9", "")

    with pytest.raises(
            ValueError,
            match="invalid Bitcoin unsigned refund transaction raw"):
        RefundSignature().sign("eyJtIjogImFzZCJ9", "")

    with pytest.raises(
            TypeError,
            match=
            "invalid Bitcoin solver, it's only takes Bitcoin FundSolver class"
    ):
        FundSignature().sign(
            unsigned_raw=
            "eyJmZWUiOiA2NzgsICJyYXciOiAiMDIwMDAwMDAwMWVjMzEyZTkyZDgzODdiMTVmNjIzOGQ0OTE4MzQ0YjYyYWIxNDdkN2YzODQ0ZGM4MWU2NTM3NzZmZThiODRlZjMwMTAwMDAwMDAwZmZmZmZmZmYwMjEwMjcwMDAwMDAwMDAwMDAxN2E5MTQyYmIwMTNjM2U0YmViMDg0MjFkZWRjZjgxNWNiNjVhNWMzODgxNzhiODc1MDhhMGUwMDAwMDAwMDAwMTk3NmE5MTQ2NGE4MzkwYjBiMTY4NWZjYmYyZDRiNDU3MTE4ZGM4ZGE5MmQ1NTM0ODhhYzAwMDAwMDAwIiwgIm91dHB1dHMiOiBbeyJhbW91bnQiOiA5NjM1OTAsICJuIjogMSwgInNjcmlwdCI6ICI3NmE5MTQ2NGE4MzkwYjBiMTY4NWZjYmYyZDRiNDU3MTE4ZGM4ZGE5MmQ1NTM0ODhhYyJ9XSwgIm5ldHdvcmsiOiAidGVzdG5ldCIsICJ0eXBlIjogImJpdGNvaW5fZnVuZF91bnNpZ25lZCJ9",
            solver=RefundSolver(private_key=sender_wallet.private_key(),
                                secret_hash=sha256(
                                    "Hello Meheret!".encode()).hex(),
                                recipient_address=recipient_wallet.address(),
                                sender_address=sender_wallet.address(),
                                sequence=1000))

    with pytest.raises(
            TypeError,
            match=
            "invalid Bitcoin solver, it's only takes Bitcoin ClaimSolver class"
    ):
        ClaimSignature().sign(
            unsigned_raw=
            "eyJmZWUiOiA1NzYsICJyYXciOiAiMDIwMDAwMDAwMWVjMzEyZTkyZDgzODdiMTVmNjIzOGQ0OTE4MzQ0YjYyYWIxNDdkN2YzODQ0ZGM4MWU2NTM3NzZmZThiODRlZjMwMDAwMDAwMDAwZmZmZmZmZmYwMWQwMjQwMDAwMDAwMDAwMDAxOTc2YTkxNDk4Zjg3OWZiN2Y4YjQ5NTFkZWU5YmM4YTAzMjdiNzkyZmJlMzMyYjg4OGFjMDAwMDAwMDAiLCAib3V0cHV0cyI6IHsiYW1vdW50IjogMTAwMDAsICJuIjogMCwgInNjcmlwdCI6ICJhOTE0MmJiMDEzYzNlNGJlYjA4NDIxZGVkY2Y4MTVjYjY1YTVjMzg4MTc4Yjg3In0sICJuZXR3b3JrIjogInRlc3RuZXQiLCAidHlwZSI6ICJiaXRjb2luX2NsYWltX3Vuc2lnbmVkIn0",
            solver=FundSolver(private_key=sender_wallet.private_key()))

    with pytest.raises(
            TypeError,
            match=
            "invalid Bitcoin solver, it's only takes Bitcoin RefundSolver class"
    ):
        RefundSignature().sign(
            unsigned_raw=
            "eyJmZWUiOiA1NzYsICJyYXciOiAiMDIwMDAwMDAwMWVjMzEyZTkyZDgzODdiMTVmNjIzOGQ0OTE4MzQ0YjYyYWIxNDdkN2YzODQ0ZGM4MWU2NTM3NzZmZThiODRlZjMwMDAwMDAwMDAwZmZmZmZmZmYwMWQwMjQwMDAwMDAwMDAwMDAxOTc2YTkxNDY0YTgzOTBiMGIxNjg1ZmNiZjJkNGI0NTcxMThkYzhkYTkyZDU1MzQ4OGFjMDAwMDAwMDAiLCAib3V0cHV0cyI6IHsidmFsdWUiOiAxMDAwMCwgIm4iOiAwLCAic2NyaXB0X3B1YmtleSI6ICJhOTE0MmJiMDEzYzNlNGJlYjA4NDIxZGVkY2Y4MTVjYjY1YTVjMzg4MTc4Yjg3In0sICJuZXR3b3JrIjogInRlc3RuZXQiLCAidHlwZSI6ICJiaXRjb2luX3JlZnVuZF91bnNpZ25lZCJ9",
            solver=ClaimSolver(private_key=recipient_wallet.private_key(),
                               secret="Hello Meheret!",
                               secret_hash=sha256(
                                   "Hello Meheret!".encode()).hex(),
                               recipient_address=recipient_wallet.address(),
                               sender_address=sender_wallet.address(),
                               sequence=1000))
Exemplo n.º 7
0
def sign(private, raw, secret, version):
    if secret is None:
        secret = str()
    if len(private) != 64:
        click.echo(click.style("Error: {}")
                   .format("invalid bitcoin private key"), err=True)
        sys.exit()

    unsigned_raw = str(raw + "=" * (-len(raw) % 4))
    try:
        transaction = json.loads(b64decode(unsigned_raw.encode()).decode())
    except (binascii.Error, json.decoder.JSONDecodeError) as exception:
        click.echo(click.style("Error: {}")
                   .format("invalid bitcoin unsigned transaction raw"), err=True)
        sys.exit()
    if "type" not in transaction or "network" not in transaction:
        click.echo(click.style("Warning: {}", fg="yellow")
                   .format("there is no type & network provided in bitcoin unsigned transaction raw"), err=True)
        click.echo(click.style("Error: {}")
                   .format("invalid bitcoin unsigned transaction raw"), err=True)
        sys.exit()

    if transaction["type"] == "bitcoin_fund_unsigned":
        # Fund HTLC solver
        fund_solver = FundSolver(private_key=private)
        try:
            # Fund signature
            fund_signature = FundSignature(network=transaction["network"], version=version)
            fund_signature.sign(unsigned_raw=unsigned_raw, solver=fund_solver)
            click.echo(fund_signature.signed_raw())
        except Exception as exception:
            click.echo(click.style("Error: {}").format(str(exception)), err=True)
            sys.exit()

    elif transaction["type"] == "bitcoin_claim_unsigned":
        if secret != str():
            _secret = secret
        elif "secret" not in transaction or transaction["secret"] is None:
            click.echo(click.style("Warning: {}")
                       .format("secret key is empty, use -s or --secret \"Hello Meheret!\""), err=False)
            _secret = str()
        else:
            _secret = transaction["secret"]
        # Claim HTLC solver
        claim_solver = ClaimSolver(
            secret=_secret,
            private_key=private
        )
        try:
            # Claim signature
            claim_signature = ClaimSignature(network=transaction["network"], version=version)
            claim_signature.sign(unsigned_raw=unsigned_raw, solver=claim_solver)
            click.echo(claim_signature.signed_raw())
        except Exception as exception:
            click.echo(click.style("Error: {}").format(str(exception)), err=True)
            sys.exit()

    elif transaction["type"] == "bitcoin_refund_unsigned":
        if secret != str():
            _secret = secret
        elif "secret" not in transaction or transaction["secret"] is None:
            click.echo(click.style("Warning: {}")
                       .format("secret key is empty, use -s or --secret \"Hello Meheret!\""), err=False)
            _secret = str()
        else:
            _secret = transaction["secret"]
        # Refunding HTLC solver
        refund_solver = RefundSolver(
            secret=_secret,
            private_key=private
        )
        try:
            # Refund signature
            refund_signature = RefundSignature(network=transaction["network"], version=version)
            refund_signature.sign(unsigned_raw=unsigned_raw, solver=refund_solver)
            click.echo(refund_signature.signed_raw())
        except Exception as exception:
            click.echo(click.style("Error: {}").format(str(exception)), err=True)
            sys.exit()
Exemplo n.º 8
0
def test_bitcoin_claim_solver():

    htlc_claim_solver = ClaimSolver(
        private_key=recipient_wallet.private_key(),
        secret="Hello Meheret!",
        # Witness from HTLC agreements
        secret_hash=sha256("Hello Meheret!".encode()).hex(),
        recipient_address=recipient_wallet.address(),
        sender_address=sender_wallet.address(),
        sequence=1000)

    assert recipient_wallet.private_key(
    ) == htlc_claim_solver.private_key.hexlify()
    assert isinstance(htlc_claim_solver.solve(), IfElseSolver)
    assert isinstance(htlc_claim_solver.witness("testnet"), IfElseScript)

    bytecode_claim_solver = ClaimSolver(
        private_key=recipient_wallet.private_key(),
        secret="Hello Meheret!",
        # Witness from HTLC bytecode
        bytecode=
        "63aa20821124b554d13f247b1e5d10b84e44fb1296f18f38bbaa1bea34a12c843e01588876a91498f879fb7f8"
        "b4951dee9bc8a0327b792fbe332b888ac670164b27576a91464a8390b0b1685fcbf2d4b457118dc8da92d553488ac68"
    )

    assert recipient_wallet.private_key(
    ) == bytecode_claim_solver.private_key.hexlify()
    assert isinstance(bytecode_claim_solver.solve(), IfElseSolver)
    assert isinstance(bytecode_claim_solver.witness("testnet"), IfElseScript)

    with pytest.raises(TypeError, match="private key must be string format"):
        ClaimSolver(int(), str())
    with pytest.raises(TypeError, match="secret must be string format"):
        ClaimSolver(str(), int())
    with pytest.raises(TypeError, match="secret hash must be string format"):
        ClaimSolver(str(), str(), int())
    with pytest.raises(ValueError,
                       match="invalid secret hash, length must be 64"):
        ClaimSolver(str(), str(), str())
    with pytest.raises(AddressError, match=r"invalid recipient *.* address"):
        ClaimSolver(str(), str(), sha256(b"Hello Meheret!").hex(), "adsfsdfsd")
    with pytest.raises(AddressError, match=r"invalid sender *.* address"):
        ClaimSolver(str(), str(),
                    sha256(b"Hello Meheret!").hex(),
                    "2N729UBGZB3xjsGFRgKivy4bSjkaJGMVSpB", "adsfsdfsd")
    with pytest.raises(TypeError, match="sequence must be integer format"):
        ClaimSolver(str(), str(),
                    sha256(b"Hello Meheret!").hex(),
                    "2N729UBGZB3xjsGFRgKivy4bSjkaJGMVSpB",
                    "2N729UBGZB3xjsGFRgKivy4bSjkaJGMVSpB", float())
    with pytest.raises(TypeError, match="bytecode must be string format"):
        ClaimSolver(str(), str(), bytecode=123423423423)
Exemplo n.º 9
0
def test_bitcoin_claim_transaction():

    unsigned_claim_transaction = ClaimTransaction(version=2, network=network)

    unsigned_claim_transaction.build_transaction(transaction_id=transaction_id,
                                                 wallet=recipient_wallet,
                                                 amount=10_000)

    assert unsigned_claim_transaction.fee() == 576
    assert unsigned_claim_transaction.hash(
    ) == "a179dd565ea771869b0dfe1fd90c629f379cce9bd31d8814137fcb48fdd43b7e"
    assert unsigned_claim_transaction.raw(
    ) == "0200000001ec312e92d8387b15f6238d4918344b62ab147d7f3844dc81e653776fe8b84ef30000000000ffffffff01d0240000000000001976a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac00000000"
    assert unsigned_claim_transaction.json() == {
        'hex':
        '0200000001ec312e92d8387b15f6238d4918344b62ab147d7f3844dc81e653776fe8b84ef30000000000ffffffff01d0240000000000001976a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac00000000',
        'txid':
        'a179dd565ea771869b0dfe1fd90c629f379cce9bd31d8814137fcb48fdd43b7e',
        'hash':
        'a179dd565ea771869b0dfe1fd90c629f379cce9bd31d8814137fcb48fdd43b7e',
        'size':
        85,
        'vsize':
        85,
        'version':
        2,
        'locktime':
        0,
        'vin': [{
            'txid':
            'f34eb8e86f7753e681dc44387f7d14ab624b3418498d23f6157b38d8922e31ec',
            'vout': 0,
            'scriptSig': {
                'asm': '',
                'hex': ''
            },
            'sequence': '4294967295'
        }],
        'vout': [{
            'value': '0.00009424',
            'n': 0,
            'scriptPubKey': {
                'asm':
                'OP_DUP OP_HASH160 98f879fb7f8b4951dee9bc8a0327b792fbe332b8 OP_EQUALVERIFY OP_CHECKSIG',
                'hex': '76a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac',
                'type': 'p2pkh',
                'address': 'muTnffLDR5LtFeLR2i3WsKVfdyvzfyPnVB'
            }
        }]
    }
    assert unsigned_claim_transaction.type() == "bitcoin_claim_unsigned"
    assert unsigned_claim_transaction.unsigned_raw(
    ) == "eyJmZWUiOiA1NzYsICJyYXciOiAiMDIwMDAwMDAwMWVjMzEyZTkyZDgzODdiMTVmNjIzOGQ0OTE4MzQ0YjYyYWIxNDdkN2YzODQ0ZGM4MWU2NTM3NzZmZThiODRlZjMwMDAwMDAwMDAwZmZmZmZmZmYwMWQwMjQwMDAwMDAwMDAwMDAxOTc2YTkxNDk4Zjg3OWZiN2Y4YjQ5NTFkZWU5YmM4YTAzMjdiNzkyZmJlMzMyYjg4OGFjMDAwMDAwMDAiLCAib3V0cHV0cyI6IHsiYW1vdW50IjogMTAwMDAsICJuIjogMCwgInNjcmlwdCI6ICJhOTE0MmJiMDEzYzNlNGJlYjA4NDIxZGVkY2Y4MTVjYjY1YTVjMzg4MTc4Yjg3In0sICJuZXR3b3JrIjogInRlc3RuZXQiLCAidHlwZSI6ICJiaXRjb2luX2NsYWltX3Vuc2lnbmVkIn0="

    signed_claim_transaction = unsigned_claim_transaction.sign(
        solver=ClaimSolver(private_key=recipient_wallet.private_key(),
                           secret="Hello Meheret!",
                           secret_hash=sha256("Hello Meheret!".encode()).hex(),
                           recipient_address=recipient_wallet.address(),
                           sender_address=sender_wallet.address(),
                           sequence=1000))

    assert signed_claim_transaction.fee() == 576
    assert signed_claim_transaction.hash(
    ) == "8f98079b6257d65abc2c1c1a14c3bff50a6be949e75a30c127b3a2c0618012e1"
    assert signed_claim_transaction.raw(
    ) == "0200000001ec312e92d8387b15f6238d4918344b62ab147d7f3844dc81e653776fe8b84ef300000000d9473044022060291b5a87474f775dda5c244b21fc2716bfa09c4636ea4c707918c9f759374e02201ef5e768af10d01a1031294e952f6a8ed5c0a75e23f58aee062a89fed2134af70121039213ebcaefdd3e109720c17867ce1bd6d076b0e65e3b6390e6e38548a65e76af0e48656c6c6f204d65686572657421514c5d63aa20821124b554d13f247b1e5d10b84e44fb1296f18f38bbaa1bea34a12c843e01588876a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac6702e803b27576a91464a8390b0b1685fcbf2d4b457118dc8da92d553488ac68ffffffff01d0240000000000001976a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac00000000"
    assert signed_claim_transaction.json() == {
        'hex':
        '0200000001ec312e92d8387b15f6238d4918344b62ab147d7f3844dc81e653776fe8b84ef300000000d9473044022060291b5a87474f775dda5c244b21fc2716bfa09c4636ea4c707918c9f759374e02201ef5e768af10d01a1031294e952f6a8ed5c0a75e23f58aee062a89fed2134af70121039213ebcaefdd3e109720c17867ce1bd6d076b0e65e3b6390e6e38548a65e76af0e48656c6c6f204d65686572657421514c5d63aa20821124b554d13f247b1e5d10b84e44fb1296f18f38bbaa1bea34a12c843e01588876a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac6702e803b27576a91464a8390b0b1685fcbf2d4b457118dc8da92d553488ac68ffffffff01d0240000000000001976a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac00000000',
        'txid':
        '8f98079b6257d65abc2c1c1a14c3bff50a6be949e75a30c127b3a2c0618012e1',
        'hash':
        '8f98079b6257d65abc2c1c1a14c3bff50a6be949e75a30c127b3a2c0618012e1',
        'size':
        302,
        'vsize':
        302,
        'version':
        2,
        'locktime':
        0,
        'vin': [{
            'txid':
            'f34eb8e86f7753e681dc44387f7d14ab624b3418498d23f6157b38d8922e31ec',
            'vout': 0,
            'scriptSig': {
                'asm':
                '3044022060291b5a87474f775dda5c244b21fc2716bfa09c4636ea4c707918c9f759374e02201ef5e768af10d01a1031294e952f6a8ed5c0a75e23f58aee062a89fed2134af701 039213ebcaefdd3e109720c17867ce1bd6d076b0e65e3b6390e6e38548a65e76af 48656c6c6f204d65686572657421 OP_1 63aa20821124b554d13f247b1e5d10b84e44fb1296f18f38bbaa1bea34a12c843e01588876a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac6702e803b27576a91464a8390b0b1685fcbf2d4b457118dc8da92d553488ac68',
                'hex':
                '473044022060291b5a87474f775dda5c244b21fc2716bfa09c4636ea4c707918c9f759374e02201ef5e768af10d01a1031294e952f6a8ed5c0a75e23f58aee062a89fed2134af70121039213ebcaefdd3e109720c17867ce1bd6d076b0e65e3b6390e6e38548a65e76af0e48656c6c6f204d65686572657421514c5d63aa20821124b554d13f247b1e5d10b84e44fb1296f18f38bbaa1bea34a12c843e01588876a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac6702e803b27576a91464a8390b0b1685fcbf2d4b457118dc8da92d553488ac68'
            },
            'sequence': '4294967295'
        }],
        'vout': [{
            'value': '0.00009424',
            'n': 0,
            'scriptPubKey': {
                'asm':
                'OP_DUP OP_HASH160 98f879fb7f8b4951dee9bc8a0327b792fbe332b8 OP_EQUALVERIFY OP_CHECKSIG',
                'hex': '76a91498f879fb7f8b4951dee9bc8a0327b792fbe332b888ac',
                'type': 'p2pkh',
                'address': 'muTnffLDR5LtFeLR2i3WsKVfdyvzfyPnVB'
            }
        }]
    }
    assert signed_claim_transaction.type() == "bitcoin_claim_signed"