13. 网络服务
13.1 NODE_ID设置
现在我们需要为我们搭建好的公链搭建网络层面的连接,到时候项目完成,意味着这份代码就代表一个客户端
拷贝代码:/Users/qinjianquan/pc-network/Part70-Merkle-NODE_ID
先转账测试代码是否正常工作:
./bc transfer -from '["1NQ43HNtgWCcbRvam2j8SN7VQD5m2nEgCU"]' -to '["16WdQu5DuEPLuDXWqZiwKW4XdQWH3L7rxo"]' -amount '["2"]'
接下来我们开始正式做网络相关的工作
我们设置一个环境变量,此时每次在启动客户端时就需要输入一个任意NODE_ID值,如:export NODE_ID=3000
func (cli CLI) Run() {
isValidArgs()
//get Node ID from env var
nodeID := os.Getenv("NODE_ID")
if nodeID == "" {
fmt.Printf("NODE_ID is not set\n")
os.Exit(1)
}
fmt.Printf("NODE_ID:%s\n", nodeID)
--
}
13.2 NODE_ID项目配置
按照惯例先把之前的文件复制并重新命名
/Users/qinjianquan/publicChain/Part71-Net-NODE_ID-Configuration
然后我们需要重新配置数据库和钱包文件
格式化数据库
/Users/qinjianquan/publicChain/Part71-Net-NODE_ID-Configuration/src/Blockchain_Iterator.go
const dbName = "blockChain_%s.db"
然后更改部分函数,另外也需要为涉及的函数增加一个参数nodeID string
func CreatBlockchainWithGenesisBlock(address string, nodeID string) *Blockchain {
//format db name
dbName := fmt.Sprintf(dbName, nodeID)
if DBExists(dbName) {
fmt.Println("Genesis block existed")
os.Exit(1)
}
--
}
func BlockChainObject(nodeID string) *Blockchain {
//format db name
dbName := fmt.Sprintf(dbName, nodeID)
if DBExists(dbName) {
fmt.Println("database didn't exist")
os.Exit(1)
}
--
}
格式化钱包
/Users/qinjianquan/publicChain/Part71-Net-NODE_ID-Configuration/src/Wallets.go
const walletFile = "wallets_%s.dat"
func NewWallets(nodeID string) (*Wallets, error) {
walletFile := fmt.Sprintf(walletFile, nodeID)
//to find the file,if there is no file,create a one
if _, err := os.Stat(walletFile); os.IsNotExist(err) {
//create a struct
wallets := &Wallets{}
//access its property and initialize it
wallets.WalletMap = make(map[string]*Wallet)
return wallets, err
}
--
}
当然这也需要更新与之相关的其他函数,根据提示补充即可
这样做的目的在于可以将节点的印记和数据库、钱包关联起来,以作区分
编译并设置NODE_ID
go build main.go
export NODE_ID=3000
//创建钱包
./main createWallet
NODE_ID:3000
Wallet address: 15wtkW1HNytLtdbmm448Le6WaftU8hq5Lv
//创建创世区块
./main createBlockChain -address 15wtkW1HNytLtdbmm448Le6WaftU8hq5Lv
NODE_ID:3000
is creating genesis block...
Block hash:00006001e75e2905628142518f09a0fd03ef078b1040518056d2e44e03b80ca1
查看数据库和钱包文件,其名称如预期的一样已被更改
ls
blockChain_3000.db main main.go src wallets_3000.dat
拷贝重命名数据库
cp blockChain_3000.db blockChain_3001.db
qinjianquan@MacBook-Pro-10 Part71-Net-NODE_ID-Configuration % ls
blockChain_3000.db blockChain_3001.db main main.go src wallets_3000.dat
用新的节点创建钱包
NODE_ID=3001
qinjianquan@MacBook-Pro-10 Part71-Net-NODE_ID-Configuration % ./bc createWallet
NODE_ID:3001
Wallet address: 1G6xGK8Zn1AZVAW6LcdDr2fwf7RqWXWhEs
1
./bc getAddressList
NODE_ID:3001
Address list:
1G6xGK8Zn1AZVAW6LcdDr2fwf7RqWXWhEs
13iAHiLFxYiqNSJHP2baiFyDumd9chEfAU
注意:此时还是在一条链上
13.3 区块链的验证逻辑
按照惯例先把之前的文件复制并重新命名
/Users/qinjianquan/publicChain/Part72-Net-Mine_Cli
现在我们在转账时增加验证环节
/Users/qinjianquan/publicChain/Part72-Net-Mine_Cli/src/CLI.go
func (cli CLI) Run() {
--
flagSendBlockVerify := transferBlockCmd.Bool("mine", false, "Whether to verify now")
--
if transferBlockCmd.Parsed() {
if *flagFrom == "" || *flagTo == "" || *flagAmount == "" {
printUsage()
os.Exit(1)
}
from := JSONToArray(*flagFrom)
to := JSONToArray(*flagTo)
//verify the validity of address before transaction occurs
for index, fromAddress := range from {
if IsValidForAddress([]byte(fromAddress)) == false || IsValidForAddress([]byte(to[index])) == false {
fmt.Println("Address is invalid")
printUsage()
os.Exit(1)
}
}
amount := JSONToArray(*flagAmount)
cli.send(from, to, amount, nodeID, *flagSendBlockVerify)
}
--
}
/Users/qinjianquan/publicChain/Part72-Net-Mine_Cli/src/CLI_transfer.go
func (cli CLI) send(from []string, to []string, amount []string, nodeID string, mineNow bool) {
blockchain := BlockChainObject(nodeID)
defer blockchain.DB.Close()
if mineNow {
//mine a new clock
blockchai