#time #ethereum #blockchain #boost #transaction #timestamp #discrete

timeboost-rs

区块链交易离散时间提升协议的 Rust 实现

5 个版本

0.1.5 2023 年 8 月 21 日
0.1.4 2023 年 8 月 21 日
0.1.3 2023 年 8 月 21 日
0.1.1 2023 年 8 月 21 日
0.1.0 2023 年 8 月 21 日

#2313魔法豆

MIT/Apache

29KB
370

Timeboost-rs

此库实现了 时间提升排序策略,用于 Rust 中的区块链交易。

Security audit Rust Rust Documentation

该协议由 @OffchainLabs 研究员 Akaki Mamageishvili、Mahimna Kelkar、Ed Felten 和伦敦大学 Jan Christoph Schlegel 编写的名为 "购买时间:延迟竞赛与交易排序竞标" 的研究论文所描述。此 crate 中实现的所有想法都是上述研究的结果。

时间提升是一种对交易进行公平排序的方法,它考虑时间戳和竞标来创建一个分数,该分数可以用于对 rollup 序列化器进行排序。它支持低延迟最终性,类似于先到先得,但对用户更加公平。有了时间提升,竞标可以帮助在最终排序中购买时间,但最多只能购买一个常数因子 G(以毫秒为单位)。

此库包含 Rust 代码,定义了一个异步的 TimeBoostService,可以通过输入通道接收交易,并通过在内部应用协议,持续输出最终排序列表。此实现是时间提升协议的“离散”版本,因为它在时间 G 的轮次中运行。以下是它的工作原理:

  1. 记录初始时间戳,T
  2. 在后台接收交易,将它们推送到按竞标排序的优先队列中(如果有时间戳相同的情况,则按最早到达时间戳解决冲突)
  3. 在时间 T+G,其中 G 是定义在毫秒中的常数,所有在优先队列中的交易都将被释放,并且它们的时戳将被修改为它们在输出流中发射的时间。
  4. T = T_now 重新开始计数,直到下一轮

感谢 Ed Felten 提出的想法。

依赖项

Rust 稳定版本 1.71.1

使用方法

使用此库的主要方法是使用一个事务输出通道初始化 TimeBoostService 结构体。

use timeboost_rs::TimeBoostService;
use tokio::sync::broadcast;

let (tx_output_feed, mut rx) = broadcast::channel(100);
let mut service = TimeBoostService::new(tx_output_feed);

可以通过选项配置服务,以自定义最大提升因子 G 或事务输入通道的容量。

let mut service = TimeBoostService::new(tx_output_feed)
                    .input_feed_buffer_capacity(1000)
                    .g_factor(200 /* millis */);

放入此服务的事务类型为 BoostableTx,它是由三个字段组成的简单结构体。

pub struct BoostableTx {
    pub id: u64,
    pub bid: u64,
    pub timestamp: NaiveDateTime,
}

BoostableTx 根据 时间提升规范实现了 Ord 特性,这意味着它们按最大出价排序,出价相同的情况下按最早时间戳作为平局决定。要使用自定义事务类型与 TimeBoostService 一起使用,为您自己的类型实现 From 特性。

以下是一个使用时间提升、向其中发送事务以及接收输出的完整示例。

use timeboost_rs::{TimeBoostService, BoostableTx};
use tokio::sync::broadcast;

#[tokio::main]
async fn main() {
    let (tx_output_feed, mut rx) = broadcast::channel(100);
    let mut service = TimeBoostService::new(tx_output_feed);

    // Obtain a channel handle to send txs to the TimeBoostService.
    let sender = service.sender();

    // Spawn a dedicated thread for the time boost service.
    std::thread::spawn(move || service.run());

    let mut txs = vec![
        BoostableTx::new(0 /* id */, 1 /* bid */, 100 /* unix timestamp millis */),
        BoostableTx::new(1 /* id */, 100 /* bid */, 101 /* unix timestamp millis */),
    ];

    // Send the txs to the time boost service.
    for tx in txs.iter() {
        sender.send(tx.clone()).unwrap();
    }

    // Await receipt of both txs from the timeboost service's output feed.
    let mut got_txs = vec![];
    for _ in 0..2 {
        let tx = rx.recv().await.unwrap();
        got_txs.push(tx);
    }

    // Assert we received 2 txs from the output feed.
    assert_eq!(txs.len(), 2);

    // Assert the output is the same as the reversed input, as
    // the highest bid txs will be released first.
    txs.reverse();
    let want = txs.into_iter().map(|tx| tx.id).collect::<Vec<_>>();
    let got = got_txs.into_iter().map(|tx| tx.id).collect::<Vec<_>>();
    assert_eq!(want, got);
}

度量指标

该库公开了一个 TIME_BOOST_ROUNDS_TOTAL prometheus 计数器,用于检查经过的轮数。

lazy_static! {
    static ref TIME_BOOST_ROUNDS_TOTAL: IntCounter = register_int_counter!(
        "timeboost_rounds_total",
        "Number of time boost rounds elapsed"
    )
    .unwrap();
}

许可证

根据您的选择,在 Apache 许可证 2.0 版MIT 许可证 下授权。

除非您明确声明,否则根据 Apache-2.0 许可证定义的,您有意提交的任何贡献,均应按上述方式双重许可,不附加任何额外条款或条件。

依赖项

~6–13MB
~147K SLoC