mirror of
https://github.com/serai-dex/serai.git
synced 2025-01-22 02:34:55 +00:00
Remove ethereum-serai/serai-processor-ethereum-contracts
contracts was smashed out of ethereum-serai. Both have now been smashed into individual crates. Creates a TODO directory with left-over test code yet to be moved.
This commit is contained in:
parent
433beac93a
commit
bdc3bda04a
26 changed files with 35 additions and 6193 deletions
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
|
@ -52,12 +52,10 @@ jobs:
|
|||
-p serai-processor-signers \
|
||||
-p serai-processor-bin \
|
||||
-p serai-bitcoin-processor \
|
||||
-p serai-processor-ethereum-contracts \
|
||||
-p serai-processor-ethereum-primitives \
|
||||
-p serai-processor-ethereum-deployer \
|
||||
-p serai-processor-ethereum-router \
|
||||
-p serai-processor-ethereum-erc20 \
|
||||
-p ethereum-serai \
|
||||
-p serai-ethereum-processor \
|
||||
-p serai-monero-processor \
|
||||
-p tendermint-machine \
|
||||
|
|
93
Cargo.lock
generated
93
Cargo.lock
generated
|
@ -184,17 +184,6 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloy-json-abi"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "299d2a937b6c60968df3dad2a988b0f0e03277b344639a4f7a31bd68e6285e59"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"alloy-sol-type-parser",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloy-json-rpc"
|
||||
version = "0.3.1"
|
||||
|
@ -426,7 +415,6 @@ version = "0.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71c4d842beb7a6686d04125603bc57614d5ed78bf95e4753274db3db4ba95214"
|
||||
dependencies = [
|
||||
"alloy-json-abi",
|
||||
"alloy-sol-macro-input",
|
||||
"const-hex",
|
||||
"heck 0.5.0",
|
||||
|
@ -445,33 +433,21 @@ version = "0.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1306e8d3c9e6e6ecf7a39ffaf7291e73a5f655a2defd366ee92c2efebcdf7fee"
|
||||
dependencies = [
|
||||
"alloy-json-abi",
|
||||
"const-hex",
|
||||
"dunce",
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde_json",
|
||||
"syn 2.0.77",
|
||||
"syn-solidity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloy-sol-type-parser"
|
||||
version = "0.8.0"
|
||||
source = "git+https://github.com/alloy-rs/core?rev=446b9d2fbce12b88456152170709a3eaac929af0#446b9d2fbce12b88456152170709a3eaac929af0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"winnow 0.6.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloy-sol-types"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "577e262966e92112edbd15b1b2c0947cc434d6e8311df96d3329793fe8047da9"
|
||||
dependencies = [
|
||||
"alloy-json-abi",
|
||||
"alloy-primitives",
|
||||
"alloy-sol-macro",
|
||||
"const-hex",
|
||||
|
@ -2503,30 +2479,6 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ethereum-serai"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-core",
|
||||
"alloy-network",
|
||||
"alloy-node-bindings",
|
||||
"alloy-provider",
|
||||
"alloy-rpc-client",
|
||||
"alloy-rpc-types-eth",
|
||||
"alloy-simple-request-transport",
|
||||
"alloy-sol-types",
|
||||
"ethereum-schnorr-contract",
|
||||
"flexible-transcript",
|
||||
"group",
|
||||
"k256",
|
||||
"modular-frost",
|
||||
"rand_core",
|
||||
"serai-processor-ethereum-contracts",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "event-listener"
|
||||
version = "2.5.3"
|
||||
|
@ -6127,16 +6079,6 @@ dependencies = [
|
|||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.2.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn 2.0.77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "primeorder"
|
||||
version = "0.13.6"
|
||||
|
@ -6302,7 +6244,7 @@ dependencies = [
|
|||
"log",
|
||||
"multimap",
|
||||
"petgraph",
|
||||
"prettyplease 0.1.25",
|
||||
"prettyplease",
|
||||
"prost",
|
||||
"prost-types",
|
||||
"regex",
|
||||
|
@ -8385,11 +8327,18 @@ version = "0.1.0"
|
|||
name = "serai-ethereum-processor"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-core",
|
||||
"alloy-provider",
|
||||
"alloy-rlp",
|
||||
"alloy-rpc-client",
|
||||
"alloy-rpc-types-eth",
|
||||
"alloy-simple-request-transport",
|
||||
"borsh",
|
||||
"ciphersuite",
|
||||
"const-hex",
|
||||
"dkg",
|
||||
"ethereum-serai",
|
||||
"ethereum-schnorr-contract",
|
||||
"hex",
|
||||
"k256",
|
||||
"log",
|
||||
|
@ -8400,6 +8349,9 @@ dependencies = [
|
|||
"serai-db",
|
||||
"serai-env",
|
||||
"serai-processor-bin",
|
||||
"serai-processor-ethereum-erc20",
|
||||
"serai-processor-ethereum-primitives",
|
||||
"serai-processor-ethereum-router",
|
||||
"serai-processor-key-gen",
|
||||
"serai-processor-primitives",
|
||||
"serai-processor-scanner",
|
||||
|
@ -8707,20 +8659,6 @@ dependencies = [
|
|||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serai-processor-ethereum-contracts"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"alloy-sol-macro-expander",
|
||||
"alloy-sol-macro-input",
|
||||
"alloy-sol-types",
|
||||
"build-solidity-contracts",
|
||||
"prettyplease 0.2.22",
|
||||
"serde_json",
|
||||
"syn 2.0.77",
|
||||
"syn-solidity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serai-processor-ethereum-deployer"
|
||||
version = "0.1.0"
|
||||
|
@ -8770,7 +8708,6 @@ dependencies = [
|
|||
"alloy-provider",
|
||||
"alloy-rpc-types-eth",
|
||||
"alloy-simple-request-transport",
|
||||
"alloy-sol-macro",
|
||||
"alloy-sol-macro-expander",
|
||||
"alloy-sol-macro-input",
|
||||
"alloy-sol-types",
|
||||
|
@ -8924,7 +8861,6 @@ dependencies = [
|
|||
"curve25519-dalek",
|
||||
"dkg",
|
||||
"dockertest",
|
||||
"ethereum-serai",
|
||||
"hex",
|
||||
"k256",
|
||||
"monero-simple-request-rpc",
|
||||
|
@ -11954,3 +11890,8 @@ dependencies = [
|
|||
"cc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[patch.unused]]
|
||||
name = "alloy-sol-type-parser"
|
||||
version = "0.8.0"
|
||||
source = "git+https://github.com/alloy-rs/core?rev=446b9d2fbce12b88456152170709a3eaac929af0#446b9d2fbce12b88456152170709a3eaac929af0"
|
||||
|
|
|
@ -87,12 +87,10 @@ members = [
|
|||
|
||||
"processor/bin",
|
||||
"processor/bitcoin",
|
||||
"processor/ethereum/contracts",
|
||||
"processor/ethereum/primitives",
|
||||
"processor/ethereum/deployer",
|
||||
"processor/ethereum/router",
|
||||
"processor/ethereum/erc20",
|
||||
"processor/ethereum/ethereum-serai",
|
||||
"processor/ethereum",
|
||||
"processor/monero",
|
||||
|
||||
|
|
|
@ -59,12 +59,10 @@ exceptions = [
|
|||
{ allow = ["AGPL-3.0"], name = "serai-processor-signers" },
|
||||
|
||||
{ allow = ["AGPL-3.0"], name = "serai-bitcoin-processor" },
|
||||
{ allow = ["AGPL-3.0"], name = "serai-processor-ethereum-contracts" },
|
||||
{ allow = ["AGPL-3.0"], name = "serai-processor-ethereum-primitives" },
|
||||
{ allow = ["AGPL-3.0"], name = "serai-processor-ethereum-deployer" },
|
||||
{ allow = ["AGPL-3.0"], name = "serai-processor-ethereum-router" },
|
||||
{ allow = ["AGPL-3.0"], name = "serai-processor-ethereum-erc20" },
|
||||
{ allow = ["AGPL-3.0"], name = "ethereum-serai" },
|
||||
{ allow = ["AGPL-3.0"], name = "serai-ethereum-processor" },
|
||||
{ allow = ["AGPL-3.0"], name = "serai-monero-processor" },
|
||||
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
[package]
|
||||
name = "serai-processor-ethereum-contracts"
|
||||
version = "0.1.0"
|
||||
description = "Ethereum contracts for the Serai processor"
|
||||
license = "AGPL-3.0-only"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/processor/ethereum/contracts"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>", "Elizabeth Binks <elizabethjbinks@gmail.com>"]
|
||||
edition = "2021"
|
||||
publish = false
|
||||
rust-version = "1.79"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
alloy-sol-types = { version = "0.8", default-features = false, features = ["json"] }
|
||||
|
||||
[build-dependencies]
|
||||
build-solidity-contracts = { path = "../../../networks/ethereum/build-contracts" }
|
||||
|
||||
syn = { version = "2", default-features = false, features = ["proc-macro"] }
|
||||
|
||||
serde_json = { version = "1", default-features = false, features = ["std"] }
|
||||
|
||||
syn-solidity = { version = "0.8", default-features = false }
|
||||
alloy-sol-macro-input = { version = "0.8", default-features = false }
|
||||
alloy-sol-macro-expander = { version = "0.8", default-features = false }
|
||||
prettyplease = { version = "0.2", default-features = false }
|
|
@ -1,15 +0,0 @@
|
|||
AGPL-3.0-only license
|
||||
|
||||
Copyright (c) 2022-2024 Luke Parker
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License Version 3 as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
@ -1,7 +0,0 @@
|
|||
# Serai Processor Ethereum Contracts
|
||||
|
||||
The Ethereum contracts used for (and for testing) the Serai processor. This is
|
||||
its own crate for organizational and build-time reasons. It is not intended to
|
||||
be publicly used.
|
||||
|
||||
This crate will fail to build if `solc` is not installed and available.
|
|
@ -1,69 +0,0 @@
|
|||
use std::{env, fs};
|
||||
|
||||
use alloy_sol_macro_input::{SolInputKind, SolInput};
|
||||
|
||||
fn write(sol: syn_solidity::File, file: &str) {
|
||||
let sol = alloy_sol_macro_expander::expand::expand(sol).unwrap();
|
||||
fs::write(
|
||||
file,
|
||||
// TODO: Replace `prettyplease::unparse` with `to_string`
|
||||
prettyplease::unparse(&syn::File {
|
||||
attrs: vec![],
|
||||
items: vec![syn::parse2(sol).unwrap()],
|
||||
shebang: None,
|
||||
})
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn sol(sol: &str, file: &str) {
|
||||
let alloy_sol_macro_input::SolInputKind::Sol(sol) =
|
||||
syn::parse_str(&std::fs::read_to_string(sol).unwrap()).unwrap()
|
||||
else {
|
||||
panic!("parsed .sol file wasn't SolInputKind::Sol");
|
||||
};
|
||||
write(sol, file);
|
||||
}
|
||||
|
||||
fn abi(ident: &str, abi: &str, file: &str) {
|
||||
let SolInputKind::Sol(sol) = (SolInput {
|
||||
attrs: vec![],
|
||||
path: None,
|
||||
kind: SolInputKind::Json(
|
||||
syn::parse_str(ident).unwrap(),
|
||||
serde_json::from_str(&fs::read_to_string(abi).unwrap()).unwrap(),
|
||||
),
|
||||
})
|
||||
.normalize_json()
|
||||
.unwrap()
|
||||
.kind
|
||||
else {
|
||||
panic!("normalized JSON wasn't SolInputKind::Sol");
|
||||
};
|
||||
write(sol, file);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let artifacts_path =
|
||||
env::var("OUT_DIR").unwrap().to_string() + "/serai-processor-ethereum-contracts";
|
||||
build_solidity_contracts::build(
|
||||
&["../../../networks/ethereum/schnorr/contracts"],
|
||||
"contracts",
|
||||
&artifacts_path,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// TODO: Use OUT_DIR for the generated code
|
||||
if !fs::exists("src/abigen").unwrap() {
|
||||
fs::create_dir("src/abigen").unwrap();
|
||||
}
|
||||
|
||||
// These can be handled with the sol! macro
|
||||
sol("contracts/IERC20.sol", "src/abigen/erc20.rs");
|
||||
sol("contracts/Deployer.sol", "src/abigen/deployer.rs");
|
||||
// This cannot be handled with the sol! macro. The Solidity requires an import, the ABI is built
|
||||
// to OUT_DIR and the macro doesn't support non-static paths:
|
||||
// https://github.com/alloy-rs/core/issues/738
|
||||
abi("Router", &(artifacts_path.clone() + "/Router.abi"), "src/abigen/router.rs");
|
||||
}
|
|
@ -1,584 +0,0 @@
|
|||
///Module containing a contract's types and functions.
|
||||
/**
|
||||
|
||||
```solidity
|
||||
contract Deployer {
|
||||
event Deployment(bytes32 indexed init_code_hash, address created);
|
||||
error DeploymentFailed();
|
||||
function deploy(bytes memory init_code) external { <stmts> }
|
||||
}
|
||||
```*/
|
||||
#[allow(non_camel_case_types, non_snake_case, clippy::style)]
|
||||
pub mod Deployer {
|
||||
use super::*;
|
||||
use ::alloy_sol_types as alloy_sol_types;
|
||||
/**Event with signature `Deployment(bytes32,address)` and selector `0x60b877a3bae7bf0f0bd5e1c40ebf44ea158201397f6b72d7c05360157b1ec0fc`.
|
||||
```solidity
|
||||
event Deployment(bytes32 indexed init_code_hash, address created);
|
||||
```*/
|
||||
#[allow(non_camel_case_types, non_snake_case, clippy::style)]
|
||||
#[derive(Clone)]
|
||||
pub struct Deployment {
|
||||
#[allow(missing_docs)]
|
||||
pub init_code_hash: ::alloy_sol_types::private::FixedBytes<32>,
|
||||
#[allow(missing_docs)]
|
||||
pub created: ::alloy_sol_types::private::Address,
|
||||
}
|
||||
#[allow(non_camel_case_types, non_snake_case, clippy::style)]
|
||||
const _: () = {
|
||||
use ::alloy_sol_types as alloy_sol_types;
|
||||
#[automatically_derived]
|
||||
impl alloy_sol_types::SolEvent for Deployment {
|
||||
type DataTuple<'a> = (::alloy_sol_types::sol_data::Address,);
|
||||
type DataToken<'a> = <Self::DataTuple<
|
||||
'a,
|
||||
> as alloy_sol_types::SolType>::Token<'a>;
|
||||
type TopicList = (
|
||||
alloy_sol_types::sol_data::FixedBytes<32>,
|
||||
::alloy_sol_types::sol_data::FixedBytes<32>,
|
||||
);
|
||||
const SIGNATURE: &'static str = "Deployment(bytes32,address)";
|
||||
const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([
|
||||
96u8,
|
||||
184u8,
|
||||
119u8,
|
||||
163u8,
|
||||
186u8,
|
||||
231u8,
|
||||
191u8,
|
||||
15u8,
|
||||
11u8,
|
||||
213u8,
|
||||
225u8,
|
||||
196u8,
|
||||
14u8,
|
||||
191u8,
|
||||
68u8,
|
||||
234u8,
|
||||
21u8,
|
||||
130u8,
|
||||
1u8,
|
||||
57u8,
|
||||
127u8,
|
||||
107u8,
|
||||
114u8,
|
||||
215u8,
|
||||
192u8,
|
||||
83u8,
|
||||
96u8,
|
||||
21u8,
|
||||
123u8,
|
||||
30u8,
|
||||
192u8,
|
||||
252u8,
|
||||
]);
|
||||
const ANONYMOUS: bool = false;
|
||||
#[allow(unused_variables)]
|
||||
#[inline]
|
||||
fn new(
|
||||
topics: <Self::TopicList as alloy_sol_types::SolType>::RustType,
|
||||
data: <Self::DataTuple<'_> as alloy_sol_types::SolType>::RustType,
|
||||
) -> Self {
|
||||
Self {
|
||||
init_code_hash: topics.1,
|
||||
created: data.0,
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn tokenize_body(&self) -> Self::DataToken<'_> {
|
||||
(
|
||||
<::alloy_sol_types::sol_data::Address as alloy_sol_types::SolType>::tokenize(
|
||||
&self.created,
|
||||
),
|
||||
)
|
||||
}
|
||||
#[inline]
|
||||
fn topics(&self) -> <Self::TopicList as alloy_sol_types::SolType>::RustType {
|
||||
(Self::SIGNATURE_HASH.into(), self.init_code_hash.clone())
|
||||
}
|
||||
#[inline]
|
||||
fn encode_topics_raw(
|
||||
&self,
|
||||
out: &mut [alloy_sol_types::abi::token::WordToken],
|
||||
) -> alloy_sol_types::Result<()> {
|
||||
if out.len() < <Self::TopicList as alloy_sol_types::TopicList>::COUNT {
|
||||
return Err(alloy_sol_types::Error::Overrun);
|
||||
}
|
||||
out[0usize] = alloy_sol_types::abi::token::WordToken(
|
||||
Self::SIGNATURE_HASH,
|
||||
);
|
||||
out[1usize] = <::alloy_sol_types::sol_data::FixedBytes<
|
||||
32,
|
||||
> as alloy_sol_types::EventTopic>::encode_topic(&self.init_code_hash);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl alloy_sol_types::private::IntoLogData for Deployment {
|
||||
fn to_log_data(&self) -> alloy_sol_types::private::LogData {
|
||||
From::from(self)
|
||||
}
|
||||
fn into_log_data(self) -> alloy_sol_types::private::LogData {
|
||||
From::from(&self)
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl From<&Deployment> for alloy_sol_types::private::LogData {
|
||||
#[inline]
|
||||
fn from(this: &Deployment) -> alloy_sol_types::private::LogData {
|
||||
alloy_sol_types::SolEvent::encode_log_data(this)
|
||||
}
|
||||
}
|
||||
};
|
||||
/**Custom error with signature `DeploymentFailed()` and selector `0x30116425`.
|
||||
```solidity
|
||||
error DeploymentFailed();
|
||||
```*/
|
||||
#[allow(non_camel_case_types, non_snake_case)]
|
||||
#[derive(Clone)]
|
||||
pub struct DeploymentFailed {}
|
||||
#[allow(non_camel_case_types, non_snake_case, clippy::style)]
|
||||
const _: () = {
|
||||
use ::alloy_sol_types as alloy_sol_types;
|
||||
#[doc(hidden)]
|
||||
type UnderlyingSolTuple<'a> = ();
|
||||
#[doc(hidden)]
|
||||
type UnderlyingRustTuple<'a> = ();
|
||||
#[cfg(test)]
|
||||
#[allow(dead_code, unreachable_patterns)]
|
||||
fn _type_assertion(
|
||||
_t: alloy_sol_types::private::AssertTypeEq<UnderlyingRustTuple>,
|
||||
) {
|
||||
match _t {
|
||||
alloy_sol_types::private::AssertTypeEq::<
|
||||
<UnderlyingSolTuple as alloy_sol_types::SolType>::RustType,
|
||||
>(_) => {}
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
#[doc(hidden)]
|
||||
impl ::core::convert::From<DeploymentFailed> for UnderlyingRustTuple<'_> {
|
||||
fn from(value: DeploymentFailed) -> Self {
|
||||
()
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
#[doc(hidden)]
|
||||
impl ::core::convert::From<UnderlyingRustTuple<'_>> for DeploymentFailed {
|
||||
fn from(tuple: UnderlyingRustTuple<'_>) -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl alloy_sol_types::SolError for DeploymentFailed {
|
||||
type Parameters<'a> = UnderlyingSolTuple<'a>;
|
||||
type Token<'a> = <Self::Parameters<
|
||||
'a,
|
||||
> as alloy_sol_types::SolType>::Token<'a>;
|
||||
const SIGNATURE: &'static str = "DeploymentFailed()";
|
||||
const SELECTOR: [u8; 4] = [48u8, 17u8, 100u8, 37u8];
|
||||
#[inline]
|
||||
fn new<'a>(
|
||||
tuple: <Self::Parameters<'a> as alloy_sol_types::SolType>::RustType,
|
||||
) -> Self {
|
||||
tuple.into()
|
||||
}
|
||||
#[inline]
|
||||
fn tokenize(&self) -> Self::Token<'_> {
|
||||
()
|
||||
}
|
||||
}
|
||||
};
|
||||
/**Function with signature `deploy(bytes)` and selector `0x00774360`.
|
||||
```solidity
|
||||
function deploy(bytes memory init_code) external { <stmts> }
|
||||
```*/
|
||||
#[allow(non_camel_case_types, non_snake_case)]
|
||||
#[derive(Clone)]
|
||||
pub struct deployCall {
|
||||
pub init_code: ::alloy_sol_types::private::Bytes,
|
||||
}
|
||||
///Container type for the return parameters of the [`deploy(bytes)`](deployCall) function.
|
||||
#[allow(non_camel_case_types, non_snake_case)]
|
||||
#[derive(Clone)]
|
||||
pub struct deployReturn {}
|
||||
#[allow(non_camel_case_types, non_snake_case, clippy::style)]
|
||||
const _: () = {
|
||||
use ::alloy_sol_types as alloy_sol_types;
|
||||
{
|
||||
#[doc(hidden)]
|
||||
type UnderlyingSolTuple<'a> = (::alloy_sol_types::sol_data::Bytes,);
|
||||
#[doc(hidden)]
|
||||
type UnderlyingRustTuple<'a> = (::alloy_sol_types::private::Bytes,);
|
||||
#[cfg(test)]
|
||||
#[allow(dead_code, unreachable_patterns)]
|
||||
fn _type_assertion(
|
||||
_t: alloy_sol_types::private::AssertTypeEq<UnderlyingRustTuple>,
|
||||
) {
|
||||
match _t {
|
||||
alloy_sol_types::private::AssertTypeEq::<
|
||||
<UnderlyingSolTuple as alloy_sol_types::SolType>::RustType,
|
||||
>(_) => {}
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
#[doc(hidden)]
|
||||
impl ::core::convert::From<deployCall> for UnderlyingRustTuple<'_> {
|
||||
fn from(value: deployCall) -> Self {
|
||||
(value.init_code,)
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
#[doc(hidden)]
|
||||
impl ::core::convert::From<UnderlyingRustTuple<'_>> for deployCall {
|
||||
fn from(tuple: UnderlyingRustTuple<'_>) -> Self {
|
||||
Self { init_code: tuple.0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
#[doc(hidden)]
|
||||
type UnderlyingSolTuple<'a> = ();
|
||||
#[doc(hidden)]
|
||||
type UnderlyingRustTuple<'a> = ();
|
||||
#[cfg(test)]
|
||||
#[allow(dead_code, unreachable_patterns)]
|
||||
fn _type_assertion(
|
||||
_t: alloy_sol_types::private::AssertTypeEq<UnderlyingRustTuple>,
|
||||
) {
|
||||
match _t {
|
||||
alloy_sol_types::private::AssertTypeEq::<
|
||||
<UnderlyingSolTuple as alloy_sol_types::SolType>::RustType,
|
||||
>(_) => {}
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
#[doc(hidden)]
|
||||
impl ::core::convert::From<deployReturn> for UnderlyingRustTuple<'_> {
|
||||
fn from(value: deployReturn) -> Self {
|
||||
()
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
#[doc(hidden)]
|
||||
impl ::core::convert::From<UnderlyingRustTuple<'_>> for deployReturn {
|
||||
fn from(tuple: UnderlyingRustTuple<'_>) -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl alloy_sol_types::SolCall for deployCall {
|
||||
type Parameters<'a> = (::alloy_sol_types::sol_data::Bytes,);
|
||||
type Token<'a> = <Self::Parameters<
|
||||
'a,
|
||||
> as alloy_sol_types::SolType>::Token<'a>;
|
||||
type Return = deployReturn;
|
||||
type ReturnTuple<'a> = ();
|
||||
type ReturnToken<'a> = <Self::ReturnTuple<
|
||||
'a,
|
||||
> as alloy_sol_types::SolType>::Token<'a>;
|
||||
const SIGNATURE: &'static str = "deploy(bytes)";
|
||||
const SELECTOR: [u8; 4] = [0u8, 119u8, 67u8, 96u8];
|
||||
#[inline]
|
||||
fn new<'a>(
|
||||
tuple: <Self::Parameters<'a> as alloy_sol_types::SolType>::RustType,
|
||||
) -> Self {
|
||||
tuple.into()
|
||||
}
|
||||
#[inline]
|
||||
fn tokenize(&self) -> Self::Token<'_> {
|
||||
(
|
||||
<::alloy_sol_types::sol_data::Bytes as alloy_sol_types::SolType>::tokenize(
|
||||
&self.init_code,
|
||||
),
|
||||
)
|
||||
}
|
||||
#[inline]
|
||||
fn abi_decode_returns(
|
||||
data: &[u8],
|
||||
validate: bool,
|
||||
) -> alloy_sol_types::Result<Self::Return> {
|
||||
<Self::ReturnTuple<
|
||||
'_,
|
||||
> as alloy_sol_types::SolType>::abi_decode_sequence(data, validate)
|
||||
.map(Into::into)
|
||||
}
|
||||
}
|
||||
};
|
||||
///Container for all the [`Deployer`](self) function calls.
|
||||
pub enum DeployerCalls {
|
||||
deploy(deployCall),
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl DeployerCalls {
|
||||
/// All the selectors of this enum.
|
||||
///
|
||||
/// Note that the selectors might not be in the same order as the variants.
|
||||
/// No guarantees are made about the order of the selectors.
|
||||
///
|
||||
/// Prefer using `SolInterface` methods instead.
|
||||
pub const SELECTORS: &'static [[u8; 4usize]] = &[[0u8, 119u8, 67u8, 96u8]];
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl alloy_sol_types::SolInterface for DeployerCalls {
|
||||
const NAME: &'static str = "DeployerCalls";
|
||||
const MIN_DATA_LENGTH: usize = 64usize;
|
||||
const COUNT: usize = 1usize;
|
||||
#[inline]
|
||||
fn selector(&self) -> [u8; 4] {
|
||||
match self {
|
||||
Self::deploy(_) => <deployCall as alloy_sol_types::SolCall>::SELECTOR,
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn selector_at(i: usize) -> ::core::option::Option<[u8; 4]> {
|
||||
Self::SELECTORS.get(i).copied()
|
||||
}
|
||||
#[inline]
|
||||
fn valid_selector(selector: [u8; 4]) -> bool {
|
||||
Self::SELECTORS.binary_search(&selector).is_ok()
|
||||
}
|
||||
#[inline]
|
||||
#[allow(unsafe_code, non_snake_case)]
|
||||
fn abi_decode_raw(
|
||||
selector: [u8; 4],
|
||||
data: &[u8],
|
||||
validate: bool,
|
||||
) -> alloy_sol_types::Result<Self> {
|
||||
static DECODE_SHIMS: &[fn(
|
||||
&[u8],
|
||||
bool,
|
||||
) -> alloy_sol_types::Result<DeployerCalls>] = &[
|
||||
{
|
||||
fn deploy(
|
||||
data: &[u8],
|
||||
validate: bool,
|
||||
) -> alloy_sol_types::Result<DeployerCalls> {
|
||||
<deployCall as alloy_sol_types::SolCall>::abi_decode_raw(
|
||||
data,
|
||||
validate,
|
||||
)
|
||||
.map(DeployerCalls::deploy)
|
||||
}
|
||||
deploy
|
||||
},
|
||||
];
|
||||
let Ok(idx) = Self::SELECTORS.binary_search(&selector) else {
|
||||
return Err(
|
||||
alloy_sol_types::Error::unknown_selector(
|
||||
<Self as alloy_sol_types::SolInterface>::NAME,
|
||||
selector,
|
||||
),
|
||||
);
|
||||
};
|
||||
(unsafe { DECODE_SHIMS.get_unchecked(idx) })(data, validate)
|
||||
}
|
||||
#[inline]
|
||||
fn abi_encoded_size(&self) -> usize {
|
||||
match self {
|
||||
Self::deploy(inner) => {
|
||||
<deployCall as alloy_sol_types::SolCall>::abi_encoded_size(inner)
|
||||
}
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec<u8>) {
|
||||
match self {
|
||||
Self::deploy(inner) => {
|
||||
<deployCall as alloy_sol_types::SolCall>::abi_encode_raw(inner, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
///Container for all the [`Deployer`](self) custom errors.
|
||||
pub enum DeployerErrors {
|
||||
DeploymentFailed(DeploymentFailed),
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl DeployerErrors {
|
||||
/// All the selectors of this enum.
|
||||
///
|
||||
/// Note that the selectors might not be in the same order as the variants.
|
||||
/// No guarantees are made about the order of the selectors.
|
||||
///
|
||||
/// Prefer using `SolInterface` methods instead.
|
||||
pub const SELECTORS: &'static [[u8; 4usize]] = &[[48u8, 17u8, 100u8, 37u8]];
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl alloy_sol_types::SolInterface for DeployerErrors {
|
||||
const NAME: &'static str = "DeployerErrors";
|
||||
const MIN_DATA_LENGTH: usize = 0usize;
|
||||
const COUNT: usize = 1usize;
|
||||
#[inline]
|
||||
fn selector(&self) -> [u8; 4] {
|
||||
match self {
|
||||
Self::DeploymentFailed(_) => {
|
||||
<DeploymentFailed as alloy_sol_types::SolError>::SELECTOR
|
||||
}
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn selector_at(i: usize) -> ::core::option::Option<[u8; 4]> {
|
||||
Self::SELECTORS.get(i).copied()
|
||||
}
|
||||
#[inline]
|
||||
fn valid_selector(selector: [u8; 4]) -> bool {
|
||||
Self::SELECTORS.binary_search(&selector).is_ok()
|
||||
}
|
||||
#[inline]
|
||||
#[allow(unsafe_code, non_snake_case)]
|
||||
fn abi_decode_raw(
|
||||
selector: [u8; 4],
|
||||
data: &[u8],
|
||||
validate: bool,
|
||||
) -> alloy_sol_types::Result<Self> {
|
||||
static DECODE_SHIMS: &[fn(
|
||||
&[u8],
|
||||
bool,
|
||||
) -> alloy_sol_types::Result<DeployerErrors>] = &[
|
||||
{
|
||||
fn DeploymentFailed(
|
||||
data: &[u8],
|
||||
validate: bool,
|
||||
) -> alloy_sol_types::Result<DeployerErrors> {
|
||||
<DeploymentFailed as alloy_sol_types::SolError>::abi_decode_raw(
|
||||
data,
|
||||
validate,
|
||||
)
|
||||
.map(DeployerErrors::DeploymentFailed)
|
||||
}
|
||||
DeploymentFailed
|
||||
},
|
||||
];
|
||||
let Ok(idx) = Self::SELECTORS.binary_search(&selector) else {
|
||||
return Err(
|
||||
alloy_sol_types::Error::unknown_selector(
|
||||
<Self as alloy_sol_types::SolInterface>::NAME,
|
||||
selector,
|
||||
),
|
||||
);
|
||||
};
|
||||
(unsafe { DECODE_SHIMS.get_unchecked(idx) })(data, validate)
|
||||
}
|
||||
#[inline]
|
||||
fn abi_encoded_size(&self) -> usize {
|
||||
match self {
|
||||
Self::DeploymentFailed(inner) => {
|
||||
<DeploymentFailed as alloy_sol_types::SolError>::abi_encoded_size(
|
||||
inner,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec<u8>) {
|
||||
match self {
|
||||
Self::DeploymentFailed(inner) => {
|
||||
<DeploymentFailed as alloy_sol_types::SolError>::abi_encode_raw(
|
||||
inner,
|
||||
out,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
///Container for all the [`Deployer`](self) events.
|
||||
pub enum DeployerEvents {
|
||||
Deployment(Deployment),
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl DeployerEvents {
|
||||
/// All the selectors of this enum.
|
||||
///
|
||||
/// Note that the selectors might not be in the same order as the variants.
|
||||
/// No guarantees are made about the order of the selectors.
|
||||
///
|
||||
/// Prefer using `SolInterface` methods instead.
|
||||
pub const SELECTORS: &'static [[u8; 32usize]] = &[
|
||||
[
|
||||
96u8,
|
||||
184u8,
|
||||
119u8,
|
||||
163u8,
|
||||
186u8,
|
||||
231u8,
|
||||
191u8,
|
||||
15u8,
|
||||
11u8,
|
||||
213u8,
|
||||
225u8,
|
||||
196u8,
|
||||
14u8,
|
||||
191u8,
|
||||
68u8,
|
||||
234u8,
|
||||
21u8,
|
||||
130u8,
|
||||
1u8,
|
||||
57u8,
|
||||
127u8,
|
||||
107u8,
|
||||
114u8,
|
||||
215u8,
|
||||
192u8,
|
||||
83u8,
|
||||
96u8,
|
||||
21u8,
|
||||
123u8,
|
||||
30u8,
|
||||
192u8,
|
||||
252u8,
|
||||
],
|
||||
];
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl alloy_sol_types::SolEventInterface for DeployerEvents {
|
||||
const NAME: &'static str = "DeployerEvents";
|
||||
const COUNT: usize = 1usize;
|
||||
fn decode_raw_log(
|
||||
topics: &[alloy_sol_types::Word],
|
||||
data: &[u8],
|
||||
validate: bool,
|
||||
) -> alloy_sol_types::Result<Self> {
|
||||
match topics.first().copied() {
|
||||
Some(<Deployment as alloy_sol_types::SolEvent>::SIGNATURE_HASH) => {
|
||||
<Deployment as alloy_sol_types::SolEvent>::decode_raw_log(
|
||||
topics,
|
||||
data,
|
||||
validate,
|
||||
)
|
||||
.map(Self::Deployment)
|
||||
}
|
||||
_ => {
|
||||
alloy_sol_types::private::Err(alloy_sol_types::Error::InvalidLog {
|
||||
name: <Self as alloy_sol_types::SolEventInterface>::NAME,
|
||||
log: alloy_sol_types::private::Box::new(
|
||||
alloy_sol_types::private::LogData::new_unchecked(
|
||||
topics.to_vec(),
|
||||
data.to_vec().into(),
|
||||
),
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[automatically_derived]
|
||||
impl alloy_sol_types::private::IntoLogData for DeployerEvents {
|
||||
fn to_log_data(&self) -> alloy_sol_types::private::LogData {
|
||||
match self {
|
||||
Self::Deployment(inner) => {
|
||||
alloy_sol_types::private::IntoLogData::to_log_data(inner)
|
||||
}
|
||||
}
|
||||
}
|
||||
fn into_log_data(self) -> alloy_sol_types::private::LogData {
|
||||
match self {
|
||||
Self::Deployment(inner) => {
|
||||
alloy_sol_types::private::IntoLogData::into_log_data(inner)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +0,0 @@
|
|||
pub mod erc20;
|
||||
pub mod deployer;
|
||||
pub mod router;
|
File diff suppressed because it is too large
Load diff
|
@ -1,16 +0,0 @@
|
|||
#[rustfmt::skip]
|
||||
#[expect(warnings)]
|
||||
#[expect(needless_pass_by_value)]
|
||||
#[expect(clippy::all)]
|
||||
#[expect(clippy::ignored_unit_patterns)]
|
||||
#[expect(clippy::redundant_closure_for_method_calls)]
|
||||
mod abigen;
|
||||
|
||||
pub mod erc20 {
|
||||
pub use super::abigen::erc20::IERC20::*;
|
||||
}
|
||||
pub mod router {
|
||||
pub const BYTECODE: &[u8] =
|
||||
include_bytes!(concat!(env!("OUT_DIR"), "/serai-processor-ethereum-contracts/Router.bin"));
|
||||
pub use super::abigen::router::Router::*;
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
[package]
|
||||
name = "ethereum-serai"
|
||||
version = "0.1.0"
|
||||
description = "An Ethereum library supporting Schnorr signing and on-chain verification"
|
||||
license = "AGPL-3.0-only"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/processor/ethereum/ethereum-serai"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>", "Elizabeth Binks <elizabethjbinks@gmail.com>"]
|
||||
edition = "2021"
|
||||
publish = false
|
||||
rust-version = "1.79"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
thiserror = { version = "1", default-features = false }
|
||||
|
||||
rand_core = { version = "0.6", default-features = false, features = ["std"] }
|
||||
|
||||
transcript = { package = "flexible-transcript", path = "../../../crypto/transcript", default-features = false, features = ["recommended"] }
|
||||
|
||||
group = { version = "0.13", default-features = false }
|
||||
k256 = { version = "^0.13.1", default-features = false, features = ["std", "ecdsa", "arithmetic"] }
|
||||
frost = { package = "modular-frost", path = "../../../crypto/frost", default-features = false, features = ["secp256k1"] }
|
||||
|
||||
alloy-core = { version = "0.8", default-features = false }
|
||||
alloy-sol-types = { version = "0.8", default-features = false, features = ["json"] }
|
||||
alloy-consensus = { version = "0.3", default-features = false, features = ["k256"] }
|
||||
alloy-network = { version = "0.3", default-features = false }
|
||||
alloy-rpc-types-eth = { version = "0.3", default-features = false }
|
||||
alloy-rpc-client = { version = "0.3", default-features = false }
|
||||
alloy-simple-request-transport = { path = "../../../networks/ethereum/alloy-simple-request-transport", default-features = false }
|
||||
alloy-provider = { version = "0.3", default-features = false }
|
||||
|
||||
alloy-node-bindings = { version = "0.3", default-features = false, optional = true }
|
||||
|
||||
ethereum-schnorr-contract = { path = "../../../networks/ethereum/schnorr", default-features = false }
|
||||
contracts = { package = "serai-processor-ethereum-contracts", path = "../contracts" }
|
||||
|
||||
[dev-dependencies]
|
||||
frost = { package = "modular-frost", path = "../../../crypto/frost", default-features = false, features = ["tests"] }
|
||||
|
||||
tokio = { version = "1", features = ["macros"] }
|
||||
|
||||
alloy-node-bindings = { version = "0.3", default-features = false }
|
||||
|
||||
[features]
|
||||
tests = ["alloy-node-bindings", "frost/tests"]
|
|
@ -1,15 +0,0 @@
|
|||
AGPL-3.0-only license
|
||||
|
||||
Copyright (c) 2022-2023 Luke Parker
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License Version 3 as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
@ -1,15 +0,0 @@
|
|||
# Ethereum
|
||||
|
||||
This package contains Ethereum-related functionality, specifically deploying and
|
||||
interacting with Serai contracts.
|
||||
|
||||
While `monero-serai` and `bitcoin-serai` are general purpose libraries,
|
||||
`ethereum-serai` is Serai specific. If any of the utilities are generally
|
||||
desired, please fork and maintain your own copy to ensure the desired
|
||||
functionality is preserved, or open an issue to request we make this library
|
||||
general purpose.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- solc
|
||||
- [Foundry](https://github.com/foundry-rs/foundry)
|
|
@ -1,32 +0,0 @@
|
|||
use group::ff::PrimeField;
|
||||
use k256::{
|
||||
elliptic_curve::{
|
||||
ops::Reduce,
|
||||
point::{AffineCoordinates, DecompressPoint},
|
||||
sec1::ToEncodedPoint,
|
||||
},
|
||||
AffinePoint, ProjectivePoint, Scalar, U256 as KU256,
|
||||
};
|
||||
|
||||
use frost::{
|
||||
algorithm::{Hram, SchnorrSignature},
|
||||
curve::{Ciphersuite, Secp256k1},
|
||||
};
|
||||
|
||||
pub use ethereum_schnorr_contract::*;
|
||||
|
||||
use alloy_core::primitives::{Parity, Signature as AlloySignature, Address};
|
||||
use alloy_consensus::{SignableTransaction, Signed, TxLegacy};
|
||||
|
||||
/// The HRAm to use for the Schnorr Solidity library.
|
||||
///
|
||||
/// This will panic if the public key being signed for is not representable within the Schnorr
|
||||
/// Solidity library.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct EthereumHram {}
|
||||
impl Hram<Secp256k1> for EthereumHram {
|
||||
#[allow(non_snake_case)]
|
||||
fn hram(R: &ProjectivePoint, A: &ProjectivePoint, m: &[u8]) -> Scalar {
|
||||
Signature::challenge(*R, &PublicKey::new(*A).unwrap(), m)
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
use thiserror::Error;
|
||||
|
||||
pub mod alloy {
|
||||
pub use alloy_core::primitives;
|
||||
pub use alloy_core as core;
|
||||
pub use alloy_sol_types as sol_types;
|
||||
|
||||
pub use alloy_consensus as consensus;
|
||||
pub use alloy_network as network;
|
||||
pub use alloy_rpc_types_eth as rpc_types;
|
||||
pub use alloy_simple_request_transport as simple_request_transport;
|
||||
pub use alloy_rpc_client as rpc_client;
|
||||
pub use alloy_provider as provider;
|
||||
}
|
||||
|
||||
pub mod crypto;
|
||||
|
||||
/*
|
||||
pub(crate) mod abi {
|
||||
pub use contracts::erc20;
|
||||
pub use contracts::deployer;
|
||||
pub use contracts::router;
|
||||
}
|
||||
|
||||
pub mod erc20;
|
||||
pub mod deployer;
|
||||
pub mod router;
|
||||
|
||||
pub mod machine;
|
||||
|
||||
#[cfg(any(test, feature = "tests"))]
|
||||
pub mod tests;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Error)]
|
||||
pub enum Error {
|
||||
#[error("failed to verify Schnorr signature")]
|
||||
InvalidSignature,
|
||||
#[error("couldn't make call/send TX")]
|
||||
ConnectionError,
|
||||
}
|
||||
*/
|
|
@ -1,427 +0,0 @@
|
|||
use std::{
|
||||
io::{self, Read},
|
||||
collections::HashMap,
|
||||
};
|
||||
|
||||
use rand_core::{RngCore, CryptoRng};
|
||||
|
||||
use transcript::{Transcript, RecommendedTranscript};
|
||||
|
||||
use group::GroupEncoding;
|
||||
use frost::{
|
||||
curve::{Ciphersuite, Secp256k1},
|
||||
Participant, ThresholdKeys, FrostError,
|
||||
algorithm::Schnorr,
|
||||
sign::*,
|
||||
};
|
||||
|
||||
use alloy_core::primitives::U256;
|
||||
|
||||
use crate::{
|
||||
crypto::{PublicKey, EthereumHram, Signature},
|
||||
router::{
|
||||
abi::{Call as AbiCall, OutInstruction as AbiOutInstruction},
|
||||
Router,
|
||||
},
|
||||
};
|
||||
|
||||
/// The HRAm to use for the Schnorr Solidity library.
|
||||
///
|
||||
/// This will panic if the public key being signed for is not representable within the Schnorr
|
||||
/// Solidity library.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct EthereumHram {}
|
||||
impl Hram<Secp256k1> for EthereumHram {
|
||||
#[allow(non_snake_case)]
|
||||
fn hram(R: &ProjectivePoint, A: &ProjectivePoint, m: &[u8]) -> Scalar {
|
||||
Signature::challenge(*R, &PublicKey::new(*A).unwrap(), m)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Call {
|
||||
pub to: [u8; 20],
|
||||
pub value: U256,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
impl Call {
|
||||
pub fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> {
|
||||
let mut to = [0; 20];
|
||||
reader.read_exact(&mut to)?;
|
||||
|
||||
let value = {
|
||||
let mut value_bytes = [0; 32];
|
||||
reader.read_exact(&mut value_bytes)?;
|
||||
U256::from_le_slice(&value_bytes)
|
||||
};
|
||||
|
||||
let mut data_len = {
|
||||
let mut data_len = [0; 4];
|
||||
reader.read_exact(&mut data_len)?;
|
||||
usize::try_from(u32::from_le_bytes(data_len)).expect("u32 couldn't fit within a usize")
|
||||
};
|
||||
|
||||
// A valid DoS would be to claim a 4 GB data is present for only 4 bytes
|
||||
// We read this in 1 KB chunks to only read data actually present (with a max DoS of 1 KB)
|
||||
let mut data = vec![];
|
||||
while data_len > 0 {
|
||||
let chunk_len = data_len.min(1024);
|
||||
let mut chunk = vec![0; chunk_len];
|
||||
reader.read_exact(&mut chunk)?;
|
||||
data.extend(&chunk);
|
||||
data_len -= chunk_len;
|
||||
}
|
||||
|
||||
Ok(Call { to, value, data })
|
||||
}
|
||||
|
||||
fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
|
||||
writer.write_all(&self.to)?;
|
||||
writer.write_all(&self.value.as_le_bytes())?;
|
||||
|
||||
let data_len = u32::try_from(self.data.len())
|
||||
.map_err(|_| io::Error::other("call data length exceeded 2**32"))?;
|
||||
writer.write_all(&data_len.to_le_bytes())?;
|
||||
writer.write_all(&self.data)
|
||||
}
|
||||
}
|
||||
impl From<Call> for AbiCall {
|
||||
fn from(call: Call) -> AbiCall {
|
||||
AbiCall { to: call.to.into(), value: call.value, data: call.data.into() }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub enum OutInstructionTarget {
|
||||
Direct([u8; 20]),
|
||||
Calls(Vec<Call>),
|
||||
}
|
||||
impl OutInstructionTarget {
|
||||
fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> {
|
||||
let mut kind = [0xff];
|
||||
reader.read_exact(&mut kind)?;
|
||||
|
||||
match kind[0] {
|
||||
0 => {
|
||||
let mut addr = [0; 20];
|
||||
reader.read_exact(&mut addr)?;
|
||||
Ok(OutInstructionTarget::Direct(addr))
|
||||
}
|
||||
1 => {
|
||||
let mut calls_len = [0; 4];
|
||||
reader.read_exact(&mut calls_len)?;
|
||||
let calls_len = u32::from_le_bytes(calls_len);
|
||||
|
||||
let mut calls = vec![];
|
||||
for _ in 0 .. calls_len {
|
||||
calls.push(Call::read(reader)?);
|
||||
}
|
||||
Ok(OutInstructionTarget::Calls(calls))
|
||||
}
|
||||
_ => Err(io::Error::other("unrecognized OutInstructionTarget"))?,
|
||||
}
|
||||
}
|
||||
|
||||
fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
|
||||
match self {
|
||||
OutInstructionTarget::Direct(addr) => {
|
||||
writer.write_all(&[0])?;
|
||||
writer.write_all(addr)?;
|
||||
}
|
||||
OutInstructionTarget::Calls(calls) => {
|
||||
writer.write_all(&[1])?;
|
||||
let call_len = u32::try_from(calls.len())
|
||||
.map_err(|_| io::Error::other("amount of calls exceeded 2**32"))?;
|
||||
writer.write_all(&call_len.to_le_bytes())?;
|
||||
for call in calls {
|
||||
call.write(writer)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct OutInstruction {
|
||||
pub target: OutInstructionTarget,
|
||||
pub value: U256,
|
||||
}
|
||||
impl OutInstruction {
|
||||
fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> {
|
||||
let target = OutInstructionTarget::read(reader)?;
|
||||
|
||||
let value = {
|
||||
let mut value_bytes = [0; 32];
|
||||
reader.read_exact(&mut value_bytes)?;
|
||||
U256::from_le_slice(&value_bytes)
|
||||
};
|
||||
|
||||
Ok(OutInstruction { target, value })
|
||||
}
|
||||
fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
|
||||
self.target.write(writer)?;
|
||||
writer.write_all(&self.value.as_le_bytes())
|
||||
}
|
||||
}
|
||||
impl From<OutInstruction> for AbiOutInstruction {
|
||||
fn from(instruction: OutInstruction) -> AbiOutInstruction {
|
||||
match instruction.target {
|
||||
OutInstructionTarget::Direct(addr) => {
|
||||
AbiOutInstruction { to: addr.into(), calls: vec![], value: instruction.value }
|
||||
}
|
||||
OutInstructionTarget::Calls(calls) => AbiOutInstruction {
|
||||
to: [0; 20].into(),
|
||||
calls: calls.into_iter().map(Into::into).collect(),
|
||||
value: instruction.value,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub enum RouterCommand {
|
||||
UpdateSeraiKey { chain_id: U256, nonce: U256, key: PublicKey },
|
||||
Execute { chain_id: U256, nonce: U256, outs: Vec<OutInstruction> },
|
||||
}
|
||||
|
||||
impl RouterCommand {
|
||||
pub fn msg(&self) -> Vec<u8> {
|
||||
match self {
|
||||
RouterCommand::UpdateSeraiKey { chain_id, nonce, key } => {
|
||||
Router::update_serai_key_message(*chain_id, *nonce, key)
|
||||
}
|
||||
RouterCommand::Execute { chain_id, nonce, outs } => Router::execute_message(
|
||||
*chain_id,
|
||||
*nonce,
|
||||
outs.iter().map(|out| out.clone().into()).collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> {
|
||||
let mut kind = [0xff];
|
||||
reader.read_exact(&mut kind)?;
|
||||
|
||||
match kind[0] {
|
||||
0 => {
|
||||
let mut chain_id = [0; 32];
|
||||
reader.read_exact(&mut chain_id)?;
|
||||
|
||||
let mut nonce = [0; 32];
|
||||
reader.read_exact(&mut nonce)?;
|
||||
|
||||
let key = PublicKey::new(Secp256k1::read_G(reader)?)
|
||||
.ok_or(io::Error::other("key for RouterCommand doesn't have an eth representation"))?;
|
||||
Ok(RouterCommand::UpdateSeraiKey {
|
||||
chain_id: U256::from_le_slice(&chain_id),
|
||||
nonce: U256::from_le_slice(&nonce),
|
||||
key,
|
||||
})
|
||||
}
|
||||
1 => {
|
||||
let mut chain_id = [0; 32];
|
||||
reader.read_exact(&mut chain_id)?;
|
||||
let chain_id = U256::from_le_slice(&chain_id);
|
||||
|
||||
let mut nonce = [0; 32];
|
||||
reader.read_exact(&mut nonce)?;
|
||||
let nonce = U256::from_le_slice(&nonce);
|
||||
|
||||
let mut outs_len = [0; 4];
|
||||
reader.read_exact(&mut outs_len)?;
|
||||
let outs_len = u32::from_le_bytes(outs_len);
|
||||
|
||||
let mut outs = vec![];
|
||||
for _ in 0 .. outs_len {
|
||||
outs.push(OutInstruction::read(reader)?);
|
||||
}
|
||||
|
||||
Ok(RouterCommand::Execute { chain_id, nonce, outs })
|
||||
}
|
||||
_ => Err(io::Error::other("reading unknown type of RouterCommand"))?,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
|
||||
match self {
|
||||
RouterCommand::UpdateSeraiKey { chain_id, nonce, key } => {
|
||||
writer.write_all(&[0])?;
|
||||
writer.write_all(&chain_id.as_le_bytes())?;
|
||||
writer.write_all(&nonce.as_le_bytes())?;
|
||||
writer.write_all(&key.point().to_bytes())
|
||||
}
|
||||
RouterCommand::Execute { chain_id, nonce, outs } => {
|
||||
writer.write_all(&[1])?;
|
||||
writer.write_all(&chain_id.as_le_bytes())?;
|
||||
writer.write_all(&nonce.as_le_bytes())?;
|
||||
writer.write_all(&u32::try_from(outs.len()).unwrap().to_le_bytes())?;
|
||||
for out in outs {
|
||||
out.write(writer)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut res = vec![];
|
||||
self.write(&mut res).unwrap();
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct SignedRouterCommand {
|
||||
command: RouterCommand,
|
||||
signature: Signature,
|
||||
}
|
||||
|
||||
impl SignedRouterCommand {
|
||||
pub fn new(key: &PublicKey, command: RouterCommand, signature: &[u8; 64]) -> Option<Self> {
|
||||
let c = Secp256k1::read_F(&mut &signature[.. 32]).ok()?;
|
||||
let s = Secp256k1::read_F(&mut &signature[32 ..]).ok()?;
|
||||
let signature = Signature { c, s };
|
||||
|
||||
if !signature.verify(key, &command.msg()) {
|
||||
None?
|
||||
}
|
||||
Some(SignedRouterCommand { command, signature })
|
||||
}
|
||||
|
||||
pub fn command(&self) -> &RouterCommand {
|
||||
&self.command
|
||||
}
|
||||
|
||||
pub fn signature(&self) -> &Signature {
|
||||
&self.signature
|
||||
}
|
||||
|
||||
pub fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> {
|
||||
let command = RouterCommand::read(reader)?;
|
||||
|
||||
let mut sig = [0; 64];
|
||||
reader.read_exact(&mut sig)?;
|
||||
let signature = Signature::from_bytes(sig)?;
|
||||
|
||||
Ok(SignedRouterCommand { command, signature })
|
||||
}
|
||||
|
||||
pub fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
|
||||
self.command.write(writer)?;
|
||||
writer.write_all(&self.signature.to_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RouterCommandMachine {
|
||||
key: PublicKey,
|
||||
command: RouterCommand,
|
||||
machine: AlgorithmMachine<Secp256k1, Schnorr<Secp256k1, RecommendedTranscript, EthereumHram>>,
|
||||
}
|
||||
|
||||
impl RouterCommandMachine {
|
||||
pub fn new(keys: ThresholdKeys<Secp256k1>, command: RouterCommand) -> Option<Self> {
|
||||
// The Schnorr algorithm should be fine without this, even when using the IETF variant
|
||||
// If this is better and more comprehensive, we should do it, even if not necessary
|
||||
let mut transcript = RecommendedTranscript::new(b"ethereum-serai RouterCommandMachine v0.1");
|
||||
let key = keys.group_key();
|
||||
transcript.append_message(b"key", key.to_bytes());
|
||||
transcript.append_message(b"command", command.serialize());
|
||||
|
||||
Some(Self {
|
||||
key: PublicKey::new(key)?,
|
||||
command,
|
||||
machine: AlgorithmMachine::new(Schnorr::new(transcript), keys),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl PreprocessMachine for RouterCommandMachine {
|
||||
type Preprocess = Preprocess<Secp256k1, ()>;
|
||||
type Signature = SignedRouterCommand;
|
||||
type SignMachine = RouterCommandSignMachine;
|
||||
|
||||
fn preprocess<R: RngCore + CryptoRng>(
|
||||
self,
|
||||
rng: &mut R,
|
||||
) -> (Self::SignMachine, Self::Preprocess) {
|
||||
let (machine, preprocess) = self.machine.preprocess(rng);
|
||||
|
||||
(RouterCommandSignMachine { key: self.key, command: self.command, machine }, preprocess)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RouterCommandSignMachine {
|
||||
key: PublicKey,
|
||||
command: RouterCommand,
|
||||
machine: AlgorithmSignMachine<Secp256k1, Schnorr<Secp256k1, RecommendedTranscript, EthereumHram>>,
|
||||
}
|
||||
|
||||
impl SignMachine<SignedRouterCommand> for RouterCommandSignMachine {
|
||||
type Params = ();
|
||||
type Keys = ThresholdKeys<Secp256k1>;
|
||||
type Preprocess = Preprocess<Secp256k1, ()>;
|
||||
type SignatureShare = SignatureShare<Secp256k1>;
|
||||
type SignatureMachine = RouterCommandSignatureMachine;
|
||||
|
||||
fn cache(self) -> CachedPreprocess {
|
||||
unimplemented!(
|
||||
"RouterCommand machines don't support caching their preprocesses due to {}",
|
||||
"being already bound to a specific command"
|
||||
);
|
||||
}
|
||||
|
||||
fn from_cache(
|
||||
(): (),
|
||||
_: ThresholdKeys<Secp256k1>,
|
||||
_: CachedPreprocess,
|
||||
) -> (Self, Self::Preprocess) {
|
||||
unimplemented!(
|
||||
"RouterCommand machines don't support caching their preprocesses due to {}",
|
||||
"being already bound to a specific command"
|
||||
);
|
||||
}
|
||||
|
||||
fn read_preprocess<R: Read>(&self, reader: &mut R) -> io::Result<Self::Preprocess> {
|
||||
self.machine.read_preprocess(reader)
|
||||
}
|
||||
|
||||
fn sign(
|
||||
self,
|
||||
commitments: HashMap<Participant, Self::Preprocess>,
|
||||
msg: &[u8],
|
||||
) -> Result<(RouterCommandSignatureMachine, Self::SignatureShare), FrostError> {
|
||||
if !msg.is_empty() {
|
||||
panic!("message was passed to a RouterCommand machine when it generates its own");
|
||||
}
|
||||
|
||||
let (machine, share) = self.machine.sign(commitments, &self.command.msg())?;
|
||||
|
||||
Ok((RouterCommandSignatureMachine { key: self.key, command: self.command, machine }, share))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RouterCommandSignatureMachine {
|
||||
key: PublicKey,
|
||||
command: RouterCommand,
|
||||
machine:
|
||||
AlgorithmSignatureMachine<Secp256k1, Schnorr<Secp256k1, RecommendedTranscript, EthereumHram>>,
|
||||
}
|
||||
|
||||
impl SignatureMachine<SignedRouterCommand> for RouterCommandSignatureMachine {
|
||||
type SignatureShare = SignatureShare<Secp256k1>;
|
||||
|
||||
fn read_share<R: Read>(&self, reader: &mut R) -> io::Result<Self::SignatureShare> {
|
||||
self.machine.read_share(reader)
|
||||
}
|
||||
|
||||
fn complete(
|
||||
self,
|
||||
shares: HashMap<Participant, Self::SignatureShare>,
|
||||
) -> Result<SignedRouterCommand, FrostError> {
|
||||
let signature = self.machine.complete(shares)?;
|
||||
let signature = Signature::new(signature).expect("machine produced an invalid signature");
|
||||
assert!(signature.verify(&self.key, &self.command.msg()));
|
||||
Ok(SignedRouterCommand { command: self.command, signature })
|
||||
}
|
||||
}
|
|
@ -40,8 +40,12 @@ impl Action {
|
|||
|
||||
fn message(&self) -> Vec<u8> {
|
||||
match self {
|
||||
Action::SetKey { chain_id, nonce, key } => Router::update_serai_key_message(*chain_id, *nonce, key),
|
||||
Action::Batch { chain_id, nonce, outs } => Router::execute_message(*chain_id, *nonce, OutInstructions::from(outs.as_ref())),
|
||||
Action::SetKey { chain_id, nonce, key } => {
|
||||
Router::update_serai_key_message(*chain_id, *nonce, key)
|
||||
}
|
||||
Action::Batch { chain_id, nonce, outs } => {
|
||||
Router::execute_message(*chain_id, *nonce, OutInstructions::from(outs.as_ref()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,9 +133,17 @@ impl PreprocessMachine for ClonableTransctionMachine {
|
|||
self,
|
||||
rng: &mut R,
|
||||
) -> (Self::SignMachine, Self::Preprocess) {
|
||||
let (machine, preprocess) = AlgorithmMachine::new(IetfSchnorr::<Secp256k1, EthereumHram>::ietf(), self.0.clone())
|
||||
let (machine, preprocess) =
|
||||
AlgorithmMachine::new(IetfSchnorr::<Secp256k1, EthereumHram>::ietf(), self.0.clone())
|
||||
.preprocess(rng);
|
||||
(ActionSignMachine(PublicKey::new(self.0.group_key()).expect("signing with non-representable key"), self.1, machine), preprocess)
|
||||
(
|
||||
ActionSignMachine(
|
||||
PublicKey::new(self.0.group_key()).expect("signing with non-representable key"),
|
||||
self.1,
|
||||
machine,
|
||||
),
|
||||
preprocess,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ dkg = { path = "../../crypto/dkg", default-features = false, features = ["std"]
|
|||
bitcoin-serai = { path = "../../networks/bitcoin" }
|
||||
|
||||
k256 = "0.13"
|
||||
ethereum-serai = { path = "../../processor/ethereum/ethereum-serai" }
|
||||
|
||||
monero-simple-request-rpc = { path = "../../networks/monero/rpc/simple-request" }
|
||||
monero-wallet = { path = "../../networks/monero/wallet" }
|
||||
|
|
Loading…
Reference in a new issue