github.com/deroproject/derosuite@v2.1.6-1.0.20200307070847-0f2e589c7a2b+incompatible/blockchain/rpcserver/gettransactions.go (about) 1 // Copyright 2017-2018 DERO Project. All rights reserved. 2 // Use of this source code in any form is governed by RESEARCH license. 3 // license can be found in the LICENSE file. 4 // GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8 5 // 6 // 7 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 8 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 9 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 10 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 11 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 12 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 13 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 14 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 15 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 17 package rpcserver 18 19 import "net/http" 20 import "encoding/hex" 21 import "encoding/json" 22 23 import "github.com/romana/rlog" 24 import "github.com/vmihailenco/msgpack" 25 26 import "github.com/deroproject/derosuite/crypto" 27 import "github.com/deroproject/derosuite/globals" 28 import "github.com/deroproject/derosuite/structures" 29 import "github.com/deroproject/derosuite/transaction" 30 31 // we definitely need to clear up the MESS that has been created by the MONERO project 32 // half of their APIs are json rpc and half are http 33 // for compatibility reasons, we are implementing theirs ( however we are also providin a json rpc implementation) 34 // we should DISCARD the http 35 36 // NOTE: we have currently not implemented the decode as json parameter 37 // it is however on the pending list 38 39 type GetTransaction_Handler struct{} 40 41 func gettransactions(rw http.ResponseWriter, req *http.Request) { 42 decoder := json.NewDecoder(req.Body) 43 var p structures.GetTransaction_Params 44 err := decoder.Decode(&p) 45 if err != nil { 46 panic(err) 47 } 48 defer req.Body.Close() 49 50 result := gettransactions_fill(p) 51 //logger.Debugf("Request %+v", p) 52 53 encoder := json.NewEncoder(rw) 54 encoder.Encode(result) 55 } 56 57 // fill up the response 58 func gettransactions_fill(p structures.GetTransaction_Params) (result structures.GetTransaction_Result) { 59 60 for i := 0; i < len(p.Tx_Hashes); i++ { 61 62 hash := crypto.HashHexToHash(p.Tx_Hashes[i]) 63 64 { // check if tx is from blockchain 65 tx, err := chain.Load_TX_FROM_ID(nil, hash) 66 if err == nil { 67 var related structures.Tx_Related_Info 68 69 // check whether tx is orphan 70 71 /*if chain.Is_TX_Orphan(hash) { 72 result.Txs_as_hex = append(result.Txs_as_hex, "") // given empty data 73 result.Txs = append(result.Txs, related) // should we have an orphan tx marker 74 } else */{ 75 76 // topo height at which it was mined 77 related.Block_Height = int64(chain.Load_TX_Height(nil, hash)) 78 79 if tx.IsCoinbase() { // fill reward but only for coinbase 80 blhash, err := chain.Load_Block_Topological_order_at_index(nil, int64(related.Block_Height)) 81 if err == nil { // if err return err 82 related.Reward = chain.Load_Block_Total_Reward(nil, blhash) 83 } 84 } 85 86 if !tx.IsCoinbase() { 87 // expand ring members and provide information 88 related.Ring = make([][]globals.TX_Output_Data, len(tx.Vin), len(tx.Vin)) 89 for i := 0; i < len(tx.Vin); i++ { 90 related.Ring[i] = make([]globals.TX_Output_Data, len(tx.Vin[i].(transaction.Txin_to_key).Key_offsets), len(tx.Vin[i].(transaction.Txin_to_key).Key_offsets)) 91 ring_member := uint64(0) 92 for j := 0; j < len(tx.Vin[i].(transaction.Txin_to_key).Key_offsets); j++ { 93 ring_member += tx.Vin[i].(transaction.Txin_to_key).Key_offsets[j] 94 95 var ring_data globals.TX_Output_Data 96 data_bytes, err := chain.Read_output_index(nil, ring_member) 97 98 err = msgpack.Unmarshal(data_bytes, &ring_data) 99 if err != nil { 100 rlog.Warnf("RPC err while unmarshallin output index data index = %d data_len %d err %s", ring_member, len(data_bytes), err) 101 } 102 related.Ring[i][j] = ring_data 103 } 104 } 105 err = nil 106 } 107 108 // also fill where the tx is found and in which block is valid and in which it is invalid 109 110 blocks := chain.Load_TX_blocks(nil, hash) 111 112 for i := range blocks { 113 114 // logger.Infof("%s tx valid %+v",blocks[i],chain.IS_TX_Valid(nil,blocks[i],hash)) 115 // logger.Infof("%s block topo %+v", blocks[i], chain.Is_Block_Topological_order(nil,blocks[i])) 116 if chain.IS_TX_Valid(nil, blocks[i], hash) && chain.Is_Block_Topological_order(nil, blocks[i]) { 117 related.ValidBlock = blocks[i].String() 118 } else { 119 120 related.InvalidBlock = append(related.InvalidBlock, blocks[i].String()) 121 } 122 123 } 124 125 index := chain.Find_TX_Output_Index(hash) 126 // index := uint64(0) 127 128 // logger.Infof("TX hash %s height %d",hash, related.Block_Height) 129 for i := 0; i < len(tx.Vout); i++ { 130 if index >= 0 { 131 related.Output_Indices = append(related.Output_Indices, uint64(index+int64(i))) 132 } else { 133 related.Output_Indices = append(related.Output_Indices, 0) 134 } 135 } 136 result.Txs_as_hex = append(result.Txs_as_hex, hex.EncodeToString(tx.Serialize())) 137 result.Txs = append(result.Txs, related) 138 } 139 continue 140 } 141 } 142 // check whether we can get the tx from the pool 143 { 144 tx := chain.Mempool.Mempool_Get_TX(hash) 145 if tx != nil { // found the tx in the mempool 146 result.Txs_as_hex = append(result.Txs_as_hex, hex.EncodeToString(tx.Serialize())) 147 148 var related structures.Tx_Related_Info 149 150 related.Block_Height = -1 // not mined 151 related.In_pool = true 152 153 for i := 0; i < len(tx.Vout); i++ { 154 related.Output_Indices = append(related.Output_Indices, 0) // till the tx is mined we do not get indices 155 } 156 157 result.Txs = append(result.Txs, related) 158 159 continue // no more processing required 160 } 161 } 162 163 { // we could not fetch the tx, return an empty string 164 result.Txs_as_hex = append(result.Txs_as_hex, "") 165 result.Status = "TX NOT FOUND" 166 return 167 } 168 169 } 170 result.Status = "OK" 171 return 172 }