Facebook Libra币开发指南---Move语言开发代币智能合约

7 篇文章 0 订阅
7 篇文章 0 订阅

由于Libra Core基本还处于试验阶段,还没有API和SDK,因此除了命令行之外,没有其他接口。虽然文档中有Move语言介绍,但是在目前的testnet上,还不支持部署基于Move语言的智能合约,因此使我们这种特别喜欢动手尝试的人,非常抓狂。不过还是有牛人,发现可以使用Libra的功能测试框架,来编写和运行Move语言编写的智能合约,所以我们也可以基于这种方法来尝试一把。

代币智能合约

我们可以使用Move语言来开发一个代币的智能合约,代码如下所示:

modules:

module Capability {

    // Capability is responsible for declaring an account's permissions.
    // We define the notion of an owner, minter and blacklisted.
    // Only the owner can assign blacklisted and minter capabilities.

    // The owner is defined by hardcoding its account before publishing the module.

    // -----------------------------------------------------------------

    // Declare owner as a resource. It's only meant to be published once
    resource Owner { }

    // Declare a resource that declares an address's capabilities.
    // Every address using EToken will need to publish a resource themselves.
    // However, only the owner can change its content.
    resource T {
        minter: bool,
        blacklisted: bool,
    }

    // Every account should execute this once before using Capability and EToken module.
    // If the sender is the hardcoded owner, then owner capability is published.
    // Reverts if already published
    public publish() {
        let sender: address;
        sender = get_txn_sender();

        // Publish owner capability if sender is the privileged account
        // Uncomment the following line in production and use a real owner account: if (move(sender) == 0x0) {
        if (true) {
            // Always branch to here when testing, otherwise the test can't complete as the sender address is randomly chosen.
            Self.grant_owner_capability();
        }

        // Publish a new capability with no permissions.
        move_to_sender<T>(T{ minter: false, blacklisted: false });

        return;    
    }

    // Internal function that grants owner capability
    grant_owner_capability() {
        move_to_sender<Owner>(Owner {});
        return;
    }

    // Grants minter capability to receiver, but can only succeed if sender owns the owner capability.
    public grant_minter_capability(receiver: address, owner_capability: &R#Self.Owner) {
        let capability_ref: &mut R#Self.T;

        release(move(owner_capability));

        // Pull a mutable reference to the receiver's capability, and change its permission.
        capability_ref = borrow_global<T>(move(receiver));
        *(&mut move(capability_ref).minter) = true;

        return;
    }

    // Grants blacklist capability to receiver, but can only succeed if sender owns the owner capability.
    public grant_blacklisted_capability(receiver: address, owner_capability: &R#Self.Owner) {
        let capability_ref: &mut R#Self.T;

        release(move(owner_capability));

        // Pull a mutable reference to the receiver's capability, and change its permission.
        capability_ref = borrow_global<T>(move(receiver));
        *(&mut move(capability_ref).blacklisted) = true;

        return;
    }

    // This returns an immutable reference to the owner capability if it exists.
    // Is used by the owner to show ownership to privileged functions.
    // Reverts if owner capability does not exist.
    public borrow_owner_capability(): &R#Self.Owner {
        let sender: address;
        let owner_capability_ref: &mut R#Self.Owner;
        let owner_capability_immut_ref: &R#Self.Owner;

        sender = get_txn_sender();
        owner_capability_ref = borrow_global<Owner>(move(sender));
        owner_capability_immut_ref = freeze(move(owner_capability_ref));

        return move(owner_capability_immut_ref);
    }

    // This returns an immutable reference to the general capability if it exists.
    // Should be used by every account to prove capabilities.
    // Reverts if capability does not exist.
    public borrow_capability(): &R#Self.T {
        let sender: address;
        let capability_ref: &mut R#Self.T;
        let capability_immut_ref: &R#Self.T;

        sender = get_txn_sender();
        capability_ref = borrow_global<T>(move(sender));
        capability_immut_ref = freeze(move(capability_ref));

        return move(capability_immut_ref);
    }

    // Return whether the capability allows minting.
    public is_minter(capability: &R#Self.T): bool {
        let is_minter: bool;
        is_minter = *(&move(capability).minter);
        return move(is_minter);
    }

    // Return true the capability is not blacklisted.
    public is_not_blacklisted(capability: &R#Self.T): bool {
        let is_blacklisted: bool;
        is_blacklisted = *(&move(capability).blacklisted);
        return !move(is_blacklisted);
    }

    // Reverts if capability does not allow minting
    public require_minter(capability: &R#Self.T) {
        let is_minter: bool;
        is_minter = Self.is_minter(move(capability));
        assert(move(is_minter), 0);
        return;
    }

    // Reverts if capability is blacklisted
    public require_not_blacklisted(capability: &R#Self.T) {
        let is_not_blacklisted: bool;
        is_not_blacklisted = Self.is_not_blacklisted(move(capability));
        assert(move(is_not_blacklisted), 0);
        return;
    }
}

module EToken {

    // This module is responsible for an actual eToken.
    // For it to be useful a capability has to be published by using the Capability module above.
    
    // -----------------------------------------------------------------

    import Transaction.Capability;

    // Declare the eToken resource, storing an account's total balance.
    resource T {
        value: u64,
    }

    // Publishes an initial zero eToken to the sender.
    // Should be called once before using this module.
    public publish() {
        move_to_sender<T>(T{ value: 0 });
        return;
    }

    // Mint new eTokens.
    // Reverts if capability does not allow it.
    public mint(value: u64, capability: &R#Capability.T): R#Self.T {
        Capability.require_minter(move(capability));
        return T{value: move(value)};
    }

    // Returns an account's eToken balance.
    // Reverts if an initial eToken hasn't been published.
    public balance(): u64 {
        let sender: address;
        let token_ref: &mut R#Self.T;
        let token_value: u64;

        sender = get_txn_sender();
        token_ref = borrow_global<T>(move(sender));
        token_value = *(&move(token_ref).value);

        return move(token_value);
    }

    // Deposit owned tokens to an payee's address, and destroy the tokens to deposit,
    // Reverts if user is blacklisted.
    public deposit(payee: address, to_deposit: R#Self.T, capability: &R#Capability.T) {
        let payee_token_ref: &mut R#Self.T;
        let payee_token_value: u64;
        let to_deposit_value: u64;

        Capability.require_not_blacklisted(move(capability));

        payee_token_ref = borrow_global<T>(move(payee));
        payee_token_value = *(&copy(payee_token_ref).value);

        // Unpack and destroy to_deposit tokens
        T{ value: to_deposit_value } = move(to_deposit);

        // Increase the payees balance with the destroyed token amount
        *(&mut move(payee_token_ref).value) = move(payee_token_value) + move(to_deposit_value);

        return;
    }

    // Withdraw an amount of tokens of the sender and return it.
    // This works by splitting the token published and returning the specified amount as tokens. 
    public withdraw(amount: u64, capability: &R#Capability.T): R#Self.T {
        let sender: address;
        let sender_token_ref: &mut R#Self.T;
        let value: u64;

        Capability.require_not_blacklisted(move(capability));

        sender = get_txn_sender();
        sender_token_ref = borrow_global<T>(move(sender));
        value = *(&copy(sender_token_ref).value);

        // Make sure that sender has enough tokens
        assert(copy(value) >= copy(amount), 1);

        // Split the senders token and return the amount specified
        *(&mut move(sender_token_ref).value) = move(value) - copy(amount);
        return T{ value: move(amount) };
    }
}

script:

// Performs simple testing to crudely verify the published modules above.

import Transaction.Capability;
import Transaction.EToken;

main() {
    let sender: address;
    let owner_capability: &R#Capability.Owner;
    let capability: &R#Capability.T;
    let minted_tokens: R#EToken.T;
    let balance: u64;

    sender = get_txn_sender();

    // Publish initial capability
    Capability.publish();

    // Borrow owner_capability for minter delegation
    owner_capability = Capability.borrow_owner_capability();

    // Delegate itself as a minter
    Capability.grant_minter_capability(copy(sender), move(owner_capability));

    // Borrow general capability for proof of minting capability
    capability = Capability.borrow_capability();

    // Publish an eToken account
    EToken.publish();

    // Mint 100 eTokens and prove minter capability
    minted_tokens = EToken.mint(100, copy(capability));

    // Deposit the freshly minted tokens to itself
    EToken.deposit(move(sender), move(minted_tokens), move(capability));

    // Test that the balance corresponds with the intended behaviour
    balance = EToken.balance();
    assert(move(balance) == 100, 3);

    return;
}

将该文件保存到language/functional_tests/tests/testsuite/modules/目录下,然后运行如下命令:

cargo test -p functional_tests eToken

运行结果如下所示:
在这里插入图片描述

### 回答1: Libra R-CNN是Facebook AI Research团队于2019年提出的一种目标检测算法,它采用了一种新的思路——将目标检测过程分为两个阶段:先使用高效的RPN网络生成候选框,再使用分类器对候选框进行分类和回归。这种方法可以大大提高检测效率,同时保持较高的精度。与传统的Faster R-CNN相比,Libra R-CNN的检测速度快了近3倍,同时保持了相当的精度。 ### 回答2: Libra R-CNN是由Facebook AI Research团队在2019年提出的一种目标检测算法。目标检测是计算机视觉中的一个重要任务,旨在识别和定位图像中的不同目标。 Libra R-CNN的设计目标是解决目标检测中存在的两个挑战:不平衡的目标类别分布和多尺度目标的检测问题。在目标类别分布上,一些类别的目标在数据集中往往是非常罕见的,这导致传统的目标检测算法在罕见类别上的性能较差。而在多尺度目标的检测上,由于图像中的目标可能具有不同的尺度,传统的目标检测算法在检测小目标和大目标时往往表现不佳。 Libra R-CNN通过引入新的损失函数和网络结构来解决这两个问题。其中,采用了一种新的正负样本选择策略来平衡不同目标类别的分布,使得模型能够更好地处理罕见类别的目标。此外,通过引入一个多尺度特征融合模块,Libra R-CNN能够有效地处理不同尺度的目标,提高目标检测的性能。 实验证明,Libra R-CNN在多个目标检测数据集上取得了很好的性能表现,相较于其他目标检测算法具有更好的检测准确性和鲁棒性。该算法在推动目标检测技术的发展上具有重要的意义,为解决目标检测中的挑战提供了新的思路和方法。 总之,Libra R-CNN是一种解决目标检测中不平衡目标类别分布和多尺度目标检测问题的算法,通过引入新的损失函数和网络结构,取得了很好的性能表现。它对于推动目标检测技术的发展具有重要的意义。 ### 回答3: Libra R-CNN是一种基于目标检测和实例分割的深度学习模型算法。它被设计用于解决目标检测中存在的物体不平衡问题,即训练样本中不同类别的物体数量差异过大。通常,在目标检测任务中,一些常见的物体类别(如人、车)的样本数量会远远超过其他类别,这会导致模型过度关注于此类常见类别而忽略其他类别。而Libra R-CNN就是为了解决这个问题而提出的。 Libra R-CNN的核心思想是通过引入一种新的调节因子,对损失函数进行重新定义,从而有效平衡不同类别的物体样本的权重。这个调节因子综合考虑了每个类别的物体例子在整个训练集中出现的频率,以及目标检测任务中不同类别之间的难易程度。通过对不同类别样本的权重进行调整,Libra R-CNN能够更加均衡地对待训练集中的不同类别物体,提高模型对少样本类别的检测能力。 此外,Libra R-CNN还引入了一种新的网络结构,叫做Libra引导采样(Libra RoI Sampling)。这个结构能够根据样本的难易程度,自适应地调整样本的采样比例,让模型更加关注难以检测的类别。通过这种方式,Libra R-CNN在目标检测中取得了较好的性能。 综上所述,Libra R-CNN是一种通过引入调节因子和采样策略来解决目标检测中物体不平衡问题的算法模型。它的提出有效地解决了训练样本中不同类别物体数量差异过大的问题,提高了对少样本类别的检测能力,并在目标检测任务中取得了较好的性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值