Amount uint64
SourcePos uint64
ControlProgram []byte
+ Vote []byte
AccountID string
Address string
ControlProgramIndex uint64
// connect the inputs to the mux
for _, spend := range spends {
- spentOutput := entryMap[*spend.SpentOutputId].(*bc.IntraChainOutput)
- spend.SetDestination(&muxID, spentOutput.Source.Value, spend.Ordinal)
+ switch spentOutput := entryMap[*spend.SpentOutputId].(type) {
+ case *bc.IntraChainOutput:
+ spend.SetDestination(&muxID, spentOutput.Source.Value, spend.Ordinal)
+
+ case *bc.VoteOutput:
+ spend.SetDestination(&muxID, spentOutput.Source.Value, spend.Ordinal)
+ }
}
for _, crossIn := range crossIns {
package state
import (
- "errors"
-
"github.com/vapor/consensus"
"github.com/vapor/database/storage"
+ "github.com/vapor/errors"
"github.com/vapor/protocol/bc"
)
func (view *UtxoViewpoint) ApplyTransaction(block *bc.Block, tx *bc.Tx, statusFail bool) error {
for _, prevout := range tx.SpentOutputIDs {
- spentOutput, err := tx.IntraChainOutput(prevout)
+ assetID := bc.AssetID{}
+ entryOutput, err := tx.Entry(prevout)
if err != nil {
return err
}
- if statusFail && *spentOutput.Source.Value.AssetId != *consensus.BTMAssetID {
+
+ switch output := entryOutput.(type) {
+ case *bc.IntraChainOutput:
+ assetID = *output.Source.Value.AssetId
+ case *bc.VoteOutput:
+ assetID = *output.Source.Value.AssetId
+ default:
+ return errors.Wrapf(bc.ErrEntryType, "entry %x has unexpected type %T", prevout.Bytes(), entryOutput)
+ }
+
+ if statusFail && assetID != *consensus.BTMAssetID {
continue
}
}
for _, id := range tx.TxHeader.ResultIds {
- output, err := tx.IntraChainOutput(*id)
+ assetID := bc.AssetID{}
+ entryOutput, err := tx.Entry(*id)
if err != nil {
- // error due to it's a retirement, utxo doesn't care this output type so skip it
continue
}
- if statusFail && *output.Source.Value.AssetId != *consensus.BTMAssetID {
+
+ switch output := entryOutput.(type) {
+ case *bc.IntraChainOutput:
+ assetID = *output.Source.Value.AssetId
+ case *bc.VoteOutput:
+ assetID = *output.Source.Value.AssetId
+ default:
+ // due to it's a retirement, utxo doesn't care this output type so skip it
+ continue
+ }
+
+ if statusFail && assetID != *consensus.BTMAssetID {
continue
}
func (view *UtxoViewpoint) DetachTransaction(tx *bc.Tx, statusFail bool) error {
for _, prevout := range tx.SpentOutputIDs {
- spentOutput, err := tx.IntraChainOutput(prevout)
+ assetID := bc.AssetID{}
+ entryOutput, err := tx.Entry(prevout)
if err != nil {
return err
}
- if statusFail && *spentOutput.Source.Value.AssetId != *consensus.BTMAssetID {
+
+ switch output := entryOutput.(type) {
+ case *bc.IntraChainOutput:
+ assetID = *output.Source.Value.AssetId
+ case *bc.VoteOutput:
+ assetID = *output.Source.Value.AssetId
+ default:
+ return errors.Wrapf(bc.ErrEntryType, "entry %x has unexpected type %T", prevout.Bytes(), entryOutput)
+ }
+
+ if statusFail && assetID != *consensus.BTMAssetID {
continue
}
}
for _, id := range tx.TxHeader.ResultIds {
- output, err := tx.IntraChainOutput(*id)
+ assetID := bc.AssetID{}
+ entryOutput, err := tx.Entry(*id)
if err != nil {
- // error due to it's a retirement, utxo doesn't care this output type so skip it
continue
}
- if statusFail && *output.Source.Value.AssetId != *consensus.BTMAssetID {
+
+ switch output := entryOutput.(type) {
+ case *bc.IntraChainOutput:
+ assetID = *output.Source.Value.AssetId
+ case *bc.VoteOutput:
+ assetID = *output.Source.Value.AssetId
+ default:
+ // due to it's a retirement, utxo doesn't care this output type so skip it
+ continue
+ }
+
+ if statusFail && assetID != *consensus.BTMAssetID {
continue
}
if e.SpentOutputId == nil {
return errors.Wrap(ErrMissingField, "spend without spent output ID")
}
- spentOutput, err := vs.tx.IntraChainOutput(*e.SpentOutputId)
+ var (
+ controlProgram *bc.Program
+ value *bc.AssetAmount
+ )
+ entryOutput, err := vs.tx.Entry(*e.SpentOutputId)
if err != nil {
return errors.Wrap(err, "getting spend prevout")
}
- gasLeft, err := vm.Verify(NewTxVMContext(vs, e, spentOutput.ControlProgram, e.WitnessArguments), vs.gasStatus.GasLeft)
+
+ switch output := entryOutput.(type) {
+ case *bc.IntraChainOutput:
+ controlProgram = output.ControlProgram
+ value = output.Source.Value
+ case *bc.VoteOutput:
+ controlProgram = output.ControlProgram
+ value = output.Source.Value
+ default:
+ return errors.Wrapf(bc.ErrEntryType, "entry %x has unexpected type %T", e.SpentOutputId.Bytes(), entryOutput)
+ }
+
+ gasLeft, err := vm.Verify(NewTxVMContext(vs, e, controlProgram, e.WitnessArguments), vs.gasStatus.GasLeft)
if err != nil {
return errors.Wrap(err, "checking control program")
}
if err = vs.gasStatus.updateUsage(gasLeft); err != nil {
return err
}
- eq, err := spentOutput.Source.Value.Equal(e.WitnessDestination.Value)
+
+ eq, err := value.Equal(e.WitnessDestination.Value)
if err != nil {
return err
}
return errors.WithDetailf(
ErrMismatchedValue,
"previous output is for %d unit(s) of %x, spend wants %d unit(s) of %x",
- spentOutput.Source.Value.Amount,
- spentOutput.Source.Value.AssetId.Bytes(),
+ value.Amount,
+ value.AssetId.Bytes(),
e.WitnessDestination.Value.Amount,
e.WitnessDestination.Value.AssetId.Bytes(),
)
continue
}
- resOut, err := tx.IntraChainOutput(*sp.SpentOutputId)
+ entryOutput, err := tx.Entry(*sp.SpentOutputId)
if err != nil {
- log.WithFields(log.Fields{"module": logModule, "err": err}).Error("txInToUtxos fail on get resOut")
+ log.WithFields(log.Fields{"module": logModule, "err": err}).Error("txInToUtxos fail on get entryOutput")
continue
}
- if statusFail && *resOut.Source.Value.AssetId != *consensus.BTMAssetID {
+ utxo := &account.UTXO{}
+ switch resOut := entryOutput.(type) {
+ case *bc.IntraChainOutput:
+ if statusFail && *resOut.Source.Value.AssetId != *consensus.BTMAssetID {
+ continue
+ }
+ utxo = &account.UTXO{
+ OutputID: *sp.SpentOutputId,
+ AssetID: *resOut.Source.Value.AssetId,
+ Amount: resOut.Source.Value.Amount,
+ ControlProgram: resOut.ControlProgram.Code,
+ SourceID: *resOut.Source.Ref,
+ SourcePos: resOut.Source.Position,
+ }
+
+ case *bc.VoteOutput:
+ if statusFail && *resOut.Source.Value.AssetId != *consensus.BTMAssetID {
+ continue
+ }
+ utxo = &account.UTXO{
+ OutputID: *sp.SpentOutputId,
+ AssetID: *resOut.Source.Value.AssetId,
+ Amount: resOut.Source.Value.Amount,
+ ControlProgram: resOut.ControlProgram.Code,
+ SourceID: *resOut.Source.Ref,
+ SourcePos: resOut.Source.Position,
+ Vote: resOut.Vote,
+ }
+
+ default:
+ log.WithFields(log.Fields{"module": logModule}).Error("txInToUtxos fail on get resOut")
continue
}
- utxos = append(utxos, &account.UTXO{
- OutputID: *sp.SpentOutputId,
- AssetID: *resOut.Source.Value.AssetId,
- Amount: resOut.Source.Value.Amount,
- ControlProgram: resOut.ControlProgram.Code,
- SourceID: *resOut.Source.Ref,
- SourcePos: resOut.Source.Position,
- })
+ utxos = append(utxos, utxo)
}
return utxos
}
func txOutToUtxos(tx *types.Tx, statusFail bool, vaildHeight uint64) []*account.UTXO {
utxos := []*account.UTXO{}
for i, out := range tx.Outputs {
- bcOut, err := tx.IntraChainOutput(*tx.ResultIds[i])
+ entryOutput, err := tx.Entry(*tx.ResultIds[i])
if err != nil {
+ log.WithFields(log.Fields{"module": logModule, "err": err}).Error("txOutToUtxos fail on get entryOutput")
continue
}
- if statusFail && *out.AssetAmount().AssetId != *consensus.BTMAssetID {
+ utxo := &account.UTXO{}
+ switch bcOut := entryOutput.(type) {
+ case *bc.IntraChainOutput:
+ if statusFail && *out.AssetAmount().AssetId != *consensus.BTMAssetID {
+ continue
+ }
+ utxo = &account.UTXO{
+ OutputID: *tx.OutputID(i),
+ AssetID: *out.AssetAmount().AssetId,
+ Amount: out.AssetAmount().Amount,
+ ControlProgram: out.ControlProgram(),
+ SourceID: *bcOut.Source.Ref,
+ SourcePos: bcOut.Source.Position,
+ ValidHeight: vaildHeight,
+ }
+
+ case *bc.VoteOutput:
+ if statusFail && *out.AssetAmount().AssetId != *consensus.BTMAssetID {
+ continue
+ }
+ utxo = &account.UTXO{
+ OutputID: *tx.OutputID(i),
+ AssetID: *out.AssetAmount().AssetId,
+ Amount: out.AssetAmount().Amount,
+ ControlProgram: out.ControlProgram(),
+ SourceID: *bcOut.Source.Ref,
+ SourcePos: bcOut.Source.Position,
+ ValidHeight: vaildHeight,
+ Vote: bcOut.Vote,
+ }
+
+ default:
+ log.WithFields(log.Fields{"module": logModule}).Error("txOutToUtxos fail on get bcOut")
continue
}
- utxos = append(utxos, &account.UTXO{
- OutputID: *tx.OutputID(i),
- AssetID: *out.AssetAmount().AssetId,
- Amount: out.AssetAmount().Amount,
- ControlProgram: out.ControlProgram(),
- SourceID: *bcOut.Source.Ref,
- SourcePos: bcOut.Source.Position,
- ValidHeight: vaildHeight,
- })
+ utxos = append(utxos, utxo)
}
return utxos
}
func TestGetAccountUtxos(t *testing.T) {
testDB := dbm.NewDB("testdb", "leveldb", "temp")
- defer os.RemoveAll("temp")
+ defer func() {
+ testDB.Close()
+ os.RemoveAll("temp")
+ }()
cases := []struct {
dbUtxos map[string]*account.UTXO
func TestFilterAccountUtxo(t *testing.T) {
testDB := dbm.NewDB("testdb", "leveldb", "temp")
- defer os.RemoveAll("temp")
+ defer func() {
+ testDB.Close()
+ os.RemoveAll("temp")
+ }()
cases := []struct {
dbPrograms map[string]*account.CtrlProgram
},
},
},
+ {
+ tx: types.NewTx(types.TxData{
+ Inputs: []*types.TxInput{
+ types.NewUnvoteInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 1, 1, []byte{0x51}, []byte("af594006a40837d9f028daabb6d589df0b9138daefad5683e5233c2646279217294a8d532e60863bcf196625a35fb8ceeffa3c09610eb92dcfb655a947f13269")),
+ },
+ Outputs: []*types.TxOutput{
+ types.NewIntraChainOutput(bc.AssetID{V0: 1}, 1, []byte{0x51}),
+ },
+ }),
+ statusFail: false,
+ wantUtxos: []*account.UTXO{
+ &account.UTXO{
+ OutputID: bc.NewHash([32]byte{0x95, 0x23, 0x06, 0xa5, 0x2f, 0xc4, 0xe2, 0x36, 0x03, 0x0f, 0xe3, 0xe6, 0xb8, 0x0b, 0xcc, 0x3c, 0x1e, 0x17, 0x3e, 0x25, 0x95, 0xd0, 0xbf, 0x08, 0x11, 0x73, 0x06, 0xd4, 0x64, 0x9c, 0xfb, 0x3b}),
+ AssetID: bc.AssetID{V0: 1},
+ Amount: 1,
+ ControlProgram: []byte{0x51},
+ Vote: []byte("af594006a40837d9f028daabb6d589df0b9138daefad5683e5233c2646279217294a8d532e60863bcf196625a35fb8ceeffa3c09610eb92dcfb655a947f13269"),
+ SourceID: bc.Hash{V0: 1},
+ SourcePos: 1,
+ },
+ },
+ },
}
for i, c := range cases {