mirror of
https://github.com/serai-dex/serai.git
synced 2025-01-26 04:25:57 +00:00
Add calls to get the messages to sign for the router
This commit is contained in:
parent
381495618c
commit
d21034c349
2 changed files with 61 additions and 110 deletions
|
@ -77,6 +77,8 @@ contract Router {
|
||||||
external
|
external
|
||||||
_updateSeraiKeyAtEndOfFn(_nonce, newSeraiKey)
|
_updateSeraiKeyAtEndOfFn(_nonce, newSeraiKey)
|
||||||
{
|
{
|
||||||
|
// This DST needs a length prefix as well to prevent DSTs potentially being substrings of each
|
||||||
|
// other, yet this fine for our very well-defined, limited use
|
||||||
bytes32 message = keccak256(abi.encodePacked("updateSeraiKey", block.chainid, _nonce, newSeraiKey));
|
bytes32 message = keccak256(abi.encodePacked("updateSeraiKey", block.chainid, _nonce, newSeraiKey));
|
||||||
_nonce++;
|
_nonce++;
|
||||||
|
|
||||||
|
|
|
@ -156,6 +156,42 @@ impl InInstruction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A list of `OutInstruction`s.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct OutInstructions(Vec<abi::OutInstruction>);
|
||||||
|
impl From<&[(SeraiAddress, (Coin, Amount))]> for OutInstructions {
|
||||||
|
fn from(outs: &[(SeraiAddress, (Coin, Amount))]) -> Self {
|
||||||
|
Self(
|
||||||
|
outs
|
||||||
|
.iter()
|
||||||
|
.map(|(address, (coin, amount))| {
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
let (destinationType, destination) = match address {
|
||||||
|
SeraiAddress::Address(address) => (
|
||||||
|
abi::DestinationType::Address,
|
||||||
|
(abi::AddressDestination { destination: Address::from(address) }).abi_encode(),
|
||||||
|
),
|
||||||
|
SeraiAddress::Contract(contract) => (
|
||||||
|
abi::DestinationType::Code,
|
||||||
|
(abi::CodeDestination { gas: contract.gas(), code: contract.code().to_vec().into() })
|
||||||
|
.abi_encode(),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
abi::OutInstruction {
|
||||||
|
destinationType,
|
||||||
|
destination: destination.into(),
|
||||||
|
coin: match coin {
|
||||||
|
Coin::Ether => [0; 20].into(),
|
||||||
|
Coin::Erc20(address) => address.into(),
|
||||||
|
},
|
||||||
|
value: amount.0.try_into().expect("couldn't convert u64 to u256"),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Executed an command.
|
/// Executed an command.
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum Executed {
|
pub enum Executed {
|
||||||
|
@ -188,13 +224,13 @@ impl Executed {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Router(Arc<RootProvider<SimpleRequest>>, Address);
|
pub struct Router(Arc<RootProvider<SimpleRequest>>, Address);
|
||||||
impl Router {
|
impl Router {
|
||||||
pub(crate) fn code() -> Vec<u8> {
|
fn code() -> Vec<u8> {
|
||||||
const BYTECODE: &[u8] =
|
const BYTECODE: &[u8] =
|
||||||
include_bytes!(concat!(env!("OUT_DIR"), "/serai-processor-ethereum-router/Router.bin"));
|
include_bytes!(concat!(env!("OUT_DIR"), "/serai-processor-ethereum-router/Router.bin"));
|
||||||
Bytes::from_hex(BYTECODE).expect("compiled-in Router bytecode wasn't valid hex").to_vec()
|
Bytes::from_hex(BYTECODE).expect("compiled-in Router bytecode wasn't valid hex").to_vec()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn init_code(key: &PublicKey) -> Vec<u8> {
|
fn init_code(key: &PublicKey) -> Vec<u8> {
|
||||||
let mut bytecode = Self::code();
|
let mut bytecode = Self::code();
|
||||||
// Append the constructor arguments
|
// Append the constructor arguments
|
||||||
bytecode.extend((abi::constructorCall { initialSeraiKey: key.eth_repr().into() }).abi_encode());
|
bytecode.extend((abi::constructorCall { initialSeraiKey: key.eth_repr().into() }).abi_encode());
|
||||||
|
@ -226,6 +262,17 @@ impl Router {
|
||||||
self.1
|
self.1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the message to be signed in order to update the key for Serai.
|
||||||
|
pub fn update_serai_key_message(chain_id: U256, nonce: u64, key: &PublicKey) -> Vec<u8> {
|
||||||
|
(
|
||||||
|
"updateSeraiKey",
|
||||||
|
chain_id,
|
||||||
|
U256::try_from(nonce).expect("couldn't convert u64 to u256"),
|
||||||
|
key.eth_repr(),
|
||||||
|
)
|
||||||
|
.abi_encode_packed()
|
||||||
|
}
|
||||||
|
|
||||||
/// Construct a transaction to update the key representing Serai.
|
/// Construct a transaction to update the key representing Serai.
|
||||||
pub fn update_serai_key(&self, public_key: &PublicKey, sig: &Signature) -> TxLegacy {
|
pub fn update_serai_key(&self, public_key: &PublicKey, sig: &Signature) -> TxLegacy {
|
||||||
// TODO: Set a more accurate gas
|
// TODO: Set a more accurate gas
|
||||||
|
@ -239,111 +286,24 @@ impl Router {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the message to be signed in order to execute a series of `OutInstruction`s.
|
||||||
|
pub fn execute_message(chain_id: U256, nonce: u64, outs: OutInstructions) -> Vec<u8> {
|
||||||
|
("execute", chain_id, U256::try_from(nonce).expect("couldn't convert u64 to u256"), outs.0)
|
||||||
|
.abi_encode()
|
||||||
|
}
|
||||||
|
|
||||||
/// Construct a transaction to execute a batch of `OutInstruction`s.
|
/// Construct a transaction to execute a batch of `OutInstruction`s.
|
||||||
pub fn execute(&self, outs: &[(SeraiAddress, (Coin, Amount))], sig: &Signature) -> TxLegacy {
|
pub fn execute(&self, outs: OutInstructions, sig: &Signature) -> TxLegacy {
|
||||||
|
let outs_len = outs.0.len();
|
||||||
TxLegacy {
|
TxLegacy {
|
||||||
to: TxKind::Call(self.1),
|
to: TxKind::Call(self.1),
|
||||||
input: abi::executeCall::new((
|
input: abi::executeCall::new((outs.0, sig.into())).abi_encode().into(),
|
||||||
outs
|
|
||||||
.iter()
|
|
||||||
.map(|(address, (coin, amount))| {
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
let (destinationType, destination) = match address {
|
|
||||||
SeraiAddress::Address(address) => (
|
|
||||||
abi::DestinationType::Address,
|
|
||||||
(abi::AddressDestination { destination: Address::from(address) }).abi_encode(),
|
|
||||||
),
|
|
||||||
SeraiAddress::Contract(contract) => (
|
|
||||||
abi::DestinationType::Code,
|
|
||||||
(abi::CodeDestination {
|
|
||||||
gas: contract.gas(),
|
|
||||||
code: contract.code().to_vec().into(),
|
|
||||||
})
|
|
||||||
.abi_encode(),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
abi::OutInstruction {
|
|
||||||
destinationType,
|
|
||||||
destination: destination.into(),
|
|
||||||
coin: match coin {
|
|
||||||
Coin::Ether => [0; 20].into(),
|
|
||||||
Coin::Erc20(address) => address.into(),
|
|
||||||
},
|
|
||||||
value: amount.0.try_into().expect("couldn't convert u64 to u256"),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
sig.into(),
|
|
||||||
))
|
|
||||||
.abi_encode()
|
|
||||||
.into(),
|
|
||||||
// TODO
|
// TODO
|
||||||
gas_limit: 100_000 + ((200_000 + 10_000) * u128::try_from(outs.len()).unwrap()),
|
gas_limit: 100_000 + ((200_000 + 10_000) * u128::try_from(outs_len).unwrap()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
/// Get the key for Serai at the specified block.
|
|
||||||
#[cfg(test)]
|
|
||||||
pub async fn serai_key(&self, at: [u8; 32]) -> Result<PublicKey, RpcError<TransportErrorKind>> {
|
|
||||||
let call = TransactionRequest::default()
|
|
||||||
.to(self.1)
|
|
||||||
.input(TransactionInput::new(abi::seraiKeyCall::new(()).abi_encode().into()));
|
|
||||||
let bytes = self
|
|
||||||
.0
|
|
||||||
.call(&call)
|
|
||||||
.block(BlockId::Hash(B256::from(at).into()))
|
|
||||||
.await
|
|
||||||
?;
|
|
||||||
let res =
|
|
||||||
abi::seraiKeyCall::abi_decode_returns(&bytes, true)?;
|
|
||||||
PublicKey::from_eth_repr(res._0.0).ok_or_else(|| TransportErrorKind::Custom(
|
|
||||||
"TODO".to_string().into()))
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
/// Get the message to be signed in order to update the key for Serai.
|
|
||||||
pub(crate) fn update_serai_key_message(chain_id: U256, nonce: U256, key: &PublicKey) -> Vec<u8> {
|
|
||||||
let mut buffer = b"updateSeraiKey".to_vec();
|
|
||||||
buffer.extend(&chain_id.to_be_bytes::<32>());
|
|
||||||
buffer.extend(&nonce.to_be_bytes::<32>());
|
|
||||||
buffer.extend(&key.eth_repr());
|
|
||||||
buffer
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
/// Get the current nonce for the published batches.
|
|
||||||
#[cfg(test)]
|
|
||||||
pub async fn nonce(&self, at: [u8; 32]) -> Result<U256, RpcError<TransportErrorKind>> {
|
|
||||||
let call = TransactionRequest::default()
|
|
||||||
.to(self.1)
|
|
||||||
.input(TransactionInput::new(abi::nonceCall::new(()).abi_encode().into()));
|
|
||||||
let bytes = self
|
|
||||||
.0
|
|
||||||
.call(&call)
|
|
||||||
.block(BlockId::Hash(B256::from(at).into()))
|
|
||||||
.await
|
|
||||||
?;
|
|
||||||
let res =
|
|
||||||
abi::nonceCall::abi_decode_returns(&bytes, true)?;
|
|
||||||
Ok(res._0)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
/// Get the message to be signed in order to update the key for Serai.
|
|
||||||
pub(crate) fn execute_message(
|
|
||||||
chain_id: U256,
|
|
||||||
nonce: U256,
|
|
||||||
outs: Vec<abi::OutInstruction>,
|
|
||||||
) -> Vec<u8> {
|
|
||||||
("execute".to_string(), chain_id, nonce, outs).abi_encode_params()
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// Fetch the `InInstruction`s emitted by the Router from this block.
|
/// Fetch the `InInstruction`s emitted by the Router from this block.
|
||||||
pub async fn in_instructions(
|
pub async fn in_instructions(
|
||||||
&self,
|
&self,
|
||||||
|
@ -568,15 +528,4 @@ impl Router {
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
#[cfg(feature = "tests")]
|
|
||||||
pub fn key_updated_filter(&self) -> Filter {
|
|
||||||
Filter::new().address(self.1).event_signature(SeraiKeyUpdated::SIGNATURE_HASH)
|
|
||||||
}
|
|
||||||
#[cfg(feature = "tests")]
|
|
||||||
pub fn executed_filter(&self) -> Filter {
|
|
||||||
Filter::new().address(self.1).event_signature(ExecutedEvent::SIGNATURE_HASH)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue