【用Python自幹一個區塊鏈(3)】

李耕銘
Jan 4, 2021

我們的區塊鏈還少了一個必要的東西:P2P網路,區塊鏈沒辦法接收其他人的請求,只能在本機端跑,因此接下來就會來透過通訊把區塊鏈區分成:節點端(礦工端)與客戶端!

節點與使用者的溝通

前置作業

現在的目標是模擬節點或礦工端跟使用者端的互動,節點儲存了自創世塊以來的所有交易明細,同時也負責接受交易、打包交易至區塊、挖掘區塊、廣播挖掘到的區塊等等;而使用者端通常只會讀取鏈上的資料與發起交易,也因為交易紀錄動輒數十GB起跳,為了效率與經濟的考量,使用者端通常也不會儲存交易紀錄。

為了方便模擬我們把兩端的程式都跑在同一台電腦上,這裡選用的通訊方式是socket;也因為加入通訊後程式必須同時處理多樣的工作,所以使用thread來讓程式能夠順利執行監聽與挖礦這兩件事情。

節點的功能

節點的功能與我們之前所撰寫的並無差異,也就是需要:

  1. 產生公私鑰(錢包地址)
  2. 儲存交易紀錄
  3. 確認帳戶餘額
  4. 驗證交易上面的數位簽章
  5. 打包交易並挖掘新區塊

使用者端的功能

使用者端至少需要能夠產生公私鑰簽署交易,簡單說就是為了避免私鑰外洩的風險,所有跟私鑰有關的作業(產生公私鑰或簽署數位簽章)通通都由使用者端完成,不需要仰賴外界或是將私鑰傳至節點即可完成。

  1. 產生公私鑰(錢包地址)
  2. 向節點查詢資料
  3. 發起並簽署交易

節點端

在節點端這裡首先我們需要準備socket的端口讓外界可以連入,因為測試時節點端與使用者端都在本機上,所以IP地址給的是本機的127.0.0.1,至於Port則因為每一個節點所用的Port不同,因此在執行程式時再透過命令列的參數給定。

準備socket連線的端口

開thread監聽新連線與傳入訊息

為了在打包交易與挖礦的同時能夠接收外界的資訊,我們開一個thread在bind之後等待外界的新連線s.accept(),同時在每次新連線建立之後,又為每一個獨立的連線開一個thread去接收並且處理資訊。

接收訊息後處理

這裡我們根據使用者傳遞過來的資料,判別使用者想要做

  1. 取得帳戶餘額
  2. 發起交易

再根據使用者想做的事情分別去接收不同參數,並且回傳結果給使用者。

啟動節點

完成上面接收並且處理資訊的過程後,便可以啟動節點、打包新交易、挖掘新區塊、調節難度,同時我們也可以根據外界的請求做相對應的處置。在這裡為了測試轉帳,我們同時產出一組礦工的公私鑰來使用(轉帳的前提是帳戶裡必須有足夠的餘額,在一開始也只有礦工有,因此我們只能用礦工的公私鑰來發起交易)。

客戶端

客戶端這裡的工作相對單純,首先建立與節點間的socket聯繫,這裡節點的IP因為同在本地端因此也為127.0.0.1,節點端的Port的部分則在啟動程式碼時再帶入。之後就可以開一個Thread不停去接收socket傳過來的資訊。

接收訊息

產生錢包地址與公私鑰

為了避免私鑰外洩,強烈建議公私鑰都在使用者的本地端產生,在利用RSA加密法產生一對鑰匙後,再把裏頭的前綴與後綴字濾掉後便是我們的公私鑰。比方說公鑰是:

— — -BEGIN PUBLIC KEY — — -
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANrG/HiSL6M41EaDsmpVKW+E4QZKaiW2KZD2RR7If7f9jMZiojoS1/uM0N6AQ2G8TUkPHjBuAnS1Dn4PJZAUysMCAwEAAQ==
— — -END PUBLIC KEY — — -

產生的地址便是

MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANrG/HiSL6M41EaDsmpVKW+E4QZKaiW2KZD2RR7If7f9jMZiojoS1/uM0N6AQ2G8TUkPHjBuAnS1Dn4PJZAUysMCAwEAAQ==

私鑰原本是:

 — — -BEGIN RSA PRIVATE KEY — — -
MIIBOwIBAAJBANrG/HiSL6M41EaDsmpVKW+E4QZKaiW2KZD2RR7If7f9jMZiojoS1/uM0N6AQ2G8TUkPHjBuAnS1Dn4PJZAUysMCAwEAAQJBAKWsPHKd2X9UQMQpZQnK9fbifHmEDsACI5YIOK2oDbfo3mzW+gfxHtS1YVZz5TlymUAwm+qxBnwjTPEm+Jqn9ukCIQD1pl7vOofGdAiPBM0M2mJpOh7/b82XSCO/LCyRaP8pPwIhAOP+wxujrxReBwzZmH6rqpKuuK2ueEVY/eVxpnHfaZl9AiAlT2mn6DnrGICcSFxkkV7VILDIl1Cgo6JaTPlP9KScvQIhAIMFft49XHnZ5zdNPMNep7GP0vWMk/VWROI8Q6ig+TCJAiBFug2F+uZz3Gma5ySWBN49eH95o1PqYkDcoATkZ90skQ==
— — -END RSA PRIVATE KEY — — -

過濾後產生的私鑰便是:

MIIBOwIBAAJBANrG/HiSL6M41EaDsmpVKW+E4QZKaiW2KZD2RR7If7f9jMZiojoS1/uM0N6AQ2G8TUkPHjBuAnS1Dn4PJZAUysMCAwEAAQJBAKWsPHKd2X9UQMQpZQnK9fbifHmEDsACI5YIOK2oDbfo3mzW+gfxHtS1YVZz5TlymUAwm+qxBnwjTPEm+Jqn9ukCIQD1pl7vOofGdAiPBM0M2mJpOh7/b82XSCO/LCyRaP8pPwIhAOP+wxujrxReBwzZmH6rqpKuuK2ueEVY/eVxpnHfaZl9AiAlT2mn6DnrGICcSFxkkV7VILDIl1Cgo6JaTPlP9KScvQIhAIMFft49XHnZ5zdNPMNep7GP0vWMk/VWROI8Q6ig+TCJAiBFug2F+uZz3Gma5ySWBN49eH95o1PqYkDcoATkZ90skQ==

同時這裡的程式碼節點端也會用到喔!

初始化交易

接著就可以來初始化一筆交易了!依序填入這筆交易的匯款方、收款方、匯款金額、手續費與備註後生成一筆交易。

簽章交易

為了讓礦工驗證這筆交易的確是由我們親自發出的,因此發出去交易前我們先透過私鑰對交易的內容做簽署,完成後就得到這筆交易的數位簽章,礦工可以透過數位簽章確認是由我們發出的。

控制流程

接著便是控制整個流程了!在使用者端總共有三件事情可以做:

  1. 產生地址與公私鑰
  2. 向節點詢問帳戶的餘額
  3. 發起並簽署交易後送到節點端等待礦工確認與上鏈

文章列表:

  1. 定義基本架構、功能與格式
    http://bit.ly/3rPRrtE
  2. 利用非對稱加密簽署並發送交易
    http://bit.ly/3og5jLF
  3. 製作節點與用戶端程式
    http://bit.ly/2KVXBb2
  4. 節點間的廣播與同步
    http://bit.ly/394aurx

工商服務

我在台大資工訓練班有開設相關區塊鏈課程,有興趣的可以參考。
https://train.csie.ntu.edu.tw/train/course.php?id=3174

本章的程式碼如下

用戶端

節點端

--

--