2
1
mirror of https://github.com/gitchain/gitchain.git synced 2020-06-03 16:49:55 +00:00
gitchain/main.go
2014-05-26 13:15:20 +08:00

269 lines
9.4 KiB
Go

package main
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
"os"
"github.com/alecthomas/kingpin"
"github.com/gitchain/gitchain/server"
"github.com/gitchain/gitchain/server/api"
"github.com/gitchain/gitchain/server/config"
"github.com/gitchain/gitchain/server/context"
httpserver "github.com/gitchain/gitchain/server/http"
netserver "github.com/gitchain/gitchain/server/net"
"github.com/gorilla/rpc/json"
)
func jsonrpc(cfg *config.T, method string, req, res interface{}) error {
buf, err := json.EncodeClientRequest(method, req)
if err != nil {
return err
}
resp, err := http.Post(fmt.Sprintf("http://localhost:%d/rpc", cfg.API.HttpPort), "application/json", bytes.NewBuffer(buf))
if err != nil {
return err
}
defer resp.Body.Close()
json.DecodeClientResponse(resp.Body, res)
return nil
}
func main() {
var configFile, dataPath, assets, netHostname string
var httpPort, netPort int
var alias, repo, random, hash, node string
app := kingpin.New("gitchain", "Gitchain daemon and command line interface")
app.Flag("config", "configuration file").Short('c').ExistingFileVar(&configFile)
app.Flag("data-path", "path to the data directory").Short('d').StringVar(&dataPath)
app.Flag("development-mode-assets", "path to the assets (ui) directory, only for developmenty").ExistingDirVar(&assets)
app.Flag("net-hostname", "Gitchain network hostname").StringVar(&netHostname)
app.Flag("http-port", "HTTTP port to connect to or listen on").IntVar(&httpPort)
app.Flag("net-port", "Network port to listen").IntVar(&netPort)
keypairGenerate := app.Command("keypair-generate", "Generates a new keypair")
keypairGenerate.Arg("alias", "Keypair name to save it under").Required().StringVar(&alias)
keypairPrimary := app.Command("keypair-primary", "Sets or gets primary keypair")
keypairPrimary.Arg("alias", "Keypair name to save it under").StringVar(&alias)
app.Command("keypair-list", "Lists all keypairs")
nameReservation := app.Command("name-reservation", "Submits a Name Reservation Transaction")
nameReservation.Arg("alias", "Keypair name to save it under").Required().StringVar(&alias)
nameReservation.Arg("name", "Repository name to reserve").Required().StringVar(&repo)
nameAllocation := app.Command("name-allocation", "Submits a Name Allocation Transaction")
nameAllocation.Arg("alias", "Keypair name to save it under").Required().StringVar(&alias)
nameAllocation.Arg("name", "Repository name to allocate").Required().StringVar(&repo)
nameAllocation.Arg("random", "Random number returned by the name-reservation command").Required().StringVar(&random)
app.Command("repo-list", "Lists all repositories")
block := app.Command("block", "Renders a block")
block.Arg("block", "Block hash").Required().StringVar(&hash)
app.Command("block-last", "Returns last block hash")
transactions := app.Command("transactions", "Returns a list of transactions in a block")
transactions.Arg("block", "Block hash").Required().StringVar(&hash)
transaction := app.Command("transaction", "Renders a transaction")
transaction.Arg("txn", "Transaction hash").Required().StringVar(&hash)
app.Command("info", "Returns gitchain node information")
join := app.Command("node-join", "Connect to another node")
join.Arg("node", "Node address <host:port>").Required().StringVar(&node)
command := kingpin.MustParse(app.Parse(os.Args[1:]))
var cfg *config.T
var err error
cfg = config.Default()
cfg.General.DataPath = dataPath
if httpPort != 0 {
cfg.API.HttpPort = httpPort
}
cfg.API.DevelopmentModeAssets = assets
cfg.Network.Hostname = netHostname
if netPort != 0 {
cfg.Network.Port = netPort
}
if len(configFile) > 0 {
err = config.ReadFile(configFile, cfg)
if err != nil {
log.Printf("Error read config file %s: %v", configFile, err) // don't use log15 here
os.Exit(1)
}
}
switch command {
case "keypair-generate":
var resp api.GeneratePrivateKeyReply
err := jsonrpc(cfg, "KeyService.GeneratePrivateKey", &api.GeneratePrivateKeyArgs{Alias: alias}, &resp)
if err != nil {
fmt.Printf("Can't generate private key because of %v\n", err)
os.Exit(1)
}
if resp.Success {
fmt.Printf("Private key has been successfully generated with an alias of %s, the public address is %s\n", alias, resp.PublicKey)
} else {
fmt.Printf("Server can't generate the private key\n")
os.Exit(1)
}
case "keypair-primary":
if alias != "" {
var resp api.SetMainKeyReply
err := jsonrpc(cfg, "KeyService.SetMainKey", &api.SetMainKeyArgs{Alias: alias}, &resp)
if err != nil {
fmt.Printf("Can't set main private key to %s because of %v\n", alias, err)
os.Exit(1)
}
if !resp.Success {
fmt.Printf("Can't set main private key to %s (doesn't exist?)\n", alias)
os.Exit(1)
}
fmt.Printf("Successfully set main private key to %s\n", alias)
} else {
var mainKeyResp api.GetMainKeyReply
err = jsonrpc(cfg, "KeyService.GetMainKey", &api.GetMainKeyArgs{}, &mainKeyResp)
if err != nil {
fmt.Printf("Can't discover main private key because of %v\n", err)
os.Exit(1)
}
fmt.Println(mainKeyResp.Alias)
}
case "keypair-list":
var resp api.ListPrivateKeysReply
err := jsonrpc(cfg, "KeyService.ListPrivateKeys", &api.ListPrivateKeysArgs{}, &resp)
if err != nil {
fmt.Printf("Can't list private keys because of %v\n", err)
os.Exit(1)
}
var mainKeyResp api.GetMainKeyReply
err = jsonrpc(cfg, "KeyService.GetMainKey", &api.GetMainKeyArgs{}, &mainKeyResp)
if err != nil {
fmt.Printf("Can't discover main private key because of %v\n", err)
os.Exit(1)
}
for i := range resp.Aliases {
fmt.Printf("%s %s\n", func() string {
if resp.Aliases[i] == mainKeyResp.Alias {
return "*"
} else {
return " "
}
}(), resp.Aliases[i])
}
case "name-reservation":
var resp api.NameReservationReply
err := jsonrpc(cfg, "NameService.NameReservation", &api.NameReservationArgs{Alias: alias, Name: repo}, &resp)
if err != nil {
fmt.Printf("Can't make a name reservation because of %v\n", err)
os.Exit(1)
}
fmt.Printf("Name reservation for %s has been submitted (%s)\nRecord the above transaction hash and following random number for use during allocation: %s\n", repo, resp.Id, resp.Random)
case "name-allocation":
var resp api.NameAllocationReply
err := jsonrpc(cfg, "NameService.NameAllocation", &api.NameAllocationArgs{Alias: alias, Name: repo, Random: random}, &resp)
if err != nil {
fmt.Printf("Can't make a name allocation because of %v\n", err)
os.Exit(1)
}
fmt.Printf("Name allocation for %s has been submitted (%s)\n", repo, resp.Id)
case "repo-list":
var resp api.ListRepositoriesReply
err := jsonrpc(cfg, "RepositoryService.ListRepositories", &api.ListRepositoriesArgs{}, &resp)
if err != nil {
fmt.Printf("Can't list repositories because of %v\n", err)
os.Exit(1)
}
for i := range resp.Repositories {
fmt.Printf("%s %s %s\n", resp.Repositories[i].Name, resp.Repositories[i].Status, resp.Repositories[i].NameAllocationTx)
}
case "block-last":
var resp api.GetLastBlockReply
err := jsonrpc(cfg, "BlockService.GetLastBlock", &api.GetLastBlockArgs{}, &resp)
if err != nil {
fmt.Printf("Can't get a block because of %v\n", err)
os.Exit(1)
}
fmt.Printf("%s\n", resp.Hash)
case "block":
var resp api.GetBlockReply
err := jsonrpc(cfg, "BlockService.GetBlock", &api.GetBlockArgs{Hash: hash}, &resp)
if err != nil {
fmt.Printf("Can't get a block because of %v\n", err)
os.Exit(1)
}
fmt.Printf("Previous block hash: %v\nNext block hash: %v\nMerkle root hash: %v\nTimestamp: %v\nBits: %#x\nNonce: %v\nTransactions: %d\n",
resp.PreviousBlockHash, resp.NextBlockHash, resp.MerkleRootHash,
time.Unix(resp.Timestamp, 0).String(), resp.Bits, resp.Nonce, resp.NumTransactions)
case "transactions":
var resp api.BlockTransactionsReply
err := jsonrpc(cfg, "BlockService.BlockTransactions", &api.BlockTransactionsArgs{Hash: hash}, &resp)
if err != nil {
fmt.Printf("Can't get a list of block transactions because of %v\n", err)
os.Exit(1)
}
for i := range resp.Transactions {
fmt.Println(resp.Transactions[i])
}
case "transaction":
var resp api.GetTransactionReply
err := jsonrpc(cfg, "TransactionService.GetTransaction", &api.GetTransactionArgs{Hash: hash}, &resp)
if err != nil {
fmt.Printf("Can't get a transaction because of %v\n", err)
os.Exit(1)
}
fmt.Printf("Previous transaction hash: %v\nPublic key: %v\nNext public key: %v\nValid: %v\n%+v\n",
resp.PreviousTransactionHash, resp.PublicKey, resp.NextPublicKey, resp.Valid,
resp.Content)
case "info":
resp, err := http.Get(fmt.Sprintf("http://localhost:%d/info", cfg.API.HttpPort))
if err != nil {
fmt.Printf("Can't retrieve info because of %v\n", err)
os.Exit(1)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("Can't retrieve info because of %v\n", err)
os.Exit(1)
}
fmt.Println(string(body))
case "join":
var resp api.JoinReply
err := jsonrpc(cfg, "NetService.Join", &api.JoinArgs{Host: node}, &resp)
if err != nil {
fmt.Printf("Can't join because of %v\n", err)
os.Exit(1)
}
default:
srv := &context.T{Config: cfg}
err := srv.Init()
if err != nil {
log.Printf("Error during server initialization: %v", err) // don't use log15 here
os.Exit(1)
}
go netserver.Server(srv)
go server.NameRegistrar(srv)
go server.RepositoryServer(srv)
go server.MiningFactory(srv)
go server.TransactionListener(srv)
httpserver.Server(srv)
}
}