update exercises #19
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Run Setup Script | |
| on: | |
| push: | |
| branches: | |
| - main # Trigger on pushes to the main branch | |
| jobs: | |
| bitcoin-setup: | |
| runs-on: ubuntu-latest # Use the latest Ubuntu environment | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 # Check out the repository code | |
| - name: Cache Bitcoin Core | |
| id: cache-bitcoin | |
| uses: actions/cache@v3 | |
| with: | |
| path: | | |
| bitcoin-28.0 | |
| bitcoin-28.0-x86_64-linux-gnu.tar.gz | |
| key: bitcoin-core-28.0 | |
| - name: Setup Bitcoin Core | |
| run: | | |
| if [ "${{ steps.cache-bitcoin.outputs.cache-hit }}" != 'true' ]; then | |
| wget https://bitcoincore.org/bin/bitcoin-core-28.0/bitcoin-28.0-x86_64-linux-gnu.tar.gz | |
| tar -xzvf bitcoin-28.0-x86_64-linux-gnu.tar.gz | |
| fi | |
| sudo bash .github/setup.sh | |
| - name: Start bitcoind in regtest mode | |
| run: | | |
| bitcoind -regtest -daemon | |
| echo "Waiting for bitcoind to be ready..." | |
| # Wait for bitcoind to start (max 30s) | |
| for i in {1..30}; do | |
| if bitcoin-cli -regtest getblockchaininfo > /dev/null 2>&1; then | |
| echo "✅ bitcoind is ready!" | |
| break | |
| fi | |
| echo "Still waiting for bitcoind..." | |
| sleep 1 | |
| done | |
| - name: 01.sh - Verify Wallet Creation | |
| run: | | |
| chmod +x submission/01.sh | |
| WALLET=$(submission/01.sh) | |
| if [[ "$WALLET" == *"btrustwallet"* ]]; then | |
| echo "✅ Success: Wallet creation passed!" | |
| else | |
| echo "❌ Error: Wallet creation failed!" | |
| exit 1 | |
| fi | |
| - name: 02.sh - Verify Change Address Generation | |
| run: | | |
| chmod +x submission/02.sh | |
| CHANGE_ADDRESS=$(submission/02.sh) | |
| if [[ "$CHANGE_ADDRESS" =~ ^bcrt1[ac-hj-np-z02-9]{8,87}$ ]]; then | |
| echo "✅ Success: Change address generation passed!" | |
| else | |
| echo "❌ Error: Change address generation failed!" | |
| exit 1 | |
| fi | |
| - name: 03.sh - Verify Adding Funds to SegWit Address | |
| run: | | |
| chmod +x submission/03.sh | |
| ADD=$(submission/03.sh) | |
| BALANCE=$(bitcoin-cli -regtest getreceivedbyaddress "$ADD" 0) | |
| if (( $(echo "$BALANCE > 0" | bc -l) )); then | |
| echo "✅ Success: Adding funds to SegWit address passed!" | |
| else | |
| echo "❌ Error: Adding funds to SegWit address failed!" | |
| exit 1 | |
| fi | |
| - name: 04.sh - Verify Listing the current UTXOs in your wallet. | |
| run: | | |
| chmod +x submission/04.sh | |
| UTXOs=$(submission/04.sh) | |
| if [[ "$UTXOs" != "[]" && "$UTXOs" =~ "txid" ]]; then | |
| echo "✅ Success: Listing the current UTXOs in your wallet passed!" | |
| else | |
| echo "❌ Error: Listing the current UTXOs in your wallet failed!" | |
| exit 1 | |
| fi | |
| - name: 05.sh - Verify Transaction ID | |
| run: | | |
| chmod +x submission/05.sh | |
| TRANSACTION_ID=$(submission/05.sh) | |
| EXPECTED_OUTPUT=23c19f37d4e92e9a115aab86e4edc1b92a51add4e0ed0034bb166314dde50e16 | |
| if [[ "$TRANSACTION_ID" == "$EXPECTED_OUTPUT" ]]; then | |
| echo "✅ Success: Transaction ID Check passed!" | |
| else | |
| echo "❌ Error: Transaction ID Check failed!" | |
| exit 1 | |
| fi | |
| - name: 06.sh - Verify Total Transaction Output Amount In Satoshis | |
| run: | | |
| chmod +x submission/06.sh | |
| ACTUAL_OUTPUT=$(submission/06.sh) | |
| EXPECTED_OUTPUT=23679108 | |
| if [[ "$ACTUAL_OUTPUT" == "$EXPECTED_OUTPUT" ]]; then | |
| echo "✅ Success: Total Transaction Output Amount In Satoshis Check passed!" | |
| else | |
| echo "❌ Error: Total Transaction Output Amount In Satoshis Check failed!" | |
| exit 1 | |
| fi | |
| - name: 07.sh - Verify Raw Transaction Hex | |
| run: | | |
| chmod +x submission/07.sh | |
| ACTUAL_OUTPUT=$(submission/07.sh) | |
| EXPECTED_OUTPUT=0200000002160ee5dd146316bb3400ede0d4ad512ab9c1ede486ab5a119a2ee9d4379fc1230000000000fdffffff160ee5dd146316bb3400ede0d4ad512ab9c1ede486ab5a119a2ee9d4379fc1230100000000fdffffff01002d31010000000017a91421ed90762e16eaaea188aae19142e5b25bf75d238700000000 | |
| if [[ "$ACTUAL_OUTPUT" == "$EXPECTED_OUTPUT" ]]; then | |
| echo "✅ Success: Raw Transaction Hex Check passed!" | |
| else | |
| echo "❌ Error: Raw Transaction Hex Check failed!" | |
| exit 1 | |
| fi | |
| - name: 08.sh - Verify Raw Transaction Hex | |
| run: | | |
| chmod +x submission/08.sh | |
| ACTUAL_OUTPUT=$(submission/08.sh) | |
| EXPECTED_OUTPUT=0200000002160ee5dd146316bb3400ede0d4ad512ab9c1ede486ab5a119a2ee9d4379fc1230000000000fdffffff160ee5dd146316bb3400ede0d4ad512ab9c1ede486ab5a119a2ee9d4379fc1230100000000fdffffff01640269010000000017a91421ed90762e16eaaea188aae19142e5b25bf75d238700000000 | |
| if [[ "$ACTUAL_OUTPUT" == "$EXPECTED_OUTPUT" ]]; then | |
| echo "✅ Success: Raw Transaction Hex Check passed!" | |
| else | |
| echo "❌ Error: Raw Transaction Hex Check failed!" | |
| exit 1 | |
| fi | |
| - name: 09.sh - Verify Raw Transaction Hex | |
| run: | | |
| chmod +x submission/09.sh | |
| ACTUAL_OUTPUT=$(submission/09.sh) | |
| EXPECTED_OUTPUT=0200000002160ee5dd146316bb3400ede0d4ad512ab9c1ede486ab5a119a2ee9d4379fc123000000000001000000160ee5dd146316bb3400ede0d4ad512ab9c1ede486ab5a119a2ee9d4379fc12301000000000100000001002d31010000000017a91421ed90762e16eaaea188aae19142e5b25bf75d238700000000 | |
| if [[ "$ACTUAL_OUTPUT" == "$EXPECTED_OUTPUT" ]]; then | |
| echo "✅ Success: Raw Transaction Hex Check passed!" | |
| else | |
| echo "❌ Error: Raw Transaction Hex Check failed!" | |
| exit 1 | |
| fi | |
| - name: final.sh - Verify Advanced Transaction Exercise | |
| run: | | |
| chmod +x submission/final.sh | |
| echo "Running finalexercise script..." | |
| # Run the script with a timeout to handle potential infinite loops | |
| ACTUAL_OUTPUT=$(timeout 30s submission/final.sh || echo "ERROR: Script execution failed or timed out") | |
| ACTUAL_OUTPUT=${ACTUAL_OUTPUT: -164} | |
| # First check: Verify output is a valid transaction hex string | |
| if ! [[ $ACTUAL_OUTPUT =~ ^02[0-9a-fA-F]+$ ]]; then | |
| echo "❌ Error: Advanced Transaction Exercise failed! Output is not a valid hex string." | |
| echo "Output: $ACTUAL_OUTPUT" | |
| exit 1 | |
| fi | |
| echo "✓✅ Basic check passed: Output is a valid hex string format" | |
| # Second check: Verify it's a valid Bitcoin transaction | |
| echo "Verifying transaction validity..." | |
| DECODED_TX=$(bitcoin-cli -regtest decoderawtransaction "$ACTUAL_OUTPUT" 2>/dev/null) | |
| if [ $? -ne 0 ]; then | |
| echo "❌ Error: Invalid transaction format! The hex string is not a valid Bitcoin transaction." | |
| exit 1 | |
| fi | |
| echo "✓✅ Transaction validity check passed: Output is a valid Bitcoin transaction" | |
| # Third check: Verify RBF is enabled via sequence numbers | |
| echo "Checking RBF implementation..." | |
| VIN_SEQUENCES=$(echo "$DECODED_TX" | jq -r '.vin[].sequence') | |
| RBF_ENABLED=false | |
| for seq in $VIN_SEQUENCES; do | |
| # Any sequence number below 0xFFFFFFFE (4294967294) enables RBF | |
| if [ "$seq" -lt 4294967294 ]; then | |
| RBF_ENABLED=true | |
| break | |
| fi | |
| done | |
| if [ "$RBF_ENABLED" = false ]; then | |
| echo "❌ Error: RBF not enabled! All sequence numbers are ≥ 4294967294." | |
| exit 1 | |
| fi | |
| echo "✓✅ RBF check passed: Transaction has at least one input with RBF-enabling sequence number" | |
| # Fourth check: Verify transaction has multiple outputs (payment + change) | |
| echo "Checking transaction structure..." | |
| NUM_VOUTS=$(echo "$DECODED_TX" | jq '.vout | length') | |
| if [ "$NUM_VOUTS" -lt 1 ]; then | |
| echo "❌ Error: Transaction doesn't have any outputs!" | |
| exit 1 | |
| fi | |
| echo "✓✅ Transaction structure check passed: Transaction has $NUM_VOUTS output(s)" | |
| # Fifth check: Look for a CSV timelock implementation | |
| # Note: The final transaction should have a timelock implementation | |
| echo "Checking for timelock implementation..." | |
| # This is a simplified check - we're looking for any sequence number that could be a timelock | |
| # In a real scenario, we'd check more specifically for the exact timelock requirements | |
| CSV_FOUND=false | |
| for seq in $VIN_SEQUENCES; do | |
| # Look for sequence values that are low numbers (typical for CSV timelock) | |
| # This is a heuristic check since we don't know exactly which input uses CSV | |
| if [ "$seq" -gt 0 ] && [ "$seq" -lt 100 ]; then | |
| CSV_FOUND=true | |
| break | |
| fi | |
| done | |
| # This is a soft check - we'll warn but not fail the build | |
| if [ "$CSV_FOUND" = false ]; then | |
| echo "⚠️ Warning: No obvious CSV timelock implementation found. Sequence numbers don't indicate a typical timelock value." | |
| echo "This might still be correct depending on the specific implementation." | |
| else | |
| echo "✓ Timelock check passed: Found potential CSV timelock implementation" | |
| fi | |
| echo "✅ Success: Advanced Transaction Exercise passed all critical checks!" | |
| echo "Transaction is valid, enables RBF, and has proper structure." |