Skip to content

Commit

Permalink
merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
manlikeHB committed Sep 9, 2024
2 parents e120fd2 + 76e96fd commit ee4b196
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 133 deletions.
6 changes: 3 additions & 3 deletions src/codec.cairo
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Bitcoin binary codec traits, implementations, and helpers.

use super::types::transaction::{Transaction, TxIn, TxOut, OutPoint};
use raito::utils::hash::Hash;
use raito::utils::hash::Digest;

pub trait Encode<T> {
/// Encode using Bitcoin codec and append to the buffer.
Expand Down Expand Up @@ -46,8 +46,8 @@ pub impl EncodeU64 of Encode<u64> {
}
}

pub impl EncodeHash of Encode<Hash> {
fn encode_to(self: @Hash, ref dest: ByteArray) {
pub impl EncodeHash of Encode<Digest> {
fn encode_to(self: @Digest, ref dest: ByteArray) {
dest.append(@(*self).into());
}
}
Expand Down
26 changes: 13 additions & 13 deletions src/types/block.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! The data is expected to be prepared in advance and passed as program arguments.

use crate::utils::hash::Hash;
use crate::utils::hash::Digest;
use crate::utils::sha256::double_sha256_u32_array;
use crate::utils::numeric::u32_byte_reverse;
use super::transaction::Transaction;
Expand All @@ -21,7 +21,7 @@ pub struct Block {
pub enum TransactionData {
/// Merkle root of all transactions in the block.
/// This variant is used for header-only validation mode (light client).
MerkleRoot: Hash,
MerkleRoot: Digest,
/// List of all transactions included in the block.
/// This variant is used for the full consensus validation mode.
Transactions: Span<Transaction>,
Expand Down Expand Up @@ -54,7 +54,7 @@ pub struct Header {
#[generate_trait]
pub impl BlockHashImpl of BlockHash {
/// Compute hash of the block header given the missing fields.
fn hash(self: @Header, prev_block_hash: Hash, merkle_root: Hash) -> Hash {
fn hash(self: @Header, prev_block_hash: Digest, merkle_root: Digest) -> Digest {
let mut header_data_u32: Array<u32> = array![];

header_data_u32.append(u32_byte_reverse(*self.version));
Expand All @@ -80,7 +80,7 @@ pub impl TransactionDataDefault of Default<TransactionData> {
mod tests {
use super::{Header, BlockHash};
use raito::types::chain_state::ChainState;
use raito::utils::hash::Hash;
use raito::utils::hash::Digest;

#[test]
fn test_block_hash() {
Expand All @@ -93,14 +93,14 @@ mod tests {
let header = Header {
version: 1_u32, time: 1231731025_u32, bits: 0x1d00ffff_u32, nonce: 1889418792_u32
};
let merkle_root: Hash =
let merkle_root: Digest =
0x7dac2c5666815c17a3b36427de37bb9d2e2c5ccec3f8633eb91a4205cb4c10ff_u256
.into();

let block_hash_result: Hash = header.hash(chain_state.best_block_hash, merkle_root);
let block_hash_result: Digest = header.hash(chain_state.best_block_hash, merkle_root);

//0x00000000d1145790a8694403d4063f323d499e655c83426834d4ce2f8dd4a2ee
let expected_block_hash: Hash =
let expected_block_hash: Digest =
0x00000000d1145790a8694403d4063f323d499e655c83426834d4ce2f8dd4a2ee_u256
.into();

Expand All @@ -118,13 +118,13 @@ mod tests {
let header = Header {
version: 1_u32, time: 1231731025_u32, bits: 0x1d00ffff_u32, nonce: 1889418792_u32
};
let merkle_root: Hash =
let merkle_root: Digest =
0x6dac2c5666815c17a3b36427de37bb9d2e2c5ccec3f8633eb91a4205cb4c10ff_u256
.into();

let block_hash_result: Hash = header.hash(chain_state.best_block_hash, merkle_root);
let block_hash_result: Digest = header.hash(chain_state.best_block_hash, merkle_root);

let expected_block_hash: Hash =
let expected_block_hash: Digest =
0x00000000d1145790a8694403d4063f323d499e655c83426834d4ce2f8dd4a2ee_u256
.into();

Expand All @@ -142,13 +142,13 @@ mod tests {
let header = Header {
version: 1_u32, time: 1231731025_u32, bits: 0x1d00ffff_u32, nonce: 1889418792_u32
};
let merkle_root: Hash =
let merkle_root: Digest =
0x7dac2c5666815c17a3b36427de37bb9d2e2c5ccec3f8633eb91a4205cb4c10ff_u256
.into();

let block_hash_result: Hash = header.hash(chain_state.best_block_hash, merkle_root);
let block_hash_result: Digest = header.hash(chain_state.best_block_hash, merkle_root);

let expected_block_hash: Hash =
let expected_block_hash: Digest =
0x00000000d1145790a8694403d4063f323d499e655c83426834d4ce2f8dd4a2ee_u256
.into();

Expand Down
6 changes: 3 additions & 3 deletions src/types/chain_state.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//! Chain state alone is not enough to do full block validation, however
//! it is sufficient to validate block headers.

use crate::utils::hash::Hash;
use crate::utils::hash::Digest;
use crate::validation::{
difficulty::{validate_bits, adjust_difficulty}, coinbase::validate_coinbase,
timestamp::{validate_timestamp, next_prev_timestamps},
Expand All @@ -20,7 +20,7 @@ pub struct ChainState {
/// Total work done.
pub total_work: u256,
/// Best block.
pub best_block_hash: Hash,
pub best_block_hash: Digest,
/// Current target.
pub current_target: u256,
/// Start of the current epoch.
Expand Down Expand Up @@ -97,6 +97,6 @@ pub impl BlockValidatorImpl of BlockValidator {
)
}
}
// TODO: implement Hash trait for ChainState
// TODO: implement Digest trait for ChainState


54 changes: 48 additions & 6 deletions src/types/transaction.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
//! Types are extended with extra information required for validation.
//! The data is expected to be prepared in advance and passed as program arguments.

use crate::utils::{hash::Hash};
use crate::utils::{hash::Digest};
use core::hash::{Hash, HashStateTrait};

/// Represents a transaction.
/// https://learnmeabitcoin.com/technical/transaction/
Expand Down Expand Up @@ -76,10 +77,10 @@ pub struct TxIn {
/// one by one, first inputs then outputs. Output validation might put something to the
/// cache while input validation might remove an item, thus it's important to maintain
/// the order.
#[derive(Drop, Copy, Debug, PartialEq, Serde)]
#[derive(Drop, Copy, Debug, PartialEq, Serde, Hash)]
pub struct OutPoint {
/// The hash of the referenced transaction.
pub txid: Hash,
pub txid: Digest,
/// The index of the specific output in the transaction.
pub vout: u32,
/// Referenced output data (meta field).
Expand All @@ -102,6 +103,7 @@ pub struct OutPoint {
pub is_coinbase: bool
}


/// Output of a transaction.
/// https://learnmeabitcoin.com/technical/transaction/output/
///
Expand All @@ -111,7 +113,7 @@ pub struct OutPoint {
/// - Do nothing in case of a provably unspendable output
///
/// Read more: https://en.bitcoin.it/wiki/Script#Provably_Unspendable/Prunable_Outputs
#[derive(Drop, Copy, Debug, PartialEq, Serde)]
#[derive(Drop, Copy, Debug, PartialEq, Serde, Hash)]
pub struct TxOut {
/// The value of the output in satoshis.
/// Can be in range [0, 21_000_000] BTC (including both ends).
Expand All @@ -137,12 +139,52 @@ impl ByteArraySnapSerde of Serde<@ByteArray> {
}
}


impl ByteArraySnapHash<S, +HashStateTrait<S>, +Drop<S>> of Hash<@ByteArray, S> {
#[inline]
fn update_state(mut state: S, value: @ByteArray) -> S {
let mut serialized_bytearray: Array<felt252> = array![];
value.serialize(ref serialized_bytearray);

for felt in serialized_bytearray {
state = state.update(felt);
};
state
}
}

impl TxOutDefault of Default<TxOut> {
fn default() -> TxOut {
TxOut { value: 0, pk_script: @"", cached: false, }
}
}
// TODO: implement Hash trait for OutPoint (for creating hash digests to use in utreexo/utxo cache)
// Maybe we need to rename utils::hash::Hash (e.g. to Digest) to avoid confusion

#[cfg(test)]
mod tests {
use super::HashStateTrait;
use core::hash::HashStateExTrait;
use core::poseidon::PoseidonTrait;
use super::{OutPoint, TxOut};
use crate::utils::{hash::{DigestTrait}};

#[test]
pub fn test_outpoint_poseidon_hash() {
let test_outpoint = OutPoint {
txid: DigestTrait::new([1, 2, 3, 4, 5, 6, 7, 8]),
vout: 2,
// https://learnmeabitcoin.com/explorer/tx/0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9#output-0
data: TxOut {
value: 50_u64,
pk_script: @"410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac",
cached: false,
},
block_height: 9,
block_time: 1650000000,
is_coinbase: false,
};
let hash = PoseidonTrait::new().update_with(test_outpoint).finalize();
assert_eq!(
hash, 2066345132208626685244560166700396327660679738257525753112003865133004328681
);
}
}
Loading

0 comments on commit ee4b196

Please sign in to comment.