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 = ðConfig
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}