diff --git a/bfa_client/src/bfa/node.go b/bfa_client/src/bfa/node.go index 2a9fbd8df3b0588d46dcbebb3595b198b13acb89..a63283040e465ecdbd1615c15d4230031af6a14c 100644 --- a/bfa_client/src/bfa/node.go +++ b/bfa_client/src/bfa/node.go @@ -3,39 +3,135 @@ package bfa import ( . "../clique" . "../util" - "context" + "encoding/json" "fmt" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/rpc" "math/big" + "reflect" "sort" "strconv" ) type Node rpc.Client +type BigInt big.Int + +func (b BigInt) MarshalJSON() ([]byte, error) { + i := (big.Int)(b) + return []byte(i.String()), nil +} + +func (b *BigInt) String() string { + return (*big.Int)(b).String() +} + +// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction +type RPCTransaction struct { + BlockHash string `json:"blockHash"` + BlockNumber int64 `json:"blockNumber"` + From string `json:"from"` + Gas uint64 `json:"gas"` + GasPrice uint64 `json:"gasPrice"` + Hash string `json:"hash"` + Input string `json:"input"` + Nonce uint64 `json:"nonce"` + To string `json:"to"` + TransactionIndex uint `json:"transactionIndex"` + Value string `json:"value"` + V *BigInt `json:"v"` + R *BigInt `json:"r"` + S *BigInt `json:"s"` +} + type Block struct { - ParentHash common.Hash `json:"parentHash"` - Coinbase common.Address `json:"miner"` - Root common.Hash `json:"stateRoot"` - TxHash common.Hash `json:"transactionsRoot"` - ReceiptHash common.Hash `json:"receiptsRoot"` - Bloom types.Bloom `json:"logsBloom"` - Difficulty *big.Int `json:"difficulty"` - Number *big.Int `json:"number"` - GasLimit uint64 `json:"gasLimit"` - GasUsed uint64 `json:"gasUsed"` - Time *big.Int `json:"timestamp"` - Extra []byte `json:"extraData"` - MixDigest common.Hash `json:"mixHash"` - Nonce types.BlockNonce `json:"nonce"` - Transactions []types.Transaction `json:"transactions"` - TotalDifficulty *big.Int `json:"totalDifficulty"` - Signer string `json:"signer"` + ParentHash string `json:"parentHash"` + Coinbase string `json:"miner"` + Root string `json:"stateRoot"` + TxHash string `json:"transactionsRoot"` + ReceiptHash string `json:"receiptsRoot"` + Bloom string `json:"logsBloom"` + Difficulty uint64 `json:"difficulty"` + Number uint64 `json:"number"` + GasLimit uint64 `json:"gasLimit"` + GasUsed uint64 `json:"gasUsed"` + Time uint64 `json:"timestamp"` + Extra string `json:"extraData"` + MixDigest string `json:"mixHash"` + Nonce uint64 `json:"nonce"` + Transactions []RPCTransaction `json:"transactions"` + TotalDifficulty uint64 `json:"totalDifficulty"` + Signer string `json:"signer"` +} + +func mapToStruct(m map[string]interface{}, s interface{}) { + v := reflect.ValueOf(s).Elem() + numFields := v.NumField() + for i := 0; i < numFields; i++ { + field := v.Field(i) + jsonName := v.Type().Field(i).Tag.Get("json") + if value, ok := m[jsonName]; ok { + switch x := value.(type) { + case string: + switch field.Kind() { + case reflect.String: + field.SetString(x) + case reflect.Uint64, reflect.Uint: + if uintValue, err := strconv.ParseUint(x, 0, 64); err == nil { + field.SetUint(uintValue) + } + case reflect.Int64, reflect.Int: + if intValue, err := strconv.ParseInt(x, 0, 64); err == nil { + field.SetInt(intValue) + } + } + } + } + } +} + +func (block *Block) UnmarshalJSON(b []byte) error { + var m map[string]interface{} + if err := json.Unmarshal(b, &m); err != nil { + return err + } + mapToStruct(m, block) + //v := reflect.ValueOf(block).Elem() + //numFields := v.NumField() + //for i := 0; i < numFields; i++ { + // field := v.Field(i) + // jsonName := v.Type().Field(i).Tag.Get("json") + // if value, ok := m[jsonName]; ok { + // switch x := value.(type) { + // case string: + // switch field.Kind() { + // case reflect.String: + // field.SetString(x) + // case reflect.Uint64: + // if uintValue, err := strconv.ParseUint(x, 0, 64); err == nil { + // field.SetUint(uintValue) + // } + // } + // } + // } + //} + for _, x := range m["transactions"].([]interface{}) { + t := new(RPCTransaction) + m := x.(map[string]interface{}) + mapToStruct(m, t) + v, _ := new(big.Int).SetString(m["v"].(string), 0) + r, _ := new(big.Int).SetString(m["r"].(string), 0) + s, _ := new(big.Int).SetString(m["s"].(string), 0) + t.V = (*BigInt)(v) + t.R = (*BigInt)(r) + t.S = (*BigInt)(s) + fmt.Println(t.R, t.S, t.V) + block.Transactions = append(block.Transactions, *t) + } + return nil } type Snapshot struct { @@ -161,32 +257,43 @@ func (node *Node) HeaderByNumber(blockNumber int64) types.Header { } func (node *Node) BlockByNumber(blockNumber int64) (block Block) { - ethClient := ethclient.NewClient((*rpc.Client)(node)) - b, err := ethClient.BlockByNumber(context.Background(), nil) - h := b.Header() - Check(err) - block.ParentHash = h.ParentHash - block.Coinbase = h.Coinbase - block.Root = h.Root - block.TxHash = h.TxHash - block.ReceiptHash = h.ReceiptHash - block.Bloom = h.Bloom - block.Difficulty = h.Difficulty - block.Number = h.Number - block.GasLimit = h.GasLimit - block.GasUsed = h.GasUsed - block.Time = h.Time - block.Extra = h.Extra - block.MixDigest = h.MixDigest - block.Nonce = h.Nonce - for _, transaction := range b.Transactions() { - block.Transactions = append(block.Transactions, *transaction) - } - block.Signer, err = GetSigner(h) - block.TotalDifficulty = b.DeprecatedTd() - return block + var ( + number string + ) + if blockNumber < 0 { + number = Latest + } else { + number = fmt.Sprintf("0x%x", blockNumber) + } + node.Call(&block, "eth_getBlockByNumber", number, true) + return } +//func (node *Node) BlockxByNumber(blockNumber int64) (block Block) { +// ethClient := ethclient.NewClient((*rpc.Client)(node)) +// b, err := ethClient.BlockByNumber(context.Background(), big.NewInt(blockNumber)) +// h := b.Header() +// Check(err) +// block.ParentHash = h.ParentHash +// block.Coinbase = h.Coinbase +// block.Root = h.Root +// block.TxHash = h.TxHash +// block.ReceiptHash = h.ReceiptHash +// block.Bloom = h.Bloom +// block.Difficulty = h.Difficulty +// block.Number = h.Number +// block.GasLimit = h.GasLimit +// block.GasUsed = h.GasUsed +// block.Time = h.Time +// block.Extra = h.Extra +// block.MixDigest = h.MixDigest +// block.Nonce = h.Nonce +// block.Transactions = b.Transactions() +// block.Signer, err = GetSigner(h) +// block.TotalDifficulty = b.DeprecatedTd() +// return block +//} + func (node *Node) BlockSigner(blockNumber int64) (signer string) { header := node.HeaderByNumber(blockNumber) signer, err := GetSigner(&header) diff --git a/bfa_client/src/client/bfa_client.go b/bfa_client/src/client/bfa_client.go index f4e323462a72572e5a0a8a2ebac18c9c5761a747..dcc6c4039a44c02aed5a111000a46b72571ceb13 100644 --- a/bfa_client/src/client/bfa_client.go +++ b/bfa_client/src/client/bfa_client.go @@ -407,7 +407,8 @@ func block() { node, err := bfa.Dial(url) util.Check(err) defer node.Close() - util.PrintJson(node.BlockByNumber(blockNumber)) + block := node.BlockByNumber(blockNumber) + util.PrintJson(block) } func main() {