4 "github.com/vapor/consensus"
5 "github.com/vapor/protocol/bc"
6 "github.com/vapor/protocol/vm"
7 "github.com/vapor/protocol/vm/vmutil"
10 // MapTx converts a types TxData object into its entries-based
12 func MapTx(oldTx *TxData) *bc.Tx {
13 txID, txHeader, entries := mapTx(oldTx)
18 InputIDs: make([]bc.Hash, len(oldTx.Inputs)),
21 spentOutputIDs := make(map[bc.Hash]bool)
22 for id, e := range entries {
24 switch e := e.(type) {
30 spentOutputIDs[*e.SpentOutputId] = true
31 if *e.WitnessDestination.Value.AssetId == *consensus.BTMAssetID {
32 tx.GasInputIDs = append(tx.GasInputIDs, id)
43 if ord >= uint64(len(oldTx.Inputs)) {
49 for id := range spentOutputIDs {
50 tx.SpentOutputIDs = append(tx.SpentOutputIDs, id)
55 func mapTx(tx *TxData) (headerID bc.Hash, hdr *bc.TxHeader, entryMap map[bc.Hash]bc.Entry) {
56 entryMap = make(map[bc.Hash]bc.Entry)
57 addEntry := func(e bc.Entry) bc.Hash {
65 issuances []*bc.Issuance
70 muxSources := make([]*bc.ValueSource, len(tx.Inputs))
71 for i, input := range tx.Inputs {
72 switch inp := input.TypedInput.(type) {
74 nonceHash := inp.NonceHash()
75 assetDefHash := inp.AssetDefinitionHash()
76 value := input.AssetAmount()
78 issuance := bc.NewIssuance(&nonceHash, &value, uint64(i))
79 issuance.WitnessAssetDefinition = &bc.AssetDefinition{
81 IssuanceProgram: &bc.Program{
82 VmVersion: inp.VMVersion,
83 Code: inp.IssuanceProgram,
86 issuance.WitnessArguments = inp.Arguments
87 issuanceID := addEntry(issuance)
89 muxSources[i] = &bc.ValueSource{
93 issuances = append(issuances, issuance)
96 // create entry for prevout
97 prog := &bc.Program{VmVersion: inp.VMVersion, Code: inp.ControlProgram}
98 src := &bc.ValueSource{
100 Value: &inp.AssetAmount,
101 Position: inp.SourcePosition,
103 prevout := bc.NewOutput(src, prog, 0) // ordinal doesn't matter for prevouts, only for result outputs
104 prevoutID := addEntry(prevout)
105 // create entry for spend
106 spend := bc.NewSpend(&prevoutID, uint64(i))
107 spend.WitnessArguments = inp.Arguments
108 spendID := addEntry(spend)
110 muxSources[i] = &bc.ValueSource{
112 Value: &inp.AssetAmount,
114 spends = append(spends, spend)
117 coinbase = bc.NewCoinbase(inp.Arbitrary)
118 coinbaseID := addEntry(coinbase)
121 muxSources[i] = &bc.ValueSource{
123 Value: &out.AssetAmount,
126 // create entry for prevout
127 prog := &bc.Program{VmVersion: inp.VMVersion, Code: inp.ControlProgram}
128 src := &bc.ValueSource{
130 Value: &inp.AssetAmount,
131 Position: inp.SourcePosition,
133 prevout := bc.NewOutput(src, prog, 0) // ordinal doesn't matter for prevouts, only for result outputs
134 prevoutID := addEntry(prevout)
136 claim = bc.NewClaim(&prevoutID, uint64(i), input.Peginwitness)
137 claim.WitnessArguments = inp.Arguments
138 claimID := addEntry(claim)
139 muxSources[i] = &bc.ValueSource{
141 Value: &inp.AssetAmount,
146 mux := bc.NewMux(muxSources, &bc.Program{VmVersion: 1, Code: []byte{byte(vm.OP_TRUE)}})
147 muxID := addEntry(mux)
149 // connect the inputs to the mux
150 for _, spend := range spends {
151 spentOutput := entryMap[*spend.SpentOutputId].(*bc.Output)
152 spend.SetDestination(&muxID, spentOutput.Source.Value, spend.Ordinal)
154 for _, issuance := range issuances {
155 issuance.SetDestination(&muxID, issuance.Value, issuance.Ordinal)
159 coinbase.SetDestination(&muxID, mux.Sources[0].Value, 0)
163 claim.SetDestination(&muxID, mux.Sources[0].Value, 0)
166 // convert types.outputs to the bc.output
167 var resultIDs []*bc.Hash
168 for i, out := range tx.Outputs {
169 src := &bc.ValueSource{
171 Value: &out.AssetAmount,
175 if vmutil.IsUnspendable(out.ControlProgram) {
177 r := bc.NewRetirement(src, uint64(i))
178 resultID = addEntry(r)
181 prog := &bc.Program{out.VMVersion, out.ControlProgram}
182 o := bc.NewOutput(src, prog, uint64(i))
183 resultID = addEntry(o)
186 dest := &bc.ValueDestination{
191 resultIDs = append(resultIDs, &resultID)
192 mux.WitnessDestinations = append(mux.WitnessDestinations, dest)
194 h := bc.NewTxHeader(tx.Version, tx.SerializedSize, tx.TimeRange, resultIDs)
195 return addEntry(h), h, entryMap
198 func mapBlockHeader(old *BlockHeader) (bc.Hash, *bc.BlockHeader) {
199 proof := &bc.Proof{Sign: old.Proof.Sign, ControlProgram: old.Proof.ControlProgram}
200 bh := bc.NewBlockHeader(old.Version, old.Height, &old.PreviousBlockHash, old.Timestamp, &old.TransactionsMerkleRoot, &old.TransactionStatusHash, proof)
201 return bc.EntryID(bh), bh
204 // MapBlock converts a types block to bc block
205 func MapBlock(old *Block) *bc.Block {
211 b.ID, b.BlockHeader = mapBlockHeader(&old.BlockHeader)
212 for _, oldTx := range old.Transactions {
213 b.Transactions = append(b.Transactions, oldTx.Tx)