github.com/vchain-us/vcn@v0.9.11-0.20210921212052-a2484d23c0b3/pkg/cmd/inspect/lc_inspect.go (about) 1 /* 2 * Copyright (c) 2018-2020 vChain, Inc. All Rights Reserved. 3 * This software is released under GPL3. 4 * The full license information can be found under: 5 * https://www.gnu.org/licenses/gpl-3.0.en.html 6 * 7 */ 8 9 package inspect 10 11 import ( 12 "context" 13 "fmt" 14 immuschema "github.com/codenotary/immudb/pkg/api/schema" 15 "github.com/fatih/color" 16 "github.com/vchain-us/ledger-compliance-go/schema" 17 "github.com/vchain-us/vcn/pkg/api" 18 "github.com/vchain-us/vcn/pkg/cmd/internal/cli" 19 "github.com/vchain-us/vcn/pkg/cmd/internal/types" 20 "github.com/vchain-us/vcn/pkg/meta" 21 "google.golang.org/grpc/codes" 22 "google.golang.org/grpc/metadata" 23 "google.golang.org/grpc/status" 24 "math" 25 "time" 26 ) 27 28 func lcInspect(hash string, signerID string, u *api.LcUser, first, last uint64, start, end string, output string) (err error) { 29 var contextSignerID string 30 31 if signerID == "" { 32 if output == "" { 33 fmt.Println("no signer ID provided. Full history of the item is returned") 34 } 35 } else { 36 contextSignerID = signerID 37 } 38 39 results, err := GetLcResults(hash, signerID, u, first, last, start, end) 40 if err != nil { 41 if s, ok := status.FromError(err); ok { 42 if s.Code() == codes.ResourceExhausted { 43 return fmt.Errorf("too many notarizations are returned. Try to use --first or --last filter or datetime range filter") 44 } 45 } 46 return err 47 } 48 l := len(results) 49 if output == "" { 50 fmt.Printf(`current signerID `) 51 color.Set(meta.StyleAffordance()) 52 fmt.Printf("%s\n", contextSignerID) 53 color.Unset() 54 fmt.Printf(`%d notarizations found for "%s"`, l, hash) 55 fmt.Println() 56 fmt.Println() 57 } 58 59 return cli.PrintLcSlice(output, results) 60 } 61 62 func GetLcResults(hash, signerID string, u *api.LcUser, first, last uint64, start, end string) (results []*types.LcResult, err error) { 63 md := metadata.Pairs(meta.VcnLCPluginTypeHeaderName, meta.VcnLCPluginTypeHeaderValue) 64 ctx := metadata.NewOutgoingContext(context.Background(), md) 65 66 var key []byte 67 if signerID == "" { 68 key = []byte(hash) 69 } else { 70 key = api.AppendPrefix(meta.VcnPrefix, []byte(signerID)) 71 key = api.AppendSignerId(hash, key) 72 } 73 74 if start != "" || end != "" { 75 if signerID == "" { 76 key = append([]byte(meta.IndexDateRangePrefix), key...) 77 } 78 results, err = getTimeRangedResults(ctx, u, key, first, last, start, end) 79 if err != nil { 80 return nil, err 81 } 82 } else { 83 if signerID == "" { 84 results, err = getSignerResults(ctx, key, u, first, last) 85 if err != nil { 86 return nil, err 87 } 88 } else { 89 results, err = getHistoryResults(ctx, key, u, first, last) 90 if err != nil { 91 return nil, err 92 } 93 } 94 } 95 96 return results, nil 97 } 98 99 func getSignerResults(ctx context.Context, key []byte, u *api.LcUser, first, last uint64) ([]*types.LcResult, error) { 100 var err error 101 var zitems *schema.ZItemExtList 102 103 desc := false 104 var limit uint64 = 0 105 var seekKey []byte 106 107 if first > 0 { 108 limit = first 109 } 110 if last > 0 { 111 limit = last 112 desc = true 113 seekKey = make([]byte, 256) 114 for i := 0; i < 256; i++ { 115 seekKey[i] = 0xFF 116 } 117 } 118 119 zitems, err = u.Client.ZScanExt(ctx, &immuschema.ZScanRequest{ 120 Set: key, 121 SeekKey: seekKey, 122 SeekScore: math.MaxFloat64, 123 SeekAtTx: math.MaxUint64, 124 Limit: limit, 125 Desc: desc, 126 SinceTx: math.MaxUint64, 127 NoWait: true, 128 }) 129 if err != nil { 130 return nil, err 131 } 132 133 results := make([]*types.LcResult, len(zitems.Items)) 134 var i = 0 135 for _, v := range zitems.Items { 136 lca, err := api.ZItemToLcArtifact(v) 137 if err != nil { 138 results[i].AddError(err) 139 } 140 results[i] = types.NewLcResult(lca, true, nil) 141 142 i++ 143 } 144 return results, nil 145 } 146 147 func getHistoryResults(ctx context.Context, key []byte, u *api.LcUser, first, last uint64) ([]*types.LcResult, error) { 148 var err error 149 var items *schema.ItemExtList 150 151 desc := false 152 var limit uint64 = 0 153 154 if first > 0 { 155 limit = first 156 } 157 if last > 0 { 158 limit = last 159 desc = true 160 } 161 162 items, err = u.Client.HistoryExt(ctx, &immuschema.HistoryRequest{ 163 Key: key, 164 Limit: int32(limit), 165 Desc: desc, 166 }) 167 if err != nil { 168 return nil, err 169 } 170 171 results := make([]*types.LcResult, len(items.Items)) 172 var i = 0 173 for _, v := range items.Items { 174 lca, err := api.ItemToLcArtifact(v) 175 if err != nil { 176 return nil, err 177 } 178 results[i] = types.NewLcResult(lca, true, nil) 179 if err != nil { 180 results[i].AddError(err) 181 } 182 i++ 183 } 184 return results, nil 185 } 186 187 func getTimeRangedResults(ctx context.Context, u *api.LcUser, set []byte, first, last uint64, start, end string) ([]*types.LcResult, error) { 188 var err error 189 var zitems *schema.ZItemExtList 190 191 var startScore *immuschema.Score = nil 192 var endScore *immuschema.Score = nil 193 194 if start != "" { 195 timeStart, err := time.Parse(meta.DateShortForm, start) 196 if err != nil { 197 return nil, err 198 } 199 startScore = &immuschema.Score{ 200 Score: float64(timeStart.UnixNano()), // there is no precision loss. 52 bit are enough to represent seconds. 201 } 202 } 203 204 if end != "" { 205 timeEnd, err := time.Parse(meta.DateShortForm, end) 206 if err != nil { 207 return nil, err 208 } 209 endScore = &immuschema.Score{ 210 Score: float64(timeEnd.UnixNano()), // there is no precision loss. 52 bit are enough to represent seconds. 211 } 212 } 213 214 desc := false 215 216 var limit uint64 = 0 217 var seekKey []byte 218 219 if first > 0 { 220 limit = first 221 } 222 if last > 0 { 223 limit = last 224 desc = true 225 seekKey = make([]byte, 1024) 226 for i := 0; i < 1024; i++ { 227 seekKey[i] = 0xFF 228 } 229 } 230 231 zitems, err = u.Client.ZScanExt(ctx, &immuschema.ZScanRequest{ 232 Set: set, 233 SeekKey: seekKey, 234 SeekScore: math.MaxFloat64, 235 SeekAtTx: math.MaxUint64, 236 Limit: limit, 237 Desc: desc, 238 MinScore: startScore, 239 MaxScore: endScore, 240 SinceTx: math.MaxUint64, 241 NoWait: true, 242 }) 243 if err != nil { 244 return nil, err 245 } 246 247 results := make([]*types.LcResult, len(zitems.Items)) 248 var i = 0 249 for _, v := range zitems.Items { 250 lca, err := api.ZItemToLcArtifact(v) 251 if err != nil { 252 results[i].AddError(err) 253 } 254 results[i] = types.NewLcResult(lca, true, nil) 255 256 i++ 257 } 258 return results, nil 259 }