Skip to content

Commit 1f96db0

Browse files
committed
added node syncing
1 parent 683432f commit 1f96db0

File tree

4 files changed

+162
-0
lines changed

4 files changed

+162
-0
lines changed

block/blockchain.go

+59
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package block
22

33
import (
4+
"bytes"
45
"crypto/ecdsa"
56
"crypto/sha256"
67
"encoding/json"
78
"fmt"
89
"goBlockchain/utils"
910
"log"
11+
"net/http"
1012
"strings"
1113
"sync"
1214
"time"
@@ -17,6 +19,12 @@ const (
1719
MINING_SENDER = "THE BLOCKCHAIN"
1820
MINING_REWARD = 1.0
1921
MINING_TIMER_SEC = 20
22+
23+
BLOCKCHAIN_PORT_RANGE_START = 5000
24+
BLOCKCHAIN_PORT_RANGE_END = 5003
25+
NEIGHBOR_IP_RANGE_START = 0
26+
NEIGHBOR_IP_RANGE_END = 1
27+
BLOCKCHAIN_NEIGHBOR_SYNC_TIME_SEC = 20
2028
)
2129

2230
type Block struct {
@@ -69,6 +77,8 @@ type Blockchain struct {
6977
blockchainAddress string
7078
port uint16
7179
mux sync.Mutex
80+
neighbors []string
81+
muxNeighbors sync.Mutex
7282
}
7383

7484
func NewBlockchain(blockchainAddress string, port uint16) *Blockchain {
@@ -80,10 +90,34 @@ func NewBlockchain(blockchainAddress string, port uint16) *Blockchain {
8090
return bc
8191
}
8292

93+
func (bc *Blockchain) Run() {
94+
bc.StartSyncNeighbors()
95+
}
96+
97+
func (bc *Blockchain) SetNeighbors() {
98+
bc.neighbors = utils.FindNeighbors(utils.GetHost(), bc.port, NEIGHBOR_IP_RANGE_START, NEIGHBOR_IP_RANGE_END, BLOCKCHAIN_PORT_RANGE_START, BLOCKCHAIN_PORT_RANGE_END)
99+
log.Printf("%v", bc.neighbors)
100+
}
101+
102+
func (bc *Blockchain) SyncNeighbors() {
103+
bc.muxNeighbors.Lock()
104+
defer bc.muxNeighbors.Unlock()
105+
bc.SetNeighbors()
106+
}
107+
108+
func (bc *Blockchain) StartSyncNeighbors() {
109+
bc.SyncNeighbors()
110+
_ = time.AfterFunc(time.Second*BLOCKCHAIN_NEIGHBOR_SYNC_TIME_SEC, bc.StartSyncNeighbors)
111+
}
112+
83113
func (bc *Blockchain) TransactionPool() []*Transaction {
84114
return bc.transactionPool
85115
}
86116

117+
func (bc *Blockchain) ClearTransactionPool() {
118+
bc.transactionPool = bc.transactionPool[:0]
119+
}
120+
87121
func (bc *Blockchain) MarshalJSON() ([]byte, error) {
88122
return json.Marshal(struct {
89123
Blocks []*Block `json:"chains"`
@@ -96,6 +130,13 @@ func (bc *Blockchain) CreateBlock(nonce int, previousHash [32]byte) *Block {
96130
b := NewBlock(nonce, previousHash, bc.transactionPool)
97131
bc.chain = append(bc.chain, b)
98132
bc.transactionPool = []*Transaction{}
133+
for _, n := range bc.neighbors {
134+
endpoint := fmt.Sprintf("http://%s/transactions", n)
135+
client := &http.Client{}
136+
req, _ := http.NewRequest("DELETE", endpoint, nil)
137+
resp, _ := client.Do(req)
138+
log.Printf("%v", resp)
139+
}
99140
return b
100141
}
101142

@@ -115,6 +156,24 @@ func (bc *Blockchain) Print() {
115156
func (bc *Blockchain) CreateTransaction(sender string, recipient string, value float32,
116157
senderPublicKey *ecdsa.PublicKey, s *utils.Signature) bool {
117158
isTransacted := bc.AddTransaction(sender, recipient, value, senderPublicKey, s)
159+
160+
if isTransacted {
161+
for _, n := range bc.neighbors {
162+
publicKeyStr := fmt.Sprintf("%064x%064x", senderPublicKey.X.Bytes(), senderPublicKey.Y.Bytes())
163+
signatureStr := s.String()
164+
bt := &TransactionRequest{
165+
&sender, &recipient, &publicKeyStr, &value, &signatureStr,
166+
}
167+
m, _ := json.Marshal(bt)
168+
buf := bytes.NewBuffer(m)
169+
endpoint := fmt.Sprintf("http://%s/transactions", n)
170+
client := &http.Client{}
171+
req, _ := http.NewRequest("PUT", endpoint, buf)
172+
resp, _ := client.Do(req)
173+
log.Printf("%v", resp)
174+
}
175+
}
176+
118177
return isTransacted
119178
}
120179

blockchain_server/blockchain_server.go

+35
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,39 @@ func (bcs *BlockchainServer) Transactions(w http.ResponseWriter, req *http.Reque
9696
m = utils.JsonStatus("success")
9797
}
9898
io.WriteString(w, string(m))
99+
case http.MethodPut:
100+
decoder := json.NewDecoder(req.Body)
101+
var t block.TransactionRequest
102+
err := decoder.Decode(&t)
103+
if err != nil {
104+
log.Printf("ERROR: %v", err)
105+
io.WriteString(w, string(utils.JsonStatus("fail")))
106+
return
107+
}
108+
if !t.Validate() {
109+
log.Println("ERROR: missing field(s)")
110+
io.WriteString(w, string(utils.JsonStatus("fail")))
111+
return
112+
}
113+
publicKey := utils.PublicKeyFromString(*t.SenderPublicKey)
114+
signature := utils.SignatureFromString(*t.Signature)
115+
bc := bcs.GetBlockchain()
116+
isUpdated := bc.AddTransaction(*t.SenderBlockchainAddress,
117+
*t.RecipientBlockchainAddress, *t.Value, publicKey, signature)
118+
119+
w.Header().Add("Content-Type", "application/json")
120+
var m []byte
121+
if !isUpdated {
122+
w.WriteHeader(http.StatusBadRequest)
123+
m = utils.JsonStatus("fail")
124+
} else {
125+
m = utils.JsonStatus("success")
126+
}
127+
io.WriteString(w, string(m))
128+
case http.MethodDelete:
129+
bc := bcs.GetBlockchain()
130+
bc.ClearTransactionPool()
131+
io.WriteString(w, string(utils.JsonStatus("success")))
99132
default:
100133
log.Println("ERROR: Invalid HTTP Method")
101134
w.WriteHeader(http.StatusBadRequest)
@@ -157,6 +190,8 @@ func (bcs *BlockchainServer) Amount(w http.ResponseWriter, req *http.Request) {
157190
}
158191

159192
func (bcs *BlockchainServer) Run() {
193+
bcs.GetBlockchain().Run()
194+
160195
http.HandleFunc("/", bcs.GetChain)
161196
http.HandleFunc("/transactions", bcs.Transactions)
162197
http.HandleFunc("/mine", bcs.Mine)

cmd/main.go

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"goBlockchain/utils"
6+
)
7+
8+
func main() {
9+
fmt.Println(utils.GetHost())
10+
}

utils/neighbor.go

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package utils
2+
3+
import (
4+
"fmt"
5+
"net"
6+
"os"
7+
"regexp"
8+
"strconv"
9+
"time"
10+
)
11+
12+
func IsFoundHost(host string, port uint16) bool {
13+
target := fmt.Sprintf("%s:%d", host, port)
14+
15+
_, err := net.DialTimeout("tcp", target, 1*time.Second)
16+
if err != nil {
17+
fmt.Printf("%s %v\n", target, err)
18+
return false
19+
}
20+
return true
21+
}
22+
23+
var PATTERN = regexp.MustCompile(`((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?\.){3})(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)`)
24+
25+
func FindNeighbors(myHost string, myPort uint16, startIp uint8, endIp uint8, startPort uint16, endPort uint16) []string {
26+
address := fmt.Sprintf("%s:%d", myHost, myPort)
27+
28+
m := PATTERN.FindStringSubmatch(myHost)
29+
if m == nil {
30+
return nil
31+
}
32+
prefixHost := m[1]
33+
lastIp, _ := strconv.Atoi(m[len(m)-1])
34+
neighbors := make([]string, 0)
35+
36+
for port := startPort; port <= endPort; port += 1 {
37+
for ip := startIp; ip <= endIp; ip += 1 {
38+
guessHost := fmt.Sprintf("%s%d", prefixHost, lastIp+int(ip))
39+
guessTarget := fmt.Sprintf("%s:%d", guessHost, port)
40+
if guessTarget != address && IsFoundHost(guessHost, port) {
41+
neighbors = append(neighbors, guessTarget)
42+
}
43+
}
44+
}
45+
return neighbors
46+
}
47+
48+
func GetHost() string {
49+
hostname, err := os.Hostname()
50+
if err != nil {
51+
return "127.0.0.1"
52+
}
53+
address, err := net.LookupHost(hostname)
54+
if err != nil {
55+
return "127.0.0.1"
56+
}
57+
return address[0]
58+
}

0 commit comments

Comments
 (0)