mirror of
https://github.com/serai-dex/serai.git
synced 2025-01-03 17:40:34 +00:00
Various simplifications re: Serai transactions
Removes PairSigner for the pair directly. Resets spec_version to 1. Defines the extrinsic without its length prefix, only prefixing during publish.
This commit is contained in:
parent
c6cf33e370
commit
372149c2cc
9 changed files with 36 additions and 67 deletions
|
@ -40,6 +40,8 @@ impl<'a> SeraiInInstructions<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute_batch(batch: SignedBatch) -> Vec<u8> {
|
pub fn execute_batch(batch: SignedBatch) -> Vec<u8> {
|
||||||
Serai::unsigned::<InInstructions, _>(&in_instructions::Call::<Runtime>::execute_batch { batch })
|
Serai::unsigned(&serai_runtime::RuntimeCall::InInstructions(
|
||||||
|
in_instructions::Call::<Runtime>::execute_batch { batch },
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ pub use sp_core::{
|
||||||
sr25519::{Public, Pair},
|
sr25519::{Public, Pair},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use subxt;
|
|
||||||
use subxt::{
|
use subxt::{
|
||||||
error::Error as SubxtError,
|
error::Error as SubxtError,
|
||||||
config::{
|
config::{
|
||||||
|
@ -21,7 +20,6 @@ use subxt::{
|
||||||
substrate::{BlakeTwo256, SubstrateHeader},
|
substrate::{BlakeTwo256, SubstrateHeader},
|
||||||
extrinsic_params::BaseExtrinsicParams,
|
extrinsic_params::BaseExtrinsicParams,
|
||||||
},
|
},
|
||||||
tx::Signer,
|
|
||||||
rpc::types::{ChainBlock, ChainBlockExtrinsic},
|
rpc::types::{ChainBlock, ChainBlockExtrinsic},
|
||||||
Config as SubxtConfig, OnlineClient,
|
Config as SubxtConfig, OnlineClient,
|
||||||
};
|
};
|
||||||
|
@ -150,41 +148,32 @@ impl Serai {
|
||||||
Ok(Serai(OnlineClient::<SeraiConfig>::from_url(url).await.map_err(SeraiError::RpcError)?))
|
Ok(Serai(OnlineClient::<SeraiConfig>::from_url(url).await.map_err(SeraiError::RpcError)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unsigned<P: 'static, C: Encode>(call: &C) -> Vec<u8> {
|
fn unsigned(call: &serai_runtime::RuntimeCall) -> Vec<u8> {
|
||||||
// TODO: Should Serai purge the old transaction code AND set this to 0/1?
|
// TODO: Should Serai purge the old transaction code AND set this to 0/1?
|
||||||
const TRANSACTION_VERSION: u8 = 4;
|
const EXTRINSIC_FORMAT_VERSION: u8 = 4;
|
||||||
|
|
||||||
// Protocol version
|
let mut bytes = vec![EXTRINSIC_FORMAT_VERSION];
|
||||||
let mut bytes = vec![TRANSACTION_VERSION];
|
|
||||||
|
|
||||||
// Pallet index
|
|
||||||
bytes.push(u8::try_from(PalletInfo::index::<P>().unwrap()).unwrap());
|
|
||||||
// Call
|
|
||||||
bytes.extend(call.encode());
|
bytes.extend(call.encode());
|
||||||
|
bytes
|
||||||
// Prefix the length
|
|
||||||
let mut complete_bytes = Compact(u32::try_from(bytes.len()).unwrap()).encode();
|
|
||||||
complete_bytes.extend(bytes);
|
|
||||||
complete_bytes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sign<S: Send + Sync + Signer<SeraiConfig>>(
|
pub fn sign(
|
||||||
&self,
|
&self,
|
||||||
signer: &S,
|
signer: &Pair,
|
||||||
call: &serai_runtime::RuntimeCall,
|
call: &serai_runtime::RuntimeCall,
|
||||||
nonce: u32,
|
nonce: u32,
|
||||||
tip: Tip,
|
tip: Tip,
|
||||||
) -> Vec<u8> {
|
) -> Vec<u8> {
|
||||||
const SPEC_VERSION: u32 = 100;
|
const SPEC_VERSION: u32 = 1;
|
||||||
const IMPL_VERSION: u32 = 1;
|
const TX_VERSION: u32 = 1;
|
||||||
const TRANSACTION_VERSION: u8 = 4;
|
const EXTRINSIC_FORMAT_VERSION: u8 = 4;
|
||||||
|
|
||||||
let era = subxt::config::substrate::Era::Immortal;
|
let era = subxt::config::substrate::Era::Immortal;
|
||||||
let extra = (era, Compact(nonce), tip);
|
let extra = (era, Compact(nonce), tip);
|
||||||
let genesis = self.0.genesis_hash();
|
let genesis = self.0.genesis_hash();
|
||||||
let mortality_checkpoint = genesis;
|
let mortality_checkpoint = genesis;
|
||||||
let mut signature_payload =
|
let mut signature_payload =
|
||||||
(call, extra, SPEC_VERSION, IMPL_VERSION, genesis, mortality_checkpoint).encode();
|
(call, extra, SPEC_VERSION, TX_VERSION, genesis, mortality_checkpoint).encode();
|
||||||
if signature_payload.len() > 256 {
|
if signature_payload.len() > 256 {
|
||||||
use subxt::config::Hasher;
|
use subxt::config::Hasher;
|
||||||
signature_payload = BlakeTwo256::hash(&signature_payload).0.to_vec();
|
signature_payload = BlakeTwo256::hash(&signature_payload).0.to_vec();
|
||||||
|
@ -192,19 +181,20 @@ impl Serai {
|
||||||
let signature = signer.sign(&signature_payload);
|
let signature = signer.sign(&signature_payload);
|
||||||
|
|
||||||
let signed = 1 << 7;
|
let signed = 1 << 7;
|
||||||
let extrinsic =
|
(signed + EXTRINSIC_FORMAT_VERSION, signer.public(), signature, extra, call).encode()
|
||||||
(signed + TRANSACTION_VERSION, signer.address(), signature, extra, call).encode();
|
|
||||||
let mut res = Compact(u32::try_from(extrinsic.len()).unwrap()).encode();
|
|
||||||
res.extend(&extrinsic);
|
|
||||||
res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn publish(&self, tx: &[u8]) -> Result<(), SeraiError> {
|
pub async fn publish(&self, tx: &[u8]) -> Result<(), SeraiError> {
|
||||||
|
let mut length_prefixed = Compact(u32::try_from(tx.len()).unwrap()).encode();
|
||||||
|
length_prefixed.extend(tx);
|
||||||
self
|
self
|
||||||
.0
|
.0
|
||||||
.rpc()
|
.rpc()
|
||||||
.deref()
|
.deref()
|
||||||
.request::<String>("author_submitExtrinsic", subxt::rpc::rpc_params![hex::encode(tx)])
|
.request::<String>(
|
||||||
|
"author_submitExtrinsic",
|
||||||
|
subxt::rpc::rpc_params![hex::encode(length_prefixed)],
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
// Drop the hash, which is the hash of the raw extrinsic, as extrinsics are allowed to share
|
// Drop the hash, which is the hash of the raw extrinsic, as extrinsics are allowed to share
|
||||||
// hashes and this hash is accordingly useless/unsafe
|
// hashes and this hash is accordingly useless/unsafe
|
||||||
|
@ -386,23 +376,3 @@ impl<'a> TemporalSerai<'a> {
|
||||||
SeraiValidatorSets(self)
|
SeraiValidatorSets(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct PairSigner(Pair, <SeraiConfig as SubxtConfig>::AccountId);
|
|
||||||
impl PairSigner {
|
|
||||||
pub fn new(pair: Pair) -> Self {
|
|
||||||
let id = pair.public();
|
|
||||||
PairSigner(pair, id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Signer<SeraiConfig> for PairSigner {
|
|
||||||
fn account_id(&self) -> &<SeraiConfig as SubxtConfig>::AccountId {
|
|
||||||
&self.1
|
|
||||||
}
|
|
||||||
fn address(&self) -> <SeraiConfig as SubxtConfig>::Address {
|
|
||||||
self.1.into()
|
|
||||||
}
|
|
||||||
fn sign(&self, payload: &[u8]) -> <SeraiConfig as SubxtConfig>::Signature {
|
|
||||||
self.0.sign(payload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -81,10 +81,8 @@ impl<'a> SeraiValidatorSets<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_keys(network: NetworkId, key_pair: KeyPair, signature: Signature) -> Vec<u8> {
|
pub fn set_keys(network: NetworkId, key_pair: KeyPair, signature: Signature) -> Vec<u8> {
|
||||||
Serai::unsigned::<ValidatorSets, _>(&validator_sets::Call::<Runtime>::set_keys {
|
Serai::unsigned(&serai_runtime::RuntimeCall::ValidatorSets(
|
||||||
network,
|
validator_sets::Call::<Runtime>::set_keys { network, key_pair, signature },
|
||||||
key_pair,
|
))
|
||||||
signature,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ use serai_client::{
|
||||||
primitives::{InInstruction, InInstructionWithBalance, Batch},
|
primitives::{InInstruction, InInstructionWithBalance, Batch},
|
||||||
},
|
},
|
||||||
coins::{primitives::OutInstruction, CoinsEvent},
|
coins::{primitives::OutInstruction, CoinsEvent},
|
||||||
PairSigner, Serai, SeraiCoins,
|
Serai, SeraiCoins,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
@ -91,7 +91,7 @@ serai_test!(
|
||||||
serai,
|
serai,
|
||||||
&serai
|
&serai
|
||||||
.sign(
|
.sign(
|
||||||
&PairSigner::new(pair),
|
&pair,
|
||||||
&SeraiCoins::burn_with_instruction(instruction.clone()),
|
&SeraiCoins::burn_with_instruction(instruction.clone()),
|
||||||
0,
|
0,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use serai_runtime::primitives::{Coin, Amount};
|
use serai_runtime::primitives::{Coin, Amount};
|
||||||
|
|
||||||
use serai_client::{Serai, SeraiDex, PairSigner};
|
use serai_client::{Serai, SeraiDex};
|
||||||
use sp_core::{sr25519::Pair, Pair as PairTrait};
|
use sp_core::{sr25519::Pair, Pair as PairTrait};
|
||||||
|
|
||||||
use crate::common::tx::publish_tx;
|
use crate::common::tx::publish_tx;
|
||||||
|
@ -17,7 +17,7 @@ pub async fn add_liquidity(
|
||||||
let address = pair.public();
|
let address = pair.public();
|
||||||
|
|
||||||
let tx = serai.sign(
|
let tx = serai.sign(
|
||||||
&PairSigner::new(pair),
|
&pair,
|
||||||
&SeraiDex::add_liquidity(coin, coin_amount, sri_amount, Amount(1), Amount(1), address.into()),
|
&SeraiDex::add_liquidity(coin, coin_amount, sri_amount, Amount(1), Amount(1), address.into()),
|
||||||
nonce,
|
nonce,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
|
@ -39,7 +39,7 @@ pub async fn swap(
|
||||||
let address = pair.public();
|
let address = pair.public();
|
||||||
|
|
||||||
let tx = serai.sign(
|
let tx = serai.sign(
|
||||||
&PairSigner::new(pair),
|
&pair,
|
||||||
&SeraiDex::swap(from_coin, to_coin, amount_in, amount_out_min, address.into()),
|
&SeraiDex::swap(from_coin, to_coin, amount_in, amount_out_min, address.into()),
|
||||||
nonce,
|
nonce,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
|
|
|
@ -34,7 +34,7 @@ pub async fn publish_tx(serai: &Serai, tx: &[u8]) -> [u8; 32] {
|
||||||
};
|
};
|
||||||
|
|
||||||
for transaction in block.transactions() {
|
for transaction in block.transactions() {
|
||||||
if transaction.0 == tx[2 ..] {
|
if transaction.0 == tx {
|
||||||
return block.hash();
|
return block.hash();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,8 +88,7 @@ pub mod opaque {
|
||||||
pub const VERSION: RuntimeVersion = RuntimeVersion {
|
pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||||
spec_name: create_runtime_str!("serai"),
|
spec_name: create_runtime_str!("serai"),
|
||||||
impl_name: create_runtime_str!("core"),
|
impl_name: create_runtime_str!("core"),
|
||||||
// TODO: 1? Do we prefer some level of compatibility or our own path?
|
spec_version: 1,
|
||||||
spec_version: 100,
|
|
||||||
impl_version: 1,
|
impl_version: 1,
|
||||||
apis: RUNTIME_API_VERSIONS,
|
apis: RUNTIME_API_VERSIONS,
|
||||||
transaction_version: 1,
|
transaction_version: 1,
|
||||||
|
|
|
@ -12,7 +12,7 @@ use ciphersuite::{group::GroupEncoding, Ciphersuite, Secp256k1};
|
||||||
use dkg::Participant;
|
use dkg::Participant;
|
||||||
|
|
||||||
use serai_client::{
|
use serai_client::{
|
||||||
PairTrait, PairSigner,
|
PairTrait,
|
||||||
primitives::{
|
primitives::{
|
||||||
NetworkId, Coin, Amount, Balance, BlockHash, SeraiAddress, ExternalAddress,
|
NetworkId, Coin, Amount, Balance, BlockHash, SeraiAddress, ExternalAddress,
|
||||||
insecure_pair_from_name,
|
insecure_pair_from_name,
|
||||||
|
@ -211,7 +211,7 @@ async fn sign_test() {
|
||||||
let balance = Balance { coin: Coin::Serai, amount: Amount(1_000_000_000) };
|
let balance = Balance { coin: Coin::Serai, amount: Amount(1_000_000_000) };
|
||||||
serai
|
serai
|
||||||
.publish(&serai.sign(
|
.publish(&serai.sign(
|
||||||
&PairSigner::new(insecure_pair_from_name("Ferdie")),
|
&insecure_pair_from_name("Ferdie"),
|
||||||
&SeraiCoins::transfer(address, balance),
|
&SeraiCoins::transfer(address, balance),
|
||||||
0,
|
0,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
|
@ -219,7 +219,7 @@ async fn sign_test() {
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
(PairSigner::new(pair), address)
|
(pair, address)
|
||||||
};
|
};
|
||||||
|
|
||||||
#[allow(clippy::inconsistent_digit_grouping)]
|
#[allow(clippy::inconsistent_digit_grouping)]
|
||||||
|
|
|
@ -16,7 +16,7 @@ use serai_client::{
|
||||||
validator_sets::primitives::{Session, ValidatorSet},
|
validator_sets::primitives::{Session, ValidatorSet},
|
||||||
in_instructions::primitives::Shorthand,
|
in_instructions::primitives::Shorthand,
|
||||||
coins::primitives::{OutInstruction, OutInstructionWithBalance},
|
coins::primitives::{OutInstruction, OutInstructionWithBalance},
|
||||||
PairTrait, PairSigner, SeraiCoins,
|
PairTrait, SeraiCoins,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::tests::*;
|
use crate::tests::*;
|
||||||
|
@ -249,7 +249,7 @@ async fn mint_and_burn_test() {
|
||||||
let balance = Balance { coin: Coin::Serai, amount: Amount(1_000_000_000) };
|
let balance = Balance { coin: Coin::Serai, amount: Amount(1_000_000_000) };
|
||||||
serai
|
serai
|
||||||
.publish(&serai.sign(
|
.publish(&serai.sign(
|
||||||
&PairSigner::new(insecure_pair_from_name("Ferdie")),
|
&insecure_pair_from_name("Ferdie"),
|
||||||
&SeraiCoins::transfer(address, balance),
|
&SeraiCoins::transfer(address, balance),
|
||||||
0,
|
0,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
|
@ -257,7 +257,7 @@ async fn mint_and_burn_test() {
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
(PairSigner::new(pair), address)
|
(pair, address)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Send in BTC
|
// Send in BTC
|
||||||
|
|
Loading…
Reference in a new issue