Skip to content

Commit

Permalink
Script to run mainnet block transactions (#253)
Browse files Browse the repository at this point in the history
<!-- enter the gh issue after hash -->

- [ ] issue #
- [ ] follows contribution
[guide](https://github.com/keep-starknet-strange/shinigami/blob/main/CONTRIBUTING.md)
- [ ] code change includes tests

<!-- PR description below -->
  • Loading branch information
b-j-roberts authored Oct 5, 2024
1 parent 8e70313 commit a33a3c7
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 3 deletions.
19 changes: 17 additions & 2 deletions packages/cmds/src/main.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,26 @@ struct ValidateRawInput {
utxo_hints: Array<UTXO>
}

fn run_raw_transaction(input: ValidateRawInput) -> u8 {
fn run_raw_transaction(mut input: ValidateRawInput) -> u8 {
println!("Running Bitcoin Script with raw transaction: '{}'", input.raw_transaction);
let raw_transaction = hex_to_bytecode(@input.raw_transaction);
let transaction = TransactionTrait::deserialize(raw_transaction);
let res = validate::validate_transaction(@transaction, 0, input.utxo_hints);
let mut utxo_hints = array![];
for hint in input
.utxo_hints
.span() {
println!("UTXO hint: 'amount: {}, script_pubkey: {}'", hint.amount, hint.pubkey_script);
let pubkey_script = hex_to_bytecode(hint.pubkey_script);
utxo_hints
.append(
UTXO {
amount: *hint.amount,
pubkey_script: pubkey_script,
block_height: *hint.block_height,
}
);
};
let res = validate::validate_transaction(@transaction, 0, utxo_hints);
match res {
Result::Ok(_) => {
println!("Execution successful");
Expand Down
2 changes: 1 addition & 1 deletion packages/engine/src/engine.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::transaction::{
use crate::hash_cache::{HashCache, HashCacheTrait};
use crate::witness;
use shinigami_utils::byte_array::{byte_array_to_bool, byte_array_to_felt252_le};
use shinigami_utils::bytecode::hex_to_bytecode;
use shinigami_utils::bytecode::{hex_to_bytecode, bytecode_to_hex};
use shinigami_utils::hash::sha256_byte_array;

pub const MAX_STACK_SIZE: u32 = 1000;
Expand Down
75 changes: 75 additions & 0 deletions scripts/run_bitcoin_transaction.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/bin/bash
#
# This script fetches and runs a bitcoin transaction using Shinigami Script Engine.

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
BASE_DIR=$SCRIPT_DIR/..

TXID=$1

RPC_API="https://bitcoin-mainnet.public.blastapi.io"

# Input needed
# raw_transaction_hex: ByteArray,
# utxo_hints: Array<UTXO>
# pub struct UTXO {
# pub amount: i64,
# pub pubkey_script: ByteArray,
# pub block_height: i32,
# // TODO: flags?
#}

# Fetch the transaction
RES=$(curl -s -X POST -H "Content-Type: application/json" -d "{\"jsonrpc\":\"1.0\",\"id\":0,\"method\":\"getrawtransaction\",\"params\":[\"$TXID\", true]}" $RPC_API)

RAW_TX_HEX=$(echo $RES | jq '.result.hex' | tr -d '"')
RAW_TX_HEX="0x$RAW_TX_HEX"
# echo "RAW_TX_HEX: $RAW_TX_HEX"

RAW_TX_TEXT=$($SCRIPT_DIR/text_to_byte_array.sh $RAW_TX_HEX)
RAW_TX_INPUT=$(sed 's/^\[\(.*\)\]$/\1/' <<< $RAW_TX_TEXT)
# echo "RAW_TX_INPUT: $RAW_TX_INPUT"

# Fetch the vin's for utxo_hints
VINS=$(echo $RES | jq '.result.vin')
# echo "VINS: $VINS"

BLOCK_HEIGHT=0 # TODO?
AMOUNT=0 # TODO?
UTXOS=""
for vin in $(echo $VINS | jq -r '.[] | @base64'); do
_jq() {
echo ${vin} | base64 --decode | jq -r ${1}
}

TXID=$(echo $(_jq '.txid'))
VOUT=$(echo $(_jq '.vout'))

# Fetch the transaction
RES=$(curl -s -X POST -H "Content-Type: application/json" -d "{\"jsonrpc\":\"1.0\",\"id\":0,\"method\":\"getrawtransaction\",\"params\":[\"$TXID\", true]}" $RPC_API)

# AMOUNT=$(echo $RES | jq ".result.vout[$VOUT].value")
# echo "AMOUNT: $AMOUNT"

PUBKEY_SCRIPT=$(echo $RES | jq ".result.vout[$VOUT].scriptPubKey.hex" | tr -d '"')
PUBKEY_SCRIPT="0x$PUBKEY_SCRIPT"
# echo "PUBKEY_SCRIPT: $PUBKEY_SCRIPT"

PUBKEY_SCRIPT_TEXT=$($SCRIPT_DIR/text_to_byte_array.sh $PUBKEY_SCRIPT)
PUBKEY_SCRIPT_INPUT=$(sed 's/^\[\(.*\)\]$/\1/' <<< $PUBKEY_SCRIPT_TEXT)
# echo "PUBKEY_SCRIPT_INPUT: $PUBKEY_SCRIPT_INPUT"

# Construct UTXO
UTXO="{\"amount\":$AMOUNT,\"pubkey_script\":\"$PUBKEY_SCRIPT\",\"block_height\":$BLOCK_HEIGHT}"
# echo "UTXO: $UTXO"

UTXOS="$UTXOS$AMOUNT,$PUBKEY_SCRIPT_INPUT,$BLOCK_HEIGHT,"
done
UTXOS=$(sed 's/,$//' <<< $UTXOS)

JOINED_INPUT="[$RAW_TX_INPUT,[$UTXOS]]"
# echo "JOINED_INPUT: $JOINED_INPUT"

echo "scarb cairo-run --package shinigami_cmds --function run_raw_transaction \"$JOINED_INPUT\""
scarb cairo-run --package shinigami_cmds --function run_raw_transaction --no-build $JOINED_INPUT
# TODO: Error checking
55 changes: 55 additions & 0 deletions scripts/run_block_transactions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/bin/bash
#
# This script fetches and runs a bitcoin transaction using Shinigami Script Engine.

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
BASE_DIR=$SCRIPT_DIR/..

BLOCK=$1
echo "Running block $BLOCK"

OUTPUTS=$BASE_DIR/outputs/block-$BLOCK
mkdir -p $OUTPUTS

RPC_API="https://bitcoin-mainnet.public.blastapi.io"

# Fetch blockhash
RES=$(curl -s -X POST -H "Content-Type: application/json" -d "{\"jsonrpc\":\"1.0\",\"id\":0,\"method\":\"getblockhash\", \"params\": [$BLOCK]}" $RPC_API)
BLOCKHASH=$(echo $RES | jq -r '.result')

# Fetch the block
RES=$(curl -s -X POST -H "Content-Type: application/json" -d "{\"jsonrpc\":\"1.0\",\"id\":0,\"method\":\"getblock\", \"params\": [\"$BLOCKHASH\"]}" $RPC_API)

# Loop through the transactions
FIRST_IDX=$2
if [ -z "$FIRST_IDX" ]; then
FIRST_IDX=0
fi
LAST_IDX=$3
if [ -z "$LAST_IDX" ]; then
LAST_IDX=$(echo $RES | jq -r ".result.tx | length")
fi
IDX=$FIRST_IDX
while true; do
TXID=$(echo $RES | jq -r ".result.tx[$IDX]")
if [ "$TXID" == "null" ]; then
break
fi
OUTPUT_FILE=$OUTPUTS/tx-$IDX.txt
rm -f $OUTPUT_FILE
touch $OUTPUT_FILE
echo "Running transaction $BLOCK::$IDX - $TXID" >> $OUTPUT_FILE
echo "" >> $OUTPUT_FILE
if [ $IDX -eq 0 ]; then
# TODO
echo "Skipping coinbase transaction" >> $OUTPUT_FILE
IDX=$((IDX+1))
continue
fi
$SCRIPT_DIR/run_bitcoin_transaction.sh $TXID >> $OUTPUT_FILE
IDX=$((IDX+1))
if [ $IDX -ge $LAST_IDX ]; then
break
fi
done
echo "Done running block $BLOCK"
25 changes: 25 additions & 0 deletions scripts/run_blocks.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash
#
# This script runs all transactions in a blocks

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
BASE_DIR=$SCRIPT_DIR/..

echo "Building shinigami..."
cd $BASE_DIR && scarb build
echo "Shinigami built successfully!"
echo

START_BLOCK=$1
END_BLOCK=$2
echo "Running blocks $START_BLOCK to $END_BLOCK"

IDX=$START_BLOCK
while true; do
$SCRIPT_DIR/run_block_transactions.sh $IDX
IDX=$((IDX+1))
if [ $IDX -ge $END_BLOCK ]; then
break
fi
done
echo "Done running blocks"
File renamed without changes.

0 comments on commit a33a3c7

Please sign in to comment.