Add files via upload

This commit is contained in:
[#571] 2020-07-10 17:20:30 -05:00 committed by GitHub
parent 06f9493429
commit a2c34ec03f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 575 additions and 165 deletions

View File

@ -1,8 +1,8 @@
.PHONY: default build node client
default: build
build: node.go client.go serve.go
go build -o node node.go serve.go
go build -o client client.go
go build -o node node.go serve.go values.go
go build -o client client.go values.go
node: node
./node
client: client

View File

@ -1,6 +1,7 @@
package blockchain
import (
"time"
"sort"
"bytes"
"math/big"
@ -48,6 +49,7 @@ func (block *Block) hash() []byte {
ToBytes(uint64(block.Difficulty)),
block.PrevHash,
[]byte(block.Miner),
[]byte(block.TimeStamp),
},
[]byte{},
))
@ -105,3 +107,27 @@ func (block *Block) mappingIsValid() bool {
}
return true
}
func (chain *BlockChain) timeIsValid(block *Block, index uint64) bool {
btime, err := time.Parse(time.RFC3339, block.TimeStamp)
if err != nil {
return false
}
var sblock string
row := chain.DB.QueryRow("SELECT Block FROM BlockChain WHERE Hash=$1", Base64Encode(block.PrevHash))
row.Scan(&sblock)
lblock := DeserializeBlock(sblock)
if lblock == nil {
return false
}
ltime, err := time.Parse(time.RFC3339, lblock.TimeStamp)
if err != nil {
return false
}
result := btime.Sub(ltime)
return result >= TIME_SESSION
}

View File

@ -3,6 +3,7 @@ package blockchain
import (
"os"
"fmt"
"time"
"bytes"
"errors"
"database/sql"
@ -20,19 +21,15 @@ func NewChain(filename, receiver string) error {
return errors.New("open database")
}
defer db.Close()
_, err = db.Exec(`
CREATE TABLE BlockChain (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Hash VARCHAR(44) UNIQUE,
Block TEXT
);
`)
_, err = db.Exec(CREATE_TABLE)
chain := &BlockChain{
DB: db,
}
genesis := &Block{
CurrHash: []byte(GENESIS_BLOCK),
Mapping: make(map[string]uint64),
Miner: receiver,
TimeStamp: time.Now().Format(time.RFC3339),
}
genesis.Mapping[STORAGE_CHAIN] = STORAGE_VALUE
genesis.Mapping[receiver] = GENESIS_REWARD
@ -48,10 +45,48 @@ func LoadChain(filename string) *BlockChain {
chain := &BlockChain{
DB: db,
}
chain.Index = chain.Size()
chain.index = chain.Size()
return chain
}
func (chain *BlockChain) BlockIsValid(block *Block) bool {
// size := chain.index
// chain.index = size - 1
// defer func() {
// chain.index = size
// }()
switch {
case block == nil:
println(1)
return false
case block.Difficulty != DIFFICULTY:
println(2)
return false
case !block.hashIsValid():
println(3)
return false
case !chain.hashIsValid(block, chain.Size()):
println(4)
return false
case !block.signIsValid():
println(5)
return false
case !block.proofIsValid():
println(6)
return false
case !block.mappingIsValid():
println(7)
return false
case !chain.timeIsValid(block, chain.Size()):
println(8)
return false
case !chain.transactionsIsValid(block):
println(9)
return false
}
return true
}
func (chain *BlockChain) Size() uint64 {
var index uint64
row := chain.DB.QueryRow("SELECT Id FROM BlockChain ORDER BY Id DESC")
@ -91,9 +126,15 @@ func (chain *BlockChain) PrintChain() error {
}
if !block.hashIsValid() {
fmt.Printf("[%d][FAILED] hash is not valid\n", index)
fmt.Printf("[%d][FAILED] block hash is not valid\n", index)
} else {
fmt.Printf("[%d][SUCCESS] hash is valid\n", index)
fmt.Printf("[%d][SUCCESS] block hash is valid\n", index)
}
if !chain.hashIsValid(block, index - 1) {
fmt.Printf("[%d][FAILED] chain hash is not valid\n", index)
} else {
fmt.Printf("[%d][SUCCESS] chain hash is valid\n", index)
}
if !block.signIsValid() {
@ -114,14 +155,20 @@ func (chain *BlockChain) PrintChain() error {
fmt.Printf("[%d][SUCCESS] mapping is valid\n", index)
}
size = chain.Index
chain.Index = index - 1
if !chain.timeIsValid(block, index - 1) {
fmt.Printf("[%d][FAILED] time is not valid\n", index)
} else {
fmt.Printf("[%d][SUCCESS] time is valid\n", index)
}
size = chain.index
chain.index = index - 1
if !chain.transactionsIsValid(block) {
fmt.Printf("[%d][FAILED] transactions is not valid\n", index)
} else {
fmt.Printf("[%d][SUCCESS] transactions is valid\n", index)
}
chain.Index = size
chain.index = size
print:
fmt.Printf("[%d] => %s\n\n", index, sblock)
@ -135,7 +182,7 @@ func (chain *BlockChain) Balance(address string) uint64 {
block *Block
balance uint64
)
rows, err := chain.DB.Query("SELECT Block FROM BlockChain WHERE Id <= $1 ORDER BY Id DESC", chain.Index)
rows, err := chain.DB.Query("SELECT Block FROM BlockChain WHERE Id <= $1 ORDER BY Id DESC", chain.index)
if err != nil {
return balance
}
@ -158,9 +205,9 @@ func (chain *BlockChain) LastHash() []byte {
return Base64Decode(hash)
}
func (chain *BlockChain) PushBlock(user *User, block *Block) {
func (chain *BlockChain) AcceptBlock(user *User, block *Block) *Block {
if !chain.transactionsIsValid(block) {
return
return nil
}
block.AddTransaction(chain, &Transaction{
RandBytes: GenerateRandomBytes(RAND_BYTES),
@ -168,20 +215,28 @@ func (chain *BlockChain) PushBlock(user *User, block *Block) {
Receiver: user.Address(),
Value: STORAGE_REWARD,
})
block.TimeStamp = time.Now().Format(time.RFC3339)
block.CurrHash = block.hash()
block.Signature = block.sign(user.Private())
block.Nonce = block.proof()
chain.AddBlock(block)
return block
}
func (chain *BlockChain) AddBlock(block *Block) {
chain.Index += 1
chain.index += 1
chain.DB.Exec("INSERT INTO BlockChain (Hash, Block) VALUES ($1, $2)",
Base64Encode(block.CurrHash),
SerializeBlock(block),
)
}
func (chain *BlockChain) hashIsValid(block *Block, index uint64) bool {
var id uint64
row := chain.DB.QueryRow("SELECT Id FROM BlockChain WHERE Hash=$1", Base64Encode(block.PrevHash))
row.Scan(&id)
return id == index
}
func (chain *BlockChain) transactionsIsValid(block *Block) bool {
lentxs := len(block.Transactions)
plusStorage := 0
@ -192,16 +247,19 @@ func (chain *BlockChain) transactionsIsValid(block *Block) bool {
}
}
if lentxs == 0 || lentxs > TXS_LIMIT + plusStorage {
// fmt.Println("Q:", 1)
return false
}
for i := 0; i < lentxs-1; i++ {
for j := i+1; j < lentxs; j++ {
// rand bytes not be equal
if bytes.Equal(block.Transactions[i].RandBytes, block.Transactions[j].RandBytes) {
// fmt.Println("Q:", 2)
return false
}
// storage tx only one
if block.Transactions[i].Sender == STORAGE_CHAIN && block.Transactions[j].Sender == STORAGE_CHAIN {
// fmt.Println("Q:", 3)
return false
}
}
@ -211,20 +269,25 @@ func (chain *BlockChain) transactionsIsValid(block *Block) bool {
// storage tx has no hash and signature
if tx.Sender == STORAGE_CHAIN {
if tx.Receiver != block.Miner || tx.Value != STORAGE_REWARD {
// fmt.Println("Q:", 4)
return false
}
} else {
if !tx.hashIsValid() {
// fmt.Println("Q:", 5)
return false
}
if !tx.signIsValid() {
// fmt.Println("Q:", 6)
return false
}
}
if !chain.balanceIsValid(block, tx.Sender) {
// fmt.Println("Q:", 7)
return false
}
if !chain.balanceIsValid(block, tx.Receiver) {
// fmt.Println("Q:", 8)
return false
}
}

View File

@ -10,6 +10,16 @@ func init() {
rand.Seed(time.Now().UnixNano())
}
const (
CREATE_TABLE = `
CREATE TABLE BlockChain (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Hash VARCHAR(44) UNIQUE,
Block TEXT
);
`
)
const (
// DEBUG = false
DEBUG = true
@ -19,14 +29,15 @@ const (
STORAGE_REWARD = 1
GENESIS_BLOCK = "GENESIS-BLOCK"
GENESIS_REWARD = 100
DIFFICULTY = 15
TXS_LIMIT = 6
TRANSFER_MAX = 10
DIFFICULTY = 20 // 15
TXS_LIMIT = 2 // 6
TIME_SESSION = 1 * time.Minute// minutes
START_PERCENT = 10
RAND_BYTES = 32
)
type BlockChain struct {
Index uint64
index uint64
DB *sql.DB
}
@ -39,6 +50,7 @@ type Block struct {
Mapping map[string]uint64
Miner string // Hashname
Signature []byte // Miner sign
TimeStamp string // time.Now().Format(time.RFC850)
}
type Transaction struct {
@ -50,4 +62,5 @@ type Transaction struct {
ToStorage uint64
CurrHash []byte
Signature []byte
// TimeStamp string
}

View File

@ -14,7 +14,7 @@ func NewTransaction(user *User, lasthash []byte, to string, value uint64) *Trans
Receiver: to,
Value: value,
}
if value > TRANSFER_MAX {
if value > START_PERCENT {
tx.ToStorage = STORAGE_REWARD
}
tx.CurrHash = tx.hash()
@ -31,7 +31,7 @@ func (block *Block) AddTransaction(chain *BlockChain, tx *Transaction) error {
if value, ok := block.Mapping[tx.Sender]; ok {
balanceInChain = value
}
if tx.Value > TRANSFER_MAX && tx.ToStorage != STORAGE_REWARD {
if tx.Value > START_PERCENT && tx.ToStorage != STORAGE_REWARD {
return errors.New("storage reward pass")
}
if balanceInBlock > balanceInChain {

103
client.go
View File

@ -12,62 +12,59 @@ import (
bc "./blockchain"
)
var (
Addresses []string
User *bc.User
)
const (
OPT_BLOCKCHAIN = "[GET-BLOCKCHAIN]"
OPT_LASTHASH = "[GET-LASTHASH]"
OPT_BALANCE = "[GET-BALANCE]"
OPT_TRANSACTION = "[ADD-TRANSACTION]"
)
func init() {
if len(os.Args) < 2 {
fmt.Println("failed: len(os.Args) < 2\n")
os.Exit(1)
}
var (
addrExist = false
userExist = false
addrStr = ""
userNewStr = ""
userLoadStr = ""
)
var (
addrExist = false
userNewExist = false
userLoadExist = false
)
for i := 1; i < len(os.Args); i++ {
arg := os.Args[i]
switch {
case strings.HasPrefix(arg, "-newuser:"):
arg = strings.Replace(arg, "-newuser:", "", 1)
User = userNew(arg)
if User == nil {
fmt.Println("failed: generate user\n")
os.Exit(1)
}
userExist = true
case strings.HasPrefix(arg, "-loaduser:"):
arg = strings.Replace(arg, "-loaduser:", "", 1)
User = userLoad(arg)
if User == nil {
fmt.Println("failed: load user\n")
os.Exit(1)
}
userExist = true
case strings.HasPrefix(arg, "-loadaddr:"):
arg = strings.Replace(arg, "-loadaddr:", "", 1)
err := json.Unmarshal([]byte(readFile(arg)), &Addresses)
if err != nil {
fmt.Println("failed: load addresses\n")
os.Exit(1)
}
if len(Addresses) == 0 {
fmt.Println("failed: len(Addresses) == 0\n")
os.Exit(1)
}
addrStr = strings.Replace(arg, "-loadaddr:", "", 1)
addrExist = true
case strings.HasPrefix(arg, "-newuser:"):
userNewStr = strings.Replace(arg, "-newuser:", "", 1)
userNewExist = true
case strings.HasPrefix(arg, "-loaduser:"):
userLoadStr = strings.Replace(arg, "-loaduser:", "", 1)
userLoadExist = true
}
}
if !userExist || !addrExist {
fmt.Println("failed: !userExist || !addrExist\n")
err := json.Unmarshal([]byte(readFile(addrStr)), &Addresses)
if err != nil {
fmt.Println("failed: load addresses\n")
os.Exit(1)
}
if len(Addresses) == 0 {
fmt.Println("failed: len(Addresses) == 0\n")
os.Exit(1)
}
if !(userNewExist || userLoadExist) || !addrExist {
fmt.Println("failed: !(userNewExist || userLoadExist) || !addrExist\n")
os.Exit(1)
}
if userNewExist {
User = userNew(userNewStr)
}
if userLoadExist {
User = userLoad(userLoadStr)
}
if User == nil {
fmt.Println("failed: load user\n")
os.Exit(1)
}
}
@ -113,7 +110,7 @@ func handleClient() {
func chainPrint() {
for i := 0; ; i++ {
res := nt.Send(Addresses[0], &nt.Package{
Option: OPT_BLOCKCHAIN,
Option: GET_CHAIN,
Data: fmt.Sprintf("%d", i),
})
if res.Data == "" {
@ -130,7 +127,7 @@ func chainTX(splited []string) {
return
}
res := nt.Send(Addresses[0], &nt.Package{
Option: OPT_LASTHASH,
Option: GET_LASTHASH,
})
num, err := strconv.Atoi(splited[2])
if err != nil {
@ -140,12 +137,20 @@ func chainTX(splited []string) {
tx := bc.NewTransaction(User, bc.Base64Decode(res.Data), splited[1], uint64(num))
sertx := bc.SerializeTX(tx)
for _, addr := range Addresses {
nt.Send(addr, &nt.Package{
Option: OPT_TRANSACTION,
res := nt.Send(addr, &nt.Package{
Option: ADD_TRANSACTION,
Data: sertx,
})
if res == nil {
continue
}
if res.Data == "ok" {
fmt.Printf("success: (%s)\n", addr)
} else {
fmt.Printf("fail: (%s)\n", addr)
}
}
fmt.Println("success: transaction sent\n")
fmt.Println()
}
func chainBalance(splited []string) {
@ -154,7 +159,7 @@ func chainBalance(splited []string) {
return
}
res := nt.Send(Addresses[0], &nt.Package{
Option: OPT_BALANCE,
Option: GET_BALANCE,
Data: splited[1],
})
fmt.Println("Balance:", res.Data, "coins\n")
@ -166,7 +171,7 @@ func userBalance() {
return
}
res := nt.Send(Addresses[0], &nt.Package{
Option: OPT_BALANCE,
Option: GET_BALANCE,
Data: User.Address(),
})
fmt.Println("Balance:", res.Data, "coins\n")

42
examples/exmp_bc.go Normal file
View File

@ -0,0 +1,42 @@
package main
import (
"os"
bc "./blockchain"
)
const (
BLOCKCHAIN_DB = "blockchain.db"
)
const (
purse1 = "MIIBPAIBAAJBAO+M9NcRJAoZucR2PoenzfTN3bpfpJuuq4bXwbzabAh+XhmY4I5LfNN016SNhjzHqp8y6uD/pdHmp6tVcXZ5Gk0CAwEAAQJBAJdiNLhVFLltWIBXWVzRJs616pGFL7lSwQMOBlkaj3stZ7koGsIcT3PaQRMf23FKq1gUzMPyey0njP4+WJ7ZTuECIQD5k7Nn8HFYAHjnadoJFTzxHzbWKEpLcULNmtFoGGL65wIhAPW3MtXdWdy5zcWFad4Rf8SCmsip4NMWAQBaIBsvyi6rAiEA9e3AVISO+7uDZ+1bZ6Xg5mzuuTr8crjJrhaHkL6vEjMCIAllSfJXlnoUOMQWx+eP77zJ6bVGmaw4qS0kRRoFB8wlAiEA8kYB4ODHHgP/4kn74gVOqDWKGOZZk2uxNTWzgQnF4f0="
purse2 = "MIIBPAIBAAJBAOJhasuqmGs/YSTkQOsrXmiFLvdqwRVTUJCJ3LG64pietxsAZKiGs57uGHjs4nDTmMiHkeo6OxoLBlUJvGB4RV8CAwEAAQJAD72wXFsPYB23FoackP2iAeiI3IFaza3OY06CvwT8rpnxHcinpeAfxeanEraHsWNpPmzqhsx066Wuup3idJQxkQIhAP96uD/G+taZ1owsDid+aCzNjSDNFzxLqCibygv3Ghm5AiEA4teEV4XvF5yFqDMpwqXYFuGFXvwMmKuFuyhjo3b7g9cCIQCHMvByf+Ca1MqfX2kWKWUD4LuA0kgrlnYlF1yzPE9JsQIhAJNJroOJ0lG5bstk1ROuzV0l94xSCffDPyTjt7Z21h6nAiEA5atlLYR1LaId1rz1wJFMi5O2iMFJjLC1g6USqO0s5ZA="
)
func main() {
user1 := bc.LoadUser(purse1)
user2 := bc.LoadUser(purse2)
err := bc.NewChain(BLOCKCHAIN_DB, user1.Address())
if err != nil {
panic(err)
}
chain := bc.LoadChain(BLOCKCHAIN_DB)
for i := 0; i < 3; i++ {
block := bc.NewBlock(user2.Address(), chain.LastHash())
block.AddTransaction(chain, block.NewTransaction(user1, "aaa", 11))
block.AddTransaction(chain, block.NewTransaction(user1, "bbb", 11))
chain.PushBlock(user2, block)
}
chain.PrintChain()
}
func fileIsExist(filename string) bool {
if _, err := os.Stat(filename); os.IsNotExist(err) {
return false
}
return true
}

32
examples/exmp_net.go Normal file
View File

@ -0,0 +1,32 @@
package main
import (
"fmt"
"net"
"strings"
"./network"
)
const (
TITLE_OPTION = "[TITLE-MESSAGE]"
SERVER_ADDR = ":8080"
)
func main() {
network.Listen(SERVER_ADDR, handleFunc)
for i := 0; i < 3; i++ {
pack := network.Send(SERVER_ADDR, &network.Package{
Option: TITLE_OPTION,
Data: "hello, world!",
})
fmt.Println(network.Serialize(pack))
}
}
func handleFunc(conn net.Conn, pack *network.Package) {
network.HandleAction(TITLE_OPTION, conn, pack, handleGet)
}
func handleGet(pack *network.Package) (set string) {
return strings.ToUpper(pack.Data)
}

View File

@ -9,7 +9,11 @@ type Listener net.Listener
type Conn net.Conn
func Listen(address string, handle func(Conn, *Package)) Listener {
listener, err := net.Listen("tcp", address)
splited := strings.Split(address, ":")
if len(splited) != 2 {
return nil
}
listener, err := net.Listen("tcp", "0.0.0.0:" + splited[1])
if err != nil {
return nil
}

116
node.go
View File

@ -5,6 +5,7 @@ import (
"fmt"
"strings"
"io/ioutil"
"encoding/json"
nt "./network"
bc "./blockchain"
)
@ -15,61 +16,104 @@ func init() {
os.Exit(1)
}
var (
addrExist = false
userExist = false
chainExist = false
serveStr = ""
addrStr = ""
userNewStr = ""
userLoadStr = ""
chainNewStr = ""
chainLoadStr = ""
)
var (
serveExist = false
addrExist = false
userNewExist = false
userLoadExist = false
chainNewExist = false
chainLoadExist = false
)
for i := 1; i < len(os.Args); i++ {
arg := os.Args[i]
switch {
case strings.HasPrefix(arg, "-address:"):
Address = strings.Replace(arg, "-address:", "", 1)
case strings.HasPrefix(arg, "-serve:"):
serveStr = strings.Replace(arg, "-serve:", "", 1)
serveExist = true
case strings.HasPrefix(arg, "-loadaddr:"):
addrStr = strings.Replace(arg, "-loadaddr:", "", 1)
addrExist = true
case strings.HasPrefix(arg, "-newuser:"):
arg = strings.Replace(arg, "-newuser:", "", 1)
User = userNew(arg)
if User == nil {
fmt.Println("failed: generate user\n")
os.Exit(1)
}
userExist = true
userNewStr = strings.Replace(arg, "-newuser:", "", 1)
userNewExist = true
case strings.HasPrefix(arg, "-loaduser:"):
arg = strings.Replace(arg, "-loaduser:", "", 1)
User = userLoad(arg)
if User == nil {
fmt.Println("failed: load user\n")
os.Exit(1)
}
userExist = true
userLoadStr = strings.Replace(arg, "-loaduser:", "", 1)
userLoadExist = true
case strings.HasPrefix(arg, "-newchain:"):
arg = strings.Replace(arg, "-newchain:", "", 1)
Chain = chainNew(arg)
if Chain == nil {
fmt.Println("failed: genesis block\n")
os.Exit(1)
}
chainExist = true
chainNewStr = strings.Replace(arg, "-newchain:", "", 1)
chainNewExist = true
case strings.HasPrefix(arg, "-loadchain:"):
arg = strings.Replace(arg, "-loadchain:", "", 1)
Chain = chainLoad(arg)
if Chain == nil {
fmt.Println("failed: load chain\n")
os.Exit(1)
}
chainExist = true
chainLoadStr = strings.Replace(arg, "-loadchain:", "", 1)
chainLoadExist = true
}
}
if !userExist || !chainExist || !addrExist {
fmt.Println("failed: !userExist || !chainExist || !addrExist\n")
if !(userNewExist || userLoadExist) || !(chainNewExist || chainLoadExist) || !serveExist || !addrExist {
fmt.Println("failed: !(userNewExist || userLoadExist) || !(chainNewExist || chainLoadExist) || !serveExist || !addrExist\n")
os.Exit(1)
}
Serve = serveStr
var addresses []string
err := json.Unmarshal([]byte(readFile(addrStr)), &addresses)
if err != nil {
fmt.Println("failed: load addresses\n")
os.Exit(1)
}
var mapaddr = make(map[string]bool)
for _, addr := range addresses {
if addr == Serve {
continue
}
if _, ok := mapaddr[addr]; ok {
continue
}
mapaddr[addr] = true
Addresses = append(Addresses, addr)
}
if userNewExist {
User = userNew(userNewStr)
}
if userLoadExist {
User = userLoad(userLoadStr)
}
if User == nil {
fmt.Println("failed: load user\n")
os.Exit(1)
}
if chainNewExist {
Filename = chainNewStr
Chain = chainNew(chainNewStr)
}
if chainLoadExist {
Filename = chainLoadStr
Chain = chainLoad(chainLoadStr)
}
if Chain == nil {
fmt.Println("failed: load chain\n")
os.Exit(1)
}
Block = bc.NewBlock(User.Address(), Chain.LastHash())
// работа с адресами
}
func main() {
nt.Listen(Address, handleServer)
nt.Listen(Serve, handleServer)
for {
fmt.Scanln()
Chain.PrintChain()
}
}

260
serve.go
View File

@ -1,77 +1,231 @@
package main
import (
"fmt"
"strconv"
bc "./blockchain"
nt "./network"
)
var (
Address string
Chain *bc.BlockChain
Block *bc.Block
User *bc.User
)
const (
OPT_BLOCKCHAIN = "[GET-BLOCKCHAIN]"
OPT_LASTHASH = "[GET-LASTHASH]"
OPT_BALANCE = "[GET-BALANCE]"
OPT_TRANSACTION = "[ADD-TRANSACTION]"
"io"
"os"
"fmt"
"time"
"bytes"
"strings"
"strconv"
"encoding/hex"
bc "./blockchain"
nt "./network"
)
func handleServer(conn nt.Conn, pack *nt.Package) {
nt.Handle(OPT_BLOCKCHAIN, conn, pack, getBlockChain)
nt.Handle(OPT_LASTHASH, conn, pack, getLastHash)
nt.Handle(OPT_BALANCE, conn, pack, getBalance)
nt.Handle(OPT_TRANSACTION, conn, pack, addTransaction)
nt.Handle(GET_SIZE, conn, pack, getSize)
nt.Handle(ADD_BLOCK, conn, pack, addBlock)
nt.Handle(GET_CHAIN, conn, pack, getChain)
nt.Handle(GET_LASTHASH, conn, pack, getLastHash)
nt.Handle(GET_BALANCE, conn, pack, getBalance)
nt.Handle(ADD_TRANSACTION, conn, pack, addTransaction)
}
func getBlockChain(pack *nt.Package) string {
if Chain == nil {
return ""
}
num, err := strconv.Atoi(pack.Data)
if err != nil {
return ""
}
if uint64(num) < Chain.Index {
return getBlock(Chain, num)
}
return ""
func getSize(pack *nt.Package) string {
return fmt.Sprintf("%d", Chain.Size())
}
func addBlock(pack *nt.Package) string {
println(111)
splited := strings.Split(pack.Data, SEPARATOR)
if len(splited) != 3 {
println(222)
return "fail"
}
block := bc.DeserializeBlock(splited[2])
if !Chain.BlockIsValid(block) {
currSize := Chain.Size()
num, err := strconv.Atoi(splited[1])
if err != nil {
println(333)
return "fail"
}
if currSize < uint64(num) {
return compareChains(splited[0], uint64(num))
}
println(444)
return "fail"
}
Chain.AddBlock(block)
Block = bc.NewBlock(User.Address(), Chain.LastHash())
println(555)
return "ok"
}
func compareChains(address string, num uint64) string {
filename := "temp_" + hex.EncodeToString(bc.GenerateRandomBytes(8))
file, err := os.Create(filename)
if err != nil {
println(111666)
return "fail"
}
file.Close()
defer func() {
os.Remove(filename)
}()
res := nt.Send(address, &nt.Package{
Option: GET_CHAIN,
Data: fmt.Sprintf("%d", 0),
})
if res == nil {
println(777)
return "fail"
}
block := bc.DeserializeBlock(res.Data)
if block == nil {
println(888)
return "fail"
}
if bc.NewChain(filename, block.Miner) != nil {
println(999)
return "fail"
}
chain := bc.LoadChain(filename)
defer func() {
chain.DB.Close()
}()
for i := uint64(1); i < num; i++ {
res := nt.Send(address, &nt.Package{
Option: GET_CHAIN,
Data: fmt.Sprintf("%d", i),
})
if res == nil {
println("AAA")
return "fail"
}
block := bc.DeserializeBlock(res.Data)
if block == nil {
println("BBB")
return "fail"
}
if !chain.BlockIsValid(block) {
println("CCC")
return "fail"
}
chain.AddBlock(block)
}
println("DDD")
Chain.DB.Close()
os.Remove(Filename)
copyFile(filename, Filename)
Chain = bc.LoadChain(Filename)
Block = bc.NewBlock(User.Address(), Chain.LastHash())
return "ok"
}
func copyFile(src, dst string) error {
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return err
}
defer out.Close()
_, err = io.Copy(out, in)
if err != nil {
return err
}
return out.Close()
}
func getChain(pack *nt.Package) string {
num, err := strconv.Atoi(pack.Data)
if err != nil {
return ""
}
size := Chain.Size()
if uint64(num) < size {
return getBlock(Chain, num)
}
return ""
}
func getBlock(chain *bc.BlockChain, i int) string {
var block string
var block string
row := chain.DB.QueryRow("SELECT Block FROM BlockChain WHERE Id=$1", i+1)
row.Scan(&block)
return block
}
func getLastHash(pack *nt.Package) string {
if Chain == nil {
return ""
}
return bc.Base64Encode(Chain.LastHash())
return bc.Base64Encode(Chain.LastHash())
}
func getBalance(pack *nt.Package) string {
if Chain == nil {
return "-1"
}
return fmt.Sprintf("%d", Chain.Balance(pack.Data))
return fmt.Sprintf("%d", Chain.Balance(pack.Data))
}
func addTransaction(pack *nt.Package) string {
var tx = bc.DeserializeTX(pack.Data)
if tx == nil || len(Block.Transactions) == bc.TXS_LIMIT {
return "fail"
}
Block.AddTransaction(Chain, tx)
if len(Block.Transactions) == bc.TXS_LIMIT {
Chain.PushBlock(User, Block)
Block = bc.NewBlock(User.Address(), Chain.LastHash())
}
return "ok"
var tx = bc.DeserializeTX(pack.Data)
// println(111)
if tx == nil || len(Block.Transactions) == bc.TXS_LIMIT {
// println(222)
return "fail"
}
if Block.AddTransaction(Chain, tx) != nil {
// println(333)
return "fail"
}
lastBlock := getLastBlock()
if lastBlock == nil {
return "fail"
}
btime, err := time.Parse(time.RFC3339, lastBlock.TimeStamp)
if err != nil {
return "fail"
}
mod := time.Now().Sub(btime)
diff := mod < bc.TIME_SESSION
if len(Block.Transactions) == bc.TXS_LIMIT || (!diff && len(Block.Transactions) != 0) {
go func() {
if diff {
time.Sleep(bc.TIME_SESSION - mod)
}
block := *Block
res := Chain.AcceptBlock(User, &block)
// println(666)
if res != nil && bytes.Equal(block.PrevHash, Block.PrevHash) {
// println(555)
Chain.AddBlock(&block)
pushBlockToNet(&block)
}
Block = bc.NewBlock(User.Address(), Chain.LastHash())
}()
// println(444)
}
return "ok"
}
func getLastBlock() *bc.Block {
var sblock string
row := Chain.DB.QueryRow("SELECT Block FROM BlockChain ORDER BY Id DESC")
row.Scan(&sblock)
return bc.DeserializeBlock(sblock)
}
func pushBlockToNet(block *bc.Block) {
var sblock = bc.SerializeBlock(block)
for _, addr := range Addresses {
nt.Send(addr, &nt.Package{
Option: ADD_BLOCK,
Data: Serve + SEPARATOR + fmt.Sprintf("%d", Chain.Size()) + SEPARATOR + sblock,
})
}
}

27
values.go Normal file
View File

@ -0,0 +1,27 @@
package main
import (
bc "./blockchain"
)
var (
Filename string
Addresses []string
Serve string
Chain *bc.BlockChain
Block *bc.Block
User *bc.User
)
const (
SEPARATOR = "_SEPARATOR_"
)
const (
GET_SIZE = "[GET_SIZE]"
ADD_BLOCK = "[ADD_BLOCK]"
GET_CHAIN = "[GET_CHAIN]"
GET_LASTHASH = "[GET_LASTHASH]"
GET_BALANCE = "[GET_BALANCE]"
ADD_TRANSACTION = "[ADD_TRANSACTION]"
)