您好,登錄后才能下訂單哦!
這篇文章主要講解了“Bytom中Dapp Demo合約交易的提交方法是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Bytom中Dapp Demo合約交易的提交方法是什么”吧!
為了方便理解,這里簡單說說儲(chǔ)蓄分紅合約的內(nèi)容,具體可以查看儲(chǔ)蓄分紅合約詳細(xì)說明,儲(chǔ)蓄分紅,顧名思義就是儲(chǔ)蓄之后,當(dāng)達(dá)到一定的時(shí)間,按照比例返回本息這樣的意思,所以demo中拆分成saving(儲(chǔ)蓄)與profit(提現(xiàn))兩個(gè)頁面,本章內(nèi)容是針對(duì)合約交易的提交,所以只針對(duì)儲(chǔ)蓄頁面說明。
比原官方demo地址
1)訪問的前提需要用chrome打開比原官方demo地址,同時(shí)安裝bycoin插件,在應(yīng)用商店搜索就行;
2)安裝完bycoin,需要初始化用戶信息,新建或者導(dǎo)入備份文件去恢復(fù)用戶;
3)填寫指定資產(chǎn)數(shù)量,點(diǎn)擊確定;
4)彈出合約交易專用頁面,填寫密碼,點(diǎn)擊確認(rèn);
5)查看交易流水
源碼 : 儲(chǔ)蓄分紅合約前端源代碼 (本章內(nèi)容講解的是 2019年7月10號(hào) 最新版的代碼)
前端代碼是基于前端框架react去做的,很容易讀懂,結(jié)構(gòu)如上,我們來看看作為儲(chǔ)蓄頁面(saving)Bytom-Dapp-Demo1\src\components\layout\save\index.jsx
//提交后的方法 FixedLimitDeposit(amount, address) //####### 1. .then(()=> { //####### 2. this.refs.btn.removeAttribute("disabled"); this.setState({ error:'', msg:`Submit success!!! you spent ${amount} deposite asset,and gain ${amount} billasset.` }) }).catch(err => { //####### 3. this.refs.btn.removeAttribute("disabled"); this.setState({ error:err, msg: '' }) })
1)接收了輸入框的金額,還有當(dāng)前用戶的地址;
2)成功后提示內(nèi)容;
3)失敗后提示內(nèi)容;
接下來到FixedLimitDeposit方法
export function FixedLimitDeposit(amount, address) { const object = { address: address, amount: amount, parameter: [amount, address] } return submitContract(listDepositUTXO, createContractTransaction, updateDatatbaseBalance, object) //####### 1. }
傳入三個(gè)方法體分別是 listDepositUTXO(查找當(dāng)前合約所有的UTXO), createContractTransaction(創(chuàng)建提交前的合約參數(shù)),updateDatatbaseBalance(更新用戶的提交列表)
進(jìn)入Dapp-Demo1\src\components\layout\save\action.js 的 submitContract方法
return new Promise((resolve, reject) => { //list available utxo return listDepositUTXO().then(resp => { //####### 1. //create the Contract Transaction return createContractTransaction(resp, amount, address).then(object =>{ //####### 2. const input = object.input const output = object.output const args = object.args const utxo = object.utxo //Lock UTXO return updateUtxo({"hash": utxo}) //####### 3. .then(()=>{ //Transactions return window.bytom.send_advanced_transaction({input, output, gas: GetContractArgs().gas*100000000, args}) //####### 4. .then((resp) => { //Update Balance return updateDatatbaseBalance(resp, ...updateParameters).then(()=>{//####### 5. resolve() }).catch(err => { throw err }) }) .catch(err => { throw err.message }) }) .catch(err => { throw err }) }).catch(err => { throw err }) }).catch(err => { reject(err) }) })
首先調(diào)用listDepositUTXO 拿到當(dāng)前節(jié)約鎖定的所有UTXO的信息,待會(huì)詳細(xì)說明;
2)調(diào)用 createContractTransaction 方法,組裝好合約的對(duì)應(yīng)信息參數(shù);
3)選取要使用的 UTXO后,調(diào)用updateUtxo 告訴bufferserver ,該UTXO已經(jīng)被使用,更改狀態(tài),防止其他人調(diào)用了;
4)執(zhí)行window.bytom.send_advanced_transaction方法,參考插件錢包API,是高級(jí)交易方法,這個(gè)是bycoin插件的原生方法,調(diào)起 提交交易的頁面,讓用戶輸入密碼;
5)交易確認(rèn)后,調(diào)用 updateDatatbaseBalance 提交數(shù)據(jù)到后端;
再來看看api.js的listDepositUTXO 方法,所有與bufferserver交互的接口全部寫到這個(gè)文件里面:
function listDepositUTXO() { return listDappUTXO({//****** 1. "program": GetContractArgs().depositProgram, "asset": GetContractArgs().assetBill, "sort": { "by":"amount", "order":"desc" } }) } //Api call from Buffer server export function listDappUTXO(params) { let url switch (window.bytom.net){ case "testnet": url = "/dapptestnet/list-utxos" break default: url = "/dapp/list-utxos" } return post(url, params).then(resp => resp.data) }
很明顯最終是調(diào)用bufferserver的/list-utxos方法,非常簡單,值得一提的是
1)里面的結(jié)構(gòu)體根據(jù)program(合約代碼)與asset(資產(chǎn)ID)去查找UTXO,這里其實(shí)底層是調(diào)用官方的blockcenter接口的,后面會(huì)細(xì)說;
繼續(xù)看看Dapp-Demo1\src\components\layout\save\action.js 的createContractTransaction方法
function createContractTransaction(resp, amount, address){ return new Promise((resolve, reject) => { //utxo pre calculation const limit = GetContractArgs().radio * 100000000 //****** 1. if (resp.length === 0) { reject( 'Empty UTXO info, it might be that the utxo is locked. Please retry after 60s.') } else if (amount < limit) { reject( `Please enter an amount bigger or equal than ${limit}.`) } const result = matchesUTXO(resp, amount) //****** 2. const billAmount = result.amount const billAsset = result.asset const utxo = result.hash //contract calculation if (amount > billAmount) { reject('input amount must be smaller or equal to ' + billAmount + '.') } else { const input = [] const output = [] const args = contractArguments(amount, address) //****** 3. input.push(spendUTXOAction(utxo)) //****** 4. input.push(spendWalletAction(amount, GetContractArgs().assetDeposited)) //****** 5. if (amount < billAmount) { //****** 6. output.push(controlProgramAction(amount, GetContractArgs().assetDeposited, GetContractArgs().profitProgram)) output.push(controlAddressAction(amount, billAsset, address)) output.push(controlProgramAction((BigNumber(billAmount).minus(BigNumber(amount))).toNumber(), billAsset, GetContractArgs().depositProgram)) } else { output.push(controlProgramAction(amount, GetContractArgs().assetDeposited, GetContractArgs().profitProgram)) output.push(controlAddressAction(billAmount, billAsset, address)) } resolve({ //****** 7 input, output, args, utxo }) } }) }
這個(gè)方法比較復(fù)雜,我們一步一步來
這里先看看 7),最終返回的內(nèi)容是 input、 output、 args、 utxo, 跟發(fā)送交易頁面里面的input、 output、 args對(duì)應(yīng)起來,如 圖K
(圖K)
上一章說過,所有比原鏈的交易都要存在質(zhì)量守恒定理,input與output的總和要相對(duì)應(yīng),合約交易里面執(zhí)行方法必須需要參數(shù),這里的args就代表傳入的參數(shù),utxo是代表 utxo的id
1)做一下限制,設(shè)置最少值
2)matchesUTXO ,根據(jù)上面的內(nèi)容,剛剛已經(jīng)通過listDepositUTXO 拿到所有可用的UTXO列表,這個(gè)時(shí)候要根據(jù)用戶輸入的數(shù)額amount,選擇一個(gè)起碼 大于或等于的 amount 的UTXO出來;
3)contractArguments ,構(gòu)建args,就是合約里面方法的參數(shù);
4)通常合約交易會(huì)有自己資產(chǎn)的input,合約UTXO的input,這里是要解鎖的utxo的input;
5)這個(gè)是錢包資產(chǎn)的input;
上一章內(nèi)容說過,解鎖合約的交易,必須根據(jù)合約里面的邏輯,計(jì)算出對(duì)應(yīng)的結(jié)果,所以這里的邏輯跟合約里面邏輯是一樣的,儲(chǔ)蓄分紅合約詳細(xì)說明 如圖;
判斷邏輯一樣,這里插件錢包跟上一章說的pc錢包接口的結(jié)構(gòu)有所不同,但是原理一樣。
最后我們看看src\components\layout\save\action.js 的updateDatatbaseBalance 方法
function updateDatatbaseBalance(resp, amount, address){ return updateBalances({ "tx_id": resp.transaction_hash, address, "asset": GetContractArgs().assetDeposited, "amount": -amount }).then(()=>{ return updateBalances({ "tx_id": resp.transaction_hash, address, "asset": GetContractArgs().assetBill, "amount": amount }) }).catch(err => { throw err }) } export function updateBalances(params) { let url switch (window.bytom.net) { case "testnet": url = "/dapptestnet/update-balance" break default: url = "/dapp/update-balance" } return post(url, params) }
同樣是調(diào)用bufferserver,這里是調(diào)用update-balance方法,把成功后的交易提交到后端。
上面介紹了dapp-demo前端代碼的內(nèi)容,介紹了里面的方法,除了插件api的調(diào)用比較復(fù)雜外,其他都是普通的應(yīng)用邏輯調(diào)用,主要理解了質(zhì)量守恒定理,剩下的都是對(duì)數(shù)據(jù)審核數(shù)據(jù)的問題,非常簡單。
有應(yīng)用開發(fā)的讀者應(yīng)該一下子就能理解到問題核心吧,我現(xiàn)在在說說里面的坑;
1) UTXO鎖定接口容易被刷; 假如我一個(gè)開發(fā)人員知道這個(gè)接口,狂刷你這個(gè)接口狂鎖應(yīng)用的UTXO,這樣應(yīng)用長期都會(huì)癱瘓狀態(tài);
解決方案:這個(gè)應(yīng)該從應(yīng)用方面去考慮,譬如接口加一些一次性的驗(yàn)證碼,加refer的監(jiān)控,加授權(quán)之類的方式,后端加上交易監(jiān)控,去維持著各種情況UTXO的狀態(tài),比較抽象,而且比較復(fù)雜,不過這是必須的;
2)并發(fā)問題;跟1)一樣,就算我是一個(gè)正常用戶,選擇了一個(gè)UTXO解鎖后,居然通過http接口告訴后端去鎖定,調(diào)起 輸入密碼頁面 (圖K),這個(gè)時(shí)候如果用戶不輸入密碼不提交,在比原鏈上該UTXO是沒有被解鎖,但是bufferserver會(huì)卻鎖住了。
解決方案: 后端源碼是鎖定一段時(shí)間,如果沒有使用,則定期解鎖出來,這種情況也是需要應(yīng)用的監(jiān)控判斷,維護(hù)所有utxo的狀態(tài),個(gè)人建議在發(fā)合約的時(shí)候,發(fā)多筆UTXO鎖定合約,可用的UTXO就會(huì)變多,這個(gè)時(shí)候有些同學(xué)問,TPS豈不是也一樣不高,如果用過火幣的同學(xué)就知道了,區(qū)塊鏈交易本來就不太注重TPS,而且火幣的交易必須要超過60-100個(gè)區(qū)塊,才確定一筆交易,這個(gè)看應(yīng)用開發(fā)者如何去判斷,取舍。
3)用戶交易信息接口容易被刷;跟1)一樣,交易完成后,直接通過http接口去提交數(shù)據(jù),我狂刷,豈不是億萬富翁....;
解決方案:想要用戶的交易信息,生成交易賬單,可以直接用插件的接口,不過要通過合約編碼去篩選出來,筆者是通過監(jiān)控區(qū)塊鏈瀏覽器所有交易,進(jìn)入數(shù)據(jù)庫交易表的方式,這樣可以時(shí)時(shí)刻刻監(jiān)控所以交易。
4)容易產(chǎn)生鏈?zhǔn)藉e(cuò)誤; 這里dapp-demo發(fā)的是一個(gè)合約的UTXO,假如用戶提交交易之后會(huì)產(chǎn)生新的UTXO,但是這個(gè)UTXO還沒有確認(rèn)的,bufferserver的list-utxo接口會(huì)把還沒有確認(rèn)的UTXO,從而解決并發(fā)問題,但是我一個(gè)開發(fā)人員,知道合約的編碼,隨便寫個(gè)交易提交了,雖然肯定會(huì)失敗,但是需要時(shí)間,這個(gè)時(shí)候bufferserver也把這個(gè)肯定失敗的UTXO返回過來前端,一直鏈?zhǔn)疆a(chǎn)生一堆交易,很容易產(chǎn)生鏈?zhǔn)绞 ?/p>
解決方案:1)這里我跟比原官方的老大深深討論過,最優(yōu)方案當(dāng)然是合約本身設(shè)置一個(gè)密碼,輸入?yún)?shù)必須要根據(jù)這個(gè)密碼去加incode密過,傳入合約交易參數(shù),合約本身在解釋的時(shí)候,再decode解密驗(yàn)證,保證出入的參數(shù)是官方的,這樣就不會(huì)有人攻擊.....不過結(jié)論是,暫時(shí)比原鏈的合約引擎不支持。
2)一定要隱藏好合約邏輯,其他人就沒辦法去惡意調(diào)用惡意占用,例如前端代碼混淆,或者args參數(shù)是后端生成,另外建議比原的blockcenter的build-transaction接口參數(shù)可以加密這樣,去掩蓋合約邏輯。
感謝各位的閱讀,以上就是“Bytom中Dapp Demo合約交易的提交方法是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)Bytom中Dapp Demo合約交易的提交方法是什么這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。