1. 程式人生 > >btcd simnet(模擬環境下)單節點與雙節點的運行

btcd simnet(模擬環境下)單節點與雙節點的運行

多個 not fig 用戶創建 tran bug 現實 不同 extend

btcd simnet模擬環境下的運行

  • 前言
  • 背景
  • 運行比特幣客戶端
    • 生成錢包
    • 開啟btcd服務和btcwallet
    • 使用btcctl操作本地區塊鏈
      • 查看本地賬戶
      • 創建一個賬戶
      • 給用戶分配地址
      • 開始挖礦生成區塊
      • 進行轉賬
  • 其他節點連入本地
  • 結束語

前言

上一篇說到在外網服務器上安裝好了btcd和btcwallet,且編譯了btcd和btcwallet的相關組件,現在我們運行比特幣節點所需要的軟件已經安裝好了,接下來就是使用和運行了。
由於Btcd網上的資料不多,和以太坊相比簡直差遠了,Bitcoin的資料也不多,但至少比Btcd還是要完善的,文檔也還齊全,Btcd有一些細節功能甚至還沒開發完全。所以當初倒騰這個啟動和交互式環境確實花了較多時間。看了很多國外的博客,也和他們有過一些交流,但很多東西自己運行起來就不是那麽回事,總是踩了很多坑,以前弄以太坊私鏈的時候一個下午就全部搞定了,這個btcd足足弄了我一天半。
本文我會介紹btcd在simnet即模擬環境下的啟動和運行方法,其中包括錢包的使用和btcctl交互式rpc命令的使用。最後我會簡單介紹一下simnet環境下多節點的連接。

背景

這裏我簡單介紹一下btcd的四種運行模式,分別有Mainnet,Regression,Testnet和Simnet四種
先給出源碼中參數設置部分的代碼
技術分享圖片
Mainnet就是比特幣主網,連入這個網就是正兒八經地玩比特幣了,你可能需要同步主網區塊,維護區塊鏈信息,然後在主網挖礦等等。我們僅做測試和實驗,故不選擇連入主網。
Testnet是一個公開的測試網,所有開發者都可以訪問這個網絡。為了避免有人惡意囤積上面的Testnet bitcoin,這個testnet每隔一段時期就會清空並以新的創始塊重新開始。任何打算在比特幣主幹網上用於生產的軟件開發都應該首先在testnet上用測試幣進行測試。這樣可以保護開發人員免受由於軟件錯誤而導致的金錢損失,也可以保護網絡免受由於軟件錯誤導致的意外攻擊。
Regression代表“回歸測試”,允許用戶創建本地區塊鏈以進行測試。 與testnet3(它是一個公共和共享的測試區塊鏈)不同,Regressiont區塊鏈旨在作為本地測試的封閉系統運行。 用戶從頭開始啟動regtest區塊鏈,創建一個本地的創世區塊。 可以將其他節點添加到網絡中,或者使用單個節點運行它來測試Bitcoin Core軟件
至於Simnet,也是本地測試的一種網絡,源碼中它的配置參數和Regression還是有一些不同的,比如端口號,和一些分叉的參數,細節我也沒有深入挖掘,大家可以去源碼看一看不同的參數是不是影響你的需求。

我把Regression和Simnet配置的細節放在下面以便對比

var RegressionNetParams = Params{
	Name:        "regtest",
	Net:         wire.TestNet,
	DefaultPort: "18444",
	DNSSeeds:    []DNSSeed{},

	// Chain parameters
	GenesisBlock:             &regTestGenesisBlock,
	GenesisHash:              &regTestGenesisHash,
	PowLimit:                 regressionPowLimit,
	PowLimitBits:             0x207fffff,
	CoinbaseMaturity:         100,
	BIP0034Height:            100000000, // Not active - Permit ver 1 blocks
	BIP0065Height:            1351,      // Used by regression tests
	BIP0066Height:            1251,      // Used by regression tests
	SubsidyReductionInterval: 150,
	TargetTimespan:           time.Hour * 24 * 14, // 14 days
	TargetTimePerBlock:       time.Minute * 10,    // 10 minutes
	RetargetAdjustmentFactor: 4,                   // 25% less, 400% more
	ReduceMinDifficulty:      true,
	MinDiffReductionTime:     time.Minute * 20, // TargetTimePerBlock * 2
	GenerateSupported:        true,

	// Checkpoints ordered from oldest to newest.
	Checkpoints: nil,

	// Consensus rule change deployments.
	//
	// The miner confirmation window is defined as:
	//   target proof of work timespan / target proof of work spacing
	RuleChangeActivationThreshold: 108, // 75%  of MinerConfirmationWindow
	MinerConfirmationWindow:       144,
	Deployments: [DefinedDeployments]ConsensusDeployment{
		DeploymentTestDummy: {
			BitNumber:  28,
			StartTime:  0,             // Always available for vote
			ExpireTime: math.MaxInt64, // Never expires
		},
		DeploymentCSV: {
			BitNumber:  0,
			StartTime:  0,             // Always available for vote
			ExpireTime: math.MaxInt64, // Never expires
		},
		DeploymentSegwit: {
			BitNumber:  1,
			StartTime:  0,             // Always available for vote
			ExpireTime: math.MaxInt64, // Never expires.
		},
	},

	// Mempool parameters
	RelayNonStdTxs: true,

	// Human-readable part for Bech32 encoded segwit addresses, as defined in
	// BIP 173.
	Bech32HRPSegwit: "bcrt", // always bcrt for reg test net

	// Address encoding magics
	PubKeyHashAddrID: 0x6f, // starts with m or n
	ScriptHashAddrID: 0xc4, // starts with 2
	PrivateKeyID:     0xef, // starts with 9 (uncompressed) or c (compressed)

	// BIP32 hierarchical deterministic extended key magics
	HDPrivateKeyID: [4]byte{0x04, 0x35, 0x83, 0x94}, // starts with tprv
	HDPublicKeyID:  [4]byte{0x04, 0x35, 0x87, 0xcf}, // starts with tpub

	// BIP44 coin type used in the hierarchical deterministic path for
	// address generation.
	HDCoinType: 1,
}

var SimNetParams = Params{
	Name:        "simnet",
	Net:         wire.SimNet,
	DefaultPort: "18555",
	DNSSeeds:    []DNSSeed{}, // NOTE: There must NOT be any seeds.

	// Chain parameters
	GenesisBlock:             &simNetGenesisBlock,
	GenesisHash:              &simNetGenesisHash,
	PowLimit:                 simNetPowLimit,
	PowLimitBits:             0x207fffff,
	BIP0034Height:            0, // Always active on simnet
	BIP0065Height:            0, // Always active on simnet
	BIP0066Height:            0, // Always active on simnet
	CoinbaseMaturity:         100,
	SubsidyReductionInterval: 210000,
	TargetTimespan:           time.Hour * 24 * 14, // 14 days
	TargetTimePerBlock:       time.Minute * 10,    // 10 minutes
	RetargetAdjustmentFactor: 4,                   // 25% less, 400% more
	ReduceMinDifficulty:      true,
	MinDiffReductionTime:     time.Minute * 20, // TargetTimePerBlock * 2
	GenerateSupported:        true,

	// Checkpoints ordered from oldest to newest.
	Checkpoints: nil,

	// Consensus rule change deployments.
	//
	// The miner confirmation window is defined as:
	//   target proof of work timespan / target proof of work spacing
	RuleChangeActivationThreshold: 75, // 75% of MinerConfirmationWindow
	MinerConfirmationWindow:       100,
	Deployments: [DefinedDeployments]ConsensusDeployment{
		DeploymentTestDummy: {
			BitNumber:  28,
			StartTime:  0,             // Always available for vote
			ExpireTime: math.MaxInt64, // Never expires
		},
		DeploymentCSV: {
			BitNumber:  0,
			StartTime:  0,             // Always available for vote
			ExpireTime: math.MaxInt64, // Never expires
		},
		DeploymentSegwit: {
			BitNumber:  1,
			StartTime:  0,             // Always available for vote
			ExpireTime: math.MaxInt64, // Never expires.
		},
	},

	// Mempool parameters
	RelayNonStdTxs: true,

	// Human-readable part for Bech32 encoded segwit addresses, as defined in
	// BIP 173.
	Bech32HRPSegwit: "sb", // always sb for sim net

	// Address encoding magics
	PubKeyHashAddrID:        0x3f, // starts with S
	ScriptHashAddrID:        0x7b, // starts with s
	PrivateKeyID:            0x64, // starts with 4 (uncompressed) or F (compressed)
	WitnessPubKeyHashAddrID: 0x19, // starts with Gg
	WitnessScriptHashAddrID: 0x28, // starts with ?

	// BIP32 hierarchical deterministic extended key magics
	HDPrivateKeyID: [4]byte{0x04, 0x20, 0xb9, 0x00}, // starts with sprv
	HDPublicKeyID:  [4]byte{0x04, 0x20, 0xbd, 0x3a}, // starts with spub

	// BIP44 coin type used in the hierarchical deterministic path for
	// address generation.
	HDCoinType: 115, // ASCII for s
}

運行比特幣客戶端

生成錢包

首先,模擬環境下也是需要一個錢包的,錢包裏面可以有多個本地的賬戶,一個賬戶也可以有多個地址

btcwallet --simnet --create

創建一個simnet模式下的錢包

運行如下
技術分享圖片
要求輸入private passphrase,這個passphrase一定要記住,後續解鎖錢包的時候需要用到
後面問你是不是需要多一層的加密或者是否有本地錢包種子可以加載,我們第一次啟動,這些都不需要指定

錢包生成之後,~/.btcwallet文件夾下面就有logs和simnnet文件夾了
技術分享圖片

開啟btcd服務和btcwallet

生成錢包之後,準備工作就算全部完成了,我們來啟動btcd服務
btcd --simnet --rpcuser=rpcuser --rpcpass=rpcpass --rpclisten=0.0.0.0:18556 --listen=0.0.0.0:18555

命令解釋如下:

  1. simnet 指定模擬環境 (註意這個參數後面的命令都是要加上,默認會連到主網上去)
  2. rpcuser 指定btcd的一個用戶名
  3. rpcpass 指定btcd用戶名的密碼
  4. rpclisten 指定rpc監聽服務器(就是後面我們利用btcctl交互的監聽服務器)
  5. listen 指定btcd監聽服務器(其他節點通過這個服務器進行連接)

然後我們需要再打開一個窗口,上面的btcd命令讓它在原來的窗口進行運行
運行指令
btcwallet --simnet --username=rpcuser --password=rpcpass

命令解釋如下:

  1. username 這個username必須和上面btcd開啟時指定的rpcuser是一個 不然無法認證通過
  2. password 同理password也必須和上面的rpcpass是同一個

上面兩步運行情況如下
技術分享圖片
上面是btcwallet的運行窗口,下面是btcd運行窗口。
因為我之前調試代碼的時候加了一些輸出,所以下面的窗口可能有一些輸出和你不一樣。
可以看到當btcwallet打開之後,btcd會顯示 New websocket client 127.0.0.1:50754 這就是錢包客戶端的socket接入

使用btcctl操作本地區塊鏈

到這裏 btcd和btcwallet開啟了之後,服務就算啟動完了。接下來我們需要再打開一個窗口,使用btcctl命令操作區塊鏈,註意,btcd和btcwallet的窗口別關,所以,完整操作一共需要開三個窗口。btcd和btcwallet一般是不需要動的,我們在btcctl的窗口進行交互即可。
我這裏截一個屏幕,後續講解命令的時候就不截圖了

技術分享圖片

接下來的操作都是一些常用的操作,後面我會寫一篇博客把btcctl常用的命令進行簡單敘述

查看本地賬戶

btcctl --simnet --rpcuser=rpcuser --rpcpass=rpcpass --wallet listaccounts

命令解釋如下:

  1. simnet 同理需要指定模擬環境
  2. rpcuser 需要和btcd開啟的那個rpcuser一樣
  3. rpcpass 需要和btcd開啟的那個rpcpass一樣
  4. –wallet btcctl的指令有兩大類 一類是和錢包有關的,另一類則不是,下一篇博客我會詳細介紹這些命令
  5. listacoounts 列出當前錢包下的所有用戶和他們的余額balance

默認情況下裏面只有兩個賬戶default和imported

創建一個賬戶

為了後面轉賬功能更加便於觀察,我們創建一個賬戶

  1. 創建賬戶之前,需要先對錢包解鎖,這裏用到walletpassphrase即前面建立錢包的時候輸入的passphrase。我這裏是"hht"
    btcctl --simnet --rpcuser=rpcuser --rpcpass=rpcpass --wallet walletpassphrase "hht" 600

    解鎖命令後面跟著一個數字,意思是解鎖多久,單位是秒,600s即解鎖十分鐘
    解鎖命令輸入完成之後,可以在btcwallet界面看到消息 “The wallet has been temporarily unlocked”

  2. 解鎖之後,即可創建賬戶了
    btcctl --simnet --rpcuser=rpcuser --rpcpass=rpcpass --wallet createnewaccount kingsley

    這裏通過createnewaccount建立一個賬戶kingsley。

    我的服務器運行這步命令之後,btcctl界面會卡死。我當時卡在這好久好久,找卡死的解決辦法。但是,後來偶然發現,只需要將錢包ctrl+c關閉一下(btcctl也就被停了),再重啟一下錢包,就發現kingsley賬戶已經創建好了。
    也許你不會遇到和我一樣的問題,因為這個問題我在網上找了很久都沒有找到解決辦法,也許是wallet的bug吧。如果你知道原因也歡迎在評論留下您的觀點,謝謝。

    此時再listaccounts可以看到有三個用戶了:default、imported、kingsley

給用戶分配地址

錢包裏面有賬戶是不夠的,比特幣之間轉賬都是基於地址來進行,所以我們要使用後續功能,必須給賬戶分配一個地址。賬戶可以有多個地址。

  1. 現在,我們通過getaddressesbyaccount命令看default和kingsley下的地址
    btcctl --simnet --rpcuser=rpcuser --rpcpass=rpcpass --wallet getaddressesbyaccount default

技術分享圖片
可以看到default賬戶和kingsley賬戶都是沒有地址的,接下來給他們生成地址

  1. 用getnewaddress命令給default分配一個地址
    btcctl --simnet --rpcuser=rpcuser --rpcpass=rpcpass --wallet getnewaddress default

    和創建賬戶一樣,我的服務器運行這步命令之後,btcctl界面會卡死。解決辦法也是一樣的,只需要將錢包ctrl+c關閉一下(btcctl也就被停了),再重啟一下錢包就可以了。

  2. 用getnewaddress命令給kingsley分配一個地址
    btcctl --simnet --rpcuser=rpcuser --rpcpass=rpcpass --wallet getnewaddress kingsley

  3. 通過getaddressesbyaccount命令看default和kingsley下的地址

技術分享圖片

上面 -4: the client has been shutdown就是我將btcwallet殺死之後btcctl的回顯,可以看到default和kingsley已經分配好了地址

開始挖礦生成區塊

現在我們在本地創建好了兩個賬戶,每個賬戶下都有地址了。我們就可以做一些和區塊鏈有關的操作了。
現在區塊鏈上只有一個btcd啟動時初始化的創世區塊。我們來手動生成一些區塊。

在挖礦之前,需要重啟btcd,並給btcd指定一個礦工地址,這樣後面挖出來的區塊獎勵就會給這個地址的賬戶了

  1. 重啟btcd,指定礦工地址,隨意指定,我就用上面的default的地址 SX5uJ3YGgYBQ7iCkjWmZ4hGvsTuE7PvJgk
    btcd --simnet --rpcuser=rpcuser --rpcpass=rpcpass --rpclisten=0.0.0.0:18556 --listen=0.0.0.0:18555 --miningaddr=SX5uJ3YGgYBQ7iCkjWmZ4hGvsTuE7PvJgk --txindex

    命令解釋如下

    1. miningaddr是指定的礦工地址,即本btcd客戶端挖礦出來之後把獎勵給哪個賬戶
    2. txindex 是後面為了使用getrawtranscation查詢交易參數所需要指定的參數。這裏也可以選擇不指定。
  2. 重新打開btcwallet
    btcwallet --simnet --username=rpcuser --password=rpcpass

  3. 通過generate命令手動生成區塊
    btcctl --simnet --rpcuser=rpcuser --rpcpass=rpcpass generate 300

    該指令可以在區塊鏈中手動生成300個區塊,由於全網沒有交易數據,所以這些生成的區塊都只有一個coinbase交易。
    指令運行成功之後可以看到btcd和btcwallet和btcctl三個窗口都有回顯,表示已經生成了區塊
    此時再用listaccounts命令即可以看到剛剛挖出區塊的獎勵已經進入礦工地址了
    技術分享圖片

這裏註意,如果生成的區塊量很少的話,可能礦工賬戶裏會沒有錢。這大概類似以太坊gas的存在類似吧。具體原因我也沒有深究,如有知道的朋友歡迎留言交流。

這裏再提一點,關於這個generate手動生成區塊。有人會問不能讓他自動進行挖礦嘛。
這是可以的,但是在源碼裏面做了一個約束,必須還要有另外一個節點連到本btcd客戶端,才會進行自動挖礦,並且想要自動挖礦,必須更改源代碼config.go中的defaultGenerate參數,將其從默認的false改為true。這樣當有另外一個節點連接進來時,就會自動執行挖礦。同理,在我們的測試網絡,暫時還沒有交易數據,不管是手動挖的區塊還是自動挖的區塊,都只有coinbase交易。
並且,當把defaultGenerate參數改為true的時候

  1. 打開btcd的時候就必須指定挖礦地址,這在剛剛啟動測試環境的時候是不現實的,因為鏈上還沒有一個合法的地址。當然隨便指定一個格式合法地址也是可以的
  2. 不能再用generate函數手動生成區塊了,必須btcctl --simnet --rpcuser=rpcuser --rpcpass=rpcpass --wallet setgenerate 0才行

進行轉賬

我們的default賬戶現在已經有很多比特幣了,我們可以嘗試進行轉賬。此處使用命令sendtoaddress命令,這個命令默認是從default賬戶下轉賬出去的。也有從指定賬戶轉到指定賬戶的命令,不過我沒怎麽用過

  1. 轉賬之前必須先對賬戶進行解鎖
    btcctl --simnet --rpcuser=rpcuser --rpcpass=rpcpass --wallet walletpassphrase "hht" 600

  2. 從default賬戶轉賬100比特幣給kingsley賬戶
    btcctl --simnet --rpcuser=rpcuser --rpcpass=rpcpass --wallet sendtoaddress SYaDYKqmywEGNUvVtCdnCdD2GpvSAWYBmn 100

    這裏可能會出現錯誤 -32603:insufficient funds available to construct transaction
    原因就是沒有足夠的funds,如果我們遇到這個問題,多generate一點區塊多拿一點錢就可以了。

技術分享圖片

可以看到轉賬成功之後 會把這條交易的hash顯示出來。

現在我們listaccounts是看不到kingsley收到了錢的,因為這條交易雖然已經驗證,但還沒有被寫入區塊鏈,所以我們需要手動生成一個塊來將這條命令包含進區塊鏈

btcctl --simnet --rpcuser=rpcuser --rpcpass=rpcpass generate 1

當有新的區塊生成後,剛剛的那條交易就寫入了區塊鏈,這是listaccounts就可以看到Kingsley賬戶下已經有剛剛轉來的100比特幣了。

技術分享圖片

其他節點連入本地

上述描述的是只有本地一個btcd客戶端和一個btcwallet客戶端的環境,稱作機器A。在simnet環境下,可以有任意個節點進行相連組成p2p網絡。
在本文的最後,我簡單介紹一下,其他節點怎麽連入該測試網絡。

我們開啟另一臺服務器,稱作機器B,配置好同A一樣的btcd和btcwallet等軟件。

A機器按照上述方法進行啟動,不需要作更改。

B機器如果想要練到A機器所在的網絡,如下操作

  1. 啟動btcd客戶端
    btcd --simnet -u rpcuser -P rpcpass --rpclisten=0.0.0.0:18556 --listen=0.0.0.0:18555 --simnet --connect=X.X.X.X --miningaddr=XXXXXX
    可以看到和之前啟動Btcd命令一樣,只需要多加一個connect參數,指定A機器的IP地址就好了,這個miningaddr同理也是B機器挖礦成功後的礦工地址,這裏指定一個A機器default地址也是可以的,那B挖出來錢就給A中的defaulta吧。
    我這麽解釋應該很清楚了

  2. 啟動btcwallet客戶端
    這裏就和A機器完全一樣了,因為btcwallet操作的是本地的錢包賬戶。所以正常啟動就好。

當B機器加入之後,可以在A機器btcd窗口看到有新節點加入,這樣兩個節點就連在一起了。一筆跨機器的轉賬也可以正常進行。
通過此方法可以連入無數個節點。方法類似,這裏就不再贅述

結束語

下篇博客我會介紹一下btcctl常用的命令,當然不一定常用,只不過是我實驗經常用的到的命令。

btcd simnet(模擬環境下)單節點與雙節點的運行