上一篇文章介绍了Bitcoin Computer的基本原理和特点,本文介绍Bitcoin Computer如何对比特币进行操作。
Bitcoin Computer的合约还有一个保留成员变量_amount。这个成员变量用于控制合约所在输出的比特币数量,单位为聪。结合上一篇讲到的另一个保留成员变量_owners,就可以实现比特币转账了。
钞票合约解析
我们来看一个钞票合约的例子。
import Computer from 'bitcoin-computer';
class Cash {
constructor(amount) {
this._amount = amount
}
transfer(to) {
this._owners = [to]
}
}
(async () => {
const computerA = new Computer.default({
seed: 'the mnemonic words',
chain: 'BSV',
network: 'testnet'
});
const computerB = new Computer.default({
seed: 'different mnemonic words',
chain: 'BSV',
network: 'testnet'
});
let cash = await computerA.new(Cash, [1000]);
console.log(cash);
await cash.transfer(computerB.db.wallet.getPublicKey().toString());
console.log(cash);
cash = await computerB.sync(cash._rev);
await cash.transfer(computerA.db.wallet.getPublicKey().toString());
console.log(cash);
})();
- 定义一个钞票合约。构造函数的参数对
_amount进行初始化,这在合约部署时确定了对应output的聪数。transfer方法相当于把钞票的使用权转给谁。 - 用两组不同的助记词定义两个
Computer实例,用于更换钞票的所属权。 - 用
computerA部署合约,面额1000聪,此时所属权归computerA。 - 调用
transfer方法把钞票所有权转给computerB。 computerB把合约同步下来,再转回给computerA。
合约部署之后的cash变量值如下:
Cash {
_amount: 1000,
_id: '3323850d869658f5a89b832d359c1cbb308caa3ff2a4e19c28e837878a8f31ad:0',
_rev: '3323850d869658f5a89b832d359c1cbb308caa3ff2a4e19c28e837878a8f31ad:0',
_rootId: '3323850d869658f5a89b832d359c1cbb308caa3ff2a4e19c28e837878a8f31ad:0'
}
_amount变量的值为1000,那么该输出里也应该有1000聪。查看区块浏览器,发现确实如此。
另外,脚本输出中多签名的公钥为03367b59cc6ba5cdb93b3bdc61c7018655462251b3608383c5a1b4adcf5f1bcc1f。同时javascript创建实例的代码也附在了脚本中,上一篇文章中我们已经解释过了。
computerA调用transfer方法后,cash变量值如下:
Cash {
_amount: 1000,
_id: '3323850d869658f5a89b832d359c1cbb308caa3ff2a4e19c28e837878a8f31ad:0',
_rev: '2db31d5718b491d5bfb69c8acdf7b952571c547653020f2d5b382fdd00156b12:0',
_rootId: '3323850d869658f5a89b832d359c1cbb308caa3ff2a4e19c28e837878a8f31ad:0',
_owners: [
'02c9788a60264523ba77500e19a0b2626c9b09b25daa16cfee09b4e1135d610c90'
]
}
查看区块链浏览器,合约输出里依然保持了1000聪,但多签名的公钥已经改为02c9788a60264523ba77500e19a0b2626c9b09b25daa16cfee09b4e1135d610c90,相当于解锁权已经给了computerB。
computerB把合约数据同步过来,再调用transfer方法转给computerA。cash变量值如下:
Cash {
_amount: 1000,
_rev: '258f09ca6649a4c7e1e980df2e1bf7467f48b815b3008fcc4701730c6ab66837:0',
_id: '3323850d869658f5a89b832d359c1cbb308caa3ff2a4e19c28e837878a8f31ad:0',
_rootId: '3323850d869658f5a89b832d359c1cbb308caa3ff2a4e19c28e837878a8f31ad:0',
_owners: [
'03367b59cc6ba5cdb93b3bdc61c7018655462251b3608383c5a1b4adcf5f1bcc1f'
]
}
查看区块链浏览器,合约输出还是1000聪,多签名的公钥又改回了03367b59cc6ba5cdb93b3bdc61c7018655462251b3608383c5a1b4adcf5f1bcc1f,相当于解锁权又还给了computerA。
通过这样一个合约,大家就理解_amount的作用了:决定合约输出的聪数。
合约手续费
大家可能会有个疑问,1000聪转来转去没变,那转账手续费是谁出的?可以在区块浏览器中查看前面几笔转账,观察可以发现,手续费是由执行合约的Computer示例出的。即:
- 合约部署时,由
computerA出手续费。同时也出了1000聪放到合约输出中。出钱的地址为mjg7nQ4VuJ3rTws8QFAD3NMMs1YgtzDm7C,也就是公钥03367b59cc6ba5cdb93b3bdc61c7018655462251b3608383c5a1b4adcf5f1bcc1f对应的地址。 computerA调用合约的transfer方法时,手续费也是从自己的地址mjg7nQ4VuJ3rTws8QFAD3NMMs1YgtzDm7C出的。computerB调用合约的transfer方法是,手续费从computerB的地址mpkhoZmfrxAAnU5mAv5yKcY83pYqWxh6jT转出,也就是公钥02c9788a60264523ba77500e19a0b2626c9b09b25daa16cfee09b4e1135d610c90对应的地址。
也就是说,手续费是由执行合约的Computer实例的P2PKH地址出。
从合约转出部分比特币
前面我用把1000聪面额的cash全面额转出,那是否可以部分转出呢?也是可以的。我们看如下程序:
import Computer from 'bitcoin-computer';
class Cash {
constructor(amount) {
this._amount = amount
}
transfer(amount, to) {
this._amount = amount;
this._owners = [to]
}
}
(async () => {
const computerA = new Computer.default({
seed: 'the mnemonic words',
chain: 'BSV',
network: 'testnet'
});
const computerB = new Computer.default({
seed: 'different mnemonic words',
chain: 'BSV',
network: 'testnet'
});
let cash = await computerA.new(Cash, [2000]);
await cash.transfer(1000, computerB.db.wallet.getPublicKey().toString());
console.log(cash);
})();
对Cash合约的代码进行了改进,transfer方法允许携带amount参数来明确转多少聪。
computerA向合约中部署了2000聪,但只转给了computerB1000聪,通过区块链浏览器可以看到,这次transfer执行操作的tx把剩下的币转到了computerA控制的地址mjg7nQ4VuJ3rTws8QFAD3NMMs1YgtzDm7C中,也就是说转到了合约执行者的地址。
同时,还可以看到,这笔转账的手续费是从部署到合约中的2000聪里出的。
总结
Bitcoin Computer通过保留成员变量_amount,可以对合约输出中的比特币数进行控制,结合_owners变量,可以完成对比特币的转账。
下一篇我们将介绍Bitcoin Computer的token方案。




