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)
41 //spentOutputIDs[*e.SpentOutputId] = true
43 if *e.WitnessDestination.Value.AssetId == *consensus.BTMAssetID {
44 tx.GasInputIDs = append(tx.GasInputIDs, id)
52 if ord >= uint64(len(oldTx.Inputs)) {
58 for id := range spentOutputIDs {
59 tx.SpentOutputIDs = append(tx.SpentOutputIDs, id)
64 func mapTx(tx *TxData) (headerID bc.Hash, hdr *bc.TxHeader, entryMap map[bc.Hash]bc.Entry) {
65 entryMap = make(map[bc.Hash]bc.Entry)
66 addEntry := func(e bc.Entry) bc.Hash {
75 issuances []*bc.Issuance
80 muxSources := make([]*bc.ValueSource, len(tx.Inputs))
81 for i, input := range tx.Inputs {
82 switch inp := input.TypedInput.(type) {
84 nonceHash := inp.NonceHash()
85 assetDefHash := inp.AssetDefinitionHash()
86 value := input.AssetAmount()
88 issuance := bc.NewIssuance(&nonceHash, &value, uint64(i))
89 issuance.WitnessAssetDefinition = &bc.AssetDefinition{
91 IssuanceProgram: &bc.Program{
92 VmVersion: inp.VMVersion,
93 Code: inp.IssuanceProgram,
96 issuance.WitnessArguments = inp.Arguments
97 issuanceID := addEntry(issuance)
99 muxSources[i] = &bc.ValueSource{
103 issuances = append(issuances, issuance)
106 // create entry for prevout
107 prog := &bc.Program{VmVersion: inp.VMVersion, Code: inp.ControlProgram}
108 src := &bc.ValueSource{
110 Value: &inp.AssetAmount,
111 Position: inp.SourcePosition,
113 prevout := bc.NewOutput(src, prog, 0) // ordinal doesn't matter for prevouts, only for result outputs
114 prevoutID := addEntry(prevout)
115 // create entry for spend
116 spend := bc.NewSpend(&prevoutID, uint64(i))
117 spend.WitnessArguments = inp.Arguments
118 spendID := addEntry(spend)
120 muxSources[i] = &bc.ValueSource{
122 Value: &inp.AssetAmount,
124 spends = append(spends, spend)
127 coinbase = bc.NewCoinbase(inp.Arbitrary)
128 coinbaseID := addEntry(coinbase)
131 muxSources[i] = &bc.ValueSource{
133 Value: &out.AssetAmount,
136 // create entry for prevout
137 prog := &bc.Program{VmVersion: inp.VMVersion, Code: inp.ControlProgram}
138 src := &bc.ValueSource{
140 Value: &inp.AssetAmount,
141 Position: inp.SourcePosition,
143 prevout := bc.NewOutput(src, prog, 0) // ordinal doesn't matter for prevouts, only for result outputs
144 prevoutID := addEntry(prevout)
146 claim = bc.NewClaim(&prevoutID, uint64(i), input.Peginwitness)
147 claim.WitnessArguments = inp.Arguments
148 claimID := addEntry(claim)
149 muxSources[i] = &bc.ValueSource{
151 Value: &inp.AssetAmount,
154 // create entry for prevout
155 prog := &bc.Program{VmVersion: inp.VMVersion, Code: inp.ControlProgram}
156 src := &bc.ValueSource{
158 Value: &inp.AssetAmount,
159 Position: inp.SourcePosition,
161 prevout := bc.NewOutput(src, prog, 0) // ordinal doesn't matter for prevouts, only for result outputs
162 prevoutID := addEntry(prevout)
163 // create entry for dpos
164 dpos := bc.NewDpos(&prevoutID, uint64(i), uint32(inp.Type), inp.Stake, inp.From, inp.To, inp.Info)
165 dpos.WitnessArguments = inp.Arguments
166 dposID := addEntry(dpos)
168 muxSources[i] = &bc.ValueSource{
170 Value: &inp.AssetAmount,
172 dposs = append(dposs, dpos)
176 mux := bc.NewMux(muxSources, &bc.Program{VmVersion: 1, Code: []byte{byte(vm.OP_TRUE)}})
177 muxID := addEntry(mux)
179 // connect the inputs to the mux
180 for _, spend := range spends {
181 spentOutput := entryMap[*spend.SpentOutputId].(*bc.Output)
182 spend.SetDestination(&muxID, spentOutput.Source.Value, spend.Ordinal)
184 for _, issuance := range issuances {
185 issuance.SetDestination(&muxID, issuance.Value, issuance.Ordinal)
188 // connect the inputs to the mux
189 for _, dpos := range dposs {
190 spentOutput := entryMap[*dpos.SpentOutputId].(*bc.Output)
191 dpos.SetDestination(&muxID, spentOutput.Source.Value, dpos.Ordinal)
195 coinbase.SetDestination(&muxID, mux.Sources[0].Value, 0)
199 claim.SetDestination(&muxID, mux.Sources[0].Value, 0)
202 // convert types.outputs to the bc.output
203 var resultIDs []*bc.Hash
204 for i, out := range tx.Outputs {
205 src := &bc.ValueSource{
207 Value: &out.AssetAmount,
211 if vmutil.IsUnspendable(out.ControlProgram) {
213 r := bc.NewRetirement(src, uint64(i))
214 resultID = addEntry(r)
218 prog := &bc.Program{out.VMVersion, out.ControlProgram}
219 o := bc.NewOutput(src, prog, uint64(i))
220 resultID = addEntry(o)
223 dest := &bc.ValueDestination{
228 resultIDs = append(resultIDs, &resultID)
229 mux.WitnessDestinations = append(mux.WitnessDestinations, dest)
231 h := bc.NewTxHeader(tx.Version, tx.SerializedSize, tx.TimeRange, resultIDs)
232 return addEntry(h), h, entryMap
235 func mapBlockHeader(old *BlockHeader) (bc.Hash, *bc.BlockHeader) {
236 proof := &bc.Proof{Sign: old.Proof.Sign, ControlProgram: old.Proof.ControlProgram}
237 bh := bc.NewBlockHeader(old.Version, old.Height, &old.PreviousBlockHash, old.Timestamp, &old.TransactionsMerkleRoot, &old.TransactionStatusHash, proof, old.Extra, old.Coinbase)
238 return bc.EntryID(bh), bh
241 // MapBlock converts a types block to bc block
242 func MapBlock(old *Block) *bc.Block {
248 b.ID, b.BlockHeader = mapBlockHeader(&old.BlockHeader)
249 for _, oldTx := range old.Transactions {
250 b.Transactions = append(b.Transactions, oldTx.Tx)