#transaction #processor #wavelet #write #transfer #sender #account

transaction-processor

使用 Rust 编写 Wavelet 的交易处理器

2 个版本

使用旧的 Rust 2015

0.0.1 2018 年 11 月 8 日
0.0.0 2018 年 8 月 27 日

#12#wavelet

MIT 许可证

18KB
340

transaction-processor-rs

文档

使用 Rust 编写 Wavelet 的交易处理器。

什么是交易处理器?

在 Wavelet 中,当接受有效交易时,它会应用于账本状态。交易处理器定义了交易对账本状态应有什么影响。

例如,如 builtin/money 中定义的,标记为 transfer 的交易,如果有效,应从发送者账户的余额中扣除 amount PERLs,并将扣除的余额添加到 recipient 账户。

编写自己的交易处理器

每次应用交易时都会调用交易处理器。交易处理器的入口函数应有签名 (context: TransactionContext) -> ProcessResult<()>。参数 context 包含交易的 标记负载,其中 标记 用于其类型,而 负载 包含处理器定义的信息。在入口函数内部,您应将 context.tag 与您自己定义的标记进行匹配,并且只有在标记是您想要的时才执行您的逻辑。否则,什么也不做并返回 Err(ProcessError::Ignore)

编写完入口函数后,使用宏 processor_entry!(your_entry); 进行注册。交易处理器只能有一个入口函数。

让我们以内置的 money 处理器(处理 transfer 交易)为例。

首先,我们定义所有必要的序列化和反序列化数据结构

#[derive(Deserialize)]
pub struct Transfer {
    recipient: String,
    amount: u64,
}

#[derive(Serialize)]
pub struct ContractReason {
    pub kind: String,
    pub details: TransferReason,
}

#[derive(Serialize)]
pub struct TransferReason {
    pub amount: u64,
    pub sender: String,
}

然后是入口函数

// We name the entry as `handle_transaction`; Can change to whatever your want.
fn handle_transaction(context: TransactionContext) -> ProcessResult<()> {
    // Match on the transaction tag.
    match context.tag.as_str() {
        "transfer" => {
            // Read and decode the payload as type `Transfer`.
            let payload: Transfer = context.read_payload()?;

            // Load transaction sender.
            // Currently, most information about the transaction is kept as immutable global state.
            let sender = Account::sender();

            // Load transaction recipient with `payload.recipient` as its ID.
            let recipient = Account::load(&payload.recipient);

            // Invoke the builtin `transfer` operation.
            transaction_processor::transfer::transfer(&sender, &recipient, payload.amount)?;

            // Build activation reason for the smart contract system.
            let reason = transaction_processor::serde_json::to_vec(&ContractReason {
                kind: "transfer".into(),
                details: TransferReason {
                    amount: payload.amount,
                    sender: Account::sender_id(),
                },
            }).unwrap();

            // If the recipient is a smart contract, activate it.
            transaction_processor::contract::activate(&payload.recipient, &reason)?;

            Ok(())
        }
        _ => Err(ProcessError::Ignore), // Ignore any transactions we don't understand.
    }
}

注册入口

processor_entry!(handle_transaction);

构建

请确保您已安装带有 wasm32-unknown-unknown 目标的最新稳定 Rust 工具链。如果您尚未安装目标,请使用以下命令进行安装:

rustup target add wasm32-unknown-unknown

然后,在您的项目目录下运行

cargo build --release --target wasm32-unknown-unknown

贡献

我们在 Perlin 喜欢与开源社区互动,并且愿意接受问题和拉取请求。

对于所有代码贡献,请确保它们尽可能遵循以下指南

  1. 修复 Rust 编译器生成的所有警告,除非在某些非常特殊的情况下。
  2. 提交信息格式为 module_name: 将按下的内容 as 作为一句话 这使得我们的维护者和其他人都能知道您希望解决的具体代码更改。
  3. 考虑向后兼容性。新方法是完全可以接受的,但例如更改现有公共 API 应仅在有充分理由的情况下进行。

如果您...

  1. 喜欢我们正在做的工作,
  2. 想要全职与我们合作,
  3. 或者对为开源项目工作并获得报酬感兴趣

... 我们在招聘

为了吸引我们的注意,只需提交一个 PR 并开始贡献。

依赖项

~0.7–1.4MB
~33K SLoC