snapshot before rebranding

This commit is contained in:
2025-12-14 07:37:21 +03:00
parent 5520d491a5
commit 09735eb97a
1752 changed files with 58116 additions and 15986 deletions
@@ -0,0 +1,370 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
use crate::{
error::Error,
helpers::StreamOf,
transaction::{AccountMetadata, Transaction, TransactionStatus},
};
use futures::stream::{self};
use futures_util::StreamExt;
use serde::{Deserialize, Serialize};
use std::{
any::Any,
fmt,
str::FromStr,
sync::atomic::{AtomicUsize, Ordering},
time::Duration,
};
use subxt::ext::codec::{Decode, Encode};
use tokio::task::yield_now;
use tracing::trace;
pub(crate) const LOG_TARGET: &str = "fake_tx";
#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Encode, Decode)]
#[serde(try_from = "String", into = "String")]
pub(crate) struct FakeHash([u8; 4]);
impl AsRef<[u8]> for FakeHash {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl From<[u8; 4]> for FakeHash {
fn from(value: [u8; 4]) -> Self {
Self(value)
}
}
impl fmt::Debug for FakeHash {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", hex::encode(self.0))
}
}
impl fmt::Display for FakeHash {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", hex::encode(self.0))
}
}
impl FromStr for FakeHash {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut bytes = [0; 4];
hex::decode_to_slice(s, &mut bytes).map_err(|_| "hex::decode failed".to_string())?;
Ok(FakeHash(bytes))
}
}
impl From<FakeHash> for String {
fn from(hash: FakeHash) -> Self {
hex::encode(hash.0)
}
}
impl TryFrom<String> for FakeHash {
type Error = String;
fn try_from(value: String) -> Result<Self, Self::Error> {
FakeHash::from_str(&value)
}
}
#[derive(Clone)]
pub struct EventDef {
event: TransactionStatus<FakeHash>,
delay: u32,
}
impl EventDef {
pub fn validated(delay: u32) -> Self {
Self { event: TransactionStatus::Validated, delay }
}
pub fn broadcasted(delay: u32) -> Self {
Self {
//todo
event: TransactionStatus::Broadcasted,
delay,
}
}
pub fn in_block(h: u32, delay: u32) -> Self {
Self { event: TransactionStatus::InBlock(h.to_le_bytes().into()), delay }
}
pub fn finalized(h: u32, delay: u32) -> Self {
Self { event: TransactionStatus::Finalized(h.to_le_bytes().into()), delay }
}
pub fn dropped(delay: u32) -> Self {
Self { event: TransactionStatus::Dropped("xxx".to_string()), delay }
}
pub fn invalid(delay: u32) -> Self {
Self { event: TransactionStatus::Invalid("xxx".to_string()), delay }
}
pub fn error(delay: u32) -> Self {
Self { event: TransactionStatus::Error("xxx".to_string()), delay }
}
}
#[derive(Clone)]
pub(crate) struct EventsStreamDef(pub Vec<EventDef>);
impl From<Vec<EventDef>> for EventsStreamDef {
fn from(value: Vec<EventDef>) -> Self {
Self(value)
}
}
pub(crate) struct FakeTransaction {
hash: FakeHash,
stream_def: Vec<EventsStreamDef>,
current_stream_def: AtomicUsize,
nonce: u128,
account_metadata: AccountMetadata,
}
impl Transaction for FakeTransaction {
type HashType = FakeHash;
fn hash(&self) -> Self::HashType {
self.hash
}
fn as_any(&self) -> &dyn Any {
self
}
fn nonce(&self) -> u128 {
self.nonce
}
fn account_metadata(&self) -> AccountMetadata {
self.account_metadata.clone()
}
fn valid_until(&self) -> &Option<u64> {
&None
}
}
#[allow(dead_code)]
impl FakeTransaction {
pub(crate) fn get_current_stream_def(&self) -> EventsStreamDef {
self.stream_def[self.current_stream_def.load(Ordering::Relaxed)].clone()
}
pub(crate) fn new_multiple(index: u32, nonce: u128, stream_def: Vec<EventsStreamDef>) -> Self {
Self {
stream_def,
hash: index.to_le_bytes().into(),
current_stream_def: Default::default(),
nonce,
account_metadata: AccountMetadata::Derived(index),
}
}
pub(crate) fn new_with_keyring(
account: String,
nonce: u128,
stream_def: Vec<EventsStreamDef>,
) -> Self {
let acc_as_bytes = account.as_bytes();
Self {
stream_def,
hash: [acc_as_bytes[0], acc_as_bytes[1], acc_as_bytes[2], acc_as_bytes[3]].into(),
current_stream_def: Default::default(),
nonce,
account_metadata: AccountMetadata::KeyRing(account),
}
}
pub(crate) fn new(index: u32, nonce: u128, stream_def: EventsStreamDef) -> Self {
Self {
stream_def: vec![stream_def],
hash: index.to_le_bytes().into(),
current_stream_def: Default::default(),
nonce,
account_metadata: AccountMetadata::Derived(index),
}
}
pub(crate) fn new_inblock_then_droppable_2nd_success(
hash: u32,
nonce: u128,
delay: u32,
) -> Self {
Self::new_multiple(
hash,
nonce,
vec![
EventsStreamDef(vec![
EventDef::broadcasted(delay),
EventDef::validated(delay),
EventDef::in_block(1, delay),
EventDef::in_block(2, delay),
EventDef::in_block(3, delay),
EventDef::dropped(delay),
]),
EventsStreamDef(vec![
EventDef::broadcasted(delay),
EventDef::validated(delay),
EventDef::in_block(1, delay),
EventDef::in_block(2, delay),
EventDef::in_block(3, delay),
EventDef::finalized(2, delay),
]),
],
)
}
pub(crate) fn new_droppable_2nd_success(hash: u32, nonce: u128, delay: u32) -> Self {
Self::new_multiple(
hash,
nonce,
vec![
EventsStreamDef(vec![EventDef::dropped(delay)]),
EventsStreamDef(vec![
EventDef::broadcasted(delay),
EventDef::validated(delay),
EventDef::in_block(1, delay),
EventDef::in_block(2, delay),
EventDef::in_block(3, delay),
EventDef::finalized(2, delay),
]),
],
)
}
pub(crate) fn new_droppable_loop(hash: u32, nonce: u128, delay: u32) -> Self {
Self::new_multiple(
hash,
nonce,
vec![
EventsStreamDef(vec![EventDef::dropped(delay)]),
EventsStreamDef(vec![EventDef::dropped(delay)]),
EventsStreamDef(vec![EventDef::dropped(delay)]),
EventsStreamDef(vec![EventDef::dropped(delay)]),
EventsStreamDef(vec![EventDef::dropped(delay)]),
],
)
}
pub(crate) fn new_droppable(hash: u32, nonce: u128, delay: u32) -> Self {
Self::new(hash, nonce, EventsStreamDef(vec![EventDef::dropped(delay)]))
}
pub(crate) fn new_invalid(hash: u32, nonce: u128, delay: u32) -> Self {
Self::new(hash, nonce, EventsStreamDef(vec![EventDef::invalid(delay)]))
}
pub(crate) fn new_error(hash: u32, nonce: u128, delay: u32) -> Self {
Self::new(hash, nonce, EventsStreamDef(vec![EventDef::error(delay)]))
}
pub(crate) fn new_finalizable_quick(hash: u32, nonce: u128) -> Self {
let delay = 0;
Self::new(
hash,
nonce,
EventsStreamDef(vec![
EventDef::broadcasted(delay),
EventDef::validated(delay),
EventDef::in_block(1, delay),
EventDef::in_block(2, delay),
EventDef::in_block(3, delay),
EventDef::finalized(2, delay),
]),
)
}
pub(crate) fn new_finalizable(hash: u32, nonce: u128) -> Self {
Self::new(
hash,
nonce,
EventsStreamDef(vec![
EventDef::broadcasted(100),
EventDef::validated(300),
EventDef::in_block(1, 1000),
EventDef::in_block(2, 1000),
EventDef::in_block(3, 1000),
EventDef::finalized(2, 2000),
]),
)
}
pub(crate) fn events(&self) -> StreamOf<TransactionStatus<FakeHash>> {
let def = self.get_current_stream_def();
stream::unfold(def.0.into_iter(), move |mut i| async {
yield_now().await;
if let Some(EventDef { event, delay }) = i.next() {
if delay > 0 {
tokio::time::sleep(Duration::from_millis(delay.into())).await;
}
trace!(target:LOG_TARGET, ?event, ?delay, "play");
Some((event, i))
} else {
None
}
})
.boxed()
}
pub(crate) async fn submit_result(&self) -> Result<FakeHash, Error> {
let EventDef { event, delay } = self
.get_current_stream_def()
.0
.pop()
.expect("there shall be at least event. qed.");
if delay > 0 {
tokio::time::sleep(Duration::from_millis(delay.into())).await;
}
trace!(target:LOG_TARGET, "submit_result: delayed: {:?}", self.hash);
match event {
TransactionStatus::Finalized(_) => Ok(self.hash),
TransactionStatus::Dropped(message) =>
Err(Error::Other(format!("submit-error:dropped:{message}").to_string())),
TransactionStatus::Invalid(message) =>
Err(Error::Other(format!("submit-error:invalid:{message}").to_string())),
TransactionStatus::Error(message) =>
Err(Error::Other(format!("submit-error:error:{message}").to_string())),
TransactionStatus::Validated |
TransactionStatus::NoLongerInBestBlock |
TransactionStatus::Broadcasted |
TransactionStatus::InBlock(_) => todo!(),
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::init_logger;
#[tokio::test]
async fn fake_transaction_events() {
init_logger();
let t = FakeTransaction::new(
1,
0,
EventsStreamDef(vec![
EventDef::broadcasted(100),
EventDef::validated(300),
EventDef::in_block(1, 1000),
EventDef::in_block(2, 1000),
EventDef::in_block(3, 1000),
EventDef::finalized(2, 2000),
]),
);
let v = t.events().collect::<Vec<_>>().await;
assert_eq!(
v,
vec![
TransactionStatus::Broadcasted,
TransactionStatus::Validated,
TransactionStatus::InBlock(1u32.to_le_bytes().into()),
TransactionStatus::InBlock(2u32.to_le_bytes().into()),
TransactionStatus::InBlock(3u32.to_le_bytes().into()),
TransactionStatus::Finalized(2u32.to_le_bytes().into())
]
);
tracing::info!("{v:?}")
}
}