Solidity撰寫智能合約與注意事項(二)

from:

https://medium.com/taipei-ethereum-meetup/solidity%E6%92%B0%E5%AF%AB%E6%99%BA%E8%83%BD%E5%90%88%E7%B4%84%E8%88%87%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A0%85-%E4%BA%8C-dd915bdeafa0


這篇將介紹以太坊的log資料及event的使用

類似於比特幣的OP_RETURN,以太坊也提供一個把資料永久寫入區塊鏈裡的方法 — event,event所寫入的資料會被記錄在一個Receipt資料裡。

每一筆transaction都會有一個對應的Receipt,用來記錄這筆transaction的執行結果

eth.getTransaction()

getTransaction可以得到這筆transaction的相關資料,這些資料在transaction被製作出來的時候就有了,而Receipt則是直到被執行完(也就是transaction被放進鏈裡)後才會有。

註:(1)gas是指這次提供的gas總量

(2)input是合約的code(這是一個部署合約的transaction,所以input就是整份合約的code)。

用getTransacitonReceipt("hash")來取得transaction對應的Receipt:

eth.getTransactionReceipt()

註:(1)gasUsed是這筆transaction所花費的gas(我們提供了4700000,只花了118615,剩下的會退還給我們)

(2)logs則是我們這篇介紹的log,如果有event被觸發,資料就會被入在這

那什麼時候會需要用到event呢?

1. 當作一個額外的儲存空間,而且很便宜。event寫入的成本和用合約變數來儲存的成本相比之下少了很多,如果你開發的dapp需要將使用者的使用紀錄(如付款紀錄)等記錄下來當作證明,與其用一個陣列儲存,不如在每次使用時用event寫進log裡。

但要注意的是,這些寫進log裡的資料是沒辦法被合約所存取的。

2. 當成return value來使用。合約裡函式的回傳值並非總是可以使用,假設一個有回傳值的函式:

contract f00{

function foo(int _value) returns (int) {

return _value * _value;

}

}

什麼時候你可以拿到這個回傳值?只有在你使用call在本地進行模擬的時候才會有回傳值,如下:

var ret = f00.foo.call(25);

console.log(ret);    //625

當你使用sendTransaction,真的做出一筆交易的時候,他會回傳你這筆transaction的hash值,所以這時候你可以使用event來將回傳值記錄起來:

contract f00{

event retValue(int _value);

function foo(int _value) returns(int) {

return _value * _value;

}

}

這時候在前端便可以利用像javascript那樣監聽的功能:

var retValueEvent = f00.retValue();

retValueEvent.watch(function(err, result){

if(err){

console.log(err);

return;

}

console.log(result.args._value);

});

當transaction被收入區塊鏈裡後,就會觸發監聽器然後按照你設定的callback函式執行對應的動作。如果要結束監聽,執行 retValueEvent.stopWatching()。

3. 最後便是當你開發dapp的時候,藉由觸發event寫入log,再觸發監聽器執行對應動作,如此完成從 外界->鏈->鏈->外界 一個完整的執行過程。對使用者來說就像一個是對資料庫操作的動作,只是這個資料庫變成了區塊鏈。

接下來以簡單的例子來介紹監聽器更多的功能

contract depositAccount {

event Deposit(addressindexed_owner, uint _amount, uint _time);

function deposit() payable {

Deposit(msg.sender, msg.value, now);

}

}

首先先介紹第二行的indexed。

在Receipt裡如果有log,會寫在logs欄位裡,每筆log其中有兩部分:data和topics。一般event寫入的資料都會寫在data裡,但如果在event的變數加入一個indexed屬性,到時候觸發時這個變數對應寫入的值就會寫在topics裡,在topcis裡的值可以用來當作監聽器的篩選條件。

註:一份Receipt裡面可以有很多筆log(表示一次transaction可以觸發很多次event),一筆log最多只能儲存四個topics,而第一個topic必須是這個event的識別值identifier,代表一個event最多只能有三個變數可以有indexed屬性。

transaction的logs裡的其中一筆log

上面這張圖是其中某一筆log,這個event沒有加indexed的變數,值都會寫在data欄位裡(32byte為一單位接在一起,圖中為十六進位的9和19),topcis裡唯一一個值 0x35bd26...是該event的識別值。

下面這張圖是變數都加上indexed的event的log記錄:

event有indexed

因為所有變數都加上indexed,所以data裡沒有值,值都寫在topics裡(十六進位的102和abcde)。

接下來在前端加入監聽器:

var depositEvent = depositAccount.Deposit({_owner:null},{fromBlock: 5000, toBlock: ‘latest’});

depositEvent.watch(function(err, results) {

if (err) {

console.log(err);

return;

}

console.log(results.blockNumber);

});

第一行的{fromBlock: 5000, toBlock: ‘latest’}是加入的篩選條件,表示監聽從第5000個區塊開始到最新的區塊。如果event被觸發,那callback函式就會印出是發生在第幾個區塊( result.blockNumber )。

如果我們要用有加上indexed的變數(_owner變數)來當篩選條件的話,就指定_owner應該要是多少,如果給null(像上面的例子),那就是任何address都可以的意思:

var depositEvent = depositaccount.Deposit({_owner:'0xbd7255b64eeb594ca57652c94249da6a9b37cd2f'});

depositEvent.watch(function(err, results) {

if (err) {

console.log(err);

return;

}

if(results.args._amount > web3.toWei(0.05,"ether")){

console.log("User: " + results.args._owner +

" deposits: " + results.args._amount +

" on: " +

JSON.stringify(new Date((parseInt(results.args._time)+28800)*1000))

);

}

});

這個callback會在"0xbd7255b64eeb594ca57652c94249da6a9b37cd2f"這個address存錢的時候被觸發,存入超過0.05 ether的時候會印出存入的金額和存入時間。

References:

[1]https://media.consensys.net/technical-introduction-to-events-and-logs-in-ethereum-a074d65dd61e#.u7l9ejta3

[2]https://github.com/ethereum/wiki/wiki/JavaScript-API#contract-events

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,186评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,858评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,620评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,888评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,009评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,149评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,204评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,956评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,385评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,698评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,863评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,544评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,185评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,899评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,141评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,684评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,750评论 2 351

推荐阅读更多精彩内容

  • 一一與旋轉屋 徐空文 (這是十幾年前創作的第一個劇本,雖然幼稚,但現在看來竟是我最喜歡的劇本之一,雖然之後曾以寫劇...
    徐空文阅读 523评论 0 5
  • 为何叫做 shell ? shell prompt(PS1) 与 Carriage Return(CR) 的关系?...
    Zero___阅读 3,145评论 3 49
  • 每一个孩子都是各自家庭里的宝,每一个父母都希望给孩子创造最好的生活环境,让孩子享受到最好的教育资源,给孩子一片明媚...
    橡树心阅读 513评论 0 2
  • 1 文件目录文件普通文件: 纯文本文件 (简历.日志,word文档) 二进制文件(.exe文...
    我本无邪阅读 228评论 0 0
  • 前一秒,叽叽喳喳的声音掩盖了我的落寞。 下一秒,猝不及防的泪水出卖了我的脆弱。 只因为——这一秒,你的容颜倒映在我...
    莫负青柠阅读 196评论 2 2