新版以太坊Ethereum庫ethersV5.0配合後端Golang1.18實時連結區塊鏈錢包(Metamask/Okc)以及驗籤操作

劉悅的技術部落格發表於2022-12-25

區塊鏈去中心化思想無處不在,比如最近使用個體抗原自檢替代大規模的中心化核酸檢測,就是去中心化思想的落地實踐,避免了大規模聚集導致的交叉感染,提高了檢測效率,本次我們使用Ethereum最新的ethersV5.0以上版本連結去中心化區塊鏈錢包,並且透過後端Golang1.18服務進行驗籤。

在之前的一篇文章:青山不遮,畢竟東流,整合Web3.0身份錢包MetaMask以太坊一鍵登入(Tornado6+Vue.js3)中,我們使用的是ethersV4.0版本連結Metamask錢包,後端使用基於Python3.10的Tornado6.0框架,為了避免同質化,這裡換成Okc錢包,客戶端外掛安裝地址:https://chrome.google.com/webstore/detail/okx-wallet/mcohilncbfahbmgdjkbpemcciiolgcge

前端連結瀏覽器錢包

首先解除安裝Vue2.0專案:

npm uninstall vue-cli -g

這裡node版本要在8.9以上,npm版本要在6以上;

隨後安裝Vue3.0以上版本:

npm install -g @vue/cli

然後安裝pnpm:

npm install -g pnpm

pnpm解決了傳統npm的node_modules依賴困境,主要透過軟連結和硬連結的結合使用,最終達到節省磁碟空間,安裝速度快,嚴格高效等目的,這裡推薦使用pnpm進行包管理。

接著,在當前專案中安裝ethers庫:

pnpm install ethers@5.7.2 --save

注意這裡版本要求v5.0以上。

根據ethers5.4官方文件所述:https://docs.ethers.io/v5/getting-started/#getting-started--connecting-rpc

ethers5.0版本支援非同步async操作,提高了效率,async函式就是使用async關鍵字宣告的函式。它是 AsyncFunction 建構函式的例項,並且其中允許使用 await 關鍵字。async 和 await 關鍵字讓我們可以用一種更簡潔的方式寫出基於 Promise 的非同步行為,而無需刻意地鏈式呼叫 promise。

宣告非同步連結方法:

//連結邏輯  
    connect:async function(){  
  
  
},

隨後請求連結當前的區塊鏈錢包,並且非同步獲取公鑰地址:

const provider = new ethers.providers.Web3Provider(window.ethereum);  
  
const accounts = await provider.send("eth_requestAccounts", []);

列印錢包地址:

console.log(accounts);

如圖所示:

這裡已經列印出了okc錢包的公鑰地址,隨後生成簽名:

const signer = provider.getSigner();  
  
  
var rightnow = (Date.now()/1000).toFixed(0)  
  
            console.log(rightnow);  
  
            signer.signMessage("Signing in at "+rightnow)  
              .then((signature) => {      
                        //列印簽名和公鑰  
                        console.log(accounts[0],signature);  
              });

這裡透過provider物件獲取簽名者物件signer,接著呼叫signMessage方法來進行簽名操作,加簽演算法採用最簡單的字串+時間戳的形式。

前端返回簽名和公鑰地址:

0x5cae6c39a56d99d68e7a20c76da0ec387e34249b 
0x1093b6dc7c6ae1340b2ebcf819dac1a7160b69a2abbb14d86a0696bd96d6b36923d5f3f82588f30a9353b327014338f51d4e7a90baa8052791a8017f156b57511c

後端Golang驗籤

驗籤的目的很好理解,如果在連結錢包的一瞬間,客戶端被監聽的其他軟體惡意篡改公鑰地址,那麼很可能會給客戶造成不可挽回的經濟損失,所以暴露在前端的一切資料都需要後端進行校驗,之前我們採用的是Python3.10版本進行驗籤操作:

from web3.auto import w3  
from eth_account.messages import defunct_hash_message  
import time  
  
public_address = "0x5cae6c39a56d99d68e7a20c76da0ec387e34249b"  
signature = "0xc7b06789e6710652d8540487055e0e75918c9c4366ec47c9e7008760df1dedd6506a908f466e448481afed3fe009bbdbfdfa16c28585eff68be54d600083d4251b"  
  
  
#rightnow = int(time.time())  
  
rightnow = 1670142219  
  
print(rightnow)  
  
     
original_message = 'Signing in at {}'.format(rightnow)  
  
message_hash = defunct_hash_message(text=original_message)  
  
signer = w3.eth.account.recoverHash(message_hash, signature=signature)  
  
print(signer)

程式返回:

1670142219  
0x5cAE6c39A56d99d68e7A20c76da0ec387e34249b

這裡透過簽名反向解析出了公鑰地址,並且和前端獲取的地址保持一致。

下面我們採用Golang1.18版本來驗籤,看看有什麼不一樣,首先安裝Golang1.18,請移步:兔起鶻落全端涵蓋,Go lang1.18入門精煉教程,由白丁入鴻儒,全平臺(Sublime 4)Go lang開發環境搭建EP00

隨後安裝基於Golang的Ethereum庫:

go get github.com/storyicon/sigverify

根據官方文件指引:https://github.com/storyicon/sigverify

構建main.go檔案:

package main  
  
import (  
	"fmt"  
  
	ethcommon "github.com/ethereum/go-ethereum/common"  
	"github.com/storyicon/sigverify"  
)  
  
func main() {  
	valid, err := sigverify.VerifyEllipticCurveHexSignatureEx(  
		ethcommon.HexToAddress("0x5cae6c39a56d99d68e7a20c76da0ec387e34249b"),  
		[]byte("Signing in at 1670142219"),  
		"0xc7b06789e6710652d8540487055e0e75918c9c4366ec47c9e7008760df1dedd6506a908f466e448481afed3fe009bbdbfdfa16c28585eff68be54d600083d4251b",  
	)  
	fmt.Println(valid, err) // true <nil>  
}

這裡sigverify.VerifyEllipticCurveHexSignatureEx方法有三個引數,分別是公鑰地址,簽名字符集以及前端返回的簽名字串,返回值為valid:

➜  mydemo git:(master) ✗ go run "/Users/liuyue/wodfan/work/mydemo/src/mytest.go"  
true <nil>

如果驗籤透過會返回布林值:true。

至此,後端驗籤流程就結束了。

結語

總體而言,前端Ethers採用了ES7新語法async/await實現了重大改進,它提供了一種使用同步程式碼樣式非同步連結錢包物件的方式,而且不會阻塞主執行緒,而後端Golang作為編譯型語言驗籤流程反而比解釋型的Python更加簡單方便。

相關文章