Skip to content

Latest commit

 

History

History
786 lines (595 loc) · 17.7 KB

File metadata and controls

786 lines (595 loc) · 17.7 KB

Testing Guide for Bitcoin Transaction Scripts

Table of Contents

  1. Prerequisites
  2. Environment Setup
  3. Testing Question 1 (P2PKH)
  4. Testing Question 2 (Custom Script)
  5. Testing Question 3 (Multisig)
  6. Testing Question 4 (Atomic Swap)
  7. Verification Methods
  8. Common Issues and Solutions

Prerequisites

Required Software

  • Python 3.7 or higher
  • pip package manager
  • Internet connection for API calls

Required Accounts

  • BlockCypher account with API token (free tier is sufficient)
  • Access to Bitcoin Testnet3 faucets
  • Access to BCY Testnet faucets

Installation Verification

# Check Python version
python --version  # Should be 3.7+

# Check pip
pip --version

# Install dependencies
pip install -r requirements.txt

# Verify installation
python -c "import bitcoin; print('bitcoin-lib installed successfully')"
python -c "import requests; print('requests installed successfully')"

Environment Setup

Step 1: Generate Keys

For Questions 1-3, generate a Bitcoin testnet key pair:

cd lib/
python keygen.py

This will output:

  • Private key (Base58)
  • Public key (hex)
  • Address

Example output:

Private key: cTk4zH8F5zKxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Public key: 02f5d8axxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Address: mn6bEQxxxxxxxxxxxxxxxxxxxxxxxxx

Step 2: Fund Your Address

Visit a Bitcoin testnet faucet and send coins to your address:

Wait for 1-3 confirmations (approximately 10-30 minutes).

Step 3: Verify Funds

Check your balance using BlockCypher:

curl https://api.blockcypher.com/v1/btc/test3/addrs/YOUR_ADDRESS/balance

Step 4: Update Configuration

Edit lib/config.py and add your private key:

my_private_key = CBitcoinSecret('YOUR_PRIVATE_KEY_FROM_KEYGEN')

Testing Question 1 (P2PKH)

Purpose

Test the standard Pay-To-Public-Key-Hash transaction implementation.

Test Steps

  1. Check your balance:
curl https://api.blockcypher.com/v1/btc/test3/addrs/$(python -c "from lib.config import my_address; print(my_address)")/balance
  1. Get UTXO information:
curl https://api.blockcypher.com/v1/btc/test3/addrs/YOUR_ADDRESS

Look for the txrefs array to find:

  • tx_hash: Your txid_to_spend
  • tx_output_n: Your utxo_index
  • value: Amount in satoshis (divide by 100,000,000 for BTC)
  1. Update Q1.py parameters:
amount_to_send = 0.00099  # Your UTXO value minus fee
txid_to_spend = 'abc123...'  # From tx_hash above
utxo_index = 0  # From tx_output_n above
  1. Run the test:
python Q1.py
  1. Expected output:
200 OK
{"tx": {"hash": "def456..."}, ...}
  1. Verify transaction:
curl https://api.blockcypher.com/v1/btc/test3/txs/NEW_TX_HASH

Validation Criteria

  • ✓ Script verification passes (no errors)
  • ✓ Transaction is accepted by network (200 OK response)
  • ✓ Transaction appears on blockchain explorer
  • ✓ Faucet address receives the funds

Testing Question 2 (Custom Script)

Purpose

Test custom script creation and redemption using SHA-256 hash verification.

Test Steps

Part A: Create Custom Script Transaction

  1. Update Q2a.py parameters:
amount_to_send = 0.00099
txid_to_spend = 'your_txid'
utxo_index = 0
  1. Run Q2a:
python Q2a.py
  1. Save the transaction hash from response

  2. Wait for confirmation (1-3 blocks)

Part B: Redeem Custom Script Transaction

  1. Update Q2b.py parameters:
amount_to_send = 0.00098  # Q2a amount minus fee
txid_to_spend = 'tx_hash_from_Q2a'
utxo_index = 0
  1. Run Q2b:
python Q2b.py
  1. Verify redemption:
  • Check that scriptSig contains two copies of "secret"
  • Verify both SHA-256 hashes match
  • Confirm transaction is accepted

Validation Criteria

  • ✓ Q2a transaction creates custom script output
  • ✓ Q2b successfully redeems with correct secret
  • ✓ Both transactions confirmed on blockchain
  • ✓ Script logic correctly validates identical inputs

Testing Different Scenarios

Test with wrong secret: Modify Q2b.py temporarily:

txin_scriptSig = [
    "wrong".encode('utf-8'),
    "secret".encode('utf-8'),
]

Expected: Script verification should fail

Test with single input:

txin_scriptSig = [
    "secret".encode('utf-8'),
]

Expected: Script verification should fail (stack underflow)

Testing Question 3 (Multisig)

Purpose

Test 2-of-3 multisignature transaction creation and redemption.

Test Steps

Part A: Generate Customer Keys

  1. Generate three key pairs:
python lib/keygen.py  # Run three times
  1. Update Q3a.py with customer keys:
cust1_private_key = CBitcoinSecret('customer1_key')
cust2_private_key = CBitcoinSecret('customer2_key')
cust3_private_key = CBitcoinSecret('customer3_key')

Part B: Create Multisig Transaction

  1. Update Q3a.py parameters:
amount_to_send = 0.00099
txid_to_spend = 'your_txid'
utxo_index = 0
  1. Run Q3a:
python Q3a.py
  1. Save transaction hash and wait for confirmation

Part C: Redeem Multisig Transaction

  1. Update Q3b.py parameters:
amount_to_send = 0.00098
txid_to_spend = 'tx_hash_from_Q3a'
utxo_index = 0
  1. Run Q3b:
python Q3b.py

Validation Criteria

  • ✓ Multisig script correctly requires 2 of 3 signatures
  • ✓ Transaction verifies with customer1 and customer2 signatures
  • ✓ OP_0 is included (CHECKMULTISIG bug workaround)
  • ✓ Both transactions confirmed

Testing Different Signature Combinations

Modify multisig_scriptSig in Q3b.py to test different combinations:

Test 1: Customer 1 and 2

return [OP_0, cust1_sig, cust2_sig]

Test 2: Customer 1 and 3

return [OP_0, cust1_sig, cust3_sig]

Test 3: Customer 2 and 3

return [OP_0, cust2_sig, cust3_sig]

Test 4: Only one signature (should fail)

return [OP_0, cust1_sig]

Testing Question 4 (Atomic Swap)

Purpose

Test cross-chain atomic swap between BTC Testnet3 and BCY Testnet.

Test Steps

Setup Phase

  1. Generate keys for both networks:

For BTC Testnet3:

python lib/keygen.py

For BCY Testnet:

curl -X POST https://api.blockcypher.com/v1/bcy/test/addrs?token=YOUR_TOKEN
  1. Update lib/config.py with all keys:
alice_secret_key_BTC = CBitcoinSecret('alice_btc_key')
bob_secret_key_BTC = CBitcoinSecret('bob_btc_key')

alice_secret_key_BCY = CBitcoinSecret.from_secret_bytes(x('alice_bcy_private_hex'))
bob_secret_key_BCY = CBitcoinSecret.from_secret_bytes(x('bob_bcy_private_hex'))
  1. Fund addresses:

Alice BTC (Testnet3):

Bob BCY:

curl -d '{"address": "BOB_BCY_ADDRESS", "amount": 1000000}' \
  https://api.blockcypher.com/v1/bcy/test/faucet?token=YOUR_TOKEN
  1. Verify funds:
# Check Alice BTC
curl https://api.blockcypher.com/v1/btc/test3/addrs/ALICE_BTC_ADDRESS/balance

# Check Bob BCY
curl https://api.blockcypher.com/v1/bcy/test/addrs/BOB_BCY_ADDRESS/balance
  1. Get current block heights:
# BTC Testnet3
curl https://api.blockcypher.com/v1/btc/test3 | grep height

# BCY Testnet
curl https://api.blockcypher.com/v1/bcy/test | grep height

Update Q4.py Configuration

# Alice's BTC transaction
alice_txid_to_spend = "alice_txid_from_faucet"
alice_utxo_index = 0
alice_amount_to_send = 0.001

# Bob's BCY transaction
bob_txid_to_spend = "bob_txid_from_faucet"
bob_utxo_index = 0
bob_amount_to_send = 0.001

# Block heights (update with current values)
btc_test3_chain_height = 2500000  # Update
bcy_test_chain_height = 3000000   # Update

# Timelocks (in blocks)
alice_locktime = 5  # Must be > bob_locktime
bob_locktime = 3

tx_fee = 0.0001

Test Scenario 1: Successful Swap (Alice Redeems)

  1. Configure for successful swap:
broadcast_transactions = True
alice_redeems = True
  1. Run the swap:
python swap.py
  1. Monitor progress: The script will output:
Alice swap tx (BTC) created successfully!
Bob swap tx (BCY) created successfully!
Sleeping for 30 minutes to let transactions confirm...
Alice redeem from swap tx (BCY) created successfully!
Bob redeem from swap tx (BTC) created successfully!
  1. Verify transactions:

Check Alice's BTC swap transaction:

curl https://api.blockcypher.com/v1/btc/test3/txs/ALICE_SWAP_TXID

Check Bob's BCY swap transaction:

curl https://api.blockcypher.com/v1/bcy/test/txs/BOB_SWAP_TXID

Check Alice's redemption (BCY):

curl https://api.blockcypher.com/v1/bcy/test/txs/ALICE_REDEEM_TXID

Verify secret is revealed in Alice's redemption transaction.

Check Bob's redemption (BTC):

curl https://api.blockcypher.com/v1/btc/test3/txs/BOB_REDEEM_TXID

Test Scenario 2: Refund Path (Alice Doesn't Redeem)

  1. Configure for refund:
broadcast_transactions = True
alice_redeems = False
  1. Run the swap:
python swap.py
  1. Monitor progress:
Alice swap tx (BTC) created successfully!
Bob swap tx (BCY) created successfully!
Sleeping for 30 minutes to let transactions confirm...
Sleeping for bob_locktime blocks to pass locktime...
Bob return coins (BCY) tx created successfully!
Sleeping for alice_locktime blocks to pass locktime...
Alice return coins tx (BTC) created successfully!
  1. Verify refund transactions:

Both parties should receive their original coins back after timelocks expire.

Test Scenario 3: Dry Run (No Broadcast)

  1. Configure for dry run:
broadcast_transactions = False
alice_redeems = True
  1. Run the swap:
python swap.py
  1. Verify:
  • All transactions are created successfully
  • Script verification passes
  • No actual broadcasting occurs

Validation Criteria

Successful Swap:

  • ✓ Alice creates valid BTC swap transaction
  • ✓ Bob creates valid BCY swap transaction
  • ✓ Alice can redeem Bob's BCY with secret
  • ✓ Secret is revealed on BCY blockchain
  • ✓ Bob can redeem Alice's BTC using revealed secret
  • ✓ Both parties receive swapped coins

Refund Path:

  • ✓ Swap transactions are created but not redeemed
  • ✓ After bob_locktime, Bob can refund with both signatures
  • ✓ After alice_locktime, Alice can refund with both signatures
  • ✓ Both parties recover original coins

Security Properties:

  • ✓ Bob cannot redeem without knowing secret
  • ✓ Alice cannot take Bob's coins without revealing secret
  • ✓ Timelocks prevent premature redemption
  • ✓ 2-of-2 multisig prevents unilateral refunds

Verification Methods

Method 1: API Verification

Use BlockCypher API to check transaction status:

# Check transaction details
curl https://api.blockcypher.com/v1/btc/test3/txs/TX_HASH

# Check address balance
curl https://api.blockcypher.com/v1/btc/test3/addrs/ADDRESS/balance

# Check UTXO status
curl https://api.blockcypher.com/v1/btc/test3/addrs/ADDRESS/full

Method 2: Block Explorer Verification

Visit these explorers to manually verify transactions:

BTC Testnet3:

BCY Testnet:

Method 3: Script Verification

All scripts include built-in verification using VerifyScript:

VerifyScript(txin.scriptSig, CScript(txin_scriptPubKey),
             tx, 0, (SCRIPT_VERIFY_P2SH,))

If this passes without exception, the script is valid.

Method 4: Decode Raw Transaction

# Get raw transaction
curl https://api.blockcypher.com/v1/btc/test3/txs/TX_HASH?includeHex=true

# Decode using bitcoin-cli (if available)
bitcoin-cli -testnet decoderawtransaction RAW_HEX

Common Issues and Solutions

Issue 1: Insufficient Funds

Symptom:

Error: Not enough funds

Solution:

  • Verify you have received funds from faucet
  • Check that amount_to_send < available balance
  • Ensure you account for transaction fees
  • Wait for previous transactions to confirm

Issue 2: Script Verification Failed

Symptom:

bitcoin.core.scripteval.VerifyScriptError: ...

Solution:

  • Double-check scriptPubKey implementation
  • Verify scriptSig provides correct inputs
  • Ensure signatures are created with correct keys
  • Check stack operations match expected flow

Issue 3: Transaction Not Found

Symptom:

404 Not Found

Solution:

  • Verify the txid is correct (64 hex characters)
  • Check that transaction has been broadcast
  • Wait for transaction to propagate (1-2 minutes)
  • Ensure you're using correct network (testnet vs mainnet)

Issue 4: UTXO Already Spent

Symptom:

Error: Input already spent

Solution:

  • Get a new UTXO from faucet
  • Check transaction history to find unspent outputs
  • Use split_test_coins.py to create multiple UTXOs

Issue 5: Timelock Not Passed

Symptom:

Error: Locktime requirement not satisfied

Solution:

  • Wait for more blocks to be mined
  • Verify current block height is greater than nLockTime
  • Check that transaction nSequence allows locktime

Issue 6: Multisig Signature Order

Symptom:

Error: Signature must be zero for failed CHECK(MULTI)SIG operation

Solution:

  • Ensure OP_0 is first element in scriptSig
  • Verify signatures are in correct order matching public keys
  • Check that you have enough signatures (2 for 2-of-3)

Issue 7: API Rate Limiting

Symptom:

Error: 429 Too Many Requests

Solution:

  • Wait a few minutes before retrying
  • Use API token for higher rate limits
  • Implement exponential backoff
  • Cache responses when possible

Issue 8: Network Connectivity

Symptom:

requests.exceptions.ConnectionError

Solution:

  • Check internet connection
  • Verify API endpoints are accessible
  • Check if BlockCypher API is down
  • Try alternative blockchain explorers

Testing Checklist

Use this checklist to ensure complete testing:

Question 1 (P2PKH)

  • Private key generated and configured
  • Test coins received from faucet
  • UTXO identified correctly
  • Transaction broadcasts successfully
  • Transaction confirms on blockchain
  • Faucet receives coins

Question 2 (Custom Script)

  • Q2a creates custom script transaction
  • Transaction confirms
  • Q2b redeems with correct secret
  • Tested with wrong secret (should fail)
  • Both transactions on blockchain

Question 3 (Multisig)

  • Three customer key pairs generated
  • Multisig transaction created
  • Transaction confirms
  • Redemption with 2 signatures works
  • Tested different signature combinations
  • Verified OP_0 requirement

Question 4 (Atomic Swap)

  • Keys generated for both networks
  • Both addresses funded
  • Block heights updated
  • Dry run successful (broadcast=False)
  • Successful swap path tested (alice_redeems=True)
  • Refund path tested (alice_redeems=False)
  • Secret revealed correctly
  • Timelocks working properly

Performance Benchmarks

Expected timings for each test:

Operation Expected Time
Key Generation < 1 second
Transaction Creation < 1 second
Script Verification < 1 second
API Broadcast 1-3 seconds
First Confirmation 10-30 minutes
Full Confirmation (6 blocks) 1-3 hours
Atomic Swap Complete 1-2 hours

Security Testing

Test Invalid Inputs

  1. Invalid Signature:
# Use wrong private key
wrong_sig = wrong_private_key.sign(sighash)
  1. Invalid Public Key:
# Use wrong public key
wrong_public_key = wrong_private_key.pub
  1. Modified Transaction:
# Change amount after signing
txout = create_txout(different_amount, ...)

All these should result in script verification failure.

Test Replay Attacks

Try to rebroadcast the same transaction twice:

curl -d '{"tx": "SAME_RAW_TX"}' \
  https://api.blockcypher.com/v1/btc/test3/txs/push

Expected: Second attempt should fail (transaction already in mempool/blockchain).

Automated Testing Script

Create a test runner script run_tests.sh:

#!/bin/bash

echo "Running Bitcoin Transaction Tests..."

# Test Q1
echo "Testing Q1 (P2PKH)..."
python Q1.py > test_q1.log 2>&1
if [ $? -eq 0 ]; then
    echo "✓ Q1 passed"
else
    echo "✗ Q1 failed - check test_q1.log"
fi

# Test Q2a
echo "Testing Q2a (Custom Script Creation)..."
python Q2a.py > test_q2a.log 2>&1
if [ $? -eq 0 ]; then
    echo "✓ Q2a passed"
else
    echo "✗ Q2a failed - check test_q2a.log"
fi

# Wait for confirmation
echo "Waiting 20 minutes for Q2a confirmation..."
sleep 1200

# Test Q2b
echo "Testing Q2b (Custom Script Redemption)..."
python Q2b.py > test_q2b.log 2>&1
if [ $? -eq 0 ]; then
    echo "✓ Q2b passed"
else
    echo "✗ Q2b failed - check test_q2b.log"
fi

echo "Testing complete. Review log files for details."

Make executable and run:

chmod +x run_tests.sh
./run_tests.sh

Conclusion

This testing guide provides comprehensive procedures for validating all Bitcoin transaction script implementations. Follow each section carefully, verify results at each step, and use the troubleshooting guide when issues arise.

For additional help:

  • Review the README.md for implementation details
  • Check docs/Q4design_doc.txt for atomic swap design
  • Consult Bitcoin Script documentation
  • Review BlockCypher API documentation

Remember: Always test on testnet before any mainnet operations!