4 "github.com/vapor/consensus"
5 "github.com/vapor/crypto/sha3pool"
6 "github.com/vapor/protocol/bc"
7 "github.com/vapor/protocol/vm"
8 "github.com/vapor/protocol/vm/vmutil"
11 // MapTx converts a types TxData object into its entries-based
13 func MapTx(oldTx *TxData) *bc.Tx {
14 txID, txHeader, entries := mapTx(oldTx)
19 InputIDs: make([]bc.Hash, len(oldTx.Inputs)),
22 spentOutputIDs := make(map[bc.Hash]bool)
23 for id, e := range entries {
25 switch e := e.(type) {
31 spentOutputIDs[*e.SpentOutputId] = true
32 if *e.WitnessDestination.Value.AssetId == *consensus.BTMAssetID {
33 tx.GasInputIDs = append(tx.GasInputIDs, id)
42 //spentOutputIDs[*e.SpentOutputId] = true
44 if *e.WitnessDestination.Value.AssetId == *consensus.BTMAssetID {
45 tx.GasInputIDs = append(tx.GasInputIDs, id)
53 if ord >= uint64(len(oldTx.Inputs)) {
59 for id := range spentOutputIDs {
60 tx.SpentOutputIDs = append(tx.SpentOutputIDs, id)
65 func mapTx(tx *TxData) (headerID bc.Hash, hdr *bc.TxHeader, entryMap map[bc.Hash]bc.Entry) {
66 entryMap = make(map[bc.Hash]bc.Entry)
67 addEntry := func(e bc.Entry) bc.Hash {
76 issuances []*bc.Issuance
81 muxSources := make([]*bc.ValueSource, len(tx.Inputs))
82 for i, input := range tx.Inputs {
83 switch inp := input.TypedInput.(type) {
85 nonceHash := inp.NonceHash()
86 assetDefHash := inp.AssetDefinitionHash()
87 value := input.AssetAmount()
89 issuance := bc.NewIssuance(&nonceHash, &value, uint64(i))
90 issuance.WitnessAssetDefinition = &bc.AssetDefinition{
92 IssuanceProgram: &bc.Program{
93 VmVersion: inp.VMVersion,
94 Code: inp.IssuanceProgram,
97 issuance.WitnessArguments = inp.Arguments
98 issuanceID := addEntry(issuance)
100 muxSources[i] = &bc.ValueSource{
104 issuances = append(issuances, issuance)
107 // create entry for prevout
108 prog := &bc.Program{VmVersion: inp.VMVersion, Code: inp.ControlProgram}
109 src := &bc.ValueSource{
111 Value: &inp.AssetAmount,
112 Position: inp.SourcePosition,
114 prevout := bc.NewOutput(src, prog, 0) // ordinal doesn't matter for prevouts, only for result outputs
115 prevoutID := addEntry(prevout)
116 // create entry for spend
117 spend := bc.NewSpend(&prevoutID, uint64(i))
118 spend.WitnessArguments = inp.Arguments
119 spendID := addEntry(spend)
121 muxSources[i] = &bc.ValueSource{
123 Value: &inp.AssetAmount,
125 spends = append(spends, spend)
128 coinbase = bc.NewCoinbase(inp.Arbitrary)
129 coinbaseID := addEntry(coinbase)
132 muxSources[i] = &bc.ValueSource{
134 Value: &out.AssetAmount,
137 // create entry for prevout
138 prog := &bc.Program{VmVersion: inp.VMVersion, Code: inp.ControlProgram}
139 src := &bc.ValueSource{
141 Value: &inp.AssetAmount,
142 Position: inp.SourcePosition,
144 prevout := bc.NewOutput(src, prog, 0) // ordinal doesn't matter for prevouts, only for result outputs
145 prevoutID := addEntry(prevout)
147 claim = bc.NewClaim(&prevoutID, uint64(i), input.Peginwitness)
148 claim.WitnessArguments = inp.Arguments
149 claimID := addEntry(claim)
150 muxSources[i] = &bc.ValueSource{
152 Value: &inp.AssetAmount,
155 // create entry for prevout
156 prog := &bc.Program{VmVersion: inp.VMVersion, Code: inp.ControlProgram}
157 src := &bc.ValueSource{
159 Value: &inp.AssetAmount,
160 Position: inp.SourcePosition,
162 prevout := bc.NewOutput(src, prog, 0) // ordinal doesn't matter for prevouts, only for result outputs
163 prevoutID := addEntry(prevout)
164 // create entry for dpos
165 dpos := bc.NewDpos(&prevoutID, uint64(i), uint32(inp.Type), inp.Stake, inp.From, inp.To, inp.Info)
166 dpos.WitnessArguments = inp.Arguments
167 dposID := addEntry(dpos)
169 muxSources[i] = &bc.ValueSource{
171 Value: &inp.AssetAmount,
173 dposs = append(dposs, dpos)
177 mux := bc.NewMux(muxSources, &bc.Program{VmVersion: 1, Code: []byte{byte(vm.OP_TRUE)}})
178 muxID := addEntry(mux)
180 // connect the inputs to the mux
181 for _, spend := range spends {
182 spentOutput := entryMap[*spend.SpentOutputId].(*bc.Output)
183 spend.SetDestination(&muxID, spentOutput.Source.Value, spend.Ordinal)
185 for _, issuance := range issuances {
186 issuance.SetDestination(&muxID, issuance.Value, issuance.Ordinal)
189 // connect the inputs to the mux
190 for _, dpos := range dposs {
191 spentOutput := entryMap[*dpos.SpentOutputId].(*bc.Output)
192 dpos.SetDestination(&muxID, spentOutput.Source.Value, dpos.Ordinal)
196 coinbase.SetDestination(&muxID, mux.Sources[0].Value, 0)
200 claim.SetDestination(&muxID, mux.Sources[0].Value, 0)
203 // convert types.outputs to the bc.output
204 var resultIDs []*bc.Hash
205 for i, out := range tx.Outputs {
206 src := &bc.ValueSource{
208 Value: &out.AssetAmount,
212 if vmutil.IsUnspendable(out.ControlProgram) {
214 r := bc.NewRetirement(src, uint64(i))
215 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 refdatahash := hashData(tx.ReferenceData)
232 h := bc.NewTxHeader(tx.Version, tx.SerializedSize, &refdatahash, tx.TimeRange, resultIDs)
233 return addEntry(h), h, entryMap
236 func mapBlockHeader(old *BlockHeader) (bc.Hash, *bc.BlockHeader) {
237 proof := &bc.Proof{Sign: old.Proof.Sign, ControlProgram: old.Proof.ControlProgram}
238 bh := bc.NewBlockHeader(old.Version, old.Height, &old.PreviousBlockHash, old.Timestamp, &old.TransactionsMerkleRoot, &old.TransactionStatusHash, proof, old.Extra, old.Coinbase)
239 return bc.EntryID(bh), bh
242 // MapBlock converts a types block to bc block
243 func MapBlock(old *Block) *bc.Block {
249 b.ID, b.BlockHeader = mapBlockHeader(&old.BlockHeader)
250 for _, oldTx := range old.Transactions {
251 b.Transactions = append(b.Transactions, oldTx.Tx)
256 func hashData(data []byte) bc.Hash {
258 sha3pool.Sum256(b32[:], data)
259 return bc.NewHash(b32)