JeffDeCola/jeffCoin

View on GitHub
jeffCoin.go

Summary

Maintainability
A
3 hrs
Test Coverage
// jeffcoin.go

package main

import (
    "flag"
    "fmt"
    "os"
    "time"

    log "github.com/sirupsen/logrus"

    blockchain "github.com/JeffDeCola/jeffCoin/blockchain"
    routingnode "github.com/JeffDeCola/jeffCoin/routingnode"
    testblockchain "github.com/JeffDeCola/jeffCoin/testblockchain"
    wallet "github.com/JeffDeCola/jeffCoin/wallet"
    webserver "github.com/JeffDeCola/jeffCoin/webserver"
)

const (
    toolVersion = "1.3.5"
)

var genesisPtr, testblockchainPtr, gcePtr, walletPtr *bool
var nodeNamePtr, nodeIPPtr, nodeHTTPPortPtr, nodeTCPPortPtr *string
var networkIPPtr, networkTCPPortPtr *string
var nodePasswordPtr *string

func checkErr(err error) {
    if err != nil {
        fmt.Printf("Error is %+v\n", err)
        log.Fatal("ERROR:", err)
    }
}

func genesisNode(jeffCoinAddress string) {

    genesisBlockDataString := `
    {
        "blockID": 0,
        "timestamp": "",
        "transactions": [
            {
                "txID": 0,
                "inputs": [
                    {
                        "refTxID": -1,
                        "inPubKey": "",
                        "signature": "Hello World, Welcome to the first transaction and block of jeffCoin"
                    }
                ],
                "outputs": [
                    {
                        "outPubKey": "` + jeffCoinAddress + `",
                        "value": 100000000
                    }
                ]
            }
        ],
        "hash": "",
        "prevhash": "",
        "difficulty": 8,
        "nonce": ""
    }`

    // GENESIS blockchain
    s := "GENESIS blockchain"
    log.Info("MAIN:                        " + s)
    blockchain.GenesisBlockchain(genesisBlockDataString)

    // GENESIS nodeList
    s = "GENESIS nodeList"
    log.Info("MAIN:                        " + s)
    routingnode.GenesisNodeList()

}

func newNode() {

    // REQUEST nodeList FROM THE NETWORK
    s := "REQUEST nodeList FROM THE NETWORK"
    log.Info("MAIN:                        " + s)
    err := routingnode.RequestNodeList(*networkIPPtr, *networkTCPPortPtr)
    checkErr(err)

    // BROADCAST thisNode TO THE NETWORK
    s = "BROADCAST thisNode TO THE NETWORK"
    log.Info("MAIN:                        " + s)
    err = routingnode.BroadcastThisNode()
    checkErr(err)

    // APPEND thisNode to nodeList
    s = "APPEND thisNode to nodeList"
    log.Info("MAIN:                        " + s)
    routingnode.AppendThisNode()

    // REQUEST blockchain FROM THE NETWORK
    s = "REQUEST blockchain FROM THE NETWORK"
    log.Info("MAIN:                        " + s)
    err = blockchain.RequestBlockchain(*networkIPPtr, *networkTCPPortPtr)
    checkErr(err)

}

// masterFlowControl - Controls the mining of blocks and addint to the chain
func masterFlowControl(genesis bool) {

    // START IT UP
    if genesis {

    }

}

func init() {

    // SET FORMAT
    log.SetFormatter(&log.TextFormatter{})
    // log.SetFormatter(&log.JSONFormatter{})

    // SET OUTPUT (DEFAULT stderr)
    log.SetOutput(os.Stdout)

    // GCE
    gcePtr = flag.Bool("gce", false, "Is this Node on GCE")
    // CREATE FIRST NODE (GENISIS)
    genesisPtr = flag.Bool("genesis", false, "Create your first Node")
    // LOG LEVEL
    logLevelPtr := flag.String("loglevel", "info", "LogLevel (info, debug or trace)")
    // NETWORK NODE IP
    networkIPPtr = flag.String("networkip", "127.0.0.1", "Network IP")
    // NETWORK NODE TCP PORT
    networkTCPPortPtr = flag.String("networktcpport", "3000", "Network TCP Port")
    // YOUR NODE WEB PORT
    nodeHTTPPortPtr = flag.String("nodehttpport", "2001", "Node Web Port")
    // YOUR NODE IP
    nodeIPPtr = flag.String("nodeip", "127.0.0.1", "Node IP")
    // NODE NAME
    nodeNamePtr = flag.String("nodename", "Jeff", "Node Name")
    // PASSWORD
    nodePasswordPtr = flag.String("nodepassword", "yourpassword", "Set/Reset your Password")
    // YOUR NODE TCP PORT
    nodeTCPPortPtr = flag.String("nodetcpport", "3001", "Node TCP Port")
    // TEST FLAG
    testblockchainPtr = flag.Bool("testblockchain", false, "Loads the blockchain with test data")
    // VERSION FLAG
    versionPtr := flag.Bool("v", false, "prints current version")
    // VERSION FLAG
    walletPtr = flag.Bool("wallet", false, "Only the wallet and webserver (GUI/API)")

    // Parse the flags
    flag.Parse()

    // SET LOG LEVEL
    if *logLevelPtr == "trace" {
        log.SetLevel(log.TraceLevel)
    } else if *logLevelPtr == "debug" {
        log.SetLevel(log.DebugLevel)
    } else if *logLevelPtr == "info" {
        log.SetLevel(log.InfoLevel)
    } else {
        log.Error("Error setting log levels")
        os.Exit(0)
    }

    // CHECK VERSION
    if *versionPtr {
        fmt.Println(toolVersion)
        os.Exit(0)
    }

    // MUST HAVE A PASSWORD
    if *nodePasswordPtr == "yourpassword" {
        log.Error("You must supply a Node Password")
        os.Exit(0)
    }
}

func main() {

    fmt.Printf("\nSTART...\n")
    fmt.Printf("Press return to exit\n\n")

    // DO YOU HAVE A PASSWORD HASH FILE
    if _, err := os.Stat("credentials/" + *nodeNamePtr + "-password-hash.json"); err == nil {
        // Read password hash from a file and put in struct
        // Will also check password hash
        s := "READ existing password hash from a file and put in struct"
        log.Info("MAIN:                        " + s)
        webserver.ReadPasswordFile(*nodeNamePtr, *nodePasswordPtr)
    } else {
        // Write the password hash to a file and put in struct
        s := "Writes the password hash to a file"
        log.Info("MAIN:                        " + s)
        webserver.WritePasswordFile(*nodeNamePtr, *nodePasswordPtr)
    }

    // DO YOU HAVE A WALLET FILE
    if _, err := os.Stat("credentials/" + *nodeNamePtr + "-wallet-encrypted.json"); err == nil {
        // READ existing wallet from a file (Keys and jeffCoin Address) and put in struct
        // Will also decrypt encrypted Private Key in file
        s := "READ existing wallet from a file (Keys and jeffCoin Address) and put in struct"
        log.Info("MAIN:                        " + s)
        wallet.ReadWalletFile(*nodeNamePtr, *nodePasswordPtr)
    } else {
        // GENESIS wallet - Creates the wallet and write to file (Keys and jeffCoin Address)
        // Will also encrypt Private Key for file
        s := "GENESIS wallet - Creates the wallet and write to file (Keys and jeffCoin Address)"
        log.Info("MAIN:                        " + s)
        wallet.GenesisWallet(*nodeNamePtr, *nodePasswordPtr)
    }

    // "DESTROY" PASSWORD
    *nodePasswordPtr = "destroy"
    s := "Node Password destroyed"
    log.Info("MAIN:                        " + s)

    // START WEBSERVER (HTTP SERVER)
    s = "START WEBSERVER (HTTP SERVER)"
    log.Info("MAIN:                        " + s)
    if *gcePtr {
        go webserver.StartHTTPServer("0.0.0.0", *nodeHTTPPortPtr)
    } else {
        go webserver.StartHTTPServer(*nodeIPPtr, *nodeHTTPPortPtr)
    }

    // GIVE IT A SECOND
    time.Sleep(1 * time.Second)

    // START ROUTING NODE (TCP SERVER)
    // Do not start if wallet only
    if !*walletPtr {
        s = "START ROUTING NODE (TCP SERVER)"
        log.Info("MAIN:                        " + s)
        if *gcePtr {
            go routingnode.StartRoutingNode("0.0.0.0", *nodeTCPPortPtr)
        } else {
            go routingnode.StartRoutingNode(*nodeIPPtr, *nodeTCPPortPtr)
        }
    }

    // GIVE IT A SECOND
    time.Sleep(1 * time.Second)

    // LOAD thisNode
    s = "LOAD thisNode"
    log.Info("MAIN:                        " + s)
    myNode := routingnode.NodeStruct{
        NodeName:       *nodeNamePtr,
        NodeIP:         *nodeIPPtr,
        NodeHTTPPort:   *nodeHTTPPortPtr,
        NodeTCPPort:    *nodeTCPPortPtr,
        NetworkIP:      *networkIPPtr,
        NetworkTCPPort: *networkTCPPortPtr,
        TestBlockChain: *testblockchainPtr,
        WalletOnly:     *walletPtr,
        ToolVersion:    toolVersion,
    }
    myNode.LoadThisNode()

    // CREATE GENESIS NODE OR A NEW NODE
    // Do not start if wallet only
    if !*walletPtr {
        if *genesisPtr {
            theWallet := wallet.GetWallet()
            genesisNode(theWallet.PublicKeyHex)
        } else {
            newNode()
        }
    }

    // TESTING - LOAD BLOCKCHAIN WITH TEST DATA
    if *testblockchainPtr {
        testblockchain.LoadTestDatatoBlockchain()
        // SHOW BALANCES
        balance := blockchain.GetAddressBalance(testblockchain.MockFoundersPubKey)
        log.Info("\n\nThe balance for " + testblockchain.MockFoundersPubKey[0:40] + "... (Address) is " + balance + "\n\n")
        balance = blockchain.GetAddressBalance(testblockchain.MockJeffPubKey)
        log.Info("\n\nThe balance for " + testblockchain.MockJeffPubKey[0:40] + "... (Address) is " + balance + "\n\n")
        balance = blockchain.GetAddressBalance(testblockchain.MockMattPubKey)
        log.Info("\n\nThe balance for " + testblockchain.MockMattPubKey[0:40] + "... (Address) is " + balance + "\n\n")
        balance = blockchain.GetAddressBalance(testblockchain.MockJillPubKey)
        log.Info("\n\nThe balance for " + testblockchain.MockJillPubKey[0:40] + "... (Address) is " + balance + "\n\n")
        balance = blockchain.GetAddressBalance(testblockchain.MockCoinVaultPubKey)
        log.Info("\n\nThe balance for " + testblockchain.MockCoinVaultPubKey[0:40] + "... (Address) is " + balance + "\n\n")
    }

    // KICK OFF MASTER CONTROL
    s = "KICK OFF MASTER CONTROL"
    log.Info("MAIN:                        " + s)
    go masterFlowControl(*genesisPtr)

    // PRESS RETURN TO EXIT
    s = "PRESS RETURN TO EXIT"
    log.Info("MAIN:                        " + s)
    fmt.Scanln()
    fmt.Printf("\n...DONE\n")

}