You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

182 lines
5.2 KiB

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