mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Replace custom read/write impls in router with borsh
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -9455,6 +9455,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"alloy-consensus",
|
"alloy-consensus",
|
||||||
"alloy-primitives",
|
"alloy-primitives",
|
||||||
|
"borsh",
|
||||||
"group",
|
"group",
|
||||||
"k256",
|
"k256",
|
||||||
]
|
]
|
||||||
@@ -9475,6 +9476,7 @@ dependencies = [
|
|||||||
"alloy-sol-macro-input",
|
"alloy-sol-macro-input",
|
||||||
"alloy-sol-types",
|
"alloy-sol-types",
|
||||||
"alloy-transport",
|
"alloy-transport",
|
||||||
|
"borsh",
|
||||||
"build-solidity-contracts",
|
"build-solidity-contracts",
|
||||||
"ethereum-schnorr-contract",
|
"ethereum-schnorr-contract",
|
||||||
"group",
|
"group",
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ rustdoc-args = ["--cfg", "docsrs"]
|
|||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] }
|
||||||
|
|
||||||
group = { version = "0.13", default-features = false }
|
group = { version = "0.13", default-features = false }
|
||||||
k256 = { version = "^0.13.1", default-features = false, features = ["std", "arithmetic"] }
|
k256 = { version = "^0.13.1", default-features = false, features = ["std", "arithmetic"] }
|
||||||
|
|
||||||
|
|||||||
24
processor/ethereum/primitives/src/borsh.rs
Normal file
24
processor/ethereum/primitives/src/borsh.rs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
use ::borsh::{io, BorshSerialize, BorshDeserialize};
|
||||||
|
|
||||||
|
use alloy_primitives::{U256, Address};
|
||||||
|
|
||||||
|
/// Serialize a U256 with a borsh-compatible API.
|
||||||
|
pub fn serialize_u256(value: &U256, writer: &mut impl io::Write) -> io::Result<()> {
|
||||||
|
let value: [u8; 32] = value.to_be_bytes();
|
||||||
|
value.serialize(writer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialize an address with a borsh-compatible API.
|
||||||
|
pub fn deserialize_u256(reader: &mut impl io::Read) -> io::Result<U256> {
|
||||||
|
<[u8; 32]>::deserialize_reader(reader).map(|value| U256::from_be_bytes(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serialize an address with a borsh-compatible API.
|
||||||
|
pub fn serialize_address(address: &Address, writer: &mut impl io::Write) -> io::Result<()> {
|
||||||
|
<[u8; 20]>::from(address.0).serialize(writer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialize an address with a borsh-compatible API.
|
||||||
|
pub fn deserialize_address(reader: &mut impl io::Read) -> io::Result<Address> {
|
||||||
|
<[u8; 20]>::deserialize_reader(reader).map(|address| Address(address.into()))
|
||||||
|
}
|
||||||
@@ -2,12 +2,27 @@
|
|||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
use ::borsh::{BorshSerialize, BorshDeserialize};
|
||||||
|
|
||||||
use group::ff::PrimeField;
|
use group::ff::PrimeField;
|
||||||
use k256::Scalar;
|
use k256::Scalar;
|
||||||
|
|
||||||
use alloy_primitives::PrimitiveSignature;
|
use alloy_primitives::PrimitiveSignature;
|
||||||
use alloy_consensus::{SignableTransaction, Signed, TxLegacy};
|
use alloy_consensus::{SignableTransaction, Signed, TxLegacy};
|
||||||
|
|
||||||
|
mod borsh;
|
||||||
|
pub use borsh::*;
|
||||||
|
|
||||||
|
/// An index of a log within a block.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
|
||||||
|
#[borsh(crate = "::borsh")]
|
||||||
|
pub struct LogIndex {
|
||||||
|
/// The hash of the block which produced this log.
|
||||||
|
pub block_hash: [u8; 32],
|
||||||
|
/// The index of this log within the execution of the block.
|
||||||
|
pub index_within_block: u64,
|
||||||
|
}
|
||||||
|
|
||||||
/// The Keccak256 hash function.
|
/// The Keccak256 hash function.
|
||||||
pub fn keccak256(data: impl AsRef<[u8]>) -> [u8; 32] {
|
pub fn keccak256(data: impl AsRef<[u8]>) -> [u8; 32] {
|
||||||
alloy_primitives::keccak256(data.as_ref()).into()
|
alloy_primitives::keccak256(data.as_ref()).into()
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ rustdoc-args = ["--cfg", "docsrs"]
|
|||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
borsh = { version = "1", default-features = false, features = ["std", "derive", "de_strict_order"] }
|
||||||
|
|
||||||
group = { version = "0.13", default-features = false }
|
group = { version = "0.13", default-features = false }
|
||||||
|
|
||||||
alloy-core = { version = "0.8", default-features = false }
|
alloy-core = { version = "0.8", default-features = false }
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use std::{sync::Arc, io, collections::HashSet};
|
use std::{sync::Arc, collections::HashSet};
|
||||||
|
|
||||||
|
use borsh::{BorshSerialize, BorshDeserialize};
|
||||||
|
|
||||||
use group::ff::PrimeField;
|
use group::ff::PrimeField;
|
||||||
|
|
||||||
@@ -16,6 +18,7 @@ use alloy_transport::{TransportErrorKind, RpcError};
|
|||||||
use alloy_simple_request_transport::SimpleRequest;
|
use alloy_simple_request_transport::SimpleRequest;
|
||||||
use alloy_provider::{Provider, RootProvider};
|
use alloy_provider::{Provider, RootProvider};
|
||||||
|
|
||||||
|
use ethereum_primitives::LogIndex;
|
||||||
use ethereum_schnorr::{PublicKey, Signature};
|
use ethereum_schnorr::{PublicKey, Signature};
|
||||||
use ethereum_deployer::Deployer;
|
use ethereum_deployer::Deployer;
|
||||||
use erc20::{Transfer, Erc20};
|
use erc20::{Transfer, Erc20};
|
||||||
@@ -65,12 +68,18 @@ impl From<&Signature> for abi::Signature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A coin on Ethereum.
|
/// A coin on Ethereum.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
|
||||||
pub enum Coin {
|
pub enum Coin {
|
||||||
/// Ether, the native coin of Ethereum.
|
/// Ether, the native coin of Ethereum.
|
||||||
Ether,
|
Ether,
|
||||||
/// An ERC20 token.
|
/// An ERC20 token.
|
||||||
Erc20(Address),
|
Erc20(
|
||||||
|
#[borsh(
|
||||||
|
serialize_with = "ethereum_primitives::serialize_address",
|
||||||
|
deserialize_with = "ethereum_primitives::deserialize_address"
|
||||||
|
)]
|
||||||
|
Address,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Coin {
|
impl Coin {
|
||||||
@@ -80,100 +89,31 @@ impl Coin {
|
|||||||
Coin::Erc20(address) => *address,
|
Coin::Erc20(address) => *address,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a `Coin`.
|
|
||||||
pub fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> {
|
|
||||||
let mut kind = [0xff];
|
|
||||||
reader.read_exact(&mut kind)?;
|
|
||||||
Ok(match kind[0] {
|
|
||||||
0 => Coin::Ether,
|
|
||||||
1 => {
|
|
||||||
let mut address = [0; 20];
|
|
||||||
reader.read_exact(&mut address)?;
|
|
||||||
Coin::Erc20(address.into())
|
|
||||||
}
|
|
||||||
_ => Err(io::Error::other("unrecognized Coin type"))?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write the `Coin`.
|
|
||||||
pub fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
|
|
||||||
match self {
|
|
||||||
Coin::Ether => writer.write_all(&[0]),
|
|
||||||
Coin::Erc20(token) => {
|
|
||||||
writer.write_all(&[1])?;
|
|
||||||
writer.write_all(token.as_ref())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An InInstruction from the Router.
|
/// An InInstruction from the Router.
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
|
||||||
pub struct InInstruction {
|
pub struct InInstruction {
|
||||||
/// The ID for this `InInstruction`.
|
/// The ID for this `InInstruction`.
|
||||||
pub id: ([u8; 32], u64),
|
pub id: LogIndex,
|
||||||
/// The address which transferred these coins to Serai.
|
/// The address which transferred these coins to Serai.
|
||||||
pub from: [u8; 20],
|
#[borsh(
|
||||||
|
serialize_with = "ethereum_primitives::serialize_address",
|
||||||
|
deserialize_with = "ethereum_primitives::deserialize_address"
|
||||||
|
)]
|
||||||
|
pub from: Address,
|
||||||
/// The coin transferred.
|
/// The coin transferred.
|
||||||
pub coin: Coin,
|
pub coin: Coin,
|
||||||
/// The amount transferred.
|
/// The amount transferred.
|
||||||
|
#[borsh(
|
||||||
|
serialize_with = "ethereum_primitives::serialize_u256",
|
||||||
|
deserialize_with = "ethereum_primitives::deserialize_u256"
|
||||||
|
)]
|
||||||
pub amount: U256,
|
pub amount: U256,
|
||||||
/// The data associated with the transfer.
|
/// The data associated with the transfer.
|
||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InInstruction {
|
|
||||||
/// Read an `InInstruction`.
|
|
||||||
pub fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> {
|
|
||||||
let id = {
|
|
||||||
let mut id_hash = [0; 32];
|
|
||||||
reader.read_exact(&mut id_hash)?;
|
|
||||||
let mut id_pos = [0; 8];
|
|
||||||
reader.read_exact(&mut id_pos)?;
|
|
||||||
let id_pos = u64::from_le_bytes(id_pos);
|
|
||||||
(id_hash, id_pos)
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut from = [0; 20];
|
|
||||||
reader.read_exact(&mut from)?;
|
|
||||||
|
|
||||||
let coin = Coin::read(reader)?;
|
|
||||||
let mut amount = [0; 32];
|
|
||||||
reader.read_exact(&mut amount)?;
|
|
||||||
let amount = U256::from_le_slice(&amount);
|
|
||||||
|
|
||||||
let mut data_len = [0; 4];
|
|
||||||
reader.read_exact(&mut data_len)?;
|
|
||||||
let data_len = usize::try_from(u32::from_le_bytes(data_len))
|
|
||||||
.map_err(|_| io::Error::other("InInstruction data exceeded 2**32 in length"))?;
|
|
||||||
let mut data = vec![0; data_len];
|
|
||||||
reader.read_exact(&mut data)?;
|
|
||||||
|
|
||||||
Ok(InInstruction { id, from, coin, amount, data })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write the `InInstruction`.
|
|
||||||
pub fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
|
|
||||||
writer.write_all(&self.id.0)?;
|
|
||||||
writer.write_all(&self.id.1.to_le_bytes())?;
|
|
||||||
|
|
||||||
writer.write_all(&self.from)?;
|
|
||||||
|
|
||||||
self.coin.write(writer)?;
|
|
||||||
writer.write_all(&self.amount.as_le_bytes())?;
|
|
||||||
|
|
||||||
writer.write_all(
|
|
||||||
&u32::try_from(self.data.len())
|
|
||||||
.map_err(|_| {
|
|
||||||
io::Error::other("InInstruction being written had data exceeding 2**32 in length")
|
|
||||||
})?
|
|
||||||
.to_le_bytes(),
|
|
||||||
)?;
|
|
||||||
writer.write_all(&self.data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A list of `OutInstruction`s.
|
/// A list of `OutInstruction`s.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct OutInstructions(Vec<abi::OutInstruction>);
|
pub struct OutInstructions(Vec<abi::OutInstruction>);
|
||||||
@@ -205,7 +145,7 @@ impl From<&[(SeraiAddress, U256)]> for OutInstructions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An action which was executed by the Router.
|
/// An action which was executed by the Router.
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)]
|
||||||
pub enum Executed {
|
pub enum Executed {
|
||||||
/// New key was set.
|
/// New key was set.
|
||||||
SetKey {
|
SetKey {
|
||||||
@@ -230,44 +170,6 @@ impl Executed {
|
|||||||
Executed::SetKey { nonce, .. } | Executed::Batch { nonce, .. } => *nonce,
|
Executed::SetKey { nonce, .. } | Executed::Batch { nonce, .. } => *nonce,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write the Executed.
|
|
||||||
pub fn write(&self, writer: &mut impl io::Write) -> io::Result<()> {
|
|
||||||
match self {
|
|
||||||
Self::SetKey { nonce, key } => {
|
|
||||||
writer.write_all(&[0])?;
|
|
||||||
writer.write_all(&nonce.to_le_bytes())?;
|
|
||||||
writer.write_all(key)
|
|
||||||
}
|
|
||||||
Self::Batch { nonce, message_hash } => {
|
|
||||||
writer.write_all(&[1])?;
|
|
||||||
writer.write_all(&nonce.to_le_bytes())?;
|
|
||||||
writer.write_all(message_hash)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Read an Executed.
|
|
||||||
pub fn read(reader: &mut impl io::Read) -> io::Result<Self> {
|
|
||||||
let mut kind = [0xff];
|
|
||||||
reader.read_exact(&mut kind)?;
|
|
||||||
if kind[0] >= 2 {
|
|
||||||
Err(io::Error::other("unrecognized type of Executed"))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut nonce = [0; 8];
|
|
||||||
reader.read_exact(&mut nonce)?;
|
|
||||||
let nonce = u64::from_le_bytes(nonce);
|
|
||||||
|
|
||||||
let mut payload = [0; 32];
|
|
||||||
reader.read_exact(&mut payload)?;
|
|
||||||
|
|
||||||
Ok(match kind[0] {
|
|
||||||
0 => Self::SetKey { nonce, key: payload },
|
|
||||||
1 => Self::Batch { nonce, message_hash: payload },
|
|
||||||
_ => unreachable!(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A view of the Router for Serai.
|
/// A view of the Router for Serai.
|
||||||
@@ -452,17 +354,17 @@ impl Router {
|
|||||||
))?;
|
))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let id = (
|
let id = LogIndex {
|
||||||
log
|
block_hash: log
|
||||||
.block_hash
|
.block_hash
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
TransportErrorKind::Custom("log didn't have its block hash set".to_string().into())
|
TransportErrorKind::Custom("log didn't have its block hash set".to_string().into())
|
||||||
})?
|
})?
|
||||||
.into(),
|
.into(),
|
||||||
log.log_index.ok_or_else(|| {
|
index_within_block: log.log_index.ok_or_else(|| {
|
||||||
TransportErrorKind::Custom("log didn't have its index set".to_string().into())
|
TransportErrorKind::Custom("log didn't have its index set".to_string().into())
|
||||||
})?,
|
})?,
|
||||||
);
|
};
|
||||||
|
|
||||||
let tx_hash = log.transaction_hash.ok_or_else(|| {
|
let tx_hash = log.transaction_hash.ok_or_else(|| {
|
||||||
TransportErrorKind::Custom("log didn't have its transaction hash set".to_string().into())
|
TransportErrorKind::Custom("log didn't have its transaction hash set".to_string().into())
|
||||||
@@ -551,7 +453,7 @@ impl Router {
|
|||||||
|
|
||||||
in_instructions.push(InInstruction {
|
in_instructions.push(InInstruction {
|
||||||
id,
|
id,
|
||||||
from: *log.from.0,
|
from: log.from,
|
||||||
coin,
|
coin,
|
||||||
amount: log.amount,
|
amount: log.amount,
|
||||||
data: log.instruction.as_ref().to_vec(),
|
data: log.instruction.as_ref().to_vec(),
|
||||||
|
|||||||
@@ -17,13 +17,12 @@ use alloy_provider::RootProvider;
|
|||||||
|
|
||||||
use alloy_node_bindings::{Anvil, AnvilInstance};
|
use alloy_node_bindings::{Anvil, AnvilInstance};
|
||||||
|
|
||||||
|
use ethereum_primitives::LogIndex;
|
||||||
use ethereum_schnorr::{PublicKey, Signature};
|
use ethereum_schnorr::{PublicKey, Signature};
|
||||||
use ethereum_deployer::Deployer;
|
use ethereum_deployer::Deployer;
|
||||||
|
|
||||||
use crate::{Coin, OutInstructions, Router};
|
use crate::{Coin, OutInstructions, Router};
|
||||||
|
|
||||||
mod read_write;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn execute_reentrancy_guard() {
|
fn execute_reentrancy_guard() {
|
||||||
let hash = alloy_core::primitives::keccak256(b"ReentrancyGuard Router.execute");
|
let hash = alloy_core::primitives::keccak256(b"ReentrancyGuard Router.execute");
|
||||||
@@ -217,7 +216,10 @@ async fn test_eth_in_instruction() {
|
|||||||
assert_eq!(parsed_in_instructions.len(), 1);
|
assert_eq!(parsed_in_instructions.len(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parsed_in_instructions[0].id,
|
parsed_in_instructions[0].id,
|
||||||
(<[u8; 32]>::from(receipt.block_hash.unwrap()), receipt.inner.logs()[0].log_index.unwrap())
|
LogIndex {
|
||||||
|
block_hash: *receipt.block_hash.unwrap(),
|
||||||
|
index_within_block: receipt.inner.logs()[0].log_index.unwrap(),
|
||||||
|
},
|
||||||
);
|
);
|
||||||
assert_eq!(parsed_in_instructions[0].from, signer);
|
assert_eq!(parsed_in_instructions[0].from, signer);
|
||||||
assert_eq!(parsed_in_instructions[0].coin, Coin::Ether);
|
assert_eq!(parsed_in_instructions[0].coin, Coin::Ether);
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
use rand_core::{RngCore, OsRng};
|
|
||||||
|
|
||||||
use alloy_core::primitives::U256;
|
|
||||||
|
|
||||||
use crate::{Coin, InInstruction, Executed};
|
|
||||||
|
|
||||||
fn coins() -> [Coin; 2] {
|
|
||||||
[Coin::Ether, {
|
|
||||||
let mut erc20 = [0; 20];
|
|
||||||
OsRng.fill_bytes(&mut erc20);
|
|
||||||
Coin::Erc20(erc20.into())
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_coin_read_write() {
|
|
||||||
for coin in coins() {
|
|
||||||
let mut res = vec![];
|
|
||||||
coin.write(&mut res).unwrap();
|
|
||||||
assert_eq!(coin, Coin::read(&mut res.as_slice()).unwrap());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_in_instruction_read_write() {
|
|
||||||
for coin in coins() {
|
|
||||||
let instruction = InInstruction {
|
|
||||||
id: (
|
|
||||||
{
|
|
||||||
let mut tx_id = [0; 32];
|
|
||||||
OsRng.fill_bytes(&mut tx_id);
|
|
||||||
tx_id
|
|
||||||
},
|
|
||||||
OsRng.next_u64(),
|
|
||||||
),
|
|
||||||
from: {
|
|
||||||
let mut from = [0; 20];
|
|
||||||
OsRng.fill_bytes(&mut from);
|
|
||||||
from
|
|
||||||
},
|
|
||||||
coin,
|
|
||||||
amount: U256::from_le_bytes({
|
|
||||||
let mut amount = [0; 32];
|
|
||||||
OsRng.fill_bytes(&mut amount);
|
|
||||||
amount
|
|
||||||
}),
|
|
||||||
data: {
|
|
||||||
let len = usize::try_from(OsRng.next_u64() % 65536).unwrap();
|
|
||||||
let mut data = vec![0; len];
|
|
||||||
OsRng.fill_bytes(&mut data);
|
|
||||||
data
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut buf = vec![];
|
|
||||||
instruction.write(&mut buf).unwrap();
|
|
||||||
assert_eq!(InInstruction::read(&mut buf.as_slice()).unwrap(), instruction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_executed_read_write() {
|
|
||||||
for executed in [
|
|
||||||
Executed::SetKey {
|
|
||||||
nonce: OsRng.next_u64(),
|
|
||||||
key: {
|
|
||||||
let mut key = [0; 32];
|
|
||||||
OsRng.fill_bytes(&mut key);
|
|
||||||
key
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Executed::Batch {
|
|
||||||
nonce: OsRng.next_u64(),
|
|
||||||
message_hash: {
|
|
||||||
let mut message_hash = [0; 32];
|
|
||||||
OsRng.fill_bytes(&mut message_hash);
|
|
||||||
message_hash
|
|
||||||
},
|
|
||||||
},
|
|
||||||
] {
|
|
||||||
let mut res = vec![];
|
|
||||||
executed.write(&mut res).unwrap();
|
|
||||||
assert_eq!(executed, Executed::read(&mut res.as_slice()).unwrap());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -145,7 +145,7 @@ impl ReceivedOutput<<Secp256k1 as Ciphersuite>::G, Address> for Output {
|
|||||||
Output::Output { key, instruction } => {
|
Output::Output { key, instruction } => {
|
||||||
writer.write_all(&[0])?;
|
writer.write_all(&[0])?;
|
||||||
writer.write_all(key.to_bytes().as_ref())?;
|
writer.write_all(key.to_bytes().as_ref())?;
|
||||||
instruction.write(writer)
|
instruction.serialize(writer)
|
||||||
}
|
}
|
||||||
Output::Eventuality { key, nonce } => {
|
Output::Eventuality { key, nonce } => {
|
||||||
writer.write_all(&[1])?;
|
writer.write_all(&[1])?;
|
||||||
@@ -164,7 +164,7 @@ impl ReceivedOutput<<Secp256k1 as Ciphersuite>::G, Address> for Output {
|
|||||||
Ok(match kind[0] {
|
Ok(match kind[0] {
|
||||||
0 => {
|
0 => {
|
||||||
let key = Secp256k1::read_G(reader)?;
|
let key = Secp256k1::read_G(reader)?;
|
||||||
let instruction = EthereumInInstruction::read(reader)?;
|
let instruction = EthereumInInstruction::deserialize_reader(reader)?;
|
||||||
Self::Output { key, instruction }
|
Self::Output { key, instruction }
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
|
|||||||
Reference in New Issue
Block a user