mirror of
https://github.com/number571/blockchain.git
synced 2026-09-12 19:50:00 +05:00
289 lines
5.3 KiB
Go
289 lines
5.3 KiB
Go
package main
|
|
|
|
import (
|
|
bc "./blockchain"
|
|
nt "./network"
|
|
"bufio"
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
func init() {
|
|
if len(os.Args) < 2 {
|
|
panic("failed: len(os.Args) < 2")
|
|
}
|
|
var (
|
|
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, "-loadaddr:"):
|
|
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 !(userNewExist || userLoadExist) || !addrExist {
|
|
panic("failed: !(userNewExist || userLoadExist) || !addrExist")
|
|
}
|
|
err := json.Unmarshal([]byte(readFile(addrStr)), &Addresses)
|
|
if err != nil {
|
|
panic("failed: load addresses")
|
|
}
|
|
if len(Addresses) == 0 {
|
|
panic("failed: len(Addresses) == 0")
|
|
}
|
|
if userNewExist {
|
|
User = userNew(userNewStr)
|
|
}
|
|
if userLoadExist {
|
|
User = userLoad(userLoadStr)
|
|
}
|
|
if User == nil {
|
|
panic("failed: load user")
|
|
}
|
|
}
|
|
|
|
func readFile(filename string) string {
|
|
data, err := ioutil.ReadFile(filename)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
return string(data)
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
var (
|
|
Addresses []string
|
|
User *bc.User
|
|
)
|
|
|
|
func writeFile(filename string, data string) error {
|
|
return ioutil.WriteFile(filename, []byte(data), 0644)
|
|
}
|
|
|
|
func handleClient() {
|
|
var (
|
|
message string
|
|
splited []string
|
|
)
|
|
for {
|
|
message = inputString("> ")
|
|
splited = strings.Split(message, " ")
|
|
switch splited[0] {
|
|
case "/exit":
|
|
os.Exit(0)
|
|
case "/user":
|
|
if len(splited) < 2 {
|
|
fmt.Println("failed: len(user) < 2\n")
|
|
continue
|
|
}
|
|
switch splited[1] {
|
|
case "address":
|
|
userAddress()
|
|
case "purse":
|
|
userPurse()
|
|
case "balance":
|
|
userBalance()
|
|
default:
|
|
fmt.Println("command undefined\n")
|
|
}
|
|
case "/chain":
|
|
if len(splited) < 2 {
|
|
fmt.Println("failed: len(chain) < 2\n")
|
|
continue
|
|
}
|
|
switch splited[1] {
|
|
case "print":
|
|
chainPrint()
|
|
case "tx":
|
|
chainTX(splited[1:])
|
|
case "balance":
|
|
chainBalance(splited[1:])
|
|
case "block":
|
|
chainBlock(splited[1:])
|
|
case "size":
|
|
chainSize()
|
|
default:
|
|
fmt.Println("command undefined\n")
|
|
}
|
|
default:
|
|
fmt.Println("command undefined\n")
|
|
}
|
|
}
|
|
}
|
|
|
|
func inputString(begin string) string {
|
|
fmt.Print(begin)
|
|
msg, _ := bufio.NewReader(os.Stdin).ReadString('\n')
|
|
return strings.Replace(msg, "\n", "", 1)
|
|
}
|
|
|
|
func userAddress() {
|
|
fmt.Println("Address:", User.Address(), "\n")
|
|
}
|
|
|
|
func userPurse() {
|
|
fmt.Println("Purse:", User.Purse(), "\n")
|
|
}
|
|
|
|
func userBalance() {
|
|
printBalance(User.Address())
|
|
}
|
|
|
|
func chainPrint() {
|
|
for i := 0; ; i++ {
|
|
res := nt.Send(Addresses[0], &nt.Package{
|
|
Option: GET_BLOCK,
|
|
Data: fmt.Sprintf("%d", i),
|
|
})
|
|
if res == nil || res.Data == ""{
|
|
break
|
|
}
|
|
fmt.Printf("[%d] => %s\n", i+1, res.Data)
|
|
}
|
|
fmt.Println()
|
|
}
|
|
|
|
func chainTX(splited []string) {
|
|
if len(splited) != 3 {
|
|
fmt.Println("failed: len(splited) != 3\n")
|
|
return
|
|
}
|
|
num, err := strconv.Atoi(splited[2])
|
|
if err != nil {
|
|
fmt.Println("failed: strconv.Atoi(num)\n")
|
|
return
|
|
}
|
|
for _, addr := range Addresses {
|
|
res := nt.Send(addr, &nt.Package{
|
|
Option: GET_LHASH,
|
|
})
|
|
if res == nil {
|
|
continue
|
|
}
|
|
tx := bc.NewTransaction(User, bc.Base64Decode(res.Data), splited[1], uint64(num))
|
|
res = nt.Send(addr, &nt.Package{
|
|
Option: ADD_TRNSX,
|
|
Data: bc.SerializeTX(tx),
|
|
})
|
|
if res == nil {
|
|
continue
|
|
}
|
|
if res.Data == "ok" {
|
|
fmt.Printf("ok: (%s)\n", addr)
|
|
} else {
|
|
fmt.Printf("fail: (%s)\n", addr)
|
|
}
|
|
}
|
|
fmt.Println()
|
|
}
|
|
|
|
func chainBalance(splited []string) {
|
|
if len(splited) != 2 {
|
|
fmt.Println("fail: len(splited) != 2\n")
|
|
return
|
|
}
|
|
printBalance(splited[1])
|
|
}
|
|
|
|
func chainBlock(splited []string) {
|
|
if len(splited) != 2 {
|
|
fmt.Println("failed: len(splited) != 2\n")
|
|
return
|
|
}
|
|
num, err := strconv.Atoi(splited[1])
|
|
if err != nil {
|
|
fmt.Println("failed: strconv.Atoi(num)\n")
|
|
return
|
|
}
|
|
res := nt.Send(Addresses[0], &nt.Package{
|
|
Option: GET_BLOCK,
|
|
Data: fmt.Sprintf("%d", num-1),
|
|
})
|
|
if res == nil || res.Data == "" {
|
|
fmt.Println("failed: getBlock\n")
|
|
return
|
|
}
|
|
fmt.Printf("[%d] => %s\n", num, res.Data)
|
|
}
|
|
|
|
func chainSize() {
|
|
res := nt.Send(Addresses[0], &nt.Package{
|
|
Option: GET_CSIZE,
|
|
})
|
|
if res == nil || res.Data == "" {
|
|
fmt.Println("failed: getSize\n")
|
|
return
|
|
}
|
|
fmt.Printf("Size: %s blocks\n\n", res.Data)
|
|
}
|
|
|
|
func printBalance(useraddr string) {
|
|
for _, addr := range Addresses {
|
|
res := nt.Send(addr, &nt.Package{
|
|
Option: GET_BLNCE,
|
|
Data: useraddr,
|
|
})
|
|
if res == nil {
|
|
continue
|
|
}
|
|
fmt.Printf("Balance (%s): %s coins\n", addr, res.Data)
|
|
}
|
|
fmt.Println()
|
|
}
|
|
|
|
const (
|
|
ADD_BLOCK = iota + 1
|
|
ADD_TRNSX
|
|
GET_BLOCK
|
|
GET_LHASH
|
|
GET_BLNCE
|
|
GET_CSIZE
|
|
)
|
|
|
|
func main() {
|
|
handleClient()
|
|
}
|
|
|