專案 GitHub 位置: https://github.com/weiawesome/block-chain_go
API 相關接口
如今 區塊鏈 基本功能都已完善
但是必須要提供一個方式
可以讓使用者提供交易上去 或是 獲取區塊資訊
所以這回主要將目標著重於以下幾點
首先必須先定義 接口的模樣
檔案位置: "./api/client.go"
物件屬性
type ClientAPI struct {
ConnectNodeAddr string
Conn net.Conn
}
連線與斷線方法
func (c *ClientAPI) Connect() error {
conn, err := net.Dial("tcp", c.ConnectNodeAddr)
if err != nil {
return err
}
c.Conn = conn
return nil
}
func (c *ClientAPI) DisConnect() error {
err := c.Conn.Close()
if err != nil {
return err
}
return nil
}
交易相關方法
func (c *ClientAPI) SubmitFreeTransaction(Amount float64, Address string) error {
return TransactionAPI.SubmitFreeTransaction(c.Conn, Amount, Address)
}
func (c *ClientAPI) SubmitTransaction(From []transaction.From, To []transaction.To, Fee float64, PublicKey string, Signature string) error {
return TransactionAPI.SubmitTransaction(c.Conn, From, To, Fee, PublicKey, Signature)
}
區塊資訊相關方法
func (c *ClientAPI) GetBlock(BlockHash string) (content.ReturnBlock, error) {
return BlockAPI.GetBlock(c.Conn, BlockHash)
}
func (c *ClientAPI) GetBlockByHeight(BlockHeight int64) ([]content.ReturnBlock, error) {
return BlockAPI.GetBlockByHeight(c.Conn, BlockHeight)
}
func (c *ClientAPI) GetLastBlock() (content.ReturnBlock, error) {
return BlockAPI.GetBlock(c.Conn, content.InitQuery)
}
最後與傳輸相關格式
檔案位置: "./api/content"
//block.go
type BroadcastBlock struct {
Block blockchain.Block `json:"block"`
}
//transcation.go
type BroadcastTransaction struct {
Transaction transaction.Transaction
}
//query_block.go
const (
InitQuery = "InitQuery"
QueryByHash = "QueryByHash"
QueryByHeight = "QueryByHeight"
)
type QueryBlock struct {
QueryType string `json:"type"`
BlockHash string `json:"blockHash"`
}
type QueryBlockByHeight struct {
QueryType string `json:"type"`
BlockHeight int64 `json:"block_height"`
}
type ReturnBlock struct {
Block blockchain.Block `json:"block"`
}
//paremeters.go
const (
SuffixString = "\r\nEOF\r\n"
BufferSize = 1024 * 10
)
//utils.go
func SendContent(conn net.Conn, val string) {
responseBytes := []byte(string(val) + SuffixString)
_, err := conn.Write(responseBytes)
if err != nil {
return
}
}
在區塊鏈一開始是部會有虛擬貨幣的
像是比特幣在一開始也沒有正常的交易
(主要是透過礦工挖礦獲得獎勵方式)
根據協定不同 規定礦工挖掘 空區塊則獎勵減半
但是此處避免太消耗計算資源 限定了 不挖掘空區塊
因此對應要處理 免費獲得虛擬貨幣的方式 方便測試
免費獲得虛擬貨幣
檔案位置: "./api/transaction/submit_free_transaction.go"
func SubmitFreeTransaction(Conn net.Conn, Amount float64, Address string) error {
if Amount > conseous.MasterAmount || Amount < 0 {
return errors.New("amount can't large than " + strconv.Itoa(conseous.MasterAmount) + " or less than 0")
}
var f []transaction.From
f = append(f, transaction.From{UTXOHash: conseous.MasterHash})
var t []transaction.To
t = append(t, transaction.To{Address: Address, Amount: Amount})
return SubmitTransaction(Conn, f, t, 0, conseous.MasterPublicKey, conseous.MasterSignature)
}
提交交易
檔案位置: "./api/transaction/submit_transaction.go"
func SubmitTransaction(Conn net.Conn, From []transaction.From, To []transaction.To, Fee float64, PublicKey string, Signature string) error {
t := transaction.Transaction{From: From, To: To, Fee: Fee, PublicKey: PublicKey, Signature: Signature}
strVal, err := t.ToString()
if err != nil {
return err
}
t.TransactionHash = utils.HashSHA256(strVal)
request, err := json.Marshal(content.BroadcastTransaction{Transaction: t})
if err != nil {
return err
}
content.SendContent(Conn, string(request))
return nil
}
獲取區塊資訊 分為三種獲取方式
從 區塊哈希 獲取
檔案位置: "./api/block/get_block.go"
func GetBlock(Conn net.Conn, BlockHash string) (content.ReturnBlock, error) {
request, err := json.Marshal(content.QueryBlock{QueryType: content.QueryByHash, BlockHash: BlockHash})
if err != nil {
return content.ReturnBlock{}, err
}
content.SendContent(Conn, string(request))
totalResponse := ""
buffer := make([]byte, content.BufferSize)
for {
_, err := Conn.Read(buffer)
if err != nil {
break
}
response := string(buffer)
totalResponse += response
if strings.ContainsAny(totalResponse, content.SuffixString) {
totalResponse = totalResponse[:strings.Index(totalResponse, content.SuffixString)]
break
}
}
var block content.ReturnBlock
err = json.Unmarshal([]byte(totalResponse), &block)
return block, nil
}
從 區塊高度 獲取
檔案位置: "./api/block/get_block_by_height.go"
func GetBlockByHeight(Conn net.Conn, BlockHeight int64) ([]content.ReturnBlock, error) {
request, err := json.Marshal(content.QueryBlockByHeight{QueryType: content.QueryByHeight, BlockHeight: BlockHeight})
if err != nil {
return []content.ReturnBlock{}, err
}
content.SendContent(Conn, string(request))
totalResponse := ""
buffer := make([]byte, content.BufferSize)
for {
_, err := Conn.Read(buffer)
if err != nil {
break
}
response := string(buffer)
totalResponse += response
if strings.ContainsAny(totalResponse, content.SuffixString) {
totalResponse = totalResponse[:strings.Index(totalResponse, content.SuffixString)]
break
}
}
var block []content.ReturnBlock
err = json.Unmarshal([]byte(totalResponse), &block)
return block, nil
}
備註: 結果為 List 有可能有分支的狀態 若分支仍存在 則回傳所有符合結果
直接獲取最後區塊
檔案位置: "./api/client.go"
func (c *ClientAPI) GetLastBlock() (content.ReturnBlock, error) {
return BlockAPI.GetBlock(c.Conn, content.InitQuery)
}
其實所謂API接口其實就是提供方法使用
能建立節點並傳給 區塊鏈中礦工節點 進行區塊運算
感覺偏簡單吧~~~
希望透過這篇能理解
經過一整個禮拜的努力
系統架構規劃、節點建立、節點溝通、資料庫建立、區塊運算...
還有共識機制、分支處理 等等等等
現在也有了 相關的API接口
想真的是迫不及待看區塊鏈跑起來的樣子了吧!!!
說實在話真心很感動!