github.com/turingchain2020/turingchain@v1.1.21/blockchain/query_tx.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package blockchain 6 7 import ( 8 "bytes" 9 "fmt" 10 11 "github.com/turingchain2020/turingchain/common" 12 "github.com/turingchain2020/turingchain/common/merkle" 13 "github.com/turingchain2020/turingchain/types" 14 ) 15 16 //ProcGetTransactionByAddr 获取地址对应的所有交易信息 17 //存储格式key:addr:flag:height ,value:txhash 18 //key=addr :获取本地参与的所有交易 19 //key=addr:1 :获取本地作为from方的所有交易 20 //key=addr:2 :获取本地作为to方的所有交易 21 func (chain *BlockChain) ProcGetTransactionByAddr(addr *types.ReqAddr) (*types.ReplyTxInfos, error) { 22 if addr == nil || len(addr.Addr) == 0 { 23 return nil, types.ErrInvalidParam 24 } 25 //默认取10笔交易数据 26 if addr.Count == 0 { 27 addr.Count = 10 28 } 29 30 if int64(addr.Count) > types.MaxBlockCountPerTime { 31 return nil, types.ErrMaxCountPerTime 32 } 33 //入参数校验 34 curheigt := chain.GetBlockHeight() 35 if addr.GetHeight() > curheigt || addr.GetHeight() < -1 { 36 chainlog.Error("ProcGetTransactionByAddr Height err") 37 return nil, types.ErrInvalidParam 38 } 39 if addr.GetDirection() != 0 && addr.GetDirection() != 1 { 40 chainlog.Error("ProcGetTransactionByAddr Direction err") 41 return nil, types.ErrInvalidParam 42 } 43 if addr.GetIndex() < 0 || addr.GetIndex() > types.MaxTxsPerBlock { 44 chainlog.Error("ProcGetTransactionByAddr Index err") 45 return nil, types.ErrInvalidParam 46 } 47 //查询的drivers--> main 驱动的名称 48 //查询的方法: --> GetTxsByAddr 49 //查询的参数: --> interface{} 类型 50 cfg := chain.client.GetConfig() 51 txinfos, err := chain.query.Query(cfg.ExecName("coins"), "GetTxsByAddr", addr) 52 if err != nil { 53 chainlog.Info("ProcGetTransactionByAddr does not exist tx!", "addr", addr, "err", err) 54 return nil, err 55 } 56 return txinfos.(*types.ReplyTxInfos), nil 57 } 58 59 //ProcGetTransactionByHashes 返回类型 60 //type TransactionDetails struct { 61 // Txs []*Transaction 62 //} 63 //通过hashs获取交易详情 64 func (chain *BlockChain) ProcGetTransactionByHashes(hashs [][]byte) (TxDetails *types.TransactionDetails, err error) { 65 if int64(len(hashs)) > types.MaxBlockCountPerTime { 66 return nil, types.ErrMaxCountPerTime 67 } 68 var txDetails types.TransactionDetails 69 for _, txhash := range hashs { 70 txresult, err := chain.GetTxResultFromDb(txhash) 71 var txDetail types.TransactionDetail 72 if err == nil && txresult != nil { 73 setTxDetailFromTxResult(&txDetail, txresult) 74 75 //chainlog.Debug("ProcGetTransactionByHashes", "txDetail", txDetail.String()) 76 txDetails.Txs = append(txDetails.Txs, &txDetail) 77 } else { 78 txDetails.Txs = append(txDetails.Txs, &txDetail) // 79 chainlog.Debug("ProcGetTransactionByHashes hash no exit", "txhash", common.ToHex(txhash)) 80 } 81 } 82 return &txDetails, nil 83 } 84 85 //getTxHashProofs 获取指定txindex在txs中的proof ,注释:index从0开始 86 func getTxHashProofs(Txs []*types.Transaction, index int32) [][]byte { 87 txlen := len(Txs) 88 leaves := make([][]byte, txlen) 89 90 for index, tx := range Txs { 91 leaves[index] = tx.Hash() 92 } 93 94 proofs := merkle.GetMerkleBranch(leaves, uint32(index)) 95 chainlog.Debug("getTransactionDetail", "index", index, "proofs", proofs) 96 97 return proofs 98 } 99 100 //GetTxResultFromDb 通过txhash 从txindex db中获取tx信息 101 //type TxResult struct { 102 // Height int64 103 // Index int32 104 // Tx *types.Transaction 105 // Receiptdate *ReceiptData 106 //} 107 func (chain *BlockChain) GetTxResultFromDb(txhash []byte) (tx *types.TxResult, err error) { 108 txinfo, err := chain.blockStore.GetTx(txhash) 109 if err != nil { 110 return nil, err 111 } 112 return txinfo, nil 113 } 114 115 //HasTx 是否包含该交易 116 func (chain *BlockChain) HasTx(txhash []byte, txHeight int64) (has bool, err error) { 117 118 if txHeight > 0 { 119 return chain.txHeightCache.Contains(txhash, txHeight), nil 120 } 121 return chain.blockStore.HasTx(txhash) 122 } 123 124 //GetDuplicateTxHashList 获取重复的交易 125 func (chain *BlockChain) GetDuplicateTxHashList(txhashlist *types.TxHashList) (duptxhashlist *types.TxHashList, err error) { 126 var dupTxHashList types.TxHashList 127 //onlyquerycache := false 128 //FIXME:这里Count实际传的是区块高度的值,代码中没找到-1的传参,不清楚具体含义 129 //对于非txHeight类交易,直接查询数据库,不会有影响,暂时先注释 130 //if txhashlist.Count == -1 { 131 // onlyquerycache = true 132 //} 133 if txhashlist.Expire != nil && len(txhashlist.Expire) != len(txhashlist.Hashes) { 134 return nil, types.ErrInvalidParam 135 } 136 cfg := chain.client.GetConfig() 137 for i, txhash := range txhashlist.Hashes { 138 expire := int64(0) 139 if txhashlist.Expire != nil { 140 expire = txhashlist.Expire[i] 141 } 142 txHeight := types.GetTxHeight(cfg, expire, txhashlist.Count) 143 has, err := chain.HasTx(txhash, txHeight) 144 if err == nil && has { 145 dupTxHashList.Hashes = append(dupTxHashList.Hashes, txhash) 146 } 147 } 148 return &dupTxHashList, nil 149 } 150 151 /*ProcQueryTxMsg 函数功能: 152 EventQueryTx(types.ReqHash) : rpc模块会向 blockchain 模块 发送 EventQueryTx(types.ReqHash) 消息 , 153 查询交易的默克尔树,回复消息 EventTransactionDetail(types.TransactionDetail) 154 结构体: 155 type ReqHash struct {Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`} 156 type TransactionDetail struct {Hashs [][]byte `protobuf:"bytes,1,rep,name=hashs,proto3" json:"hashs,omitempty"} 157 */ 158 func (chain *BlockChain) ProcQueryTxMsg(txhash []byte) (proof *types.TransactionDetail, err error) { 159 txresult, err := chain.GetTxResultFromDb(txhash) 160 if err != nil { 161 return nil, err 162 } 163 block, err := chain.GetBlock(txresult.Height) 164 if err != nil { 165 return nil, err 166 } 167 168 var txDetail types.TransactionDetail 169 cfg := chain.client.GetConfig() 170 height := block.Block.GetHeight() 171 if chain.isParaChain { 172 height = block.Block.GetMainHeight() 173 } 174 //获取指定tx在txlist中的proof,需要区分ForkRootHash前后proof证明数据 175 if !cfg.IsFork(height, "ForkRootHash") { 176 proofs := getTxHashProofs(block.Block.Txs, txresult.Index) 177 txDetail.Proofs = proofs 178 } else { 179 txproofs := chain.getMultiLayerProofs(txresult.Height, block.Block.Hash(cfg), block.Block.Txs, txresult.Index) 180 txDetail.TxProofs = txproofs 181 txDetail.FullHash = block.Block.Txs[txresult.Index].FullHash() 182 } 183 184 setTxDetailFromTxResult(&txDetail, txresult) 185 return &txDetail, nil 186 } 187 188 func setTxDetailFromTxResult(TransactionDetail *types.TransactionDetail, txresult *types.TxResult) { 189 TransactionDetail.Receipt = txresult.Receiptdate 190 TransactionDetail.Tx = txresult.GetTx() 191 TransactionDetail.Height = txresult.GetHeight() 192 TransactionDetail.Index = int64(txresult.GetIndex()) 193 TransactionDetail.Blocktime = txresult.GetBlocktime() 194 195 //获取Amount 196 amount, err := txresult.GetTx().Amount() 197 if err != nil { 198 // return nil, err 199 amount = 0 200 } 201 TransactionDetail.Amount = amount 202 assets, err := txresult.GetTx().Assets() 203 if err != nil { 204 assets = nil 205 } 206 TransactionDetail.Assets = assets 207 TransactionDetail.ActionName = txresult.GetTx().ActionName() 208 209 //获取from地址 210 TransactionDetail.Fromaddr = txresult.GetTx().From() 211 } 212 213 //ProcGetAddrOverview 获取addrOverview 214 //type AddrOverview { 215 // int64 reciver = 1; 216 // int64 balance = 2; 217 // int64 txCount = 3;} 218 func (chain *BlockChain) ProcGetAddrOverview(addr *types.ReqAddr) (*types.AddrOverview, error) { 219 cfg := chain.client.GetConfig() 220 if addr == nil || len(addr.Addr) == 0 { 221 chainlog.Error("ProcGetAddrOverview input err!") 222 return nil, types.ErrInvalidParam 223 } 224 chainlog.Debug("ProcGetAddrOverview", "Addr", addr.GetAddr()) 225 226 var addrOverview types.AddrOverview 227 228 //获取地址的reciver 229 amount, err := chain.query.Query(cfg.ExecName("coins"), "GetAddrReciver", addr) 230 if err != nil { 231 chainlog.Error("ProcGetAddrOverview", "GetAddrReciver err", err) 232 addrOverview.Reciver = 0 233 } else { 234 addrOverview.Reciver = amount.(*types.Int64).GetData() 235 } 236 if err != nil && err != types.ErrEmpty { 237 return nil, err 238 } 239 240 var reqkey types.ReqKey 241 242 //新的代码不支持PrefixCount查询地址交易计数,executor/localdb.go PrefixCount 243 //现有的节点都已经升级了localdb,也就是都支持通过GetAddrTxsCount来获取地址交易计数 244 reqkey.Key = []byte(fmt.Sprintf("AddrTxsCount:%s", addr.Addr)) 245 count, err := chain.query.Query(cfg.ExecName("coins"), "GetAddrTxsCount", &reqkey) 246 if err != nil { 247 chainlog.Error("ProcGetAddrOverview", "GetAddrTxsCount err", err) 248 addrOverview.TxCount = 0 249 } else { 250 addrOverview.TxCount = count.(*types.Int64).GetData() 251 } 252 chainlog.Debug("GetAddrTxsCount", "TxCount ", addrOverview.TxCount) 253 254 return &addrOverview, nil 255 } 256 257 //getTxFullHashProofs 获取指定txinde在txs中的proof, ForkRootHash之后使用fullhash来计算 258 func getTxFullHashProofs(Txs []*types.Transaction, index int32) [][]byte { 259 txlen := len(Txs) 260 leaves := make([][]byte, txlen) 261 262 for index, tx := range Txs { 263 leaves[index] = tx.FullHash() 264 } 265 266 proofs := merkle.GetMerkleBranch(leaves, uint32(index)) 267 268 return proofs 269 } 270 271 //获取指定交易在子链中的路径证明,使用fullhash 272 func (chain *BlockChain) getMultiLayerProofs(height int64, blockHash []byte, Txs []*types.Transaction, index int32) []*types.TxProof { 273 var proofs []*types.TxProof 274 275 //平行链节点上的交易都是单层merkle树,使用FullHash直接计算即可 276 if chain.isParaChain { 277 txProofs := getTxFullHashProofs(Txs, index) 278 proof := types.TxProof{Proofs: txProofs, Index: uint32(index)} 279 proofs = append(proofs, &proof) 280 return proofs 281 } 282 283 //主链节点的处理 284 title, haveParaTx := types.GetParaExecTitleName(string(Txs[index].Execer)) 285 if !haveParaTx { 286 title = types.MainChainName 287 } 288 289 replyparaTxs, err := chain.LoadParaTxByHeight(height, "", 0, 1) 290 if err != nil || 0 == len(replyparaTxs.Items) { 291 filterlog.Error("getMultiLayerProofs", "height", height, "blockHash", common.ToHex(blockHash), "err", err) 292 return nil 293 } 294 295 //获取本子链的第一笔交易的index值,以及最后一笔交易的index值 296 var startIndex int32 297 var childIndex uint32 298 var hashes [][]byte 299 var exist bool 300 var childHash []byte 301 var txCount int32 302 303 for _, paratx := range replyparaTxs.Items { 304 if title == paratx.Title && bytes.Equal(blockHash, paratx.GetHash()) { 305 startIndex = paratx.GetStartIndex() 306 childIndex = paratx.ChildHashIndex 307 childHash = paratx.ChildHash 308 txCount = paratx.GetTxCount() 309 exist = true 310 } 311 hashes = append(hashes, paratx.ChildHash) 312 } 313 //只有主链的交易,没有其他平行链的交易 314 if len(replyparaTxs.Items) == 1 && startIndex == 0 && childIndex == 0 { 315 txProofs := getTxFullHashProofs(Txs, index) 316 proof := types.TxProof{Proofs: txProofs, Index: uint32(index)} 317 proofs = append(proofs, &proof) 318 return proofs 319 } 320 321 endindex := startIndex + txCount 322 //不存在或者获取到的索引错误直接返回 323 if !exist || startIndex > index || endindex > int32(len(Txs)) || childIndex >= uint32(len(replyparaTxs.Items)) { 324 filterlog.Error("getMultiLayerProofs", "height", height, "blockHash", common.ToHex(blockHash), "exist", exist, "replyparaTxs", replyparaTxs) 325 filterlog.Error("getMultiLayerProofs", "startIndex", startIndex, "index", index, "childIndex", childIndex) 326 return nil 327 } 328 329 //主链和平行链交易都存在,获取本子链所有交易的hash值 330 var childHashes [][]byte 331 for i := startIndex; i < endindex; i++ { 332 childHashes = append(childHashes, Txs[i].FullHash()) 333 } 334 txOnChildIndex := index - startIndex 335 336 //计算单笔交易在子链中的路径证明 337 txOnChildBranch := merkle.GetMerkleBranch(childHashes, uint32(txOnChildIndex)) 338 txproof := types.TxProof{Proofs: txOnChildBranch, Index: uint32(txOnChildIndex), RootHash: childHash} 339 proofs = append(proofs, &txproof) 340 341 //子链在整个区块中的路径证明 342 childBranch := merkle.GetMerkleBranch(hashes, childIndex) 343 childproof := types.TxProof{Proofs: childBranch, Index: childIndex} 344 proofs = append(proofs, &childproof) 345 return proofs 346 }