github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/contract/instance.go (about)

     1  package contract
     2  
     3  import (
     4  	"github.com/bytom/bytom/protocol/bc"
     5  	"github.com/bytom/bytom/protocol/bc/types"
     6  	"github.com/google/uuid"
     7  )
     8  
     9  type Status uint8
    10  
    11  const (
    12  	Lagging Status = iota + 1
    13  	InSync
    14  	Ended
    15  	OffChain
    16  )
    17  
    18  type TreeNode struct {
    19  	TxHash   bc.Hash     `json:"tx_hash"`
    20  	UTXOs    []*UTXO     `json:"utxos"`
    21  	Children []*TreeNode `json:"children"`
    22  }
    23  
    24  type Instance struct {
    25  	TraceID       string   `json:"trace_id"`
    26  	UTXOs         []*UTXO  `json:"utxos"`
    27  	TxHash        *bc.Hash `json:"tx_hash"`
    28  	Status        Status   `json:"status"`
    29  	EndedHeight   uint64   `json:"ended_height"`
    30  	ScannedHash   bc.Hash  `json:"scanned_hash"`
    31  	ScannedHeight uint64   `json:"scanned_height"`
    32  	Unconfirmed   []*TreeNode
    33  }
    34  
    35  func newInstance(t *transfer, block *types.Block) *Instance {
    36  	inst := &Instance{
    37  		TraceID:       uuid.New().String(),
    38  		TxHash:        &t.txHash,
    39  		UTXOs:         t.outUTXOs,
    40  		Status:        Lagging,
    41  		ScannedHeight: block.Height,
    42  		ScannedHash:   block.Hash(),
    43  	}
    44  	if len(t.outUTXOs) == 0 {
    45  		inst.Status = Ended
    46  		inst.UTXOs = t.inUTXOs
    47  	}
    48  	return inst
    49  }
    50  
    51  func (i *Instance) transferTo(t *transfer, blockHeight uint64) *Instance {
    52  	inst := &Instance{
    53  		TraceID:     i.TraceID,
    54  		Status:      i.Status,
    55  		Unconfirmed: i.Unconfirmed,
    56  		UTXOs:       t.outUTXOs,
    57  		TxHash:      &t.txHash,
    58  	}
    59  	if len(t.outUTXOs) == 0 {
    60  		inst.Status = Ended
    61  		inst.EndedHeight = blockHeight
    62  		inst.UTXOs = t.inUTXOs
    63  	}
    64  	inst.confirmTx(t.txHash)
    65  	return inst
    66  }
    67  
    68  func (i *Instance) rollbackTo(t *transfer) *Instance {
    69  	return &Instance{
    70  		TraceID:     i.TraceID,
    71  		Status:      InSync,
    72  		UTXOs:       t.inUTXOs,
    73  		TxHash:      nil,
    74  		Unconfirmed: nil,
    75  	}
    76  }
    77  
    78  func (i *Instance) confirmTx(txHash bc.Hash) {
    79  	for _, node := range i.Unconfirmed {
    80  		if node.TxHash == txHash {
    81  			i.Unconfirmed = node.Children
    82  			return
    83  		}
    84  	}
    85  	i.Unconfirmed = nil
    86  }
    87  
    88  type instanceIndex struct {
    89  	traceIdToInst  map[string]*Instance
    90  	utxoHashToInst map[bc.Hash]*Instance
    91  }
    92  
    93  func newInstanceIndex() *instanceIndex {
    94  	return &instanceIndex{
    95  		traceIdToInst:  make(map[string]*Instance),
    96  		utxoHashToInst: make(map[bc.Hash]*Instance),
    97  	}
    98  }
    99  
   100  func (i *instanceIndex) getAll() []*Instance {
   101  	var instances []*Instance
   102  	for _, inst := range i.traceIdToInst {
   103  		instances = append(instances, inst)
   104  	}
   105  	return instances
   106  }
   107  
   108  func (i *instanceIndex) getByID(traceID string) *Instance {
   109  	return i.traceIdToInst[traceID]
   110  }
   111  
   112  func (i *instanceIndex) getByUTXO(utxoHash bc.Hash) *Instance {
   113  	return i.utxoHashToInst[utxoHash]
   114  }
   115  
   116  func (i *instanceIndex) add(instance *Instance) {
   117  	i.traceIdToInst[instance.TraceID] = instance
   118  	for _, utxo := range instance.UTXOs {
   119  		i.utxoHashToInst[utxo.Hash] = instance
   120  	}
   121  }
   122  
   123  func (i *instanceIndex) save(newInst *Instance) {
   124  	i.remove(newInst.TraceID)
   125  	i.add(newInst)
   126  }
   127  
   128  func (i *instanceIndex) remove(id string) {
   129  	if inst, ok := i.traceIdToInst[id]; ok {
   130  		delete(i.traceIdToInst, id)
   131  		for _, utxo := range inst.UTXOs {
   132  			delete(i.utxoHashToInst, utxo.Hash)
   133  		}
   134  	}
   135  }
   136  
   137  type UTXO struct {
   138  	Hash      bc.Hash    `json:"hash"`
   139  	AssetID   bc.AssetID `json:"asset_id"`
   140  	Amount    uint64     `json:"amount"`
   141  	Program   []byte     `json:"program"`
   142  	SourceID  bc.Hash    `json:"source_id"`
   143  	SourcePos uint64     `json:"source_pos"`
   144  	StateData [][]byte   `json:"state_data"`
   145  }
   146  
   147  func inputToUTXO(tx *types.Tx, index int) *UTXO {
   148  	input := tx.Inputs[index]
   149  	outputID, _ := input.SpentOutputID()
   150  	spendInput := input.TypedInput.(*types.SpendInput)
   151  	return &UTXO{
   152  		Hash:      outputID,
   153  		AssetID:   input.AssetID(),
   154  		Amount:    input.Amount(),
   155  		Program:   input.ControlProgram(),
   156  		SourceID:  spendInput.SourceID,
   157  		SourcePos: spendInput.SourcePosition,
   158  		StateData: spendInput.StateData,
   159  	}
   160  }
   161  
   162  func outputToUTXO(tx *types.Tx, index int) *UTXO {
   163  	output := tx.Outputs[index]
   164  	outputID := tx.OutputID(index)
   165  	originalOutput, _ := tx.OriginalOutput(*outputID)
   166  	return &UTXO{
   167  		Hash:      *outputID,
   168  		AssetID:   *output.AssetId,
   169  		Amount:    output.Amount,
   170  		Program:   output.ControlProgram,
   171  		SourceID:  *originalOutput.Source.Ref,
   172  		SourcePos: uint64(index),
   173  		StateData: originalOutput.StateData,
   174  	}
   175  }