8585 chmod +x submission/05.sh
8686 FEE=$(submission/05.sh)
8787 if [[ "$(actual_sha "$FEE")" == "$EXPECTED_05_SHA" ]]; then
88- echo "✅ Success: TX Fee (05.sh) verification passed!"
88+ echo "✅ Success: TX Fee verification passed!"
8989 else
90- echo "❌ Error: TX Fee (05.sh) verification failed!"
90+ echo "❌ Error: TX Fee verification failed!"
9191 exit 1
9292 fi
9393
@@ -141,6 +141,35 @@ jobs:
141141 exit 1
142142 fi
143143
144+ # Verify descriptor.txt is valid
145+ if [[ ! -s submission/descriptor.txt ]]; then
146+ echo "❌ Error : descriptor.txt is empty or missing."
147+ exit 1
148+ fi
149+ DESC=$(cat submission/descriptor.txt | tr -d '\n')
150+ DESC_INFO=$(bitcoin-cli -signet getdescriptorinfo "$DESC" 2>/dev/null) || true
151+ if [[ -z "$DESC_INFO" ]]; then
152+ echo "❌ descriptor.txt could not be validated."
153+ exit 1
154+ fi
155+ DESC_VALID=$(echo "$DESC_INFO" | jq -r '.issolvable')
156+ if [[ "$DESC_VALID" == "true" ]]; then
157+ echo "✅ Descriptor is valid."
158+ else
159+ echo "❌ Descriptor is not valid."
160+ exit 1
161+ fi
162+
163+ # Verify descriptor can derive at least one tb1 address
164+ DESC_CHECKSUM=$(echo "$DESC_INFO" | jq -r '.descriptor')
165+ DESC_ADDR=$(bitcoin-cli -signet deriveaddresses "$DESC_CHECKSUM" "[0,0]" | jq -r '.[0]')
166+ if [[ "$DESC_ADDR" == "tb1"* ]]; then
167+ echo "✅ Descriptor derives a valid signet address : $DESC_ADDR"
168+ else
169+ echo "❌ Descriptor does not derive a valid signet address."
170+ exit 1
171+ fi
172+
144173 # Verify native SegWit address exists
145174 if [ ! -s submission/address.txt ]; then
146175 echo "❌ Error : address.txt is empty or missing."
@@ -327,4 +356,137 @@ jobs:
327356 else
328357 echo "❌ multisig-coinbase does not match."
329358 exit 1
330- fi
359+ fi
360+
361+
362+ # # TASK 6 — PSBT
363+
364+ # Verify psbt.txt exists and is valid PSBT
365+ if [[ ! -s submission/psbt.txt ]]; then
366+ echo "❌ Error : psbt.txt is empty or missing."
367+ exit 1
368+ fi
369+ PSBT_BASE64=$(cat submission/psbt.txt | tr -d '\n')
370+ PSBT_DECODED=$(bitcoin-cli -signet decodepsbt "$PSBT_BASE64" 2>/dev/null) || true
371+ if [[ -n "$PSBT_DECODED" ]]; then
372+ echo "✅ psbt.txt contains a valid PSBT."
373+ else
374+ echo "❌ psbt.txt does not contain a valid PSBT."
375+ exit 1
376+ fi
377+
378+ # Verify PSBT has output paying 5,000 sats to the target address
379+ PSBT_TARGET=$(echo "$PSBT_DECODED" | jq -r '.tx.vout[] | select(.scriptPubKey.address=="tb1qddpcyus3u603n63lk7m5epjllgexc24vj5ltp7") | .value')
380+ if [[ "$PSBT_TARGET" == "0.00005000" ]]; then
381+ echo "✅ PSBT pays exactly 5,000 sats to target address."
382+ else
383+ echo "❌ PSBT does not pay 5,000 sats to target address."
384+ exit 1
385+ fi
386+
387+ # Verify psbt-tx.txt exists and tx is confirmed on signet
388+ if [[ ! -s submission/psbt-tx.txt ]]; then
389+ echo "❌ Error : psbt-tx.txt is empty or missing."
390+ exit 1
391+ fi
392+ PSBT_TXID=$(cat submission/psbt-tx.txt | tr -d '\n')
393+ PSBT_TX_DETAILS=$(bitcoin-cli -signet getrawtransaction "$PSBT_TXID" true 2>/dev/null) || true
394+ if [[ -n "$PSBT_TX_DETAILS" ]]; then
395+ echo "✅ PSBT transaction exists on signet : $PSBT_TXID"
396+ else
397+ echo "❌ PSBT transaction not found on signet : $PSBT_TXID"
398+ exit 1
399+ fi
400+
401+ # Verify the broadcast tx pays 5,000 sats to target
402+ PSBT_TX_AMOUNT=$(echo "$PSBT_TX_DETAILS" | jq -r '.vout[] | select(.scriptPubKey.address=="tb1qddpcyus3u603n63lk7m5epjllgexc24vj5ltp7") | .value')
403+ if [[ "$PSBT_TX_AMOUNT" == "0.00005000" ]]; then
404+ echo "✅ Broadcast PSBT transaction pays exactly 5,000 sats to target."
405+ else
406+ echo "❌ Broadcast PSBT transaction does not pay 5,000 sats to target."
407+ exit 1
408+ fi
409+
410+
411+ # # TASK 7 — P2WSH MULTISIG
412+
413+ # Verify p2wsh-address.txt
414+ if [[ ! -s submission/p2wsh-address.txt ]]; then
415+ echo "❌ Error : p2wsh-address.txt is empty or missing."
416+ exit 1
417+ fi
418+ P2WSH_ADDR=$(cat submission/p2wsh-address.txt | tr -d '\n')
419+ if [[ "$P2WSH_ADDR" == "tb1q"* ]]; then
420+ echo "✅ P2WSH address is native SegWit : $P2WSH_ADDR"
421+ else
422+ echo "❌ P2WSH address does not start with tb1q : $P2WSH_ADDR"
423+ exit 1
424+ fi
425+
426+ # Verify p2wsh-witness-script.txt is valid hex
427+ if [[ ! -s submission/p2wsh-witness-script.txt ]]; then
428+ echo "❌ Error : p2wsh-witness-script.txt is empty or missing."
429+ exit 1
430+ fi
431+ P2WSH_SCRIPT=$(cat submission/p2wsh-witness-script.txt | tr -d '\n')
432+ if [[ "$P2WSH_SCRIPT" =~ ^[0-9a-fA-F]+$ ]]; then
433+ echo "✅ P2WSH witness script is valid hex."
434+ else
435+ echo "❌ P2WSH witness script is not valid hex."
436+ exit 1
437+ fi
438+
439+ # Verify p2wsh-funding-tx.txt exists on signet and pays to the P2WSH address
440+ if [[ ! -s submission/p2wsh-funding-tx.txt ]]; then
441+ echo "❌ Error : p2wsh-funding-tx.txt is empty or missing."
442+ exit 1
443+ fi
444+ P2WSH_TXID=$(cat submission/p2wsh-funding-tx.txt | tr -d '\n')
445+ P2WSH_TX=$(bitcoin-cli -signet getrawtransaction "$P2WSH_TXID" true 2>/dev/null) || true
446+ if [[ -z "$P2WSH_TX" ]]; then
447+ echo "❌ P2WSH funding transaction not found on signet : $P2WSH_TXID"
448+ exit 1
449+ fi
450+ P2WSH_MATCH=$(echo "$P2WSH_TX" | jq --arg addr "$P2WSH_ADDR" '.vout[] | select(.scriptPubKey.address == $addr)')
451+ if [[ -n "$P2WSH_MATCH" ]]; then
452+ echo "✅ P2WSH funding transaction pays to the P2WSH address."
453+ else
454+ echo "❌ P2WSH funding transaction does not pay to the P2WSH address."
455+ exit 1
456+ fi
457+
458+
459+ # # TASK 8 — OP_RETURN
460+
461+ # Verify opreturn-tx.txt exists on signet
462+ if [[ ! -s submission/opreturn-tx.txt ]]; then
463+ echo "❌ Error : opreturn-tx.txt is empty or missing."
464+ exit 1
465+ fi
466+ OPRETURN_TXID=$(cat submission/opreturn-tx.txt | tr -d '\n')
467+ OPRETURN_TX=$(bitcoin-cli -signet getrawtransaction "$OPRETURN_TXID" true 2>/dev/null) || true
468+ if [[ -z "$OPRETURN_TX" ]]; then
469+ echo "❌ OP_RETURN transaction not found on signet : $OPRETURN_TXID"
470+ exit 1
471+ fi
472+ echo "✅ OP_RETURN transaction exists on signet : $OPRETURN_TXID"
473+
474+ # Verify tx has a nulldata output
475+ OPRETURN_HEX=$(echo "$OPRETURN_TX" | jq -r '.vout[] | select(.scriptPubKey.type=="nulldata") | .scriptPubKey.hex')
476+ if [[ -z "$OPRETURN_HEX" ]]; then
477+ echo "❌ Transaction does not contain an OP_RETURN output."
478+ exit 1
479+ fi
480+ echo "✅ Transaction contains an OP_RETURN output."
481+
482+ # Verify the OP_RETURN data matches the student's GitHub username
483+ OPRETURN_DATA=$(echo "$OPRETURN_HEX" | sed 's/^6a//' | sed 's/^..//')
484+ OPRETURN_DECODED=$(echo "$OPRETURN_DATA" | xxd -r -p)
485+ EXPECTED_OPRETURN_SHA=$(printf '%s' "$WALLET" | sha256sum | awk '{print $1}')
486+ ACTUAL_OPRETURN_SHA=$(printf '%s' "$OPRETURN_DECODED" | sha256sum | awk '{print $1}')
487+ if [[ "$ACTUAL_OPRETURN_SHA" == "$EXPECTED_OPRETURN_SHA" ]]; then
488+ echo "✅ OP_RETURN data matches GitHub username."
489+ else
490+ echo "❌ OP_RETURN data does not match GitHub username."
491+ exit 1
492+ fi
0 commit comments