github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/rpc/api/parsing.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package api 18 19 import ( 20 "bytes" 21 "encoding/binary" 22 "encoding/hex" 23 "encoding/json" 24 "math/big" 25 "strings" 26 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/core/types" 29 "github.com/ethereum/go-ethereum/rpc/shared" 30 ) 31 32 type hexdata struct { 33 data []byte 34 isNil bool 35 } 36 37 func (d *hexdata) String() string { 38 return "0x" + common.Bytes2Hex(d.data) 39 } 40 41 func (d *hexdata) MarshalJSON() ([]byte, error) { 42 if d.isNil { 43 return json.Marshal(nil) 44 } 45 return json.Marshal(d.String()) 46 } 47 48 func newHexData(input interface{}) *hexdata { 49 d := new(hexdata) 50 51 if input == nil { 52 d.isNil = true 53 return d 54 } 55 switch input := input.(type) { 56 case []byte: 57 d.data = input 58 case common.Hash: 59 d.data = input.Bytes() 60 case *common.Hash: 61 if input == nil { 62 d.isNil = true 63 } else { 64 d.data = input.Bytes() 65 } 66 case common.Address: 67 d.data = input.Bytes() 68 case *common.Address: 69 if input == nil { 70 d.isNil = true 71 } else { 72 d.data = input.Bytes() 73 } 74 case types.Bloom: 75 d.data = input.Bytes() 76 case *types.Bloom: 77 if input == nil { 78 d.isNil = true 79 } else { 80 d.data = input.Bytes() 81 } 82 case *big.Int: 83 if input == nil { 84 d.isNil = true 85 } else { 86 d.data = input.Bytes() 87 } 88 case int64: 89 d.data = big.NewInt(input).Bytes() 90 case uint64: 91 buff := make([]byte, 8) 92 binary.BigEndian.PutUint64(buff, input) 93 d.data = buff 94 case int: 95 d.data = big.NewInt(int64(input)).Bytes() 96 case uint: 97 d.data = big.NewInt(int64(input)).Bytes() 98 case int8: 99 d.data = big.NewInt(int64(input)).Bytes() 100 case uint8: 101 d.data = big.NewInt(int64(input)).Bytes() 102 case int16: 103 d.data = big.NewInt(int64(input)).Bytes() 104 case uint16: 105 buff := make([]byte, 2) 106 binary.BigEndian.PutUint16(buff, input) 107 d.data = buff 108 case int32: 109 d.data = big.NewInt(int64(input)).Bytes() 110 case uint32: 111 buff := make([]byte, 4) 112 binary.BigEndian.PutUint32(buff, input) 113 d.data = buff 114 case string: // hexstring 115 // aaargh ffs TODO: avoid back-and-forth hex encodings where unneeded 116 bytes, err := hex.DecodeString(strings.TrimPrefix(input, "0x")) 117 if err != nil { 118 d.isNil = true 119 } else { 120 d.data = bytes 121 } 122 default: 123 d.isNil = true 124 } 125 126 return d 127 } 128 129 type hexnum struct { 130 data []byte 131 isNil bool 132 } 133 134 func (d *hexnum) String() string { 135 // Get hex string from bytes 136 out := common.Bytes2Hex(d.data) 137 // Trim leading 0s 138 out = strings.TrimLeft(out, "0") 139 // Output "0x0" when value is 0 140 if len(out) == 0 { 141 out = "0" 142 } 143 return "0x" + out 144 } 145 146 func (d *hexnum) MarshalJSON() ([]byte, error) { 147 if d.isNil { 148 return json.Marshal(nil) 149 } 150 return json.Marshal(d.String()) 151 } 152 153 func newHexNum(input interface{}) *hexnum { 154 d := new(hexnum) 155 156 d.data = newHexData(input).data 157 158 return d 159 } 160 161 type BlockRes struct { 162 fullTx bool 163 164 BlockNumber *hexnum `json:"number"` 165 BlockHash *hexdata `json:"hash"` 166 ParentHash *hexdata `json:"parentHash"` 167 Nonce *hexdata `json:"nonce"` 168 Sha3Uncles *hexdata `json:"sha3Uncles"` 169 LogsBloom *hexdata `json:"logsBloom"` 170 TransactionRoot *hexdata `json:"transactionsRoot"` 171 StateRoot *hexdata `json:"stateRoot"` 172 Miner *hexdata `json:"miner"` 173 Difficulty *hexnum `json:"difficulty"` 174 TotalDifficulty *hexnum `json:"totalDifficulty"` 175 Size *hexnum `json:"size"` 176 ExtraData *hexdata `json:"extraData"` 177 GasLimit *hexnum `json:"gasLimit"` 178 GasUsed *hexnum `json:"gasUsed"` 179 UnixTimestamp *hexnum `json:"timestamp"` 180 Transactions []*TransactionRes `json:"transactions"` 181 Uncles []*UncleRes `json:"uncles"` 182 } 183 184 func (b *BlockRes) MarshalJSON() ([]byte, error) { 185 if b.fullTx { 186 var ext struct { 187 BlockNumber *hexnum `json:"number"` 188 BlockHash *hexdata `json:"hash"` 189 ParentHash *hexdata `json:"parentHash"` 190 Nonce *hexdata `json:"nonce"` 191 Sha3Uncles *hexdata `json:"sha3Uncles"` 192 LogsBloom *hexdata `json:"logsBloom"` 193 TransactionRoot *hexdata `json:"transactionsRoot"` 194 StateRoot *hexdata `json:"stateRoot"` 195 Miner *hexdata `json:"miner"` 196 Difficulty *hexnum `json:"difficulty"` 197 TotalDifficulty *hexnum `json:"totalDifficulty"` 198 Size *hexnum `json:"size"` 199 ExtraData *hexdata `json:"extraData"` 200 GasLimit *hexnum `json:"gasLimit"` 201 GasUsed *hexnum `json:"gasUsed"` 202 UnixTimestamp *hexnum `json:"timestamp"` 203 Transactions []*TransactionRes `json:"transactions"` 204 Uncles []*hexdata `json:"uncles"` 205 } 206 207 ext.BlockNumber = b.BlockNumber 208 ext.BlockHash = b.BlockHash 209 ext.ParentHash = b.ParentHash 210 ext.Nonce = b.Nonce 211 ext.Sha3Uncles = b.Sha3Uncles 212 ext.LogsBloom = b.LogsBloom 213 ext.TransactionRoot = b.TransactionRoot 214 ext.StateRoot = b.StateRoot 215 ext.Miner = b.Miner 216 ext.Difficulty = b.Difficulty 217 ext.TotalDifficulty = b.TotalDifficulty 218 ext.Size = b.Size 219 ext.ExtraData = b.ExtraData 220 ext.GasLimit = b.GasLimit 221 ext.GasUsed = b.GasUsed 222 ext.UnixTimestamp = b.UnixTimestamp 223 ext.Transactions = b.Transactions 224 ext.Uncles = make([]*hexdata, len(b.Uncles)) 225 for i, u := range b.Uncles { 226 ext.Uncles[i] = u.BlockHash 227 } 228 return json.Marshal(ext) 229 } else { 230 var ext struct { 231 BlockNumber *hexnum `json:"number"` 232 BlockHash *hexdata `json:"hash"` 233 ParentHash *hexdata `json:"parentHash"` 234 Nonce *hexdata `json:"nonce"` 235 Sha3Uncles *hexdata `json:"sha3Uncles"` 236 LogsBloom *hexdata `json:"logsBloom"` 237 TransactionRoot *hexdata `json:"transactionsRoot"` 238 StateRoot *hexdata `json:"stateRoot"` 239 Miner *hexdata `json:"miner"` 240 Difficulty *hexnum `json:"difficulty"` 241 TotalDifficulty *hexnum `json:"totalDifficulty"` 242 Size *hexnum `json:"size"` 243 ExtraData *hexdata `json:"extraData"` 244 GasLimit *hexnum `json:"gasLimit"` 245 GasUsed *hexnum `json:"gasUsed"` 246 UnixTimestamp *hexnum `json:"timestamp"` 247 Transactions []*hexdata `json:"transactions"` 248 Uncles []*hexdata `json:"uncles"` 249 } 250 251 ext.BlockNumber = b.BlockNumber 252 ext.BlockHash = b.BlockHash 253 ext.ParentHash = b.ParentHash 254 ext.Nonce = b.Nonce 255 ext.Sha3Uncles = b.Sha3Uncles 256 ext.LogsBloom = b.LogsBloom 257 ext.TransactionRoot = b.TransactionRoot 258 ext.StateRoot = b.StateRoot 259 ext.Miner = b.Miner 260 ext.Difficulty = b.Difficulty 261 ext.TotalDifficulty = b.TotalDifficulty 262 ext.Size = b.Size 263 ext.ExtraData = b.ExtraData 264 ext.GasLimit = b.GasLimit 265 ext.GasUsed = b.GasUsed 266 ext.UnixTimestamp = b.UnixTimestamp 267 ext.Transactions = make([]*hexdata, len(b.Transactions)) 268 for i, tx := range b.Transactions { 269 ext.Transactions[i] = tx.Hash 270 } 271 ext.Uncles = make([]*hexdata, len(b.Uncles)) 272 for i, u := range b.Uncles { 273 ext.Uncles[i] = u.BlockHash 274 } 275 return json.Marshal(ext) 276 } 277 } 278 279 func NewBlockRes(block *types.Block, fullTx bool) *BlockRes { 280 if block == nil { 281 return nil 282 } 283 284 res := new(BlockRes) 285 res.fullTx = fullTx 286 res.BlockNumber = newHexNum(block.Number()) 287 res.BlockHash = newHexData(block.Hash()) 288 res.ParentHash = newHexData(block.ParentHash()) 289 res.Nonce = newHexData(block.Nonce()) 290 res.Sha3Uncles = newHexData(block.UncleHash()) 291 res.LogsBloom = newHexData(block.Bloom()) 292 res.TransactionRoot = newHexData(block.TxHash()) 293 res.StateRoot = newHexData(block.Root()) 294 res.Miner = newHexData(block.Coinbase()) 295 res.Difficulty = newHexNum(block.Difficulty()) 296 res.TotalDifficulty = newHexNum(block.Td) 297 res.Size = newHexNum(block.Size().Int64()) 298 res.ExtraData = newHexData(block.Extra()) 299 res.GasLimit = newHexNum(block.GasLimit()) 300 res.GasUsed = newHexNum(block.GasUsed()) 301 res.UnixTimestamp = newHexNum(block.Time()) 302 303 txs := block.Transactions() 304 res.Transactions = make([]*TransactionRes, len(txs)) 305 for i, tx := range txs { 306 res.Transactions[i] = NewTransactionRes(tx) 307 res.Transactions[i].BlockHash = res.BlockHash 308 res.Transactions[i].BlockNumber = res.BlockNumber 309 res.Transactions[i].TxIndex = newHexNum(i) 310 } 311 312 uncles := block.Uncles() 313 res.Uncles = make([]*UncleRes, len(uncles)) 314 for i, uncle := range uncles { 315 res.Uncles[i] = NewUncleRes(uncle) 316 } 317 318 return res 319 } 320 321 type TransactionRes struct { 322 Hash *hexdata `json:"hash"` 323 Nonce *hexnum `json:"nonce"` 324 BlockHash *hexdata `json:"blockHash"` 325 BlockNumber *hexnum `json:"blockNumber"` 326 TxIndex *hexnum `json:"transactionIndex"` 327 From *hexdata `json:"from"` 328 To *hexdata `json:"to"` 329 Value *hexnum `json:"value"` 330 Gas *hexnum `json:"gas"` 331 GasPrice *hexnum `json:"gasPrice"` 332 Input *hexdata `json:"input"` 333 } 334 335 func NewTransactionRes(tx *types.Transaction) *TransactionRes { 336 if tx == nil { 337 return nil 338 } 339 340 var v = new(TransactionRes) 341 v.Hash = newHexData(tx.Hash()) 342 v.Nonce = newHexNum(tx.Nonce()) 343 // v.BlockHash = 344 // v.BlockNumber = 345 // v.TxIndex = 346 from, _ := tx.From() 347 v.From = newHexData(from) 348 v.To = newHexData(tx.To()) 349 v.Value = newHexNum(tx.Value()) 350 v.Gas = newHexNum(tx.Gas()) 351 v.GasPrice = newHexNum(tx.GasPrice()) 352 v.Input = newHexData(tx.Data()) 353 return v 354 } 355 356 type UncleRes struct { 357 BlockNumber *hexnum `json:"number"` 358 BlockHash *hexdata `json:"hash"` 359 ParentHash *hexdata `json:"parentHash"` 360 Nonce *hexdata `json:"nonce"` 361 Sha3Uncles *hexdata `json:"sha3Uncles"` 362 ReceiptHash *hexdata `json:"receiptHash"` 363 LogsBloom *hexdata `json:"logsBloom"` 364 TransactionRoot *hexdata `json:"transactionsRoot"` 365 StateRoot *hexdata `json:"stateRoot"` 366 Miner *hexdata `json:"miner"` 367 Difficulty *hexnum `json:"difficulty"` 368 ExtraData *hexdata `json:"extraData"` 369 GasLimit *hexnum `json:"gasLimit"` 370 GasUsed *hexnum `json:"gasUsed"` 371 UnixTimestamp *hexnum `json:"timestamp"` 372 } 373 374 func NewUncleRes(h *types.Header) *UncleRes { 375 if h == nil { 376 return nil 377 } 378 379 var v = new(UncleRes) 380 v.BlockNumber = newHexNum(h.Number) 381 v.BlockHash = newHexData(h.Hash()) 382 v.ParentHash = newHexData(h.ParentHash) 383 v.Sha3Uncles = newHexData(h.UncleHash) 384 v.Nonce = newHexData(h.Nonce[:]) 385 v.LogsBloom = newHexData(h.Bloom) 386 v.TransactionRoot = newHexData(h.TxHash) 387 v.StateRoot = newHexData(h.Root) 388 v.Miner = newHexData(h.Coinbase) 389 v.Difficulty = newHexNum(h.Difficulty) 390 v.ExtraData = newHexData(h.Extra) 391 v.GasLimit = newHexNum(h.GasLimit) 392 v.GasUsed = newHexNum(h.GasUsed) 393 v.UnixTimestamp = newHexNum(h.Time) 394 v.ReceiptHash = newHexData(h.ReceiptHash) 395 396 return v 397 } 398 399 // type FilterLogRes struct { 400 // Hash string `json:"hash"` 401 // Address string `json:"address"` 402 // Data string `json:"data"` 403 // BlockNumber string `json:"blockNumber"` 404 // TransactionHash string `json:"transactionHash"` 405 // BlockHash string `json:"blockHash"` 406 // TransactionIndex string `json:"transactionIndex"` 407 // LogIndex string `json:"logIndex"` 408 // } 409 410 // type FilterWhisperRes struct { 411 // Hash string `json:"hash"` 412 // From string `json:"from"` 413 // To string `json:"to"` 414 // Expiry string `json:"expiry"` 415 // Sent string `json:"sent"` 416 // Ttl string `json:"ttl"` 417 // Topics string `json:"topics"` 418 // Payload string `json:"payload"` 419 // WorkProved string `json:"workProved"` 420 // } 421 422 type ReceiptRes struct { 423 TransactionHash *hexdata `json:"transactionHash"` 424 TransactionIndex *hexnum `json:"transactionIndex"` 425 BlockNumber *hexnum `json:"blockNumber"` 426 BlockHash *hexdata `json:"blockHash"` 427 CumulativeGasUsed *hexnum `json:"cumulativeGasUsed"` 428 GasUsed *hexnum `json:"gasUsed"` 429 ContractAddress *hexdata `json:"contractAddress"` 430 Logs *[]interface{} `json:"logs"` 431 } 432 433 func NewReceiptRes(rec *types.Receipt) *ReceiptRes { 434 if rec == nil { 435 return nil 436 } 437 438 var v = new(ReceiptRes) 439 v.TransactionHash = newHexData(rec.TxHash) 440 if rec.GasUsed != nil { 441 v.GasUsed = newHexNum(rec.GasUsed.Bytes()) 442 } 443 v.CumulativeGasUsed = newHexNum(rec.CumulativeGasUsed) 444 445 // If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation 446 if bytes.Compare(rec.ContractAddress.Bytes(), bytes.Repeat([]byte{0}, 20)) != 0 { 447 v.ContractAddress = newHexData(rec.ContractAddress) 448 } 449 450 logs := make([]interface{}, len(rec.Logs())) 451 for i, log := range rec.Logs() { 452 logs[i] = NewLogRes(log) 453 } 454 v.Logs = &logs 455 456 return v 457 } 458 459 func numString(raw interface{}) (*big.Int, error) { 460 var number *big.Int 461 // Parse as integer 462 num, ok := raw.(float64) 463 if ok { 464 number = big.NewInt(int64(num)) 465 return number, nil 466 } 467 468 // Parse as string/hexstring 469 str, ok := raw.(string) 470 if ok { 471 number = common.String2Big(str) 472 return number, nil 473 } 474 475 return nil, shared.NewInvalidTypeError("", "not a number or string") 476 } 477 478 func blockHeight(raw interface{}, number *int64) error { 479 // Parse as integer 480 num, ok := raw.(float64) 481 if ok { 482 *number = int64(num) 483 return nil 484 } 485 486 // Parse as string/hexstring 487 str, ok := raw.(string) 488 if !ok { 489 return shared.NewInvalidTypeError("", "not a number or string") 490 } 491 492 switch str { 493 case "earliest": 494 *number = 0 495 case "latest": 496 *number = -1 497 case "pending": 498 *number = -2 499 default: 500 if common.HasHexPrefix(str) { 501 *number = common.String2Big(str).Int64() 502 } else { 503 return shared.NewInvalidTypeError("blockNumber", "is not a valid string") 504 } 505 } 506 507 return nil 508 } 509 510 func blockHeightFromJson(msg json.RawMessage, number *int64) error { 511 var raw interface{} 512 if err := json.Unmarshal(msg, &raw); err != nil { 513 return shared.NewDecodeParamError(err.Error()) 514 } 515 return blockHeight(raw, number) 516 }