以太坊賬戶類(lèi)型
交易部署合約
交易調(diào)用合約(ERC20 等)
合約運(yùn)行報(bào)錯(cuò)
合約的gas不足
拋出event的交易
多合約互相調(diào)用
Token 與 NFT 數(shù)據(jù)區(qū)別
交易、消息與調(diào)用(Message Call)的區(qū)別
介紹區(qū)塊鏈交易
區(qū)塊鏈?zhǔn)且环N記錄保存系統(tǒng),在將條目添加到數(shù)據(jù)鏈之前會(huì)有多個(gè)源來(lái)驗(yàn)證該條目。數(shù)據(jù)一旦添加,便無(wú)法更改,記錄隨之分布到網(wǎng)絡(luò)中的多個(gè)位置。向區(qū)塊鏈序列添加新記錄(稱(chēng)為區(qū)塊)需要由連接到區(qū)塊鏈網(wǎng)絡(luò)的多個(gè)成員進(jìn)行驗(yàn)證。這些數(shù)據(jù)區(qū)塊相互鏈接而形成鏈。區(qū)塊鏈中的全部交易對(duì)其中的所有人公開(kāi),但所有個(gè)人身份都是隱藏的。
區(qū)塊鏈技術(shù)使用算法為每個(gè)區(qū)塊分配加密哈希(包含字母和數(shù)字的唯一字符串,有時(shí)也稱(chēng)為“數(shù)字指紋”)。除哈希以外,每個(gè)區(qū)塊還包含帶時(shí)間戳的先前交易的記錄集,以及前一個(gè)區(qū)塊的哈希。正是這種機(jī)制確保了在鏈中的連續(xù)區(qū)塊之間建立起不可變的鏈接。
加密術(shù)和時(shí)間戳的組合確保了區(qū)塊鏈技術(shù)能自動(dòng)驗(yàn)證這個(gè)增長(zhǎng)的哈希序列永遠(yuǎn)不會(huì)更改。
比特幣交易流程:
交易的生成→交易的傳播→整個(gè)網(wǎng)絡(luò)節(jié)點(diǎn)驗(yàn)證→記錄到區(qū)塊鏈
第一步:所有者A利用他的私鑰對(duì)前一次交易(比特貨來(lái)源)和下一位所有者B簽署一個(gè)數(shù)字簽名,并將這個(gè)簽名附加在這枚貨幣的末尾,制作成交易單,B以公鑰作為接收方地址
第二步:A將交易單廣播至全網(wǎng),比特幣就發(fā)送給了B,每個(gè)節(jié)點(diǎn)都將收到的交易信息納入一個(gè)區(qū)塊中。對(duì)B而言,該枚比特幣會(huì)即時(shí)顯示在比特幣錢(qián)包中,但直到區(qū)塊確認(rèn)成功后才可用。確認(rèn)這筆交易真實(shí)有效后,礦工即可將這條交易信息與其他交易信息一起放入某個(gè)區(qū)塊
第三步:每個(gè)節(jié)點(diǎn)通過(guò)解一道數(shù)學(xué)難題,即找到數(shù)學(xué)難題的解, 但是答案并不唯一。這個(gè)過(guò)程也是嘗試對(duì)這個(gè)區(qū)塊進(jìn)行“挖礦”, 從而去獲得創(chuàng)建新區(qū)塊權(quán)利,并爭(zhēng)取得到比特幣的獎(jiǎng)勵(lì)(新比特幣會(huì)在此過(guò)程中產(chǎn)生)
第四步:當(dāng)一個(gè)節(jié)點(diǎn)找到解時(shí),它就向全網(wǎng)廣播該區(qū)塊記錄的所有蓋時(shí)間戳交易,并由全網(wǎng)其他節(jié)點(diǎn)核對(duì)
第五步:全網(wǎng)其他節(jié)點(diǎn)核對(duì)該區(qū)塊記賬的正確性,驗(yàn)證無(wú)誤后,他們會(huì)將有效區(qū)塊的信息加入自己的區(qū)塊鏈,表明交易完成。這個(gè)過(guò)程中,其他礦工仍需將前一個(gè)區(qū)塊的哈希值加入新區(qū)塊,最終將所有區(qū)塊相連,構(gòu)成名副其實(shí)的“區(qū)塊鏈”。
以太坊賬戶類(lèi)型
外部賬戶 (Externally owned account, EOA )
合約賬戶 (Contract accounts)
外部賬戶(用戶賬戶/普通賬戶)
有對(duì)應(yīng)的以太幣余額
可發(fā)送交易(轉(zhuǎn)幣或觸發(fā)合約代碼)
由用戶私鑰控制
沒(méi)有關(guān)聯(lián)代碼
合約賬戶
有對(duì)應(yīng)的以太幣余額
有關(guān)聯(lián)代碼
由代碼控制
可通過(guò)交易或來(lái)自其它合約的調(diào)用消息來(lái)觸發(fā)代碼執(zhí)行
執(zhí)行代碼時(shí)可以操作自己的存儲(chǔ)空間,也可以調(diào)用其它合約
賬戶主要參數(shù)
Address: 20-bytes(160bit), 從公鑰計(jì)算得來(lái)
nonce:如果是外部賬戶,表示從這個(gè)賬戶發(fā)出的交易個(gè)數(shù);如果是合約賬戶,表示這個(gè)賬戶創(chuàng)建的合約個(gè)數(shù)
balance:賬戶余額
codeHash:如果是外部賬戶,它是空字符串的hash,如果是合約賬戶表示EVM代碼的hash
以太坊交易類(lèi)型
有兩種類(lèi)型的交易: 一種是能夠產(chǎn)生消息調(diào)用的交易,另一種是能夠生成新賬戶的交易(比如說(shuō)生成合約)
交易Transaction指存儲(chǔ)了消息的簽名數(shù)據(jù)包,在區(qū)塊鏈上從一個(gè)外部賬戶發(fā)送到另外一個(gè)外部賬戶。
消息Message指一些虛擬對(duì)象,他們不會(huì)被序列化,且僅存在于以太坊的執(zhí)行環(huán)境中,他們可以被理解為函數(shù)調(diào)用。
0. 普通交易
轉(zhuǎn)賬是最常見(jiàn)的一種普通交易,這里轉(zhuǎn)賬是指從一個(gè)賬戶向另一個(gè)賬戶發(fā)送貨幣以太幣。因?yàn)樗?EVM 原生指令,不需要使用智能合約。發(fā)送轉(zhuǎn)賬交易的時(shí)候只需要指定交易的發(fā)送者、接收者、轉(zhuǎn)幣的數(shù)量。
交易包含以下主要字段:
type:交易的類(lèi)型,ContractCreation(創(chuàng)建合約)還是MessageCall(調(diào)用合約或轉(zhuǎn)賬)
nonce: 發(fā)送地址的交易計(jì)數(shù),也可以理解為(“僅使用一次的數(shù)字”)是以太坊網(wǎng)絡(luò)用來(lái)跟蹤你的賬戶狀態(tài)、避免多重支付和重放攻擊的一個(gè)數(shù)值(可以理解成流水號(hào))。當(dāng)你的交易因?yàn)?gas fee 太低而暫時(shí)無(wú)法打包的時(shí)候,你可以使用同一個(gè) nonce 但指定更高的 gas price 來(lái) “替換” 你的那筆卡住的交易;一旦這筆 “更快” 的交易得以打包上鏈,你原來(lái)簽名的那筆交易(因?yàn)槭褂昧送粋€(gè) nonce)就會(huì)被以太坊的節(jié)點(diǎn)拋棄掉了。
gasPrice:為交易付出的Gas價(jià)格
gas: 為交易付出的gas
to:接受方地址, 若to為空,表示創(chuàng)建合約
value: 向目標(biāo)賬戶發(fā)送的金額
Input:交易的附加數(shù)據(jù)
R, S, V:交易簽名結(jié)構(gòu)體
data: 編譯的合約代碼 或者是調(diào)用函數(shù)的簽名和編碼的參數(shù);
1.JSON-RPC API
作用:為了讓客戶端連接以太坊節(jié)點(diǎn)的協(xié)議,通過(guò)使用RPC API來(lái)查詢區(qū)塊鏈參數(shù),發(fā)送交易等
eth_signTransaction
對(duì)交易進(jìn)行簽名,隨后用 eth_sendRawTransaction 提交到網(wǎng)絡(luò)上
相關(guān)參數(shù)為:
from: 20字節(jié),發(fā)送方地址;
to: 20字節(jié),接收方地址,當(dāng)為空時(shí),為創(chuàng)建合約交易;
gas: 可選項(xiàng),默認(rèn)為90000;
gasPrice: 可選項(xiàng);
value: 可選項(xiàng),交易金額;
data: 編譯的合約代碼 或者是調(diào)用函數(shù)的簽名和編碼的參數(shù);
nonce: 可選項(xiàng), 可以覆蓋同一nonce的pending交易。
返回值:
簽名名的交易對(duì)象
// Request
curl -X POST --data '{
"id": 1,
"jsonrpc": "2.0",
"method": "eth_signTransaction",
"params": [{
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675",
"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
"gas": "0x76c0",
"gasPrice": "0x9184e72a000",
"to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
"value": "0x9184e72a"
}]
}'
// Result
{
"id": 1,
"jsonrpc": "2.0",
"result": "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b"
}
eth_sendTransaction
創(chuàng)建消息調(diào)用的交易,或者data域中包含代碼的時(shí)候,為創(chuàng)建合約的交易
相關(guān)參數(shù)和eth_signTransaction差不多
返回值:
交易的Hash值
eth_sendRawTransaction
創(chuàng)建消息調(diào)用的交易或者創(chuàng)建合約,已經(jīng)簽名的交易
參數(shù):
dat: 簽名的交易數(shù)據(jù)
返回值:
data: 32字節(jié),交易的hash值。
eth_getTransactionByHash
返回指定交易對(duì)應(yīng)的交易信息
eth_getTransactionReceipt
返回指定交易對(duì)應(yīng)的收據(jù)信息
2.交易部署合約
從外部賬戶到合約賬戶的消息會(huì)激活合約賬戶的代碼,執(zhí)行各種操作,也就是我們常說(shuō)的調(diào)用智能合約??梢酝ㄟ^(guò)向0地址發(fā)起交易來(lái)創(chuàng)建合約賬戶。
3.交易調(diào)用合約(ERC20 等)
對(duì)于驅(qū)動(dòng)合約執(zhí)行的交易,有幾個(gè)關(guān)鍵點(diǎn):
1、合約在創(chuàng)建時(shí),會(huì)生成一個(gè)合約地址,所以,通過(guò)交易調(diào)用合約的時(shí)候,就以合約地址為目的地址
2、在交易的data域,會(huì)標(biāo)明要調(diào)用合約的哪個(gè)函數(shù),并且提供了該函數(shù)所需要的參數(shù)
3、調(diào)用合約的交易,同樣可以發(fā)送一筆以太幣給合約,金額在value字段顯示
4.合約運(yùn)行報(bào)錯(cuò)
5.合約的gas不足
什么是礦工費(fèi)
礦工費(fèi)是以太坊先提出來(lái)的,這也是以太坊和比特幣的不同之處,以太坊引入了 gas 的概念,gas的目的是限制執(zhí)行交易所需的工作量,同時(shí)為執(zhí)行支付費(fèi)用。gas 用來(lái)衡量你的這筆交易(或者合約代碼調(diào)用)所消耗的資源(包括計(jì)算量,存儲(chǔ),帶寬等)
礦工費(fèi)怎么計(jì)算
當(dāng)你在以太坊區(qū)塊鏈上進(jìn)行轉(zhuǎn)賬時(shí),礦工要把你的交易打包并放上區(qū)塊鏈,才能使交易完成,在這過(guò)程中會(huì)消耗區(qū)塊鏈的運(yùn)算資源,所以要支付費(fèi)用。Gas由兩部分組成:Gas Price(價(jià)格) * Gas limit(限制)。Gas Price(單位是Gwei) 指的是用戶愿意花費(fèi)于每個(gè) Gas 單位的價(jià)錢(qián),由用戶自己決定。Gas Limit 是用戶愿意為執(zhí)行某個(gè)操作或確認(rèn)交易支付的最大Gas量(最少21,000),不同時(shí)期、不同的操作默認(rèn)值不同,在執(zhí)行操作時(shí)可設(shè)置Gas Limit
礦工費(fèi)不足會(huì)怎樣
礦工會(huì)優(yōu)先選取Gas合理,Gas Price較高的交易進(jìn)行打包。如果用戶交易時(shí)所支付的礦工費(fèi)非常低,那么這筆交易可能不會(huì)被礦工打包, 從而造成交易失敗
交易失敗的特點(diǎn)
失敗的交易一旦被執(zhí)行,就一定會(huì)被打包到區(qū)塊鏈中,并且執(zhí)行過(guò)程中消耗的gas也不會(huì)退還,交易的成功與失敗可以使用交易的收據(jù)狀態(tài)進(jìn)行判斷
失敗的交易如果沒(méi)有打包到區(qū)塊,那么可能的原因就有很多了,根據(jù)交易所處的階段不同大概有這么幾種可能:
a.交易gas過(guò)低或參數(shù)錯(cuò)誤根本沒(méi)有進(jìn)入到pending隊(duì)列
b.交易進(jìn)入pending進(jìn)行處理,然而在檢查gas等參數(shù)時(shí)報(bào)錯(cuò)被丟棄
6.拋出event的交易
事件
當(dāng)定義的事件觸發(fā)時(shí),我們可以將事件存儲(chǔ)到EVM的交易日志中,日志是區(qū)塊鏈中的一種特殊數(shù)據(jù)結(jié)構(gòu)。日志與合約關(guān)聯(lián),與合約的存儲(chǔ)合并存入?yún)^(qū)塊鏈中。只要某個(gè)區(qū)塊可以訪問(wèn),其相關(guān)的日志就可以訪問(wèn)。但在合約中,我們不能直接訪問(wèn)日志和事件數(shù)據(jù)(即便是創(chuàng)建日志的合約)
事件和日志的主要用途有三種:
幫助用戶客戶端(web3.js)讀取智能合約的返回值;
智能合約異步通知用戶客戶端(web3.js);
用于智能合約的存儲(chǔ)(比Storage便宜得多)
使用時(shí)機(jī)
在交易中如果修改了狀態(tài)數(shù)據(jù)時(shí),就需要拋出event
pragma solidity ^0.4.0;
contract Transfer{
event transfer(address indexed _from, address indexed _to,uint indexedvalue);
function deposit() payable {
address current = this;
uintvalue = msg.value;
transfer(msg.sender, current,value);
}
function getBanlance() constantreturns(uint) {
return this.balance;
}
/* fallback function */
function(){}
}
7.多合約互相調(diào)用
在 Solidity 中,call 函數(shù)簇可以實(shí)現(xiàn)跨合約的函數(shù)調(diào)用功能,其中包括 call、delegatecall 和 callcode 三種方式。
以下是 Solidity 中 call 函數(shù)簇的調(diào)用模型:
<address>.call(...) returns (bool) <address>.callcode(...) returns (bool) <address>.delegatecall(...) returns (bool)
這些函數(shù)提供了靈活的方式與合約進(jìn)行交互,并且可以接受任何長(zhǎng)度、任何類(lèi)型的參數(shù),其傳入的參數(shù)會(huì)被填充至 32 字節(jié)最后拼接為一個(gè)字符串序列,由 EVM 解析執(zhí)行。
在函數(shù)調(diào)用的過(guò)程中, Solidity 中的內(nèi)置變量 msg 會(huì)隨著調(diào)用的發(fā)起而改變,msg 保存了調(diào)用方的信息包括:調(diào)用發(fā)起的地址,交易金額,被調(diào)用函數(shù)字符序列等。
三種調(diào)用方式的異同點(diǎn)
call: 最常用的調(diào)用方式,調(diào)用后內(nèi)置變量 msg 的值會(huì)修改為調(diào)用者,執(zhí)行環(huán)境為被調(diào)用者的運(yùn)行環(huán)境(合約的 storage)。
delegatecall: 調(diào)用后內(nèi)置變量 msg 的值不會(huì)修改為調(diào)用者,但執(zhí)行環(huán)境為調(diào)用者的運(yùn)行環(huán)境。
callcode: 調(diào)用后內(nèi)置變量 msg 的值會(huì)修改為調(diào)用者,但執(zhí)行環(huán)境為調(diào)用者的運(yùn)行環(huán)境。
8.Token 與 NFT 數(shù)據(jù)區(qū)別
在區(qū)塊鏈上,數(shù)字加密貨幣分為原生幣和代幣兩大類(lèi)。前者如大家熟悉的比特幣、以太幣等,擁有自己的主鏈,使用鏈上的交易來(lái)維護(hù)賬本數(shù)據(jù);代幣則是依附于現(xiàn)有的區(qū)塊鏈,使用智能合約來(lái)進(jìn)行賬本的記錄,如依附于以太坊上而發(fā)布的token。代幣之中又可分為同質(zhì)化和非同質(zhì)化兩種
同質(zhì)化代幣,即FT(Fungible Token),互相可以替代、可接近無(wú)限拆分的token。例如,你手里有一個(gè)比特幣與我手里的一個(gè)比特幣,本質(zhì)上沒(méi)有任何區(qū)別,這就是同質(zhì)化,就是同質(zhì)化幣。
而非同質(zhì)化代幣,即NFT,則是唯一的、不可拆分的token,如加密貓、token化的數(shù)字門(mén)票等。也就相當(dāng)于帶有編號(hào)的人民幣,這個(gè)世界上不會(huì)有兩張編號(hào)一樣的人民幣,也不會(huì)有兩個(gè)完全一樣的NFT
元數(shù)據(jù)(Metadata)是所有 NFT 合約的重要組成部分。
NFT 合約的元數(shù)據(jù)(Metadata)文件是存儲(chǔ)在區(qū)塊鏈之外某處的 JSON 文件。通過(guò)一些技巧,可以在鏈上執(zhí)行此操作,也可以在 IPFS 上執(zhí)行此操作,或者在自己構(gòu)建的服務(wù)器上執(zhí)行,可以考慮使用 CDN。這些文件可能以它們存儲(chǔ)的令牌數(shù)據(jù)命名 tokenId
{
"description": "Friendly OpenSea Creature that enjoys long swims in the ocean.",
"image": "<https://storage.googleapis.com/opensea-prod.appspot.com/puffs/9.png>",
"name": "Dave Starbelly",
"attributes": [
{
"trait_type": "Base",
"value": "Starfish"
},
{
"trait_type": "Eyes",
"value": "Big"
}
],
}
9.為何交易已確認(rèn),Etherscan 上沒(méi)有數(shù)據(jù)
通常來(lái)說(shuō)交易確認(rèn)了 ,瀏覽器節(jié)點(diǎn)是百分百可以查到。
瀏覽器中心化有問(wèn)題,數(shù)據(jù)沒(méi)有顯示出來(lái), 數(shù)據(jù)被過(guò)濾或者刪除
網(wǎng)絡(luò)延遲問(wèn)題,數(shù)據(jù)在池中中排隊(duì)
10.合約什么類(lèi)型的代碼最后會(huì)影響 Etherscan 上的數(shù)據(jù),比如 emit Event?
11.交易、消息與調(diào)用(Message Call)的區(qū)別
交易Transaction指存儲(chǔ)了消息的簽名數(shù)據(jù)包,在區(qū)塊鏈上從一個(gè)外部賬戶發(fā)送到另外一個(gè)外部賬戶。
消息Message指一些虛擬對(duì)象,他們不會(huì)被序列化,且僅存在于以太坊的執(zhí)行環(huán)境中,他們可以被理解為函數(shù)調(diào)用。
合約中函數(shù)的調(diào)用創(chuàng)建的是調(diào)用還是交易?
考慮一下這四種情況:
使用調(diào)用(call)直接對(duì)合約函數(shù)進(jìn)行調(diào)用
使用sendTransaction直接對(duì)合約函數(shù)進(jìn)行調(diào)用
使用調(diào)用(call)通過(guò)合約對(duì)合約函數(shù)進(jìn)行調(diào)用
使用sendTransaction通過(guò)合約對(duì)合約函數(shù)進(jìn)行調(diào)用文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-458091.html
第一種情況與第三種情況是很明顯的調(diào)用,第二種情況由于使用的是sendTransaction方法,因此它創(chuàng)建了一筆交易。比較特殊的是第四種情況,它看似是生成了一筆交易,但是由于以太坊黃皮書(shū)中對(duì)交易的定義中提到,交易是需要外部參與者(External Actor)進(jìn)行簽名的消息,所以第四種情況沒(méi)有生成交易。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-458091.html
到了這里,關(guān)于區(qū)塊鏈常見(jiàn)交易問(wèn)題-高級(jí)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!