arnaucube
arnaucube/go-dvotePublic Self-hosted repository
go-dvote/chain/chain.go
chain/chain.goRaw
  1package chain
  2
  3import (
  4	"context"
  5	"fmt"
  6	"io/ioutil"
  7	"math/big"
  8	"os"
  9	"time"
 10
 11	"github.com/ethereum/go-ethereum/accounts/keystore"
 12	"github.com/ethereum/go-ethereum/cmd/utils"
 13	"github.com/ethereum/go-ethereum/common"
 14	"github.com/ethereum/go-ethereum/console"
 15	"github.com/ethereum/go-ethereum/core"
 16	"github.com/ethereum/go-ethereum/core/types"
 17	"github.com/ethereum/go-ethereum/eth"
 18	"github.com/ethereum/go-ethereum/ethclient"
 19	"github.com/ethereum/go-ethereum/node"
 20	"github.com/ethereum/go-ethereum/p2p/enode"
 21	//	"github.com/ethereum/go-ethereum/accounts/abi"
 22)
 23
 24type Node interface {
 25	Init() error
 26	Start()
 27	LinkBatch([]byte) error
 28}
 29
 30type EthNodeHandle struct {
 31	n *node.Node
 32	s *eth.Ethereum
 33	c *eth.Config
 34	k *keystore.KeyStore
 35}
 36
 37func Init() (Node, error) {
 38	e := new(EthNodeHandle)
 39	err := e.Init()
 40	return e, err
 41}
 42
 43func (e *EthNodeHandle) Init() error {
 44
 45	nodeConfig := node.DefaultConfig
 46	nodeConfig.IPCPath = "run/eth/ipc"
 47	nodeConfig.DataDir = "run/eth/data"
 48
 49	//might also make sense to use staticnodes instead of bootstrap
 50	var urls = []string{
 51		"enode://e97bbd1b66c91a3e042703ec1a9af9361e7c84d892632cfa995bad96f3fa630b7048c8194e2bbc8984a612db7f5f8ca29be5d807d8abe5db86d5505b62eaa382@51.15.114.224:30303",
 52		"enode://480fbf14bab92f6203140403f5a1d4b4a8af143b4bc2c48d7f09fd3a294d08955611c362064ea01681663e42638440a888c326977e178a35295f5c1ca99dfb0f@51.15.71.154:30303",
 53		"enode://d6165c23b1d4415f845922b6589fcf19c62e07555c867848a890978993230dad039c248975578216b69a9f7a8fbc2b58db4817bd693f464a6aa45af90964b1e2@51.15.102.251:30303",
 54		"enode://3722cb9af22c61294fe6a0a7beb1db176ef456eb4cab1f6551cefb44e253450342de6459bcf576bd97797cf0df9e818db3d048532f3068351ed1bacaa6ec0d20@51.15.89.137:30303",
 55	}
 56	nodeConfig.P2P.BootstrapNodes = make([]*enode.Node, 0, len(urls))
 57	for _, url := range urls {
 58		if url != "" {
 59			node, err := enode.ParseV4(url)
 60			if err != nil {
 61				return err
 62			}
 63			nodeConfig.P2P.BootstrapNodes = append(nodeConfig.P2P.BootstrapNodes, node)
 64		}
 65	}
 66	n, err := node.New(&nodeConfig)
 67	if err != nil {
 68		return err
 69	}
 70
 71	ethConfig := eth.DefaultConfig
 72	ethConfig.NetworkId = 1714
 73	//ethConfig.SyncMode = downloader.LightSync
 74	var genesisJson *os.File
 75	genesisJson, err = os.Open("genesis.json")
 76	genesisBytes, _ := ioutil.ReadAll(genesisJson)
 77	g := new(core.Genesis)
 78	g.UnmarshalJSON(genesisBytes)
 79	ethConfig.Genesis = g
 80
 81	ks := keystore.NewKeyStore("run/eth/keystore", keystore.StandardScryptN, keystore.StandardScryptP)
 82
 83	e.n = n
 84	e.c = &ethConfig
 85	e.k = ks
 86
 87	return nil
 88}
 89
 90func (e *EthNodeHandle) Start() {
 91	utils.RegisterEthService(e.n, e.c)
 92	utils.StartNode(e.n)
 93	if len(e.k.Accounts()) < 1 {
 94		e.createAccount()
 95	} else {
 96		phrase := getPassPhrase("please provide primary account passphrase", false)
 97		e.k.TimedUnlock(e.k.Accounts()[0], phrase, time.Duration(0))
 98	}
 99}
100
101func (e *EthNodeHandle) LinkBatch(data []byte) error {
102	//	contractAddr := "0x3e4FfefF898580eC8132A97A91543c8fdeF1210E"
103	bigWalletAddr := "0x781b6544b1a73c6d779eb23c7369cf8039640793"
104	var gasLimit uint64
105	gasLimit = 8000000
106	return e.sendContractTx(bigWalletAddr, gasLimit, data)
107}
108
109// might be worthwhile to create generic SendTx to call contracttx, deploytx, etc
110
111func (e *EthNodeHandle) sendContractTx(addr string, limit uint64, data []byte) error {
112
113	fmt.Println(e.n)
114	client, err := ethclient.Dial(e.n.IPCEndpoint())
115	fmt.Println("Got IPC Endpoint:" + e.n.IPCEndpoint())
116	deadline := time.Now().Add(1000 * time.Millisecond)
117	ctx, cancel := context.WithDeadline(context.TODO(), deadline)
118	defer cancel()
119	fmt.Println("context created")
120
121	accounts := e.k.Accounts()
122	fmt.Println("Listing accounts")
123	for i, a := range accounts {
124		fmt.Printf("Found account %d %s\n", i, a.Address.String())
125	}
126	acc := accounts[0]
127	sendAddr := acc.Address
128	nonce, _ := client.NonceAt(ctx, sendAddr, nil)
129	if err != nil {
130		fmt.Println("error")
131		return err
132	}
133	//create tx
134	fmt.Println("creating tx")
135	price, _ := client.SuggestGasPrice(ctx)
136	fmt.Println(price)
137	var empty []byte
138	tx := types.NewTransaction(nonce, common.HexToAddress(addr), big.NewInt(1), limit, price, empty)
139	signedTx, err := e.k.SignTx(acc, tx, big.NewInt(int64(e.c.NetworkId)))
140	if err != nil {
141		fmt.Printf("Signing error: %s", err)
142	}
143	//create ctx
144	err = client.SendTransaction(ctx, signedTx)
145	fmt.Println(err)
146	//fix return*/
147	return err
148}
149
150func (e *EthNodeHandle) createAccount() error {
151	phrase := getPassPhrase("Your new account will be locked with a passphrase. Please give a passphrase. Do not forget it!.", true)
152	acc, err := e.k.NewAccount(phrase)
153
154	if err != nil {
155		utils.Fatalf("Failed to create account: %v", err)
156	}
157	fmt.Printf("Address: {%x}\n", acc.Address)
158	e.k.TimedUnlock(e.k.Accounts()[0], phrase, time.Duration(0))
159
160	return nil
161}
162
163func getPassPhrase(prompt string, confirmation bool) string {
164	// Otherwise prompt the user for the password
165	if prompt != "" {
166		fmt.Println(prompt)
167	}
168	phrase, err := console.Stdin.PromptPassword("Passphrase: ")
169	if err != nil {
170		utils.Fatalf("Failed to read passphrase: %v", err)
171	}
172	if confirmation {
173		confirm, err := console.Stdin.PromptPassword("Repeat passphrase: ")
174		if err != nil {
175			utils.Fatalf("Failed to read passphrase confirmation: %v", err)
176		}
177		if phrase != confirm {
178			utils.Fatalf("Passphrases do not match")
179		}
180	}
181	return phrase
182}