dev_console.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. package main
  2. import (
  3. "bufio"
  4. "bytes"
  5. "encoding/hex"
  6. "errors"
  7. "fmt"
  8. "github.com/ethereum/eth-go"
  9. "github.com/ethereum/eth-go/ethchain"
  10. "github.com/ethereum/eth-go/ethdb"
  11. "github.com/ethereum/eth-go/ethutil"
  12. "github.com/ethereum/eth-go/ethwire"
  13. "github.com/obscuren/mutan"
  14. _ "math/big"
  15. "os"
  16. "strings"
  17. )
  18. type Console struct {
  19. db *ethdb.MemDatabase
  20. trie *ethutil.Trie
  21. ethereum *eth.Ethereum
  22. }
  23. func NewConsole(s *eth.Ethereum) *Console {
  24. db, _ := ethdb.NewMemDatabase()
  25. trie := ethutil.NewTrie(db, "")
  26. return &Console{db: db, trie: trie, ethereum: s}
  27. }
  28. func (i *Console) ValidateInput(action string, argumentLength int) error {
  29. err := false
  30. var expArgCount int
  31. switch {
  32. case action == "update" && argumentLength != 2:
  33. err = true
  34. expArgCount = 2
  35. case action == "get" && argumentLength != 1:
  36. err = true
  37. expArgCount = 1
  38. case action == "dag" && argumentLength != 2:
  39. err = true
  40. expArgCount = 2
  41. case action == "decode" && argumentLength != 1:
  42. err = true
  43. expArgCount = 1
  44. case action == "encode" && argumentLength != 1:
  45. err = true
  46. expArgCount = 1
  47. case action == "gettx" && argumentLength != 1:
  48. err = true
  49. expArgCount = 1
  50. case action == "tx" && argumentLength != 2:
  51. err = true
  52. expArgCount = 2
  53. case action == "getaddr" && argumentLength != 1:
  54. err = true
  55. expArgCount = 1
  56. case action == "contract" && argumentLength != 2:
  57. err = true
  58. expArgCount = 2
  59. case action == "say" && argumentLength != 1:
  60. err = true
  61. expArgCount = 1
  62. case action == "addp" && argumentLength != 1:
  63. err = true
  64. expArgCount = 1
  65. case action == "block" && argumentLength != 1:
  66. err = true
  67. expArgCount = 1
  68. }
  69. if err {
  70. return errors.New(fmt.Sprintf("'%s' requires %d args, got %d", action, expArgCount, argumentLength))
  71. } else {
  72. return nil
  73. }
  74. }
  75. func (i *Console) Editor() string {
  76. var buff bytes.Buffer
  77. for {
  78. reader := bufio.NewReader(os.Stdin)
  79. str, _, err := reader.ReadLine()
  80. if len(str) > 0 {
  81. buff.Write(str)
  82. buff.WriteString("\n")
  83. }
  84. if err != nil && err.Error() == "EOF" {
  85. break
  86. }
  87. }
  88. return buff.String()
  89. }
  90. func (i *Console) PrintRoot() {
  91. root := ethutil.NewValue(i.trie.Root)
  92. if len(root.Bytes()) != 0 {
  93. fmt.Println(hex.EncodeToString(root.Bytes()))
  94. } else {
  95. fmt.Println(i.trie.Root)
  96. }
  97. }
  98. func (i *Console) ParseInput(input string) bool {
  99. scanner := bufio.NewScanner(strings.NewReader(input))
  100. scanner.Split(bufio.ScanWords)
  101. count := 0
  102. var tokens []string
  103. for scanner.Scan() {
  104. count++
  105. tokens = append(tokens, scanner.Text())
  106. }
  107. if err := scanner.Err(); err != nil {
  108. fmt.Fprintln(os.Stderr, "reading input:", err)
  109. }
  110. if len(tokens) == 0 {
  111. return true
  112. }
  113. err := i.ValidateInput(tokens[0], count-1)
  114. if err != nil {
  115. fmt.Println(err)
  116. } else {
  117. switch tokens[0] {
  118. case "update":
  119. i.trie.Update(tokens[1], tokens[2])
  120. i.PrintRoot()
  121. case "get":
  122. fmt.Println(i.trie.Get(tokens[1]))
  123. case "root":
  124. i.PrintRoot()
  125. case "rawroot":
  126. fmt.Println(i.trie.Root)
  127. case "print":
  128. i.db.Print()
  129. case "dag":
  130. fmt.Println(ethchain.DaggerVerify(ethutil.Big(tokens[1]), // hash
  131. ethutil.BigPow(2, 36), // diff
  132. ethutil.Big(tokens[2]))) // nonce
  133. case "decode":
  134. value := ethutil.NewValueFromBytes([]byte(tokens[1]))
  135. fmt.Println(value)
  136. case "getaddr":
  137. encoded, _ := hex.DecodeString(tokens[1])
  138. addr := i.ethereum.BlockChain().CurrentBlock.State().GetAccount(encoded)
  139. fmt.Println("addr:", addr)
  140. case "block":
  141. encoded, _ := hex.DecodeString(tokens[1])
  142. block := i.ethereum.BlockChain().GetBlock(encoded)
  143. info := block.BlockInfo()
  144. fmt.Printf("++++++++++ #%d ++++++++++\n%v\n", info.Number, block)
  145. case "say":
  146. i.ethereum.Broadcast(ethwire.MsgTalkTy, []interface{}{tokens[1]})
  147. case "addp":
  148. i.ethereum.ConnectToPeer(tokens[1])
  149. case "pcount":
  150. fmt.Println("peers:", i.ethereum.Peers().Len())
  151. case "encode":
  152. fmt.Printf("%q\n", ethutil.Encode(tokens[1]))
  153. case "tx":
  154. recipient, err := hex.DecodeString(tokens[1])
  155. if err != nil {
  156. fmt.Println("recipient err:", err)
  157. } else {
  158. tx := ethchain.NewTx(recipient, ethutil.Big(tokens[2]), []string{""})
  159. key := ethutil.Config.Db.GetKeys()[0]
  160. tx.Sign(key.PrivateKey)
  161. i.ethereum.TxPool().QueueTransaction(tx)
  162. fmt.Printf("%x\n", tx.Hash())
  163. }
  164. case "gettx":
  165. addr, _ := hex.DecodeString(tokens[1])
  166. data, _ := ethutil.Config.Db.Get(addr)
  167. if len(data) != 0 {
  168. decoder := ethutil.NewValueFromBytes(data)
  169. fmt.Println(decoder)
  170. } else {
  171. fmt.Println("gettx: tx not found")
  172. }
  173. case "contract":
  174. fmt.Println("Contract editor (Ctrl-D = done)")
  175. asm := mutan.NewCompiler().Compile(strings.NewReader(i.Editor()))
  176. code := ethutil.Assemble(asm)
  177. contract := ethchain.NewContractCreationTx(ethutil.Big(tokens[0]), ethutil.Big(tokens[1]), code)
  178. key := ethutil.Config.Db.GetKeys()[0]
  179. contract.Sign(key.PrivateKey)
  180. i.ethereum.TxPool().QueueTransaction(contract)
  181. fmt.Printf("%x\n", contract.Hash()[12:])
  182. case "exit", "quit", "q":
  183. return false
  184. case "help":
  185. fmt.Printf("COMMANDS:\n" +
  186. "\033[1m= DB =\033[0m\n" +
  187. "update KEY VALUE - Updates/Creates a new value for the given key\n" +
  188. "get KEY - Retrieves the given key\n" +
  189. "root - Prints the hex encoded merkle root\n" +
  190. "rawroot - Prints the raw merkle root\n" +
  191. "block HASH - Prints the block\n" +
  192. "getaddr ADDR - Prints the account associated with the address\n" +
  193. "\033[1m= Dagger =\033[0m\n" +
  194. "dag HASH NONCE - Verifies a nonce with the given hash with dagger\n" +
  195. "\033[1m= Encoding =\033[0m\n" +
  196. "decode STR\n" +
  197. "encode STR\n" +
  198. "\033[1m= Other =\033[0m\n" +
  199. "addp HOST:PORT\n" +
  200. "tx TO AMOUNT\n" +
  201. "contract AMOUNT\n")
  202. default:
  203. fmt.Println("Unknown command:", tokens[0])
  204. }
  205. }
  206. return true
  207. }
  208. func (i *Console) Start() {
  209. fmt.Printf("Eth Console. Type (help) for help\n")
  210. reader := bufio.NewReader(os.Stdin)
  211. for {
  212. fmt.Printf("eth >>> ")
  213. str, _, err := reader.ReadLine()
  214. if err != nil {
  215. fmt.Println("Error reading input", err)
  216. } else {
  217. if !i.ParseInput(string(str)) {
  218. return
  219. }
  220. }
  221. }
  222. }