/
eos.go
178 lines (147 loc) · 4.25 KB
/
eos.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
package wrkchains
import (
"bytes"
"encoding/json"
"fmt"
"github.com/spf13/viper"
"github.com/tendermint/tendermint/libs/log"
"github.com/unification-com/wrkoracle/types"
"io/ioutil"
"net/http"
"strconv"
)
// nolint
const (
TxMRoot string = "TxMRoot"
ActionRoot string = "ActionRoot"
ProducerSig string = "ProducerSig"
)
// EosGetBlockInfoResult holds the result for a Eos getbestblockhash JSON RPC query
type EosGetBlockInfoResult struct {
ChainId string `json:"chain_id"`
LastIrreversible uint64 `json:"last_irreversible_block_num"`
HeadBlockNum uint64 `json:"head_block_num"`
}
// EosBlockHeaderResult holds the result from a Eos JSON RPC query
type EosBlockHeaderResult struct {
Id string `json:"id"` // hash
BlockNum uint64 `json:"block_num"` // height
Previous string `json:"previous"` // parent hash
TxMRoot string `json:"transaction_mroot"`
ActionRoot string `json:"action_mroot"`
ProducerSig string `json:"producer_signature"`
}
func init() {
wrkchainClientCreator := func(log log.Logger, lastHeight uint64) WrkChainClient {
return NewEosClient(log, lastHeight)
}
supportedHashMaps := []string{TxMRoot, ActionRoot, ProducerSig}
defaultHashMap := make(map[string]string)
defaultHashMap[types.FlagHash1] = TxMRoot
defaultHashMap[types.FlagHash2] = ActionRoot
defaultHashMap[types.FlagHash3] = ProducerSig
registerWrkchainModule(EosWrkchainType, wrkchainClientCreator, supportedHashMaps, defaultHashMap, false)
}
var _ WrkChainClient = (*Eos)(nil)
// Eos is a structure for holding a Eos based WRKChain client
type Eos struct {
log log.Logger
lastHeight uint64
}
// NewEosClient returns a new Eos struct
func NewEosClient(log log.Logger, lastHeight uint64) *Eos {
return &Eos{
log: log,
lastHeight: lastHeight,
}
}
func (n Eos) getLatestBlockHash() (string, error) {
queryUrl := viper.GetString(types.FlagWrkchainRpc) + "/v1/chain/get_info"
resp, err := http.Post(queryUrl, "application/json", bytes.NewBuffer([]byte{}))
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
var res EosGetBlockInfoResult
err = json.Unmarshal(body, &res)
if err != nil {
return "", err
}
return strconv.FormatUint(res.LastIrreversible, 10), nil
}
// GetBlockAtHeight is used to get the block headers for a given height from a Eos based WRKChain
func (n *Eos) GetBlockAtHeight(height uint64) (WrkChainBlockHeader, error) {
queryUrl := viper.GetString(types.FlagWrkchainRpc) + "/v1/chain/get_block"
var jsonStr []byte
atHeight, err := n.getLatestBlockHash()
if err != nil {
return WrkChainBlockHeader{}, err
}
if height > 0 {
atHeight = strconv.FormatUint(height, 10)
}
jsonStr = []byte(`{"block_num_or_id": "` + atHeight + `"}`)
resp, err := http.Post(queryUrl, "application/json", bytes.NewBuffer(jsonStr))
if err != nil {
return WrkChainBlockHeader{}, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return WrkChainBlockHeader{}, err
}
var header EosBlockHeaderResult
err = json.Unmarshal(body, &header)
if err != nil {
return WrkChainBlockHeader{}, err
}
if err != nil {
return WrkChainBlockHeader{}, err
}
blockHash := header.Id
parentHash := ""
hash1 := ""
hash2 := ""
hash3 := ""
blockHeight := header.BlockNum
if err != nil {
return WrkChainBlockHeader{}, err
}
if height == 0 {
n.lastHeight = blockHeight
}
if viper.GetBool(types.FlagParentHash) {
parentHash = header.Previous
}
hash1Ref := viper.GetString(types.FlagHash1)
hash2Ref := viper.GetString(types.FlagHash2)
hash3Ref := viper.GetString(types.FlagHash3)
if len(hash1Ref) > 0 {
hash1 = n.gethash(header, hash1Ref)
}
if len(hash2Ref) > 0 {
hash2 = n.gethash(header, hash2Ref)
}
if len(hash3Ref) > 0 {
hash3 = n.gethash(header, hash3Ref)
}
wrkchainBlock := NewWrkChainBlockHeader(blockHeight, blockHash, parentHash, hash1, hash2, hash3)
return wrkchainBlock, nil
}
func (n Eos) gethash(header EosBlockHeaderResult, ref string) string {
switch ref {
case TxMRoot:
return header.TxMRoot
case ActionRoot:
return header.ActionRoot
case ProducerSig:
return header.ProducerSig
default:
n.log.Error(fmt.Sprintf("unknown hash type '%s'", ref))
return ""
}
}