From e6d1f14231fe3c0ad276bbb7a287a6c7699383a7 Mon Sep 17 00:00:00 2001 From: Bartosz Nowak Date: Fri, 5 Jan 2024 12:17:11 +0100 Subject: [PATCH 01/12] crude implementation --- calc.py | 2 + src/common/array_append.cairo | 30 +++++++++++++++ src/lib.cairo | 1 + src/proof_of_work.cairo | 5 +++ src/proof_of_work/config.cairo | 15 ++++++++ src/proof_of_work/proof_of_work.cairo | 53 +++++++++++++++++++++++++++ src/proof_of_work/tests.cairo | 0 7 files changed, 106 insertions(+) create mode 100644 calc.py create mode 100644 src/proof_of_work.cairo create mode 100644 src/proof_of_work/config.cairo create mode 100644 src/proof_of_work/proof_of_work.cairo create mode 100644 src/proof_of_work/tests.cairo diff --git a/calc.py b/calc.py new file mode 100644 index 000000000..49292ec36 --- /dev/null +++ b/calc.py @@ -0,0 +1,2 @@ +print(2 ** 64) +print(256 ** 8) \ No newline at end of file diff --git a/src/common/array_append.cairo b/src/common/array_append.cairo index 4a173f1f0..8ecba931a 100644 --- a/src/common/array_append.cairo +++ b/src/common/array_append.cairo @@ -74,3 +74,33 @@ impl ArrayU32AppendU128 of ArrayAppendTrait { } } } + +impl ArrayU32AppendU64 of ArrayAppendTrait { + fn append_little_endian(ref self: Array, mut element: u64) { + let mut i = 2; + loop { + if i != 0 { + i -= 1; + let (q, r) = DivRem::div_rem(element, U64maxU32.try_into().unwrap()); + self.append(r.try_into().unwrap()); + element = q; + } else { + break; + } + } + } + + fn append_big_endian(ref self: Array, mut element: u64) { + let mut array = ArrayTrait::::new(); + array.append_little_endian(element); + let mut i = array.len(); + loop { + if i != 0 { + i -= 1; + self.append((*array.at(i)).flip_endianness()); + } else { + break; + } + } + } +} \ No newline at end of file diff --git a/src/lib.cairo b/src/lib.cairo index f73e223d9..e724d95fb 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -8,6 +8,7 @@ mod fri; mod table_commitment; mod vector_commitment; mod queries; +mod proof_of_work; use cairo_verifier::input_structs::stark_proof::StarkProof; diff --git a/src/proof_of_work.cairo b/src/proof_of_work.cairo new file mode 100644 index 000000000..389059c37 --- /dev/null +++ b/src/proof_of_work.cairo @@ -0,0 +1,5 @@ +mod proof_of_work; +mod config; + +#[cfg(test)] +mod tests; diff --git a/src/proof_of_work/config.cairo b/src/proof_of_work/config.cairo new file mode 100644 index 000000000..9f436fcb2 --- /dev/null +++ b/src/proof_of_work/config.cairo @@ -0,0 +1,15 @@ +const MIN_PROOF_OF_WORK_BITS: u256 = 30; +const MAX_PROOF_OF_WORK_BITS: u256 = 50; +const BYTE_UPPER_BOUND: u32 = 256; // 2 ** 8 +const WORD_UPPER_BOUND: u128 = 18446744073709551616; // 2 ** 64 + +#[derive(Drop, Copy)] +struct ProofOfWorkConfig { + // Proof of work difficulty (number of bits required to be 0). + n_bits: u8, +} + +fn proof_of_work_config_validate(config: ProofOfWorkConfig) { + assert(config.n_bits.into() >= MIN_PROOF_OF_WORK_BITS, 'value proof of work bits to low'); + assert(config.n_bits.into() <= MIN_PROOF_OF_WORK_BITS, 'value proof of work bits to big'); +} diff --git a/src/proof_of_work/proof_of_work.cairo b/src/proof_of_work/proof_of_work.cairo new file mode 100644 index 000000000..b1363cd32 --- /dev/null +++ b/src/proof_of_work/proof_of_work.cairo @@ -0,0 +1,53 @@ +use cairo_verifier::{ + common::{blake2s::blake2s, array_append::ArrayAppendTrait, math::pow}, + channel::channel::{Channel, ChannelTrait}, + proof_of_work::config::{ProofOfWorkConfig, BYTE_UPPER_BOUND, WORD_UPPER_BOUND} +}; + +#[derive(Drop, Copy)] +struct ProofOfWorkUnsentCommitment { + nonce: u64, +} + +fn proof_of_work_commit( + ref channel: Channel, unsent_commitment: ProofOfWorkUnsentCommitment, config: ProofOfWorkConfig +) { + channel.read_uint64_from_prover(unsent_commitment.nonce); + verify_proof_of_work(channel.digest, config.n_bits, unsent_commitment.nonce); +} + +fn verify_proof_of_work(digest: u256, n_bits: u8, nonce: u64) { + // Compute the initial hash. + // Hash(0123456789abcded || digest || n_bits) + // 8 bytes || 0x20 bytes || 1 byte + // Total of 0x29 bytes. + // Arrange the hash input according to the keccak requirement of 0x10 byte chunks. + let init_hash_value: u256 = 0x0123456789abcded000000000000000000000000000000000000000000000000 + // digest >> 12 -> digest << 4 + + digest / 79228162514264337593543950336 * 4294967296 + // nbits << 3 + + n_bits.into() * 16777216; + + let mut init_hash_data = ArrayTrait::::new(); + init_hash_data.append_big_endian(init_hash_value); + let init_hash = blake2s(init_hash_data); + + // Compute Hash(init_hash || nonce ) + // 0x20 bytes || 8 bytes + // Total of 0x28 bytes. + + // init_hash >> 12 -> init_hash << 8 + 4 + let hash_value: u256 = init_hash / 79228162514264337593543950336 * 79228162514264337593543950336 + // nonce << 4 + + nonce.into() * 4294967296; + + let mut hash_data = ArrayTrait::::new(); + hash_data.append_big_endian(hash_value); + let hash = blake2s(hash_data); + let work_limit = pow(2, 128 - n_bits.into()); + + assert( + Into::::into(hash.high) < Into::::into(work_limit), + 'proof of work failed' + ) +} diff --git a/src/proof_of_work/tests.cairo b/src/proof_of_work/tests.cairo new file mode 100644 index 000000000..e69de29bb From a33d6412e8ece22ba08f6552a5e1daa48cfc86b0 Mon Sep 17 00:00:00 2001 From: Bartosz Nowak Date: Sat, 6 Jan 2024 16:30:52 +0100 Subject: [PATCH 02/12] function skaffold --- src/proof_of_work/proof_of_work.cairo | 86 +++-- src/proof_of_work/tests.cairo | 1 + .../tests/test_proof_of_work.cairo | 12 + src/vector_commitment/tests.cairo | 6 - .../tests/test_vector_commitment.cairo | 55 ---- .../tests/test_vector_commitment_big.cairo | 310 ------------------ src/vector_commitment/vector_commitment.cairo | 162 --------- 7 files changed, 67 insertions(+), 565 deletions(-) create mode 100644 src/proof_of_work/tests/test_proof_of_work.cairo delete mode 100644 src/vector_commitment/tests.cairo delete mode 100644 src/vector_commitment/tests/test_vector_commitment.cairo delete mode 100644 src/vector_commitment/tests/test_vector_commitment_big.cairo delete mode 100644 src/vector_commitment/vector_commitment.cairo diff --git a/src/proof_of_work/proof_of_work.cairo b/src/proof_of_work/proof_of_work.cairo index b1363cd32..3bda3a0a2 100644 --- a/src/proof_of_work/proof_of_work.cairo +++ b/src/proof_of_work/proof_of_work.cairo @@ -1,8 +1,17 @@ +use core::array::SpanTrait; +use core::array::ArrayTrait; +use cairo_verifier::common::flip_endianness::FlipEndiannessTrait; +use core::debug::PrintTrait; use cairo_verifier::{ common::{blake2s::blake2s, array_append::ArrayAppendTrait, math::pow}, channel::channel::{Channel, ChannelTrait}, proof_of_work::config::{ProofOfWorkConfig, BYTE_UPPER_BOUND, WORD_UPPER_BOUND} }; +use cairo_verifier::common::array_print::{SpanPrintTrait, ArrayPrintTrait}; + +const POW_2_12: u256 = 79228162514264337593543950336; +const POW_2_4: u256 = 4294967296; +const POW_2_3: u256 = 16777216; #[derive(Drop, Copy)] struct ProofOfWorkUnsentCommitment { @@ -18,36 +27,49 @@ fn proof_of_work_commit( fn verify_proof_of_work(digest: u256, n_bits: u8, nonce: u64) { // Compute the initial hash. - // Hash(0123456789abcded || digest || n_bits) - // 8 bytes || 0x20 bytes || 1 byte - // Total of 0x29 bytes. - // Arrange the hash input according to the keccak requirement of 0x10 byte chunks. - let init_hash_value: u256 = 0x0123456789abcded000000000000000000000000000000000000000000000000 - // digest >> 12 -> digest << 4 - + digest / 79228162514264337593543950336 * 4294967296 - // nbits << 3 - + n_bits.into() * 16777216; - - let mut init_hash_data = ArrayTrait::::new(); - init_hash_data.append_big_endian(init_hash_value); - let init_hash = blake2s(init_hash_data); - - // Compute Hash(init_hash || nonce ) - // 0x20 bytes || 8 bytes - // Total of 0x28 bytes. - - // init_hash >> 12 -> init_hash << 8 + 4 - let hash_value: u256 = init_hash / 79228162514264337593543950336 * 79228162514264337593543950336 - // nonce << 4 - + nonce.into() * 4294967296; - - let mut hash_data = ArrayTrait::::new(); - hash_data.append_big_endian(hash_value); - let hash = blake2s(hash_data); - let work_limit = pow(2, 128 - n_bits.into()); - - assert( - Into::::into(hash.high) < Into::::into(work_limit), - 'proof of work failed' - ) + // Hash(0123456789abcded || digest || n_bits ) + // 8 bytes || 32 bytes || 1 byte + // Total of 0x29 = 41 bytes. + + // let init_hash_value: u256 = 0x0123456789abcded000000000000000000000000000000000000000000000000 + // // digest >> 12 -> digest << 4 -> nbits << 3 + // + digest / POW_2_12 * POW_2_4 + n_bits.into() * POW_2_3; + + let mut init_hash_data = ArrayTrait::::new(); + init_hash_data.append_big_endian(u256{low: 0xD7CA1D48A19D8FF802A71D94169DE383, high: 0x0123456789ABCDED1C5A5F4381DF1F5C}); + init_hash_data.append_big_endian(u256{low: 0x00000000000000000000000000000000, high: 0x82621FDC5514A10A1400000000000000}); + let span = init_hash_data.span().slice(0,41); + let mut arr = ArrayTrait::::new(); + let mut i:u32 = 0; + loop { + if i == span.len() { + break; + } + + arr.append(*span.at(i)); + i+=1; + }; + let init_hash = blake2s(arr).flip_endianness(); + init_hash.print(); + + // correct hash on test data: + // 0x6ae49da749fbe3fc98f114c0f8342a4d + // 0x26438c9c119a3b222f70d564d5df2ebc + + // // Compute Hash(init_hash || nonce ) + // // 32 bytes || 8 bytes + // // Total of 0x28 = 40 bytes. + + // // init_hash >> 12 -> init_hash << 8 + 4 -> nonce << 4 + // let hash_value: u256 = init_hash / POW_2_12 * POW_2_12 + nonce.into() * POW_2_4; + + // let mut hash_data = ArrayTrait::::new(); + // hash_data.append_big_endian(hash_value); + // let hash = blake2s(hash_data); + // let work_limit = pow(2, 128 - n_bits.into()); + + // assert( + // Into::::into(hash.high) < Into::::into(work_limit), + // 'proof of work failed' + // ) } diff --git a/src/proof_of_work/tests.cairo b/src/proof_of_work/tests.cairo index e69de29bb..1164558f8 100644 --- a/src/proof_of_work/tests.cairo +++ b/src/proof_of_work/tests.cairo @@ -0,0 +1 @@ +mod test_proof_of_work; \ No newline at end of file diff --git a/src/proof_of_work/tests/test_proof_of_work.cairo b/src/proof_of_work/tests/test_proof_of_work.cairo new file mode 100644 index 000000000..0f183537a --- /dev/null +++ b/src/proof_of_work/tests/test_proof_of_work.cairo @@ -0,0 +1,12 @@ +use cairo_verifier::proof_of_work::proof_of_work::verify_proof_of_work; + +// 142085208829254859155982631899283860045, 50861399631734199073966002375401352892 + +#[test] +#[available_gas(9999999999)] +fn test_proof_of_work_0() { + let digest: u256 = 0x1C5A5F4381DF1F5CD7CA1D48A19D8FF802A71D94169DE38382621FDC5514A10A; + let nonce: u64 = 0x1683B; + let n_bits: u8 = 20; + verify_proof_of_work(digest, n_bits, nonce); +} \ No newline at end of file diff --git a/src/vector_commitment/tests.cairo b/src/vector_commitment/tests.cairo deleted file mode 100644 index 81a308fb7..000000000 --- a/src/vector_commitment/tests.cairo +++ /dev/null @@ -1,6 +0,0 @@ -mod test_vector_commitment; -// notice: this test takes a lot of time and computation -// uncomment it when making changes to vector_commitment_decommit -// mod test_vector_commitment_big; - - diff --git a/src/vector_commitment/tests/test_vector_commitment.cairo b/src/vector_commitment/tests/test_vector_commitment.cairo deleted file mode 100644 index e0d7d34d2..000000000 --- a/src/vector_commitment/tests/test_vector_commitment.cairo +++ /dev/null @@ -1,55 +0,0 @@ -use cairo_verifier::vector_commitment::vector_commitment::{ - VectorCommitment, VectorCommitmentConfig, vector_commit, validate_vector_commitment -}; -use cairo_verifier::channel::channel::Channel; - - -#[test] -#[available_gas(9999999999)] -fn test_vector_commit() { - let mut channel = Channel { - digest: 0x0f089f70240c88c355168624ec69ffa679a81fbc7d4d47306edc4b57f2fa327f, - counter: 0x1690c7c85c57a4897623c1364852d8df91e4b36675085fddc7d10a7ea946fcbd, - }; - let unsent_felt: felt252 = 0x4b774418541bbe409a801463d95e65b16da2be518ae8c7647867dc57911cd3e; - let config = VectorCommitmentConfig { height: 15, n_verifier_friendly_commitment_layers: 5, }; - - let res = vector_commit(ref channel, unsent_felt, config); - - assert(res.config.height == config.height, 'invalid config height'); - assert( - res - .config - .n_verifier_friendly_commitment_layers == config - .n_verifier_friendly_commitment_layers, - 'invalid config n_veri...' - ); - assert( - res.commitment_hash == 0x4b774418541bbe409a801463d95e65b16da2be518ae8c7647867dc57911cd3e, - 'invalid commitment_hash' - ); -} - -#[test] -#[available_gas(9999999999)] -fn test_validate_vector_commitment() { - let config = VectorCommitmentConfig { height: 21, n_verifier_friendly_commitment_layers: 7, }; - validate_vector_commitment(config, 21, 7); -} - -#[test] -#[should_panic] -#[available_gas(9999999999)] -fn test_invalid_validate_vector_commitment_1() { - let config = VectorCommitmentConfig { height: 21, n_verifier_friendly_commitment_layers: 7, }; - validate_vector_commitment(config, 21, 8); -} - -#[test] -#[should_panic] -#[available_gas(9999999999)] -fn test_invalid_validate_vector_commitment_2() { - let config = VectorCommitmentConfig { height: 21, n_verifier_friendly_commitment_layers: 7, }; - validate_vector_commitment(config, 22, 7); -} - diff --git a/src/vector_commitment/tests/test_vector_commitment_big.cairo b/src/vector_commitment/tests/test_vector_commitment_big.cairo deleted file mode 100644 index 736cb1137..000000000 --- a/src/vector_commitment/tests/test_vector_commitment_big.cairo +++ /dev/null @@ -1,310 +0,0 @@ -use cairo_verifier::vector_commitment::vector_commitment::{ - VectorCommitment, VectorCommitmentConfig, VectorCommitmentWitness, vector_commit, VectorQuery, - vector_commitment_decommit, -}; - - -fn get_queries() -> Span { - array![ - VectorQuery { index: 8944, value: 1157029198022238202306346125123666191662554108005, }, - VectorQuery { index: 87688, value: 1156474867121067569936479332616669839586441580873, }, - VectorQuery { index: 102053, value: 525816285038390391761216558389282806925768838548, }, - VectorQuery { index: 245879, value: 107369622883479077497054209983678141110627796717, }, - VectorQuery { index: 256809, value: 949339871326160796951462878182560128992821726454, }, - VectorQuery { index: 392242, value: 1059124283686490920098445863728771935957073029275, }, - VectorQuery { index: 440172, value: 1004960524734674416414422271912833502843388467741, }, - VectorQuery { index: 548787, value: 411837609286176947519179656958589815774812246499, }, - VectorQuery { index: 577284, value: 1218039613838712880752380339674108515816375625719, }, - VectorQuery { index: 642763, value: 1265919886333784475948846562913903139069733976148, }, - VectorQuery { index: 756331, value: 896322243196765520299757197377168495469457128757, }, - VectorQuery { index: 864292, value: 1155461141686855272442638920387236548699741992582, }, - VectorQuery { index: 887991, value: 1022535991370990930332590451711848013554441682785, }, - VectorQuery { index: 918820, value: 224038758314235415917884799763993555998811070874, }, - VectorQuery { index: 931416, value: 505599032726154718331451347724946473511894248513 }, - ] - .span() -} - -fn get_invalid_queries() -> Span { - let queries = get_queries(); - let mut arr = ArrayTrait::new(); - let mut i = 0; - loop { - if i == queries.len() { - break; - }; - let q: VectorQuery = *queries[i]; - arr.append(if i == 2 { - VectorQuery { index: q.index + 1, value: q.value, } - } else { - q - }); - i += 1; - }; - arr.span() -} - -fn get_witness_authentications() -> Span { - array![ - 129252051435949032402481343903845417193011527432, - 1225462692330827760978713557642008436414090898865, - 67278565381239641413204827679887695736774949722, - 1078737717881769867930343257891164653408549478967, - 699890010136795418357117423249809483421135104011, - 1246725019495457082404930310201117186225574274808, - 723869797280768133619441460202235386787293092423, - 1065705212454360682518628382427562287270474022017, - 132595479574670041812174530172942470686780741377, - 115204718186786809942616812806473344950571253985, - 174494651288798776983066705991272364346692942282, - 1144214219004314557441377864651829949041601374916, - 1144737824385908743128900179556770453136927471451, - 1324666863329091299627640371062328029507747786540, - 400033442185649920227240137265193691762114243870, - 929556168503307423697654578587105824549232375013, - 992473586222458822718584294390418372763339729490, - 559508766994081021959582568425445270940875089230, - 1457966172391082807647461191887436468448874921400, - 374685932446416860702177528029688824704652771918, - 722140008860956153474204736531617486044303706374, - 337722875347521152970485245152695697802284782753, - 76010873097836317324289623471464500411232434976, - 1205000356605622625443139319902766366558189706253, - 584545402305080207884674795412779962516690190794, - 1336543663070328359671498017960496366794041172263, - 693772702025653592740778330593788799476134763712, - 728514340246547938323148150842723484958662012016, - 519290082616360949938148752793505475441002752559, - 723133633493102587412710472937948133597498575856, - 1064594489972968825305377979089126406275651298079, - 1105669943152283253809188893132668715196982163373, - 1363751346163822705338716284144513801543535110791, - 1057297862963634306346469733804130934824303341465, - 329515556736269120047004508929269543409035839509, - 707534049752829818810413527304084266658616754202, - 24288270301868464729682420275929446480331102786, - 782671616367791141347198864110968015447085454649, - 1254580574425156059392997420901602649329415091482, - 1296510118098249753084460724048516338336081050282, - 360571627435884760738632373190030414827040234533, - 1193425221860672995585627045122920131505237674141, - 348786223387419613557158061783235653279978947848, - 823666191489032333637271229518473814379136559039, - 711128794346109838057305189137235376064970826136, - 1370062945284145071679435202472879457653694193880, - 722456183315366327826272373833769146787730610278, - 617359116566433262570931811814803367549683886067, - 843830235568725219864882930311430450970601663237, - 20902789173392053554346178256678634898692112140, - 1201636521372336090888488633468602605854156932434, - 192989805897152073277086196053379203802028652254, - 819197352000746607897063819174399507135088334875, - 1254070248365975163268881700927356364512005819549, - 384485742925737075125558171189823184747260071086, - 52367179244203221219738608019365412864010027481, - 355749377817907287419711827423429250644463481353, - 556462634055986568951930230495067318823573975904, - 652573113028817052542488657684348382359884544171, - 1297524519052549338814385804924898853557210549673, - 1119477041597051138418307503938290828713707506878, - 72702646129902549080859047912684015619899878102, - 880477999432584191754007708087879409971034029809, - 470344519995489566393362986596849542039617088634, - 684367815563499819856823734114848372990903276818, - 243202486505099723505217908346744059990213806031, - 555158461664595942018039191221383691666789085975, - 11821397572682171073592171968267836059403285477, - 619894725331734721759533859158593593644862021185, - 262855523658555885607754663360657363558724961224, - 1072425736316177086559960552856261179995424533699, - 581270161438048957204998284798464679312993539517, - 897822880860424952726346927895244514718820459654, - 494307545242707451547796189203487595746355467677, - 1362369406220368591374616363651390231707015524461, - 414632574441094368895219437770710487412242005699, - 480391984031630003470886120991511843429033559267, - 981591297479551608148283560626656104501014183976, - 583810357920642441922979502163757550069375438807, - 328890686654810252803059723218673458123024427908, - 1289989029439735915845556245444697284021594326044, - 1035970154858362957604154189846632955281442804168, - 323862099416260717514677837171155202545986426739, - 328400785730367667700353867700436012248164215418, - 135979493245810259505341510765062807193460677870, - 627451456094834851497099056511096471948428859770, - 700502029106838281704343472764723785659333967360, - 334456027866086957698458106702961598594720783019, - 458222183623161850671638910941095636412077784501, - 1122137720889395761157893600901744324802698825148, - 1448764409069039053075809033686912216986000703620, - 792255386468970156876349310409036972519702788382, - 611622514578220212650015686510991357334332526321, - 454294461524589510165811621089261258920768019784, - 338962929308266778153157771712525964827399800101, - 748761032394372878784297012379906638073161690490, - 67628125700078984825365295529539097499567718163, - 1130572930870299079180028617397651346918457999528, - 36080049230420232748444406355506779098785421267, - 297066567052505225495646605125198281365448584715, - 1074733233798124869632086957466013346775458158729, - 1364192732241261257428316731256239569441832604629, - 553572555782828773582079845757316014562927917006, - 943677144889175241268947697461652480660135808659, - 1442133732367194601761291556072044665497375897957, - 885631862120018279012460204209072282711144267514, - 1214153597179838957778564081996949751351637853143, - 1156971759099790375749596762588431406564603700733, - 57961712361072929158851132227666858535966753634, - 1014329779829403275348224333384512404819084345901, - 1341664690376430445493358835494199379551678927701, - 605442995159995092435987140353799364620864655583, - 244963069037870328408775596183594382069195933547, - 1400155198527958333895054253805111597999975629367, - 624332706617608273153632596657422439473865601534, - 250919144290433127631168657728553838883440582737, - 634824650801749308336641619229378166697737796860, - 1104393496976264550357400420532446755641903530701, - 562712329257804497435794048438301848239136415934, - 782074013427887983360055140257980627808574391953, - 962700601453811244504860457783937155656563486920, - 1164662158087277506703451858867691608805608253506, - 935265576689394835412603753741471690588459521119, - 167995339264932845879715996451813459250169996292, - 1457426793976345543286858519555661542445206999549, - 495412880373689754890269927107806714589454807605, - 35551084423207969965136294758420222974320360446, - 265081110641874102231974635133317960851185639094, - 541529643057158500340012369575079949551707811165, - 47373574829345524358285805230537257424790876561, - 566131870544568345569835299882729231101558319779, - 1029466537649541674539162034986830724843815320725, - 427365786256311191924484728309890844547109563285, - 1226226420466297889665082427096593704282012124108, - 493566626241416811791461900365381280206488581453, - 680520796993477790639023445067952868375184548258, - 107319448305638554512601197083726162458187965398, - 1446100224265260954300104321471395398900386628445, - 1237608113258246846458822898650571580336723838781, - 1021482327712713685987289492874627808822335400968, - 1393323843220193697753702976061546584630768227320, - 1014413414982411627120026252713205467504785248817, - 913284896358370631207606541076467794279995623415, - 1279848522342588915039370726875009338435471000144, - 285179316197317608529554393165292906180537988899, - 137456060680944256102099804162791325640094818855, - 459587748134981387429216237606376184889621259070, - 1341627645769802971399130628674358421429505048682, - 263693299923159250970376076611522108796973595976, - 595448409134138005159968667003601742949411747614, - 1214022933768346447083260749895619486409350459877, - 418420131921148322781663281981292918187653509047, - 170986266479870242082981990102308241101272824496, - 664294101447237406297765887747124544839553733225, - 645638724081060418276140455560289946823823338694, - 225700651383829837113289180055919069685857718416, - 1274948884388164058800518139082374851303197491654, - 318544139260360034868538838966670017991820400918, - 493434433829387573243142398035312325738844543504, - 871562621546701190192746150765016511537421156902, - 1226144336800198064968872183011434243985881635637, - 933918616510628466904999025460544430068809059164, - 702347514591737542532453702017132423109845537884, - 1071273845827175552327342248791604080573046209535, - 1240817655838657777135854670018996744283012987140, - 875870204659290766842682491017828696152096574071, - 188093316895476935759161449048578340446272061868, - 1047368933218345554844031311793217887851890540215, - 318272618419464007910946656117605915607262707437, - 72348024748165956394988346572832307275179895132, - 696107273382489207132905531488953541031316047136, - 1153300963483156870549866289780302011025589910544, - 1213849092247398023832528007117429967152166744967, - 258731089257221728950612134332122567903177998599, - 1011094064269480402916938198977427236939615094114, - 395057475784029903970346736942716566679924813952, - 965304568859603254315481647975028967685575998547, - 1231260725384430048320357522266716443316707419375, - 1083476655088364771949473024534812164517340832950, - 219117598913375711779500502300211199073254282447, - 531781436976979080089627274084141126005951318884550194581019234109257825426, - 1984130212785264031690496591872617895170530808940282502615991056284599773675, - 624928039510714257128178481029069588172585192205434268492629304196634243142, - 2759109178751924651989509714451631067235754254158394695082619100422371625099, - 3616459225423243662539171717987414123046202991886322574915445418792219493783, - 250099987791792528719725414667427900089487397921101000923158573268468075600, - 1171977947792793907526898242047289872149964803492792810358548061030014390670, - 517940796285710800763503663124627034165719506616730903314697988135384762087, - 2978489716176670984999929826889034748132059545556091968874195299522479653503, - 3156901470139192515846232610466134547489304497987200744153272882088309247546, - 2271132343292181256363930817563559091272623111865558328139100299133447872037, - 2407603494502602086567737233993139100687851859455045058239611556483024198145, - 399946639682055340408654227351616438295685444024175637875412757126508623626, - 1239852395631881554222480630854261080352264710297721680011036013910922026362, - 3547396785177851334938120068496523245850817648583216503270948727685236008766, - 2291914496115720017778831031813270125598817515769022024603836296706663193056, - 1255651566965983475880702270607700495860973914832518677027627381741215471798, - 3162163812495127826880384877995715139171402263184442951467845605747727386880, - 1595510720607891065543083479453169604293414489813992941886580317431493476623, - 895648157989004382892671694585781073193150111911015114937061197222604883819, - 1690221331559299185495539482741039676594697421539958107668932286624822773560, - 171330745669863752368164172995966146372795881210659723206393907000336305782, - 2558634962282203112969743964216132555082308163009871618222973280267102103796, - 1854175805901945322816753803258506171085854477181413465333714860072134296452, - 2124983658823929096824064606711864064698711817311542448788186405078446042530, - 436568007905860808446023745844727311824794421693704653413316691028257762924, - 1790025259471642264118065531242296139945917841714368873412838204226147748176, - 3545450395333616493955819500282071940109389900146520397987942694625369946419, - 504572680146834543151760572155435772241191953237293646936403611588575344067, - 1453707733288359575113225984420369529431640589423469137665205461741215782019, - 1078442870290594540234064110441530217786343778702231032989504015825770502848, - 1762038109675393365384494673904143604736183814300514203509225129611803796841, - 3168343011425788357340908113385557674778513971005067669498918588637678048138, - 2800996729503490756008769747114586808778301049019558225168101664263801121317, - 1459128843780323772043992043417506140863339674679260953303495275076571081967, - 566425159096466240243194822864904174327967643619893905310523054847208824571, - 2485774431932381684984705469318832649861979267891693686077075736411281388345, - 2321332014555865517696908771400079038131685886977964532360949769016303733377, - 1202983991695884159509860739890480434476431248904228816889494280590746992095, - 3179534162109476342822054635774907146637020893465101234651958821782341008552, - 1554524506123275059219094199851800413779738441851310628268833464653437327266, - 1851375360642908260691827424401929317757606317916773610105833984603596857784, - 488612167967513385313989139180076046535526339112576789167163080246687213041, - 2664697130168323663000560790743737867624518566770128057504613939909582620632, - 440675098182478954229939270534923198966639529614537413200468710898911858275, - 1612429434502327404018012209215889219366444799607283044067236194357007723906, - 2193273363628533348290695232934416288392938919819363657667649966527822015016, - 1394754713887140095602355373328553645092278783149527895719471120429701764478, - 1075724842662989335468528908116802032030906667500613297221647595406068106876, - 1145720166361978830818985131684525612821849437881963152582648517987656170242, - 3011114029276924436505563433464520331248987625963149365139994455589348268051, - 1643293848324002295213462888260312636052214431402365640390341129728736785907, - ] - .span() -} - -#[test] -#[available_gas(9999999999)] -fn test_vector_commitment_decommit() { - let witness_authentications = get_witness_authentications(); - let commitment = VectorCommitment { - config: VectorCommitmentConfig { height: 20, n_verifier_friendly_commitment_layers: 9, }, - commitment_hash: 936159606372446880770773180413943646119933747687072192231671834696463400536 - }; - let witness = VectorCommitmentWitness { authentications: witness_authentications, }; - - vector_commitment_decommit(commitment, get_queries(), witness); -} - -#[test] -#[should_panic] -#[available_gas(9999999999)] -fn test_invalid_vector_commitment_decommit() { - let witness_authentications = get_witness_authentications(); - let commitment = VectorCommitment { - config: VectorCommitmentConfig { height: 20, n_verifier_friendly_commitment_layers: 9, }, - commitment_hash: 936159606372446880770773180413943646119933747687072192231671834696463400536 - }; - let witness = VectorCommitmentWitness { authentications: witness_authentications, }; - - vector_commitment_decommit(commitment, get_invalid_queries(), witness); -} diff --git a/src/vector_commitment/vector_commitment.cairo b/src/vector_commitment/vector_commitment.cairo deleted file mode 100644 index 255cc3e38..000000000 --- a/src/vector_commitment/vector_commitment.cairo +++ /dev/null @@ -1,162 +0,0 @@ -use cairo_verifier::common::{ - array_append::ArrayAppendTrait, blake2s::blake2s, math::pow, blake2s::truncated_blake2s, - flip_endianness::FlipEndiannessTrait, math::DivRemFelt252, math::Felt252PartialOrd -}; -use cairo_verifier::channel::channel::{Channel, ChannelImpl}; -use poseidon::hades_permutation; - -// Commitment for a vector of field elements. -#[derive(Drop, Copy)] -struct VectorCommitment { - config: VectorCommitmentConfig, - commitment_hash: felt252 -} - -#[derive(Drop, Copy)] -struct VectorCommitmentConfig { - height: felt252, - n_verifier_friendly_commitment_layers: felt252, -} - -// A query to the vector commitment. -#[derive(Drop, Copy)] -struct VectorQuery { - index: felt252, - value: felt252, -} - -// A query to the vector commitment that contains also the depth of the query in the Merkle tree. -#[derive(Drop, Copy)] -struct VectorQueryWithDepth { - index: felt252, - value: felt252, - depth: felt252, -} - -// Witness for a decommitment over queries. -#[derive(Drop, Copy)] -struct VectorCommitmentWitness { - // The authentication values: all the siblings of the subtree generated by the queried indices, - // bottom layer up, left to right. - authentications: Span, -} - -fn validate_vector_commitment( - config: VectorCommitmentConfig, - expected_height: felt252, - n_verifier_friendly_commitment_layers: felt252, -) { - assert(config.height == expected_height, 'height mismatch'); - // Note that n_verifier_friendly_commitment_layers can be greater than height (in such a case, - // all Merkle layers use the verifier-friendly hash). - assert( - config.n_verifier_friendly_commitment_layers == n_verifier_friendly_commitment_layers, - 'n_verifier_friendly... mismatch' - ); -} - -fn vector_commit( - ref channel: Channel, unsent_commitment: felt252, config: VectorCommitmentConfig -) -> VectorCommitment { - channel.read_felt_from_prover(unsent_commitment); // commitment is being sent - VectorCommitment { config: config, commitment_hash: unsent_commitment, } -} - -// Decommits a VectorCommitment at multiple indices. -// Indices must be sorted and unique. -fn vector_commitment_decommit( - commitment: VectorCommitment, queries: Span, witness: VectorCommitmentWitness, -) { - let shift = pow(2, commitment.config.height); - let shifted_queries = shift_queries(queries, shift, commitment.config.height); - - let expected_commitment = compute_root_from_queries( - shifted_queries, - 0, - commitment.config.n_verifier_friendly_commitment_layers, - witness.authentications, - 0 - ); - - assert(expected_commitment == commitment.commitment_hash, 'decommitment failed'); -} - -// Verifies a queue of Merkle queries. [queue_head, queue_tail) is a queue, where each element -// represents a node index (given in a heap-like indexing) and value (either an inner -// node or a leaf). -fn compute_root_from_queries( - mut queue: Array, - start: u32, - n_verifier_friendly_layers: felt252, - authentications: Span, - auth_start: u32 -) -> felt252 { - let current: VectorQueryWithDepth = *queue[start]; - - if current.index == 1 { // root - assert(current.depth == 0, 'root depth must be 0'); - assert(start + 1 == queue.len(), 'root must be the last element'); - assert(auth_start == authentications.len(), 'authentications is too long'); - return current.value; - } - - let (parent, bit) = DivRem::div_rem(current.index, 2.try_into().unwrap()); - let is_verifier_friendly = n_verifier_friendly_layers >= current.depth; - let hash = if bit == 0 { - if start + 1 != queue.len() { - let next: VectorQueryWithDepth = *queue[start + 1]; - if current.index + 1 == next.index { - // next is a sibling of current - let hash = hash_blake_or_poseidon(current.value, next.value, is_verifier_friendly); - queue - .append( - VectorQueryWithDepth { - index: parent, value: hash, depth: current.depth - 1, - } - ); - return compute_root_from_queries( - queue, start + 2, n_verifier_friendly_layers, authentications, auth_start - ); - } - } - assert(auth_start != authentications.len(), 'authentications is too short'); - hash_blake_or_poseidon(current.value, *authentications[auth_start], is_verifier_friendly) - } else { - assert(auth_start != authentications.len(), 'authentications is too short'); - hash_blake_or_poseidon(*authentications[auth_start], current.value, is_verifier_friendly) - }; - queue.append(VectorQueryWithDepth { index: parent, value: hash, depth: current.depth - 1, }); - compute_root_from_queries( - queue, start + 1, n_verifier_friendly_layers, authentications, auth_start + 1 - ) -} - -// Shifts the query indices by shift=2**height, to convert index representation to heap-like. -// Validates the query index range. -fn shift_queries( - queries: Span, shift: felt252, height: felt252 -) -> Array { - let mut shifted_queries = ArrayTrait::new(); - let mut i = 0; - loop { - if i == queries.len() { - break; - }; - let q = *queries[i]; - shifted_queries - .append( - VectorQueryWithDepth { index: q.index + shift, value: q.value, depth: height, } - ); - i += 1; - }; - shifted_queries -} - -fn hash_blake_or_poseidon(x: felt252, y: felt252, is_verifier_friendly: bool) -> felt252 { - if is_verifier_friendly { - let (hash, _, _) = hades_permutation(x, y, 2); - hash - } else { - truncated_blake2s(x, y) - } -} From f732f82db5dedf7cb3505cf25210cf4c56ae77dc Mon Sep 17 00:00:00 2001 From: Bartosz Nowak Date: Sat, 6 Jan 2024 16:31:38 +0100 Subject: [PATCH 03/12] Revert "function skaffold" This reverts commit a33d6412e8ece22ba08f6552a5e1daa48cfc86b0. --- src/proof_of_work/proof_of_work.cairo | 86 ++--- src/proof_of_work/tests.cairo | 1 - .../tests/test_proof_of_work.cairo | 12 - src/vector_commitment/tests.cairo | 6 + .../tests/test_vector_commitment.cairo | 55 ++++ .../tests/test_vector_commitment_big.cairo | 310 ++++++++++++++++++ src/vector_commitment/vector_commitment.cairo | 162 +++++++++ 7 files changed, 565 insertions(+), 67 deletions(-) delete mode 100644 src/proof_of_work/tests/test_proof_of_work.cairo create mode 100644 src/vector_commitment/tests.cairo create mode 100644 src/vector_commitment/tests/test_vector_commitment.cairo create mode 100644 src/vector_commitment/tests/test_vector_commitment_big.cairo create mode 100644 src/vector_commitment/vector_commitment.cairo diff --git a/src/proof_of_work/proof_of_work.cairo b/src/proof_of_work/proof_of_work.cairo index 3bda3a0a2..b1363cd32 100644 --- a/src/proof_of_work/proof_of_work.cairo +++ b/src/proof_of_work/proof_of_work.cairo @@ -1,17 +1,8 @@ -use core::array::SpanTrait; -use core::array::ArrayTrait; -use cairo_verifier::common::flip_endianness::FlipEndiannessTrait; -use core::debug::PrintTrait; use cairo_verifier::{ common::{blake2s::blake2s, array_append::ArrayAppendTrait, math::pow}, channel::channel::{Channel, ChannelTrait}, proof_of_work::config::{ProofOfWorkConfig, BYTE_UPPER_BOUND, WORD_UPPER_BOUND} }; -use cairo_verifier::common::array_print::{SpanPrintTrait, ArrayPrintTrait}; - -const POW_2_12: u256 = 79228162514264337593543950336; -const POW_2_4: u256 = 4294967296; -const POW_2_3: u256 = 16777216; #[derive(Drop, Copy)] struct ProofOfWorkUnsentCommitment { @@ -27,49 +18,36 @@ fn proof_of_work_commit( fn verify_proof_of_work(digest: u256, n_bits: u8, nonce: u64) { // Compute the initial hash. - // Hash(0123456789abcded || digest || n_bits ) - // 8 bytes || 32 bytes || 1 byte - // Total of 0x29 = 41 bytes. - - // let init_hash_value: u256 = 0x0123456789abcded000000000000000000000000000000000000000000000000 - // // digest >> 12 -> digest << 4 -> nbits << 3 - // + digest / POW_2_12 * POW_2_4 + n_bits.into() * POW_2_3; - - let mut init_hash_data = ArrayTrait::::new(); - init_hash_data.append_big_endian(u256{low: 0xD7CA1D48A19D8FF802A71D94169DE383, high: 0x0123456789ABCDED1C5A5F4381DF1F5C}); - init_hash_data.append_big_endian(u256{low: 0x00000000000000000000000000000000, high: 0x82621FDC5514A10A1400000000000000}); - let span = init_hash_data.span().slice(0,41); - let mut arr = ArrayTrait::::new(); - let mut i:u32 = 0; - loop { - if i == span.len() { - break; - } - - arr.append(*span.at(i)); - i+=1; - }; - let init_hash = blake2s(arr).flip_endianness(); - init_hash.print(); - - // correct hash on test data: - // 0x6ae49da749fbe3fc98f114c0f8342a4d - // 0x26438c9c119a3b222f70d564d5df2ebc - - // // Compute Hash(init_hash || nonce ) - // // 32 bytes || 8 bytes - // // Total of 0x28 = 40 bytes. - - // // init_hash >> 12 -> init_hash << 8 + 4 -> nonce << 4 - // let hash_value: u256 = init_hash / POW_2_12 * POW_2_12 + nonce.into() * POW_2_4; - - // let mut hash_data = ArrayTrait::::new(); - // hash_data.append_big_endian(hash_value); - // let hash = blake2s(hash_data); - // let work_limit = pow(2, 128 - n_bits.into()); - - // assert( - // Into::::into(hash.high) < Into::::into(work_limit), - // 'proof of work failed' - // ) + // Hash(0123456789abcded || digest || n_bits) + // 8 bytes || 0x20 bytes || 1 byte + // Total of 0x29 bytes. + // Arrange the hash input according to the keccak requirement of 0x10 byte chunks. + let init_hash_value: u256 = 0x0123456789abcded000000000000000000000000000000000000000000000000 + // digest >> 12 -> digest << 4 + + digest / 79228162514264337593543950336 * 4294967296 + // nbits << 3 + + n_bits.into() * 16777216; + + let mut init_hash_data = ArrayTrait::::new(); + init_hash_data.append_big_endian(init_hash_value); + let init_hash = blake2s(init_hash_data); + + // Compute Hash(init_hash || nonce ) + // 0x20 bytes || 8 bytes + // Total of 0x28 bytes. + + // init_hash >> 12 -> init_hash << 8 + 4 + let hash_value: u256 = init_hash / 79228162514264337593543950336 * 79228162514264337593543950336 + // nonce << 4 + + nonce.into() * 4294967296; + + let mut hash_data = ArrayTrait::::new(); + hash_data.append_big_endian(hash_value); + let hash = blake2s(hash_data); + let work_limit = pow(2, 128 - n_bits.into()); + + assert( + Into::::into(hash.high) < Into::::into(work_limit), + 'proof of work failed' + ) } diff --git a/src/proof_of_work/tests.cairo b/src/proof_of_work/tests.cairo index 1164558f8..e69de29bb 100644 --- a/src/proof_of_work/tests.cairo +++ b/src/proof_of_work/tests.cairo @@ -1 +0,0 @@ -mod test_proof_of_work; \ No newline at end of file diff --git a/src/proof_of_work/tests/test_proof_of_work.cairo b/src/proof_of_work/tests/test_proof_of_work.cairo deleted file mode 100644 index 0f183537a..000000000 --- a/src/proof_of_work/tests/test_proof_of_work.cairo +++ /dev/null @@ -1,12 +0,0 @@ -use cairo_verifier::proof_of_work::proof_of_work::verify_proof_of_work; - -// 142085208829254859155982631899283860045, 50861399631734199073966002375401352892 - -#[test] -#[available_gas(9999999999)] -fn test_proof_of_work_0() { - let digest: u256 = 0x1C5A5F4381DF1F5CD7CA1D48A19D8FF802A71D94169DE38382621FDC5514A10A; - let nonce: u64 = 0x1683B; - let n_bits: u8 = 20; - verify_proof_of_work(digest, n_bits, nonce); -} \ No newline at end of file diff --git a/src/vector_commitment/tests.cairo b/src/vector_commitment/tests.cairo new file mode 100644 index 000000000..81a308fb7 --- /dev/null +++ b/src/vector_commitment/tests.cairo @@ -0,0 +1,6 @@ +mod test_vector_commitment; +// notice: this test takes a lot of time and computation +// uncomment it when making changes to vector_commitment_decommit +// mod test_vector_commitment_big; + + diff --git a/src/vector_commitment/tests/test_vector_commitment.cairo b/src/vector_commitment/tests/test_vector_commitment.cairo new file mode 100644 index 000000000..e0d7d34d2 --- /dev/null +++ b/src/vector_commitment/tests/test_vector_commitment.cairo @@ -0,0 +1,55 @@ +use cairo_verifier::vector_commitment::vector_commitment::{ + VectorCommitment, VectorCommitmentConfig, vector_commit, validate_vector_commitment +}; +use cairo_verifier::channel::channel::Channel; + + +#[test] +#[available_gas(9999999999)] +fn test_vector_commit() { + let mut channel = Channel { + digest: 0x0f089f70240c88c355168624ec69ffa679a81fbc7d4d47306edc4b57f2fa327f, + counter: 0x1690c7c85c57a4897623c1364852d8df91e4b36675085fddc7d10a7ea946fcbd, + }; + let unsent_felt: felt252 = 0x4b774418541bbe409a801463d95e65b16da2be518ae8c7647867dc57911cd3e; + let config = VectorCommitmentConfig { height: 15, n_verifier_friendly_commitment_layers: 5, }; + + let res = vector_commit(ref channel, unsent_felt, config); + + assert(res.config.height == config.height, 'invalid config height'); + assert( + res + .config + .n_verifier_friendly_commitment_layers == config + .n_verifier_friendly_commitment_layers, + 'invalid config n_veri...' + ); + assert( + res.commitment_hash == 0x4b774418541bbe409a801463d95e65b16da2be518ae8c7647867dc57911cd3e, + 'invalid commitment_hash' + ); +} + +#[test] +#[available_gas(9999999999)] +fn test_validate_vector_commitment() { + let config = VectorCommitmentConfig { height: 21, n_verifier_friendly_commitment_layers: 7, }; + validate_vector_commitment(config, 21, 7); +} + +#[test] +#[should_panic] +#[available_gas(9999999999)] +fn test_invalid_validate_vector_commitment_1() { + let config = VectorCommitmentConfig { height: 21, n_verifier_friendly_commitment_layers: 7, }; + validate_vector_commitment(config, 21, 8); +} + +#[test] +#[should_panic] +#[available_gas(9999999999)] +fn test_invalid_validate_vector_commitment_2() { + let config = VectorCommitmentConfig { height: 21, n_verifier_friendly_commitment_layers: 7, }; + validate_vector_commitment(config, 22, 7); +} + diff --git a/src/vector_commitment/tests/test_vector_commitment_big.cairo b/src/vector_commitment/tests/test_vector_commitment_big.cairo new file mode 100644 index 000000000..736cb1137 --- /dev/null +++ b/src/vector_commitment/tests/test_vector_commitment_big.cairo @@ -0,0 +1,310 @@ +use cairo_verifier::vector_commitment::vector_commitment::{ + VectorCommitment, VectorCommitmentConfig, VectorCommitmentWitness, vector_commit, VectorQuery, + vector_commitment_decommit, +}; + + +fn get_queries() -> Span { + array![ + VectorQuery { index: 8944, value: 1157029198022238202306346125123666191662554108005, }, + VectorQuery { index: 87688, value: 1156474867121067569936479332616669839586441580873, }, + VectorQuery { index: 102053, value: 525816285038390391761216558389282806925768838548, }, + VectorQuery { index: 245879, value: 107369622883479077497054209983678141110627796717, }, + VectorQuery { index: 256809, value: 949339871326160796951462878182560128992821726454, }, + VectorQuery { index: 392242, value: 1059124283686490920098445863728771935957073029275, }, + VectorQuery { index: 440172, value: 1004960524734674416414422271912833502843388467741, }, + VectorQuery { index: 548787, value: 411837609286176947519179656958589815774812246499, }, + VectorQuery { index: 577284, value: 1218039613838712880752380339674108515816375625719, }, + VectorQuery { index: 642763, value: 1265919886333784475948846562913903139069733976148, }, + VectorQuery { index: 756331, value: 896322243196765520299757197377168495469457128757, }, + VectorQuery { index: 864292, value: 1155461141686855272442638920387236548699741992582, }, + VectorQuery { index: 887991, value: 1022535991370990930332590451711848013554441682785, }, + VectorQuery { index: 918820, value: 224038758314235415917884799763993555998811070874, }, + VectorQuery { index: 931416, value: 505599032726154718331451347724946473511894248513 }, + ] + .span() +} + +fn get_invalid_queries() -> Span { + let queries = get_queries(); + let mut arr = ArrayTrait::new(); + let mut i = 0; + loop { + if i == queries.len() { + break; + }; + let q: VectorQuery = *queries[i]; + arr.append(if i == 2 { + VectorQuery { index: q.index + 1, value: q.value, } + } else { + q + }); + i += 1; + }; + arr.span() +} + +fn get_witness_authentications() -> Span { + array![ + 129252051435949032402481343903845417193011527432, + 1225462692330827760978713557642008436414090898865, + 67278565381239641413204827679887695736774949722, + 1078737717881769867930343257891164653408549478967, + 699890010136795418357117423249809483421135104011, + 1246725019495457082404930310201117186225574274808, + 723869797280768133619441460202235386787293092423, + 1065705212454360682518628382427562287270474022017, + 132595479574670041812174530172942470686780741377, + 115204718186786809942616812806473344950571253985, + 174494651288798776983066705991272364346692942282, + 1144214219004314557441377864651829949041601374916, + 1144737824385908743128900179556770453136927471451, + 1324666863329091299627640371062328029507747786540, + 400033442185649920227240137265193691762114243870, + 929556168503307423697654578587105824549232375013, + 992473586222458822718584294390418372763339729490, + 559508766994081021959582568425445270940875089230, + 1457966172391082807647461191887436468448874921400, + 374685932446416860702177528029688824704652771918, + 722140008860956153474204736531617486044303706374, + 337722875347521152970485245152695697802284782753, + 76010873097836317324289623471464500411232434976, + 1205000356605622625443139319902766366558189706253, + 584545402305080207884674795412779962516690190794, + 1336543663070328359671498017960496366794041172263, + 693772702025653592740778330593788799476134763712, + 728514340246547938323148150842723484958662012016, + 519290082616360949938148752793505475441002752559, + 723133633493102587412710472937948133597498575856, + 1064594489972968825305377979089126406275651298079, + 1105669943152283253809188893132668715196982163373, + 1363751346163822705338716284144513801543535110791, + 1057297862963634306346469733804130934824303341465, + 329515556736269120047004508929269543409035839509, + 707534049752829818810413527304084266658616754202, + 24288270301868464729682420275929446480331102786, + 782671616367791141347198864110968015447085454649, + 1254580574425156059392997420901602649329415091482, + 1296510118098249753084460724048516338336081050282, + 360571627435884760738632373190030414827040234533, + 1193425221860672995585627045122920131505237674141, + 348786223387419613557158061783235653279978947848, + 823666191489032333637271229518473814379136559039, + 711128794346109838057305189137235376064970826136, + 1370062945284145071679435202472879457653694193880, + 722456183315366327826272373833769146787730610278, + 617359116566433262570931811814803367549683886067, + 843830235568725219864882930311430450970601663237, + 20902789173392053554346178256678634898692112140, + 1201636521372336090888488633468602605854156932434, + 192989805897152073277086196053379203802028652254, + 819197352000746607897063819174399507135088334875, + 1254070248365975163268881700927356364512005819549, + 384485742925737075125558171189823184747260071086, + 52367179244203221219738608019365412864010027481, + 355749377817907287419711827423429250644463481353, + 556462634055986568951930230495067318823573975904, + 652573113028817052542488657684348382359884544171, + 1297524519052549338814385804924898853557210549673, + 1119477041597051138418307503938290828713707506878, + 72702646129902549080859047912684015619899878102, + 880477999432584191754007708087879409971034029809, + 470344519995489566393362986596849542039617088634, + 684367815563499819856823734114848372990903276818, + 243202486505099723505217908346744059990213806031, + 555158461664595942018039191221383691666789085975, + 11821397572682171073592171968267836059403285477, + 619894725331734721759533859158593593644862021185, + 262855523658555885607754663360657363558724961224, + 1072425736316177086559960552856261179995424533699, + 581270161438048957204998284798464679312993539517, + 897822880860424952726346927895244514718820459654, + 494307545242707451547796189203487595746355467677, + 1362369406220368591374616363651390231707015524461, + 414632574441094368895219437770710487412242005699, + 480391984031630003470886120991511843429033559267, + 981591297479551608148283560626656104501014183976, + 583810357920642441922979502163757550069375438807, + 328890686654810252803059723218673458123024427908, + 1289989029439735915845556245444697284021594326044, + 1035970154858362957604154189846632955281442804168, + 323862099416260717514677837171155202545986426739, + 328400785730367667700353867700436012248164215418, + 135979493245810259505341510765062807193460677870, + 627451456094834851497099056511096471948428859770, + 700502029106838281704343472764723785659333967360, + 334456027866086957698458106702961598594720783019, + 458222183623161850671638910941095636412077784501, + 1122137720889395761157893600901744324802698825148, + 1448764409069039053075809033686912216986000703620, + 792255386468970156876349310409036972519702788382, + 611622514578220212650015686510991357334332526321, + 454294461524589510165811621089261258920768019784, + 338962929308266778153157771712525964827399800101, + 748761032394372878784297012379906638073161690490, + 67628125700078984825365295529539097499567718163, + 1130572930870299079180028617397651346918457999528, + 36080049230420232748444406355506779098785421267, + 297066567052505225495646605125198281365448584715, + 1074733233798124869632086957466013346775458158729, + 1364192732241261257428316731256239569441832604629, + 553572555782828773582079845757316014562927917006, + 943677144889175241268947697461652480660135808659, + 1442133732367194601761291556072044665497375897957, + 885631862120018279012460204209072282711144267514, + 1214153597179838957778564081996949751351637853143, + 1156971759099790375749596762588431406564603700733, + 57961712361072929158851132227666858535966753634, + 1014329779829403275348224333384512404819084345901, + 1341664690376430445493358835494199379551678927701, + 605442995159995092435987140353799364620864655583, + 244963069037870328408775596183594382069195933547, + 1400155198527958333895054253805111597999975629367, + 624332706617608273153632596657422439473865601534, + 250919144290433127631168657728553838883440582737, + 634824650801749308336641619229378166697737796860, + 1104393496976264550357400420532446755641903530701, + 562712329257804497435794048438301848239136415934, + 782074013427887983360055140257980627808574391953, + 962700601453811244504860457783937155656563486920, + 1164662158087277506703451858867691608805608253506, + 935265576689394835412603753741471690588459521119, + 167995339264932845879715996451813459250169996292, + 1457426793976345543286858519555661542445206999549, + 495412880373689754890269927107806714589454807605, + 35551084423207969965136294758420222974320360446, + 265081110641874102231974635133317960851185639094, + 541529643057158500340012369575079949551707811165, + 47373574829345524358285805230537257424790876561, + 566131870544568345569835299882729231101558319779, + 1029466537649541674539162034986830724843815320725, + 427365786256311191924484728309890844547109563285, + 1226226420466297889665082427096593704282012124108, + 493566626241416811791461900365381280206488581453, + 680520796993477790639023445067952868375184548258, + 107319448305638554512601197083726162458187965398, + 1446100224265260954300104321471395398900386628445, + 1237608113258246846458822898650571580336723838781, + 1021482327712713685987289492874627808822335400968, + 1393323843220193697753702976061546584630768227320, + 1014413414982411627120026252713205467504785248817, + 913284896358370631207606541076467794279995623415, + 1279848522342588915039370726875009338435471000144, + 285179316197317608529554393165292906180537988899, + 137456060680944256102099804162791325640094818855, + 459587748134981387429216237606376184889621259070, + 1341627645769802971399130628674358421429505048682, + 263693299923159250970376076611522108796973595976, + 595448409134138005159968667003601742949411747614, + 1214022933768346447083260749895619486409350459877, + 418420131921148322781663281981292918187653509047, + 170986266479870242082981990102308241101272824496, + 664294101447237406297765887747124544839553733225, + 645638724081060418276140455560289946823823338694, + 225700651383829837113289180055919069685857718416, + 1274948884388164058800518139082374851303197491654, + 318544139260360034868538838966670017991820400918, + 493434433829387573243142398035312325738844543504, + 871562621546701190192746150765016511537421156902, + 1226144336800198064968872183011434243985881635637, + 933918616510628466904999025460544430068809059164, + 702347514591737542532453702017132423109845537884, + 1071273845827175552327342248791604080573046209535, + 1240817655838657777135854670018996744283012987140, + 875870204659290766842682491017828696152096574071, + 188093316895476935759161449048578340446272061868, + 1047368933218345554844031311793217887851890540215, + 318272618419464007910946656117605915607262707437, + 72348024748165956394988346572832307275179895132, + 696107273382489207132905531488953541031316047136, + 1153300963483156870549866289780302011025589910544, + 1213849092247398023832528007117429967152166744967, + 258731089257221728950612134332122567903177998599, + 1011094064269480402916938198977427236939615094114, + 395057475784029903970346736942716566679924813952, + 965304568859603254315481647975028967685575998547, + 1231260725384430048320357522266716443316707419375, + 1083476655088364771949473024534812164517340832950, + 219117598913375711779500502300211199073254282447, + 531781436976979080089627274084141126005951318884550194581019234109257825426, + 1984130212785264031690496591872617895170530808940282502615991056284599773675, + 624928039510714257128178481029069588172585192205434268492629304196634243142, + 2759109178751924651989509714451631067235754254158394695082619100422371625099, + 3616459225423243662539171717987414123046202991886322574915445418792219493783, + 250099987791792528719725414667427900089487397921101000923158573268468075600, + 1171977947792793907526898242047289872149964803492792810358548061030014390670, + 517940796285710800763503663124627034165719506616730903314697988135384762087, + 2978489716176670984999929826889034748132059545556091968874195299522479653503, + 3156901470139192515846232610466134547489304497987200744153272882088309247546, + 2271132343292181256363930817563559091272623111865558328139100299133447872037, + 2407603494502602086567737233993139100687851859455045058239611556483024198145, + 399946639682055340408654227351616438295685444024175637875412757126508623626, + 1239852395631881554222480630854261080352264710297721680011036013910922026362, + 3547396785177851334938120068496523245850817648583216503270948727685236008766, + 2291914496115720017778831031813270125598817515769022024603836296706663193056, + 1255651566965983475880702270607700495860973914832518677027627381741215471798, + 3162163812495127826880384877995715139171402263184442951467845605747727386880, + 1595510720607891065543083479453169604293414489813992941886580317431493476623, + 895648157989004382892671694585781073193150111911015114937061197222604883819, + 1690221331559299185495539482741039676594697421539958107668932286624822773560, + 171330745669863752368164172995966146372795881210659723206393907000336305782, + 2558634962282203112969743964216132555082308163009871618222973280267102103796, + 1854175805901945322816753803258506171085854477181413465333714860072134296452, + 2124983658823929096824064606711864064698711817311542448788186405078446042530, + 436568007905860808446023745844727311824794421693704653413316691028257762924, + 1790025259471642264118065531242296139945917841714368873412838204226147748176, + 3545450395333616493955819500282071940109389900146520397987942694625369946419, + 504572680146834543151760572155435772241191953237293646936403611588575344067, + 1453707733288359575113225984420369529431640589423469137665205461741215782019, + 1078442870290594540234064110441530217786343778702231032989504015825770502848, + 1762038109675393365384494673904143604736183814300514203509225129611803796841, + 3168343011425788357340908113385557674778513971005067669498918588637678048138, + 2800996729503490756008769747114586808778301049019558225168101664263801121317, + 1459128843780323772043992043417506140863339674679260953303495275076571081967, + 566425159096466240243194822864904174327967643619893905310523054847208824571, + 2485774431932381684984705469318832649861979267891693686077075736411281388345, + 2321332014555865517696908771400079038131685886977964532360949769016303733377, + 1202983991695884159509860739890480434476431248904228816889494280590746992095, + 3179534162109476342822054635774907146637020893465101234651958821782341008552, + 1554524506123275059219094199851800413779738441851310628268833464653437327266, + 1851375360642908260691827424401929317757606317916773610105833984603596857784, + 488612167967513385313989139180076046535526339112576789167163080246687213041, + 2664697130168323663000560790743737867624518566770128057504613939909582620632, + 440675098182478954229939270534923198966639529614537413200468710898911858275, + 1612429434502327404018012209215889219366444799607283044067236194357007723906, + 2193273363628533348290695232934416288392938919819363657667649966527822015016, + 1394754713887140095602355373328553645092278783149527895719471120429701764478, + 1075724842662989335468528908116802032030906667500613297221647595406068106876, + 1145720166361978830818985131684525612821849437881963152582648517987656170242, + 3011114029276924436505563433464520331248987625963149365139994455589348268051, + 1643293848324002295213462888260312636052214431402365640390341129728736785907, + ] + .span() +} + +#[test] +#[available_gas(9999999999)] +fn test_vector_commitment_decommit() { + let witness_authentications = get_witness_authentications(); + let commitment = VectorCommitment { + config: VectorCommitmentConfig { height: 20, n_verifier_friendly_commitment_layers: 9, }, + commitment_hash: 936159606372446880770773180413943646119933747687072192231671834696463400536 + }; + let witness = VectorCommitmentWitness { authentications: witness_authentications, }; + + vector_commitment_decommit(commitment, get_queries(), witness); +} + +#[test] +#[should_panic] +#[available_gas(9999999999)] +fn test_invalid_vector_commitment_decommit() { + let witness_authentications = get_witness_authentications(); + let commitment = VectorCommitment { + config: VectorCommitmentConfig { height: 20, n_verifier_friendly_commitment_layers: 9, }, + commitment_hash: 936159606372446880770773180413943646119933747687072192231671834696463400536 + }; + let witness = VectorCommitmentWitness { authentications: witness_authentications, }; + + vector_commitment_decommit(commitment, get_invalid_queries(), witness); +} diff --git a/src/vector_commitment/vector_commitment.cairo b/src/vector_commitment/vector_commitment.cairo new file mode 100644 index 000000000..255cc3e38 --- /dev/null +++ b/src/vector_commitment/vector_commitment.cairo @@ -0,0 +1,162 @@ +use cairo_verifier::common::{ + array_append::ArrayAppendTrait, blake2s::blake2s, math::pow, blake2s::truncated_blake2s, + flip_endianness::FlipEndiannessTrait, math::DivRemFelt252, math::Felt252PartialOrd +}; +use cairo_verifier::channel::channel::{Channel, ChannelImpl}; +use poseidon::hades_permutation; + +// Commitment for a vector of field elements. +#[derive(Drop, Copy)] +struct VectorCommitment { + config: VectorCommitmentConfig, + commitment_hash: felt252 +} + +#[derive(Drop, Copy)] +struct VectorCommitmentConfig { + height: felt252, + n_verifier_friendly_commitment_layers: felt252, +} + +// A query to the vector commitment. +#[derive(Drop, Copy)] +struct VectorQuery { + index: felt252, + value: felt252, +} + +// A query to the vector commitment that contains also the depth of the query in the Merkle tree. +#[derive(Drop, Copy)] +struct VectorQueryWithDepth { + index: felt252, + value: felt252, + depth: felt252, +} + +// Witness for a decommitment over queries. +#[derive(Drop, Copy)] +struct VectorCommitmentWitness { + // The authentication values: all the siblings of the subtree generated by the queried indices, + // bottom layer up, left to right. + authentications: Span, +} + +fn validate_vector_commitment( + config: VectorCommitmentConfig, + expected_height: felt252, + n_verifier_friendly_commitment_layers: felt252, +) { + assert(config.height == expected_height, 'height mismatch'); + // Note that n_verifier_friendly_commitment_layers can be greater than height (in such a case, + // all Merkle layers use the verifier-friendly hash). + assert( + config.n_verifier_friendly_commitment_layers == n_verifier_friendly_commitment_layers, + 'n_verifier_friendly... mismatch' + ); +} + +fn vector_commit( + ref channel: Channel, unsent_commitment: felt252, config: VectorCommitmentConfig +) -> VectorCommitment { + channel.read_felt_from_prover(unsent_commitment); // commitment is being sent + VectorCommitment { config: config, commitment_hash: unsent_commitment, } +} + +// Decommits a VectorCommitment at multiple indices. +// Indices must be sorted and unique. +fn vector_commitment_decommit( + commitment: VectorCommitment, queries: Span, witness: VectorCommitmentWitness, +) { + let shift = pow(2, commitment.config.height); + let shifted_queries = shift_queries(queries, shift, commitment.config.height); + + let expected_commitment = compute_root_from_queries( + shifted_queries, + 0, + commitment.config.n_verifier_friendly_commitment_layers, + witness.authentications, + 0 + ); + + assert(expected_commitment == commitment.commitment_hash, 'decommitment failed'); +} + +// Verifies a queue of Merkle queries. [queue_head, queue_tail) is a queue, where each element +// represents a node index (given in a heap-like indexing) and value (either an inner +// node or a leaf). +fn compute_root_from_queries( + mut queue: Array, + start: u32, + n_verifier_friendly_layers: felt252, + authentications: Span, + auth_start: u32 +) -> felt252 { + let current: VectorQueryWithDepth = *queue[start]; + + if current.index == 1 { // root + assert(current.depth == 0, 'root depth must be 0'); + assert(start + 1 == queue.len(), 'root must be the last element'); + assert(auth_start == authentications.len(), 'authentications is too long'); + return current.value; + } + + let (parent, bit) = DivRem::div_rem(current.index, 2.try_into().unwrap()); + let is_verifier_friendly = n_verifier_friendly_layers >= current.depth; + let hash = if bit == 0 { + if start + 1 != queue.len() { + let next: VectorQueryWithDepth = *queue[start + 1]; + if current.index + 1 == next.index { + // next is a sibling of current + let hash = hash_blake_or_poseidon(current.value, next.value, is_verifier_friendly); + queue + .append( + VectorQueryWithDepth { + index: parent, value: hash, depth: current.depth - 1, + } + ); + return compute_root_from_queries( + queue, start + 2, n_verifier_friendly_layers, authentications, auth_start + ); + } + } + assert(auth_start != authentications.len(), 'authentications is too short'); + hash_blake_or_poseidon(current.value, *authentications[auth_start], is_verifier_friendly) + } else { + assert(auth_start != authentications.len(), 'authentications is too short'); + hash_blake_or_poseidon(*authentications[auth_start], current.value, is_verifier_friendly) + }; + queue.append(VectorQueryWithDepth { index: parent, value: hash, depth: current.depth - 1, }); + compute_root_from_queries( + queue, start + 1, n_verifier_friendly_layers, authentications, auth_start + 1 + ) +} + +// Shifts the query indices by shift=2**height, to convert index representation to heap-like. +// Validates the query index range. +fn shift_queries( + queries: Span, shift: felt252, height: felt252 +) -> Array { + let mut shifted_queries = ArrayTrait::new(); + let mut i = 0; + loop { + if i == queries.len() { + break; + }; + let q = *queries[i]; + shifted_queries + .append( + VectorQueryWithDepth { index: q.index + shift, value: q.value, depth: height, } + ); + i += 1; + }; + shifted_queries +} + +fn hash_blake_or_poseidon(x: felt252, y: felt252, is_verifier_friendly: bool) -> felt252 { + if is_verifier_friendly { + let (hash, _, _) = hades_permutation(x, y, 2); + hash + } else { + truncated_blake2s(x, y) + } +} From 8b04f5477ce619b07cd81dbea1cc605ee59bf42c Mon Sep 17 00:00:00 2001 From: Bartosz Nowak Date: Sat, 6 Jan 2024 16:33:36 +0100 Subject: [PATCH 04/12] function skaffold --- src/proof_of_work/proof_of_work.cairo | 86 +++++++++++++++++---------- 1 file changed, 54 insertions(+), 32 deletions(-) diff --git a/src/proof_of_work/proof_of_work.cairo b/src/proof_of_work/proof_of_work.cairo index b1363cd32..3bda3a0a2 100644 --- a/src/proof_of_work/proof_of_work.cairo +++ b/src/proof_of_work/proof_of_work.cairo @@ -1,8 +1,17 @@ +use core::array::SpanTrait; +use core::array::ArrayTrait; +use cairo_verifier::common::flip_endianness::FlipEndiannessTrait; +use core::debug::PrintTrait; use cairo_verifier::{ common::{blake2s::blake2s, array_append::ArrayAppendTrait, math::pow}, channel::channel::{Channel, ChannelTrait}, proof_of_work::config::{ProofOfWorkConfig, BYTE_UPPER_BOUND, WORD_UPPER_BOUND} }; +use cairo_verifier::common::array_print::{SpanPrintTrait, ArrayPrintTrait}; + +const POW_2_12: u256 = 79228162514264337593543950336; +const POW_2_4: u256 = 4294967296; +const POW_2_3: u256 = 16777216; #[derive(Drop, Copy)] struct ProofOfWorkUnsentCommitment { @@ -18,36 +27,49 @@ fn proof_of_work_commit( fn verify_proof_of_work(digest: u256, n_bits: u8, nonce: u64) { // Compute the initial hash. - // Hash(0123456789abcded || digest || n_bits) - // 8 bytes || 0x20 bytes || 1 byte - // Total of 0x29 bytes. - // Arrange the hash input according to the keccak requirement of 0x10 byte chunks. - let init_hash_value: u256 = 0x0123456789abcded000000000000000000000000000000000000000000000000 - // digest >> 12 -> digest << 4 - + digest / 79228162514264337593543950336 * 4294967296 - // nbits << 3 - + n_bits.into() * 16777216; - - let mut init_hash_data = ArrayTrait::::new(); - init_hash_data.append_big_endian(init_hash_value); - let init_hash = blake2s(init_hash_data); - - // Compute Hash(init_hash || nonce ) - // 0x20 bytes || 8 bytes - // Total of 0x28 bytes. - - // init_hash >> 12 -> init_hash << 8 + 4 - let hash_value: u256 = init_hash / 79228162514264337593543950336 * 79228162514264337593543950336 - // nonce << 4 - + nonce.into() * 4294967296; - - let mut hash_data = ArrayTrait::::new(); - hash_data.append_big_endian(hash_value); - let hash = blake2s(hash_data); - let work_limit = pow(2, 128 - n_bits.into()); - - assert( - Into::::into(hash.high) < Into::::into(work_limit), - 'proof of work failed' - ) + // Hash(0123456789abcded || digest || n_bits ) + // 8 bytes || 32 bytes || 1 byte + // Total of 0x29 = 41 bytes. + + // let init_hash_value: u256 = 0x0123456789abcded000000000000000000000000000000000000000000000000 + // // digest >> 12 -> digest << 4 -> nbits << 3 + // + digest / POW_2_12 * POW_2_4 + n_bits.into() * POW_2_3; + + let mut init_hash_data = ArrayTrait::::new(); + init_hash_data.append_big_endian(u256{low: 0xD7CA1D48A19D8FF802A71D94169DE383, high: 0x0123456789ABCDED1C5A5F4381DF1F5C}); + init_hash_data.append_big_endian(u256{low: 0x00000000000000000000000000000000, high: 0x82621FDC5514A10A1400000000000000}); + let span = init_hash_data.span().slice(0,41); + let mut arr = ArrayTrait::::new(); + let mut i:u32 = 0; + loop { + if i == span.len() { + break; + } + + arr.append(*span.at(i)); + i+=1; + }; + let init_hash = blake2s(arr).flip_endianness(); + init_hash.print(); + + // correct hash on test data: + // 0x6ae49da749fbe3fc98f114c0f8342a4d + // 0x26438c9c119a3b222f70d564d5df2ebc + + // // Compute Hash(init_hash || nonce ) + // // 32 bytes || 8 bytes + // // Total of 0x28 = 40 bytes. + + // // init_hash >> 12 -> init_hash << 8 + 4 -> nonce << 4 + // let hash_value: u256 = init_hash / POW_2_12 * POW_2_12 + nonce.into() * POW_2_4; + + // let mut hash_data = ArrayTrait::::new(); + // hash_data.append_big_endian(hash_value); + // let hash = blake2s(hash_data); + // let work_limit = pow(2, 128 - n_bits.into()); + + // assert( + // Into::::into(hash.high) < Into::::into(work_limit), + // 'proof of work failed' + // ) } From 752585cf42393ccd5c63184e404d291112610744 Mon Sep 17 00:00:00 2001 From: Bartosz Nowak Date: Sat, 6 Jan 2024 16:39:44 +0100 Subject: [PATCH 05/12] test skaffold --- src/proof_of_work/tests.cairo | 1 + src/proof_of_work/tests/test_proof_of_work.cairo | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 src/proof_of_work/tests/test_proof_of_work.cairo diff --git a/src/proof_of_work/tests.cairo b/src/proof_of_work/tests.cairo index e69de29bb..1164558f8 100644 --- a/src/proof_of_work/tests.cairo +++ b/src/proof_of_work/tests.cairo @@ -0,0 +1 @@ +mod test_proof_of_work; \ No newline at end of file diff --git a/src/proof_of_work/tests/test_proof_of_work.cairo b/src/proof_of_work/tests/test_proof_of_work.cairo new file mode 100644 index 000000000..0f1401677 --- /dev/null +++ b/src/proof_of_work/tests/test_proof_of_work.cairo @@ -0,0 +1,10 @@ +use cairo_verifier::proof_of_work::proof_of_work::verify_proof_of_work; + +#[test] +#[available_gas(9999999999)] +fn test_verify_proof_of_work_0() { + let digest: u256 = 0x1c5a5f4381df1f5cd7ca1d48a19d8ff802a71d94169de38382621fdc5514a10a; + let nonce: u64 = 0x1683b; + let n_bits: u8 = 20; + verify_proof_of_work(digest, n_bits, nonce); +} From a4e0eef096f3699ddc001e88af239afd2c4492b6 Mon Sep 17 00:00:00 2001 From: Bartosz Nowak Date: Sat, 6 Jan 2024 19:05:18 +0100 Subject: [PATCH 06/12] blake2s u8 native version --- src/common.cairo | 1 + src/common/array_append.cairo | 116 +++++- src/common/blake2s_u8.cairo | 435 +++++++++++++++++++++ src/common/tests.cairo | 2 + src/common/tests/test_blake2s_big_u8.cairo | 85 ++++ src/common/tests/test_blake2s_u8.cairo | 98 +++++ 6 files changed, 736 insertions(+), 1 deletion(-) create mode 100644 src/common/blake2s_u8.cairo create mode 100644 src/common/tests/test_blake2s_big_u8.cairo create mode 100644 src/common/tests/test_blake2s_u8.cairo diff --git a/src/common.cairo b/src/common.cairo index 68b1bdd9c..fe7811eb7 100644 --- a/src/common.cairo +++ b/src/common.cairo @@ -1,4 +1,5 @@ mod blake2s; +mod blake2s_u8; mod flip_endianness; mod from_span; mod horner_eval; diff --git a/src/common/array_append.cairo b/src/common/array_append.cairo index 8ecba931a..af725bdb2 100644 --- a/src/common/array_append.cairo +++ b/src/common/array_append.cairo @@ -103,4 +103,118 @@ impl ArrayU32AppendU64 of ArrayAppendTrait { } } } -} \ No newline at end of file +} + +impl ArrayU8AppendU256 of ArrayAppendTrait { + fn append_little_endian(ref self: Array, element: u256) { + self.append_little_endian(element.low); + self.append_little_endian(element.high); + } + + fn append_big_endian(ref self: Array, element: u256) { + self.append_big_endian(element.high); + self.append_big_endian(element.low); + } +} + +// input's MSB is padded with 0s +// (internally felt252 is converted to u256) +impl ArrayU8AppendFelt of ArrayAppendTrait { + fn append_little_endian(ref self: Array, element: felt252) { + self.append_little_endian(Into::::into(element)); + } + + fn append_big_endian(ref self: Array, element: felt252) { + self.append_big_endian(Into::::into(element)); + } +} + +impl ArrayU8AppendU128 of ArrayAppendTrait { + fn append_little_endian(ref self: Array, mut element: u128) { + let mut i = 16; + loop { + if i != 0 { + i -= 1; + let (q, r) = DivRem::div_rem(element, U128maxU8.try_into().unwrap()); + self.append(r.try_into().unwrap()); + element = q; + } else { + break; + } + } + } + + fn append_big_endian(ref self: Array, mut element: u128) { + let mut array = ArrayTrait::::new(); + array.append_little_endian(element); + let mut i = array.len(); + loop { + if i != 0 { + i -= 1; + self.append(*array.at(i)); + } else { + break; + } + } + } +} + +impl ArrayU8AppendU64 of ArrayAppendTrait { + fn append_little_endian(ref self: Array, mut element: u64) { + let mut i = 8; + loop { + if i != 0 { + i -= 1; + let (q, r) = DivRem::div_rem(element, U64maxU8.try_into().unwrap()); + self.append(r.try_into().unwrap()); + element = q; + } else { + break; + } + } + } + + fn append_big_endian(ref self: Array, mut element: u64) { + let mut array = ArrayTrait::::new(); + array.append_little_endian(element); + let mut i = array.len(); + loop { + if i != 0 { + i -= 1; + self.append(*array.at(i)); + } else { + break; + } + } + } +} + +impl ArrayU8AppendU32 of ArrayAppendTrait { + fn append_little_endian(ref self: Array, mut element: u32) { + let mut i = 4; + loop { + if i != 0 { + i -= 1; + let (q, r) = DivRem::div_rem(element, U32maxU8.try_into().unwrap()); + self.append(r.try_into().unwrap()); + element = q; + } else { + break; + } + } + } + + fn append_big_endian(ref self: Array, mut element: u32) { + let mut array = ArrayTrait::::new(); + array.append_little_endian(element); + let mut i = array.len(); + loop { + if i != 0 { + i -= 1; + self.append(*array.at(i)); + } else { + break; + } + } + } +} diff --git a/src/common/blake2s_u8.cairo b/src/common/blake2s_u8.cairo new file mode 100644 index 000000000..e0beaada9 --- /dev/null +++ b/src/common/blake2s_u8.cairo @@ -0,0 +1,435 @@ +use core::integer::u32_wrapping_add; +use cairo_verifier::common::array_append::ArrayAppendTrait; +use cairo_verifier::common::flip_endianness::FlipEndiannessTrait; + + +fn blake2s(data: Array) -> u256 { + let mut state = blake2s_init(); + state = blake2s_update(state, data); + blake2s_final(state) +} + +// A 160 LSB truncated version of blake2s. +// hash: +// blake2s(x, y) & ~((1<<96) - 1). +fn truncated_blake2s(x: felt252, y: felt252) -> felt252 { + let mut data = ArrayTrait::::new(); + data.append_big_endian(x); + data.append_big_endian(y); + + // Truncate hash - convert value to felt, by taking the least significant 160 bits. + let hash = blake2s(data).flip_endianness() % 0x10000000000000000000000000000000000000000; + hash.try_into().unwrap() +} + +// internals: + +fn load32(p0: u8, p1: u8, p2: u8, p3: u8) -> u32 { + let mut x: u32 = p3.into(); + x = x * 256 + p2.into(); + x = x * 256 + p1.into(); + x = x * 256 + p0.into(); + x +} + +fn get_sigma(r: u32) -> Array { + if r == 0 { + array![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + } else if r == 1 { + array![14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3] + } else if r == 2 { + array![11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4] + } else if r == 3 { + array![7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8] + } else if r == 4 { + array![9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13] + } else if r == 5 { + array![2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9] + } else if r == 6 { + array![12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11] + } else if r == 7 { + array![13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10] + } else if r == 8 { + array![6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5] + } else { // r == 9 + array![10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0] + } +} + +fn rotr16(n: u32) -> u32 { + n / 65536 + (n % 65536) * 65536 +} + +fn rotr12(n: u32) -> u32 { + n / 4096 + (n % 4096) * 1048576 +} + +fn rotr8(n: u32) -> u32 { + n / 256 + (n % 256) * 16777216 +} + +fn rotr7(n: u32) -> u32 { + n / 128 + (n % 128) * 33554432 +} + +#[derive(Drop, Clone)] +struct blake2s_state { + h: Array, // length: 8 + t0: u32, + t1: u32, + f0: u32, + buf: Array, // length: 64 + buflen: u32, +} + +fn blake2s_init() -> blake2s_state { + let blake2s_IV = array![ + 0x6A09E667 ^ 0x01010020, // xor (depth, fanout, digest_length) + 0xBB67AE85, + 0x3C6EF372, + 0xA54FF53A, + 0x510E527F, + 0x9B05688C, + 0x1F83D9AB, + 0x5BE0CD19 + ]; + let mut buf = ArrayTrait::new(); + let mut i = 0; + loop { + if i == 64 { + break; + } + buf.append(0); + i += 1; + }; + + blake2s_state { h: blake2s_IV, t0: 0, t1: 0, f0: 0, buf: buf, buflen: 0 } +} + +fn blake2s_compress(mut s: blake2s_state, in: Array) -> blake2s_state { + assert(in.len() == 64, 'in array must have length 64'); + + let mut m: Array = ArrayTrait::new(); + + let mut i: u32 = 0; + loop { + if i == 16 { + break; + } + m.append(load32(*in[4*i+0], *in[4*i+1], *in[4*i+2], *in[4*i+3])); + i += 1; + }; + + let mut v0: u32 = *s.h[0]; + let mut v1: u32 = *s.h[1]; + let mut v2: u32 = *s.h[2]; + let mut v3: u32 = *s.h[3]; + let mut v4: u32 = *s.h[4]; + let mut v5: u32 = *s.h[5]; + let mut v6: u32 = *s.h[6]; + let mut v7: u32 = *s.h[7]; + let mut v8: u32 = 0x6A09E667; + let mut v9: u32 = 0xBB67AE85; + let mut v10: u32 = 0x3C6EF372; + let mut v11: u32 = 0xA54FF53A; + let mut v12: u32 = s.t0 ^ 0x510E527F; + let mut v13: u32 = s.t1 ^ 0x9B05688C; + let mut v14: u32 = s.f0 ^ 0x1F83D9AB; + let mut v15: u32 = 0x5BE0CD19; // f1 is always 0 + + let m_span = m.span(); + + let mut r = 0; + loop { + if r == 10 { + break; + } + + let sigma = get_sigma(r); + + // ROUND function begin + + let mut a = 0; + let mut b = 0; + let mut c = 0; + let mut d = 0; + let mut i = 0; + loop { + if i == 8 { + break; + } + if i == 0 { + a = v0; + b = v4; + c = v8; + d = v12; + } else if i == 1 { + a = v1; + b = v5; + c = v9; + d = v13; + } else if i == 2 { + a = v2; + b = v6; + c = v10; + d = v14; + } else if i == 3 { + a = v3; + b = v7; + c = v11; + d = v15; + } else if i == 4 { + a = v0; + b = v5; + c = v10; + d = v15; + } else if i == 5 { + a = v1; + b = v6; + c = v11; + d = v12; + } else if i == 6 { + a = v2; + b = v7; + c = v8; + d = v13; + } else if i == 7 { + a = v3; + b = v4; + c = v9; + d = v14; + }; + + // G function begin + + // a = a + b + m[sigma[r][2*i]] + a = u32_wrapping_add(u32_wrapping_add(a, b), *m_span.at(*sigma[2 * i])); + + d = rotr16(d ^ a); + + // c = c + d + c = u32_wrapping_add(c, d); + + b = rotr12(b ^ c); + + // a = a + b + m[sigma[r][2*i+1]] + a = u32_wrapping_add(u32_wrapping_add(a, b), *m_span.at(*sigma[2 * i + 1])); + + d = rotr8(d ^ a); + + // c = c + d + c = u32_wrapping_add(c, d); + + b = rotr7(b ^ c); + + // G function end + + if i == 0 { + v0 = a; + v4 = b; + v8 = c; + v12 = d; + } else if i == 1 { + v1 = a; + v5 = b; + v9 = c; + v13 = d; + } else if i == 2 { + v2 = a; + v6 = b; + v10 = c; + v14 = d; + } else if i == 3 { + v3 = a; + v7 = b; + v11 = c; + v15 = d; + } else if i == 4 { + v0 = a; + v5 = b; + v10 = c; + v15 = d; + } else if i == 5 { + v1 = a; + v6 = b; + v11 = c; + v12 = d; + } else if i == 6 { + v2 = a; + v7 = b; + v8 = c; + v13 = d; + } else if i == 7 { + v3 = a; + v4 = b; + v9 = c; + v14 = d; + }; + + i += 1; + }; + + // ROUND function end + + r += 1; + }; + + let mut new_h = ArrayTrait::new(); + new_h.append((*s.h[0]) ^ v0 ^ v8); + new_h.append((*s.h[1]) ^ v1 ^ v9); + new_h.append((*s.h[2]) ^ v2 ^ v10); + new_h.append((*s.h[3]) ^ v3 ^ v11); + new_h.append((*s.h[4]) ^ v4 ^ v12); + new_h.append((*s.h[5]) ^ v5 ^ v13); + new_h.append((*s.h[6]) ^ v6 ^ v14); + new_h.append((*s.h[7]) ^ v7 ^ v15); + s.h = new_h; + + s +} + +fn blake2s_update(mut s: blake2s_state, in: Array) -> blake2s_state { + let mut in_len = in.len(); + let mut in_shift = 0; + let in_span = in.span(); + if in_len != 0 { + let left = s.buflen; + let fill = 64 - left; + if in_len > fill { + s.buflen = 0; + + let mut new_buf = ArrayTrait::new(); + let buf_span = s.buf.span(); + let mut i: u32 = 0; + loop { + if i == left { + break; + } + new_buf.append(*buf_span.at(i)); + i += 1; + }; + + i = 0; + loop { + if i == fill { + break; + } + new_buf.append(*in_span[i]); + i += 1; + }; + + // blake2s_increment_counter + s.t0 = u32_wrapping_add(s.t0, 64_u32); + if s.t0 < 64_u32 { + s.t1 = u32_wrapping_add(s.t1, 1); + } + + s = blake2s_compress(s, new_buf); + + in_shift += fill; + in_len -= fill; + + loop { + if in_len <= 64 { + break; + } + + // blake2s_increment_counter + s.t0 = u32_wrapping_add(s.t0, 64_u32); + if s.t0 < 64_u32 { + s.t1 = u32_wrapping_add(s.t1, 1); + } + + let mut compress_in = ArrayTrait::new(); + i = 0; + loop { + if i == 64 { + break; + } + compress_in.append(*in_span[in_shift + i]); + i += 1; + }; + + s = blake2s_compress(s, compress_in); + + in_shift += 64; + in_len -= 64; + }; + } + + let mut new_buf = ArrayTrait::new(); + let buf_span = s.buf.span(); + let mut i = 0; + loop { + if i == s.buflen { + break; + } + new_buf.append(*buf_span[i]); + i += 1; + }; + i = 0; + loop { + if i == in_len { + break; + } + new_buf.append(*in_span[in_shift + i]); + i += 1; + }; + loop { + if new_buf.len() == 64 { + break; + } + new_buf.append(0); + }; + s.buf = new_buf; + s.buflen += in_len; + } + + s +} + +fn blake2s_final(mut s: blake2s_state) -> u256 { + assert(s.f0 == 0, 'blake2s_is_lastblock'); + + // blake2s_increment_counter + s.t0 = u32_wrapping_add(s.t0, s.buflen); + if s.t0 < s.buflen { + s.t1 = u32_wrapping_add(s.t1, 1); + } + + s.f0 = 0xffffffff; + + let mut i = 0; + let buf_span = s.buf.span(); + let mut buf = ArrayTrait::new(); + loop { + if i == s.buflen { + break; + } + buf.append(*buf_span[i]); + i += 1; + }; + loop { + if i == 64 { + break; + } + buf.append(0); + i += 1; + }; + + s = blake2s_compress(s, buf); + + let mut result: u256 = 0; + let mut multiplier: u256 = 1; + i = 0; + loop { + result += (*s.h[i]).into() * multiplier; + i += 1; + if i == 8 { + break; + } + multiplier *= 0x100000000; + }; + + result +} diff --git a/src/common/tests.cairo b/src/common/tests.cairo index 2dca85a79..631436903 100644 --- a/src/common/tests.cairo +++ b/src/common/tests.cairo @@ -1,4 +1,5 @@ mod test_blake2s; +mod test_blake2s_u8; mod test_flip_endianness; mod test_from_span; mod test_horner_eval; @@ -8,6 +9,7 @@ mod test_merge_sort; // notice: this test takes a lot of time and computation // uncomment it when making changes to blake2s // mod test_blake2s_big; +// mod test_blake2s_u8_big; // notice: this test takes a lot of time and computation // uncomment it when making changes to merge sort diff --git a/src/common/tests/test_blake2s_big_u8.cairo b/src/common/tests/test_blake2s_big_u8.cairo new file mode 100644 index 000000000..84f713ce9 --- /dev/null +++ b/src/common/tests/test_blake2s_big_u8.cairo @@ -0,0 +1,85 @@ +use cairo_verifier::common::blake2s_u8::blake2s; +use cairo_verifier::common::tests::test_blake2s_u8::{get_arr_v1, get_arr_v2}; + + +#[test] +#[available_gas(9999999999)] +fn test_blake2s_v1_big() { + assert( + blake2s( + get_arr_v1(16) + ) == 0xc7fa21bb08b0bd19600ad212c0fa0f7ff332f415ae1527282a939406413299aa, + 'invalid hash (16)' + ); + assert( + blake2s( + get_arr_v1(17) + ) == 0x6acb015d7514d821091ec780120b89ba4663f65e6ff6588d458ef333fe8c8a39, + 'invalid hash (17)' + ); + assert( + blake2s( + get_arr_v1(32) + ) == 0x5651036b64f7affbe498f0409950e06a352bcae03f5a79b78fec58a4cebe10d5, + 'invalid hash (32)' + ); + assert( + blake2s( + get_arr_v1(33) + ) == 0x42d5eeff1aa4972630bcca469f37bbe8c2f8014937e28cbedbc671571d3eb87c, + 'invalid hash (33)' + ); + assert( + blake2s( + get_arr_v1(250) + ) == 0x33fc848fc73514d8bc3f338b23ba684d945081da37e5a8e490db5032eac34630, + 'invalid hash (250)' + ); + assert( + blake2s( + get_arr_v1(272) + ) == 0x1b5ad0d1b82600127a6add8e1cf604a075843c3d35bbe31d636fa071674c9432, + 'invalid hash (272)' + ); +} + +#[test] +#[available_gas(9999999999)] +fn test_blake2s_v2_big() { + assert( + blake2s( + get_arr_v2(16) + ) == 0xdfe91aa5523f1df5e6549d98121e9bdbac4cbba4375e93d812ef487d0fe562f6, + 'invalid hash (16)' + ); + assert( + blake2s( + get_arr_v2(17) + ) == 0x49f2c2bb269d275a111a04c459c847838a0cf7c488d6366577a21f75620243e6, + 'invalid hash (17)' + ); + assert( + blake2s( + get_arr_v2(32) + ) == 0x83e9b2b70274d9198b6b77a1760ebacfd1f0fe232a0ed78f1c722e154ee72362, + 'invalid hash (32)' + ); + assert( + blake2s( + get_arr_v2(33) + ) == 0x93a7f68b8ea17374c11e1da719885513b598c4e191825fb584e399206c05ae15, + 'invalid hash (33)' + ); + assert( + blake2s( + get_arr_v2(250) + ) == 0xe4e6bd453ba2eb5a378d7933576dbf697b6d31cf38061c550ea36f6843a9bf43, + 'invalid hash (250)' + ); + assert( + blake2s( + get_arr_v2(272) + ) == 0x5906fef89f21466142323029000040f6c25be2ff87d581a8f752b94ad3662762, + 'invalid hash (272)' + ); +} diff --git a/src/common/tests/test_blake2s_u8.cairo b/src/common/tests/test_blake2s_u8.cairo new file mode 100644 index 000000000..388784670 --- /dev/null +++ b/src/common/tests/test_blake2s_u8.cairo @@ -0,0 +1,98 @@ +use cairo_verifier::common::blake2s_u8::{blake2s, truncated_blake2s, load32}; + +fn get_arr_v1(n: u32) -> Array { + let mut arr = ArrayTrait::new(); + let mut i: u32 = 1; + loop { + arr.append((i % 256).try_into().unwrap()); + if i == 4 * n { + break; + } + i += 1; + }; + let mut out = ArrayTrait::new(); + i = 0; + loop { + out.append(*arr[4 * i]); + out.append(*arr[4 * i + 1]); + out.append(*arr[4 * i + 2]); + out.append(*arr[4 * i + 3]); + i += 1; + if i == n { + break; + }; + }; + out +} + +fn get_arr_v2(n: u32) -> Array { + let mut arr = ArrayTrait::new(); + let mut s: u32 = 1; + let mut i: u32 = 1; + loop { + s *= 17; + s = s ^ i; + s %= 256; + arr.append(s.try_into().unwrap()); + if i == 4 * n { + break; + } + i += 1; + }; + let mut out = ArrayTrait::new(); + i = 0; + loop { + out.append(*arr[4 * i]); + out.append(*arr[4 * i + 1]); + out.append(*arr[4 * i + 2]); + out.append(*arr[4 * i + 3]); + i += 1; + if i == n { + break; + }; + }; + out +} + +#[test] +#[available_gas(9999999999)] +fn test_blake2s_v1() { + assert( + blake2s( + get_arr_v1(1) + ) == 0x035c8c55b225b3cad27dec93997fb528978127b9aa3c145c4308b8b6a4b0c7d4, + 'invalid hash (1)' + ); + assert( + blake2s( + get_arr_v1(2) + ) == 0x676da142c9e15751cf6c94e96ebc05925408612bbcf56437adf6fb21822fca4b, + 'invalid hash (2)' + ); +} + +#[test] +#[available_gas(9999999999)] +fn test_blake2s_v2() { + assert( + blake2s( + get_arr_v2(1) + ) == 0x3becbdec8344113fbee53542a4ef696e97db25efb96cef60d2919bb4dd00ed3e, + 'invalid hash (1)' + ); + assert( + blake2s( + get_arr_v2(2) + ) == 0x5229f5d506302edae36f9cac3f5d176cd9b6aa8420da6d74d7956789099faf70, + 'invalid hash (2)' + ); +} + +#[test] +#[available_gas(9999999999)] +fn test_truncated_blake2s() { + let x = 1157029198022238202306346125123666191662554108005; + let y = 129252051435949032402481343903845417193011527432; + let out = truncated_blake2s(x, y); + assert(out == 642191007116032514313255519742888271333651019057, 'invalid truncated_blake2s'); +} From fa1b453089d5c9b8f3e46e07bbe969e71456e13b Mon Sep 17 00:00:00 2001 From: Bartosz Nowak Date: Sat, 6 Jan 2024 19:18:51 +0100 Subject: [PATCH 07/12] crude impl tests working --- src/proof_of_work/proof_of_work.cairo | 39 ++++++++++++++------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/proof_of_work/proof_of_work.cairo b/src/proof_of_work/proof_of_work.cairo index 3bda3a0a2..0b3505be4 100644 --- a/src/proof_of_work/proof_of_work.cairo +++ b/src/proof_of_work/proof_of_work.cairo @@ -3,7 +3,7 @@ use core::array::ArrayTrait; use cairo_verifier::common::flip_endianness::FlipEndiannessTrait; use core::debug::PrintTrait; use cairo_verifier::{ - common::{blake2s::blake2s, array_append::ArrayAppendTrait, math::pow}, + common::{blake2s_u8::blake2s, array_append::ArrayAppendTrait, math::pow}, channel::channel::{Channel, ChannelTrait}, proof_of_work::config::{ProofOfWorkConfig, BYTE_UPPER_BOUND, WORD_UPPER_BOUND} }; @@ -38,7 +38,7 @@ fn verify_proof_of_work(digest: u256, n_bits: u8, nonce: u64) { let mut init_hash_data = ArrayTrait::::new(); init_hash_data.append_big_endian(u256{low: 0xD7CA1D48A19D8FF802A71D94169DE383, high: 0x0123456789ABCDED1C5A5F4381DF1F5C}); init_hash_data.append_big_endian(u256{low: 0x00000000000000000000000000000000, high: 0x82621FDC5514A10A1400000000000000}); - let span = init_hash_data.span().slice(0,41); + let span = init_hash_data.span().slice(0,0x29); let mut arr = ArrayTrait::::new(); let mut i:u32 = 0; loop { @@ -50,26 +50,29 @@ fn verify_proof_of_work(digest: u256, n_bits: u8, nonce: u64) { i+=1; }; let init_hash = blake2s(arr).flip_endianness(); - init_hash.print(); - - // correct hash on test data: - // 0x6ae49da749fbe3fc98f114c0f8342a4d - // 0x26438c9c119a3b222f70d564d5df2ebc // // Compute Hash(init_hash || nonce ) // // 32 bytes || 8 bytes // // Total of 0x28 = 40 bytes. - // // init_hash >> 12 -> init_hash << 8 + 4 -> nonce << 4 - // let hash_value: u256 = init_hash / POW_2_12 * POW_2_12 + nonce.into() * POW_2_4; - - // let mut hash_data = ArrayTrait::::new(); - // hash_data.append_big_endian(hash_value); - // let hash = blake2s(hash_data); - // let work_limit = pow(2, 128 - n_bits.into()); + let mut hash_data = ArrayTrait::::new(); + hash_data.append_big_endian(init_hash); + hash_data.append_big_endian(u256{low: 0x00000000000000000000000000000000, high: 0x000000000001683b0000000000000000}); + let span = hash_data.span().slice(0,0x28); + let mut arr = ArrayTrait::::new(); + let mut i:u32 = 0; + loop { + if i == span.len() { + break; + } - // assert( - // Into::::into(hash.high) < Into::::into(work_limit), - // 'proof of work failed' - // ) + arr.append(*span.at(i)); + i+=1; + }; + let hash = blake2s(arr).flip_endianness(); + let work_limit = pow(2, 128 - n_bits.into()); + assert( + Into::::into(hash.high) < Into::::into(work_limit), + 'proof of work failed' + ) } From 378f13d94881a8fcb25323ee4f530c5b5e1ce4e3 Mon Sep 17 00:00:00 2001 From: Bartosz Nowak Date: Sat, 6 Jan 2024 19:27:49 +0100 Subject: [PATCH 08/12] impl refactor --- src/proof_of_work/proof_of_work.cairo | 56 +++++-------------- src/proof_of_work/tests.cairo | 2 +- .../tests/test_proof_of_work.cairo | 10 ++++ 3 files changed, 25 insertions(+), 43 deletions(-) diff --git a/src/proof_of_work/proof_of_work.cairo b/src/proof_of_work/proof_of_work.cairo index 0b3505be4..a0a8b550b 100644 --- a/src/proof_of_work/proof_of_work.cairo +++ b/src/proof_of_work/proof_of_work.cairo @@ -1,17 +1,13 @@ -use core::array::SpanTrait; -use core::array::ArrayTrait; -use cairo_verifier::common::flip_endianness::FlipEndiannessTrait; -use core::debug::PrintTrait; use cairo_verifier::{ - common::{blake2s_u8::blake2s, array_append::ArrayAppendTrait, math::pow}, + common::{ + flip_endianness::FlipEndiannessTrait, array_print::{SpanPrintTrait, ArrayPrintTrait}, + blake2s_u8::blake2s, array_append::ArrayAppendTrait, math::pow, + }, channel::channel::{Channel, ChannelTrait}, proof_of_work::config::{ProofOfWorkConfig, BYTE_UPPER_BOUND, WORD_UPPER_BOUND} }; -use cairo_verifier::common::array_print::{SpanPrintTrait, ArrayPrintTrait}; -const POW_2_12: u256 = 79228162514264337593543950336; -const POW_2_4: u256 = 4294967296; -const POW_2_3: u256 = 16777216; +const MAGIC: u64 = 0x0123456789abcded; #[derive(Drop, Copy)] struct ProofOfWorkUnsentCommitment { @@ -31,45 +27,21 @@ fn verify_proof_of_work(digest: u256, n_bits: u8, nonce: u64) { // 8 bytes || 32 bytes || 1 byte // Total of 0x29 = 41 bytes. - // let init_hash_value: u256 = 0x0123456789abcded000000000000000000000000000000000000000000000000 - // // digest >> 12 -> digest << 4 -> nbits << 3 - // + digest / POW_2_12 * POW_2_4 + n_bits.into() * POW_2_3; - let mut init_hash_data = ArrayTrait::::new(); - init_hash_data.append_big_endian(u256{low: 0xD7CA1D48A19D8FF802A71D94169DE383, high: 0x0123456789ABCDED1C5A5F4381DF1F5C}); - init_hash_data.append_big_endian(u256{low: 0x00000000000000000000000000000000, high: 0x82621FDC5514A10A1400000000000000}); - let span = init_hash_data.span().slice(0,0x29); - let mut arr = ArrayTrait::::new(); - let mut i:u32 = 0; - loop { - if i == span.len() { - break; - } - - arr.append(*span.at(i)); - i+=1; - }; - let init_hash = blake2s(arr).flip_endianness(); + init_hash_data.append_big_endian(MAGIC); + init_hash_data.append_big_endian(digest); + init_hash_data.append(n_bits); + let init_hash = blake2s(init_hash_data).flip_endianness(); - // // Compute Hash(init_hash || nonce ) - // // 32 bytes || 8 bytes - // // Total of 0x28 = 40 bytes. + // Compute Hash(init_hash || nonce ) + // 32 bytes || 8 bytes + // Total of 0x28 = 40 bytes. let mut hash_data = ArrayTrait::::new(); hash_data.append_big_endian(init_hash); - hash_data.append_big_endian(u256{low: 0x00000000000000000000000000000000, high: 0x000000000001683b0000000000000000}); - let span = hash_data.span().slice(0,0x28); - let mut arr = ArrayTrait::::new(); - let mut i:u32 = 0; - loop { - if i == span.len() { - break; - } + hash_data.append_big_endian(nonce); + let hash = blake2s(hash_data).flip_endianness(); - arr.append(*span.at(i)); - i+=1; - }; - let hash = blake2s(arr).flip_endianness(); let work_limit = pow(2, 128 - n_bits.into()); assert( Into::::into(hash.high) < Into::::into(work_limit), diff --git a/src/proof_of_work/tests.cairo b/src/proof_of_work/tests.cairo index 1164558f8..57bb36e70 100644 --- a/src/proof_of_work/tests.cairo +++ b/src/proof_of_work/tests.cairo @@ -1 +1 @@ -mod test_proof_of_work; \ No newline at end of file +mod test_proof_of_work; diff --git a/src/proof_of_work/tests/test_proof_of_work.cairo b/src/proof_of_work/tests/test_proof_of_work.cairo index 0f1401677..78716fabc 100644 --- a/src/proof_of_work/tests/test_proof_of_work.cairo +++ b/src/proof_of_work/tests/test_proof_of_work.cairo @@ -8,3 +8,13 @@ fn test_verify_proof_of_work_0() { let n_bits: u8 = 20; verify_proof_of_work(digest, n_bits, nonce); } + +#[test] +#[should_panic] +#[available_gas(9999999999)] +fn test_verify_proof_of_work_1() { + let digest: u256 = 0x1c5a5f4381df1f5cd7ca1d48a19d8ff802a71d94169de38382621fdc5514a10a; + let nonce: u64 = 0x1683b + 1; + let n_bits: u8 = 20; + verify_proof_of_work(digest, n_bits, nonce); +} From 1281bf9db4d8f256c660891d82be017bf3cf8328 Mon Sep 17 00:00:00 2001 From: Bartosz Nowak Date: Sat, 6 Jan 2024 19:28:03 +0100 Subject: [PATCH 09/12] fmt --- src/common/blake2s_u8.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/blake2s_u8.cairo b/src/common/blake2s_u8.cairo index e0beaada9..d421034f8 100644 --- a/src/common/blake2s_u8.cairo +++ b/src/common/blake2s_u8.cairo @@ -116,7 +116,7 @@ fn blake2s_compress(mut s: blake2s_state, in: Array) -> blake2s_state { if i == 16 { break; } - m.append(load32(*in[4*i+0], *in[4*i+1], *in[4*i+2], *in[4*i+3])); + m.append(load32(*in[4 * i + 0], *in[4 * i + 1], *in[4 * i + 2], *in[4 * i + 3])); i += 1; }; From ce91ff283e573d8b0f978b5ca6f087808546397f Mon Sep 17 00:00:00 2001 From: Bartosz Nowak Date: Sat, 6 Jan 2024 19:48:16 +0100 Subject: [PATCH 10/12] cleanup --- src/proof_of_work/config.cairo | 2 -- src/proof_of_work/proof_of_work.cairo | 7 +++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/proof_of_work/config.cairo b/src/proof_of_work/config.cairo index 9f436fcb2..cc77f4254 100644 --- a/src/proof_of_work/config.cairo +++ b/src/proof_of_work/config.cairo @@ -1,7 +1,5 @@ const MIN_PROOF_OF_WORK_BITS: u256 = 30; const MAX_PROOF_OF_WORK_BITS: u256 = 50; -const BYTE_UPPER_BOUND: u32 = 256; // 2 ** 8 -const WORD_UPPER_BOUND: u128 = 18446744073709551616; // 2 ** 64 #[derive(Drop, Copy)] struct ProofOfWorkConfig { diff --git a/src/proof_of_work/proof_of_work.cairo b/src/proof_of_work/proof_of_work.cairo index a0a8b550b..20b99ffb9 100644 --- a/src/proof_of_work/proof_of_work.cairo +++ b/src/proof_of_work/proof_of_work.cairo @@ -3,8 +3,7 @@ use cairo_verifier::{ flip_endianness::FlipEndiannessTrait, array_print::{SpanPrintTrait, ArrayPrintTrait}, blake2s_u8::blake2s, array_append::ArrayAppendTrait, math::pow, }, - channel::channel::{Channel, ChannelTrait}, - proof_of_work::config::{ProofOfWorkConfig, BYTE_UPPER_BOUND, WORD_UPPER_BOUND} + channel::channel::{Channel, ChannelTrait}, proof_of_work::config::{ProofOfWorkConfig} }; const MAGIC: u64 = 0x0123456789abcded; @@ -23,8 +22,8 @@ fn proof_of_work_commit( fn verify_proof_of_work(digest: u256, n_bits: u8, nonce: u64) { // Compute the initial hash. - // Hash(0123456789abcded || digest || n_bits ) - // 8 bytes || 32 bytes || 1 byte + // Hash(0x0123456789abcded || digest || n_bits ) + // 8 bytes || 32 bytes || 1 byte // Total of 0x29 = 41 bytes. let mut init_hash_data = ArrayTrait::::new(); From 4f5eb8f7799ad6be4de5bf379f4f36ba4622e01c Mon Sep 17 00:00:00 2001 From: Bartosz Nowak Date: Mon, 8 Jan 2024 08:20:42 +0100 Subject: [PATCH 11/12] rm calc.py file --- calc.py | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 calc.py diff --git a/calc.py b/calc.py deleted file mode 100644 index 49292ec36..000000000 --- a/calc.py +++ /dev/null @@ -1,2 +0,0 @@ -print(2 ** 64) -print(256 ** 8) \ No newline at end of file From 2000bb63040251ef9c3ade6ecc32a0e538351134 Mon Sep 17 00:00:00 2001 From: Bartosz Nowak Date: Tue, 9 Jan 2024 15:56:00 +0100 Subject: [PATCH 12/12] config validate as struct method --- src/proof_of_work/config.cairo | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/proof_of_work/config.cairo b/src/proof_of_work/config.cairo index cc77f4254..f769ebd7d 100644 --- a/src/proof_of_work/config.cairo +++ b/src/proof_of_work/config.cairo @@ -7,7 +7,10 @@ struct ProofOfWorkConfig { n_bits: u8, } -fn proof_of_work_config_validate(config: ProofOfWorkConfig) { - assert(config.n_bits.into() >= MIN_PROOF_OF_WORK_BITS, 'value proof of work bits to low'); - assert(config.n_bits.into() <= MIN_PROOF_OF_WORK_BITS, 'value proof of work bits to big'); +#[generate_trait] +impl ProofOfWorkConfigImpl of ProofOfWorkConfigTrait { + fn config_validate(ref self: ProofOfWorkConfig) { + assert(self.n_bits.into() >= MIN_PROOF_OF_WORK_BITS, 'value proof of work bits to low'); + assert(self.n_bits.into() <= MAX_PROOF_OF_WORK_BITS, 'value proof of work bits to big'); + } }