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  }