diff --git a/.deny.toml b/.deny.toml index 6981f303..d48c60d0 100644 --- a/.deny.toml +++ b/.deny.toml @@ -57,6 +57,7 @@ unused-allowed-license = "deny" allow-git = [ "https://github.com/EspressoSystems/jellyfish.git", "https://github.com/logos-blockchain/logos-blockchain.git", + "https://github.com/logos-blockchain/logos-blockchain-circuits.git", ] unknown-git = "deny" unknown-registry = "deny" diff --git a/Cargo.lock b/Cargo.lock index 0bad6271..84caf697 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2670,7 +2670,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2768,6 +2768,17 @@ dependencies = [ "serde", ] +[[package]] +name = "fd-lock" +version = "4.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" +dependencies = [ + "cfg-if", + "rustix", + "windows-sys 0.59.0", +] + [[package]] name = "ferroid" version = "2.0.0" @@ -5314,7 +5325,7 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "logos-blockchain-blend-crypto" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "blake2", "logos-blockchain-groth16", @@ -5328,7 +5339,7 @@ dependencies = [ [[package]] name = "logos-blockchain-blend-message" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "blake2", "derivative", @@ -5352,7 +5363,7 @@ dependencies = [ [[package]] name = "logos-blockchain-blend-proofs" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "ed25519-dalek", "generic-array 1.3.5", @@ -5372,7 +5383,7 @@ dependencies = [ [[package]] name = "logos-blockchain-chain-broadcast-service" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "derivative", @@ -5388,7 +5399,7 @@ dependencies = [ [[package]] name = "logos-blockchain-chain-service" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "bytes", @@ -5417,19 +5428,88 @@ dependencies = [ "tracing-futures", ] +[[package]] +name = "logos-blockchain-circuits-build" +version = "0.5.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain-circuits.git?rev=2e79ac30831d89e6a349720c08d5b8b9978970e0#2e79ac30831d89e6a349720c08d5b8b9978970e0" +dependencies = [ + "dirs", + "fd-lock", + "flate2", + "tar", + "ureq", +] + +[[package]] +name = "logos-blockchain-circuits-common" +version = "0.5.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain-circuits.git?rev=2e79ac30831d89e6a349720c08d5b8b9978970e0#2e79ac30831d89e6a349720c08d5b8b9978970e0" +dependencies = [ + "logos-blockchain-circuits-types", +] + +[[package]] +name = "logos-blockchain-circuits-poc-sys" +version = "0.5.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain-circuits.git?rev=2e79ac30831d89e6a349720c08d5b8b9978970e0#2e79ac30831d89e6a349720c08d5b8b9978970e0" +dependencies = [ + "logos-blockchain-circuits-build", + "logos-blockchain-circuits-common", + "logos-blockchain-circuits-types", +] + +[[package]] +name = "logos-blockchain-circuits-pol-sys" +version = "0.5.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain-circuits.git?rev=2e79ac30831d89e6a349720c08d5b8b9978970e0#2e79ac30831d89e6a349720c08d5b8b9978970e0" +dependencies = [ + "logos-blockchain-circuits-build", + "logos-blockchain-circuits-common", + "logos-blockchain-circuits-types", +] + +[[package]] +name = "logos-blockchain-circuits-poq-sys" +version = "0.5.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain-circuits.git?rev=2e79ac30831d89e6a349720c08d5b8b9978970e0#2e79ac30831d89e6a349720c08d5b8b9978970e0" +dependencies = [ + "logos-blockchain-circuits-build", + "logos-blockchain-circuits-common", + "logos-blockchain-circuits-types", +] + [[package]] name = "logos-blockchain-circuits-prover" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "logos-blockchain-circuits-utils", "tempfile", ] +[[package]] +name = "logos-blockchain-circuits-signature-sys" +version = "0.5.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain-circuits.git?rev=2e79ac30831d89e6a349720c08d5b8b9978970e0#2e79ac30831d89e6a349720c08d5b8b9978970e0" +dependencies = [ + "logos-blockchain-circuits-build", + "logos-blockchain-circuits-common", + "logos-blockchain-circuits-types", +] + +[[package]] +name = "logos-blockchain-circuits-types" +version = "0.5.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain-circuits.git?rev=2e79ac30831d89e6a349720c08d5b8b9978970e0#2e79ac30831d89e6a349720c08d5b8b9978970e0" +dependencies = [ + "bytes", + "libc", +] + [[package]] name = "logos-blockchain-circuits-utils" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "dirs", ] @@ -5437,7 +5517,7 @@ dependencies = [ [[package]] name = "logos-blockchain-common-http-client" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "futures", "hex", @@ -5459,7 +5539,7 @@ dependencies = [ [[package]] name = "logos-blockchain-core" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "ark-ff 0.4.2", "bincode", @@ -5492,7 +5572,7 @@ dependencies = [ [[package]] name = "logos-blockchain-cryptarchia-engine" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "logos-blockchain-pol", "logos-blockchain-utils", @@ -5507,7 +5587,7 @@ dependencies = [ [[package]] name = "logos-blockchain-cryptarchia-sync" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "bytes", "futures", @@ -5526,7 +5606,7 @@ dependencies = [ [[package]] name = "logos-blockchain-groth16" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "ark-bn254 0.4.0", "ark-ec 0.4.2", @@ -5544,7 +5624,7 @@ dependencies = [ [[package]] name = "logos-blockchain-http-api-common" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "axum 0.7.9", "logos-blockchain-core", @@ -5564,7 +5644,7 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-keys" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "bytes", @@ -5590,7 +5670,7 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-macros" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "proc-macro2", "quote", @@ -5600,7 +5680,7 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-operators" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "logos-blockchain-blend-proofs", @@ -5616,7 +5696,7 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-service" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "log", @@ -5633,7 +5713,7 @@ dependencies = [ [[package]] name = "logos-blockchain-ledger" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "derivative", "logos-blockchain-blend-crypto", @@ -5659,7 +5739,7 @@ dependencies = [ [[package]] name = "logos-blockchain-libp2p" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "backon", @@ -5688,7 +5768,7 @@ dependencies = [ [[package]] name = "logos-blockchain-log-targets" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "logos-blockchain-log-targets-macros", ] @@ -5696,7 +5776,7 @@ dependencies = [ [[package]] name = "logos-blockchain-log-targets-macros" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "proc-macro2", "quote", @@ -5706,7 +5786,7 @@ dependencies = [ [[package]] name = "logos-blockchain-mmr" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "ark-ff 0.4.2", "logos-blockchain-groth16", @@ -5719,7 +5799,7 @@ dependencies = [ [[package]] name = "logos-blockchain-network-service" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "futures", @@ -5740,13 +5820,14 @@ dependencies = [ [[package]] name = "logos-blockchain-poc" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ + "logos-blockchain-circuits-poc-sys", "logos-blockchain-circuits-prover", + "logos-blockchain-circuits-types", "logos-blockchain-circuits-utils", "logos-blockchain-groth16", "logos-blockchain-proofs-error", - "logos-blockchain-witness-generator", "num-bigint 0.4.6", "serde", "serde_json", @@ -5756,15 +5837,16 @@ dependencies = [ [[package]] name = "logos-blockchain-pol" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "astro-float", + "logos-blockchain-circuits-pol-sys", "logos-blockchain-circuits-prover", + "logos-blockchain-circuits-types", "logos-blockchain-circuits-utils", "logos-blockchain-groth16", "logos-blockchain-proofs-error", "logos-blockchain-utils", - "logos-blockchain-witness-generator", "num-bigint 0.4.6", "num-traits", "serde", @@ -5775,14 +5857,15 @@ dependencies = [ [[package]] name = "logos-blockchain-poq" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ + "logos-blockchain-circuits-poq-sys", "logos-blockchain-circuits-prover", + "logos-blockchain-circuits-types", "logos-blockchain-circuits-utils", "logos-blockchain-groth16", "logos-blockchain-pol", "logos-blockchain-proofs-error", - "logos-blockchain-witness-generator", "num-bigint 0.4.6", "serde", "serde_json", @@ -5793,7 +5876,7 @@ dependencies = [ [[package]] name = "logos-blockchain-poseidon2" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "ark-bn254 0.4.0", "ark-ff 0.4.2", @@ -5804,8 +5887,9 @@ dependencies = [ [[package]] name = "logos-blockchain-proofs-error" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ + "logos-blockchain-circuits-types", "logos-blockchain-groth16", "serde_json", "thiserror 2.0.18", @@ -5814,7 +5898,7 @@ dependencies = [ [[package]] name = "logos-blockchain-services-utils" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "futures", @@ -5829,7 +5913,7 @@ dependencies = [ [[package]] name = "logos-blockchain-storage-service" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "bytes", @@ -5848,7 +5932,7 @@ dependencies = [ [[package]] name = "logos-blockchain-time-service" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "futures", @@ -5871,7 +5955,7 @@ dependencies = [ [[package]] name = "logos-blockchain-tracing" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "flate2", "logos-blockchain-log-targets", @@ -5897,7 +5981,7 @@ dependencies = [ [[package]] name = "logos-blockchain-utils" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "blake2", @@ -5916,7 +6000,7 @@ dependencies = [ [[package]] name = "logos-blockchain-utxotree" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "ark-ff 0.4.2", "logos-blockchain-groth16", @@ -5927,25 +6011,18 @@ dependencies = [ "thiserror 2.0.18", ] -[[package]] -name = "logos-blockchain-witness-generator" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" -dependencies = [ - "tempfile", -] - [[package]] name = "logos-blockchain-zksign" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "logos-blockchain-circuits-prover", + "logos-blockchain-circuits-signature-sys", + "logos-blockchain-circuits-types", "logos-blockchain-circuits-utils", "logos-blockchain-groth16", "logos-blockchain-poseidon2", "logos-blockchain-proofs-error", - "logos-blockchain-witness-generator", "num-bigint 0.4.6", "serde", "serde_json", @@ -5956,7 +6033,7 @@ dependencies = [ [[package]] name = "logos-blockchain-zone-sdk" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "futures", @@ -7666,7 +7743,7 @@ dependencies = [ "once_cell", "socket2 0.5.10", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -8585,7 +8662,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -8643,7 +8720,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs 0.26.11", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -8869,6 +8946,7 @@ dependencies = [ "nssa", "nssa_core", "rand 0.8.5", + "risc0-zkvm", "serde", "serde_json", "storage", @@ -9554,6 +9632,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "tar" +version = "0.4.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840" +dependencies = [ + "filetime", + "libc", + "xattr", +] + [[package]] name = "target-lexicon" version = "0.13.5" @@ -9570,7 +9659,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -10498,24 +10587,26 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc97a28575b85cfedf2a7e7d3cc64b3e11bd8ac766666318003abbacc7a21fc" +checksum = "dea7109cdcd5864d4eeb1b58a1648dc9bf520360d7af16ec26d0a9354bafcfc0" dependencies = [ "base64 0.22.1", + "flate2", "log", "percent-encoding", "rustls", "rustls-pki-types", "ureq-proto", - "utf-8", + "utf8-zero", + "webpki-roots", ] [[package]] name = "ureq-proto" -version = "0.5.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f" +checksum = "e994ba84b0bd1b1b0cf92878b7ef898a5c1760108fe7b6010327e274917a808c" dependencies = [ "base64 0.22.1", "http 1.4.0", @@ -10554,6 +10645,12 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1292c0d970b54115d14f2492fe0170adf21d68a1de108eebc51c1df4f346a091" +[[package]] +name = "utf8-zero" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8c0a043c9540bae7c578c88f91dda8bd82e59ae27c21baca69c8b191aaf5a6e" + [[package]] name = "utf8_iter" version = "1.0.4" @@ -10986,7 +11083,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ca9880ab..1f576d7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -137,13 +137,13 @@ schemars = "1.2" async-stream = "0.3.6" criterion = { version = "0.8", features = ["html_reports"] } -logos-blockchain-common-http-client = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "dd055cc1ef7c130f710a52a190edd97bc7b0f71b" } -logos-blockchain-key-management-system-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "dd055cc1ef7c130f710a52a190edd97bc7b0f71b" } -logos-blockchain-core = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "dd055cc1ef7c130f710a52a190edd97bc7b0f71b" } -logos-blockchain-chain-broadcast-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "dd055cc1ef7c130f710a52a190edd97bc7b0f71b" } -logos-blockchain-chain-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "dd055cc1ef7c130f710a52a190edd97bc7b0f71b" } -logos-blockchain-zone-sdk = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "dd055cc1ef7c130f710a52a190edd97bc7b0f71b" } -logos-blockchain-http-api-common = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "dd055cc1ef7c130f710a52a190edd97bc7b0f71b" } +logos-blockchain-common-http-client = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "db9a8d821c1b20f29b03d02072817150cf969b8e" } +logos-blockchain-key-management-system-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "db9a8d821c1b20f29b03d02072817150cf969b8e" } +logos-blockchain-core = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "db9a8d821c1b20f29b03d02072817150cf969b8e" } +logos-blockchain-chain-broadcast-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "db9a8d821c1b20f29b03d02072817150cf969b8e" } +logos-blockchain-chain-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "db9a8d821c1b20f29b03d02072817150cf969b8e" } +logos-blockchain-zone-sdk = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "db9a8d821c1b20f29b03d02072817150cf969b8e" } +logos-blockchain-http-api-common = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "db9a8d821c1b20f29b03d02072817150cf969b8e" } rocksdb = { version = "0.24.0", default-features = false, features = [ "snappy", diff --git a/artifacts/program_methods/bridge.bin b/artifacts/program_methods/bridge.bin index 3eacbc9d..5dd41e34 100644 Binary files a/artifacts/program_methods/bridge.bin and b/artifacts/program_methods/bridge.bin differ diff --git a/integration_tests/tests/bridge.rs b/integration_tests/tests/bridge.rs index 7cb63b22..41e304e8 100644 --- a/integration_tests/tests/bridge.rs +++ b/integration_tests/tests/bridge.rs @@ -43,6 +43,7 @@ async fn public_bridge_deposit_invocation_is_dropped() -> anyhow::Result<()> { vec![bridge_account_id, recipient_vault_id], vec![], bridge_core::Instruction::Deposit { + l1_deposit_op_id: [0_u8; 32], vault_program_id, recipient_id, amount: 1, @@ -129,6 +130,7 @@ async fn private_bridge_deposit_invocation_is_dropped() -> anyhow::Result<()> { // Serialize the bridge deposit instruction let instruction = Program::serialize_instruction(bridge_core::Instruction::Deposit { + l1_deposit_op_id: [0_u8; 32], vault_program_id, recipient_id, amount: 1, @@ -204,7 +206,9 @@ async fn submit_bedrock_deposit( // Encode deposit metadata let metadata = borsh::to_vec(&DepositMetadata { recipient_id }) - .context("Failed to encode deposit metadata")?; + .context("Failed to encode deposit metadata")? + .try_into() + .context("Encoded metadata is too big")?; let funding_key = "2e03b2eff5a45478e7e79668d2a146cf2c5c7925bce927f2b1c67f2ab4fc0d26"; @@ -307,7 +311,7 @@ async fn submit_bedrock_deposit( tip: None, deposit: DepositOp { channel_id, - inputs: Inputs::new(vec![selected_note_id]), + inputs: Inputs::new(selected_note_id), metadata, }, change_public_key: balance.address, diff --git a/program_methods/guest/src/bin/bridge.rs b/program_methods/guest/src/bin/bridge.rs index 0833d5aa..c9426be7 100644 --- a/program_methods/guest/src/bin/bridge.rs +++ b/program_methods/guest/src/bin/bridge.rs @@ -33,6 +33,7 @@ fn main() { let chained_calls = match instruction { Instruction::Deposit { + l1_deposit_op_id: _, vault_program_id, recipient_id, amount, diff --git a/programs/bridge/core/src/lib.rs b/programs/bridge/core/src/lib.rs index 1da75f97..214a5a47 100644 --- a/programs/bridge/core/src/lib.rs +++ b/programs/bridge/core/src/lib.rs @@ -12,6 +12,9 @@ pub enum Instruction { /// - Bridge PDA account /// - Recipient vault PDA account Deposit { + /// Deposit OP ID from L1, stored here to pin each [`Deposit`](Instruction::Deposit) to a + /// Deposit Event on L1. + l1_deposit_op_id: [u8; 32], vault_program_id: ProgramId, recipient_id: AccountId, amount: u128, diff --git a/sequencer/core/Cargo.toml b/sequencer/core/Cargo.toml index 985fc969..5e8a6ef6 100644 --- a/sequencer/core/Cargo.toml +++ b/sequencer/core/Cargo.toml @@ -34,6 +34,7 @@ borsh.workspace = true bytesize.workspace = true hex.workspace = true url.workspace = true +risc0-zkvm.workspace = true [features] default = [] diff --git a/sequencer/core/src/block_publisher.rs b/sequencer/core/src/block_publisher.rs index 62cd7259..f07a47c6 100644 --- a/sequencer/core/src/block_publisher.rs +++ b/sequencer/core/src/block_publisher.rs @@ -94,7 +94,7 @@ impl BlockPublisherTrait for ZoneSdkPublisher { continue; }; match event { - Event::Published { checkpoint, .. } => on_checkpoint(checkpoint), + Event::Checkpoint { checkpoint } => on_checkpoint(checkpoint), Event::TxsFinalized { items } => { for op in items.into_iter().flat_map(|item| item.ops) { match op { @@ -111,7 +111,10 @@ impl BlockPublisherTrait for ZoneSdkPublisher { } } } - Event::ChannelUpdate { .. } | Event::Ready => {} + Event::ChannelUpdate { .. } + | Event::Published { .. } + | Event::Readiness { .. } + | Event::TurnNotification { .. } => {} } } }); diff --git a/sequencer/core/src/block_store.rs b/sequencer/core/src/block_store.rs index ada6d306..68145e44 100644 --- a/sequencer/core/src/block_store.rs +++ b/sequencer/core/src/block_store.rs @@ -10,7 +10,7 @@ use log::info; use logos_blockchain_zone_sdk::sequencer::SequencerCheckpoint; use nssa::V03State; pub use storage::DbResult; -use storage::sequencer::RocksDBIO; +use storage::sequencer::{RocksDBIO, sequencer_cells::PendingDepositEventRecord}; pub struct SequencerStore { dbio: Arc, @@ -165,6 +165,27 @@ impl SequencerStore { self.dbio.put_zone_sdk_checkpoint_bytes(&bytes)?; Ok(()) } + + pub fn get_unfulfilled_deposit_events(&self) -> DbResult> { + self.dbio.get_pending_deposit_events() + } + + pub fn mark_unfulfilled_deposit_events_submitted( + &self, + deposit_op_ids: &[HashType], + submitted_block_id: u64, + ) -> DbResult { + self.dbio + .mark_pending_deposit_events_submitted(deposit_op_ids, submitted_block_id) + } + + pub fn remove_fulfilled_unfulfilled_deposit_events_up_to_block( + &self, + finalized_block_id: u64, + ) -> DbResult { + self.dbio + .remove_fulfilled_pending_deposit_events_up_to_block(finalized_block_id) + } } pub(crate) fn block_to_transactions_map(block: &Block) -> HashMap { diff --git a/sequencer/core/src/lib.rs b/sequencer/core/src/lib.rs index 13b455df..82f5065c 100644 --- a/sequencer/core/src/lib.rs +++ b/sequencer/core/src/lib.rs @@ -1,4 +1,4 @@ -use std::{path::Path, time::Instant}; +use std::{path::Path, sync::Arc, time::Instant}; use anyhow::{Context as _, Result, anyhow}; use borsh::BorshDeserialize; @@ -16,6 +16,7 @@ pub use mock::SequencerCoreWithMockClients; use nssa::{AccountId, PublicTransaction, program::Program, public_transaction::Message}; use nssa_core::GENESIS_BLOCK_ID; pub use storage::error::DbError; +use storage::sequencer::sequencer_cells::PendingDepositEventRecord; use crate::{ block_publisher::{BlockPublisherTrait, ZoneSdkPublisher}, @@ -147,26 +148,72 @@ impl SequencerCore { let dbio_for_finalized = store.dbio(); let on_finalized_block: block_publisher::FinalizedBlockSink = Box::new(move |block_id| { + // NOTE: Theoretically Zone SDK may report finalization happening multiple times for the + // same block. In practice this is very unlikely to happen. For that to + // happen Sequencer should crash between receiving Finalized and Checkpoint events while + // these events happen very fast (because Checkpoints are generated by Zone SDK + // locally). + if let Err(err) = dbio_for_finalized.clean_pending_blocks_up_to(block_id) { error!("Failed to mark pending blocks finalized up to {block_id}: {err:#}"); } + + match dbio_for_finalized.remove_fulfilled_pending_deposit_events_up_to_block(block_id) { + Ok(0) => {} + Ok(removed) => { + info!( + "Removed {removed} fulfilled pending deposit events up to finalized block {block_id}" + ); + } + Err(err) => { + error!( + "Failed to remove fulfilled pending deposit events up to block {block_id}: {err:#}" + ); + } + } }); let (mempool, mempool_handle) = MemPool::new(config.mempool_max_size); + replay_unfulfilled_deposit_events(&store, mempool_handle.clone()); + let mempool_handle_for_deposit = mempool_handle.clone(); + let dbio_for_deposit = store.dbio(); let on_deposit_event: block_publisher::OnDepositEventSink = Box::new(move |deposit| { + // NOTE: Theoretically Zone SDK may report multiple identical deposits. In practice this + // is very unlikely to happen. For that to happen Sequencer should crash + // between receiving Deposit and Checkpoint events while these events happen + // very fast (because Checkpoints are generated by Zone SDK locally). + + let dbio_for_deposit = Arc::clone(&dbio_for_deposit); let mempool_handle_for_deposit = mempool_handle_for_deposit.clone(); Box::pin(async move { - info!( - "Observed Bedrock Deposit event with id: {:?}", - hex::encode(deposit.op_id) - ); - let tx = match build_bridge_deposit_tx(&deposit) { + let id_hex = hex::encode(deposit.op_id); + info!("Observed Bedrock Deposit event with id: {id_hex}"); + + let event_record = pending_deposit_event_record(&deposit); + + match dbio_for_deposit.add_pending_deposit_event(event_record.clone()) { + Ok(true) => {} + Ok(false) => { + info!( + "Deposit event {id_hex} already persisted as unfulfilled, skipping duplicate enqueue", + ); + return; + } + Err(err) => { + error!( + "Failed to persist unfulfilled deposit event {id_hex} before enqueue: {err:#}. Deposit will be lost.", + ); + return; + } + } + + let tx = match build_bridge_deposit_tx_from_event(&event_record) { Ok(tx) => tx, Err(err) => { - warn!( - "Skipping finalized Bedrock deposit event due to tx build failure: {err:#}" + error!( + "Failed to build transaction from Bedrock deposit event {id_hex}: {err:#}. Deposit will be lost.", ); return; } @@ -177,7 +224,7 @@ impl SequencerCore { .await { error!( - "Failed to queue sequencer transaction built from finalized Bedrock event: {err:#}" + "Failed to queue sequencer transaction built from finalized Bedrock event: {err:#}. Deposit will be lost." ); } }) @@ -199,8 +246,11 @@ impl SequencerCore { // genesis block so the indexer can find the channel start. After the // first publish, zone-sdk's checkpoint persistence covers further // restarts. - if is_fresh_start && let Err(err) = block_publisher.publish_block(&genesis_block).await { - error!("Failed to publish genesis block: {err:#}"); + if is_fresh_start { + block_publisher + .publish_block(&genesis_block) + .await + .expect("Failed to publish genesis block"); } let sequencer_core = Self { @@ -217,30 +267,47 @@ impl SequencerCore { /// Produces a new block from mempool transactions and publishes it via zone-sdk. pub async fn produce_new_block(&mut self) -> Result { - let block = self + let block_with_meta = self .build_block_from_mempool() .context("Failed to build block from mempool transactions")?; + let BlockWithMeta { + block, + deposit_event_ids, + } = block_with_meta; // TODO: Remove msg_id from store.update — it is no longer needed now that // zone-sdk manages L1 settlement state via its own checkpoint. let placeholder_msg_id = [0_u8; 32]; - if let Err(err) = self.block_publisher.publish_block(&block).await { - error!("Failed to publish block to Bedrock with error: {err:#}"); - } + self.block_publisher + .publish_block(&block) + .await + .context("Failed to publish block to Bedrock")?; + self.store.update(&block, placeholder_msg_id, &self.state)?; + let updated_deposits = self + .store + .mark_unfulfilled_deposit_events_submitted(&deposit_event_ids, block.header.block_id)?; + if updated_deposits > 0 { + info!( + "Marked {updated_deposits} pending deposit events as submitted in block {}", + block.header.block_id + ); + } + Ok(self.chain_height) } /// Builds a new block from transactions in the mempool. /// Does NOT publish or store the block — the caller is responsible for that. - pub fn build_block_from_mempool(&mut self) -> Result { + fn build_block_from_mempool(&mut self) -> Result { let now = Instant::now(); let new_block_height = self.next_block_id(); - let mut valid_transactions = vec![]; + let mut valid_transactions = Vec::new(); + let mut deposit_event_ids = Vec::new(); let max_block_size = usize::try_from(self.sequencer_config.max_block_size.as_u64()) .expect("`max_block_size` should fit into usize"); @@ -311,6 +378,20 @@ impl SequencerCore { let NSSATransaction::Public(public_tx) = &tx else { panic!("Sequencer may only generate Public transactions, found {tx:#?}"); }; + + if public_tx.message.program_id == Program::bridge().id() { + let instruction: bridge_core::Instruction = + risc0_zkvm::serde::from_slice(&public_tx.message.instruction_data) + .context("Failed to deserialize bridge instruction")?; + match instruction { + bridge_core::Instruction::Deposit { + l1_deposit_op_id, .. + } => { + deposit_event_ids.push(HashType(l1_deposit_op_id)); + } + } + } + self.state .transition_from_public_transaction( public_tx, @@ -355,7 +436,11 @@ impl SequencerCore { hashable_data.transactions.len(), now.elapsed().as_secs() ); - Ok(block) + + Ok(BlockWithMeta { + block, + deposit_event_ids, + }) } pub const fn state(&self) -> &nssa::V03State { @@ -411,6 +496,60 @@ impl SequencerCore { } } +struct BlockWithMeta { + block: Block, + deposit_event_ids: Vec, +} + +/// Checks the database for any pending deposit events that have not yet been marked as submitted in +/// a block, and re-queues them in the mempool in a separate async task for inclusion in the next +/// block. +fn replay_unfulfilled_deposit_events( + store: &SequencerStore, + mempool_handle: MemPoolHandle<(TransactionOrigin, NSSATransaction)>, +) { + let replay_records: Vec = store + .get_unfulfilled_deposit_events() + .expect("Failed to load unfulfilled deposit events") + .into_iter() + .filter(|record| record.submitted_in_block_id.is_none()) + .collect(); + + if replay_records.is_empty() { + return; + } + + info!( + "Found {} unfulfilled deposit events in DB, re-queueing", + replay_records.len() + ); + tokio::spawn(async move { + for record in replay_records { + let tx = match build_bridge_deposit_tx_from_event(&record) { + Ok(tx) => tx, + Err(err) => { + warn!( + "Skipping replay of pending deposit event {} due to tx build failure: {err:#}", + hex::encode(record.deposit_op_id) + ); + continue; + } + }; + + if let Err(err) = mempool_handle + .push((TransactionOrigin::Sequencer, tx)) + .await + { + error!( + "Failed to re-queue unfulfilled deposit event {} from DB: {err:#}", + hex::encode(record.deposit_op_id) + ); + break; + } + } + }); +} + /// Builds the initial genesis state from `testnet_initial_state` plus configured genesis /// transactions. Returns the final state and the list of [`NSSATransaction`]s that should be /// committed to the genesis block so external observers can replay them. @@ -485,10 +624,22 @@ fn build_supply_bridge_account_genesis_transaction(balance: u128) -> PublicTrans PublicTransaction::new(message, witness_set) } -fn build_bridge_deposit_tx( +fn pending_deposit_event_record( deposit: &logos_blockchain_zone_sdk::state::DepositInfo, +) -> PendingDepositEventRecord { + PendingDepositEventRecord { + deposit_op_id: HashType(deposit.op_id), + source_tx_hash: HashType(deposit.tx_hash.0), + amount: deposit.amount, + metadata: deposit.metadata.clone().into(), + submitted_in_block_id: None, + } +} + +fn build_bridge_deposit_tx_from_event( + event: &PendingDepositEventRecord, ) -> Result { - let metadata = DepositMetadata::decode(&deposit.metadata) + let metadata = DepositMetadata::decode(&event.metadata) .context("Failed to decode finalized Bedrock deposit metadata")?; let bridge_program_id = Program::bridge().id(); @@ -501,9 +652,10 @@ fn build_bridge_deposit_tx( vec![nssa::system_bridge_account_id(), recipient_vault_id], vec![], bridge_core::Instruction::Deposit { + l1_deposit_op_id: event.deposit_op_id.0, vault_program_id, recipient_id: metadata.recipient_id, - amount: u128::from(deposit.amount), + amount: u128::from(event.amount), }, ) .context("Failed to build bridge deposit message")?; @@ -552,6 +704,7 @@ mod tests { }; use logos_blockchain_core::mantle::ops::channel::ChannelId; use mempool::MemPoolHandle; + use storage::sequencer::sequencer_cells::PendingDepositEventRecord; use tempfile::tempdir; use testnet_initial_state::{initial_accounts, initial_pub_accounts_private_keys}; @@ -563,6 +716,11 @@ mod tests { mock::SequencerCoreWithMockClients, }; + #[derive(borsh::BorshSerialize)] + struct DepositMetadataForEncoding { + recipient_id: nssa::AccountId, + } + fn setup_sequencer_config() -> SequencerConfig { let tempdir = tempfile::tempdir().unwrap(); let home = tempdir.path().to_path_buf(); @@ -620,6 +778,35 @@ mod tests { (sequencer, mempool_handle) } + fn tx_is_bridge_deposit( + tx: &NSSATransaction, + deposit_op_id: [u8; 32], + expected_amount: u64, + ) -> bool { + let NSSATransaction::Public(public_tx) = tx else { + return false; + }; + + if public_tx.message.program_id != nssa::program::Program::bridge().id() { + return false; + } + + let instruction: bridge_core::Instruction = + match risc0_zkvm::serde::from_slice(&public_tx.message.instruction_data) { + Ok(instruction) => instruction, + Err(_err) => return false, + }; + + matches!( + instruction, + bridge_core::Instruction::Deposit { + l1_deposit_op_id, + amount, + .. + } if l1_deposit_op_id == deposit_op_id && amount == u128::from(expected_amount) + ) + } + #[tokio::test] async fn start_from_config() { let config = setup_sequencer_config(); @@ -690,6 +877,69 @@ mod tests { let _ = SequencerCoreWithMockClients::start_from_config(config).await; } + #[tokio::test] + async fn start_from_config_replays_unfulfilled_deposit_events_from_db() { + let config = setup_sequencer_config(); + let deposit_op_id = [13_u8; 32]; + let expected_amount = 1_u64; + let recipient_id = initial_accounts()[0].account_id; + + { + let (_sequencer, _mempool_handle) = + SequencerCoreWithMockClients::start_from_config(config.clone()).await; + } + + let pending_event = PendingDepositEventRecord { + deposit_op_id: HashType(deposit_op_id), + source_tx_hash: HashType([7_u8; 32]), + amount: expected_amount, + metadata: borsh::to_vec(&DepositMetadataForEncoding { recipient_id }).unwrap(), + submitted_in_block_id: None, + }; + + { + let signing_key = nssa::PrivateKey::try_new(config.signing_key).unwrap(); + let store = SequencerStore::open_db(&config.home.join("rocksdb"), signing_key).unwrap(); + + let inserted = store + .dbio() + .add_pending_deposit_event(pending_event) + .unwrap(); + assert!(inserted); + } + + let (mut sequencer, _mempool_handle) = + SequencerCoreWithMockClients::start_from_config(config).await; + + let (origin, tx) = tokio::time::timeout(Duration::from_secs(5), async { + loop { + if let Some((origin, tx)) = sequencer.mempool.pop() { + return (origin, tx); + } + + tokio::time::sleep(Duration::from_millis(100)).await; + } + }) + .await + .expect("Timed out waiting for pending deposit event to be replayed into mempool"); + + match origin { + TransactionOrigin::Sequencer => {} + TransactionOrigin::User => { + panic!("Unexpected user transaction in empty mempool replay test") + } + } + + assert!(tx_is_bridge_deposit(&tx, deposit_op_id, expected_amount)); + + let pending_events = sequencer.store.get_unfulfilled_deposit_events().unwrap(); + let replayed_event = pending_events + .into_iter() + .find(|event| event.deposit_op_id == HashType(deposit_op_id)) + .expect("Pending deposit event should remain in DB until included in a block"); + assert!(replayed_event.submitted_in_block_id.is_none()); + } + #[test] fn transaction_pre_check_pass() { let tx = common::test_utils::produce_dummy_empty_transaction(); diff --git a/storage/src/sequencer/mod.rs b/storage/src/sequencer/mod.rs index be5e5cfe..34b7ca2c 100644 --- a/storage/src/sequencer/mod.rs +++ b/storage/src/sequencer/mod.rs @@ -1,6 +1,9 @@ use std::{path::Path, sync::Arc}; -use common::block::{BedrockStatus, Block, BlockMeta, MantleMsgId}; +use common::{ + HashType, + block::{BedrockStatus, Block, BlockMeta, MantleMsgId}, +}; use nssa::V03State; use rocksdb::{ BoundColumnFamily, ColumnFamilyDescriptor, DBWithThreadMode, MultiThreaded, Options, WriteBatch, @@ -12,7 +15,9 @@ use crate::{ error::DbError, sequencer::sequencer_cells::{ LastFinalizedBlockIdCell, LatestBlockMetaCellOwned, LatestBlockMetaCellRef, - NSSAStateCellOwned, NSSAStateCellRef, ZoneSdkCheckpointCellOwned, ZoneSdkCheckpointCellRef, + NSSAStateCellOwned, NSSAStateCellRef, PendingDepositEventRecord, + PendingDepositEventsCellOwned, PendingDepositEventsCellRef, ZoneSdkCheckpointCellOwned, + ZoneSdkCheckpointCellRef, }, }; @@ -24,6 +29,9 @@ pub const DB_META_LAST_FINALIZED_BLOCK_ID: &str = "last_finalized_block_id"; pub const DB_META_LATEST_BLOCK_META_KEY: &str = "latest_block_meta"; /// Key base for storing the zone-sdk sequencer checkpoint (opaque bytes). pub const DB_META_ZONE_SDK_CHECKPOINT_KEY: &str = "zone_sdk_checkpoint"; +/// Key base for storing queued deposit events that were not yet +/// fulfilled on L2. +pub const DB_META_PENDING_DEPOSIT_EVENTS_KEY: &str = "pending_deposit_events"; /// Key base for storing the NSSA state. pub const DB_NSSA_STATE_KEY: &str = "nssa_state"; @@ -239,6 +247,72 @@ impl RocksDBIO { self.put(&ZoneSdkCheckpointCellRef(bytes), ()) } + pub fn get_pending_deposit_events(&self) -> DbResult> { + Ok(self + .get_opt::(())? + .map_or_else(Vec::new, |cell| cell.0)) + } + + fn put_pending_deposit_events(&self, records: &[PendingDepositEventRecord]) -> DbResult<()> { + self.put(&PendingDepositEventsCellRef(records), ()) + } + + pub fn add_pending_deposit_event(&self, event: PendingDepositEventRecord) -> DbResult { + let mut records = self.get_pending_deposit_events()?; + if records + .iter() + .any(|record| record.deposit_op_id == event.deposit_op_id) + { + return Ok(false); + } + records.push(event); + self.put_pending_deposit_events(&records)?; + Ok(true) + } + + pub fn mark_pending_deposit_events_submitted( + &self, + deposit_op_ids: &[HashType], + submitted_block_id: u64, + ) -> DbResult { + let mut records = self.get_pending_deposit_events()?; + let mut updated: usize = 0; + + for record in records + .iter_mut() + .filter(|record| deposit_op_ids.contains(&record.deposit_op_id)) + { + record.submitted_in_block_id = Some(submitted_block_id); + updated = updated.saturating_add(1); + } + + if updated > 0 { + self.put_pending_deposit_events(&records)?; + } + + Ok(updated) + } + + pub fn remove_fulfilled_pending_deposit_events_up_to_block( + &self, + finalized_block_id: u64, + ) -> DbResult { + let mut records = self.get_pending_deposit_events()?; + let before = records.len(); + records.retain(|record| { + record + .submitted_in_block_id + .is_none_or(|submitted_id| submitted_id > finalized_block_id) + }); + + let removed = before.saturating_sub(records.len()); + if removed > 0 { + self.put_pending_deposit_events(&records)?; + } + + Ok(removed) + } + pub fn put_block( &self, block: &Block, diff --git a/storage/src/sequencer/sequencer_cells.rs b/storage/src/sequencer/sequencer_cells.rs index 2bf65367..78d09944 100644 --- a/storage/src/sequencer/sequencer_cells.rs +++ b/storage/src/sequencer/sequencer_cells.rs @@ -1,5 +1,5 @@ use borsh::{BorshDeserialize, BorshSerialize}; -use common::block::BlockMeta; +use common::{HashType, block::BlockMeta}; use nssa::V03State; use crate::{ @@ -8,7 +8,7 @@ use crate::{ error::DbError, sequencer::{ CF_NSSA_STATE_NAME, DB_META_LAST_FINALIZED_BLOCK_ID, DB_META_LATEST_BLOCK_META_KEY, - DB_META_ZONE_SDK_CHECKPOINT_KEY, DB_NSSA_STATE_KEY, + DB_META_PENDING_DEPOSIT_EVENTS_KEY, DB_META_ZONE_SDK_CHECKPOINT_KEY, DB_NSSA_STATE_KEY, }, }; @@ -131,12 +131,56 @@ impl SimpleWritableCell for ZoneSdkCheckpointCellRef<'_> { } } +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +pub struct PendingDepositEventRecord { + pub deposit_op_id: HashType, + pub source_tx_hash: HashType, + pub amount: u64, + pub metadata: Vec, + /// Set when block containing the deposit event is submitted, but not necessarily finalized. + pub submitted_in_block_id: Option, +} + +#[derive(BorshDeserialize)] +pub struct PendingDepositEventsCellOwned(pub Vec); + +impl SimpleStorableCell for PendingDepositEventsCellOwned { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_PENDING_DEPOSIT_EVENTS_KEY; + const CF_NAME: &'static str = CF_META_NAME; +} + +impl SimpleReadableCell for PendingDepositEventsCellOwned {} + +#[derive(BorshSerialize)] +pub struct PendingDepositEventsCellRef<'records>(pub &'records [PendingDepositEventRecord]); + +impl SimpleStorableCell for PendingDepositEventsCellRef<'_> { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_PENDING_DEPOSIT_EVENTS_KEY; + const CF_NAME: &'static str = CF_META_NAME; +} + +impl SimpleWritableCell for PendingDepositEventsCellRef<'_> { + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message( + err, + Some("Failed to serialize pending deposit events cell".to_owned()), + ) + }) + } +} + #[cfg(test)] mod uniform_tests { use crate::{ cells::SimpleStorableCell as _, sequencer::sequencer_cells::{ LatestBlockMetaCellOwned, LatestBlockMetaCellRef, NSSAStateCellOwned, NSSAStateCellRef, + PendingDepositEventsCellOwned, PendingDepositEventsCellRef, }, }; @@ -165,4 +209,20 @@ mod uniform_tests { LatestBlockMetaCellOwned::key_constructor(()).unwrap() ); } + + #[test] + fn pending_deposit_events_ref_and_owned_is_aligned() { + assert_eq!( + PendingDepositEventsCellRef::CELL_NAME, + PendingDepositEventsCellOwned::CELL_NAME + ); + assert_eq!( + PendingDepositEventsCellRef::CF_NAME, + PendingDepositEventsCellOwned::CF_NAME + ); + assert_eq!( + PendingDepositEventsCellRef::key_constructor(()).unwrap(), + PendingDepositEventsCellOwned::key_constructor(()).unwrap() + ); + } }