Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] Implement txid function #44

Merged
merged 28 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions src/state.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,6 @@ pub struct Transaction {
pub lock_time: u32,
}

/// Output of a transaction.
/// https://learnmeabitcoin.com/technical/transaction/output/
#[derive(Drop, Copy)]
pub struct TxOut {
/// The value of the output in satoshis.
pub value: i64,
/// The spending script (aka locking code) for this output.
pub pk_script: @ByteArray,
}

/// Input of a transaction.
/// https://learnmeabitcoin.com/technical/transaction/input/
///
Expand All @@ -127,7 +117,7 @@ pub struct TxIn {
/// The reference to the previous output that is being used as an input.
pub previous_output: OutPoint,
/// The witness data for transactions.
pub witness: Span<ByteArray>,
pub witness: @ByteArray,
TAdev0 marked this conversation as resolved.
Show resolved Hide resolved
}


Expand All @@ -141,3 +131,13 @@ pub struct OutPoint {
/// The index of output in the utreexo set (meta field).
pub txo_index: u64,
}

/// Output of a transaction.
/// https://learnmeabitcoin.com/technical/transaction/output/
#[derive(Drop, Copy)]
pub struct TxOut {
/// The value of the output in satoshis.
pub value: u64,
/// The spending script (aka locking code) for this output.
pub pk_script: @ByteArray,
}
23 changes: 23 additions & 0 deletions src/utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,26 @@ pub fn double_sha256(a: u256, b: u256) -> u256 {
low: x4.into() * TWO_POW_96 + x5.into() * TWO_POW_64 + x6.into() * TWO_POW_32 + x7.into(),
}
}

TAdev0 marked this conversation as resolved.
Show resolved Hide resolved
fn hex_to_byte(h: u8) -> u8 {
if h >= 48 && h <= 57 {
return h - 48;
} else if h >= 65 && h <= 70 {
return h - 55;
} else if h >= 97 && h <= 102 {
return h - 87;
}
panic!("Wrong hex character: {h}");
0
}

pub fn from_base16(hexs: ByteArray) -> @ByteArray {
let mut result: ByteArray = Default::default();
let mut i = 0;
let len = hexs.len();
while i < len {
result.append_word(hex_to_byte(hexs.at(i).unwrap()).into(), 4);
i += 1;
};
@result
}
136 changes: 130 additions & 6 deletions src/validation.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use core::sha256::{compute_sha256_byte_array, compute_sha256_u32_array};
use super::state::{Block, ChainState, Transaction, UtreexoState, TxIn, TxOut, OutPoint};
use super::merkle_tree::merkle_root;
use super::utils::{shl, shr};
use super::state::{Block, ChainState, Transaction, UtreexoState};

const MAX_TARGET: u256 = 0x00000000FFFF0000000000000000000000000000000000000000000000000000;

Expand Down Expand Up @@ -38,11 +39,98 @@ impl BlockValidatorImpl of BlockValidator {
}

#[generate_trait]
impl TransactionValidatorImpl of TransactionValidator {
pub impl TransactionValidatorImpl of TransactionValidator {
// marker, flag, and witness fields in segwit transactions are not included
// this means txid computation is the same for legacy and segwit tx
fn txid(self: @Transaction) -> u256 {
// TODO: implement
0
let version: felt252 = (*self.version).into();
TAdev0 marked this conversation as resolved.
Show resolved Hide resolved
let inputs_count: felt252 = (*self.inputs).len().into();
let inputs: Span<TxIn> = *self.inputs;
let outputs_count: felt252 = (*self.outputs).len().into();
let outputs: Span<TxOut> = *self.outputs;
let locktime: felt252 = (*self.lock_time).into();

// append version (1 byte)
let mut sha256_input: ByteArray = "";
sha256_input.append_word(version, 1);
TAdev0 marked this conversation as resolved.
Show resolved Hide resolved

// append padding (3 bytes)
let padding: felt252 = 0;
sha256_input.append_word(padding, 3);

// append inputs count
sha256_input.append_word(inputs_count, 1);

// append inputs
TAdev0 marked this conversation as resolved.
Show resolved Hide resolved
let mut i = 0;
// != instead of < to avoid range check builtin usage for comparison
while i != inputs.len() {
TAdev0 marked this conversation as resolved.
Show resolved Hide resolved
// append txid
let txid: u256 = (*inputs[i]).previous_output.txid.into();
let txid_high: felt252 = txid.high.into();
let txid_low: felt252 = txid.low.into();
sha256_input.append_word(txid_high, 16);
sha256_input.append_word(txid_low, 16);

// append VOUT
let vout: felt252 = (*inputs[i]).previous_output.vout.into();
sha256_input.append_word(vout, 4);

// append ScriptSig size
let scriptsig_size: felt252 = (*inputs[i]).script.len().into();
sha256_input.append_word(scriptsig_size, 4);

// append ScriptSig
let script_sig: @ByteArray = (*inputs[i]).script;
sha256_input.append(script_sig);

// append Sequence
let sequence: felt252 = (*inputs.at(i)).sequence.into();
sha256_input.append_word(sequence, 4);

i += 1;
};

// append outputs count
sha256_input.append_word(outputs_count, 1);

// append outputs
TAdev0 marked this conversation as resolved.
Show resolved Hide resolved
let mut i = 0;
while i != outputs.len() {
// append amount
let amount: felt252 = (*outputs.at(i).value).into();
sha256_input.append_word(amount, 8);

// append ScriptPubKey size
let script_size: felt252 = (*outputs.at(i).pk_script).len().into();
sha256_input.append_word(script_size, 1);

// append ScriptPubKey
let script: @ByteArray = *outputs.at(i).pk_script;
sha256_input.append(script);

i += 1;
};

// append locktime
sha256_input.append_word(locktime, 4);

// Compute double sha256
let firstHash = compute_sha256_byte_array(@sha256_input).span();
TAdev0 marked this conversation as resolved.
Show resolved Hide resolved
let secondHash = compute_sha256_u32_array(firstHash.into(), 0, 0).span();

let mut txid: u256 = 0;
let mut i: u32 = 0;
while i != 8 {
let element: u256 = (*secondHash[i]).into();
txid += shl(element, (32 * i));

i += 1;
};

txid
}

fn fee(self: @Transaction) -> u256 {
// TODO: implement
0
Expand Down Expand Up @@ -207,12 +295,13 @@ fn compute_block_reward(block_height: u32) -> u64 {
#[cfg(test)]
mod tests {
use raito::state::{Header, Transaction, TxIn, TxOut};
use raito::utils::from_base16;
use super::{
validate_timestamp, validate_proof_of_work, compute_block_reward, compute_total_work,
compute_work_from_target, shr, shl, Block, ChainState, UtreexoState,
compute_work_from_target, shr, shl, TransactionValidatorImpl, Block, ChainState,
UtreexoState, OutPoint
};


#[test]
fn test_validate_timestamp() {
let mut chain_state = ChainState {
Expand Down Expand Up @@ -350,4 +439,39 @@ mod tests {
let last_reward = compute_block_reward(max_halvings * block_height);
assert_eq!(last_reward, 0);
}
// #[test]
TAdev0 marked this conversation as resolved.
Show resolved Hide resolved
// fn test_txid() {
// let tx: Transaction = Transaction {
// version: 1,
// is_segwit: false,
// inputs: array![
// TxIn {
// script: from_base16(
// "4730440220758f18952b4ebe859b91bdfc86d67478e85511f9fe949c30ab9ea12c78ddf9be0220146e88b5a89ca14a3505c17a13c9f6654014ecce1ca2910db525f6b2b23e680a012102d13c14dfd083b9b19b50ad6f6209902179f98a1acda715633b5622267e067676"
// ),
// sequence: 0xffffffff,
// previous_output: OutPoint {
// txid:
// 0x183e7d7146f1fe51a79417dce4c7b0b6f848f844ff56c12d2242f86d52fae8cb_u256,
// vout: 0x01000000_u32, txo_index: 0,
// },
// witness: from_base16("")
// }
// ]
// .span(),
// outputs: array![
// TxOut {
// value: 0x04bdcd0200000000,
// pk_script: from_base16("76a9142bd74c02779861ee95f9dc61c870d31e15a29c3a88ac"),
// }
// ]
// .span(),
// lock_time: 0
// };

// let txid: u256 = TransactionValidatorImpl::txid(@tx);
// assert_eq!(
// txid, 31117111977866514605580122280379099880855664600995121277970332180238727346730
// );
// }
}
2 changes: 2 additions & 0 deletions tests/lib.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod tests;
mod utils;