Implement 'tx' command (WIP)

This commit is contained in:
Ivan Kuznetsov 2017-10-03 15:47:27 +07:00
parent c753df287a
commit 3cb93b5278
3 changed files with 93 additions and 3 deletions

View File

@ -25,9 +25,16 @@ func (cli *CLI) send(from, to string, amount int, nodeID string) {
tx := NewUTXOTransaction(&wallet, to, amount, &UTXOSet) tx := NewUTXOTransaction(&wallet, to, amount, &UTXOSet)
cbTx := NewCoinbaseTX(from, "") cbTx := NewCoinbaseTX(from, "")
txs := []*Transaction{cbTx, tx} // txs := []*Transaction{cbTx, tx}
newBlock := bc.MineBlock(txs) // var txHashes [][]byte
UTXOSet.Update(newBlock) // txHashes = append(txHashes, tx.Hash())
// txHashes = append(txHashes, cbTx.Hash())
sendTx(knownNodes[0], tx)
sendTx(knownNodes[0], cbTx)
// newBlock := bc.MineBlock(txs)
// UTXOSet.Update(newBlock)
fmt.Println("Success!") fmt.Println("Success!")
} }

View File

@ -3,6 +3,7 @@ package main
import ( import (
"bytes" "bytes"
"encoding/gob" "encoding/gob"
"encoding/hex"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -17,6 +18,7 @@ const commandLength = 12
var nodeAddress string var nodeAddress string
var knownNodes = []string{"localhost:3000"} var knownNodes = []string{"localhost:3000"}
var blocksInTransit = [][]byte{} var blocksInTransit = [][]byte{}
var mempool = make(map[string]Transaction)
type addr struct { type addr struct {
AddrList []string AddrList []string
@ -43,6 +45,11 @@ type inv struct {
Items [][]byte Items [][]byte
} }
type tx struct {
AddFrom string
Transaction []byte
}
type verzion struct { type verzion struct {
Version int Version int
BestHeight int BestHeight int
@ -133,6 +140,14 @@ func sendGetData(address, kind string, id []byte) {
sendData(address, request) sendData(address, request)
} }
func sendTx(addr string, tnx *Transaction) {
data := tx{nodeAddress, tnx.Serialize()}
payload := gobEncode(data)
request := append(commandToBytes("tx"), payload...)
sendData(addr, request)
}
func sendVersion(addr string, bc *Blockchain) { func sendVersion(addr string, bc *Blockchain) {
bestHeight := bc.GetBestHeight() bestHeight := bc.GetBestHeight()
payload := gobEncode(verzion{nodeVersion, bestHeight, nodeAddress}) payload := gobEncode(verzion{nodeVersion, bestHeight, nodeAddress})
@ -213,6 +228,14 @@ func handleInv(request []byte, bc *Blockchain) {
} }
blocksInTransit = newInTransit blocksInTransit = newInTransit
} }
if payload.Type == "tx" {
txID := payload.Items[0]
if mempool[hex.EncodeToString(txID)].ID == nil {
sendGetData(payload.AddrFrom, "tx", txID)
}
}
} }
func handleGetBlocks(request []byte, bc *Blockchain) { func handleGetBlocks(request []byte, bc *Blockchain) {
@ -249,6 +272,51 @@ func handleGetData(request []byte, bc *Blockchain) {
sendBlock(payload.AddrFrom, &block) sendBlock(payload.AddrFrom, &block)
} }
if payload.Type == "tx" {
txID := hex.EncodeToString(payload.ID)
tx := mempool[txID]
sendTx(payload.AddrFrom, &tx)
// delete(mempool, txID)
}
}
func handleTx(request []byte, bc *Blockchain) {
var buff bytes.Buffer
var payload tx
buff.Write(request[commandLength:])
dec := gob.NewDecoder(&buff)
err := dec.Decode(&payload)
if err != nil {
log.Panic(err)
}
txData := payload.Transaction
tx := DeserializeTransaction(txData)
mempool[hex.EncodeToString(tx.ID)] = tx
if nodeAddress == knownNodes[0] {
for _, node := range knownNodes {
if node != nodeAddress {
sendInv(node, "tx", [][]byte{tx.ID})
}
}
} else {
if len(mempool) >= 2 {
var txs []*Transaction
for _, tx := range mempool {
txs = append(txs, &tx)
}
newBlock := bc.MineBlock(txs)
UTXOSet := UTXOSet{bc}
UTXOSet.Update(newBlock)
mempool = make(map[string]Transaction)
}
}
} }
func handleVersion(request []byte, bc *Blockchain) { func handleVersion(request []byte, bc *Blockchain) {
@ -296,6 +364,8 @@ func handleConnection(conn net.Conn, bc *Blockchain) {
handleGetBlocks(request, bc) handleGetBlocks(request, bc)
case "getdata": case "getdata":
handleGetData(request, bc) handleGetData(request, bc)
case "tx":
handleTx(request, bc)
case "version": case "version":
handleVersion(request, bc) handleVersion(request, bc)
default: default:

View File

@ -228,3 +228,16 @@ func NewUTXOTransaction(wallet *Wallet, to string, amount int, UTXOSet *UTXOSet)
return &tx return &tx
} }
// DeserializeTransaction deserializes a transaction
func DeserializeTransaction(data []byte) Transaction {
var transaction Transaction
decoder := gob.NewDecoder(bytes.NewReader(data))
err := decoder.Decode(&transaction)
if err != nil {
log.Panic(err)
}
return transaction
}