一般智能合约需要以下几个步骤:
1.编写智能合约
2.部署智能合约
3.调用智能合约,验证合约执行结果

编写智能合约

Nebulas实现了NVM虚拟机来运行智能合约,NVM的实现使用了JavaScript V8引擎,所以我们可以使用JavaScript、TypeScript来编写智能合约。

编写智能合约的简要规范:
1.智能合约代码必须是一个Prototype的对象;
2.智能合约代码必须有一个init()的方法,这个方法只会在部署的时候被执行一次;
3.智能合约里面的私有方法是以_开头的方法,私有方法不能被外部直接调用;

我们使用JavaScript来编写第一个智能合约:银行保险柜。 这个智能合约需要实现以下功能:
1.用户可以向这个银行保险柜存钱。
2.用户可以从这个银行保险柜取钱。
3.用户可以查询银行保险柜中的余额。
智能合约示例:

'use strict';var DepositeContent = function (text) {if (text) {var o = JSON.parse(text);this.balance = new BigNumber(o.balance);this.expiryHeight = new BigNumber(o.expiryHeight);} else {this.balance = new BigNumber(0);this.expiryHeight = new BigNumber(0);}
};DepositeContent.prototype = {toString: function () {return JSON.stringify(this);}
};var BankVaultContract = function () {LocalContractStorage.defineMapProperty(this, "bankVault", {parse: function (text) {return new DepositeContent(text);},stringify: function (o) {return o.toString();}});
};// save value to contract, only after height of block, users can takeout
BankVaultContract.prototype = {init: function () {//TODO:},save: function (height) {var from = Blockchain.transaction.from;var value = Blockchain.transaction.value;var bk_height = new BigNumber(Blockchain.block.height);var orig_deposit = this.bankVault.get(from);if (orig_deposit) {value = value.plus(orig_deposit.balance);}var deposit = new DepositeContent();deposit.balance = value;deposit.expiryHeight = bk_height.plus(height);this.bankVault.put(from, deposit);},takeout: function (value) {var from = Blockchain.transaction.from;var bk_height = new BigNumber(Blockchain.block.height);var amount = new BigNumber(value);var deposit = this.bankVault.get(from);if (!deposit) {throw new Error("No deposit before.");}if (bk_height.lt(deposit.expiryHeight)) {throw new Error("Can not takeout before expiryHeight.");}if (amount.gt(deposit.balance)) {throw new Error("Insufficient balance.");}var result = Blockchain.transfer(from, amount);if (!result) {throw new Error("transfer failed.");}Event.Trigger("BankVault", {Transfer: {from: Blockchain.transaction.to,to: from,value: amount.toString()}});deposit.balance = deposit.balance.sub(amount);this.bankVault.put(from, deposit);},balanceOf: function () {var from = Blockchain.transaction.from;return this.bankVault.get(from);},verifyAddress: function (address) {// 1-valid, 0-invalidvar result = Blockchain.verifyAddress(address);return {valid: result == 0 ? false : true};}
};
module.exports = BankVaultContract;

上面智能合约的示例可以看到,BankVaultContract是一个prototype对象,这个对象有一个init()方法,满足了我们说的编写智能合约最基础的规范。

BankVaultContract实现了另外两个方法:

  • save(): 用户可以通过调用save()方法向银行保险柜存钱;
  • takeout(): 用户可以通过调用takeout()方法向银行保险柜取钱;
  • balanceOf(): 用户可以通过调用balanceOf()方法向银行保险柜查询余额;

上面的合约代码用到了内置的Blockchain对象和内置的BigNumber()方法,下面我们来逐行拆解分析合约代码:

save():

// Deposit the amount into the safesave: function (height) {var from = Blockchain.transaction.from;var value = Blockchain.transaction.value;var bk_height = new BigNumber(Blockchain.block.height);var orig_deposit = this.bankVault.get(from);if (orig_deposit) {value = value.plus(orig_deposit.balance);}var deposit = new DepositeContent();deposit.balance = value;deposit.expiryHeight = bk_height.plus(height);this.bankVault.put(from, deposit);
},

takeout():

takeout: function (value) {var from = Blockchain.transaction.from;var bk_height = new BigNumber(Blockchain.block.height);var amount = new BigNumber(value);var deposit = this.bankVault.get(from);if (!deposit) {throw new Error("No deposit before.");}if (bk_height.lt(deposit.expiryHeight)) {throw new Error("Can not takeout before expiryHeight.");}if (amount.gt(deposit.balance)) {throw new Error("Insufficient balance.");}var result = Blockchain.transfer(from, amount);if (!result) {throw new Error("transfer failed.");}Event.Trigger("BankVault", {Transfer: {from: Blockchain.transaction.to,to: from,value: amount.toString()}});deposit.balance = deposit.balance.sub(amount);this.bankVault.put(from, deposit);
},
部署智能合约

上面介绍了在Nebulas中怎么去编写一个智能合约,现在我们需要把智能合约部署到链上。在Nebulas中部署一个智能合约其实也是发送一个transaction来实现,前面有介绍过用户如何在Nebulas中进行转账交易,由于是本地测试,我们直接使用解锁 & 发送的方式来发送交易。

首先,我们在conf/default/genesis.conf中预分配过代币的账户里,选择账户n1H4MYms9F55ehcvygwWE71J8tJC4CRr2so作为发送者账号,并检查该账户的状态。

curl -i -H Accept:application/json -X POST http://localhost:8685/v1/user/accountstate -d '{"address":"n1H4MYms9F55ehcvygwWE71J8tJC4CRr2so"}'
HTTP/1.1 200 OK
Content-Type: application/json
Vary: Origin
Date: Fri, 06 Jul 2018 13:49:39 GMT
Content-Length: 72{"result": {"balance": "4999999999999977984000000","nonce": "1","type": 87}
}

该账户有足够的钱来支付手续费,接下来,我们解锁发送者账户n1H4MYms9F55ehcvygwWE71J8tJC4CRr2so,解锁12小时。

curl -i -H 'Content-Type: application/json' -X POST http://localhost:8685/v1/admin/account/unlock -d '{"address":"n1H4MYms9F55ehcvygwWE71J8tJC4CRr2so","passphrase":"passphrase","duration":"43200000000000"}'
HTTP/1.1 200 OK
Content-Type: application/json
Vary: Origin
Date: Fri, 06 Jul 2018 13:52:02 GMT
Content-Length: 26{"result": {"result": true}
}

然后,我们发送部署BankVault合约的交易。

curl -i -H 'Accept: application/json' -X POST http://localhost:8685/v1/admin/transactionWithPassphrase -H 'Content-Type: application/json' -d '{"transaction": {"from":"n1H4MYms9F55ehcvygwWE71J8tJC4CRr2so","to":"n1H4MYms9F55ehcvygwWE71J8tJC4CRr2so", "value":"0","nonce":2,"gasPrice":"1000000","gasLimit":"2000000","contract":{"source":"\"use strict\";var DepositeContent=function(text){if(text){var o=JSON.parse(text);this.balance=new BigNumber(o.balance);this.expiryHeight=new BigNumber(o.expiryHeight);}else{this.balance=new BigNumber(0);this.expiryHeight=new BigNumber(0);}};DepositeContent.prototype={toString:function(){return JSON.stringify(this);}};var BankVaultContract=function(){LocalContractStorage.defineMapProperty(this,\"bankVault\",{parse:function(text){return new DepositeContent(text);},stringify:function(o){return o.toString();}});};BankVaultContract.prototype={init:function(){},save:function(height){var from=Blockchain.transaction.from;var value=Blockchain.transaction.value;var bk_height=new BigNumber(Blockchain.block.height);var orig_deposit=this.bankVault.get(from);if(orig_deposit){value=value.plus(orig_deposit.balance);} var deposit=new DepositeContent();deposit.balance=value;deposit.expiryHeight=bk_height.plus(height);this.bankVault.put(from,deposit);},takeout:function(value){var from=Blockchain.transaction.from;var bk_height=new BigNumber(Blockchain.block.height);var amount=new BigNumber(value);var deposit=this.bankVault.get(from);if(!deposit){throw new Error(\"No deposit before.\");} if(bk_height.lt(deposit.expiryHeight)){throw new Error(\"Can not takeout before expiryHeight.\");} if(amount.gt(deposit.balance)){throw new Error(\"Insufficient balance.\");} var result=Blockchain.transfer(from,amount);if(!result){throw new Error(\"transfer failed.\");} Event.Trigger(\"BankVault\",{Transfer:{from:Blockchain.transaction.to,to:from,value:amount.toString()}});deposit.balance=deposit.balance.sub(amount);this.bankVault.put(from,deposit);},balanceOf:function(){var from=Blockchain.transaction.from;return this.bankVault.get(from);},verifyAddress:function(address){var result=Blockchain.verifyAddress(address);return{valid:result==0?false:true};}};module.exports=BankVaultContract;","sourceType":"js", "args":""}}, "passphrase": "passphrase"}'
HTTP/1.1 100 ContinueHTTP/1.1 200 OK
Content-Type: application/json
Vary: Origin
Date: Fri, 06 Jul 2018 13:54:46 GMT
Content-Length: 145{"result": {"txhash": "b6d3f13146ee3533f55536230e08c3108bb7a074cc102a08c871dee6aa37ff58","contract_address": "n1joQPGKfM1PVRSZwrFqYzwx1Sc4xgaBM8k"}
}
  • from: 合约创建者账户地址
  • to: 和from一致,同为合约创建者地址
  • value:部署合约时为"0"
  • nonce: 比创建者当前的nonce多1,可以通过GetAccountState获取创建前当前nonce
  • gasPrice:部署智能合约用到的gasPrice,可以通过GetGasPrice获取,或者使用默认值:"1000000"
  • gasLimit: 部署合约的gasLimit,通过EstimateGas可以获取部署合约的gas消耗,不能使用默认值,也可以设置一个较大值,执行时以实际使用计算。
  • contract: 合约信息,部署合约时传入的参数
    • source: 合约代码
    • sourceType: 合约代码类型,支持jsts(对应javaScript和typeScript代码)
    • args: 合约初始化方法参数,无参数为空字符串,有参数时为JSON数组

部署智能合约的返回值是transaction的hash地址txhash和合约的部署地址contract_address。 得到返回值并不能保证合约已经部署成功,因为发送交易是一个异步的过程,需要经过矿工打包,正如之前的转账交易一样,转账并不能实时到账,依赖矿工打包的速度,所以需要等待一段时间,然后可以通过查询合约地址的信息或者调用智能合约来验证合约是否部署成功。

验证合约是否部署成功

在部署智能合约的时候得到了transaction的hash地址txhash,我们可以很方便的使用console控制台查询transaction的hash信息来验证合约是否部署成功。

curl -i -H 'Content-Type: application/json' -X POST http://localhost:8685/v1/user/getTransactionReceipt -d '{"hash":"b6d3f13146ee3533f55536230e08c3108bb7a074cc102a08c871dee6aa37ff58"}'
HTTP/1.1 200 OK
Content-Type: application/json
Vary: Origin
Date: Fri, 06 Jul 2018 14:02:39 GMT
Transfer-Encoding: chunked{"result": {"hash": "b6d3f13146ee3533f55536230e08c3108bb7a074cc102a08c871dee6aa37ff58","chainId": 100,"from": "n1H4MYms9F55ehcvygwWE71J8tJC4CRr2so","to": "n1H4MYms9F55ehcvygwWE71J8tJC4CRr2so","value": "0","nonce": "2","timestamp": "1530885286","type": "deploy","data": "eyJTb3VyY2VUeXBlIjoianMiLCJTb3VyY2UiOiJcInVzZSBzdHJpY3RcIjt2YXIgRGVwb3NpdGVDb250ZW50PWZ1bmN0aW9uKHRleHQpe2lmKHRleHQpe3ZhciBvPUpTT04ucGFyc2UodGV4dCk7dGhpcy5iYWxhbmNlPW5ldyBCaWdOdW1iZXIoby5iYWxhbmNlKTt0aGlzLmV4cGlyeUhlaWdodD1uZXcgQmlnTnVtYmVyKG8uZXhwaXJ5SGVpZ2h0KTt9ZWxzZXt0aGlzLmJhbGFuY2U9bmV3IEJpZ051bWJlcigwKTt0aGlzLmV4cGlyeUhlaWdodD1uZXcgQmlnTnVtYmVyKDApO319O0RlcG9zaXRlQ29udGVudC5wcm90b3R5cGU9e3RvU3RyaW5nOmZ1bmN0aW9uKCl7cmV0dXJuIEpTT04uc3RyaW5naWZ5KHRoaXMpO319O3ZhciBCYW5rVmF1bHRDb250cmFjdD1mdW5jdGlvbigpe0xvY2FsQ29udHJhY3RTdG9yYWdlLmRlZmluZU1hcFByb3BlcnR5KHRoaXMsXCJiYW5rVmF1bHRcIix7cGFyc2U6ZnVuY3Rpb24odGV4dCl7cmV0dXJuIG5ldyBEZXBvc2l0ZUNvbnRlbnQodGV4dCk7fSxzdHJpbmdpZnk6ZnVuY3Rpb24obyl7cmV0dXJuIG8udG9TdHJpbmcoKTt9fSk7fTtCYW5rVmF1bHRDb250cmFjdC5wcm90b3R5cGU9e2luaXQ6ZnVuY3Rpb24oKXt9LHNhdmU6ZnVuY3Rpb24oaGVpZ2h0KXt2YXIgZnJvbT1CbG9ja2NoYWluLnRyYW5zYWN0aW9uLmZyb207dmFyIHZhbHVlPUJsb2NrY2hhaW4udHJhbnNhY3Rpb24udmFsdWU7dmFyIGJrX2hlaWdodD1uZXcgQmlnTnVtYmVyKEJsb2NrY2hhaW4uYmxvY2suaGVpZ2h0KTt2YXIgb3JpZ19kZXBvc2l0PXRoaXMuYmFua1ZhdWx0LmdldChmcm9tKTtpZihvcmlnX2RlcG9zaXQpe3ZhbHVlPXZhbHVlLnBsdXMob3JpZ19kZXBvc2l0LmJhbGFuY2UpO30gdmFyIGRlcG9zaXQ9bmV3IERlcG9zaXRlQ29udGVudCgpO2RlcG9zaXQuYmFsYW5jZT12YWx1ZTtkZXBvc2l0LmV4cGlyeUhlaWdodD1ia19oZWlnaHQucGx1cyhoZWlnaHQpO3RoaXMuYmFua1ZhdWx0LnB1dChmcm9tLGRlcG9zaXQpO30sdGFrZW91dDpmdW5jdGlvbih2YWx1ZSl7dmFyIGZyb209QmxvY2tjaGFpbi50cmFuc2FjdGlvbi5mcm9tO3ZhciBia19oZWlnaHQ9bmV3IEJpZ051bWJlcihCbG9ja2NoYWluLmJsb2NrLmhlaWdodCk7dmFyIGFtb3VudD1uZXcgQmlnTnVtYmVyKHZhbHVlKTt2YXIgZGVwb3NpdD10aGlzLmJhbmtWYXVsdC5nZXQoZnJvbSk7aWYoIWRlcG9zaXQpe3Rocm93IG5ldyBFcnJvcihcIk5vIGRlcG9zaXQgYmVmb3JlLlwiKTt9IGlmKGJrX2hlaWdodC5sdChkZXBvc2l0LmV4cGlyeUhlaWdodCkpe3Rocm93IG5ldyBFcnJvcihcIkNhbiBub3QgdGFrZW91dCBiZWZvcmUgZXhwaXJ5SGVpZ2h0LlwiKTt9IGlmKGFtb3VudC5ndChkZXBvc2l0LmJhbGFuY2UpKXt0aHJvdyBuZXcgRXJyb3IoXCJJbnN1ZmZpY2llbnQgYmFsYW5jZS5cIik7fSB2YXIgcmVzdWx0PUJsb2NrY2hhaW4udHJhbnNmZXIoZnJvbSxhbW91bnQpO2lmKCFyZXN1bHQpe3Rocm93IG5ldyBFcnJvcihcInRyYW5zZmVyIGZhaWxlZC5cIik7fSBFdmVudC5UcmlnZ2VyKFwiQmFua1ZhdWx0XCIse1RyYW5zZmVyOntmcm9tOkJsb2NrY2hhaW4udHJhbnNhY3Rpb24udG8sdG86ZnJvbSx2YWx1ZTphbW91bnQudG9TdHJpbmcoKX19KTtkZXBvc2l0LmJhbGFuY2U9ZGVwb3NpdC5iYWxhbmNlLnN1YihhbW91bnQpO3RoaXMuYmFua1ZhdWx0LnB1dChmcm9tLGRlcG9zaXQpO30sYmFsYW5jZU9mOmZ1bmN0aW9uKCl7dmFyIGZyb209QmxvY2tjaGFpbi50cmFuc2FjdGlvbi5mcm9tO3JldHVybiB0aGlzLmJhbmtWYXVsdC5nZXQoZnJvbSk7fSx2ZXJpZnlBZGRyZXNzOmZ1bmN0aW9uKGFkZHJlc3Mpe3ZhciByZXN1bHQ9QmxvY2tjaGFpbi52ZXJpZnlBZGRyZXNzKGFkZHJlc3MpO3JldHVybnt2YWxpZDpyZXN1bHQ9PTA/ZmFsc2U6dHJ1ZX07fX07bW9kdWxlLmV4cG9ydHM9QmFua1ZhdWx0Q29udHJhY3Q7IiwiQXJncyI6IiJ9","gas_price": "1000000","gas_limit": "2000000","contract_address": "n1joQPGKfM1PVRSZwrFqYzwx1Sc4xgaBM8k","status": 1,"gas_used": "22016","execute_error": "","execute_result": "\"\""}
}

如上所示,部署合约的交易的状态status变成了1,表示合约部署成功了。

执行智能合约方法

在Nebulas中调用智能合约的方式也很简单,同样是通过发送交易来调用智能合约。

调用智能合约的save方法
curl -i -H 'Accept: application/json' -X POST http://localhost:8685/v1/admin/trction":{"from":"n1LkDi2gGMqPrjYcczUiweyP4RxTB6Go1qS","to":"n1joQPGKfM1PVRSZwrFqYzwx1Sc4xgaBM8k", "value":"100","nonce":8,"gasPrice":"1000000","gasLimit":"2000000","contract":{"function":"save","args":"[0]"}}, "passphrase": "passphrase"}'
HTTP/1.1 200 OK
Content-Type: application/json
Vary: Origin
Date: Fri, 06 Jul 2018 14:08:55 GMT
Content-Length: 110{"result": {"txhash": "48b7c9f388c149295ee27b0d1a51a72f2c6979245ecd58c0bd70aa4fb9ff4095","contract_address": ""}
}
  • from: 用户的账户地址
  • to: 智能合约地址
  • value: 调用save()方法时想要存入智能合约代币数量
  • nonce: 比创建者当前的nonce多1,可以通过GetAccountState获取创建前当前nonce
  • gasPrice:部署智能合约用到的gasPrice,可以通过GetGasPrice获取,或者使用默认值:"1000000"
  • gasLimit: 部署合约的gasLimit,通过EstimateGas可以获取部署合约的gas消耗,不能使用默认值,也可以设置一个较大值,执行时以实际使用计算。
  • contract: 合约信息,部署合约时传入的参数
    • function: 调用合约方法
    • args: 合约方法参数,无参数为空字符串,有参数时为JSON数组
验证智能合约的方法save是否执行成功

由于执行合约方法本质是提交一个交易,所以我们可以通过验证交易是否提交成功来判断合约方法是否执行成功。

curl -i -H 'Content-Type: application/json' -X POST http://localhost:8685/v1/user/getTransactionReceipt -d '{"hash":"48b7c9f388c149295ee27b0d1a51a72f2c6979245ecd58c0bd70aa4fb9ff4095"}'
HTTP/1.1 200 OK
Content-Type: application/json
Vary: Origin
Date: Fri, 06 Jul 2018 14:12:03 GMT
Content-Length: 446{"result": {"hash": "48b7c9f388c149295ee27b0d1a51a72f2c6979245ecd58c0bd70aa4fb9ff4095","chainId": 100,"from": "n1LkDi2gGMqPrjYcczUiweyP4RxTB6Go1qS","to": "n1joQPGKfM1PVRSZwrFqYzwx1Sc4xgaBM8k","value": "100","nonce": "8","timestamp": "1530886135","type": "call","data": "eyJGdW5jdGlvbiI6InNhdmUiLCJBcmdzIjoiWzBdIn0=","gas_price": "1000000","gas_limit": "2000000","contract_address": "","status": 1,"gas_used": "20363","execute_error": "","execute_result": "\"\""}
}

如上所示,交易状态status变为了1,表示执行save方法成功了。

调用智能合约的takeout方法
curl -i -H 'Accept: application/json' -X POST http://localhost:8685/v1/admin/transactionWithPassphrase -H 'Content-Type: application/json' -d '{"transaction":{"from":"n1LkDi2gGMqPrjYcczUiweyP4RxTB6Go1qS","to":"n1joQPGKfM1PVRSZwrFqYzwx1Sc4xgaBM8k", "value":"0","nonce":9,"gasPrice":"1000000","gasLimit":"2000000","contract":{"function":"takeout","args":"[50]"}}, "passphrase": "passphrase"}'
HTTP/1.1 200 OK
Content-Type: application/json
Vary: Origin
Date: Fri, 06 Jul 2018 14:16:27 GMT
Content-Length: 110{"result": {"txhash": "d5a99ee3a8cf1cc18cb1f8852b61b6372b93843bfea5a51095dc8b69c5678baa","contract_address": ""}
}
验证智能合约的方法takeout是否执行成功

在上面save方法的执行中,我们在合约n1rVLTRxQEXscTgThmbTnn2NqdWFEKwpYUM中存了100 wei(10^-18 NAS)。此时,我们执行takeout函数,从中取出50 wei。合约里应该还有50 wei。我们检测下合约账户的余额来验证takeout方法执行是否成功。

curl -i -H 'Content-Type: application/json' -X POST http://localhost:8685/v1/user/accountstate -d '{"address":"n1joQPGKfM1PVRSZwrFqYzwx1Sc4xgaBM8k"}'
HTTP/1.1 200 OK
Content-Type: application/json
Vary: Origin
Date: Fri, 06 Jul 2018 14:19:47 GMT
Content-Length: 49{"result": {"balance": "50","nonce": "0","type": 88}
}

结果和预期相符,当然由于旷工的原因我们需要等待一定的时间才能查询到正确的数据。

查询智能合约数据

在智能合约中,我们有一些方法并不更改合约的状态,这些方法被设计来帮助我们获取合约数据,它们是只读的。在星云链上,我们在API Module中为用户提供了Call接口来帮助用户来执行这些只读的方法,使用Call接口不会发送交易,也就无需支付上链手续费。
我们调用合约n1joQPGKfM1PVRSZwrFqYzwx1Sc4xgaBM8k中的balanceOf方法来查询该合约的余额。

curl -i -H 'Accept: application/json' -X POST http://localhost:8685/v1/user/call -H 'Content-Type: application/json' -d '{"from":"n1LkDi2gGMqPrjYcczUiweyP4RxTB6Go1qS","to":"n1joQPGKfM1PVRSZwrFqYzwx1Sc4xgaBM8k","value":"0","nonce":10,"gasPrice":"1000000","gasLimit":"2000000","contract":{"function":"balanceOf","args":""}}'
HTTP/1.1 200 OK
Content-Type: application/json
Vary: Origin
Date: Fri, 06 Jul 2018 14:24:06 GMT
Content-Length: 110{"result": {"result": "{\"balance\":\"50\",\"expiryHeight\":\"3261\"}","execute_err": "","estimate_gas": "20209"}
}
下一章
智能合约存储区

基于星云链的智能合约与Dapp(四)——编写并运行智能合约相关推荐

  1. Blockathon(北京)分享:基于星云链开发的区块链垂直教育平台SuperxSchool 赢得区块松大赛亚军

    2018年5月25-27日,由HiBlock区块链社区与bitfwd所举办的区块松在中关村e世界联合创业办公社隆重举行,经过三天时间的激烈角逐,由我所带领的 SuperxSchool 区块链垂直教育平 ...

  2. Blockathon(北京)分享:基于星云链开发的区块链垂直教育平台SuperxSchool 赢得区块松大赛亚军...

    2019独角兽企业重金招聘Python工程师标准>>> 2018年5月25-27日,由HiBlock区块链社区与bitfwd所举办的区块松在中关村e世界联合创业办公社隆重举行,经过三 ...

  3. Nebulas 101 - 03 编写并运行智能合约 ---》星云链开发

    Nebulas 3200 万奖金的 DApp 开发激励计划 注册地址:https://incentive.nebulas.io/cn/signup.html?invite=58jke 时间: 2018 ...

  4. EOS智能合约与DApp开发入门教程

    EOS的是Block.One主导研发的一个区块链底层公链系统,它专门为支撑商业去中心化应用(Decentralized Application)而设计,其代码开源. 比特币被称为区块链1.0,因为它开 ...

  5. 基于区块链技术的智能网联汽车数据跨境安全研究

    文/潘妍,余宇舟,许智鑫 摘要 数据作为一种新型生产要素,蕴藏着巨大的经济价值和社会价值,已受到国际贸易合作体系各参与方的高度重视.在全球经济合作的大背景下,数据跨境流动已成为释放数据价值的关键环节, ...

  6. (四)基于区块链的自动抽奖系统从0到1实现

    文章目录 前言 一.核心功能 1.页面展示 1.抽奖接口 3.定时触发智能合约抽奖,并自动公布结果 4.项目整体代码地址 总结 前言 上一章节我们已经编写了核心的预言机合约,并且部署测试成功,现在我们 ...

  7. SSM基于区块链的物联网数据交易 计算机毕业设计源码46193

    摘  要 物联网技术作为继互联网技术后新一代的通信信息集成应用的典范,其巨大的应用前景受到了学术界和政商界的广泛关注.物联网技术在一些传统行业已经有了很深入的应用,例如,其在商品生产信息溯源.环境监测 ...

  8. 星云链智能合约开发(六):智能合约开发与部署

    编写智能合约 Nebulas实现了NVM虚拟机来运行智能合约,NVM的实现使用了JavaScript V8引擎,所以当前的开发版,我们可以使用JavaScript.TypeScript来编写智能合约. ...

  9. 关于区块链、Web3.0、智能合约、DApp、DAO一文解释清楚

    目录 区块链(Block Chain) 概念 使用范围 Web3.0 智能合约(Smart Contract) DApp(Decentralized Application) DAO(Decentra ...

最新文章

  1. python大数据结课报告_2020知到大数据分析的PYTHON基础结课答案
  2. 转!!java中File的delete()方法删除文件失败的原因
  3. 12层打败50层,ParNet 普林斯顿+英特尔:更深不一定更好
  4. 解密回声消除技术之一(理论篇)
  5. 数据结构与算法JavaScript描述——链表
  6. zoj-3802-Easy 2048 Again
  7. python中的列表分片详解_python列表与元组详解实例
  8. RabbitMQ预取值
  9. numpy之高维数组的转置:transpose方法——通过几何体来迅速理解
  10. matplotlib可视化_使用Matplotlib改善可视化设计的5个魔术技巧
  11. java 格式化字符串_Java入门 - 语言基础 - 14.String类
  12. sql活动监视器 死锁_使用system_health扩展事件监视SQL Server死锁
  13. Linux系统管理(10)——Centos8 重启网络服务 网络相关命令
  14. Concept Drift(概念漂移)
  15. 从0开始学习 GitHub 系列之「GitHub 常见的几种操作」
  16. 淘宝天猫店铺装修问题与技巧性经验汇总
  17. java-用for循环打印大写字母(部分简单大写字母)
  18. Linux下XFS文件系统使用 Quota 进行合理划分实例
  19. 如何设置Xiuno BBS URL-Rewrite(伪静态设定)
  20. C# 提取Word文档中的图片(用Spire)

热门文章

  1. c++ const指针与函数调用
  2. Google Voice
  3. 3dmax导入Sketchup 模型位置错乱的解决方法
  4. IDEA 2021 快速提示背景颜色修改
  5. iphone android 朋友圈,最近很火的微信空白朋友圈发布教程!安卓、苹果通用!
  6. 有关access的上机试题_ACCESS上机试题及答案8
  7. 根据后端返回的文件流下载文件
  8. java获取表格的题注_【转】Word之表格、图片的题注(抬头)自动编号
  9. 深度学习 word2vec(一)
  10. vue 饿了么ui 日期选择器 修改样式