package types
import (
+ log "github.com/sirupsen/logrus"
+ "golang.org/x/crypto/sha3"
+
"github.com/vapor/consensus"
- "github.com/vapor/crypto/sha3pool"
"github.com/vapor/protocol/bc"
"github.com/vapor/protocol/vm"
"github.com/vapor/protocol/vm/vmutil"
}
spentOutputIDs := make(map[bc.Hash]bool)
+ mainchainOutputIDs := make(map[bc.Hash]bool)
for id, e := range entries {
var ord uint64
switch e := e.(type) {
- case *bc.Issuance:
+ case *bc.CrossChainInput:
ord = e.Ordinal
+ mainchainOutputIDs[*e.MainchainOutputId] = true
+ if *e.WitnessDestination.Value.AssetId == *consensus.BTMAssetID {
+ tx.GasInputIDs = append(tx.GasInputIDs, id)
+ }
case *bc.Spend:
ord = e.Ordinal
tx.GasInputIDs = append(tx.GasInputIDs, id)
}
+ case *bc.VetoInput:
+ ord = e.Ordinal
+ spentOutputIDs[*e.SpentOutputId] = true
+ if *e.WitnessDestination.Value.AssetId == *consensus.BTMAssetID {
+ tx.GasInputIDs = append(tx.GasInputIDs, id)
+ }
+
case *bc.Coinbase:
ord = 0
- case *bc.Claim:
- ord = 0
+ tx.GasInputIDs = append(tx.GasInputIDs, id)
+
default:
continue
}
for id := range spentOutputIDs {
tx.SpentOutputIDs = append(tx.SpentOutputIDs, id)
}
+ for id := range mainchainOutputIDs {
+ tx.MainchainOutputIDs = append(tx.MainchainOutputIDs, id)
+ }
return tx
}
}
var (
- spends []*bc.Spend
- issuances []*bc.Issuance
- coinbase *bc.Coinbase
- claim *bc.Claim
+ spends []*bc.Spend
+ vetoInputs []*bc.VetoInput
+ crossIns []*bc.CrossChainInput
+ coinbase *bc.Coinbase
)
muxSources := make([]*bc.ValueSource, len(tx.Inputs))
for i, input := range tx.Inputs {
switch inp := input.TypedInput.(type) {
- case *IssuanceInput:
- nonceHash := inp.NonceHash()
- assetDefHash := inp.AssetDefinitionHash()
- value := input.AssetAmount()
-
- issuance := bc.NewIssuance(&nonceHash, &value, uint64(i))
- issuance.WitnessAssetDefinition = &bc.AssetDefinition{
- Data: &assetDefHash,
- IssuanceProgram: &bc.Program{
- VmVersion: inp.VMVersion,
- Code: inp.IssuanceProgram,
- },
- }
- issuance.WitnessArguments = inp.Arguments
- issuanceID := addEntry(issuance)
-
- muxSources[i] = &bc.ValueSource{
- Ref: &issuanceID,
- Value: &value,
- }
- issuances = append(issuances, issuance)
-
case *SpendInput:
// create entry for prevout
prog := &bc.Program{VmVersion: inp.VMVersion, Code: inp.ControlProgram}
Value: &inp.AssetAmount,
Position: inp.SourcePosition,
}
- prevout := bc.NewOutput(src, prog, 0) // ordinal doesn't matter for prevouts, only for result outputs
+ prevout := bc.NewIntraChainOutput(src, prog, 0) // ordinal doesn't matter for prevouts, only for result outputs
prevoutID := addEntry(prevout)
// create entry for spend
spend := bc.NewSpend(&prevoutID, uint64(i))
coinbaseID := addEntry(coinbase)
out := tx.Outputs[0]
+ value := out.AssetAmount()
muxSources[i] = &bc.ValueSource{
Ref: &coinbaseID,
- Value: &out.AssetAmount,
+ Value: &value,
}
- case *ClaimInput:
- // create entry for prevout
+
+ case *VetoInput:
prog := &bc.Program{VmVersion: inp.VMVersion, Code: inp.ControlProgram}
src := &bc.ValueSource{
Ref: &inp.SourceID,
Value: &inp.AssetAmount,
Position: inp.SourcePosition,
}
- prevout := bc.NewOutput(src, prog, 0) // ordinal doesn't matter for prevouts, only for result outputs
+ prevout := bc.NewVoteOutput(src, prog, 0, inp.Vote) // ordinal doesn't matter for prevouts, only for result outputs
prevoutID := addEntry(prevout)
+ // create entry for VetoInput
+ vetoInput := bc.NewVetoInput(&prevoutID, uint64(i))
+ vetoInput.WitnessArguments = inp.Arguments
+ vetoVoteID := addEntry(vetoInput)
+ // setup mux
+ muxSources[i] = &bc.ValueSource{
+ Ref: &vetoVoteID,
+ Value: &inp.AssetAmount,
+ }
+ vetoInputs = append(vetoInputs, vetoInput)
+
+ case *CrossChainInput:
+ prog := &bc.Program{VmVersion: inp.VMVersion, Code: inp.ControlProgram}
+ src := &bc.ValueSource{
+ Ref: &inp.SourceID,
+ Value: &inp.AssetAmount,
+ Position: inp.SourcePosition,
+ }
+
+ prevout := bc.NewIntraChainOutput(src, prog, 0) // ordinal doesn't matter
+ outputID := bc.EntryID(prevout)
+
+ assetDefHash := bc.NewHash(sha3.Sum256(inp.AssetDefinition))
+ assetDef := &bc.AssetDefinition{
+ Data: &assetDefHash,
+ IssuanceProgram: &bc.Program{
+ VmVersion: inp.VMVersion,
+ Code: inp.IssuanceProgram,
+ },
+ }
- claim = bc.NewClaim(&prevoutID, uint64(i), input.Peginwitness)
- claim.WitnessArguments = inp.Arguments
- claimID := addEntry(claim)
+ crossIn := bc.NewCrossChainInput(&outputID, &inp.AssetAmount, prog, uint64(i), assetDef)
+ crossIn.WitnessArguments = inp.Arguments
+ crossInID := addEntry(crossIn)
muxSources[i] = &bc.ValueSource{
- Ref: &claimID,
+ Ref: &crossInID,
Value: &inp.AssetAmount,
}
+ crossIns = append(crossIns, crossIn)
}
}
// connect the inputs to the mux
for _, spend := range spends {
- spentOutput := entryMap[*spend.SpentOutputId].(*bc.Output)
+ spentOutput := entryMap[*spend.SpentOutputId].(*bc.IntraChainOutput)
spend.SetDestination(&muxID, spentOutput.Source.Value, spend.Ordinal)
}
- for _, issuance := range issuances {
- issuance.SetDestination(&muxID, issuance.Value, issuance.Ordinal)
+
+ for _, vetoInput := range vetoInputs {
+ voteOutput := entryMap[*vetoInput.SpentOutputId].(*bc.VoteOutput)
+ vetoInput.SetDestination(&muxID, voteOutput.Source.Value, vetoInput.Ordinal)
}
- if coinbase != nil {
- coinbase.SetDestination(&muxID, mux.Sources[0].Value, 0)
+ for _, crossIn := range crossIns {
+ crossIn.SetDestination(&muxID, crossIn.Value, crossIn.Ordinal)
}
- if claim != nil {
- claim.SetDestination(&muxID, mux.Sources[0].Value, 0)
+ if coinbase != nil {
+ coinbase.SetDestination(&muxID, mux.Sources[0].Value, 0)
}
// convert types.outputs to the bc.output
var resultIDs []*bc.Hash
for i, out := range tx.Outputs {
+ value := out.AssetAmount()
src := &bc.ValueSource{
Ref: &muxID,
- Value: &out.AssetAmount,
+ Value: &value,
Position: uint64(i),
}
var resultID bc.Hash
- if vmutil.IsUnspendable(out.ControlProgram) {
+ switch {
+ // must deal with retirement first due to cases' priorities in the switch statement
+ case vmutil.IsUnspendable(out.ControlProgram()):
// retirement
r := bc.NewRetirement(src, uint64(i))
resultID = addEntry(r)
- } else {
- // non-retirement
- prog := &bc.Program{out.VMVersion, out.ControlProgram}
- o := bc.NewOutput(src, prog, uint64(i))
+
+ case out.OutputType() == IntraChainOutputType:
+ // non-retirement intra-chain tx
+ prog := &bc.Program{out.VMVersion(), out.ControlProgram()}
+ o := bc.NewIntraChainOutput(src, prog, uint64(i))
+ resultID = addEntry(o)
+
+ case out.OutputType() == CrossChainOutputType:
+ // non-retirement cross-chain tx
+ prog := &bc.Program{out.VMVersion(), out.ControlProgram()}
+ o := bc.NewCrossChainOutput(src, prog, uint64(i))
resultID = addEntry(o)
+
+ case out.OutputType() == VoteOutputType:
+ // non-retirement vote tx
+ voteOut, _ := out.TypedOutput.(*VoteTxOutput)
+ prog := &bc.Program{out.VMVersion(), out.ControlProgram()}
+ o := bc.NewVoteOutput(src, prog, uint64(i), voteOut.Vote)
+ resultID = addEntry(o)
+
+ default:
+ log.Warn("unknown outType")
}
dest := &bc.ValueDestination{
resultIDs = append(resultIDs, &resultID)
mux.WitnessDestinations = append(mux.WitnessDestinations, dest)
}
- refdatahash := hashData(tx.ReferenceData)
- h := bc.NewTxHeader(tx.Version, tx.SerializedSize, &refdatahash, tx.TimeRange, resultIDs, true)
+
+ h := bc.NewTxHeader(tx.Version, tx.SerializedSize, tx.TimeRange, resultIDs)
return addEntry(h), h, entryMap
}
func mapBlockHeader(old *BlockHeader) (bc.Hash, *bc.BlockHeader) {
- bh := bc.NewBlockHeader(old.Version, old.Height, &old.PreviousBlockHash, old.Timestamp, &old.TransactionsMerkleRoot, &old.TransactionStatusHash)
+ bh := bc.NewBlockHeader(old.Version, old.Height, &old.PreviousBlockHash, old.Timestamp, &old.TransactionsMerkleRoot, &old.TransactionStatusHash, old.Witness)
return bc.EntryID(bh), bh
}
}
return b
}
-
-func hashData(data []byte) bc.Hash {
- var b32 [32]byte
- sha3pool.Sum256(b32[:], data)
- return bc.NewHash(b32)
-}