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 }