From 2cbd80717d71193908839bd6dc23b2f17180132e Mon Sep 17 00:00:00 2001 From: Tristan <122918260+TAdev0@users.noreply.github.com> Date: Tue, 10 Sep 2024 22:54:45 +0200 Subject: [PATCH 1/6] [dev] remove inline attribue (#172) --- src/types/utreexo.cairo | 2 +- src/utils/bytearray.cairo | 1 - src/validation/coinbase.cairo | 2 -- src/validation/transaction.cairo | 2 -- 4 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/types/utreexo.cairo b/src/types/utreexo.cairo index 9ba075c7..960010c2 100644 --- a/src/types/utreexo.cairo +++ b/src/types/utreexo.cairo @@ -31,7 +31,7 @@ use super::transaction::OutPoint; /// Accumulator representation of the state aka "Compact State Node". /// Part of the chain state. -#[derive(Drop, Copy)] +#[derive(Drop, Copy, PartialEq, Serde, Debug)] pub struct UtreexoState { /// Roots of the Merkle tree forest. /// Index is the root height, None means a gap. diff --git a/src/utils/bytearray.cairo b/src/utils/bytearray.cairo index 064f50dd..e123e30f 100644 --- a/src/utils/bytearray.cairo +++ b/src/utils/bytearray.cairo @@ -16,7 +16,6 @@ pub impl ByteArraySnapSerde of Serde<@ByteArray> { } pub impl ByteArraySnapHash, +Drop> of Hash<@ByteArray, S> { - #[inline] fn update_state(mut state: S, value: @ByteArray) -> S { let mut serialized_bytearray: Array = array![]; value.serialize(ref serialized_bytearray); diff --git a/src/validation/coinbase.cairo b/src/validation/coinbase.cairo index caf58205..53baa73c 100644 --- a/src/validation/coinbase.cairo +++ b/src/validation/coinbase.cairo @@ -60,7 +60,6 @@ fn validate_coinbase_input(input: @TxIn, block_height: u32) -> Result<(), ByteAr Result::Ok(()) } -#[inline] /// Validate coinbase sig script (BIP-34) fn validate_coinbase_sig_script(script: @ByteArray, block_height: u32) -> Result<(), ByteArray> { let script_len = script.len(); @@ -87,7 +86,6 @@ fn validate_coinbase_sig_script(script: @ByteArray, block_height: u32) -> Result Result::Ok(()) } -#[inline] /// Validate coinbase witness fn validate_coinbase_witness(witness: Span) -> Result<(), ByteArray> { if witness.len() != 1 { diff --git a/src/validation/transaction.cairo b/src/validation/transaction.cairo index a0e5c2bf..e1c887d8 100644 --- a/src/validation/transaction.cairo +++ b/src/validation/transaction.cairo @@ -67,7 +67,6 @@ pub fn validate_transaction( return compute_transaction_fee(total_input_amount, total_output_amount); } -#[inline] /// Ensure transaction fee is not negative. fn compute_transaction_fee( total_input_amount: u64, total_output_amount: u64 @@ -80,7 +79,6 @@ fn compute_transaction_fee( return Result::Ok(total_input_amount - total_output_amount); } -#[inline] /// Ensure than coinbase output is old enough to be spent. fn validate_coinbase_maturity(output_height: u32, block_height: u32) -> Result<(), ByteArray> { if block_height <= output_height + 100 { From b4a3a54df87d4518edda7e5422534d388775b90f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kami=C5=84ski=20=40=20StarkWare?= Date: Wed, 11 Sep 2024 13:04:26 +0200 Subject: [PATCH 2/6] Components diagram (#176) --- README.md | 8 +- docs/img/components.excalidraw | 2079 ++++++++++++++++++++++++++++++++ docs/img/components.svg | 17 + 3 files changed, 2102 insertions(+), 2 deletions(-) create mode 100644 docs/img/components.excalidraw create mode 100644 docs/img/components.svg diff --git a/README.md b/README.md index a9e15c56..1d29ed7d 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Raito is a zero-knowledge Bitcoin client implemented in Cairo. It aims to provid ```mermaid flowchart TB -Pnm1(STARK proof of the chain state
up to the block n - 1,
including utxo accumulator) --> Vp(zk verifier) +Pnm1(STARK proof of the chain state up to the block n - 1, including utxo accumulator) --> Vp(zk verifier) Bn(blocks n..m) ----> Vb subgraph Cairo @@ -26,7 +26,7 @@ subgraph Cairo Vb --> ChS end -Vb --> Pn(STARK proof of the chain state
up to the block m,
including utxo accumulator) +Vb --> Pn(STARK proof of the chain state up to the block m,
including utxo accumulator) style Bn fill:pink style Pn fill:lightgreen @@ -49,6 +49,10 @@ Although this is a highly experimental project without immediate plans for deplo ## Roadmap +

+ components +

+ ### Milestone 1 - Block header validation Implement a reduced light client that can verify a range of blocks starting at genesis. diff --git a/docs/img/components.excalidraw b/docs/img/components.excalidraw new file mode 100644 index 00000000..a1d08fd7 --- /dev/null +++ b/docs/img/components.excalidraw @@ -0,0 +1,2079 @@ +{ + "type": "excalidraw", + "version": 2, + "source": "https://excalidraw.com", + "elements": [ + { + "id": "vFRNXFX39m9q9jMcfiUTs", + "type": "rectangle", + "x": 773.8748840617886, + "y": -364.6578263794893, + "width": 443.20001220703125, + "height": 762.3999633789062, + "angle": 0, + "strokeColor": "#ffd43b", + "backgroundColor": "#fff9db", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "dotted", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "Zn", + "roundness": null, + "seed": 1196178576, + "version": 681, + "versionNonce": 1570713200, + "isDeleted": false, + "boundElements": [], + "updated": 1726051252954, + "link": null, + "locked": false + }, + { + "id": "OlQhyNzC4xYaxYiMVIpNp", + "type": "rectangle", + "x": 819.0748962688199, + "y": -66.05769820566115, + "width": 358.4000244140625, + "height": 441.60003662109375, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#e3fafc", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "dotted", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "Zo", + "roundness": null, + "seed": 253553776, + "version": 819, + "versionNonce": 1755594384, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "4IRy5JWO9w3bjNd3vAALY" + }, + { + "id": "0mlUBxdk542WH_plyugqH", + "type": "arrow" + }, + { + "id": "zap4kyaz0rdo0-hRwtXJT", + "type": "arrow" + }, + { + "id": "3FaeA6gbXhf3lFDHI-1by", + "type": "arrow" + }, + { + "id": "adQ0gG4ND7sWaO3NgRvCg", + "type": "arrow" + } + ], + "updated": 1726051226631, + "link": null, + "locked": false + }, + { + "id": "4IRy5JWO9w3bjNd3vAALY", + "type": "text", + "x": 898.805021696066, + "y": -61.057698205661154, + "width": 198.9397735595703, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "Zp", + "roundness": null, + "seed": 258474640, + "version": 695, + "versionNonce": 2127389328, + "isDeleted": false, + "boundElements": null, + "updated": 1726046483406, + "link": null, + "locked": false, + "text": "consensus validation", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "top", + "containerId": "OlQhyNzC4xYaxYiMVIpNp", + "originalText": "consensus validation", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "p1SkBd3U9KUtb31g2b5og", + "type": "rectangle", + "x": 864.8750366496793, + "y": -11.657978967379904, + "width": 288.0000305175781, + "height": 367.199951171875, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#99e9f2", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "dotted", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "Zs", + "roundness": null, + "seed": 1190119568, + "version": 702, + "versionNonce": 707434128, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "VTu4_oVkyOEMO4CjPRMhW" + }, + { + "id": "0mlUBxdk542WH_plyugqH", + "type": "arrow" + }, + { + "id": "3FaeA6gbXhf3lFDHI-1by", + "type": "arrow" + } + ], + "updated": 1726047632268, + "link": null, + "locked": false + }, + { + "id": "VTu4_oVkyOEMO4CjPRMhW", + "type": "text", + "x": 933.6051391887418, + "y": -6.657978967379904, + "width": 150.53982543945312, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "Zt", + "roundness": null, + "seed": 945675408, + "version": 600, + "versionNonce": 767674000, + "isDeleted": false, + "boundElements": null, + "updated": 1726046477932, + "link": null, + "locked": false, + "text": "block validation", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "top", + "containerId": "p1SkBd3U9KUtb31g2b5og", + "originalText": "block validation", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 906, + "versionNonce": 109459600, + "index": "Zu", + "isDeleted": false, + "id": "46TXE340NfJVz-ExR_Ntg", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "dotted", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 889.0748352336636, + "y": 123.74195389394822, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 246.3999633789062, + "height": 222.400146484375, + "seed": 779618448, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "OT5Pjyf0K1R184eX3jIFY" + }, + { + "id": "3FaeA6gbXhf3lFDHI-1by", + "type": "arrow" + } + ], + "updated": 1726050163287, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 830, + "versionNonce": 1501684336, + "index": "Zv", + "isDeleted": false, + "id": "OT5Pjyf0K1R184eX3jIFY", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 903.354940824484, + "y": 128.74195389394822, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 217.83975219726562, + "height": 25, + "seed": 1367897744, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1726046374765, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "transaction validation", + "textAlign": "center", + "verticalAlign": "top", + "containerId": "46TXE340NfJVz-ExR_Ntg", + "originalText": "transaction validation", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "Jq37eLzJFtAphIByXXJ8J", + "type": "rectangle", + "x": 883.8749450969449, + "y": 31.542155309963846, + "width": 244.7999877929688, + "height": 64.00006103515625, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "a0", + "roundness": { + "type": 3 + }, + "seed": 2100957808, + "version": 543, + "versionNonce": 68680848, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "KxKd8R05CEMH2kYjmvG1K" + } + ], + "updated": 1726046848776, + "link": null, + "locked": false + }, + { + "id": "KxKd8R05CEMH2kYjmvG1K", + "type": "text", + "x": 921.6050400066129, + "y": 51.04218582754197, + "width": 169.3397979736328, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "a0V", + "roundness": null, + "seed": 1007192208, + "version": 446, + "versionNonce": 591404656, + "isDeleted": false, + "boundElements": null, + "updated": 1726045175596, + "link": null, + "locked": false, + "text": "header validation", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "Jq37eLzJFtAphIByXXJ8J", + "originalText": "header validation", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "6d5F4qlkBsianjtDW-DFS", + "type": "rectangle", + "x": 515.675024442648, + "y": -33.85789962167678, + "width": 165.5999755859375, + "height": 93.60000610351562, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aB", + "roundness": { + "type": 3 + }, + "seed": 2066883696, + "version": 728, + "versionNonce": 812569200, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "iiOg1LCjOHC5ozMm407bS" + }, + { + "id": "UgL2Tuek8HSxxStjQYB0q", + "type": "arrow" + }, + { + "id": "0mlUBxdk542WH_plyugqH", + "type": "arrow" + } + ], + "updated": 1726051262809, + "link": null, + "locked": false + }, + { + "id": "iiOg1LCjOHC5ozMm407bS", + "type": "text", + "x": 555.2750534343472, + "y": 0.44210343008103337, + "width": 86.39991760253906, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aC", + "roundness": null, + "seed": 1322088560, + "version": 688, + "versionNonce": 1716037744, + "isDeleted": false, + "boundElements": null, + "updated": 1726051262811, + "link": null, + "locked": false, + "text": "full node", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "6d5F4qlkBsianjtDW-DFS", + "originalText": "full node", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "ia3NpRXin76YPLtFP4Yl3", + "type": "rectangle", + "x": 919.6749939250699, + "y": 284.94208817129197, + "width": 195.20001220703125, + "height": 41.600067138671875, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aC8", + "roundness": { + "type": 3 + }, + "seed": 379577488, + "version": 617, + "versionNonce": 1085809296, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "WnFHta4VWF5MQyUmBCxW8" + } + ], + "updated": 1726046864018, + "link": null, + "locked": false + }, + { + "id": "WnFHta4VWF5MQyUmBCxW8", + "type": "text", + "x": 937.6250976848355, + "y": 293.2421217406279, + "width": 159.2998046875, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aCG", + "roundness": null, + "seed": 726540944, + "version": 588, + "versionNonce": 129134224, + "isDeleted": false, + "boundElements": null, + "updated": 1726046408098, + "link": null, + "locked": false, + "text": "script validation", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "ia3NpRXin76YPLtFP4Yl3", + "originalText": "script validation", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 904, + "versionNonce": 260106864, + "index": "aCd", + "isDeleted": false, + "id": "Ss1_PWLNhrSWpBTmOopDV", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 916.6747192668668, + "y": 226.94225601797166, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 195.20001220703125, + "height": 44.000091552734375, + "seed": 1266475120, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "cQiXWAbergoCUDlg7BMCc" + }, + { + "id": "adQ0gG4ND7sWaO3NgRvCg", + "type": "arrow" + } + ], + "updated": 1726046859355, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 893, + "versionNonce": 1380229232, + "index": "aCl", + "isDeleted": false, + "id": "cQiXWAbergoCUDlg7BMCc", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 926.8748230266324, + "y": 236.44230179433885, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 174.7998046875, + "height": 25, + "seed": 1273451120, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1726046394358, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "UTXO verification", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "Ss1_PWLNhrSWpBTmOopDV", + "originalText": "UTXO verification", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 1127, + "versionNonce": 107678352, + "index": "aD", + "isDeleted": false, + "id": "Y-atAe5CEQudIM5qB3LGl", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 510.67520754811676, + "y": 198.34206680898728, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 165.5999755859375, + "height": 93.60000610351562, + "seed": 879980688, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "puxQis3GvrmQmj6Ewshuy" + }, + { + "id": "adQ0gG4ND7sWaO3NgRvCg", + "type": "arrow" + }, + { + "id": "UgL2Tuek8HSxxStjQYB0q", + "type": "arrow" + } + ], + "updated": 1726051280505, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1122, + "versionNonce": 1721914512, + "index": "aE", + "isDeleted": false, + "id": "puxQis3GvrmQmj6Ewshuy", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 538.8352493571988, + "y": 220.1420698607451, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 109.27989196777344, + "height": 50, + "seed": 1406590608, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1726051280506, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "utreexo\nbridge node", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "Y-atAe5CEQudIM5qB3LGl", + "originalText": "utreexo\nbridge node", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "adQ0gG4ND7sWaO3NgRvCg", + "type": "arrow", + "x": 677.2751831340543, + "y": 249.72548691501987, + "width": 138.79955291748047, + "height": 0.9433040090914915, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aF", + "roundness": { + "type": 2 + }, + "seed": 274845296, + "version": 2082, + "versionNonce": 2009806992, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "0FIupR64RF-AbNbrvCDwP" + } + ], + "updated": 1726051280506, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 138.79955291748047, + -0.9433040090914915 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "Y-atAe5CEQudIM5qB3LGl", + "focus": 0.10879727040177857, + "gap": 1, + "fixedPoint": null + }, + "endBinding": { + "elementId": "OlQhyNzC4xYaxYiMVIpNp", + "focus": -0.41810056413000074, + "gap": 3.0001602172851562, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "0FIupR64RF-AbNbrvCDwP", + "type": "text", + "x": 1230.2597323995374, + "y": 173.66878046063067, + "width": 76.0399169921875, + "height": 75, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aG", + "roundness": null, + "seed": 452208272, + "version": 32, + "versionNonce": 1394634864, + "isDeleted": false, + "boundElements": null, + "updated": 1726045282081, + "link": null, + "locked": false, + "text": "utxo\ninclusion\nproofs", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "adQ0gG4ND7sWaO3NgRvCg", + "originalText": "utxo\ninclusion\nproofs", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "UgL2Tuek8HSxxStjQYB0q", + "type": "arrow", + "x": 602.359464326293, + "y": 60.742106481838846, + "width": 3.252438008386207, + "height": 135.59994506835938, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aH", + "roundness": { + "type": 2 + }, + "seed": 232236176, + "version": 1675, + "versionNonce": 1760929424, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "lzW_E-Dknz3Cjp3-7IVvd" + } + ], + "updated": 1726051280506, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -3.252438008386207, + 135.59994506835938 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "6d5F4qlkBsianjtDW-DFS", + "focus": -0.0848461298687917, + "gap": 1, + "fixedPoint": null + }, + "endBinding": { + "elementId": "Y-atAe5CEQudIM5qB3LGl", + "focus": 0.053160184157585534, + "gap": 2.0000152587890625, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "lzW_E-Dknz3Cjp3-7IVvd", + "type": "text", + "x": 1339.8186975423196, + "y": 63.542170568752894, + "width": 57.27995300292969, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aHV", + "roundness": null, + "seed": 1272586896, + "version": 8, + "versionNonce": 480416400, + "isDeleted": false, + "boundElements": null, + "updated": 1726043762970, + "link": null, + "locked": false, + "text": "blocks", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "UgL2Tuek8HSxxStjQYB0q", + "originalText": "blocks", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "0mlUBxdk542WH_plyugqH", + "type": "arrow", + "x": 682.2750000285855, + "y": 12.953114543529589, + "width": 136.4517173655363, + "height": 1.7043832129644851, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aI", + "roundness": { + "type": 2 + }, + "seed": 1104431216, + "version": 1752, + "versionNonce": 1020327536, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "vZTRp78c_rn0-LAvcVhkn" + } + ], + "updated": 1726051262810, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 136.4517173655363, + -1.7043832129644851 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "6d5F4qlkBsianjtDW-DFS", + "focus": 0.022112512524973975, + "gap": 1, + "fixedPoint": null + }, + "endBinding": { + "elementId": "OlQhyNzC4xYaxYiMVIpNp", + "focus": 0.6359857359815234, + "gap": 1, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "vZTRp78c_rn0-LAvcVhkn", + "type": "text", + "x": 1138.8349441814175, + "y": -64.95781417245803, + "width": 57.27995300292969, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aJ", + "roundness": null, + "seed": 349960816, + "version": 8, + "versionNonce": 1181125232, + "isDeleted": false, + "boundElements": null, + "updated": 1726043727503, + "link": null, + "locked": false, + "text": "blocks", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "0mlUBxdk542WH_plyugqH", + "originalText": "blocks", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "3FaeA6gbXhf3lFDHI-1by", + "type": "arrow", + "x": 1181.1332952764878, + "y": 267.5422163451201, + "width": 71.54169864858204, + "height": 1.567668477541588, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "ah", + "roundness": { + "type": 2 + }, + "seed": 2089958032, + "version": 934, + "versionNonce": 137755792, + "isDeleted": false, + "boundElements": null, + "updated": 1726051175901, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 71.54169864858204, + -1.567668477541588 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "p1SkBd3U9KUtb31g2b5og", + "focus": 0.5321123566425469, + "gap": 28.25822810923046, + "fixedPoint": null + }, + "endBinding": { + "elementId": "meCDK-TD6HL11SHWrQCBW", + "focus": -0.0881613568239664, + "gap": 1, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "Sx7Xvkm8n1gPTX2MebqV0", + "type": "rectangle", + "x": 896.6748413371793, + "y": -334.25786300058303, + "width": 180.800048828125, + "height": 56.000030517578125, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffd43b", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "ai", + "roundness": { + "type": 3 + }, + "seed": 1513587312, + "version": 391, + "versionNonce": 474861200, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "BNjgoH0KcjIxXt9pYsPgf" + }, + { + "id": "IwaIfRpdALQBDgV0u-ATE", + "type": "arrow" + }, + { + "id": "zr6A3arcQYrb0Em0BgkHX", + "type": "arrow" + } + ], + "updated": 1726047038018, + "link": null, + "locked": false + }, + { + "id": "BNjgoH0KcjIxXt9pYsPgf", + "type": "text", + "x": 920.4449447917691, + "y": -318.75784774179397, + "width": 133.2598419189453, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aiV", + "roundness": null, + "seed": 94841456, + "version": 273, + "versionNonce": 1286962320, + "isDeleted": false, + "boundElements": null, + "updated": 1726047038018, + "link": null, + "locked": false, + "text": "stark verifier", + "fontSize": 20, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "Sx7Xvkm8n1gPTX2MebqV0", + "originalText": "stark verifier", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 870, + "versionNonce": 957720720, + "index": "as", + "isDeleted": false, + "id": "A7N4kLQMptJOkqU5E4DfL", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "dotted", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 821.6749328899136, + "y": -232.65779586191115, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 335.19995117187506, + "height": 118.39990234374997, + "seed": 1604022928, + "groupIds": [ + "t-XPndLuq3N4YvRhUk6XX" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "W-a8bRzcGmPEjXd4jALkn" + }, + { + "id": "zr6A3arcQYrb0Em0BgkHX", + "type": "arrow" + }, + { + "id": "zap4kyaz0rdo0-hRwtXJT", + "type": "arrow" + } + ], + "updated": 1726047035918, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 689, + "versionNonce": 2003965584, + "index": "at", + "isDeleted": false, + "id": "W-a8bRzcGmPEjXd4jALkn", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 953.0649551677457, + "y": -227.65779586191115, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 72.41990661621094, + "height": 25, + "seed": 514760848, + "groupIds": [ + "t-XPndLuq3N4YvRhUk6XX" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1726047035918, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 5, + "text": "verified", + "textAlign": "center", + "verticalAlign": "top", + "containerId": "A7N4kLQMptJOkqU5E4DfL", + "originalText": "verified", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 999, + "versionNonce": 938795152, + "index": "au", + "isDeleted": false, + "id": "xiLjXbKFxuf582YFoRlCJ", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 838.8151754298465, + "y": -195.95775313730178, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 143.31571977535447, + "height": 63.19996643066406, + "seed": 791416464, + "groupIds": [ + "t-XPndLuq3N4YvRhUk6XX" + ], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "id": "Qn4GW_gGfSRHpCZs3FwEn", + "type": "text" + } + ], + "updated": 1726047035918, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 827, + "versionNonce": 1168789136, + "index": "av", + "isDeleted": false, + "id": "Qn4GW_gGfSRHpCZs3FwEn", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 854.5530905543401, + "y": -176.85776992196975, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 111.83988952636719, + "height": 25, + "seed": 1774959760, + "groupIds": [ + "t-XPndLuq3N4YvRhUk6XX" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1726047035918, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 5, + "text": "chain state", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "xiLjXbKFxuf582YFoRlCJ", + "originalText": "chain state", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 1392, + "versionNonce": 377617552, + "index": "aw", + "isDeleted": false, + "id": "wDJ5UcgOitmQVb6wFc-BV", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 996.8661636121401, + "y": -195.55771346445022, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 145.49011817706395, + "height": 64, + "seed": 1346742928, + "groupIds": [ + "t-XPndLuq3N4YvRhUk6XX" + ], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "id": "axqPpvy7aOZU_TExH_LMz", + "type": "text" + } + ], + "updated": 1726047035918, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1142, + "versionNonce": 204728976, + "index": "ax", + "isDeleted": false, + "id": "axqPpvy7aOZU_TExH_LMz", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1009.6212706132698, + "y": -188.55771346445022, + "strokeColor": "#1e1e1e", + "backgroundColor": "#b2f2bb", + "width": 119.97990417480469, + "height": 50, + "seed": 1834080400, + "groupIds": [ + "t-XPndLuq3N4YvRhUk6XX" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1726047035918, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 5, + "text": "utxo merkle \naccumulator", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "wDJ5UcgOitmQVb6wFc-BV", + "originalText": "utxo merkle accumulator", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 1265, + "versionNonce": 1064197776, + "index": "azG", + "isDeleted": false, + "id": "meCDK-TD6HL11SHWrQCBW", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "dotted", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1252.0749573039761, + "y": 150.14237503652635, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ebfbee", + "width": 187.99987792968759, + "height": 208.7998046875, + "seed": 732126832, + "groupIds": [ + "FzZYbLV792S3RtinrAqt8" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "wJiOgag0fhKyd-7ulo941" + }, + { + "id": "3FaeA6gbXhf3lFDHI-1by", + "type": "arrow" + } + ], + "updated": 1726051167308, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1068, + "versionNonce": 1345583760, + "index": "azV", + "isDeleted": false, + "id": "wJiOgag0fhKyd-7ulo941", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1319.084921293234, + "y": 155.14237503652635, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ebfbee", + "width": 53.979949951171875, + "height": 25, + "seed": 512626800, + "groupIds": [ + "FzZYbLV792S3RtinrAqt8" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1726051167309, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 5, + "text": "proof", + "textAlign": "center", + "verticalAlign": "top", + "containerId": "meCDK-TD6HL11SHWrQCBW", + "originalText": "proof", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 1284, + "versionNonce": 2062952592, + "index": "azl", + "isDeleted": false, + "id": "6MJcYEo6mHeF_YEA28iJO", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1274.815297500159, + "y": 195.24244217519822, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 143.31571977535447, + "height": 63.19996643066406, + "seed": 89293424, + "groupIds": [ + "FzZYbLV792S3RtinrAqt8" + ], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "id": "zjsEKV9bbiImLOha8078C", + "type": "text" + } + ], + "updated": 1726051167309, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1112, + "versionNonce": 692229776, + "index": "b00", + "isDeleted": false, + "id": "zjsEKV9bbiImLOha8078C", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1290.5532126246526, + "y": 214.34242539053025, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ebfbee", + "width": 111.83988952636719, + "height": 25, + "seed": 1052292208, + "groupIds": [ + "FzZYbLV792S3RtinrAqt8" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1726051167309, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 5, + "text": "chain state", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "6MJcYEo6mHeF_YEA28iJO", + "originalText": "chain state", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 1723, + "versionNonce": 1875985552, + "index": "b00V", + "isDeleted": false, + "id": "jOgsVLQFNDDfjLwkM1oUr", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1275.8662856824526, + "y": 273.8424330199248, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 145.49011817706395, + "height": 64, + "seed": 277390960, + "groupIds": [ + "FzZYbLV792S3RtinrAqt8" + ], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "id": "Gtil3CQd9GWRJfyo0XBFJ", + "type": "text" + } + ], + "updated": 1726051167309, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1474, + "versionNonce": 207237776, + "index": "b01", + "isDeleted": false, + "id": "Gtil3CQd9GWRJfyo0XBFJ", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1288.6213926835821, + "y": 280.8424330199248, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ebfbee", + "width": 119.97990417480469, + "height": 50, + "seed": 1200248944, + "groupIds": [ + "FzZYbLV792S3RtinrAqt8" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1726051167309, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 5, + "text": "utxo merkle \naccumulator", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "jOgsVLQFNDDfjLwkM1oUr", + "originalText": "utxo merkle accumulator", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "IwaIfRpdALQBDgV0u-ATE", + "type": "arrow", + "x": 696.0747131633511, + "y": -304.11763979415537, + "width": 199.02465149538898, + "height": 1.5402171029120382, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b06", + "roundness": { + "type": 2 + }, + "seed": 904018576, + "version": 686, + "versionNonce": 1950726256, + "isDeleted": false, + "boundElements": null, + "updated": 1726051209826, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 199.02465149538898, + -1.5402171029120382 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "cwLLnN-1jTMdIZNDEow_n", + "focus": -0.45026786372359473, + "gap": 1, + "fixedPoint": null + }, + "endBinding": { + "elementId": "Sx7Xvkm8n1gPTX2MebqV0", + "focus": 0.0038952289644372906, + "gap": 1.575476678439145, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "zr6A3arcQYrb0Em0BgkHX", + "type": "arrow", + "x": 982.5732480335655, + "y": -277.2578095948213, + "width": 0.48651040507729704, + "height": 38.999977111816406, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b07", + "roundness": { + "type": 2 + }, + "seed": 723379312, + "version": 293, + "versionNonce": 587904144, + "isDeleted": false, + "boundElements": null, + "updated": 1726047038040, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -0.48651040507729704, + 38.999977111816406 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "Sx7Xvkm8n1gPTX2MebqV0", + "focus": 0.04561855825192419, + "gap": 1.0000228881835938, + "fixedPoint": null + }, + "endBinding": { + "elementId": "A7N4kLQMptJOkqU5E4DfL", + "focus": -0.037986458919341964, + "gap": 5.600036621093764, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "zap4kyaz0rdo0-hRwtXJT", + "type": "arrow", + "x": 983.6910781344301, + "y": -113.25789351816118, + "width": 3.017949999096004, + "height": 42.20007324218753, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b08", + "roundness": { + "type": 2 + }, + "seed": 1327634032, + "version": 173, + "versionNonce": 2047248016, + "isDeleted": false, + "boundElements": null, + "updated": 1726047035985, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 3.017949999096004, + 42.20007324218753 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "A7N4kLQMptJOkqU5E4DfL", + "focus": 0.05755010789097818, + "gap": 1, + "fixedPoint": null + }, + "endBinding": { + "elementId": "OlQhyNzC4xYaxYiMVIpNp", + "focus": 0.015207863669545869, + "gap": 5.0001220703125, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "type": "rectangle", + "version": 675, + "versionNonce": 294525072, + "index": "b09", + "isDeleted": false, + "id": "-kMJn4t02d3BEj1iHbvsI", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 914.6749023723355, + "y": 169.74218277578416, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 195.20001220703125, + "height": 41.600067138671875, + "seed": 713915024, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "qODkEh4lm-W3hsbAvtR-i" + } + ], + "updated": 1726046854154, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 663, + "versionNonce": 50382448, + "index": "b0A", + "isDeleted": false, + "id": "qODkEh4lm-W3hsbAvtR-i", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 936.3549866008511, + "y": 178.0422163451201, + "strokeColor": "#1e1e1e", + "backgroundColor": "transparent", + "width": 151.83984375, + "height": 25, + "seed": 1310697616, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1726046421370, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "consensus rules", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "-kMJn4t02d3BEj1iHbvsI", + "originalText": "consensus rules", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "id": "6VvMekiLDQkruhQDgnoct", + "type": "text", + "x": 1139.4749206828824, + "y": -340.65779586191115, + "width": 49.21995544433594, + "height": 25, + "angle": 0, + "strokeColor": "#1e1e1e", + "backgroundColor": "#fff9db", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "dotted", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "b0C", + "roundness": null, + "seed": 380584560, + "version": 33, + "versionNonce": 1305454192, + "isDeleted": false, + "boundElements": null, + "updated": 1726047161439, + "link": null, + "locked": false, + "text": "Cairo", + "fontSize": 20, + "fontFamily": 5, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Cairo", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 1419, + "versionNonce": 1876825744, + "index": "b0D", + "isDeleted": false, + "id": "cwLLnN-1jTMdIZNDEow_n", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "dotted", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 508.47510378835113, + "y": -360.45772261972365, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ebfbee", + "width": 187.99987792968759, + "height": 208.7998046875, + "seed": 1914053264, + "groupIds": [ + "gKhb0zfr_4XXWP_0mOYtd" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "Hc1h69tP3l0GVZB4vPvCg" + }, + { + "id": "IwaIfRpdALQBDgV0u-ATE", + "type": "arrow" + } + ], + "updated": 1726051204516, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1221, + "versionNonce": 1459405968, + "index": "b0E", + "isDeleted": false, + "id": "Hc1h69tP3l0GVZB4vPvCg", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 575.485067777609, + "y": -355.45772261972365, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ebfbee", + "width": 53.979949951171875, + "height": 25, + "seed": 1850953872, + "groupIds": [ + "gKhb0zfr_4XXWP_0mOYtd" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1726051204516, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 5, + "text": "proof", + "textAlign": "center", + "verticalAlign": "top", + "containerId": "cwLLnN-1jTMdIZNDEow_n", + "originalText": "proof", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 1437, + "versionNonce": 2011226256, + "index": "b0F", + "isDeleted": false, + "id": "aNm6PI-DtRQWT2Sj0bi7s", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 531.215443984534, + "y": -315.3576554810518, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 143.31571977535447, + "height": 63.19996643066406, + "seed": 112901776, + "groupIds": [ + "gKhb0zfr_4XXWP_0mOYtd" + ], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "id": "uziA6oySDKPMBkhclY7Na", + "type": "text" + } + ], + "updated": 1726051204516, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1265, + "versionNonce": 672550544, + "index": "b0G", + "isDeleted": false, + "id": "uziA6oySDKPMBkhclY7Na", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 546.9533591090276, + "y": -296.25767226571975, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ebfbee", + "width": 111.83988952636719, + "height": 25, + "seed": 1006922896, + "groupIds": [ + "gKhb0zfr_4XXWP_0mOYtd" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1726051204516, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 5, + "text": "chain state", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "aNm6PI-DtRQWT2Sj0bi7s", + "originalText": "chain state", + "autoResize": true, + "lineHeight": 1.25 + }, + { + "type": "rectangle", + "version": 1876, + "versionNonce": 1265499280, + "index": "b0H", + "isDeleted": false, + "id": "ydKJB4ugsrqufvEqVHRk5", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 532.2664321668276, + "y": -236.75766463632522, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ffffff", + "width": 145.49011817706395, + "height": 64, + "seed": 937974416, + "groupIds": [ + "gKhb0zfr_4XXWP_0mOYtd" + ], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "id": "I1QEZkbQosDrXZjKyV4O5", + "type": "text" + } + ], + "updated": 1726051204516, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1627, + "versionNonce": 1134553744, + "index": "b0I", + "isDeleted": false, + "id": "I1QEZkbQosDrXZjKyV4O5", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 545.0215391679571, + "y": -229.75766463632522, + "strokeColor": "#1e1e1e", + "backgroundColor": "#ebfbee", + "width": 119.97990417480469, + "height": 50, + "seed": 756975760, + "groupIds": [ + "gKhb0zfr_4XXWP_0mOYtd" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1726051204516, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 5, + "text": "utxo merkle \naccumulator", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "ydKJB4ugsrqufvEqVHRk5", + "originalText": "utxo merkle accumulator", + "autoResize": true, + "lineHeight": 1.25 + } + ], + "appState": { + "gridSize": 20, + "gridStep": 5, + "gridModeEnabled": false, + "viewBackgroundColor": "#ffffff" + }, + "files": {} +} \ No newline at end of file diff --git a/docs/img/components.svg b/docs/img/components.svg new file mode 100644 index 00000000..0f42a0c9 --- /dev/null +++ b/docs/img/components.svg @@ -0,0 +1,17 @@ + + + + + + + + consensus validationblock validationtransaction validationheader validationfull nodescript validationUTXO verificationutreexobridge nodeutxoinclusionproofsblocksblocksstark verifierverifiedchain stateutxo merkle accumulatorproofchain stateutxo merkle accumulatorconsensus rulesCairoproofchain stateutxo merkle accumulator \ No newline at end of file From e5df914a69fe0d4b4a90f270e4995de1b42c1236 Mon Sep 17 00:00:00 2001 From: Mexes Date: Wed, 11 Sep 2024 13:52:13 +0100 Subject: [PATCH 3/6] feat: add Python linter and code formating checks to the CI (#175) --- .github/workflows/python-lint.yml | 31 +++++++++++++++++++++++++++++++ Scarb.toml | 1 + scripts/data/format_args.py | 30 ++++++++++++++++++------------ scripts/data/generate_data.py | 6 ++++-- scripts/data/requirements.txt | 5 ++++- scripts/misc/create_issues.py | 24 +++++++++++++++++------- 6 files changed, 75 insertions(+), 22 deletions(-) create mode 100644 .github/workflows/python-lint.yml diff --git a/.github/workflows/python-lint.yml b/.github/workflows/python-lint.yml new file mode 100644 index 00000000..120c8f8e --- /dev/null +++ b/.github/workflows/python-lint.yml @@ -0,0 +1,31 @@ +name: Python Lint and Formatting Check + +on: [push, pull_request] + +jobs: + lint: + name: Lint and Format Check + runs-on: ubuntu-latest + + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install flake8 black + + - name: Lint with flake8 + run: | + flake8 scripts/ --count --select=E9,F63,F7,F82 --show-source --statistics + flake8 scripts/ --count --exit-zero --max-complexity=10 --max-line-length=88 --statistics + + - name: Check code formatting with black + run: | + black --check scripts/ \ No newline at end of file diff --git a/Scarb.toml b/Scarb.toml index 8f063046..7ee245b7 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -8,6 +8,7 @@ regenerate_tests= "./scripts/data/regenerate_tests.sh" integration_tests = "scarb build && ./scripts/data/integration_tests.sh" client= "scarb build && ./scripts/data/client.sh" test = "scarb cairo-test && scarb run integration_tests" +lint = "flake8 scripts/ && black --check scripts/" [dependencies] diff --git a/scripts/data/format_args.py b/scripts/data/format_args.py index 9d3c18cd..9d054e8e 100644 --- a/scripts/data/format_args.py +++ b/scripts/data/format_args.py @@ -20,7 +20,7 @@ def serialize(obj): return 1 if obj else 0 elif isinstance(obj, int): # This covers u8, u16, u32, u64, u128, felt252 - assert(obj >= 0 and obj < 2 ** 252) + assert obj >= 0 and obj < 2**252 return obj elif isinstance(obj, str): if obj == "0" * 64: @@ -30,25 +30,27 @@ def serialize(obj): # TODO: there might still be collisions with hashes # Try to cast to int and then to low/high parts num = int(obj) - assert(num >= 0 and num < 2 ** 256) - lo = num % 2 ** 128 - hi = num // 2 ** 128 + assert num >= 0 and num < 2**256 + lo = num % 2**128 + hi = num // 2**128 return (lo, hi) - elif obj.startswith('0x'): + elif obj.startswith("0x"): # Split into 31-byte chunks and save the remainder src = bytes.fromhex(obj[2:]) num_chunks = len(src) // 31 main_len = num_chunks * 31 rem_len = len(src) - main_len - main = [int.from_bytes(src[i:i+31], 'big') for i in range(0, main_len, 31)] + main = [ + int.from_bytes(src[i : i + 31], "big") for i in range(0, main_len, 31) + ] # TODO: check if this is how byte31 is implemented - rem = int.from_bytes(src[main_len:].rjust(31, b'\x00'), 'big') + rem = int.from_bytes(src[main_len:].rjust(31, b"\x00"), "big") return tuple([len(main)] + main + [rem, rem_len]) else: # Reversed hex string into 4-byte words then into BE u32 - assert(len(obj) == 64) + assert len(obj) == 64 rev = list(reversed(bytes.fromhex(obj))) - return tuple(int.from_bytes(rev[i:i+4], 'big') for i in range(0, 32, 4)) + return tuple(int.from_bytes(rev[i : i + 4], "big") for i in range(0, 32, 4)) elif isinstance(obj, list): arr = list(map(serialize, obj)) return tuple([len(arr)] + arr) @@ -68,6 +70,7 @@ def flatten_tuples(src): :return: an object that can only contain integers and lists, top-level tuple converts to a list. """ res = [] + def append_obj(obj, to): if isinstance(obj, int): to.append(obj) @@ -81,6 +84,7 @@ def append_obj(obj, to): append_obj(item, to) else: raise NotImplementedError(obj) + append_obj(src, res) return res @@ -92,12 +96,14 @@ def format_cairo1_run(args: list) -> str: :param args: Python object containing already processed arguments. :return: Returns string with removed commas. """ + def format_item(item): if isinstance(item, list): arr = " ".join(map(format_item, item)) - return f'[{arr}]' + return f"[{arr}]" else: return str(item) + return format_item(args) @@ -106,12 +112,12 @@ def format_args(): Expects a single CLI argument containing file path. Output is compatible with the Scarb runner arguments format. """ - if (len(sys.argv) != 2): + if len(sys.argv) != 2: raise TypeError("Expected single argument") args = json.loads(Path(sys.argv[1]).read_text()) res = flatten_tuples(serialize(args)) print([res]) -if __name__ == '__main__': +if __name__ == "__main__": format_args() diff --git a/scripts/data/generate_data.py b/scripts/data/generate_data.py index aa4855f2..691a42e6 100755 --- a/scripts/data/generate_data.py +++ b/scripts/data/generate_data.py @@ -190,13 +190,15 @@ def format_coinbase_input(input: dict): "block_time": 0, "is_coinbase": False, }, - "witness": ["0x0000000000000000000000000000000000000000000000000000000000000000"], + "witness": [ + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], } def format_output(output: dict): """Formats transaction output according to the Cairo type.""" - value = (Decimal(str(output["value"])) * Decimal('100000000')).to_integral_value() + value = (Decimal(str(output["value"])) * Decimal("100000000")).to_integral_value() return { "value": int(value), "pk_script": f'0x{output["scriptPubKey"]["hex"]}', diff --git a/scripts/data/requirements.txt b/scripts/data/requirements.txt index ef487e06..4ce787d1 100644 --- a/scripts/data/requirements.txt +++ b/scripts/data/requirements.txt @@ -1 +1,4 @@ -requests==2.32.3 \ No newline at end of file +requests==2.32.3 +black==24.8.0 +flake8==7.1.1 +flake8-black==0.3.6 \ No newline at end of file diff --git a/scripts/misc/create_issues.py b/scripts/misc/create_issues.py index 4cd113ff..a6b88330 100644 --- a/scripts/misc/create_issues.py +++ b/scripts/misc/create_issues.py @@ -3,14 +3,20 @@ import sys import argparse + def create_issue(title, body, labels): cmd = [ - "gh", "issue", "create", - "--title", title, - "--body", body, - "--label", ",".join(labels) + "gh", + "issue", + "create", + "--title", + title, + "--body", + body, + "--label", + ",".join(labels), ] - + try: subprocess.run(cmd, check=True) print(f"Successfully created issue: {title}") @@ -19,8 +25,11 @@ def create_issue(title, body, labels): print(f"Error message: {e}") sys.exit(1) + def main(): - parser = argparse.ArgumentParser(description="Create GitHub issues from a JSON file.") + parser = argparse.ArgumentParser( + description="Create GitHub issues from a JSON file." + ) parser.add_argument("json_file", help="Path to the JSON file containing issue data") args = parser.parse_args() @@ -41,5 +50,6 @@ def main(): for issue in data["issues"]: create_issue(issue["title"], issue["body"], issue["labels"]) + if __name__ == "__main__": - main() \ No newline at end of file + main() From 7428d1f93c263ab9ca8005b87639b87e4c359b9f Mon Sep 17 00:00:00 2001 From: Michael Zaikin Date: Wed, 11 Sep 2024 20:14:26 +0100 Subject: [PATCH 4/6] Add new contributors (#182) --- .all-contributorsrc | 54 +++++++++++++++++++++++++++++++++++++++++++++ README.md | 3 +++ 2 files changed, 57 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index be74b079..0974e3de 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -144,6 +144,60 @@ "contributions": [ "code" ] + }, + { + "login": "Gerson2102", + "name": "Gerson", + "avatar_url": "https://avatars.githubusercontent.com/u/71728860?v=4", + "profile": "https://github.com/Gerson2102", + "contributions": [ + "code" + ] + }, + { + "login": "PavitraAgarwal21", + "name": "PavitraAgarwal21", + "avatar_url": "https://avatars.githubusercontent.com/u/85789615?v=4", + "profile": "https://github.com/PavitraAgarwal21", + "contributions": [ + "code" + ] + }, + { + "login": "bloomingpeach", + "name": "Nguyen Dao", + "avatar_url": "https://avatars.githubusercontent.com/u/177087057?v=4", + "profile": "https://github.com/bloomingpeach", + "contributions": [ + "code" + ] + }, + { + "login": "od-hunter", + "name": "Hunter001", + "avatar_url": "https://avatars.githubusercontent.com/u/146340502?v=4", + "profile": "https://github.com/od-hunter", + "contributions": [ + "code" + ] + }, + { + "login": "feltroidprime", + "name": "feltroid Prime", + "avatar_url": "https://avatars.githubusercontent.com/u/96737978?v=4", + "profile": "https://github.com/feltroidprime", + "contributions": [ + "code" + ] + }, + { + "login": "mexes20", + "name": "Mexes", + "avatar_url": "https://avatars.githubusercontent.com/u/127276944?v=4", + "profile": "https://github.com/mexes20", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 1d29ed7d..92ca81be 100644 --- a/README.md +++ b/README.md @@ -217,6 +217,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Gerson
Gerson

💻 PavitraAgarwal21
PavitraAgarwal21

💻 bloomingpeach
Nguyen Dao

💻 + od-hunter
Hunter001

💻 + feltroidprime
feltroid Prime

💻 + mexes20
Mexes

💻 From d7c6006fc93836abd87fd956d1032b07e3b5179a Mon Sep 17 00:00:00 2001 From: Michael Zaikin Date: Thu, 12 Sep 2024 10:07:51 +0100 Subject: [PATCH 5/6] Refactor project into a workspace (#169) --- .gitignore | 2 +- README.md | 28 ++---------- Scarb.lock | 16 ++++++- Scarb.toml | 23 +++++----- packages/client/README.md | 45 +++++++++++++++++++ packages/client/Scarb.toml | 16 +++++++ packages/client/src/lib.cairo | 4 ++ {src => packages/client/src}/main.cairo | 4 +- {src => packages/client/src}/test.cairo | 4 +- .../client/tests}/data/full_169.json | 0 .../client/tests}/data/full_757738.json | 0 .../client/tests}/data/light_150012.json | 0 .../client/tests}/data/light_169.json | 0 .../client/tests}/data/light_2015.json | 0 .../client/tests}/data/light_209999.json | 0 .../client/tests}/data/light_24834.json | 0 .../client/tests}/data/light_32255.json | 0 .../client/tests}/data/light_478557.json | 0 .../client/tests}/data/light_481823.json | 0 .../client/tests}/data/light_491406.json | 0 .../client/tests}/data/light_57042.json | 0 .../client/tests}/data/light_629999.json | 0 .../client/tests}/data/light_709631.json | 0 .../client/tests}/data/light_757738.json | 0 .../client/tests}/data/light_757752.json | 0 .../client/tests}/data/light_774627.json | 0 .../client/tests}/data/light_839999.json | 0 packages/consensus/README.md | 8 ++++ packages/consensus/Scarb.toml | 14 ++++++ {src => packages/consensus/src}/codec.cairo | 6 +-- packages/consensus/src/lib.cairo | 17 +++++++ .../consensus/src}/types/block.cairo | 10 ++--- .../consensus/src}/types/chain_state.cairo | 2 +- .../consensus/src}/types/transaction.cairo | 4 +- .../consensus/src}/types/utreexo.cairo | 0 .../consensus/src}/types/utxo_set.cairo | 0 .../consensus/src}/validation/block.cairo | 2 +- .../consensus/src}/validation/coinbase.cairo | 4 +- .../src}/validation/difficulty.cairo | 2 +- .../consensus/src}/validation/locktime.cairo | 2 +- .../consensus/src}/validation/timestamp.cairo | 0 .../src}/validation/transaction.cairo | 2 +- .../consensus/src}/validation/work.cairo | 2 +- packages/utils/README.md | 3 ++ packages/utils/Scarb.toml | 11 +++++ .../utils/src}/bit_shifts.cairo | 0 .../utils/src}/bytearray.cairo | 0 {src/utils => packages/utils/src}/hash.cairo | 2 +- {src/utils => packages/utils/src}/hex.cairo | 4 +- packages/utils/src/lib.cairo | 9 ++++ .../utils/src}/merkle_tree.cairo | 2 +- .../utils/src}/numeric.cairo | 0 .../utils => packages/utils/src}/sha256.cairo | 2 +- scripts/data/client.sh | 12 ++--- scripts/data/integration_tests.sh | 10 +++-- scripts/data/regenerate_tests.sh | 7 +-- src/lib.cairo | 35 --------------- 57 files changed, 199 insertions(+), 115 deletions(-) create mode 100644 packages/client/README.md create mode 100644 packages/client/Scarb.toml create mode 100644 packages/client/src/lib.cairo rename {src => packages/client/src}/main.cairo (88%) rename {src => packages/client/src}/test.cairo (94%) rename {tests => packages/client/tests}/data/full_169.json (100%) rename {tests => packages/client/tests}/data/full_757738.json (100%) rename {tests => packages/client/tests}/data/light_150012.json (100%) rename {tests => packages/client/tests}/data/light_169.json (100%) rename {tests => packages/client/tests}/data/light_2015.json (100%) rename {tests => packages/client/tests}/data/light_209999.json (100%) rename {tests => packages/client/tests}/data/light_24834.json (100%) rename {tests => packages/client/tests}/data/light_32255.json (100%) rename {tests => packages/client/tests}/data/light_478557.json (100%) rename {tests => packages/client/tests}/data/light_481823.json (100%) rename {tests => packages/client/tests}/data/light_491406.json (100%) rename {tests => packages/client/tests}/data/light_57042.json (100%) rename {tests => packages/client/tests}/data/light_629999.json (100%) rename {tests => packages/client/tests}/data/light_709631.json (100%) rename {tests => packages/client/tests}/data/light_757738.json (100%) rename {tests => packages/client/tests}/data/light_757752.json (100%) rename {tests => packages/client/tests}/data/light_774627.json (100%) rename {tests => packages/client/tests}/data/light_839999.json (100%) create mode 100644 packages/consensus/README.md create mode 100644 packages/consensus/Scarb.toml rename {src => packages/consensus/src}/codec.cairo (99%) create mode 100644 packages/consensus/src/lib.cairo rename {src => packages/consensus/src}/types/block.cairo (96%) rename {src => packages/consensus/src}/types/chain_state.cairo (99%) rename {src => packages/consensus/src}/types/transaction.cairo (98%) rename {src => packages/consensus/src}/types/utreexo.cairo (100%) rename {src => packages/consensus/src}/types/utxo_set.cairo (100%) rename {src => packages/consensus/src}/validation/block.cairo (96%) rename {src => packages/consensus/src}/validation/coinbase.cairo (99%) rename {src => packages/consensus/src}/validation/difficulty.cairo (99%) rename {src => packages/consensus/src}/validation/locktime.cairo (99%) rename {src => packages/consensus/src}/validation/timestamp.cairo (100%) rename {src => packages/consensus/src}/validation/transaction.cairo (99%) rename {src => packages/consensus/src}/validation/work.cairo (99%) create mode 100644 packages/utils/README.md create mode 100644 packages/utils/Scarb.toml rename {src/utils => packages/utils/src}/bit_shifts.cairo (100%) rename {src/utils => packages/utils/src}/bytearray.cairo (100%) rename {src/utils => packages/utils/src}/hash.cairo (99%) rename {src/utils => packages/utils/src}/hex.cairo (97%) create mode 100644 packages/utils/src/lib.cairo rename {src/utils => packages/utils/src}/merkle_tree.cairo (99%) rename {src/utils => packages/utils/src}/numeric.cairo (100%) rename {src/utils => packages/utils/src}/sha256.cairo (97%) delete mode 100644 src/lib.cairo diff --git a/.gitignore b/.gitignore index b2c7f1ca..2fb090f2 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,4 @@ Cargo.lock .python-version __pycache__ -.raito \ No newline at end of file +.client_cache/ \ No newline at end of file diff --git a/README.md b/README.md index 92ca81be..76b31c63 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Extend light client with partial transaction validation, but without UTXO checks Tasks: -* [ ] reassess validation check list (analyze Bitcoin core codebase) +* [x] reassess validation check list (analyze Bitcoin core codebase) * [x] generate & run integration tests e2e instead of Cairo codegen * [x] transaction ID calculation * [x] transaction root computation @@ -135,40 +135,18 @@ Raito is a reference to Light Yagami (夜神月, Yagami Raito) from the manga/an ## Usage -This will compile all the components: +This will compile all the packages: ```bash scarb build ``` -This will run unit and integration tests: +This will run tests for all the packages: ```bash scarb test ``` -For integration tests ony: - -```bash -scarb run integration_tests -``` - -Run for specific test file(s): - -```bash -scarb run integration_tests tests/data/light_481823.json -``` - -Re-generate integration test data: - -```base -scarb run regenerate_tests --force -``` - -* Without `--force` flag only non-existent files will be created -* Files are located in [tests/data/](https://github.com/keep-starknet-strange/raito/blob/main/tests/data) -* If you want to add a new test case, edit [scripts/data/regenerate_tests.sh](https://github.com/keep-starknet-strange/raito/blob/main/scripts/data/regenerate_tests.sh) - ## Build dependencies Install necessary packages required by Python scripts: diff --git a/Scarb.lock b/Scarb.lock index a0e0284f..8beea944 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -2,5 +2,19 @@ version = 1 [[package]] -name = "raito" +name = "client" +version = "0.1.0" +dependencies = [ + "consensus", +] + +[[package]] +name = "consensus" +version = "0.1.0" +dependencies = [ + "utils", +] + +[[package]] +name = "utils" version = "0.1.0" diff --git a/Scarb.toml b/Scarb.toml index 7ee245b7..95012dcc 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -1,16 +1,13 @@ -[package] -name = "raito" -version = "0.1.0" -edition = "2024_07" - -[scripts] -regenerate_tests= "./scripts/data/regenerate_tests.sh" -integration_tests = "scarb build && ./scripts/data/integration_tests.sh" -client= "scarb build && ./scripts/data/client.sh" -test = "scarb cairo-test && scarb run integration_tests" -lint = "flake8 scripts/ && black --check scripts/" +[workspace] +members = ["packages/*"] -[dependencies] +[workspace.package] +description = "Bitcoin ZK client." +cairo-version = "2.8.2" +version = "0.1.0" +readme = "README.md" +repository = "https://github.com/keep-starknet-strange/raito" +license-file = "LICENSE" -[dev-dependencies] +[workspace.dependencies] cairo_test = "2.8.0" diff --git a/packages/client/README.md b/packages/client/README.md new file mode 100644 index 00000000..f99b53d9 --- /dev/null +++ b/packages/client/README.md @@ -0,0 +1,45 @@ +# Bitcoin client in Cairo + +This package is a standalone Cairo program (outside of Starknet context) that implements a Bitcoin client which can work in two modes: +- Light mode: block header validation only +- Full mode: full Bitcoin consensus validation + +## Usage + +```sh +# You have to be in the "packages/client" directory +scarb run client START_HEIGHT END_HEIGHT BATCH_SIZE MODE STRATEGY +``` + +Client expects the following arguments: +* `START_HEIGHT` height of the initial chain state +* `END_HEIGHT` height of the final (resulting) chain state +* `BATCH_SIZE` number of blocks applied per single program run +* `MODE` either `light` or `full` (default is light) +* `STRATEGY` either `sequential` or `random` (default is sequential) + +## Integration tests + +In order to run integration tests: + +```sh +scarb test +``` + +Run a specific test file (or several files): + +```sh +# You have to be in the "packages/client" directory +scarb test tests/data/light_481823.json +``` + +Re-generate integration test data: + +```sh +# You have to be in the "packages/client" directory +scarb run regenerate_tests --force +``` + +If you want to just add a new test case, edit `scripts/data/regenerate_tests.sh` and run without `--force` flag. + +You can also add/remove ignored scenarios, check out `scripts/data/regenerate_tests.sh` as well. diff --git a/packages/client/Scarb.toml b/packages/client/Scarb.toml new file mode 100644 index 00000000..b2189723 --- /dev/null +++ b/packages/client/Scarb.toml @@ -0,0 +1,16 @@ +[package] +name = "client" +version = "0.1.0" +edition = "2024_07" + +[dependencies] +consensus = { path = "../consensus" } + +[dev-dependencies] +cairo_test.workspace = true + +[scripts] +test = "scarb build && ../../scripts/data/integration_tests.sh" +regenerate_tests= "../../scripts/data/regenerate_tests.sh" +client = "scarb build && ../../scripts/data/client.sh" +lint = "flake8 scripts/ && black --check scripts/ && scarb fmt" diff --git a/packages/client/src/lib.cairo b/packages/client/src/lib.cairo new file mode 100644 index 00000000..c1bd37d3 --- /dev/null +++ b/packages/client/src/lib.cairo @@ -0,0 +1,4 @@ +mod main; +// TODO: scarb cairo-run should support "features" argument +// so that we can conditionally compile this module +mod test; diff --git a/src/main.cairo b/packages/client/src/main.cairo similarity index 88% rename from src/main.cairo rename to packages/client/src/main.cairo index 714279e5..34c65fc2 100644 --- a/src/main.cairo +++ b/packages/client/src/main.cairo @@ -1,5 +1,5 @@ -use crate::types::block::Block; -use crate::types::chain_state::{ChainState, BlockValidator}; +use consensus::types::block::Block; +use consensus::types::chain_state::{ChainState, BlockValidator}; /// Raito program arguments. #[derive(Serde)] diff --git a/src/test.cairo b/packages/client/src/test.cairo similarity index 94% rename from src/test.cairo rename to packages/client/src/test.cairo index da9f7d80..a8d03acf 100644 --- a/src/test.cairo +++ b/packages/client/src/test.cairo @@ -1,5 +1,5 @@ -use crate::types::block::Block; -use crate::types::chain_state::{ChainState, BlockValidator}; +use consensus::types::block::Block; +use consensus::types::chain_state::{ChainState, BlockValidator}; use core::testing::get_available_gas; /// Integration testing program arguments. diff --git a/tests/data/full_169.json b/packages/client/tests/data/full_169.json similarity index 100% rename from tests/data/full_169.json rename to packages/client/tests/data/full_169.json diff --git a/tests/data/full_757738.json b/packages/client/tests/data/full_757738.json similarity index 100% rename from tests/data/full_757738.json rename to packages/client/tests/data/full_757738.json diff --git a/tests/data/light_150012.json b/packages/client/tests/data/light_150012.json similarity index 100% rename from tests/data/light_150012.json rename to packages/client/tests/data/light_150012.json diff --git a/tests/data/light_169.json b/packages/client/tests/data/light_169.json similarity index 100% rename from tests/data/light_169.json rename to packages/client/tests/data/light_169.json diff --git a/tests/data/light_2015.json b/packages/client/tests/data/light_2015.json similarity index 100% rename from tests/data/light_2015.json rename to packages/client/tests/data/light_2015.json diff --git a/tests/data/light_209999.json b/packages/client/tests/data/light_209999.json similarity index 100% rename from tests/data/light_209999.json rename to packages/client/tests/data/light_209999.json diff --git a/tests/data/light_24834.json b/packages/client/tests/data/light_24834.json similarity index 100% rename from tests/data/light_24834.json rename to packages/client/tests/data/light_24834.json diff --git a/tests/data/light_32255.json b/packages/client/tests/data/light_32255.json similarity index 100% rename from tests/data/light_32255.json rename to packages/client/tests/data/light_32255.json diff --git a/tests/data/light_478557.json b/packages/client/tests/data/light_478557.json similarity index 100% rename from tests/data/light_478557.json rename to packages/client/tests/data/light_478557.json diff --git a/tests/data/light_481823.json b/packages/client/tests/data/light_481823.json similarity index 100% rename from tests/data/light_481823.json rename to packages/client/tests/data/light_481823.json diff --git a/tests/data/light_491406.json b/packages/client/tests/data/light_491406.json similarity index 100% rename from tests/data/light_491406.json rename to packages/client/tests/data/light_491406.json diff --git a/tests/data/light_57042.json b/packages/client/tests/data/light_57042.json similarity index 100% rename from tests/data/light_57042.json rename to packages/client/tests/data/light_57042.json diff --git a/tests/data/light_629999.json b/packages/client/tests/data/light_629999.json similarity index 100% rename from tests/data/light_629999.json rename to packages/client/tests/data/light_629999.json diff --git a/tests/data/light_709631.json b/packages/client/tests/data/light_709631.json similarity index 100% rename from tests/data/light_709631.json rename to packages/client/tests/data/light_709631.json diff --git a/tests/data/light_757738.json b/packages/client/tests/data/light_757738.json similarity index 100% rename from tests/data/light_757738.json rename to packages/client/tests/data/light_757738.json diff --git a/tests/data/light_757752.json b/packages/client/tests/data/light_757752.json similarity index 100% rename from tests/data/light_757752.json rename to packages/client/tests/data/light_757752.json diff --git a/tests/data/light_774627.json b/packages/client/tests/data/light_774627.json similarity index 100% rename from tests/data/light_774627.json rename to packages/client/tests/data/light_774627.json diff --git a/tests/data/light_839999.json b/packages/client/tests/data/light_839999.json similarity index 100% rename from tests/data/light_839999.json rename to packages/client/tests/data/light_839999.json diff --git a/packages/consensus/README.md b/packages/consensus/README.md new file mode 100644 index 00000000..1c89183f --- /dev/null +++ b/packages/consensus/README.md @@ -0,0 +1,8 @@ +# Bitcoin consensus in Cairo + +This package is a Cairo library providing primitives for validating Bitcoin consensus. + +It is structured as follows: +* `types` module contains all Bitcoin specific entities (start your codebase tour with this folder) adapted for recursive verification; +* `validation` module contains most of the consensus validation logic; +* `codec` module contains implementation of Bitcoin binary codec for transaction types. diff --git a/packages/consensus/Scarb.toml b/packages/consensus/Scarb.toml new file mode 100644 index 00000000..7ca44ee0 --- /dev/null +++ b/packages/consensus/Scarb.toml @@ -0,0 +1,14 @@ +[package] +name = "consensus" +version = "0.1.0" +edition = "2024_07" + +[dependencies] +utils = { path = "../utils" } + +[dev-dependencies] +cairo_test.workspace = true + +[scripts] +# TODO: cairo lint +lint = "scarb fmt" diff --git a/src/codec.cairo b/packages/consensus/src/codec.cairo similarity index 99% rename from src/codec.cairo rename to packages/consensus/src/codec.cairo index d967b12e..ac5820d4 100644 --- a/src/codec.cairo +++ b/packages/consensus/src/codec.cairo @@ -1,7 +1,7 @@ //! Bitcoin binary codec traits, implementations, and helpers. use super::types::transaction::{Transaction, TxIn, TxOut, OutPoint}; -use raito::utils::hash::Digest; +use utils::hash::Digest; pub trait Encode { /// Encode using Bitcoin codec and append to the buffer. @@ -133,8 +133,8 @@ pub fn encode_compact_size(len: usize, ref dest: ByteArray) { } #[cfg(test)] mod tests { - use raito::types::transaction::{Transaction, TxIn, TxOut, OutPoint}; - use raito::utils::hex::{from_hex, hex_to_hash_rev}; + use utils::hex::{from_hex, hex_to_hash_rev}; + use crate::types::transaction::{Transaction, TxIn, TxOut, OutPoint}; use super::{Encode, TransactionCodec, encode_compact_size}; #[test] diff --git a/packages/consensus/src/lib.cairo b/packages/consensus/src/lib.cairo new file mode 100644 index 00000000..238e5741 --- /dev/null +++ b/packages/consensus/src/lib.cairo @@ -0,0 +1,17 @@ +pub mod validation { + pub mod difficulty; + pub mod coinbase; + pub mod locktime; + pub mod timestamp; + pub mod transaction; + pub mod work; + pub mod block; +} +pub mod codec; +pub mod types { + pub mod utreexo; + pub mod chain_state; + pub mod block; + pub mod transaction; + pub mod utxo_set; +} diff --git a/src/types/block.cairo b/packages/consensus/src/types/block.cairo similarity index 96% rename from src/types/block.cairo rename to packages/consensus/src/types/block.cairo index a404b19e..d9c13502 100644 --- a/src/types/block.cairo +++ b/packages/consensus/src/types/block.cairo @@ -2,9 +2,9 @@ //! //! The data is expected to be prepared in advance and passed as program arguments. -use crate::utils::hash::Digest; -use crate::utils::sha256::double_sha256_u32_array; -use crate::utils::numeric::u32_byte_reverse; +use utils::hash::Digest; +use utils::sha256::double_sha256_u32_array; +use utils::numeric::u32_byte_reverse; use super::transaction::Transaction; /// Represents a block in the blockchain. @@ -79,8 +79,8 @@ pub impl TransactionDataDefault of Default { #[cfg(test)] mod tests { use super::{Header, BlockHash}; - use raito::types::chain_state::ChainState; - use raito::utils::hash::Digest; + use crate::types::chain_state::ChainState; + use utils::hash::Digest; #[test] fn test_block_hash() { diff --git a/src/types/chain_state.cairo b/packages/consensus/src/types/chain_state.cairo similarity index 99% rename from src/types/chain_state.cairo rename to packages/consensus/src/types/chain_state.cairo index f1a50a11..58eb337b 100644 --- a/src/types/chain_state.cairo +++ b/packages/consensus/src/types/chain_state.cairo @@ -4,7 +4,7 @@ //! Chain state alone is not enough to do full block validation, however //! it is sufficient to validate block headers. -use crate::utils::hash::Digest; +use utils::hash::Digest; use crate::validation::{ difficulty::{validate_bits, adjust_difficulty}, coinbase::validate_coinbase, timestamp::{validate_timestamp, next_prev_timestamps}, diff --git a/src/types/transaction.cairo b/packages/consensus/src/types/transaction.cairo similarity index 98% rename from src/types/transaction.cairo rename to packages/consensus/src/types/transaction.cairo index 41471ca0..19027361 100644 --- a/src/types/transaction.cairo +++ b/packages/consensus/src/types/transaction.cairo @@ -3,7 +3,7 @@ //! Types are extended with extra information required for validation. //! The data is expected to be prepared in advance and passed as program arguments. -use crate::utils::{hash::Digest, bytearray::{ByteArraySnapHash, ByteArraySnapSerde}}; +use utils::{hash::Digest, bytearray::{ByteArraySnapHash, ByteArraySnapSerde}}; /// Represents a transaction. /// https://learnmeabitcoin.com/technical/transaction/ @@ -134,7 +134,7 @@ mod tests { use core::hash::HashStateExTrait; use core::poseidon::PoseidonTrait; use super::{OutPoint, TxOut}; - use crate::utils::{hash::{DigestTrait}}; + use utils::hash::{DigestTrait}; #[test] pub fn test_outpoint_poseidon_hash() { diff --git a/src/types/utreexo.cairo b/packages/consensus/src/types/utreexo.cairo similarity index 100% rename from src/types/utreexo.cairo rename to packages/consensus/src/types/utreexo.cairo diff --git a/src/types/utxo_set.cairo b/packages/consensus/src/types/utxo_set.cairo similarity index 100% rename from src/types/utxo_set.cairo rename to packages/consensus/src/types/utxo_set.cairo diff --git a/src/validation/block.cairo b/packages/consensus/src/validation/block.cairo similarity index 96% rename from src/validation/block.cairo rename to packages/consensus/src/validation/block.cairo index 5c13888c..fb32443c 100644 --- a/src/validation/block.cairo +++ b/packages/consensus/src/validation/block.cairo @@ -1,7 +1,7 @@ //! Block validation helpers. use crate::types::transaction::{Transaction}; use crate::codec::{Encode, TransactionCodec}; -use crate::utils::{hash::Digest, merkle_tree::merkle_root, sha256::double_sha256_byte_array}; +use utils::{hash::Digest, merkle_tree::merkle_root, sha256::double_sha256_byte_array}; use super::transaction::validate_transaction; const MAX_BLOCK_WEIGHT_LEGACY: usize = 1_000_000; diff --git a/src/validation/coinbase.cairo b/packages/consensus/src/validation/coinbase.cairo similarity index 99% rename from src/validation/coinbase.cairo rename to packages/consensus/src/validation/coinbase.cairo index 53baa73c..e6777a89 100644 --- a/src/validation/coinbase.cairo +++ b/packages/consensus/src/validation/coinbase.cairo @@ -3,7 +3,7 @@ //! https://learnmeabitcoin.com/technical/mining/coinbase-transaction/ use crate::types::transaction::{Transaction, TxIn}; -use crate::utils::{bit_shifts::shr, hash::Digest}; +use utils::{bit_shifts::shr, hash::Digest}; const BIP_34_BLOCK_HEIGHT: u32 = 227_836; const BIP_141_BLOCK_HEIGHT: u32 = 481_824; @@ -108,7 +108,7 @@ fn compute_block_reward(block_height: u32) -> u64 { #[cfg(test)] mod tests { use crate::types::transaction::{TxIn, TxOut, Transaction, OutPoint}; - use crate::utils::hex::from_hex; + use utils::hex::from_hex; use super::{ compute_block_reward, validate_coinbase, validate_coinbase_input, validate_coinbase_sig_script, validate_coinbase_witness diff --git a/src/validation/difficulty.cairo b/packages/consensus/src/validation/difficulty.cairo similarity index 99% rename from src/validation/difficulty.cairo rename to packages/consensus/src/validation/difficulty.cairo index 3e894691..1f4bf558 100644 --- a/src/validation/difficulty.cairo +++ b/packages/consensus/src/validation/difficulty.cairo @@ -4,7 +4,7 @@ //! - https://learnmeabitcoin.com/technical/mining/target/ //! - https://learnmeabitcoin.com/technical/block/bits/ -use crate::utils::{bit_shifts::{shl, shr}}; +use utils::{bit_shifts::{shl, shr}}; /// Maximum difficulty target allowed const MAX_TARGET: u256 = 0x00000000FFFF0000000000000000000000000000000000000000000000000000; diff --git a/src/validation/locktime.cairo b/packages/consensus/src/validation/locktime.cairo similarity index 99% rename from src/validation/locktime.cairo rename to packages/consensus/src/validation/locktime.cairo index a12c5a60..d930702c 100644 --- a/src/validation/locktime.cairo +++ b/packages/consensus/src/validation/locktime.cairo @@ -116,7 +116,7 @@ pub fn validate_relative_locktime( #[cfg(test)] mod tests { use crate::types::transaction::{TxIn, OutPoint, TxOut}; - use crate::utils::hex::{from_hex, hex_to_hash_rev}; + use utils::hex::{from_hex, hex_to_hash_rev}; use super::{validate_absolute_locktime, validate_relative_locktime}; // TODO: tests for invalid relative locktime diff --git a/src/validation/timestamp.cairo b/packages/consensus/src/validation/timestamp.cairo similarity index 100% rename from src/validation/timestamp.cairo rename to packages/consensus/src/validation/timestamp.cairo diff --git a/src/validation/transaction.cairo b/packages/consensus/src/validation/transaction.cairo similarity index 99% rename from src/validation/transaction.cairo rename to packages/consensus/src/validation/transaction.cairo index e1c887d8..d21a13d4 100644 --- a/src/validation/transaction.cairo +++ b/packages/consensus/src/validation/transaction.cairo @@ -97,7 +97,7 @@ fn validate_coinbase_maturity(output_height: u32, block_height: u32) -> Result<( #[cfg(test)] mod tests { use crate::types::transaction::{Transaction, TxIn, TxOut, OutPoint}; - use crate::utils::hex::{from_hex, hex_to_hash_rev}; + use utils::hex::{from_hex, hex_to_hash_rev}; use super::validate_transaction; // TODO: tests for coinbase maturity diff --git a/src/validation/work.cairo b/packages/consensus/src/validation/work.cairo similarity index 99% rename from src/validation/work.cairo rename to packages/consensus/src/validation/work.cairo index c9b272d8..cfaeaf9c 100644 --- a/src/validation/work.cairo +++ b/packages/consensus/src/validation/work.cairo @@ -1,6 +1,6 @@ //! Proof-of-work validation helpers. -use crate::utils::hash::Digest; +use utils::hash::Digest; /// Check if the work done (by calculating the block hash) satisfies the difficulty target. pub fn validate_proof_of_work(target: u256, block_hash: Digest) -> Result<(), ByteArray> { diff --git a/packages/utils/README.md b/packages/utils/README.md new file mode 100644 index 00000000..8d47ad55 --- /dev/null +++ b/packages/utils/README.md @@ -0,0 +1,3 @@ +# Common utilities + +This package contains common helpers that are not Bitcoin-specific. diff --git a/packages/utils/Scarb.toml b/packages/utils/Scarb.toml new file mode 100644 index 00000000..81475f48 --- /dev/null +++ b/packages/utils/Scarb.toml @@ -0,0 +1,11 @@ +[package] +name = "utils" +version = "0.1.0" +edition = "2024_07" + +[dev-dependencies] +cairo_test.workspace = true + +[scripts] +# TODO: cairo lint +lint = "scarb fmt" diff --git a/src/utils/bit_shifts.cairo b/packages/utils/src/bit_shifts.cairo similarity index 100% rename from src/utils/bit_shifts.cairo rename to packages/utils/src/bit_shifts.cairo diff --git a/src/utils/bytearray.cairo b/packages/utils/src/bytearray.cairo similarity index 100% rename from src/utils/bytearray.cairo rename to packages/utils/src/bytearray.cairo diff --git a/src/utils/hash.cairo b/packages/utils/src/hash.cairo similarity index 99% rename from src/utils/hash.cairo rename to packages/utils/src/hash.cairo index ceed2390..bfb4eed4 100644 --- a/src/utils/hash.cairo +++ b/packages/utils/src/hash.cairo @@ -112,7 +112,7 @@ pub impl DigestHash, +Drop> of Hash { #[cfg(test)] mod tests { - use crate::utils::hex::from_hex; + use crate::hex::from_hex; use super::Digest; #[test] diff --git a/src/utils/hex.cairo b/packages/utils/src/hex.cairo similarity index 97% rename from src/utils/hex.cairo rename to packages/utils/src/hex.cairo index 52830eed..736a403c 100644 --- a/src/utils/hex.cairo +++ b/packages/utils/src/hex.cairo @@ -1,5 +1,5 @@ //! Hex helpers -use raito::utils::hash::Digest; +use crate::hash::Digest; /// Get bytes from hex (base16) pub fn from_hex(hex_string: ByteArray) -> ByteArray { @@ -86,7 +86,7 @@ fn hex_char_to_nibble(hex_char: u8) -> u8 { #[cfg(test)] mod tests { use super::{from_hex, to_hex, hex_to_hash_rev}; - use raito::utils::hash::Digest; + use crate::hash::Digest; #[test] fn test_bytes_from_hex() { diff --git a/packages/utils/src/lib.cairo b/packages/utils/src/lib.cairo new file mode 100644 index 00000000..e85c50e3 --- /dev/null +++ b/packages/utils/src/lib.cairo @@ -0,0 +1,9 @@ +pub mod bytearray; +pub mod sha256; +pub mod hash; +pub mod bit_shifts; +pub mod merkle_tree; +pub mod numeric; + +#[cfg(target: 'test')] +pub mod hex; diff --git a/src/utils/merkle_tree.cairo b/packages/utils/src/merkle_tree.cairo similarity index 99% rename from src/utils/merkle_tree.cairo rename to packages/utils/src/merkle_tree.cairo index 18c967dd..026dd4b7 100644 --- a/src/utils/merkle_tree.cairo +++ b/packages/utils/src/merkle_tree.cairo @@ -29,7 +29,7 @@ pub fn merkle_root(ref hashes: Array) -> Digest { #[cfg(test)] mod tests { - use crate::utils::{hash::{Digest, U256IntoDigest}, hex::hex_to_hash_rev}; + use crate::{hash::{Digest, U256IntoDigest}, hex::hex_to_hash_rev}; use super::{merkle_root}; #[test] diff --git a/src/utils/numeric.cairo b/packages/utils/src/numeric.cairo similarity index 100% rename from src/utils/numeric.cairo rename to packages/utils/src/numeric.cairo diff --git a/src/utils/sha256.cairo b/packages/utils/src/sha256.cairo similarity index 97% rename from src/utils/sha256.cairo rename to packages/utils/src/sha256.cairo index 57d83951..707c69af 100644 --- a/src/utils/sha256.cairo +++ b/packages/utils/src/sha256.cairo @@ -36,7 +36,7 @@ pub fn double_sha256_u32_array(words: Array) -> Digest { #[cfg(test)] mod tests { - use crate::utils::{hex::from_hex, hash::Digest}; + use crate::{hex::from_hex, hash::Digest}; use super::{double_sha256_byte_array, double_sha256_u32_array, double_sha256_parent}; #[test] diff --git a/scripts/data/client.sh b/scripts/data/client.sh index a8235da9..5b39d1a2 100644 --- a/scripts/data/client.sh +++ b/scripts/data/client.sh @@ -1,9 +1,9 @@ #!/usr/bin/env bash -set -e; -set -o pipefail; +#set -e; +#set -o pipefail; -base_dir=".raito" +base_dir=".client_cache" start=${1:-0} end=${2:-100} @@ -23,11 +23,11 @@ run_client() { batch_file=${base_dir}/${mode}_${initial_height}_${num_blocks}.json if [ ! -f "$batch_file" ]; then - python scripts/data/generate_data.py $mode $initial_height $num_blocks true $batch_file + python ../../scripts/data/generate_data.py $mode $initial_height $num_blocks true $batch_file fi - arguments=$(python scripts/data/format_args.py $batch_file) - output=$(scarb cairo-run --no-build --function test "$arguments") + arguments=$(python ../../scripts/data/format_args.py $batch_file) + output=$(scarb cairo-run --no-build --package client --function test "$arguments") if [[ "$output" == *"FAIL"* ]]; then echo " fail" echo $output diff --git a/scripts/data/integration_tests.sh b/scripts/data/integration_tests.sh index 9c247157..bd51c13d 100755 --- a/scripts/data/integration_tests.sh +++ b/scripts/data/integration_tests.sh @@ -21,15 +21,17 @@ if [ $# -gt 0 ]; then test_files="${args[@]}" fi +echo "running integration tests ..." + for test_file in $test_files; do if [ -f "$test_file" ]; then - echo -n "test e2e:$test_file ..." + echo -n "test $test_file ..." if [[ "$ignored" =~ "$test_file" ]]; then echo " ignored" num_ignored=$((num_ignored + 1)) else - arguments=$(python scripts/data/format_args.py ${test_file}) + arguments=$(python ../../scripts/data/format_args.py ${test_file}) output=$(scarb cairo-run --no-build --function test "$arguments") gas_spent=$(echo $output | grep -o 'gas_spent=[0-9]*' | sed 's/gas_spent=//') @@ -37,7 +39,7 @@ for test_file in $test_files; do echo -e "${RED} fail ${RESET}(gas usage est.: $gas_spent)" num_fail=$((num_fail + 1)) error=$(echo $output | grep -o "error='[^']*'" | sed "s/error=//") - failures+="\te2e:$test_file — Panicked with $error\n" + failures+="\t$test_file — Panicked with $error\n" elif [[ "$output" == *"OK"* ]]; then echo -e "${GREEN} ok ${RESET}(gas usage est.: $gas_spent)" num_ok=$((num_ok + 1)) @@ -45,7 +47,7 @@ for test_file in $test_files; do echo -e "${RED} fail ${RESET}(gas usage est.: 0)" num_fail=$((num_fail + 1)) error=$(echo "$output" | sed '1d') - failures+="\te2e:$test_file — $error\n" + failures+="\t$test_file — $error\n" fi fi fi diff --git a/scripts/data/regenerate_tests.sh b/scripts/data/regenerate_tests.sh index 10397a5c..fabc833e 100755 --- a/scripts/data/regenerate_tests.sh +++ b/scripts/data/regenerate_tests.sh @@ -9,6 +9,7 @@ then fi force=0 +data_dir="tests/data" if [[ "$1" == "--force" ]]; then force=1 @@ -38,15 +39,15 @@ full_test_cases=( 757738 # Block with witness (757739) ) -mkdir tests/data || true +mkdir $data_dir || true # Generate test file if it does not exist yet or if "force" flag is set generate_test() { local mode=$1 local height=$2 - test_file="tests/data/${mode}_${test_case}.json" + test_file="${data_dir}/${mode}_${test_case}.json" if [[ ! -f "$test_file" || $force -eq 1 ]]; then - python scripts/data/generate_data.py $mode $height 1 true $test_file + python ../../scripts/data/generate_data.py $mode $height 1 true $test_file fi } diff --git a/src/lib.cairo b/src/lib.cairo deleted file mode 100644 index 737bd8af..00000000 --- a/src/lib.cairo +++ /dev/null @@ -1,35 +0,0 @@ -pub mod utils { - pub mod bytearray; - pub mod sha256; - pub mod hash; - pub mod bit_shifts; - pub mod merkle_tree; - pub mod numeric; - - #[cfg(target: 'test')] - pub mod hex; -} -pub mod validation { - pub mod difficulty; - pub mod coinbase; - pub mod locktime; - pub mod timestamp; - pub mod transaction; - pub mod work; - pub mod block; -} -pub mod codec; -pub mod types { - pub mod utreexo; - pub mod chain_state; - pub mod block; - pub mod transaction; - pub mod utxo_set; -} - -mod main; - -// TODO: move this module to a separate package -// Scarb does not support features when using cairo-run -// neither it allows to run function from the "tests" folder -mod test; From be2ea99c68ccb0ef0f1642ffe5bf197d487f83b8 Mon Sep 17 00:00:00 2001 From: lomasson <97454276+lomasson@users.noreply.github.com> Date: Fri, 13 Sep 2024 11:14:03 +0200 Subject: [PATCH 6/6] feat: pretty print structs (#188) --- packages/consensus/src/types/block.cairo | 39 +++++++++++ .../consensus/src/types/chain_state.cairo | 28 ++++++++ .../consensus/src/types/transaction.cairo | 66 +++++++++++++++++++ packages/consensus/src/types/utreexo.cairo | 43 ++++++++++++ 4 files changed, 176 insertions(+) diff --git a/packages/consensus/src/types/block.cairo b/packages/consensus/src/types/block.cairo index d9c13502..19f63b4a 100644 --- a/packages/consensus/src/types/block.cairo +++ b/packages/consensus/src/types/block.cairo @@ -6,6 +6,7 @@ use utils::hash::Digest; use utils::sha256::double_sha256_u32_array; use utils::numeric::u32_byte_reverse; use super::transaction::Transaction; +use core::fmt::{Display, Formatter, Error}; /// Represents a block in the blockchain. #[derive(Drop, Copy, Debug, PartialEq, Default, Serde)] @@ -76,6 +77,44 @@ pub impl TransactionDataDefault of Default { } } +impl BlockDisplay of Display { + fn fmt(self: @Block, ref f: Formatter) -> Result<(), Error> { + let data = match *self.data { + TransactionData::MerkleRoot(root) => format!("{}", root), + TransactionData::Transactions(txs) => format!("{}", txs.len()) + }; + let str: ByteArray = format!(" Block {{ header: {}, data: {} }}", *self.header, @data); + f.buffer.append(@str); + Result::Ok(()) + } +} + +impl HeaderDisplay of Display
{ + fn fmt(self: @Header, ref f: Formatter) -> Result<(), Error> { + let str: ByteArray = format!( + "Header {{ version: {}, time: {}, bits: {}, nonce: {}}}", + *self.version, + *self.time, + *self.bits, + *self.nonce + ); + f.buffer.append(@str); + Result::Ok(()) + } +} + +impl TransactionDataDisplay of Display { + fn fmt(self: @TransactionData, ref f: Formatter) -> Result<(), Error> { + match *self { + TransactionData::MerkleRoot(root) => f.buffer.append(@format!("MerkleRoot: {}", root)), + TransactionData::Transactions(txs) => f + .buffer + .append(@format!("Transactions: {}", txs.len())) + }; + Result::Ok(()) + } +} + #[cfg(test)] mod tests { use super::{Header, BlockHash}; diff --git a/packages/consensus/src/types/chain_state.cairo b/packages/consensus/src/types/chain_state.cairo index 58eb337b..37b01eee 100644 --- a/packages/consensus/src/types/chain_state.cairo +++ b/packages/consensus/src/types/chain_state.cairo @@ -11,6 +11,7 @@ use crate::validation::{ work::{validate_proof_of_work, compute_total_work}, block::{compute_and_validate_tx_data}, }; use super::block::{BlockHash, Block, TransactionData}; +use core::fmt::{Display, Formatter, Error}; /// Represents the state of the blockchain. #[derive(Drop, Copy, Debug, PartialEq, Serde)] @@ -97,6 +98,33 @@ pub impl BlockValidatorImpl of BlockValidator { ) } } + +impl ChainStateDisplay of Display { + fn fmt(self: @ChainState, ref f: Formatter) -> Result<(), Error> { + let mut prev_ts: ByteArray = Default::default(); + for ts in *self.prev_timestamps { + prev_ts.append(@format!("{},", ts)); + }; + let str: ByteArray = format!( + " + block_height: {} + total_work: {} + best_block_hash: {} + current_target: {} + epoch_start_time: {} + prev_timestamps: [{}] +}}", + *self.block_height, + *self.total_work, + *self.best_block_hash, + *self.current_target, + *self.epoch_start_time, + @prev_ts + ); + f.buffer.append(@str); + Result::Ok(()) + } +} // TODO: implement Digest trait for ChainState diff --git a/packages/consensus/src/types/transaction.cairo b/packages/consensus/src/types/transaction.cairo index 19027361..e5ae7d11 100644 --- a/packages/consensus/src/types/transaction.cairo +++ b/packages/consensus/src/types/transaction.cairo @@ -4,6 +4,7 @@ //! The data is expected to be prepared in advance and passed as program arguments. use utils::{hash::Digest, bytearray::{ByteArraySnapHash, ByteArraySnapSerde}}; +use core::fmt::{Display, Formatter, Error}; /// Represents a transaction. /// https://learnmeabitcoin.com/technical/transaction/ @@ -128,6 +129,71 @@ impl TxOutDefault of Default { } } +impl TransactionDisplay of Display { + fn fmt(self: @Transaction, ref f: Formatter) -> Result<(), Error> { + let str: ByteArray = format!( + "Transaction {{ version: {}, is_segwit: {}, inputs: {}, outputs: {}, lock_time: {} }}", + *self.version, + *self.is_segwit, + (*self.inputs).len(), + (*self.outputs).len(), + *self.lock_time + ); + f.buffer.append(@str); + Result::Ok(()) + } +} + +impl TxInDisplay of Display { + fn fmt(self: @TxIn, ref f: Formatter) -> Result<(), Error> { + let str: ByteArray = format!( + "TxIn {{ script: {}, sequence: {}, previous_output: {}, witness: {} }}", + *self.script, + *self.sequence, + *self.previous_output.txid, + (*self.witness).len() + ); + f.buffer.append(@str); + Result::Ok(()) + } +} + +impl OutPointDisplay of Display { + fn fmt(self: @OutPoint, ref f: Formatter) -> Result<(), Error> { + let str: ByteArray = format!( + "OutPoint {{ + txid: {}, + vout: {}, + data: {}, + block_height: {}, + block_time: {}, + is_coinbase: {}, + }}", + *self.txid, + *self.vout, + *self.data, + *self.block_height, + *self.block_time, + *self.is_coinbase + ); + f.buffer.append(@str); + Result::Ok(()) + } +} + +impl TxOutDisplay of Display { + fn fmt(self: @TxOut, ref f: Formatter) -> Result<(), Error> { + let str: ByteArray = format!( + "TxOut {{ value: {}, pk_script: {}, cached: {} }}", + *self.value, + *self.pk_script, + *self.cached + ); + f.buffer.append(@str); + Result::Ok(()) + } +} + #[cfg(test)] mod tests { use core::hash::HashStateTrait; diff --git a/packages/consensus/src/types/utreexo.cairo b/packages/consensus/src/types/utreexo.cairo index 960010c2..5ae1468e 100644 --- a/packages/consensus/src/types/utreexo.cairo +++ b/packages/consensus/src/types/utreexo.cairo @@ -28,6 +28,7 @@ //! Read more about utreexo: https://eprint.iacr.org/2019/611.pdf use super::transaction::OutPoint; +use core::fmt::{Display, Formatter, Error}; /// Accumulator representation of the state aka "Compact State Node". /// Part of the chain state. @@ -99,3 +100,45 @@ pub impl UtreexoStateDefault of Default { UtreexoState { roots: array![].span(), num_leaves: 0, } } } + +impl UtreexoStateDisplay of Display { + fn fmt(self: @UtreexoState, ref f: Formatter) -> Result<(), Error> { + let str: ByteArray = format!( + "UtreexoState {{ roots: {}, num_leaves: {}, }}", (*self.roots).len(), *self.num_leaves + ); + f.buffer.append(@str); + Result::Ok(()) + } +} + +impl UtreexoProofDisplay of Display { + fn fmt(self: @UtreexoProof, ref f: Formatter) -> Result<(), Error> { + let mut proofs: ByteArray = Default::default(); + for proof in *self.proof { + proofs.append(@format!("{},", proof)); + }; + let str: ByteArray = format!( + "UtreexoProof {{ leaf_index: {}, proof: {}, }}", *self.leaf_index, @proofs + ); + f.buffer.append(@str); + Result::Ok(()) + } +} + +impl UtreexoBatchProofDisplay of Display { + fn fmt(self: @UtreexoBatchProof, ref f: Formatter) -> Result<(), Error> { + let mut targets: ByteArray = Default::default(); + let mut proofs: ByteArray = Default::default(); + for target in *self.targets { + targets.append(@format!("{},", target)); + }; + for proof in *self.proof { + proofs.append(@format!("{},", proof)); + }; + let str: ByteArray = format!( + "UtreexoBatchProof {{ leaf_index: [{}], proof: [{}] }}", @targets, @proofs + ); + f.buffer.append(@str); + Result::Ok(()) + } +}