diff --git a/.gitignore b/.gitignore index f0df5ee..ac4fcf8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ node1.key node2.key chain1.db chain2.db +todo.txt diff --git a/blockchain/block.go b/blockchain/block.go index e211b5f..c7499a4 100644 --- a/blockchain/block.go +++ b/blockchain/block.go @@ -58,8 +58,8 @@ func (block *Block) sign(priv *rsa.PrivateKey) []byte { return Sign(priv, block.CurrHash) } -func (block *Block) proof() uint64 { - return ProofOfWork(block.CurrHash, block.Difficulty) +func (block *Block) proof(ch chan bool) uint64 { + return ProofOfWork(block.CurrHash, block.Difficulty, ch) } func (block *Block) hashIsValid() bool { diff --git a/blockchain/chain.go b/blockchain/chain.go index 0691bb4..d71ec7c 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -205,7 +205,7 @@ func (chain *BlockChain) LastHash() []byte { return Base64Decode(hash) } -func (chain *BlockChain) AcceptBlock(user *User, block *Block) *Block { +func (chain *BlockChain) AcceptBlock(user *User, block *Block, ch chan bool) *Block { if !chain.transactionsIsValid(block) { return nil } @@ -218,7 +218,7 @@ func (chain *BlockChain) AcceptBlock(user *User, block *Block) *Block { block.TimeStamp = time.Now().Format(time.RFC3339) block.CurrHash = block.hash() block.Signature = block.sign(user.Private()) - block.Nonce = block.proof() + block.Nonce = block.proof(ch) return block } @@ -237,6 +237,11 @@ func (chain *BlockChain) timeIsValid(block *Block, index uint64) bool { return false } + diff := time.Now().Sub(btime) + if diff < 0 { + return false + } + var sblock string row := chain.DB.QueryRow("SELECT Block FROM BlockChain WHERE Hash=$1", Base64Encode(block.PrevHash)) row.Scan(&sblock) diff --git a/blockchain/crypto.go b/blockchain/crypto.go index 8c89bad..5270ebb 100644 --- a/blockchain/crypto.go +++ b/blockchain/crypto.go @@ -55,7 +55,7 @@ func Verify(pub *rsa.PublicKey, data, sign []byte) error { } // POW for check hash package by Nonce. -func ProofOfWork(blockHash []byte, difficulty uint8) uint64 { +func ProofOfWork(blockHash []byte, difficulty uint8, ch chan bool) uint64 { var ( Target = big.NewInt(1) intHash = big.NewInt(1) @@ -64,24 +64,32 @@ func ProofOfWork(blockHash []byte, difficulty uint8) uint64 { ) Target.Lsh(Target, 256-uint(difficulty)) for nonce < math.MaxUint64 { - hash = HashSum(bytes.Join( - [][]byte{ - blockHash, - ToBytes(nonce), - }, - []byte{}, - )) - if DEBUG { - fmt.Printf("\rMining: %s", Base64Encode(hash)) - } - intHash.SetBytes(hash) - if intHash.Cmp(Target) == -1 { + select { + case <- ch: if DEBUG { fmt.Println() } - break + return nonce + default: + hash = HashSum(bytes.Join( + [][]byte{ + blockHash, + ToBytes(nonce), + }, + []byte{}, + )) + if DEBUG { + fmt.Printf("\rMining: %s", Base64Encode(hash)) + } + intHash.SetBytes(hash) + if intHash.Cmp(Target) == -1 { + if DEBUG { + fmt.Println() + } + return nonce + } + nonce++ } - nonce++ } return nonce } diff --git a/client.go b/client.go index cde2e5a..3a6f0d2 100644 --- a/client.go +++ b/client.go @@ -6,7 +6,6 @@ import ( "bufio" "strconv" "strings" - "io/ioutil" "encoding/json" nt "./network" bc "./blockchain" @@ -160,18 +159,17 @@ func chainBalance(splited []string) { fmt.Println("fail: len(splited) != 2\n") return } - res := nt.Send(Addresses[0], &nt.Package{ - Option: GET_BALANCE, - Data: splited[1], - }) - fmt.Println("Balance:", res.Data, "coins\n") + for _, addr := range Addresses { + res := nt.Send(addr, &nt.Package{ + Option: GET_BALANCE, + Data: splited[1], + }) + fmt.Printf("Balance (%s): %s coins\n", addr, res.Data) + } + fmt.Println() } func userBalance() { - if User == nil { - fmt.Println("fail: user == nil\n") - return - } for _, addr := range Addresses { res := nt.Send(addr, &nt.Package{ Option: GET_BALANCE, @@ -183,57 +181,13 @@ func userBalance() { } func userAddress() { - if User == nil { - fmt.Println("fail: user == nil\n") - return - } fmt.Println("Address:", User.Address(), "\n") } func userPurse() { - if User == nil { - fmt.Println("fail: user == nil\n") - return - } fmt.Println("Purse:", User.Purse(), "\n") } -func userNew(filename string) *bc.User { - user := bc.NewUser() - if user == nil { - return nil - } - err := writeFile(filename, user.Purse()) - if err != nil { - return nil - } - return user -} - -func userLoad(filename string) *bc.User { - priv := readFile(filename) - if priv == "" { - return nil - } - user := bc.LoadUser(priv) - if user == nil { - return nil - } - return user -} - -func writeFile(filename string, data string) error { - return ioutil.WriteFile(filename, []byte(data), 0644) -} - -func readFile(filename string) string { - data, err := ioutil.ReadFile(filename) - if err != nil { - return "" - } - return string(data) -} - func inputString(begin string) string { fmt.Print(begin) msg, _ := bufio.NewReader(os.Stdin).ReadString('\n') diff --git a/node.go b/node.go index 4659fce..a2a58d4 100644 --- a/node.go +++ b/node.go @@ -4,7 +4,6 @@ import ( "os" "fmt" "strings" - "io/ioutil" "encoding/json" nt "./network" bc "./blockchain" @@ -106,7 +105,6 @@ func init() { } Block = bc.NewBlock(User.Address(), Chain.LastHash()) - // работа с адресами } func main() { @@ -135,39 +133,3 @@ func chainLoad(filename string) *bc.BlockChain { } return chain } - -func userNew(filename string) *bc.User { - user := bc.NewUser() - if user == nil { - return nil - } - err := writeFile(filename, user.Purse()) - if err != nil { - return nil - } - return user -} - -func userLoad(filename string) *bc.User { - priv := readFile(filename) - if priv == "" { - return nil - } - user := bc.LoadUser(priv) - if user == nil { - return nil - } - return user -} - -func writeFile(filename string, data string) error { - return ioutil.WriteFile(filename, []byte(data), 0644) -} - -func readFile(filename string) string { - data, err := ioutil.ReadFile(filename) - if err != nil { - return "" - } - return string(data) -} diff --git a/serve.go b/serve.go index 8567166..c3b57c0 100644 --- a/serve.go +++ b/serve.go @@ -15,6 +15,11 @@ import ( nt "./network" ) +var ( + IsMining = false + BreakMining = make(chan bool) +) + func handleServer(conn nt.Conn, pack *nt.Package) { nt.Handle(GET_SIZE, conn, pack, getSize) nt.Handle(ADD_BLOCK, conn, pack, addBlock) @@ -53,6 +58,11 @@ func addBlock(pack *nt.Package) string { Chain.AddBlock(block) Block = bc.NewBlock(User.Address(), Chain.LastHash()) + if IsMining { + BreakMining <- true + IsMining = false + } + // println(555) return "ok" } @@ -132,6 +142,11 @@ func compareChains(address string, num uint64) string { Chain = bc.LoadChain(Filename) Block = bc.NewBlock(User.Address(), Chain.LastHash()) + if IsMining { + BreakMining <- true + IsMining = false + } + return "ok" } @@ -211,8 +226,10 @@ func addTransaction(pack *nt.Package) string { if diff { time.Sleep(bc.TIME_SESSION - mod) } - res := Chain.AcceptBlock(User, &block) + IsMining = true + res := Chain.AcceptBlock(User, &block, BreakMining) // println(666) + IsMining = false if res != nil && bytes.Equal(block.PrevHash, Block.PrevHash) { // println(555) Chain.AddBlock(&block) diff --git a/values.go b/values.go index 1b5be8a..db92d8c 100644 --- a/values.go +++ b/values.go @@ -1,6 +1,7 @@ package main import ( + "io/ioutil" bc "./blockchain" ) @@ -25,3 +26,39 @@ const ( GET_BALANCE = "[GET_BALANCE]" ADD_TRANSACTION = "[ADD_TRANSACTION]" ) + +func userNew(filename string) *bc.User { + user := bc.NewUser() + if user == nil { + return nil + } + err := writeFile(filename, user.Purse()) + if err != nil { + return nil + } + return user +} + +func userLoad(filename string) *bc.User { + priv := readFile(filename) + if priv == "" { + return nil + } + user := bc.LoadUser(priv) + if user == nil { + return nil + } + return user +} + +func writeFile(filename string, data string) error { + return ioutil.WriteFile(filename, []byte(data), 0644) +} + +func readFile(filename string) string { + data, err := ioutil.ReadFile(filename) + if err != nil { + return "" + } + return string(data) +}