m.Handle("/get-coinbase-arbitrary", jsonHandler(a.getCoinbaseArbitrary))
m.Handle("/set-coinbase-arbitrary", jsonHandler(a.setCoinbaseArbitrary))
- m.Handle("/create-asset", jsonHandler(a.createAsset))
m.Handle("/update-asset-alias", jsonHandler(a.updateAssetAlias))
m.Handle("/get-asset", jsonHandler(a.getAsset))
m.Handle("/list-assets", jsonHandler(a.listAssets))
package api
-import (
- "context"
- "strings"
-
- "github.com/vapor/asset"
- "github.com/vapor/crypto/ed25519/chainkd"
- chainjson "github.com/vapor/encoding/json"
-
- log "github.com/sirupsen/logrus"
-)
-
-// POST /create-asset
-func (a *API) createAsset(ctx context.Context, ins struct {
- Alias string `json:"alias"`
- RootXPubs []chainkd.XPub `json:"root_xpubs"`
- Quorum int `json:"quorum"`
- Definition map[string]interface{} `json:"definition"`
- LimitHeight int64 `json:"limit_height"`
- IssuanceProgram chainjson.HexBytes `json:"issuance_program"`
-}) Response {
- ass, err := a.wallet.AssetReg.Define(
- ins.RootXPubs,
- ins.Quorum,
- ins.Definition,
- ins.LimitHeight,
- strings.ToUpper(strings.TrimSpace(ins.Alias)),
- ins.IssuanceProgram,
- )
- if err != nil {
- return NewErrorResponse(err)
- }
-
- annotatedAsset, err := asset.Annotated(ass)
- if err != nil {
- return NewErrorResponse(err)
- }
-
- log.WithField("asset ID", annotatedAsset.ID.String()).Info("Created asset")
-
- return NewSuccessResponse(annotatedAsset)
-}
-
// POST /update-asset-alias
func (a *API) updateAssetAlias(updateAlias struct {
ID string `json:"id"`
decoders := map[string]func([]byte) (txbuilder.Action, error){
"control_address": txbuilder.DecodeControlAddressAction,
"control_program": txbuilder.DecodeControlProgramAction,
- "issue": a.wallet.AssetReg.DecodeIssueAction,
"retire": txbuilder.DecodeRetireAction,
"spend_account": a.wallet.AccountMgr.DecodeSpendAction,
"spend_account_unspent_output": a.wallet.AccountMgr.DecodeSpendUTXOAction,
"context"
"github.com/vapor/account"
- "github.com/vapor/asset"
"github.com/vapor/blockchain/pseudohsm"
"github.com/vapor/crypto/ed25519/chainkd"
"github.com/vapor/errors"
// WalletImage hold the ziped wallet data
type WalletImage struct {
AccountImage *account.Image `json:"account_image"`
- AssetImage *asset.Image `json:"asset_image"`
KeyImages *pseudohsm.KeyImage `json:"key_images"`
}
if err := a.wallet.Hsm.Restore(image.KeyImages); err != nil {
return NewErrorResponse(errors.Wrap(err, "restore key images"))
}
- if err := a.wallet.AssetReg.Restore(image.AssetImage); err != nil {
- return NewErrorResponse(errors.Wrap(err, "restore asset image"))
- }
if err := a.wallet.AccountMgr.Restore(image.AccountImage); err != nil {
return NewErrorResponse(errors.Wrap(err, "restore account image"))
}
if err != nil {
return NewErrorResponse(errors.Wrap(err, "backup key images"))
}
- assetImage, err := a.wallet.AssetReg.Backup()
- if err != nil {
- return NewErrorResponse(errors.Wrap(err, "backup asset image"))
- }
accountImage, err := a.wallet.AccountMgr.Backup()
if err != nil {
return NewErrorResponse(errors.Wrap(err, "backup account image"))
image := &WalletImage{
KeyImages: keyImages,
- AssetImage: assetImage,
AccountImage: accountImage,
}
return NewSuccessResponse(image)
"encoding/json"
"github.com/vapor/blockchain/query"
- chainjson "github.com/vapor/encoding/json"
- "github.com/vapor/protocol/vm/vmutil"
)
func isValidJSON(b []byte) bool {
VMVersion: a.VMVersion,
RawDefinitionByte: a.RawDefinitionByte,
Definition: &jsonDefinition,
- IssuanceProgram: chainjson.HexBytes(a.IssuanceProgram),
}
- annotatedAsset.LimitHeight = vmutil.GetIssuanceProgramRestrictHeight(a.IssuanceProgram)
- if a.Signer != nil {
- annotatedAsset.AnnotatedSigner = query.AnnotatedSigner{
- Type: a.Signer.Type,
- XPubs: a.Signer.XPubs,
- Quorum: a.Signer.Quorum,
- KeyIndex: a.Signer.KeyIndex,
- DeriveRule: a.Signer.DeriveRule,
- }
- }
return annotatedAsset, nil
}
"sync"
"github.com/golang/groupcache/lru"
- "golang.org/x/crypto/sha3"
- "github.com/vapor/blockchain/signers"
- "github.com/vapor/common"
"github.com/vapor/consensus"
- "github.com/vapor/crypto/ed25519"
- "github.com/vapor/crypto/ed25519/chainkd"
dbm "github.com/vapor/database/leveldb"
chainjson "github.com/vapor/encoding/json"
"github.com/vapor/errors"
"github.com/vapor/protocol"
"github.com/vapor/protocol/bc"
- "github.com/vapor/protocol/vm/vmutil"
)
// DefaultNativeAsset native BTM asset
)
func initNativeAsset() {
- signer := &signers.Signer{Type: "internal"}
alias := consensus.BTMAlias
definitionBytes, _ := serializeAssetDef(consensus.BTMDefinitionMap)
DefaultNativeAsset = &Asset{
- Signer: signer,
AssetID: *consensus.BTMAssetID,
Alias: &alias,
VMVersion: 1,
//Asset describe asset on bytom chain
type Asset struct {
- *signers.Signer
AssetID bc.AssetID `json:"id"`
Alias *string `json:"alias"`
VMVersion uint64 `json:"vm_version"`
- IssuanceProgram chainjson.HexBytes `json:"issue_program"`
RawDefinitionByte chainjson.HexBytes `json:"raw_definition_byte"`
DefinitionMap map[string]interface{} `json:"definition"`
}
-func (reg *Registry) getNextAssetIndex() uint64 {
- reg.assetIndexMu.Lock()
- defer reg.assetIndexMu.Unlock()
-
- nextIndex := uint64(1)
- if rawIndex := reg.db.Get(assetIndexKey); rawIndex != nil {
- nextIndex = common.BytesToUnit64(rawIndex) + 1
- }
-
- reg.db.Set(assetIndexKey, common.Unit64ToBytes(nextIndex))
- return nextIndex
-}
-
-// Define defines a new Asset.
-func (reg *Registry) Define(xpubs []chainkd.XPub, quorum int, definition map[string]interface{}, limitHeight int64, alias string, issuanceProgram chainjson.HexBytes) (*Asset, error) {
- var err error
- var assetSigner *signers.Signer
-
- alias = strings.ToUpper(strings.TrimSpace(alias))
- if alias == "" {
- return nil, errors.Wrap(ErrNullAlias)
- }
-
- if alias == consensus.BTMAlias {
- return nil, ErrInternalAsset
- }
-
- rawDefinition, err := serializeAssetDef(definition)
- if err != nil {
- return nil, ErrSerializing
- }
-
- vmver := uint64(1)
- if len(issuanceProgram) == 0 {
- if len(xpubs) == 0 {
- return nil, errors.Wrap(signers.ErrNoXPubs)
- }
-
- nextAssetIndex := reg.getNextAssetIndex()
- assetSigner, err = signers.Create("asset", xpubs, quorum, nextAssetIndex, signers.BIP0032)
- if err != nil {
- return nil, err
- }
-
- path := signers.GetBip0032Path(assetSigner, signers.AssetKeySpace)
- derivedXPubs := chainkd.DeriveXPubs(assetSigner.XPubs, path)
- derivedPKs := chainkd.XPubKeys(derivedXPubs)
- issuanceProgram, vmver, err = multisigIssuanceProgram(derivedPKs, assetSigner.Quorum, limitHeight)
- if err != nil {
- return nil, err
- }
- }
-
- defHash := bc.NewHash(sha3.Sum256(rawDefinition))
- a := &Asset{
- DefinitionMap: definition,
- RawDefinitionByte: rawDefinition,
- VMVersion: vmver,
- IssuanceProgram: issuanceProgram,
- AssetID: bc.ComputeAssetID(issuanceProgram, vmver, &defHash),
- Signer: assetSigner,
- Alias: &alias,
- }
- return a, reg.SaveAsset(a, alias)
-}
-
// SaveAsset store asset
func (reg *Registry) SaveAsset(a *Asset, alias string) error {
reg.assetMu.Lock()
return json.MarshalIndent(def, "", " ")
}
-func multisigIssuanceProgram(pubkeys []ed25519.PublicKey, nrequired int, blockHeight int64) (program []byte, vmversion uint64, err error) {
- issuanceProg, err := vmutil.P2SPMultiSigProgramWithHeight(pubkeys, nrequired, blockHeight)
- if err != nil {
- return nil, 0, err
- }
- builder := vmutil.NewBuilder()
- builder.AddRawBytes(issuanceProg)
- prog, err := builder.Build()
- return prog, 1, err
-}
-
//UpdateAssetAlias updates asset alias
func (reg *Registry) UpdateAssetAlias(id, newAlias string) error {
oldAlias := reg.GetAliasByID(id)
+++ /dev/null
-package asset
-
-import (
- "context"
- "io/ioutil"
- "os"
- "reflect"
- "sort"
- "strings"
- "testing"
-
- "github.com/vapor/consensus"
- "github.com/vapor/crypto/ed25519/chainkd"
- "github.com/vapor/database"
- dbm "github.com/vapor/database/leveldb"
- "github.com/vapor/event"
- "github.com/vapor/protocol"
- "github.com/vapor/testutil"
-)
-
-func TestDefineAssetWithLowercase(t *testing.T) {
- reg := mockNewRegistry(t)
- alias := "lower"
- asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, 0, alias, nil)
- if err != nil {
- t.Fatal(err)
- }
- if *asset.Alias != strings.ToUpper(alias) {
- t.Fatal("created asset alias should be uppercase")
- }
-}
-
-func TestDefineAssetWithSpaceTrimed(t *testing.T) {
- reg := mockNewRegistry(t)
- alias := " WITH SPACE "
- asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, 0, alias, nil)
- if err != nil {
- t.Fatal(err)
- }
- if *asset.Alias != strings.TrimSpace(alias) {
- t.Fatal("created asset alias should be uppercase")
- }
-}
-
-func TestDefineAsset(t *testing.T) {
- ctx := context.Background()
- reg := mockNewRegistry(t)
- asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, 0, "asset-alias", nil)
- if err != nil {
- testutil.FatalErr(t, err)
- }
-
- limitAsset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, 100, "limit-asset", nil)
- if err != nil {
- testutil.FatalErr(t, err)
- }
-
- assets := []*Asset{asset, limitAsset}
- for _, ass := range assets {
- found, err := reg.FindByID(ctx, &ass.AssetID)
- if err != nil {
- t.Errorf("unexpected error %v", err)
- }
-
- if !testutil.DeepEqual(ass, found) {
- t.Errorf("expected asset %v to be recorded as %v", ass, found)
- }
- }
-}
-
-func TestDefineBtmAsset(t *testing.T) {
- reg := mockNewRegistry(t)
- _, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, 0, consensus.BTMAlias, nil)
- if err == nil {
- testutil.FatalErr(t, err)
- }
-}
-
-func TestFindAssetByID(t *testing.T) {
- ctx := context.Background()
- reg := mockNewRegistry(t)
- keys := []chainkd.XPub{testutil.TestXPub}
- asset, err := reg.Define(keys, 1, nil, 0, "TESTASSET", nil)
- if err != nil {
- testutil.FatalErr(t, err)
-
- }
- found, err := reg.FindByID(ctx, &asset.AssetID)
- if err != nil {
- testutil.FatalErr(t, err)
- }
-
- if !testutil.DeepEqual(asset, found) {
- t.Errorf("expected %v and %v to match", asset, found)
- }
-}
-
-func TestUpdateAssetAlias(t *testing.T) {
- reg := mockNewRegistry(t)
-
- oldAlias := "OLD_ALIAS"
- newAlias := "NEW_ALIAS"
-
- asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, 0, oldAlias, nil)
- if err != nil {
- testutil.FatalErr(t, err)
- }
-
- if reg.UpdateAssetAlias(asset.AssetID.String(), newAlias) != nil {
- testutil.FatalErr(t, err)
- }
-
- asset1, err := reg.FindByAlias(newAlias)
- if err != nil {
- testutil.FatalErr(t, err)
- }
-
- gotAlias := *asset1.Alias
- if !reflect.DeepEqual(gotAlias, newAlias) {
- t.Fatalf("alias:\ngot: %v\nwant: %v", gotAlias, newAlias)
- }
-}
-
-type SortByAssetsAlias []*Asset
-
-func (a SortByAssetsAlias) Len() int { return len(a) }
-func (a SortByAssetsAlias) Less(i, j int) bool {
- return strings.Compare(*a[i].Alias, *a[j].Alias) <= 0
-}
-func (a SortByAssetsAlias) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
-
-func TestListAssets(t *testing.T) {
- reg := mockNewRegistry(t)
-
- firstAlias := "FIRST_ALIAS"
- secondAlias := "SECOND_ALIAS"
-
- firstAsset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, 0, firstAlias, nil)
- if err != nil {
- testutil.FatalErr(t, err)
- }
-
- secondAsset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, 0, secondAlias, nil)
- if err != nil {
- testutil.FatalErr(t, err)
- }
-
- wantAssets := []*Asset{DefaultNativeAsset, firstAsset, secondAsset}
-
- gotAssets, err := reg.ListAssets("")
- if err != nil {
- testutil.FatalErr(t, err)
- }
- sort.Sort(SortByAssetsAlias(wantAssets))
- sort.Sort(SortByAssetsAlias(gotAssets))
- if !testutil.DeepEqual(gotAssets, wantAssets) {
- t.Fatalf("got:\ngot: %v\nwant: %v", gotAssets, wantAssets)
- }
-}
-
-func mockChain(testDB dbm.DB) (*protocol.Chain, error) {
- store := database.NewStore(testDB)
- dispatcher := event.NewDispatcher()
- txPool := protocol.NewTxPool(store, dispatcher)
- chain, err := protocol.NewChain(store, txPool)
- if err != nil {
- return nil, err
- }
- return chain, nil
-}
-
-func mockNewRegistry(t *testing.T) *Registry {
- dirPath, err := ioutil.TempDir(".", "")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(dirPath)
-
- testDB := dbm.NewDB("testdb", "leveldb", "temp")
- defer os.RemoveAll("temp")
-
- chain, err := mockChain(testDB)
- if err != nil {
- t.Fatal(err)
- }
-
- return NewRegistry(testDB, chain)
-}
+++ /dev/null
-package asset
-
-import (
- "context"
- "crypto/rand"
- "encoding/json"
- "time"
-
- log "github.com/sirupsen/logrus"
-
- "github.com/vapor/blockchain/signers"
- "github.com/vapor/blockchain/txbuilder"
- "github.com/vapor/protocol/bc"
- "github.com/vapor/protocol/bc/types"
-)
-
-//NewIssueAction create a new asset issue action
-func (reg *Registry) NewIssueAction(assetAmount bc.AssetAmount) txbuilder.Action {
- return &issueAction{
- assets: reg,
- AssetAmount: assetAmount,
- }
-}
-
-//DecodeIssueAction unmarshal JSON-encoded data of asset issue action
-func (reg *Registry) DecodeIssueAction(data []byte) (txbuilder.Action, error) {
- a := &issueAction{assets: reg}
- err := json.Unmarshal(data, a)
- return a, err
-}
-
-type issueAction struct {
- assets *Registry
- bc.AssetAmount
- Arguments []txbuilder.ContractArgument `json:"arguments"`
-}
-
-func (a *issueAction) Build(ctx context.Context, builder *txbuilder.TemplateBuilder) error {
- if a.AssetId.IsZero() {
- return txbuilder.MissingFieldsError("asset_id")
- }
-
- asset, err := a.assets.FindByID(ctx, a.AssetId)
- if err != nil {
- return err
- }
-
- var nonce [8]byte
- _, err = rand.Read(nonce[:])
- if err != nil {
- return err
- }
-
- txin := types.NewIssuanceInput(nonce[:], a.Amount, asset.IssuanceProgram, nil, asset.RawDefinitionByte)
- tplIn := &txbuilder.SigningInstruction{}
- if asset.Signer != nil {
- path := signers.GetBip0032Path(asset.Signer, signers.AssetKeySpace)
- tplIn.AddRawWitnessKeys(asset.Signer.XPubs, path, asset.Signer.Quorum)
- } else if a.Arguments != nil {
- if err := txbuilder.AddContractArgs(tplIn, a.Arguments); err != nil {
- return err
- }
- }
-
- log.Info("Issue action build")
- builder.RestrictMinTime(time.Now())
- return builder.AddInput(txin, tplIn)
-}
-
-func (a *issueAction) ActionType() string {
- return "issue"
-}
+++ /dev/null
-package asset
-
-import (
- "encoding/json"
-
- log "github.com/sirupsen/logrus"
-
- "github.com/vapor/common"
-)
-
-// Image is the struct for hold export asset data
-type Image struct {
- Assets []*Asset `json:"assets"`
-}
-
-// Backup export all the asset info into image
-func (reg *Registry) Backup() (*Image, error) {
- assetImage := &Image{
- Assets: []*Asset{},
- }
-
- assetIter := reg.db.IteratorPrefix([]byte(assetPrefix))
- defer assetIter.Release()
- for assetIter.Next() {
- asset := &Asset{}
- if err := json.Unmarshal(assetIter.Value(), asset); err != nil {
- return nil, err
- }
- assetImage.Assets = append(assetImage.Assets, asset)
- }
-
- return assetImage, nil
-}
-
-// Restore load the image data into asset manage
-func (reg *Registry) Restore(image *Image) error {
- maxAssetIndex := uint64(0)
- storeBatch := reg.db.NewBatch()
- for _, asset := range image.Assets {
- if existed := reg.db.Get(Key(&asset.AssetID)); existed != nil {
- log.WithFields(log.Fields{"alias": asset.Alias, "id": asset.AssetID}).Warning("skip restore asset due to already existed")
- continue
- }
- if existed := reg.db.Get(aliasKey(*asset.Alias)); existed != nil {
- return ErrDuplicateAlias
- }
-
- rawAsset, err := json.Marshal(asset)
- if err != nil {
- return err
- }
-
- if asset.Signer.KeyIndex > maxAssetIndex {
- maxAssetIndex = asset.Signer.KeyIndex
- }
- storeBatch.Set(aliasKey(*asset.Alias), []byte(asset.AssetID.String()))
- storeBatch.Set(Key(&asset.AssetID), rawAsset)
- }
-
- if localIndex := reg.getNextAssetIndex(); localIndex < maxAssetIndex {
- storeBatch.Set(assetIndexKey, common.Unit64ToBytes(maxAssetIndex))
- }
- storeBatch.Write()
- return nil
-}
AssetAlias string `json:"asset_alias,omitempty"`
AssetDefinition *json.RawMessage `json:"asset_definition,omitempty"`
Amount uint64 `json:"amount"`
- IssuanceProgram chainjson.HexBytes `json:"issuance_program,omitempty"`
ControlProgram chainjson.HexBytes `json:"control_program,omitempty"`
Address string `json:"address,omitempty"`
SpentOutputID *bc.Hash `json:"spent_output_id,omitempty"`
//AnnotatedAsset means an annotated asset.
type AnnotatedAsset struct {
- AnnotatedSigner
ID bc.AssetID `json:"id"`
Alias string `json:"alias"`
VMVersion uint64 `json:"vm_version"`
- IssuanceProgram chainjson.HexBytes `json:"issue_program"`
RawDefinitionByte chainjson.HexBytes `json:"raw_definition_byte"`
Definition *json.RawMessage `json:"definition"`
- LimitHeight int64 `json:"limit_height"`
-}
-
-//AnnotatedSigner means an annotated signer for asset.
-type AnnotatedSigner struct {
- Type string `json:"type"`
- XPubs []chainkd.XPub `json:"xpubs"`
- Quorum int `json:"quorum"`
- KeyIndex uint64 `json:"key_index"`
- DeriveRule uint8 `json:"derive_rule"`
}
//AnnotatedUTXO means an annotated utxo.
"github.com/vapor/consensus"
"github.com/vapor/consensus/segwit"
"github.com/vapor/protocol/bc/types"
- "github.com/vapor/protocol/vm/vmutil"
)
// EstimateTxGasInfo estimate transaction consumed gas
// EstimateTxGas estimate consumed neu for transaction
func EstimateTxGas(template Template) (*EstimateTxGasInfo, error) {
- var baseP2WSHSize, totalWitnessSize, baseP2WSHGas, totalP2WPKHGas, totalP2WSHGas, totalIssueGas int64
+ var baseP2WSHSize, totalWitnessSize, baseP2WSHGas, totalP2WPKHGas, totalP2WSHGas int64
baseSize := int64(176) // inputSize(112) + outputSize(64)
baseP2WPKHSize := int64(98)
baseP2WPKHGas := int64(1409)
totalWitnessSize += baseP2WSHSize
totalP2WSHGas += baseP2WSHGas
}
-
- case types.IssuanceInputType:
- issuanceProgram := input.IssuanceProgram()
- if height := vmutil.GetIssuanceProgramRestrictHeight(issuanceProgram); height > 0 {
- // the gas for issue program with checking block height
- totalIssueGas += 5
- }
- baseIssueSize, baseIssueGas := estimateIssueGas(template.SigningInstructions[pos])
- totalWitnessSize += baseIssueSize
- totalIssueGas += baseIssueGas
}
}
flexibleGas += baseP2WPKHGas + (baseSize+baseP2WPKHSize)*consensus.StorageGasRate
} else if totalP2WSHGas > 0 {
flexibleGas += baseP2WSHGas + (baseSize+baseP2WSHSize)*consensus.StorageGasRate
- } else if totalIssueGas > 0 {
- totalIssueGas += baseP2WPKHGas
- totalWitnessSize += baseSize + baseP2WPKHSize
}
// the total transaction storage gas
totalTxSizeGas := (int64(template.Transaction.TxData.SerializedSize) + totalWitnessSize) * consensus.StorageGasRate
// the total transaction gas is composed of storage and virtual machines
- totalGas := totalTxSizeGas + totalP2WPKHGas + totalP2WSHGas + totalIssueGas + flexibleGas
+ totalGas := totalTxSizeGas + totalP2WPKHGas + totalP2WSHGas + flexibleGas
return &EstimateTxGasInfo{
TotalNeu: totalGas * consensus.VMGasRate,
FlexibleNeu: flexibleGas * consensus.VMGasRate,
StorageNeu: totalTxSizeGas * consensus.VMGasRate,
- VMNeu: (totalP2WPKHGas + totalP2WSHGas + totalIssueGas) * consensus.VMGasRate,
+ VMNeu: (totalP2WPKHGas + totalP2WSHGas) * consensus.VMGasRate,
}, nil
}
}
return witnessSize, gas
}
-
-// estimateIssueGas return the witness size and the gas consumed to execute the virtual machine for issuance program
-func estimateIssueGas(sigInst *SigningInstruction) (int64, int64) {
- var witnessSize, gas int64
- for _, witness := range sigInst.WitnessComponents {
- switch t := witness.(type) {
- case *SignatureWitness:
- witnessSize += 65 * int64(t.Quorum)
- gas += 1065*int64(len(t.Keys)) + 72*int64(t.Quorum) + 316
- case *RawTxSigWitness:
- witnessSize += 65 * int64(t.Quorum)
- gas += 1065*int64(len(t.Keys)) + 72*int64(t.Quorum) + 316
- }
- }
- return witnessSize, gas
-}
switch t := inp.TypedInput.(type) {
case *types.SpendInput:
args = t.Arguments
- case *types.IssuanceInput:
- args = t.Arguments
}
// Note: These numbers will need to change if more args are added such that the minimum length changes
switch {
"time"
"github.com/davecgh/go-spew/spew"
- "golang.org/x/crypto/sha3"
"github.com/vapor/common"
"github.com/vapor/consensus"
"github.com/vapor/crypto"
- "github.com/vapor/crypto/ed25519"
"github.com/vapor/crypto/ed25519/chainkd"
chainjson "github.com/vapor/encoding/json"
"github.com/vapor/errors"
"github.com/vapor/protocol/bc"
"github.com/vapor/protocol/bc/types"
- "github.com/vapor/protocol/vm"
"github.com/vapor/protocol/vm/vmutil"
"github.com/vapor/testutil"
)
}
}
-func TestSignatureWitnessMaterialize(t *testing.T) {
- privkey1, pubkey1, err := chainkd.NewXKeys(nil)
- if err != nil {
- t.Fatal(err)
- }
- privkey2, pubkey2, err := chainkd.NewXKeys(nil)
- if err != nil {
- t.Fatal(err)
- }
- privkey3, pubkey3, err := chainkd.NewXKeys(nil)
- if err != nil {
- t.Fatal(err)
- }
- issuanceProg, _ := vmutil.P2SPMultiSigProgram([]ed25519.PublicKey{pubkey1.PublicKey(), pubkey2.PublicKey(), pubkey3.PublicKey()}, 2)
- assetID := bc.ComputeAssetID(issuanceProg, 1, &bc.EmptyStringHash)
- outscript := mustDecodeHex("76a914c5d128911c28776f56baaac550963f7b88501dc388c0")
- unsigned := types.NewTx(types.TxData{
- Version: 1,
- Inputs: []*types.TxInput{
- types.NewIssuanceInput([]byte{1}, 100, issuanceProg, nil, nil),
- },
- Outputs: []*types.TxOutput{
- types.NewIntraChainOutput(assetID, 100, outscript),
- },
- })
-
- tpl := &Template{
- Transaction: unsigned,
- }
- h := tpl.Hash(0)
- builder := vmutil.NewBuilder()
- builder.AddData(h.Bytes())
- builder.AddOp(vm.OP_TXSIGHASH).AddOp(vm.OP_EQUAL)
- prog, _ := builder.Build()
- msg := sha3.Sum256(prog)
- sig1 := privkey1.Sign(msg[:])
- sig2 := privkey2.Sign(msg[:])
- sig3 := privkey3.Sign(msg[:])
- want := [][]byte{
- vm.Int64Bytes(0),
- sig1,
- sig2,
- prog,
- }
-
- // Test with more signatures than required, in correct order
- tpl.SigningInstructions = []*SigningInstruction{{
- WitnessComponents: []witnessComponent{
- &SignatureWitness{
- Quorum: 2,
- Keys: []keyID{
- {
- XPub: pubkey1,
- DerivationPath: []chainjson.HexBytes{{0, 0, 0, 0}},
- },
- {
- XPub: pubkey2,
- DerivationPath: []chainjson.HexBytes{{0, 0, 0, 0}},
- },
- {
- XPub: pubkey3,
- DerivationPath: []chainjson.HexBytes{{0, 0, 0, 0}},
- },
- },
- Program: prog,
- Sigs: []chainjson.HexBytes{sig1, sig2, sig3},
- },
- },
- }}
- err = materializeWitnesses(tpl)
- if err != nil {
- testutil.FatalErr(t, err)
- }
- got := tpl.Transaction.Inputs[0].Arguments()
- if !testutil.DeepEqual(got, want) {
- t.Errorf("got input witness %v, want input witness %v", got, want)
- }
-
- // Test with exact amount of signatures required, in correct order
- component := tpl.SigningInstructions[0].WitnessComponents[0].(*SignatureWitness)
- component.Sigs = []chainjson.HexBytes{sig1, sig2}
- err = materializeWitnesses(tpl)
- if err != nil {
- testutil.FatalErr(t, err)
- }
- got = tpl.Transaction.Inputs[0].Arguments()
- if !testutil.DeepEqual(got, want) {
- t.Errorf("got input witness %v, want input witness %v", got, want)
- }
-}
-
func mustDecodeHex(str string) []byte {
data, err := hex.DecodeString(str)
if err != nil {
in.Type = "spend"
in.ControlProgram = orig.ControlProgram()
in.SpentOutputID = e.SpentOutputId
- case *bc.Issuance:
- in.Type = "issue"
- in.IssuanceProgram = orig.IssuanceProgram()
}
return in
"errors"
"math/rand"
"net"
- "time"
wire "github.com/tendermint/go-wire"
"github.com/tendermint/tmlibs/flowrate"
func mockTxs(txCount int) ([]*types.Tx, []*bc.Tx) {
var txs []*types.Tx
var bcTxs []*bc.Tx
- for i := 0; i < txCount; i++ {
- trueProg := mockControlProgram(60)
- assetID := bc.ComputeAssetID(trueProg, 1, &bc.EmptyStringHash)
- now := []byte(time.Now().String())
- issuanceInp := types.NewIssuanceInput(now, 1, trueProg, nil, nil)
+ trueProg := mockControlProgram(60)
+ assetID := bc.AssetID{V0: 9999}
+ for i := uint64(0); i < uint64(txCount); i++ {
tx := types.NewTx(types.TxData{
Version: 1,
- Inputs: []*types.TxInput{issuanceInp},
+ Inputs: []*types.TxInput{types.NewSpendInput(nil, bc.Hash{V0: i + 1}, assetID, i, i, trueProg)},
Outputs: []*types.TxOutput{types.NewIntraChainOutput(assetID, 1, trueProg)},
})
txs = append(txs, tx)
"errors"
"io"
- "github.com/vapor/crypto/sha3pool"
"github.com/vapor/encoding/blockchain"
)
// IsZero tells whether a Asset pointer is nil or points to an all-zero hash.
func (a *AssetID) IsZero() bool { return (*Hash)(a).IsZero() }
-// ComputeAssetID calculate the asset id from AssetDefinition
-func (ad *AssetDefinition) ComputeAssetID() (assetID AssetID) {
- h := sha3pool.Get256()
- defer sha3pool.Put256(h)
- writeForHash(h, *ad) // error is impossible
- var b [32]byte
- h.Read(b[:]) // error is impossible
- return NewAssetID(b)
-}
-
-// ComputeAssetID implement the assetID calculate logic
-func ComputeAssetID(prog []byte, vmVersion uint64, data *Hash) AssetID {
- def := &AssetDefinition{
- IssuanceProgram: &Program{
- VmVersion: vmVersion,
- Code: prog,
- },
- Data: data,
- }
- return def.ComputeAssetID()
-}
-
// ReadFrom read the AssetAmount from the bytes
func (a *AssetAmount) ReadFrom(r *blockchain.Reader) (err error) {
var assetID AssetID
+++ /dev/null
-package bc
-
-import (
- "testing"
- "encoding/hex"
-
- "golang.org/x/crypto/sha3"
-)
-
-func TestComputeAssetID(t *testing.T) {
- issuanceScript := []byte{1}
- assetID := ComputeAssetID(issuanceScript, 1, &EmptyStringHash)
-
- unhashed := append([]byte{})
- unhashed = append(unhashed, []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}...) // vmVersion
- unhashed = append(unhashed, 0x01) // length of issuanceScript
- unhashed = append(unhashed, issuanceScript...)
- unhashed = append(unhashed, EmptyStringHash.Bytes()...)
-
- if want := NewAssetID(sha3.Sum256(unhashed)); assetID != want {
- t.Errorf("asset id = %x want %x", assetID.Bytes(), want.Bytes())
- }
-}
-
-func TestComputeAssetIDReally(t *testing.T) {
- cases := []struct {
- program string
- rawDefinition string
- wantAssetID string
- }{
- {
- program: "ae2039294f652632eee970765550c245f0b0314256b4b93aadc86279fdb45db3b70e5151ad",
- rawDefinition: "7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d",
- wantAssetID: "07c7ced3f37f48ea39da6971c89f90e9cff3202d54b0a911f12ace8501f3834e",
- },
- {
- program: "ae20620b1755451738b04f42822f4b37186563f824c9c30d485987298918f96395fe5151ad",
- rawDefinition: "7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d6f626f6c223a2022220a7d",
- wantAssetID: "0dafd0f0e42f06f3bf9a8cf5787519d3860650f27a2b3393d34e1fe06e89b469",
- },
- {
- program: "ae20db11f9dfa39c9e66421c530fe027218edd3d5b1cd98f24c826f4d9c0cd131a475151ad",
- rawDefinition: "7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d",
- wantAssetID: "a5bc30d8d0ad051e6e352ebc21d79ba798cd8c436e89f4149969c2c562371791",
- },
- }
-
- for _, c := range cases {
- progBytes, err := hex.DecodeString(c.program)
- if err != nil {
- t.Fatal(err)
- }
-
- defBytes, err := hex.DecodeString(c.rawDefinition)
- if err != nil {
- t.Fatal(err)
- }
-
- defHash := NewHash(sha3.Sum256(defBytes))
- assetID := ComputeAssetID(progBytes, 1, &defHash)
- if assetID.String() != c.wantAssetID {
- t.Errorf("got asset id:%s, want asset id:%s", assetID.String(), c.wantAssetID)
- }
- }
-}
-
-var assetIDSink AssetID
-
-func BenchmarkComputeAssetID(b *testing.B) {
- var (
- issuanceScript = []byte{5}
- )
-
- for i := 0; i < b.N; i++ {
- assetIDSink = ComputeAssetID(issuanceScript, 1, &EmptyStringHash)
- }
-}
Program
AssetID
AssetAmount
- AssetDefinition
ValueSource
ValueDestination
BlockHeader
CrossChainOutput
VoteOutput
Retirement
- Issuance
Spend
*/
package bc
return 0
}
-type AssetDefinition struct {
- IssuanceProgram *Program `protobuf:"bytes,1,opt,name=issuance_program,json=issuanceProgram" json:"issuance_program,omitempty"`
- Data *Hash `protobuf:"bytes,2,opt,name=data" json:"data,omitempty"`
-}
-
-func (m *AssetDefinition) Reset() { *m = AssetDefinition{} }
-func (m *AssetDefinition) String() string { return proto.CompactTextString(m) }
-func (*AssetDefinition) ProtoMessage() {}
-func (*AssetDefinition) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
-
-func (m *AssetDefinition) GetIssuanceProgram() *Program {
- if m != nil {
- return m.IssuanceProgram
- }
- return nil
-}
-
-func (m *AssetDefinition) GetData() *Hash {
- if m != nil {
- return m.Data
- }
- return nil
-}
-
type ValueSource struct {
Ref *Hash `protobuf:"bytes,1,opt,name=ref" json:"ref,omitempty"`
Value *AssetAmount `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
func (m *ValueSource) Reset() { *m = ValueSource{} }
func (m *ValueSource) String() string { return proto.CompactTextString(m) }
func (*ValueSource) ProtoMessage() {}
-func (*ValueSource) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
+func (*ValueSource) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
func (m *ValueSource) GetRef() *Hash {
if m != nil {
func (m *ValueDestination) Reset() { *m = ValueDestination{} }
func (m *ValueDestination) String() string { return proto.CompactTextString(m) }
func (*ValueDestination) ProtoMessage() {}
-func (*ValueDestination) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
+func (*ValueDestination) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
func (m *ValueDestination) GetRef() *Hash {
if m != nil {
func (m *BlockHeader) Reset() { *m = BlockHeader{} }
func (m *BlockHeader) String() string { return proto.CompactTextString(m) }
func (*BlockHeader) ProtoMessage() {}
-func (*BlockHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
+func (*BlockHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
func (m *BlockHeader) GetVersion() uint64 {
if m != nil {
func (m *TxHeader) Reset() { *m = TxHeader{} }
func (m *TxHeader) String() string { return proto.CompactTextString(m) }
func (*TxHeader) ProtoMessage() {}
-func (*TxHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
+func (*TxHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
func (m *TxHeader) GetVersion() uint64 {
if m != nil {
func (m *TxVerifyResult) Reset() { *m = TxVerifyResult{} }
func (m *TxVerifyResult) String() string { return proto.CompactTextString(m) }
func (*TxVerifyResult) ProtoMessage() {}
-func (*TxVerifyResult) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
+func (*TxVerifyResult) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
func (m *TxVerifyResult) GetStatusFail() bool {
if m != nil {
func (m *TransactionStatus) Reset() { *m = TransactionStatus{} }
func (m *TransactionStatus) String() string { return proto.CompactTextString(m) }
func (*TransactionStatus) ProtoMessage() {}
-func (*TransactionStatus) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
+func (*TransactionStatus) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
func (m *TransactionStatus) GetVersion() uint64 {
if m != nil {
func (m *Mux) Reset() { *m = Mux{} }
func (m *Mux) String() string { return proto.CompactTextString(m) }
func (*Mux) ProtoMessage() {}
-func (*Mux) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
+func (*Mux) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
func (m *Mux) GetSources() []*ValueSource {
if m != nil {
func (m *Coinbase) Reset() { *m = Coinbase{} }
func (m *Coinbase) String() string { return proto.CompactTextString(m) }
func (*Coinbase) ProtoMessage() {}
-func (*Coinbase) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
+func (*Coinbase) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
func (m *Coinbase) GetWitnessDestination() *ValueDestination {
if m != nil {
func (m *IntraChainOutput) Reset() { *m = IntraChainOutput{} }
func (m *IntraChainOutput) String() string { return proto.CompactTextString(m) }
func (*IntraChainOutput) ProtoMessage() {}
-func (*IntraChainOutput) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
+func (*IntraChainOutput) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
func (m *IntraChainOutput) GetSource() *ValueSource {
if m != nil {
func (m *CrossChainOutput) Reset() { *m = CrossChainOutput{} }
func (m *CrossChainOutput) String() string { return proto.CompactTextString(m) }
func (*CrossChainOutput) ProtoMessage() {}
-func (*CrossChainOutput) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
+func (*CrossChainOutput) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
func (m *CrossChainOutput) GetSource() *ValueSource {
if m != nil {
func (m *VoteOutput) Reset() { *m = VoteOutput{} }
func (m *VoteOutput) String() string { return proto.CompactTextString(m) }
func (*VoteOutput) ProtoMessage() {}
-func (*VoteOutput) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} }
+func (*VoteOutput) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
func (m *VoteOutput) GetSource() *ValueSource {
if m != nil {
func (m *Retirement) Reset() { *m = Retirement{} }
func (m *Retirement) String() string { return proto.CompactTextString(m) }
func (*Retirement) ProtoMessage() {}
-func (*Retirement) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
+func (*Retirement) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} }
func (m *Retirement) GetSource() *ValueSource {
if m != nil {
return 0
}
-type Issuance struct {
- NonceHash *Hash `protobuf:"bytes,1,opt,name=nonce_hash,json=nonceHash" json:"nonce_hash,omitempty"`
- Value *AssetAmount `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
- WitnessDestination *ValueDestination `protobuf:"bytes,3,opt,name=witness_destination,json=witnessDestination" json:"witness_destination,omitempty"`
- WitnessAssetDefinition *AssetDefinition `protobuf:"bytes,4,opt,name=witness_asset_definition,json=witnessAssetDefinition" json:"witness_asset_definition,omitempty"`
- WitnessArguments [][]byte `protobuf:"bytes,5,rep,name=witness_arguments,json=witnessArguments,proto3" json:"witness_arguments,omitempty"`
- Ordinal uint64 `protobuf:"varint,6,opt,name=ordinal" json:"ordinal,omitempty"`
-}
-
-func (m *Issuance) Reset() { *m = Issuance{} }
-func (m *Issuance) String() string { return proto.CompactTextString(m) }
-func (*Issuance) ProtoMessage() {}
-func (*Issuance) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} }
-
-func (m *Issuance) GetNonceHash() *Hash {
- if m != nil {
- return m.NonceHash
- }
- return nil
-}
-
-func (m *Issuance) GetValue() *AssetAmount {
- if m != nil {
- return m.Value
- }
- return nil
-}
-
-func (m *Issuance) GetWitnessDestination() *ValueDestination {
- if m != nil {
- return m.WitnessDestination
- }
- return nil
-}
-
-func (m *Issuance) GetWitnessAssetDefinition() *AssetDefinition {
- if m != nil {
- return m.WitnessAssetDefinition
- }
- return nil
-}
-
-func (m *Issuance) GetWitnessArguments() [][]byte {
- if m != nil {
- return m.WitnessArguments
- }
- return nil
-}
-
-func (m *Issuance) GetOrdinal() uint64 {
- if m != nil {
- return m.Ordinal
- }
- return 0
-}
-
type Spend struct {
SpentOutputId *Hash `protobuf:"bytes,1,opt,name=spent_output_id,json=spentOutputId" json:"spent_output_id,omitempty"`
WitnessDestination *ValueDestination `protobuf:"bytes,2,opt,name=witness_destination,json=witnessDestination" json:"witness_destination,omitempty"`
func (m *Spend) Reset() { *m = Spend{} }
func (m *Spend) String() string { return proto.CompactTextString(m) }
func (*Spend) ProtoMessage() {}
-func (*Spend) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} }
+func (*Spend) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
func (m *Spend) GetSpentOutputId() *Hash {
if m != nil {
proto.RegisterType((*Program)(nil), "bc.Program")
proto.RegisterType((*AssetID)(nil), "bc.AssetID")
proto.RegisterType((*AssetAmount)(nil), "bc.AssetAmount")
- proto.RegisterType((*AssetDefinition)(nil), "bc.AssetDefinition")
proto.RegisterType((*ValueSource)(nil), "bc.ValueSource")
proto.RegisterType((*ValueDestination)(nil), "bc.ValueDestination")
proto.RegisterType((*BlockHeader)(nil), "bc.BlockHeader")
proto.RegisterType((*CrossChainOutput)(nil), "bc.CrossChainOutput")
proto.RegisterType((*VoteOutput)(nil), "bc.VoteOutput")
proto.RegisterType((*Retirement)(nil), "bc.Retirement")
- proto.RegisterType((*Issuance)(nil), "bc.Issuance")
proto.RegisterType((*Spend)(nil), "bc.Spend")
}
func init() { proto.RegisterFile("bc.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
- // 943 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x56, 0xcd, 0x6e, 0x23, 0x45,
- 0x10, 0x96, 0xc7, 0x13, 0xdb, 0x29, 0x67, 0xe3, 0xb8, 0xb3, 0xbb, 0x8c, 0x56, 0x8b, 0x88, 0x46,
- 0x5a, 0xb2, 0x08, 0x29, 0x4a, 0x9c, 0x05, 0x2e, 0x1c, 0x08, 0x09, 0xcb, 0xfa, 0x10, 0x2d, 0xea,
- 0x44, 0xb9, 0x8e, 0xda, 0x9e, 0xb6, 0xdd, 0x62, 0x3c, 0x6d, 0xba, 0x7b, 0x86, 0x6c, 0x5e, 0x81,
- 0x33, 0x07, 0x9e, 0x84, 0x47, 0xe0, 0xc4, 0x33, 0x81, 0xba, 0xa6, 0xc7, 0x1e, 0xff, 0x64, 0x7f,
- 0x84, 0x10, 0xdc, 0xa6, 0x7e, 0xfa, 0xab, 0xaa, 0xaf, 0xab, 0xaa, 0x07, 0x5a, 0x83, 0xe1, 0xd1,
- 0x4c, 0x49, 0x23, 0x89, 0x37, 0x18, 0x86, 0x2f, 0xc1, 0x7f, 0xc5, 0xf4, 0x84, 0xec, 0x82, 0x97,
- 0x1f, 0x07, 0xb5, 0x83, 0xda, 0xf3, 0x06, 0xf5, 0xf2, 0x63, 0x94, 0x4f, 0x02, 0xcf, 0xc9, 0x27,
- 0x28, 0xf7, 0x82, 0xba, 0x93, 0x7b, 0x28, 0x9f, 0x06, 0xbe, 0x93, 0x4f, 0xc3, 0xaf, 0xa1, 0xf9,
- 0x83, 0x92, 0x63, 0xc5, 0xa6, 0xe4, 0x63, 0x80, 0x7c, 0x1a, 0xe5, 0x5c, 0x69, 0x21, 0x53, 0x84,
- 0xf4, 0xe9, 0x76, 0x3e, 0xbd, 0x29, 0x14, 0x84, 0x80, 0x3f, 0x94, 0x31, 0x47, 0xec, 0x1d, 0x8a,
- 0xdf, 0x61, 0x1f, 0x9a, 0x67, 0x5a, 0x73, 0xd3, 0xbf, 0xf8, 0xc7, 0x89, 0x5c, 0x42, 0x1b, 0xa1,
- 0xce, 0xa6, 0x32, 0x4b, 0x0d, 0xf9, 0x14, 0x5a, 0xcc, 0x8a, 0x91, 0x88, 0x11, 0xb4, 0xdd, 0x6b,
- 0x1f, 0x0d, 0x86, 0x47, 0x2e, 0x1a, 0x6d, 0xa2, 0xb1, 0x1f, 0x93, 0xc7, 0xd0, 0x60, 0x78, 0x02,
- 0x43, 0xf9, 0xd4, 0x49, 0xe1, 0x18, 0x3a, 0xe8, 0x7b, 0xc1, 0x47, 0x22, 0x15, 0xc6, 0x16, 0xf0,
- 0x25, 0xec, 0x09, 0xad, 0x33, 0x96, 0x0e, 0x79, 0x34, 0x2b, 0x6a, 0xae, 0x42, 0x3b, 0x1a, 0x68,
- 0xa7, 0x74, 0x2a, 0x79, 0x79, 0x0a, 0x7e, 0xcc, 0x0c, 0xc3, 0x00, 0xed, 0x5e, 0xcb, 0xfa, 0x5a,
- 0xea, 0x29, 0x6a, 0xc3, 0x04, 0xda, 0x37, 0x2c, 0xc9, 0xf8, 0x95, 0xcc, 0xd4, 0x90, 0x93, 0x27,
- 0x50, 0x57, 0x7c, 0xe4, 0x70, 0x17, 0xbe, 0x56, 0x49, 0x9e, 0xc1, 0x56, 0x6e, 0x5d, 0x1d, 0x52,
- 0x67, 0x5e, 0x50, 0x51, 0x33, 0x2d, 0xac, 0xe4, 0x09, 0xb4, 0x66, 0x52, 0x63, 0xce, 0xc8, 0x97,
- 0x4f, 0xe7, 0x72, 0xf8, 0x13, 0xec, 0x61, 0xb4, 0x0b, 0xae, 0x8d, 0x48, 0x19, 0xd6, 0xf5, 0x2f,
- 0x87, 0xfc, 0xcb, 0x83, 0xf6, 0xb7, 0x89, 0x1c, 0xfe, 0xf8, 0x8a, 0xb3, 0x98, 0x2b, 0x12, 0x40,
- 0x73, 0xb9, 0x47, 0x4a, 0xd1, 0xde, 0xc5, 0x84, 0x8b, 0xf1, 0x64, 0x7e, 0x17, 0x85, 0x44, 0x5e,
- 0x40, 0x77, 0xa6, 0x78, 0x2e, 0x64, 0xa6, 0xa3, 0x81, 0x45, 0xb2, 0x97, 0x5a, 0x5f, 0x49, 0xb7,
- 0x53, 0xba, 0x60, 0xac, 0x7e, 0x4c, 0x9e, 0xc2, 0xb6, 0x11, 0x53, 0xae, 0x0d, 0x9b, 0xce, 0xb0,
- 0x4f, 0x7c, 0xba, 0x50, 0x90, 0x2f, 0xa0, 0x6b, 0x14, 0x4b, 0x35, 0x1b, 0xda, 0x24, 0x75, 0xa4,
- 0xa4, 0x34, 0xc1, 0xd6, 0x0a, 0xe6, 0x5e, 0xd5, 0x85, 0x4a, 0x69, 0xc8, 0x37, 0xf0, 0x51, 0x45,
- 0x17, 0x69, 0xc3, 0x4c, 0xa6, 0xa3, 0x09, 0xd3, 0x93, 0xa0, 0xb1, 0x72, 0xf8, 0x51, 0xc5, 0xf1,
- 0x0a, 0xfd, 0x70, 0xe0, 0x2e, 0x80, 0xac, 0x23, 0x04, 0x4d, 0x3c, 0xfc, 0xc8, 0x1e, 0xbe, 0x5e,
- 0x3d, 0x46, 0xbb, 0x6b, 0x48, 0xe4, 0x73, 0xe8, 0xfe, 0x2c, 0x4c, 0xca, 0xb5, 0x8e, 0x98, 0x1a,
- 0x67, 0x53, 0x9e, 0x1a, 0x1d, 0xb4, 0x0e, 0xea, 0xcf, 0x77, 0xe8, 0x9e, 0x33, 0x9c, 0x95, 0xfa,
- 0xf0, 0xd7, 0x1a, 0xb4, 0xae, 0x6f, 0xdf, 0x49, 0xff, 0x21, 0x74, 0x34, 0x57, 0x82, 0x25, 0xe2,
- 0x8e, 0xc7, 0x91, 0x16, 0x77, 0xdc, 0xdd, 0xc3, 0xee, 0x42, 0x7d, 0x25, 0xee, 0xb8, 0x1d, 0x74,
- 0x4b, 0x64, 0xa4, 0x58, 0x3a, 0xe6, 0xee, 0xbe, 0x91, 0x5a, 0x6a, 0x15, 0xe4, 0x10, 0x40, 0x71,
- 0x9d, 0x25, 0x76, 0xf6, 0x74, 0xe0, 0x1f, 0xd4, 0x97, 0x68, 0xd9, 0x2e, 0x6c, 0xfd, 0x58, 0x87,
- 0x27, 0xb0, 0x7b, 0x7d, 0x7b, 0xc3, 0x95, 0x18, 0xbd, 0xa1, 0xa8, 0x24, 0x9f, 0x40, 0xdb, 0x51,
- 0x3a, 0x62, 0x22, 0xc1, 0x04, 0x5b, 0x14, 0x0a, 0xd5, 0x4b, 0x26, 0x92, 0x70, 0x04, 0xdd, 0x35,
- 0x7e, 0xde, 0x52, 0xd2, 0x57, 0xf0, 0x20, 0x47, 0xfc, 0x92, 0x67, 0x0f, 0xb3, 0x21, 0xc8, 0xf3,
- 0x52, 0x68, 0xba, 0x53, 0x38, 0x16, 0x90, 0xe1, 0x9f, 0x35, 0xa8, 0x5f, 0x66, 0xb7, 0xe4, 0x33,
- 0x68, 0x6a, 0x1c, 0x4c, 0x1d, 0xd4, 0xf0, 0x28, 0x4e, 0x40, 0x65, 0x60, 0x69, 0x69, 0x27, 0xcf,
- 0xa0, 0x59, 0x6e, 0x05, 0x6f, 0x7d, 0x2b, 0x94, 0x36, 0xf2, 0x3d, 0x3c, 0x2c, 0x6f, 0x2e, 0x5e,
- 0x0c, 0xa1, 0x0e, 0xea, 0x08, 0xff, 0x70, 0x0e, 0x5f, 0x99, 0x50, 0xba, 0xef, 0x4e, 0x54, 0x74,
- 0xf7, 0xb4, 0x80, 0x7f, 0x4f, 0x0b, 0x48, 0x68, 0x9d, 0x4b, 0x91, 0x0e, 0x98, 0xe6, 0xe4, 0x3b,
- 0xd8, 0xdf, 0x90, 0x81, 0x9b, 0xff, 0xcd, 0x09, 0x90, 0xf5, 0x04, 0xec, 0x7c, 0x31, 0x35, 0x10,
- 0x46, 0x31, 0xf5, 0xc6, 0x2d, 0xf5, 0x85, 0x22, 0xfc, 0xa5, 0x06, 0x7b, 0xfd, 0xd4, 0x28, 0x76,
- 0x3e, 0x61, 0x22, 0x7d, 0x9d, 0x99, 0x59, 0x66, 0xc8, 0x21, 0x34, 0x0a, 0xb6, 0x5c, 0xb0, 0x35,
- 0x32, 0x9d, 0x99, 0xbc, 0x80, 0xce, 0x50, 0xa6, 0x46, 0xc9, 0x24, 0x7a, 0x0b, 0xa7, 0xbb, 0xce,
- 0xa7, 0x5c, 0xb4, 0x01, 0x34, 0xa5, 0x8a, 0x45, 0xca, 0x12, 0xd7, 0x94, 0xa5, 0x88, 0xd9, 0x9c,
- 0x2b, 0xa9, 0xf5, 0xff, 0x22, 0x9b, 0xdf, 0x6a, 0x00, 0x37, 0xd2, 0xf0, 0xff, 0x38, 0x0f, 0xfb,
- 0x22, 0xe7, 0xd2, 0x70, 0x5c, 0x8e, 0x3b, 0x14, 0xbf, 0xc3, 0xd7, 0x00, 0x94, 0x1b, 0xa1, 0xb8,
- 0xed, 0x9b, 0xf7, 0x4f, 0xad, 0x12, 0xc4, 0x5b, 0x2e, 0xf6, 0x77, 0x0f, 0x5a, 0x7d, 0xf7, 0x22,
- 0xda, 0xd5, 0x90, 0x4a, 0xfb, 0x7e, 0xe2, 0xc6, 0x5c, 0x7d, 0x71, 0xb6, 0xd1, 0x86, 0x5b, 0xf2,
- 0x3d, 0xdf, 0x9d, 0x7b, 0x5a, 0xb9, 0xfe, 0x81, 0xad, 0x7c, 0x09, 0xc1, 0x7c, 0x94, 0xf0, 0xa7,
- 0x21, 0x9e, 0xbf, 0xfa, 0x48, 0x4e, 0xbb, 0xb7, 0x3f, 0x4f, 0x60, 0xf1, 0x43, 0x40, 0x1f, 0x97,
- 0x63, 0xb6, 0xf2, 0xa3, 0xb0, 0x71, 0x32, 0xb7, 0x36, 0x4f, 0x66, 0x95, 0xb9, 0xc6, 0x32, 0x73,
- 0x7f, 0xd4, 0x60, 0xeb, 0x6a, 0xc6, 0xd3, 0x98, 0x1c, 0x43, 0x47, 0xcf, 0x78, 0x6a, 0x22, 0x89,
- 0x1d, 0xb3, 0xf8, 0xa7, 0x59, 0x70, 0xf7, 0x00, 0x1d, 0x8a, 0x8e, 0xea, 0xc7, 0xf7, 0x11, 0xe3,
- 0x7d, 0x20, 0x31, 0x1b, 0x2b, 0xa9, 0xbf, 0xbb, 0x12, 0x7f, 0xa9, 0x92, 0x41, 0x03, 0xff, 0x3b,
- 0x4f, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x9e, 0xe2, 0x40, 0x89, 0x83, 0x0a, 0x00, 0x00,
+ // 835 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x56, 0xcf, 0x6f, 0xe4, 0x34,
+ 0x14, 0xd6, 0x4c, 0xd2, 0x49, 0xfa, 0xa6, 0xdb, 0xe9, 0x78, 0x77, 0x21, 0x5a, 0x81, 0xa8, 0x22,
+ 0x2d, 0x5d, 0x84, 0x54, 0xf5, 0xc7, 0x22, 0x2e, 0x1c, 0x28, 0x2d, 0xcb, 0xce, 0x61, 0xb5, 0xc8,
+ 0xad, 0x7a, 0x8d, 0x3c, 0x89, 0xdb, 0xb1, 0xc8, 0xc4, 0xc1, 0x76, 0x42, 0xb7, 0xff, 0x02, 0x67,
+ 0x0e, 0xfc, 0x45, 0x9c, 0xf8, 0x9b, 0x40, 0x7e, 0x71, 0x3a, 0x99, 0x4e, 0x5b, 0x40, 0x08, 0xb1,
+ 0xb7, 0x79, 0xcf, 0xef, 0x7d, 0xef, 0xf3, 0x67, 0x7f, 0xce, 0x40, 0x38, 0x4d, 0x77, 0x4b, 0x25,
+ 0x8d, 0x24, 0xfd, 0x69, 0x1a, 0xbf, 0x02, 0xff, 0x35, 0xd3, 0x33, 0xb2, 0x09, 0xfd, 0x7a, 0x2f,
+ 0xea, 0x6d, 0xf7, 0x5e, 0x0c, 0x68, 0xbf, 0xde, 0xc3, 0x78, 0x3f, 0xea, 0xbb, 0x78, 0x1f, 0xe3,
+ 0x83, 0xc8, 0x73, 0xf1, 0x01, 0xc6, 0x87, 0x91, 0xef, 0xe2, 0xc3, 0xf8, 0x2b, 0x08, 0xbe, 0x57,
+ 0xf2, 0x52, 0xb1, 0x39, 0xf9, 0x18, 0xa0, 0x9e, 0x27, 0x35, 0x57, 0x5a, 0xc8, 0x02, 0x21, 0x7d,
+ 0xba, 0x5e, 0xcf, 0xcf, 0x9b, 0x04, 0x21, 0xe0, 0xa7, 0x32, 0xe3, 0x88, 0xbd, 0x41, 0xf1, 0x77,
+ 0x3c, 0x81, 0xe0, 0x48, 0x6b, 0x6e, 0x26, 0x27, 0xff, 0x9a, 0xc8, 0x1b, 0x18, 0x22, 0xd4, 0xd1,
+ 0x5c, 0x56, 0x85, 0x21, 0x9f, 0x42, 0xc8, 0x6c, 0x98, 0x88, 0x0c, 0x41, 0x87, 0x07, 0xc3, 0xdd,
+ 0x69, 0xba, 0xeb, 0xa6, 0xd1, 0x00, 0x17, 0x27, 0x19, 0xf9, 0x00, 0x06, 0x0c, 0x3b, 0x70, 0x94,
+ 0x4f, 0x5d, 0x14, 0xe7, 0x30, 0x3c, 0x67, 0x79, 0xc5, 0x4f, 0x65, 0xa5, 0x52, 0x4e, 0x9e, 0x81,
+ 0xa7, 0xf8, 0x85, 0x43, 0x0a, 0x2d, 0x92, 0x55, 0x8f, 0xda, 0x24, 0x79, 0x0e, 0x6b, 0xb5, 0x2d,
+ 0x45, 0x84, 0xe1, 0xc1, 0xe8, 0x66, 0x4e, 0x43, 0x85, 0x36, 0xab, 0xe4, 0x19, 0x84, 0xa5, 0xd4,
+ 0xc2, 0x58, 0x71, 0x3c, 0x9c, 0x75, 0x13, 0xc7, 0x3f, 0xc2, 0x16, 0x4e, 0x3b, 0xe1, 0xda, 0x88,
+ 0x82, 0xd9, 0xdc, 0x7f, 0x3d, 0xf2, 0x8f, 0x3e, 0x0c, 0xbf, 0xc9, 0x65, 0xfa, 0xc3, 0x6b, 0xce,
+ 0x32, 0xae, 0x48, 0x04, 0xc1, 0xf2, 0xd1, 0xb5, 0xa1, 0x95, 0x68, 0xc6, 0xc5, 0xe5, 0xec, 0x46,
+ 0xa2, 0x26, 0x22, 0x2f, 0x61, 0x5c, 0x2a, 0x5e, 0x0b, 0x59, 0xe9, 0x64, 0x6a, 0x91, 0xac, 0xd6,
+ 0xde, 0x2d, 0xba, 0xa3, 0xb6, 0x04, 0x67, 0x4d, 0x32, 0xf2, 0x11, 0xac, 0x1b, 0x31, 0xe7, 0xda,
+ 0xb0, 0x79, 0x89, 0xc7, 0xe7, 0xd3, 0x45, 0x82, 0x7c, 0x01, 0x63, 0xa3, 0x58, 0xa1, 0x59, 0x6a,
+ 0x49, 0xea, 0x44, 0x49, 0x69, 0xa2, 0xb5, 0x5b, 0x98, 0x5b, 0xdd, 0x12, 0x2a, 0xa5, 0x21, 0x5f,
+ 0xc3, 0x87, 0x9d, 0x5c, 0xa2, 0x0d, 0x33, 0x95, 0x4e, 0x66, 0x4c, 0xcf, 0xa2, 0xc1, 0xad, 0xe6,
+ 0xa7, 0x9d, 0xc2, 0x53, 0xac, 0x43, 0x1f, 0x9c, 0x00, 0x59, 0x45, 0x88, 0x02, 0x6c, 0x7e, 0x6a,
+ 0x9b, 0xcf, 0x6e, 0xb7, 0xd1, 0xf1, 0x0a, 0x12, 0xf9, 0x1c, 0xc6, 0x3f, 0x09, 0x53, 0x70, 0xad,
+ 0x13, 0xa6, 0x2e, 0xab, 0x39, 0x2f, 0x8c, 0x8e, 0xc2, 0x6d, 0xef, 0xc5, 0x06, 0xdd, 0x72, 0x0b,
+ 0x47, 0x6d, 0x3e, 0xfe, 0xa5, 0x07, 0xe1, 0xd9, 0xd5, 0x5f, 0xca, 0xbf, 0x03, 0x23, 0xcd, 0x95,
+ 0x60, 0xb9, 0xb8, 0xe6, 0x59, 0xa2, 0xc5, 0x35, 0x77, 0xe7, 0xb0, 0xb9, 0x48, 0x9f, 0x8a, 0x6b,
+ 0x6e, 0xfd, 0x67, 0x85, 0x4c, 0x14, 0x2b, 0x2e, 0xb9, 0x3b, 0x6f, 0x94, 0x96, 0xda, 0x04, 0xd9,
+ 0x01, 0x50, 0x5c, 0x57, 0xb9, 0xb5, 0x84, 0x8e, 0xfc, 0x6d, 0x6f, 0x49, 0x96, 0xf5, 0x66, 0x6d,
+ 0x92, 0xe9, 0x78, 0x1f, 0x36, 0xcf, 0xae, 0xce, 0xb9, 0x12, 0x17, 0xef, 0x28, 0x26, 0xc9, 0x27,
+ 0x30, 0x74, 0x92, 0x5e, 0x30, 0x91, 0x23, 0xc1, 0x90, 0x42, 0x93, 0x7a, 0xc5, 0x44, 0x1e, 0x5f,
+ 0xc0, 0x78, 0x45, 0x9f, 0x07, 0xb6, 0xf4, 0x25, 0x3c, 0xaa, 0x11, 0xbf, 0xd5, 0xb9, 0x8f, 0x6c,
+ 0x08, 0xea, 0xbc, 0x34, 0x9a, 0x6e, 0x34, 0x85, 0x0d, 0x64, 0xfc, 0x7b, 0x0f, 0xbc, 0x37, 0xd5,
+ 0x15, 0xf9, 0x0c, 0x02, 0x8d, 0xc6, 0xd4, 0x51, 0x0f, 0x5b, 0xd1, 0x01, 0x1d, 0xc3, 0xd2, 0x76,
+ 0x9d, 0x3c, 0x87, 0xa0, 0x6c, 0x1e, 0x28, 0x67, 0x16, 0x7c, 0x07, 0xdc, 0x9b, 0x45, 0xdb, 0x35,
+ 0xf2, 0x1d, 0x3c, 0x69, 0x4f, 0x2e, 0x5b, 0x98, 0x50, 0x47, 0x1e, 0xc2, 0x3f, 0xb9, 0x81, 0xef,
+ 0x38, 0x94, 0x3e, 0x76, 0x1d, 0x9d, 0xdc, 0x3d, 0x57, 0xc0, 0xbf, 0xe7, 0x0a, 0x48, 0x08, 0x8f,
+ 0xa5, 0x28, 0xa6, 0x4c, 0x73, 0xf2, 0x2d, 0x3c, 0xbe, 0x83, 0x81, 0xf3, 0xff, 0xdd, 0x04, 0xc8,
+ 0x2a, 0x01, 0xeb, 0x2f, 0xa6, 0xa6, 0xc2, 0x28, 0xa6, 0xde, 0xb9, 0xb7, 0x76, 0x91, 0x88, 0x7f,
+ 0xee, 0xc1, 0xd6, 0xa4, 0x30, 0x8a, 0x1d, 0xcf, 0x98, 0x28, 0xde, 0x56, 0xa6, 0xac, 0x0c, 0xd9,
+ 0x81, 0x41, 0xa3, 0x96, 0x1b, 0xb6, 0x22, 0xa6, 0x5b, 0x26, 0x2f, 0x61, 0x94, 0xca, 0xc2, 0x28,
+ 0x99, 0x27, 0x0f, 0x68, 0xba, 0xe9, 0x6a, 0xda, 0xef, 0x42, 0x04, 0x81, 0x54, 0x99, 0x28, 0x58,
+ 0xee, 0x2e, 0x65, 0x1b, 0x22, 0x9b, 0x63, 0x25, 0xb5, 0x7e, 0x2f, 0xd8, 0xfc, 0xda, 0x03, 0x38,
+ 0x97, 0x86, 0xff, 0xcf, 0x3c, 0xec, 0x87, 0xb2, 0x96, 0x86, 0xe3, 0xe3, 0xb8, 0x41, 0xf1, 0x77,
+ 0xfc, 0x16, 0x80, 0x72, 0x23, 0x14, 0xb7, 0xf7, 0xe6, 0xef, 0x53, 0xeb, 0x0c, 0xe9, 0x2f, 0x6f,
+ 0xf6, 0xb7, 0x1e, 0xac, 0x9d, 0x96, 0xbc, 0xc8, 0xc8, 0x1e, 0x8c, 0x74, 0xc9, 0x0b, 0x93, 0x48,
+ 0xdc, 0xf7, 0xe2, 0x83, 0xb9, 0x78, 0x1c, 0x1e, 0x61, 0x41, 0xa3, 0xcb, 0x24, 0xbb, 0xef, 0xa6,
+ 0xf6, 0xff, 0xe1, 0x4d, 0xbd, 0xd3, 0x29, 0xde, 0xdd, 0x4e, 0xe9, 0xee, 0xc4, 0x5f, 0xda, 0xc9,
+ 0x74, 0x80, 0x7f, 0x6a, 0x0e, 0xff, 0x0c, 0x00, 0x00, 0xff, 0xff, 0xc7, 0x32, 0xe6, 0x29, 0xe0,
+ 0x08, 0x00, 0x00,
}
uint64 amount = 2;
}
-message AssetDefinition {
- Program issuance_program = 1;
- Hash data = 2;
-}
-
message ValueSource {
Hash ref = 1;
AssetAmount value = 2;
uint64 ordinal = 2;
}
-message Issuance {
- Hash nonce_hash = 1;
- AssetAmount value = 2;
- ValueDestination witness_destination = 3;
- AssetDefinition witness_asset_definition = 4;
- repeated bytes witness_arguments = 5;
- uint64 ordinal = 6;
-}
-
message Spend {
Hash spent_output_id = 1;
ValueDestination witness_destination = 2;
m := NewMux([]*ValueSource{{Position: 1}}, &Program{Code: []byte{1}, VmVersion: 1})
entries := []Entry{
- NewIssuance(nil, &AssetAmount{}, 0),
m,
NewTxHeader(1, 1, 0, nil),
NewIntraChainOutput(&ValueSource{}, &Program{Code: []byte{1}, VmVersion: 1}, 0),
expectEntryID string
}{
{
- entry: NewIssuance(&Hash{V0: 0, V1: 1, V2: 2, V3: 3}, &AssetAmount{&AssetID{V0: 1, V1: 2, V2: 3, V3: 4}, 100}, 1),
- expectEntryID: "3012b9b6da3962bb2388cdf5db7f3b93a2b696fcc70e79bc5da1238a6d66ae73",
- },
- {
entry: NewMux(
[]*ValueSource{
{
+++ /dev/null
-package bc
-
-import "io"
-
-// Issuance is a source of new value on a blockchain. It satisfies the
-// Entry interface.
-
-func (Issuance) typ() string { return "issuance1" }
-func (iss *Issuance) writeForHash(w io.Writer) {
- mustWriteForHash(w, iss.NonceHash)
- mustWriteForHash(w, iss.Value)
-}
-
-// SetDestination will link the issuance to the output
-func (iss *Issuance) SetDestination(id *Hash, val *AssetAmount, pos uint64) {
- iss.WitnessDestination = &ValueDestination{
- Ref: id,
- Value: val,
- Position: pos,
- }
-}
-
-// NewIssuance creates a new Issuance.
-func NewIssuance(nonceHash *Hash, value *AssetAmount, ordinal uint64) *Issuance {
- return &Issuance{
- NonceHash: nonceHash,
- Value: value,
- Ordinal: ordinal,
- }
-}
return sp, nil
}
-// Issuance try to get the issuance entry by given hash
-func (tx *Tx) Issuance(id Hash) (*Issuance, error) {
- e, ok := tx.Entries[id]
- if !ok || e == nil {
- return nil, errors.Wrapf(ErrMissingEntry, "id %x", id.Bytes())
- }
- iss, ok := e.(*Issuance)
- if !ok {
- return nil, errors.Wrapf(ErrEntryType, "entry %x has unexpected type %T", id.Bytes(), e)
- }
- return iss, nil
-}
-
// VoteOutput try to get the vote output entry by given hash
func (tx *Tx) VoteOutput(id Hash) (*VoteOutput, error) {
e, ok := tx.Entries[id]
+++ /dev/null
-package types
-
-import (
- "bytes"
- "encoding/hex"
- "encoding/json"
- "strings"
- "testing"
-
- "github.com/davecgh/go-spew/spew"
-
- "github.com/vapor/consensus"
- "github.com/vapor/encoding/blockchain"
- "github.com/vapor/protocol/bc"
- "github.com/vapor/testutil"
-)
-
-func TestBlock(t *testing.T) {
- cases := []struct {
- block *Block
- hex string
- hash bc.Hash
- }{
- {
- block: &Block{
- BlockHeader: BlockHeader{
- Version: 1,
- Height: 1,
- },
- Transactions: []*Tx{},
- },
- hex: strings.Join([]string{
- "03", // serialization flags
- "01", // version
- "01", // block height
- "0000000000000000000000000000000000000000000000000000000000000000", // prev block hash
- "00", // timestamp
- "40", // commitment extensible field length
- "0000000000000000000000000000000000000000000000000000000000000000", // transactions merkle root
- "0000000000000000000000000000000000000000000000000000000000000000", // tx status hash
- "0100", //BlockWitness
- "00", // num transactions
- }, ""),
- hash: testutil.MustDecodeHash("ba63a0f8e9a7e5f93e3ec7ce49f07276c065bdf75e270984d9390bee0b3de027"),
- },
- {
- block: &Block{
- BlockHeader: BlockHeader{
- Version: 1,
- Height: 432234,
- PreviousBlockHash: testutil.MustDecodeHash("c34048bd60c4c13144fd34f408627d1be68f6cb4fdd34e879d6d791060ea73a0"),
- Timestamp: 1522908275,
- BlockCommitment: BlockCommitment{
- TransactionStatusHash: testutil.MustDecodeHash("b94301ea4e316bee00109f68d25beaca90aeff08e9bf439a37d91d7a3b5a1470"),
- TransactionsMerkleRoot: testutil.MustDecodeHash("ad9ac003d08ff305181a345d64fe0b02311cc1a6ec04ab73f3318d90139bfe03"),
- },
- BlockWitness: BlockWitness{Witness: [][]byte{[]byte{0xbe, 0xef}}},
- },
- Transactions: []*Tx{
- NewTx(TxData{
- Version: 1,
- SerializedSize: uint64(263),
- TimeRange: 654,
- Inputs: []*TxInput{
- NewIssuanceInput([]byte("nonce"), 254354, []byte("issuanceProgram"), [][]byte{[]byte("arguments1"), []byte("arguments2")}, []byte("assetDefinition")),
- NewSpendInput([][]byte{[]byte("arguments3"), []byte("arguments4")}, testutil.MustDecodeHash("fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409"), *consensus.BTMAssetID, 254354, 3, []byte("spendProgram")),
- },
- Outputs: []*TxOutput{
- NewIntraChainOutput(testutil.MustDecodeAsset("a69849e11add96ac7053aad22ba2349a4abf5feb0475a0afcadff4e128be76cf"), 254354, []byte("true")),
- },
- }),
- NewTx(TxData{
- Version: 1,
- SerializedSize: uint64(112),
- Inputs: []*TxInput{
- NewCoinbaseInput([]byte("arbitrary")),
- },
- Outputs: []*TxOutput{
- NewIntraChainOutput(*consensus.BTMAssetID, 254354, []byte("true")),
- NewIntraChainOutput(*consensus.BTMAssetID, 254354, []byte("false")),
- },
- }),
- },
- },
- hex: strings.Join([]string{
- "03", // serialization flags
- "01", // version
- "eab01a", // block height
- "c34048bd60c4c13144fd34f408627d1be68f6cb4fdd34e879d6d791060ea73a0", // prev block hash
- "f3f896d605", // timestamp
- "40", // commitment extensible field length
- "ad9ac003d08ff305181a345d64fe0b02311cc1a6ec04ab73f3318d90139bfe03", // transactions merkle root
- "b94301ea4e316bee00109f68d25beaca90aeff08e9bf439a37d91d7a3b5a1470", // tx status hash
- "040102beef", //BlockWitness
- "02", // num transactions
- "07018e0502012a00056e6f6e6365a69849e11add96ac7053aad22ba2349a4abf5feb0475a0afcadff4e128be76cf92c30f380f6173736574446566696e6974696f6e010f69737375616e636550726f6772616d020a617267756d656e7473310a617267756d656e74733201540152fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff92c30f03010c7370656e6450726f6772616d17020a617267756d656e7473330a617267756d656e74733401012b0029a69849e11add96ac7053aad22ba2349a4abf5feb0475a0afcadff4e128be76cf92c30f01047472756500",
- "07010001010b02096172626974726172790002012b0029ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff92c30f01047472756500012c002affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff92c30f010566616c736500",
- }, ""),
- hash: testutil.MustDecodeHash("fca0cfd96604b0b28e4a16286974db155d0bbd42dd729d2e2ba058d09a963016"),
- },
- }
-
- for i, test := range cases {
- got := testutil.Serialize(t, test.block)
- want, err := hex.DecodeString(test.hex)
- if err != nil {
- t.Fatal(err)
- }
-
- if !bytes.Equal(got, want) {
- t.Errorf("test %d: bytes = %x want %x", i, got, want)
- }
-
- blockHash := test.block.Hash()
- if blockHash != test.hash {
- t.Errorf("test %d: hash = %s want %s", i, blockHash.String(), test.hash.String())
- }
-
- blockJSON, err := json.Marshal(test.block)
- if err != nil {
- t.Errorf("test %d: error marshaling block to json: %s", i, err)
- }
-
- blockFromJSON := Block{}
- if err := json.Unmarshal(blockJSON, &blockFromJSON); err != nil {
- t.Errorf("test %d: error unmarshaling block from json: %s", i, err)
- }
- if !testutil.DeepEqual(*test.block, blockFromJSON) {
- t.Errorf("test %d: got:\n%s\nwant:\n%s", i, spew.Sdump(blockFromJSON), spew.Sdump(*test.block))
- }
- }
-}
-
-func TestReadFrom(t *testing.T) {
- btmAssetID := testutil.MustDecodeAsset("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
-
- cases := []struct {
- rawBlock string
- wantBlock Block
- }{
- {
- rawBlock: "03018b5f3077f24528e94ecfc4491bb2e9ed6264a632a9a4b86b00c88093ca545d14a137d4f5e1e4054035a2d11158f47a5c5267630b2b6cf9e9a5f79a598085a2572a68defeb8013ad26978a65b4ee5b6f4914fe5c05000459a803ecf59132604e5d334d64249c5e50a010002070100010108020600313231373100010140003effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff809df3b49a010116001437e1aec83a4e6587ca9609e4e5aa728db700744900070100020160015e4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adeaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c480c1240201160014cb9f2391bafe2bc1159b2c4c8a0f17ba1b4dd94e6302405760b15cc09e543437c4e3aad05bf073e82ebdb214beccb5f4473653dfc0a9d5ae59fb149de19eb71c1c1399594757aeea4dd6327ca2790ef919bd20caa86104201381d35e235813ad1e62f9a602c82abee90565639cc4573568206b55bcd2aed90130000840142084606f20ca7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad1480d0dbc3f402b001467b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d0125ae2054a71277cc162eb3eb21b5bd9fe54402829a53b294deaed91692a2cd8a081f9c5151ad0140621c2c3554da50d2a492d9d78be7c6159359d8f5f0b93a054ce0133617a61d85c532aff449b97a3ec2804ca5fe12b4d54aa6e8c3215c33d04abee9c9abdfdb0302013f003dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c0d1e123011600144b61da45324299e40dacc255e2ea07dfce3a56d2000140003e7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad1480d0dbc3f4020116001437e1aec83a4e6587ca9609e4e5aa728db700744900",
- wantBlock: Block{
- BlockHeader: BlockHeader{
- Version: 1,
- Height: 12171,
- PreviousBlockHash: testutil.MustDecodeHash("3077f24528e94ecfc4491bb2e9ed6264a632a9a4b86b00c88093ca545d14a137"),
- Timestamp: 1553496788,
- BlockCommitment: BlockCommitment{
- TransactionsMerkleRoot: testutil.MustDecodeHash("35a2d11158f47a5c5267630b2b6cf9e9a5f79a598085a2572a68defeb8013ad2"),
- TransactionStatusHash: testutil.MustDecodeHash("6978a65b4ee5b6f4914fe5c05000459a803ecf59132604e5d334d64249c5e50a"),
- },
- },
- Transactions: []*Tx{
- {
- TxData: TxData{
- Version: 1,
- SerializedSize: 83,
- TimeRange: 0,
- Inputs: []*TxInput{
- NewCoinbaseInput(testutil.MustDecodeHexString("003132313731")),
- },
- Outputs: []*TxOutput{
- NewIntraChainOutput(btmAssetID, 41450000000, testutil.MustDecodeHexString("001437e1aec83a4e6587ca9609e4e5aa728db7007449")),
- },
- },
- },
- {
- TxData: TxData{
- Version: 1,
- SerializedSize: 564,
- TimeRange: 0,
- Inputs: []*TxInput{
- NewSpendInput(
- [][]byte{
- testutil.MustDecodeHexString("5760b15cc09e543437c4e3aad05bf073e82ebdb214beccb5f4473653dfc0a9d5ae59fb149de19eb71c1c1399594757aeea4dd6327ca2790ef919bd20caa86104"),
- testutil.MustDecodeHexString("1381d35e235813ad1e62f9a602c82abee90565639cc4573568206b55bcd2aed9"),
- },
- testutil.MustDecodeHash("4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adea"),
- btmAssetID,
- 9800000000,
- 2,
- testutil.MustDecodeHexString("0014cb9f2391bafe2bc1159b2c4c8a0f17ba1b4dd94e"),
- ),
- NewIssuanceInput(
- testutil.MustDecodeHexString("40142084606f20ca"),
- 100000000000,
- testutil.MustDecodeHexString("ae2054a71277cc162eb3eb21b5bd9fe54402829a53b294deaed91692a2cd8a081f9c5151ad"),
- [][]byte{testutil.MustDecodeHexString("621c2c3554da50d2a492d9d78be7c6159359d8f5f0b93a054ce0133617a61d85c532aff449b97a3ec2804ca5fe12b4d54aa6e8c3215c33d04abee9c9abdfdb03")},
- testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
- ),
- },
- Outputs: []*TxOutput{
- NewIntraChainOutput(btmAssetID, 9600000000, testutil.MustDecodeHexString("00144b61da45324299e40dacc255e2ea07dfce3a56d2")),
- NewIntraChainOutput(testutil.MustDecodeAsset("7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad14"), 100000000000, testutil.MustDecodeHexString("001437e1aec83a4e6587ca9609e4e5aa728db7007449")),
- },
- },
- },
- },
- },
- },
- }
-
- for _, c := range cases {
- blockBytes, err := hex.DecodeString(c.rawBlock)
- if err != nil {
- t.Fatal(err)
- }
-
- block := &Block{}
- if err := block.readFrom(blockchain.NewReader(blockBytes)); err != nil {
- t.Fatal(err)
- }
-
- for _, tx := range c.wantBlock.Transactions {
- tx.Tx = MapTx(&tx.TxData)
- }
-
- if !testutil.DeepEqual(*block, c.wantBlock) {
- t.Errorf("test block read from fail, got:%v, want:%v", *block, c.wantBlock)
- }
- }
-}
+++ /dev/null
-package types
-
-import (
- "github.com/vapor/crypto/sha3pool"
- "github.com/vapor/protocol/bc"
-)
-
-// IssuanceInput satisfies the TypedInput interface and represents a issuance.
-type IssuanceInput struct {
- Nonce []byte
- Amount uint64
-
- AssetDefinition []byte
- VMVersion uint64
- IssuanceProgram []byte
- Arguments [][]byte
-}
-
-// NewIssuanceInput create a new IssuanceInput struct.
-func NewIssuanceInput(nonce []byte, amount uint64, issuanceProgram []byte, arguments [][]byte, assetDefinition []byte) *TxInput {
- return &TxInput{
- AssetVersion: 1,
- TypedInput: &IssuanceInput{
- Nonce: nonce,
- Amount: amount,
- AssetDefinition: assetDefinition,
- VMVersion: 1,
- IssuanceProgram: issuanceProgram,
- Arguments: arguments,
- },
- }
-}
-
-// InputType is the interface function for return the input type.
-func (ii *IssuanceInput) InputType() uint8 { return IssuanceInputType }
-
-// AssetID calculate the assetID of the issuance input.
-func (ii *IssuanceInput) AssetID() bc.AssetID {
- defhash := ii.AssetDefinitionHash()
- return bc.ComputeAssetID(ii.IssuanceProgram, ii.VMVersion, &defhash)
-}
-
-// AssetDefinitionHash return the hash of the issuance asset definition.
-func (ii *IssuanceInput) AssetDefinitionHash() (defhash bc.Hash) {
- sha := sha3pool.Get256()
- defer sha3pool.Put256(sha)
- sha.Write(ii.AssetDefinition)
- defhash.ReadFrom(sha)
- return defhash
-}
-
-// NonceHash return the hash of the issuance asset definition.
-func (ii *IssuanceInput) NonceHash() (hash bc.Hash) {
- sha := sha3pool.Get256()
- defer sha3pool.Put256(sha)
- sha.Write(ii.Nonce)
- hash.ReadFrom(sha)
- return hash
-}
for id, e := range entries {
var ord uint64
switch e := e.(type) {
- case *bc.Issuance:
- ord = e.Ordinal
-
case *bc.Spend:
ord = e.Ordinal
spentOutputIDs[*e.SpentOutputId] = true
}
var (
- spends []*bc.Spend
- issuances []*bc.Issuance
- coinbase *bc.Coinbase
+ spends []*bc.Spend
+ 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}
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)
- }
if coinbase != nil {
coinbase.SetDestination(&muxID, mux.Sources[0].Value, 0)
NewIntraChainOutput(*consensus.BTMAssetID, 80, []byte{1}),
},
},
- &TxData{
- Inputs: []*TxInput{
- NewIssuanceInput([]byte("nonce"), 254354, []byte("issuanceProgram"), [][]byte{[]byte("arguments1"), []byte("arguments2")}, []byte("assetDefinition")),
- },
- Outputs: []*TxOutput{
- NewIntraChainOutput(*consensus.BTMAssetID, 80, []byte{1}),
- },
- },
- &TxData{
- Inputs: []*TxInput{
- NewIssuanceInput([]byte("nonce"), 254354, []byte("issuanceProgram"), [][]byte{[]byte("arguments1"), []byte("arguments2")}, []byte("assetDefinition")),
- NewSpendInput(nil, testutil.MustDecodeHash("db7b16ac737440d6e38559996ddabb207d7ce84fbd6f3bfd2525d234761dc863"), *consensus.BTMAssetID, 88, 3, []byte{1}),
- },
- Outputs: []*TxOutput{
- NewIntraChainOutput(*consensus.BTMAssetID, 80, []byte{1}),
- NewIntraChainOutput(*consensus.BTMAssetID, 80, []byte{1}),
- },
- },
}
for _, txData := range cases {
t.Errorf("entryMap contains nothing for tx.InputIDs[%d] (%x)", i, tx.InputIDs[i].Bytes())
}
switch newInput := resultEntry.(type) {
- case *bc.Issuance:
- if *newInput.Value.AssetId != oldIn.AssetID() || newInput.Value.Amount != oldIn.Amount() {
- t.Errorf("tx.InputIDs[%d]'s asset amount is not equal after map'", i)
- }
case *bc.Spend:
spendOut, err := tx.IntraChainOutput(*newInput.SpentOutputId)
if err != nil {
import (
"encoding/hex"
-
"math/rand"
"testing"
- "time"
"github.com/vapor/protocol/bc"
"github.com/vapor/protocol/vm"
}
}
-func TestMerkleRootRealTx(t *testing.T) {
- rawTxs := []string{
- "070100010160015e5ac79a73db78e5c9215b37cb752f0147d1157c542bb4884908ceb97abc33fe0affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0f280d42b0001160014085a02ecdf934a56343aa59a3dec9d9feb86ee43630240035e1ef422b4901997ad3c20c50d82e726d03cb6e8ccb5dddc20e0c09e0a6f2e0055331e2b54d9ec52cffb1c47d8fdf2f8887d55c336753637cbf8f832c7af0b20a29601468f08c57ca9c383d28736a9d5c7737cd483126d8db3d85490fe497b3502013f003dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0aad1b30601160014991b78d1bf731390e2dd838c05ff37ec5146886b00013f003dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8086d8f024011600145ade29df622cc68d0473aa1a20fb89690451c66e00",
- "070100020160015e4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adeaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c480c1240201160014cb9f2391bafe2bc1159b2c4c8a0f17ba1b4dd94e630240d96b8f31519c5e34ef983bb7dfb92e807df7fc1ae5a4c08846d00d4f84ebd2f8634b9e0b0374eb2508d0f989520f622aef051862c26daba0e466944e3d55d00b201381d35e235813ad1e62f9a602c82abee90565639cc4573568206b55bcd2aed901300008ede605460cacbf107b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad1480d0dbc3f402b001467b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d0125ae2054a71277cc162eb3eb21b5bd9fe54402829a53b294deaed91692a2cd8a081f9c5151ad01403a54a3ca0210d005cc9bce490478b518c405ba72e0bc1d134b739f29a73e008345229f0e061c420aa3c56a48bc1c9bf592914252ab9100e69252deeac532430f03013f003dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80e0e8f011011600144ab5249140ca4630729030941f59f75e507bd4d5000140003e7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad1480d0dbc3f402011600145ade29df622cc68d0473aa1a20fb89690451c66e00013f003dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80a2c0a012011600145ade29df622cc68d0473aa1a20fb89690451c66e00",
- "07010001016c016acf24f1471d67c25a01ac84482ecdd8550229180171cae22321f87fe43d4f6a13ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80b4c4c32101012200200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac66ef02044059c7a12d006fd34bf8b9b2cb2f99756e5c3c3fdca4c928b830c014819e933b01c92a99bfeb6add73a5087870a3de3465cfed2c99f736b5f77d5fbdc69d91ff0040b95d110d118b873a8232104a6613f0e8c6a791efa3a695c02108cebd5239c8a8471551a48f18ab8ea05d10900b485af5e95b74cd3c01044c1742e71854099c0b40a1b63dae273e3b5b757b7c61286088a934e7282e837d08d62e60d7f75eb739529cd8c6cfef2254d47a546bf8b789657ce0944fec2f7e130c8498e28cae2a9108a901ae20d441b6f375659325a04eede4fc3b74579bb08ccd05b41b99776501e22d6dca7320af6d98ca2c3cd10bf0affbfa6e86609b750523cfadb662ec963c164f05798a49209820b9f1553b03aaebe7e3f9e9222ed7db73b5079b18564042fd3b2cef74156a20271b52de5f554aa4a6f1358f1c2193617bfb3fed4546d13c4af773096a429f9420eeb4a78d8b5cb8283c221ca2d3fd96b8946b3cddee02b7ceffb8f605932588595355ad02014b0049ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80a0d9e61d012200206e8060ef3daca62841802dd9660b24b7dca81c1662b2d68ba8884ecbcd3e1e2200013f003dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80d293ad0301160014ed7d3c466dbc6cc1f3a9af21267ac162f11b30a200",
- "070100020161015f4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adea0dafd0f0e42f06f3bf9a8cf5787519d3860650f27a2b3393d34e1fe06e89b469ddc3f8c2f40200011600141da7f908979e521bf2ba12d280b2c84fc1d024416302409524d0d817176eeb718ce45671d95831cdb138d27289aa8a920104e38a8cab8a7dc8cc3fb60d65aa337b719aed0f696fb12610bfe68add89169a47ac1241e0002033444e1b57524161af3899e50fdfe270a90a1ea97fe38e86019a1e252667fb2d0161015fed3181c99ca80db720231aee6948e1183bfe29c64208c1769afa7f938d3b2cf0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff809cd2b0f4020101160014cfbccfac5018ad4b4bfbcb1fab834e3c8503746063024065beb1da2f0840188af0e3c0127b158f7a2a36f1612499694a731df1e3a9d1abe6694c42986b8700aa9856f59cb3692ee88d68b20d1278f05592fb253c58bd0520e5966eee4092eeefdd805b06f2ad368bb9392edec20998993ebe2a929052c1ce030140003e0dafd0f0e42f06f3bf9a8cf5787519d3860650f27a2b3393d34e1fe06e89b469ddfbc8a2cf0201160014583c0323603dd397ba5414255adc80b076cf232b00013f003d0dafd0f0e42f06f3bf9a8cf5787519d3860650f27a2b3393d34e1fe06e89b46980c8afa02501160014fdb3e6abf7f430fdabb53484ca2469103b2af1b5000140003effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80dafa80f4020116001408e75789f47d2a39622e5a940fa918260bf44c5400",
- "07010001016d016b1f134a47da4f6df00822935e02a07514718ea99ce5ac4e07bd6c204e098eb525ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808a858fa70200012200206205ec178dc1ac6ea05ea01bb0fcda6aa978173026fa75204a101bdad7bd6b4889010240d8d5bbf4969fba52df8fba06f75c5de0f51b2bd5f902bf234591f90e78bae20bfb5b7904cb83a1d6577c431f644d37722b432df9d64718b8300e3ab74a871a0046ae2068003e53d467b6d81beaf1e7bd9b60a5ffedc79b36ce14ecd1f30a2dcbcd0551200449030407a3a1fa0731f7f784a72c325b5ce4d534fc3cf8fb7140536ba928605152ad02014c004affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80f699b2a302012200209a0b4b27fde7d29d3b465d20eb2e19f4bda3a873d19d11f4cba53958bde92ed000013f003dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80b3ffc40301160014ed7d3c466dbc6cc1f3a9af21267ac162f11b30a200",
- }
- wantMerkleRoot := "9100f5258bdc059d911b745eada2afb3a64008e91d64e245d7b3729b8909f0c1"
-
- var txs []*bc.Tx
- for i, rawTx := range rawTxs {
- tx := Tx{}
- if err := tx.UnmarshalText([]byte(rawTx)); err != nil {
- t.Fatalf("case#%d, %v", i, err)
- }
-
- txs = append(txs, tx.Tx)
- }
-
- gotMerkleRoot, err := TxMerkleRoot(txs)
- if err != nil {
- t.Fatal(err)
- }
-
- if wantMerkleRoot != gotMerkleRoot.String() {
- t.Errorf("got merkle root:%s, want merkle root:%s", gotMerkleRoot.String(), wantMerkleRoot)
- }
-}
-
func TestDuplicateLeaves(t *testing.T) {
trueProg := []byte{byte(vm.OP_TRUE)}
- assetID := bc.ComputeAssetID(trueProg, 1, &bc.EmptyStringHash)
+ assetID := bc.AssetID{V0: 9999}
txs := make([]*bc.Tx, 6)
for i := uint64(0); i < 6; i++ {
- now := []byte(time.Now().String())
txs[i] = NewTx(TxData{
Version: 1,
- Inputs: []*TxInput{NewIssuanceInput(now, i, trueProg, nil, nil)},
Outputs: []*TxOutput{NewIntraChainOutput(assetID, i, trueProg)},
}).Tx
}
func TestAllDuplicateLeaves(t *testing.T) {
trueProg := []byte{byte(vm.OP_TRUE)}
- assetID := bc.ComputeAssetID(trueProg, 1, &bc.EmptyStringHash)
- now := []byte(time.Now().String())
- issuanceInp := NewIssuanceInput(now, 1, trueProg, nil, nil)
+ assetID := bc.AssetID{V0: 9999}
tx := NewTx(TxData{
Version: 1,
- Inputs: []*TxInput{issuanceInp},
Outputs: []*TxOutput{NewIntraChainOutput(assetID, 1, trueProg)},
}).Tx
tx1, tx2, tx3, tx4, tx5, tx6 := tx, tx, tx, tx, tx, tx
var txs []*Tx
var bcTxs []*bc.Tx
trueProg := []byte{byte(vm.OP_TRUE)}
- assetID := bc.ComputeAssetID(trueProg, 1, &bc.EmptyStringHash)
- for i := 0; i < txCount; i++ {
- now := []byte(time.Now().String())
- issuanceInp := NewIssuanceInput(now, 1, trueProg, nil, nil)
+ assetID := bc.AssetID{V0: 9999}
+ for i := uint64(0); i < uint64(txCount); i++ {
tx := NewTx(TxData{
Version: 1,
- Inputs: []*TxInput{issuanceInp},
+ Inputs: []*TxInput{NewSpendInput(nil, bc.Hash{V0: i + 1}, assetID, i, i, trueProg)},
Outputs: []*TxOutput{NewIntraChainOutput(assetID, 1, trueProg)},
})
txs = append(txs, tx)
id := tx.Tx.InputIDs[n]
e := tx.Entries[id]
switch e := e.(type) {
- case *bc.Issuance:
- e.WitnessArguments = args
case *bc.Spend:
e.WitnessArguments = args
}
{
tx: NewTx(TxData{
Version: 1,
- SerializedSize: uint64(263),
- TimeRange: 654,
- Inputs: []*TxInput{
- NewIssuanceInput([]byte("nonce"), 254354, []byte("issuanceProgram"), [][]byte{[]byte("arguments1"), []byte("arguments2")}, []byte("assetDefinition")),
- NewSpendInput([][]byte{[]byte("arguments3"), []byte("arguments4")}, testutil.MustDecodeHash("fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409"), *consensus.BTMAssetID, 254354, 3, []byte("spendProgram")),
- },
- Outputs: []*TxOutput{
- NewIntraChainOutput(testutil.MustDecodeAsset("a69849e11add96ac7053aad22ba2349a4abf5feb0475a0afcadff4e128be76cf"), 254354, []byte("true")),
- },
- }),
- hex: strings.Join([]string{
- "07", // serflags
- "01", // transaction version
- "8e05", // tx time range
- "02", // inputs count
- "01", // input 0: asset version
- "2a", // input 0: serialization length
- "00", // input 0: issuance type flag
- "05", // input 0: nonce length
- "6e6f6e6365", // input 0: nonce
- "a69849e11add96ac7053aad22ba2349a4abf5feb0475a0afcadff4e128be76cf", // input 0: assetID
- "92c30f", // input 0: amount
- "38", // input 0: input witness length
- "0f", // input 0: asset definition length
- "6173736574446566696e6974696f6e", // input 0: asset definition
- "01", // input 0: vm version
- "0f", // input 0: issuanceProgram length
- "69737375616e636550726f6772616d", // input 0: issuance program
- "02", // input 0: argument array length
- "0a", // input 0: first argument length
- "617267756d656e747331", // input 0: first argument data
- "0a", // input 0: second argument length
- "617267756d656e747332", // input 0: second argument data
- "01", // input 1: asset version
- "54", // input 1: input commitment length
- "01", // input 1: spend type flag
- "52", // input 1: spend commitment length
- "fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409", // input 1: source id
- "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // input 1: assetID
- "92c30f", // input 1: amount
- "03", // input 1: source position
- "01", // input 1: vm version
- "0c", // input 1: spend program length
- "7370656e6450726f6772616d", // input 1: spend program
- "17", // input 1: witness length
- "02", // input 1: argument array length
- "0a", // input 1: first argument length
- "617267756d656e747333", // input 1: first argument data
- "0a", // input 1: second argument length
- "617267756d656e747334", // input 1: second argument data
- "01", // outputs count
- "01", // output 0: asset version
- "2b", // output 0: serialization length
- "00", // output 0: outType
- "29", // output 0: output commitment length
- "a69849e11add96ac7053aad22ba2349a4abf5feb0475a0afcadff4e128be76cf", // output 0: assetID
- "92c30f", // output 0: amount
- "01", // output 0: version
- "04", // output 0: control program length
- "74727565", // output 0: control program
- "00", // output 0: witness length
- }, ""),
- hash: testutil.MustDecodeHash("d6a1f6ea3cc3c53c3cdcd10bbd446c643f23b37ca5e87665d03f204de8c7dc2a"),
- },
- {
- tx: NewTx(TxData{
- Version: 1,
SerializedSize: uint64(112),
Inputs: []*TxInput{
NewCoinbaseInput([]byte("arbitrary")),
}
}
-func TestTransactionTrailingGarbage(t *testing.T) {
- // validTxHex is a valid tx, we don't care what's inside as long as it's valid
- validTxHex := `07010001012b00030a0908916133a0d64d1d973b631e226ef95338ad4a536b95635f32f0d04708a6f2a26380a094a58d1d0900010101010301020301012b0029000000000000000000000000000000000000000000000000000000000000000080a094a58d1d01010100`
- validTx := Tx{}
- if err := validTx.UnmarshalText([]byte(validTxHex)); err != nil {
- t.Fatal(err)
- }
-
- invalidTxHex := validTxHex + strings.Repeat("00", 10)
- invalidTx := Tx{}
- if err := invalidTx.UnmarshalText([]byte(invalidTxHex)); err == nil {
- t.Fatal("expected error with trailing garbage but got nil")
- }
-}
-
-func TestInvalidIssuance(t *testing.T) {
- hex := strings.Join([]string{
- "07", // serflags
- "01", // transaction version
- "00", // tx maxtime
- "01", // inputs count
- "01", // input 0, asset version
- "2b", // input 0, input commitment length prefix
- "00", // input 0, input commitment, "issuance" type
- "03", // input 0, input commitment, nonce length prefix
- "0a0908", // input 0, input commitment, nonce
- "0000000000000000000000000000000000000000000000000000000000000000", // input 0, input commitment, WRONG asset id
- "80a094a58d1d", // input 0, input commitment, amount
- "29", // input 0, issuance input witness length prefix
- "03deff1d4319d67baa10a6d26c1fea9c3e8d30e33474efee1a610a9bb49d758d", // input 0, issuance input witness, initial block
- "00", // input 0, issuance input witness, asset definition
- "01", // input 0, issuance input witness, vm version
- "01", // input 0, issuance input witness, issuance program length prefix
- "01", // input 0, issuance input witness, issuance program
- "01", // input 0, issuance input witness, arguments count
- "03", // input 0, issuance input witness, argument 0 length prefix
- "010203", // input 0, issuance input witness, argument 0
- "01", // outputs count
- "01", // output 0, asset version
- "2b", // output 0, serialization length
- "00", // output 0, outType
- "29", // output 0, output commitment length
- "0000000000000000000000000000000000000000000000000000000000000000", // output 0, output commitment, asset id
- "80a094a58d1d", // output 0, output commitment, amount
- "01", // output 0, output commitment, vm version
- "0101", // output 0, output commitment, control program
- "066f7574707574", // output 0, reference data
- "00", // output 0, output witness
- "0869737375616e6365",
- }, "")
-
- tx := new(TxData)
- if err := tx.UnmarshalText([]byte(hex)); errors.Root(err) != errBadAssetID {
- t.Errorf("want errBadAssetID, got %v", err)
- }
-}
-
-func TestFuzzUnknownAssetVersion(t *testing.T) {
- rawTx := `07010001012b00030a0908916133a0d64d1d973b631e226ef95338ad4a536b95635f32f0d04708a6f2a26380a094a58d1d0900010101010301020301012b0029000000000000000000000000000000000000000000000000000000000000000080a094a58d1d01010100`
- want := Tx{}
- if err := want.UnmarshalText([]byte(rawTx)); err != nil {
- t.Fatal(err)
- }
-
- b, err := want.MarshalText()
- if err != nil {
- t.Fatal(err)
- }
-
- got := Tx{}
- if err = got.UnmarshalText(b); err != nil {
- t.Fatal(err)
- }
- if got.ID.String() != want.ID.String() {
- t.Errorf("tx id changed to %s", got.ID.String())
- }
-}
-
func BenchmarkTxWriteToTrue(b *testing.B) {
tx := &Tx{}
for i := 0; i < b.N; i++ {
// AssetAmount return the asset id and amount of the txinput.
func (t *TxInput) AssetAmount() bc.AssetAmount {
switch inp := t.TypedInput.(type) {
- case *IssuanceInput:
- assetID := inp.AssetID()
- return bc.AssetAmount{
- AssetId: &assetID,
- Amount: inp.Amount,
- }
case *SpendInput:
return inp.AssetAmount
}
// AssetID return the assetID of the txinput
func (t *TxInput) AssetID() bc.AssetID {
switch inp := t.TypedInput.(type) {
- case *IssuanceInput:
- return inp.AssetID()
case *SpendInput:
return *inp.AssetId
// Amount return the asset amount of the txinput
func (t *TxInput) Amount() uint64 {
switch inp := t.TypedInput.(type) {
- case *IssuanceInput:
- return inp.Amount
case *SpendInput:
return inp.Amount
}
return nil
}
-// IssuanceProgram return the control program of the issuance input
-func (t *TxInput) IssuanceProgram() []byte {
- if ii, ok := t.TypedInput.(*IssuanceInput); ok {
- return ii.IssuanceProgram
- }
- return nil
-}
-
-// AssetDefinition return the asset definition of the issuance input
-func (t *TxInput) AssetDefinition() []byte {
- if ii, ok := t.TypedInput.(*IssuanceInput); ok {
- return ii.AssetDefinition
- }
- return nil
-}
-
// Arguments get the args for the input
func (t *TxInput) Arguments() [][]byte {
switch inp := t.TypedInput.(type) {
- case *IssuanceInput:
- return inp.Arguments
case *SpendInput:
return inp.Arguments
}
// SetArguments set the args for the input
func (t *TxInput) SetArguments(args [][]byte) {
switch inp := t.TypedInput.(type) {
- case *IssuanceInput:
- inp.Arguments = args
case *SpendInput:
inp.Arguments = args
}
return err
}
- var assetID bc.AssetID
t.CommitmentSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
if t.AssetVersion != 1 {
return nil
return errors.Wrap(err, "reading input commitment type")
}
switch icType[0] {
- case IssuanceInputType:
- ii := new(IssuanceInput)
- t.TypedInput = ii
-
- if ii.Nonce, err = blockchain.ReadVarstr31(r); err != nil {
- return err
- }
- if _, err = assetID.ReadFrom(r); err != nil {
- return err
- }
- if ii.Amount, err = blockchain.ReadVarint63(r); err != nil {
- return err
- }
-
case SpendInputType:
si := new(SpendInput)
t.TypedInput = si
}
switch inp := t.TypedInput.(type) {
- case *IssuanceInput:
- if inp.AssetDefinition, err = blockchain.ReadVarstr31(r); err != nil {
- return err
- }
- if inp.VMVersion, err = blockchain.ReadVarint63(r); err != nil {
- return err
- }
- if inp.IssuanceProgram, err = blockchain.ReadVarstr31(r); err != nil {
- return err
- }
- if inp.AssetID() != assetID {
- return errBadAssetID
- }
- if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
- return err
- }
-
case *SpendInput:
if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
return err
}
switch inp := t.TypedInput.(type) {
- case *IssuanceInput:
- if _, err = w.Write([]byte{IssuanceInputType}); err != nil {
- return err
- }
- if _, err = blockchain.WriteVarstr31(w, inp.Nonce); err != nil {
- return err
- }
- assetID := t.AssetID()
- if _, err = assetID.WriteTo(w); err != nil {
- return err
- }
- _, err = blockchain.WriteVarint63(w, inp.Amount)
- return err
-
case *SpendInput:
if _, err = w.Write([]byte{SpendInputType}); err != nil {
return err
}
switch inp := t.TypedInput.(type) {
- case *IssuanceInput:
- if _, err := blockchain.WriteVarstr31(w, inp.AssetDefinition); err != nil {
- return err
- }
- if _, err := blockchain.WriteVarint63(w, inp.VMVersion); err != nil {
- return err
- }
- if _, err := blockchain.WriteVarstr31(w, inp.IssuanceProgram); err != nil {
- return err
- }
- _, err := blockchain.WriteVarstrList(w, inp.Arguments)
- return err
-
case *SpendInput:
_, err := blockchain.WriteVarstrList(w, inp.Arguments)
return err
"github.com/vapor/testutil"
)
-func TestSerializationIssuance(t *testing.T) {
- arguments := [][]byte{
- []byte("arguments1"),
- []byte("arguments2"),
- }
- issuance := NewIssuanceInput([]byte("nonce"), 254354, []byte("issuanceProgram"), arguments, []byte("assetDefinition"))
-
- wantHex := strings.Join([]string{
- "01", // asset version
- "2a", // serialization length
- "00", // issuance type flag
- "05", // nonce length
- "6e6f6e6365", // nonce
- "a69849e11add96ac7053aad22ba2349a4abf5feb0475a0afcadff4e128be76cf", // assetID
- "92c30f", // amount
- "38", // input witness length
- "0f", // asset definition length
- "6173736574446566696e6974696f6e", // asset definition
- "01", // vm version
- "0f", // issuanceProgram length
- "69737375616e636550726f6772616d", // issuance program
- "02", // argument array length
- "0a", // first argument length
- "617267756d656e747331", // first argument data
- "0a", // second argument length
- "617267756d656e747332", // second argument data
- }, "")
-
- // Test convert struct to hex
- var buffer bytes.Buffer
- if err := issuance.writeTo(&buffer); err != nil {
- t.Fatal(err)
- }
-
- gotHex := hex.EncodeToString(buffer.Bytes())
- if gotHex != wantHex {
- t.Errorf("serialization bytes = %s want %s", gotHex, wantHex)
- }
-
- // Test convert hex to struct
- var gotIssuance TxInput
- decodeHex, err := hex.DecodeString(wantHex)
- if err != nil {
- t.Fatal(err)
- }
-
- if err := gotIssuance.readFrom(blockchain.NewReader(decodeHex)); err != nil {
- t.Fatal(err)
- }
-
- if !testutil.DeepEqual(*issuance, gotIssuance) {
- t.Errorf("expected marshaled/unmarshaled txinput to be:\n%sgot:\n%s", spew.Sdump(*issuance), spew.Sdump(gotIssuance))
- }
-}
-
func TestSerializationSpend(t *testing.T) {
arguments := [][]byte{
[]byte("arguments1"),
},
{
category: "input output unbalance",
- desc: "issuance asset, no corresponding output",
- insts: []*signingInst{singleSignInst, singleSignInst},
- txData: types.TxData{
- Version: 1,
- Inputs: []*types.TxInput{
- types.NewSpendInput(nil,
- bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
- *consensus.BTMAssetID, 10000000000, 0, nil),
- types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
- testutil.MustDecodeHexString("fd0aec4229deb281"),
- 10000000000,
- nil,
- nil,
- testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
- ),
- },
- Outputs: []*types.TxOutput{
- types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
- },
- },
- err: true,
- gasValid: false,
- },
- {
- category: "input output unbalance",
- desc: "issuance asset A, output asset B",
- insts: []*signingInst{singleSignInst, singleSignInst},
- txData: types.TxData{
- Version: 1,
- Inputs: []*types.TxInput{
- types.NewSpendInput(nil,
- bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
- *consensus.BTMAssetID, 10000000000, 0, nil),
- types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
- testutil.MustDecodeHexString("fd0aec4229deb281"),
- 10000000000,
- nil,
- nil,
- testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
- ),
- },
- Outputs: []*types.TxOutput{
- types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
- types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707e"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
- },
- },
- err: true,
- gasValid: false,
- },
- {
- category: "input output unbalance",
- desc: "sum of output asset A greater than issuance asset A",
- insts: []*signingInst{singleSignInst, singleSignInst},
- txData: types.TxData{
- Version: 1,
- Inputs: []*types.TxInput{
- types.NewSpendInput(nil,
- bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
- *consensus.BTMAssetID, 10000000000, 0, nil),
- types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
- testutil.MustDecodeHexString("fd0aec4229deb281"),
- 10000000000,
- nil,
- nil,
- testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
- ),
- },
- Outputs: []*types.TxOutput{
- types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
- types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 20000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
- },
- },
- err: true,
- gasValid: false,
- },
- {
- category: "input output unbalance",
- desc: "sum of output asset A less than issuance asset A",
- insts: []*signingInst{singleSignInst, singleSignInst},
- txData: types.TxData{
- Version: 1,
- Inputs: []*types.TxInput{
- types.NewSpendInput(nil,
- bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
- *consensus.BTMAssetID, 10000000000, 0, nil),
- types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
- testutil.MustDecodeHexString("fd0aec4229deb281"),
- 10000000000,
- nil,
- nil,
- testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
- ),
- },
- Outputs: []*types.TxOutput{
- types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
- types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 5000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
- },
- },
- err: true,
- gasValid: false,
- },
- {
- category: "input output unbalance",
- desc: "sum of retire asset A greater than issuance asset A",
- insts: []*signingInst{singleSignInst, singleSignInst},
- txData: types.TxData{
- Version: 1,
- Inputs: []*types.TxInput{
- types.NewSpendInput(nil,
- bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
- *consensus.BTMAssetID, 10000000000, 0, nil),
- types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
- testutil.MustDecodeHexString("fd0aec4229deb281"),
- 10000000000,
- nil,
- nil,
- testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
- ),
- },
- Outputs: []*types.TxOutput{
- types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
- types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 20000000000, testutil.MustDecodeHexString("6a")),
- },
- },
- err: true,
- gasValid: false,
- },
- {
- category: "input output unbalance",
- desc: "sum of retire asset A less than issuance asset A",
- insts: []*signingInst{singleSignInst, singleSignInst},
- txData: types.TxData{
- Version: 1,
- Inputs: []*types.TxInput{
- types.NewSpendInput(nil,
- bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
- *consensus.BTMAssetID, 10000000000, 0, nil),
- types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
- testutil.MustDecodeHexString("fd0aec4229deb281"),
- 10000000000,
- nil,
- nil,
- testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
- ),
- },
- Outputs: []*types.TxOutput{
- types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
- types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 5000000000, testutil.MustDecodeHexString("6a")),
- },
- },
- err: true,
- gasValid: false,
- },
- {
- category: "input output unbalance",
desc: "spend asset A, no corresponding output",
insts: []*signingInst{singleSignInst, singleSignInst},
txData: types.TxData{
},
{
category: "overflow",
- desc: "issuance non btm input overflow",
- insts: []*signingInst{singleSignInst, singleSignInst, singleSignInst},
- txData: types.TxData{
- Version: 1,
- Inputs: []*types.TxInput{
- types.NewSpendInput(nil,
- bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
- *consensus.BTMAssetID, 10000000000, 1, nil),
- types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
- testutil.MustDecodeHexString("fd0aec4229deb281"),
- math.MaxInt64,
- nil,
- [][]byte{
- testutil.MustDecodeHexString("e8f301f7bd3b1e4ca853b15559b3a253a4f5f9c7efba233ab0f6896bec23adc6a816c350e08f6b8ac5bc23eb5720173f9190805328af581f34a7fe561358d100"),
- },
- testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
- ),
- types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
- testutil.MustDecodeHexString("fd0aec4229deb281"),
- 10000000000,
- nil,
- nil,
- testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
- ),
- },
- Outputs: []*types.TxOutput{
- types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
- types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
- },
- },
- err: true,
- gasValid: false,
- },
- {
- category: "overflow",
- desc: "sum of spend and issuance non btm input overflow",
- insts: []*signingInst{singleSignInst, singleSignInst, singleSignInst},
- txData: types.TxData{
- Version: 1,
- Inputs: []*types.TxInput{
- types.NewSpendInput(nil,
- bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
- *consensus.BTMAssetID, 10000000000, 1, nil),
- types.NewIssuanceInput( // assetID: 97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f
- testutil.MustDecodeHexString("fd0aec4229deb281"),
- math.MaxInt64,
- nil,
- nil,
- testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
- ),
- types.NewSpendInput(nil,
- bc.Hash{V0: 6970879411704044573, V1: 10086395903308657573, V2: 10107608596190358115, V3: 8645856247221333302},
- testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 100, 0, nil),
- },
- Outputs: []*types.TxOutput{
- types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
- types.NewIntraChainOutput(testutil.MustDecodeAsset("97575084e5161406a0977da729fbf51ad230e0ff0aec607a97e4336611c8707f"), 100, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
- },
- },
- err: true,
- gasValid: false,
- },
- {
- category: "overflow",
desc: "spend btm output overflow",
insts: []*signingInst{singleSignInst, singleSignInst},
txData: types.TxData{
gasValid: true,
},
{
- category: "verify signature fail",
- desc: "issuance non btm single sign",
- insts: []*signingInst{singleSignInst, multiSignInst},
- txData: types.TxData{
- Version: 1,
- Inputs: []*types.TxInput{
- types.NewSpendInput(nil,
- bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
- *consensus.BTMAssetID, 10000000000, 0, nil),
- types.NewIssuanceInput(
- testutil.MustDecodeHexString("fd0aec4229deb281"),
- 10000000000,
- // wrong issuance program
- testutil.MustDecodeHexString("ae20c38173d800e62f63bd08cfaa9bc905e4a34a61ad841d7ad6c70ead0fb48196995151ad"),
- nil,
- nil,
- ),
- },
- Outputs: []*types.TxOutput{
- types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
- types.NewIntraChainOutput(testutil.MustDecodeAsset("bf5f8da2334590ee095148ccdcf4d806b26a47a6d9e9e857ef6c2de79aee4f14"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
- },
- },
- err: true,
- gasValid: true,
- },
- {
- category: "verify signature fail",
- desc: "issuance non btm multi sign",
- insts: []*signingInst{singleSignInst, multiSignInst},
- txData: types.TxData{
- Version: 1,
- Inputs: []*types.TxInput{
- types.NewSpendInput(nil,
- bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
- *consensus.BTMAssetID, 10000000000, 0, nil),
- types.NewIssuanceInput(
- testutil.MustDecodeHexString("fd0aec4229deb281"),
- 10000000000,
- // wrong issuance program
- testutil.MustDecodeHexString("ae20ce8639c5dc70cb2b12f89a057670602eb013fc54a10ce22bd4691c62cf546b7b2081bdd879bcbce7f58e1731841c6b3deac242efa00e75124fe559fa531c0c5bb820b40b6eec74288ee4bae67191f135512454b52640cfd7be95dc84be0f02281dce20247b6e6f9230a987ef61c66820268e7b766d28c1ce7aa2c550b34e294167f340205096211460415888768a48b121013711aa711634bb9ff7341a7bd072c31525875355ad"),
- nil,
- testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
- ),
- },
- Outputs: []*types.TxOutput{
- types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
- types.NewIntraChainOutput(testutil.MustDecodeAsset("776f0a421e9176a03061d388aff4ab3b1bcd32e53a090d593a466706c69e3d3f"), 10000000000, testutil.MustDecodeHexString("00145931e1b7b65897f47845ac08fc136e0c0a4ff166")),
- },
- },
- err: true,
- gasValid: true,
- },
- {
category: "double spend",
desc: "btm asset double spend",
insts: []*signingInst{singleSignInst, singleSignInst},
panic(err)
}
inp.ControlProgram = program.ControlProgram
- case *types.IssuanceInput:
- if inp.IssuanceProgram != nil {
- continue
- }
- assetSigner, err := signers.Create("asset", xPubs, insts[i].quorum, insts[i].keyIndex, signers.BIP0032)
- if err != nil {
- panic(err)
- }
-
- path := signers.GetBip0032Path(assetSigner, signers.AssetKeySpace)
- derivedXPubs := chainkd.DeriveXPubs(assetSigner.XPubs, path)
- derivedPKs := chainkd.XPubKeys(derivedXPubs)
-
- issuanceProg, err := vmutil.P2SPMultiSigProgramWithHeight(derivedPKs, insts[i].quorum, 0)
- if err != nil {
- panic(err)
- }
-
- inp.IssuanceProgram = issuanceProg
}
}
}
arguments = append(arguments, script)
}
inp.Arguments = arguments
- case *types.IssuanceInput:
- path := signers.GetBip0032Path(&signers.Signer{KeyIndex: inst.keyIndex, DeriveRule: signers.BIP0032}, signers.AssetKeySpace)
- xPrvs, _ := mustGetRootKeys(inst.rootPrvKeys)
- for _, xPrv := range xPrvs {
- childPrv := xPrv.Derive(path)
- sigHashBytes := tx.SigHash(uint32(i)).Byte32()
- arguments = append(arguments, childPrv.Sign(sigHashBytes[:]))
- }
- inp.Arguments = arguments
}
}
}
return errors.Wrap(err, "checking retirement source")
}
- case *bc.Issuance:
- computedAssetID := e.WitnessAssetDefinition.ComputeAssetID()
- if computedAssetID != *e.Value.AssetId {
- return errors.WithDetailf(ErrMismatchedAssetID, "asset ID is %x, issuance wants %x", computedAssetID.Bytes(), e.Value.AssetId.Bytes())
- }
-
- gasLeft, err := vm.Verify(NewTxVMContext(vs, e, e.WitnessAssetDefinition.IssuanceProgram, e.WitnessArguments), vs.gasStatus.GasLeft)
- if err != nil {
- return errors.Wrap(err, "checking issuance program")
- }
- if err = vs.gasStatus.updateUsage(gasLeft); err != nil {
- return err
- }
-
- destVS := *vs
- destVS.destPos = 0
- if err = checkValidDest(&destVS, e.WitnessDestination); err != nil {
- return errors.Wrap(err, "checking issuance destination")
- }
-
case *bc.Spend:
if e.SpentOutputId == nil {
return errors.Wrap(ErrMissingField, "spend without spent output ID")
}
dest = ref.WitnessDestination
- case *bc.Issuance:
- if vs.Position != 0 {
- return errors.Wrapf(ErrPosition, "invalid position %d for issuance source", vs.Position)
- }
- dest = ref.WitnessDestination
-
case *bc.Spend:
if vs.Position != 0 {
return errors.Wrapf(ErrPosition, "invalid position %d for spend source", vs.Position)
err: nil,
},
{
- desc: "single utxo, single sign, issuance, spend, retire, btm stanard transaction, gas sufficient",
- txData: &types.TxData{
- Version: 1,
- SerializedSize: 601,
- Inputs: []*types.TxInput{
- types.NewSpendInput(
- [][]byte{
- mustDecodeString("8aab6052cb935384ac8fcbd4c0857cbce2e19825a002635d0b242757f17e5fdd148d83eb3837baf91754bf539cd08e29f66975f4bc9843ac00e280f228026105"),
- mustDecodeString("ca85ea98011ddd592d1f081ebd2a91ac0f4238784222ed85b9d95aeb654f1cf1"),
- },
- bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
- *consensus.BTMAssetID, 11818900000, 0, mustDecodeString("0014e6e1f8b11f1cfb7609037003b90f64837afd272c")),
- types.NewIssuanceInput(
- mustDecodeString("fd0aec4229deb281"),
- 10000000000,
- mustDecodeString("ae2054a71277cc162eb3eb21b5bd9fe54402829a53b294deaed91692a2cd8a081f9c5151ad"),
- [][]byte{
- mustDecodeString("e8f301f7bd3b1e4ca853b15559b3a253a4f5f9c7efba233ab0f6896bec23adc6a816c350e08f6b8ac5bc23eb5720173f9190805328af581f34a7fe561358d100"),
- },
- mustDecodeString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
- ),
- },
- Outputs: []*types.TxOutput{
- types.NewIntraChainOutput(*consensus.BTMAssetID, 1818900000, mustDecodeString("00147d6b00edfbbc758a5da6130a5fa1a4cfec8422c3")),
- types.NewIntraChainOutput(*consensus.BTMAssetID, 9900000000, []byte{byte(vm.OP_FAIL)}),
- types.NewIntraChainOutput(bc.AssetID{V0: 8879089148261671560, V1: 16875272676673176923, V2: 14627348561007036053, V3: 5774520766896450836}, 10000000000, mustDecodeString("0014447e597c1c326ad1a639f8023d3f87ae22a4e049")),
- },
- },
- gasValid: true,
- err: nil,
- },
- {
- desc: "single utxo, single sign, issuance, spend, retire, btm stanard transaction, gas insufficient",
- txData: &types.TxData{
- Version: 1,
- SerializedSize: 601,
- Inputs: []*types.TxInput{
- types.NewSpendInput(
- [][]byte{
- mustDecodeString("23ca3a6f8474b1b9ab8b77fcf3cf3fd9dfa761dff4e5d8551a72307dc065cd19100f3ca9fcca4df2f8842b71dba2fd29b73c1b06b3d8bddc2a71e8cc18842a04"),
- mustDecodeString("ca85ea98011ddd592d1f081ebd2a91ac0f4238784222ed85b9d95aeb654f1cf1"),
- },
- bc.Hash{V0: 14760873410800997144, V1: 1698395500822741684, V2: 5965908492734661392, V3: 9445539829830863994},
- *consensus.BTMAssetID, 11818900000, 0, mustDecodeString("0014e6e1f8b11f1cfb7609037003b90f64837afd272c")),
- types.NewIssuanceInput(
- mustDecodeString("4b6afc9344c3ce63"),
- 10000000000,
- mustDecodeString("ae2054a71277cc162eb3eb21b5bd9fe54402829a53b294deaed91692a2cd8a081f9c5151ad"),
- [][]byte{
- mustDecodeString("e8f301f7bd3b1e4ca85f1f8acda3a91fb73e717c096b8b82b2c7ed9d25170c0f9fcd9b5e8039094bd1174886f1b5428272eb6c2af03946bf3c2037a4b499c77107b94b96a92088a0d0d3b15559b3a253a4f5f9c7efba233ab0f6896bec23adc6a816c350e08f6b8ac5bc23eb5720173f9190805328af581f34a7fe561358d100"),
- },
- mustDecodeString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
- ),
- },
- Outputs: []*types.TxOutput{
- types.NewIntraChainOutput(*consensus.BTMAssetID, 1818900000, mustDecodeString("001482b7991d64d001009b673ffe3ca2b35eab14f142")),
- types.NewIntraChainOutput(*consensus.BTMAssetID, 10000000000, []byte{byte(vm.OP_FAIL)}),
- types.NewIntraChainOutput(bc.AssetID{V0: 8879089148261671560, V1: 16875272676673176923, V2: 14627348561007036053, V3: 5774520766896450836}, 10000000000, mustDecodeString("0014447e597c1c326ad1a639f8023d3f87ae22a4e049")),
- },
- },
- gasValid: false,
- err: vm.ErrRunLimitExceeded,
- },
- {
desc: "btm stanard transaction check signature is not passed",
txData: &types.TxData{
Version: 1,
{
desc: "unbalanced mux amounts",
f: func() {
- mux.Sources[0].Value.Amount++
- iss := tx.Entries[*mux.Sources[0].Ref].(*bc.Issuance)
- iss.WitnessDestination.Value.Amount++
- },
- err: ErrUnbalanced,
- },
- {
- desc: "unbalanced mux amounts",
- f: func() {
mux.WitnessDestinations[0].Value.Amount++
},
err: ErrUnbalanced,
err: nil,
},
{
- desc: "overflowing mux source amounts",
- f: func() {
- mux.Sources[0].Value.Amount = math.MaxInt64
- iss := tx.Entries[*mux.Sources[0].Ref].(*bc.Issuance)
- iss.WitnessDestination.Value.Amount = math.MaxInt64
- },
- err: ErrOverflow,
- },
- {
desc: "underflowing mux destination amounts",
f: func() {
mux.WitnessDestinations[0].Value.Amount = math.MaxInt64
err: ErrMismatchedReference,
},
{
- desc: "mismatched input dest and mux source",
- f: func() {
- fixture2 := sample(t, fixture)
- tx2 := types.NewTx(*fixture2.tx).Tx
- input2ID := tx2.InputIDs[2]
- input2 := tx2.Entries[input2ID].(*bc.Spend)
- dest2Ref := input2.WitnessDestination.Ref
- dest2 := tx2.Entries[*dest2Ref].(*bc.Mux)
- tx.Entries[*dest2Ref] = dest2
- tx.Entries[input2ID] = input2
- mux.Sources[0].Ref = &input2ID
- },
- err: ErrMismatchedReference,
- },
- {
desc: "invalid mux destination position",
f: func() {
mux.WitnessDestinations[0].Position = 1
},
},
{
- desc: "issuance program failure",
- f: func() {
- iss := txIssuance(t, tx, 0)
- iss.WitnessArguments[0] = []byte{}
- },
- err: vm.ErrFalseVMResult,
- },
- {
desc: "spend control program failure",
f: func() {
spend := txSpend(t, tx, 1)
err: ErrMismatchedValue,
},
{
- desc: "mismatched witness asset destination",
- f: func() {
- issuanceID := mux.Sources[0].Ref
- issuance := tx.Entries[*issuanceID].(*bc.Issuance)
- issuance.WitnessAssetDefinition.Data = &bc.Hash{V0: 9999}
- },
- err: ErrMismatchedAssetID,
- },
- {
- desc: "issuance witness position greater than length of mux sources",
- f: func() {
- issuanceID := mux.Sources[0].Ref
- issuance := tx.Entries[*issuanceID].(*bc.Issuance)
- issuance.WitnessDestination.Position = uint64(len(mux.Sources) + 1)
- },
- err: ErrPosition,
- },
- {
desc: "normal coinbase tx",
f: func() {
addCoinbase(consensus.BTMAssetID, 100000, nil)
result.assetDef = []byte{2}
}
if result.assetID.IsZero() {
- refdatahash := hashData(result.assetDef)
- result.assetID = bc.ComputeAssetID(result.issuanceProg.Code, result.issuanceProg.VmVersion, &refdatahash)
+ result.assetID = bc.AssetID{V0: 9999}
}
if result.txVersion == 0 {
args2 := [][]byte{{6}, {7}}
result.txInputs = []*types.TxInput{
- types.NewIssuanceInput([]byte{3}, 10, result.issuanceProg.Code, result.issuanceArgs, result.assetDef),
+ types.NewSpendInput(nil, *newHash(9), result.assetID, 10, 0, []byte{byte(vm.OP_TRUE)}),
types.NewSpendInput(args1, *newHash(5), result.assetID, 20, 0, cp1),
types.NewSpendInput(args2, *newHash(8), result.assetID, 40, 0, cp2),
}
return &a
}
-func txIssuance(t *testing.T, tx *bc.Tx, index int) *bc.Issuance {
- id := tx.InputIDs[index]
- res, err := tx.Issuance(id)
- if err != nil {
- t.Fatal(err)
- }
- return res
-}
-
func txSpend(t *testing.T, tx *bc.Tx, index int) *bc.Spend {
id := tx.InputIDs[index]
res, err := tx.Spend(id)
)
switch e := entry.(type) {
- case *bc.Issuance:
- a1 := e.Value.AssetId.Bytes()
- assetID = &a1
- amount = &e.Value.Amount
- destPos = &e.WitnessDestination.Position
case *bc.Spend:
spentOutput := tx.Entries[*e.SpentOutputId].(*bc.IntraChainOutput)
case *bc.Mux:
return checkMux(e)
- case *bc.Issuance:
- d, ok := ec.entries[*e.WitnessDestination.Ref]
- if !ok {
- return false, errors.Wrapf(bc.ErrMissingEntry, "entry for issuance destination %x not found", e.WitnessDestination.Ref.Bytes())
- }
- if m, ok := d.(*bc.Mux); ok {
- return checkMux(m)
- }
- if index != 0 {
- return false, errors.Wrapf(vm.ErrBadValue, "index %d >= 1", index)
- }
- return checkEntry(d)
-
case *bc.Spend:
d, ok := ec.entries[*e.WitnessDestination.Ref]
if !ok {
tx := types.NewTx(types.TxData{
Inputs: []*types.TxInput{
types.NewSpendInput(nil, bc.Hash{}, bc.NewAssetID([32]byte{1}), 5, 1, []byte("spendprog")),
- types.NewIssuanceInput(nil, 6, []byte("issueprog"), nil, nil),
},
Outputs: []*types.TxOutput{
types.NewIntraChainOutput(bc.NewAssetID([32]byte{3}), 8, []byte("wrongprog")),
}
return nil
}
-
-// GetIssuanceProgramRestrictHeight return issuance program restrict height
-// if height invalid return 0
-func GetIssuanceProgramRestrictHeight(program []byte) int64 {
- insts, err := vm.ParseProgram(program)
- if err != nil {
- return 0
- }
-
- if len(insts) >= 4 && insts[0].IsPushdata() && insts[1].Op == vm.OP_BLOCKHEIGHT && insts[2].Op == vm.OP_GREATERTHAN && insts[3].Op == vm.OP_VERIFY {
- height, err := vm.AsInt64(insts[0].Data)
- if err != nil {
- return 0
- }
-
- return height
- }
- return 0
-}
}
}
}
-
-func TestGetIssuanceProgramRestrictHeight(t *testing.T) {
- tests := []struct {
- issuanceProgram string
- wantHeight int64
- }{
- {
- issuanceProgram: "",
- wantHeight: 0,
- },
- {
- issuanceProgram: "ae20ac20f5cdb9ada2ae9836bcfff32126d6b885aa3f73ee111a95d1bf37f3904aca5151ad",
- wantHeight: 0,
- },
- {
- issuanceProgram: "01c8cda069ae20f44dd85be89de08b0f894476ccc7b3eebcf0a288c79504fa7e4c8033f5b7338020c86dc682ce3ecac64e165d9b5f8cca9ee05bd0d4df07adbfd11251ad7e88f1685152ad",
- wantHeight: 200,
- },
- }
-
- for i, test := range tests {
- program, err := hex.DecodeString(test.issuanceProgram)
- if err != nil {
- t.Fatal(err)
- }
-
- gotHeight := GetIssuanceProgramRestrictHeight(program)
- if gotHeight != test.wantHeight {
- t.Errorf("TestGetIssuanceProgramRestrictHeight #%d failed: got %d want %d", i, gotHeight, test.wantHeight)
- }
- }
-}
+++ /dev/null
-// +build functional
-
-package test
-
-import (
- "testing"
-)
-
-func TestChain(t *testing.T) {
- walk(t, chainTestDir, func(t *testing.T, name string, test *chainTestConfig) {
- if err := test.Run(); err != nil {
- t.Fatal(err)
- }
- })
-}
+++ /dev/null
-{
- "blocks": [
- {
- "append": 100
- },
- {
- "transactions": [
- {
- "inputs": [
- {"height": 1, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- }
- ],
- "append": 2
- },
- {
- "transactions": [
- {
- "inputs": [
- {"height": 2, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- }
- ]
- },
- {
- "transactions": [
- {
- "inputs": [
- {"height": 102, "tx_index": 1, "output_index": 0},
- {"height": 3, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- },
- {
- "inputs": [
- {"height": 105, "tx_index": 1, "output_index": 0},
- {"height": 4, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- }
- ]
- },
- {
- "transactions": [
- {
- "inputs": [
- {"height": 106, "tx_index": 1, "output_index": 0},
- {"height": 106, "tx_index": 2, "output_index": 0},
- {"height": 106, "tx_index": 2, "output_index": 2}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- },
- {
- "inputs": [
- {"height": 107, "tx_index": 1, "output_index": 0},
- {"height": 107, "tx_index": 1, "output_index": 2},
- {"height": 5, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- },
- {
- "inputs": [
- {"height": 107, "tx_index": 2, "output_index": 0},
- {"height": 107, "tx_index": 1, "output_index": 1},
- {"height": 6, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- }
- ]
- }
- ]
-}
\ No newline at end of file
+++ /dev/null
-{
- "blocks": [
- {
- "append": 100
- },
- {
- "transactions": [
- {
- "inputs": [
- {"height": 1, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- }
- ],
- "append": 2
- },
- {
- "transactions": [
- {
- "inputs": [
- {"height": 2, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- },
- {
- "inputs": [
- {"height": 105, "tx_index": 1, "output_index": 0},
- {"height": 3, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- }
- ]
- },
- {
- "transactions": [
- {
- "inputs": [
- {"height": 105, "tx_index": 1, "output_index": 0},
- {"height": 4, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- }
- ],
- "invalid": true
- }
- ]
-}
+++ /dev/null
-{
- "blocks": [
- {
- "append": 100
- },
- {
- "transactions": [
- {
- "inputs": [
- {"height": 1, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- }
- ],
- "append": 2
- },
- {
- "transactions": [
- {
- "inputs": [
- {"height": 2, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- }
- ]
- },
- {
- "transactions": [
- {
- "inputs": [
- {"height": 105, "tx_index": 1, "output_index": 0},
- {"height": 3, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- },
- {
- "inputs": [
- {"height": 105, "tx_index": 1, "output_index": 2},
- {"height": 4, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- }
- ]
- }
- ]
-}
\ No newline at end of file
+++ /dev/null
-{
- "rollback": 104,
- "blocks": [
- {
- "append": 100
- },
- {
- "transactions": [
- {
- "inputs": [
- {"height": 1, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- }
- ],
- "append": 2
- },
- {
- "transactions": [
- {
- "inputs": [
- {"height": 2, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- }
- ]
- },
- {
- "transactions": [
- {
- "inputs": [
- {"height": 102, "tx_index": 1, "output_index": 0},
- {"height": 3, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- },
- {
- "inputs": [
- {"height": 105, "tx_index": 1, "output_index": 0},
- {"height": 4, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- }
- ]
- },
- {
- "transactions": [
- {
- "inputs": [
- {"height": 106, "tx_index": 1, "output_index": 0},
- {"height": 106, "tx_index": 2, "output_index": 0},
- {"height": 106, "tx_index": 2, "output_index": 2}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- },
- {
- "inputs": [
- {"height": 107, "tx_index": 1, "output_index": 0},
- {"height": 107, "tx_index": 1, "output_index": 2},
- {"height": 5, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- },
- {
- "inputs": [
- {"height": 107, "tx_index": 2, "output_index": 0},
- {"height": 107, "tx_index": 1, "output_index": 1},
- {"height": 6, "tx_index": 0, "output_index": 0}
- ],
- "outputs": [3000000000, 10000000, 3000000000]
- }
- ]
- }
- ]
-}
\ No newline at end of file
+++ /dev/null
-{
- "keys": [
- {"name": "alice", "password": "alice"},
- {"name": "bob", "password": "bob"}
- ],
- "accounts": [
- {"name": "alice", "keys": ["alice"], "quorum": 1},
- {"name": "bob", "keys": ["bob"], "quorum": 1},
- {"name": "multi-sig", "keys": ["alice", "bob"], "quorum": 2}
- ],
- "transactions": [
- {
- "describe": "normal single sign btm tx",
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 100000000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "bob", "amount": 40000000000, "asset": "BTM"}
- ],
- "valid": true,
- "gas_only": false,
- "tx_fee": 60000000000
- },
- {
- "describe": "single sign btm tx, out of gas",
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 100000000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "bob", "amount": 100000000000, "asset": "BTM"}
- ],
- "gas_only": false,
- "valid": false
- },
- {
- "describe": "normal multi utxo btm tx",
- "passwords": ["alice", "bob"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 100000000000, "asset": "BTM"},
- {"type": "spend_account", "name": "bob", "amount": 100000000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "bob", "amount": 30000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 30000000000, "asset": "BTM"}
- ],
- "valid": true,
- "gas_only": false,
- "tx_fee": 140000000000
- },
- {
- "describe": "single sign asset tx",
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 100000000000, "asset": "BTM"},
- {"type": "issue", "name": "alice", "amount": 100, "asset": "GOLD"}
- ],
- "outputs": [
- {"type": "output", "name": "alice", "amount": 30000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 100, "asset": "GOLD"}
- ],
- "valid": true,
- "gas_only": false,
- "tx_fee": 70000000000
- },
- {
- "describe": "single sign asset, out of gas",
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 100000000000, "asset": "BTM"},
- {"type": "issue", "name": "alice", "amount": 100, "asset": "RMB"}
- ],
- "outputs": [
- {"type": "output", "name": "alice", "amount": 100000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 100, "asset": "RMB"}
- ],
- "valid": false,
- "gas_only": false
- },
- {
- "describe": "single sign asset, input not equal with output",
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 100000000000, "asset": "BTM"},
- {"type": "issue", "name": "alice", "amount": 100, "asset": "SILVER"}
- ],
- "outputs": [
- {"type": "output", "name": "alice", "amount": 30000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 50, "asset": "SILVER"}
- ],
- "valid": false,
- "gas_only": false
- },
- {
- "describe": "normal single sign with retire",
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 100000000000, "asset": "BTM"},
- {"type": "spend_account", "name": "alice", "amount": 100, "asset": "GOLD"}
- ],
- "outputs": [
- {"type": "output", "name": "alice", "amount": 30000000000, "asset": "BTM"},
- {"type": "retire", "name": "alice", "amount": 100, "asset": "GOLD"}
- ],
- "valid": true,
- "gas_only": false,
- "tx_fee": 70000000000
- },
- {
- "describe": "gas only tx",
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 100000000000, "asset": "BTM"},
- {"type": "spend_account", "name": "bob", "amount": 100, "asset": "GOLD"}
- ],
- "outputs": [
- {"type": "output", "name": "alice", "amount": 30000000000, "asset": "BTM"},
- {"type": "retire", "name": "alice", "amount": 100, "asset": "GOLD"}
- ],
- "valid": false,
- "gas_only": true,
- "tx_fee": 70000000000
- },
- {
- "describe": "normal multi-sig asset with issue and retire",
- "passwords": ["alice", "bob"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 100000000000, "asset": "BTM"},
- {"type": "spend_account", "name": "bob", "amount": 100000000000, "asset": "BTM"},
- {"type": "issue", "name": "multi-sig", "amount": 100, "asset": "MULTI-SIGN-ASSET"},
- {"type": "spend_account", "name": "alice", "amount": 10, "asset": "GOLD"}
- ],
- "outputs": [
- {"type": "output", "name": "multi-sig", "amount": 199500000000, "asset": "BTM"},
- {"type": "output", "name": "multi-sig", "amount": 100, "asset": "MULTI-SIGN-ASSET"},
- {"type": "retire", "name": "alice", "amount": 10, "asset": "GOLD"}
- ],
- "valid": true,
- "gas_only": false,
- "tx_fee": 500000000
- },
- {
- "describe": "multi-sig asset with issue and retire, out of gas",
- "passwords": ["alice", "bob"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 100000000000, "asset": "BTM"},
- {"type": "spend_account", "name": "bob", "amount": 100000000000, "asset": "BTM"},
- {"type": "issue", "name": "multi-sig", "amount": 100, "asset": "DOLLAR"},
- {"type": "spend_account", "name": "alice", "amount": 10, "asset": "GOLD"}
- ],
- "outputs": [
- {"type": "output", "name": "multi-sig", "amount": 200000000000, "asset": "BTM"},
- {"type": "output", "name": "multi-sig", "amount": 100, "asset": "DOLLAR"},
- {"type": "retire", "name": "alice", "amount": 10, "asset": "GOLD"}
- ],
- "gas_only": false,
- "valid": false
- },
- {
- "describe": "multi utxo btm tx, wrong sig",
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 100000000000, "asset": "BTM"},
- {"type": "spend_account", "name": "bob", "amount": 100000000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "bob", "amount": 30000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 30000000000, "asset": "BTM"}
- ],
- "gas_only": false,
- "valid": false
- },
- {
- "describe": "multi utxo btm tx, output large than input",
- "passwords": ["alice", "bob"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 100000000000, "asset": "BTM"},
- {"type": "spend_account", "name": "bob", "amount": 100000000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "bob", "amount": 90000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 200000000000, "asset": "BTM"}
- ],
- "gas_only": false,
- "valid": false
- },
- {
- "describe": "version is 0",
- "passwords": ["alice"],
- "version": 0,
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 100000000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "bob", "amount": 90000000000, "asset": "BTM"}
- ],
- "gas_only": false,
- "valid": false
- },
- {
- "describe": "version is 1",
- "passwords": ["alice"],
- "version": 1,
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 100000000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "bob", "amount": 90000000000, "asset": "BTM"}
- ],
- "tx_fee": 10000000000,
- "gas_only": false,
- "valid": true
- },
- {
- "describe": "version greater than block version(1)",
- "passwords": ["alice"],
- "version": 12,
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 100000000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "bob", "amount": 90000000000, "asset": "BTM"}
- ],
- "gas_only": false,
- "valid": false
- }
- ]
-}
\ No newline at end of file
+++ /dev/null
-{
- "keys": [
- {"name": "alice", "password": "alice"},
- {"name": "bob", "password": "bob"},
- {"name": "none", "password": "none"}
- ],
- "accounts": [
- {"name": "alice", "keys": ["alice"], "quorum": 1},
- {"name": "bob", "keys": ["bob"], "quorum": 1},
- {"name": "none", "keys": ["none"], "quorum": 1}
- ],
- "blocks": [
- {
- "coinbase_account": "alice",
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 41250000000}
- ],
- "append": 100
- },
- {
- "coinbase_account": "none",
- "transactions": [
- {
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 6000000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "bob", "amount": 500000000, "asset": "BTM"},
- {"type": "output", "name": "bob", "amount": 500000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 2000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 2000000000, "asset": "BTM"}
- ]
- }
- ],
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 39250000000},
- {"name": "bob", "asset": "BTM", "amount": 1000000000}
- ]
- },
- {
- "coinbase_account": "none",
- "transactions": [
- {
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 1000000000, "asset": "BTM"},
- {"type": "issue", "name": "alice", "amount": 100, "asset": "GOLD"}
- ],
- "outputs": [
- {"type": "output", "name": "alice", "amount": 100, "asset": "GOLD"}
- ]
- }
- ],
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 38250000000},
- {"name": "alice", "asset": "GOLD", "amount": 100},
- {"name": "bob", "asset": "BTM", "amount": 1000000000}
- ]
- },
- {
- "coinbase_account": "none",
- "transactions": [
- {
- "passwords": ["bob"],
- "inputs": [
- {"type": "spend_account", "name": "bob", "amount": 400000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "alice", "amount": 100000000, "asset": "BTM"},
- {"type": "output", "name": "bob", "amount": 200000000, "asset": "BTM"}
- ]
- },
- {
- "passwords": ["alice", "bob"],
- "inputs": [
- {"type": "spend_account", "name": "bob", "amount": 200000000, "asset": "BTM"},
- {"type": "spend_account", "name": "alice", "amount": 50, "asset": "GOLD"}
- ],
- "outputs": [
- {"type": "output", "name": "bob", "amount": 50, "asset": "GOLD"},
- {"type": "output", "name": "alice", "amount": 100000000, "asset": "BTM"}
- ]
- }
- ],
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 38450000000},
- {"name": "alice", "asset": "GOLD", "amount": 50},
- {"name": "bob", "asset": "BTM", "amount": 600000000},
- {"name": "bob", "asset": "GOLD", "amount": 50}
- ]
- }
- ]
-}
+++ /dev/null
-{
- "keys": [
- {"name": "alice", "password": "alice"},
- {"name": "bob", "password": "bob"}
- ],
- "accounts": [
- {"name": "alice", "keys": ["alice"], "quorum": 1},
- {"name": "bob", "keys": ["bob"], "quorum": 1}
- ],
- "blocks": [
- {
- "coinbase_account": "alice",
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 41250000000}
- ],
- "append": 100
- },
- {
- "coinbase_account": "bob",
- "transactions": [
- {
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 6000000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "bob", "amount": 1000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 4000000000, "asset": "BTM"}
- ]
- }
- ],
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 39250000000},
- {"name": "bob", "asset": "BTM", "amount": 43250000000}
- ],
- "append": 0
- }
- ]
-}
+++ /dev/null
-{
- "keys": [
- {"name": "alice", "password": "alice"},
- {"name": "bob", "password": "bob"},
- {"name": "default", "password": "default"}
- ],
- "accounts": [
- {"name": "alice", "keys": ["alice"], "quorum": 1},
- {"name": "bob", "keys": ["bob"], "quorum": 1},
- {"name": "default", "keys": ["default"], "quorum": 1}
- ],
- "blocks": [
- {
- "coinbase_account": "alice",
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 41250000000}
- ],
- "append": 100
- },
- {
- "coinbase_account": "bob",
- "transactions": [
- {
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 1000000000, "asset": "BTM"},
- {"type": "issue", "name": "alice", "amount": 100, "asset": "GOLD"}
- ],
- "outputs": [
- {"type": "output", "name": "alice", "amount": 100, "asset": "GOLD"}
- ]
- }
- ],
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 40250000000},
- {"name": "alice", "asset": "GOLD", "amount": 100},
- {"name": "bob", "asset": "BTM", "amount": 42250000000}
- ],
- "append": 0
- },
- {
- "coinbase_account": "default",
- "transactions": [
- {
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 700000000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "alice", "amount": 400000000000, "asset": "BTM"},
- {"type": "output", "name": "bob", "amount": 299000000000, "asset": "BTM"}
- ]
- },
- {
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 1000000000, "asset": "BTM"},
- {"type": "spend_account", "name": "alice", "amount": 100, "asset": "GOLD"}
- ],
- "outputs": [
- {"type": "retire", "name": "alice", "amount": 100, "asset": "GOLD"}
- ]
- }
- ],
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 39250000000},
- {"name": "alice", "asset": "GOLD", "amount": 0},
- {"name": "bob", "asset": "BTM", "amount": 42250000000}
- ],
- "append": 0
- },
- {
- "coinbase_account": "default",
- "transactions": [
- {
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 1000000000, "asset": "BTM"},
- {"type": "spend_account", "name": "alice", "amount": 20, "asset": "GOLD"}
- ],
- "outputs": [
- {"type": "output", "name": "bob", "amount": 20, "asset": "GOLD"}
- ]
- }
- ],
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 39250000000},
- {"name": "alice", "asset": "GOLD", "amount": 0},
- {"name": "bob", "asset": "BTM", "amount": 42250000000},
- {"name": "bob", "asset": "GOLD", "amount": 0}
- ],
- "append": 0
- },
- {
- "coinbase_account": "default",
- "transactions": [
- {
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 1000000000, "asset": "BTM"}
- ]
- }
- ],
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 39250000000},
- {"name": "alice", "asset": "GOLD", "amount": 0},
- {"name": "bob", "asset": "BTM", "amount": 42250000000},
- {"name": "bob", "asset": "GOLD", "amount": 0}
- ],
- "append": 0
- }
- ]
-}
+++ /dev/null
-{
- "keys": [
- {"name": "alice", "password": "alice"},
- {"name": "bob", "password": "bob"},
- {"name": "none", "password": "none"}
- ],
- "accounts": [
- {"name": "alice", "keys": ["alice"], "quorum": 1},
- {"name": "bob", "keys": ["bob"], "quorum": 1},
- {"name": "multi-sig", "keys": ["alice", "bob"], "quorum": 2},
- {"name": "none", "keys": ["none"], "quorum": 1}
- ],
- "blocks": [
- {
- "coinbase_account": "alice",
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 41250000000}
- ],
- "append": 100
- },
- {
- "coinbase_account": "none",
- "transactions": [
- {
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 40000000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "bob", "amount": 5000000000, "asset": "BTM"},
- {"type": "output", "name": "bob", "amount": 5000000000, "asset": "BTM"},
- {"type": "output", "name": "bob", "amount": 5000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 5000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 2000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 2000000000, "asset": "BTM"},
- {"type": "output", "name": "multi-sig", "amount": 5000000000, "asset": "BTM"},
- {"type": "output", "name": "multi-sig", "amount": 5000000000, "asset": "BTM"},
- {"type": "output", "name": "multi-sig", "amount": 5000000000, "asset": "BTM"}
- ]
- }
- ],
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 10250000000},
- {"name": "bob", "asset": "BTM", "amount": 15000000000},
- {"name": "multi-sig", "asset": "BTM", "amount": 15000000000}
- ]
- },
- {
- "coinbase_account": "none",
- "transactions": [
- {
- "passwords": ["bob", "alice"],
- "inputs": [
- {"type": "spend_account", "name": "multi-sig", "amount": 1000000000, "asset": "BTM"},
- {"type": "issue", "name": "multi-sig", "amount": 100, "asset": "GOLD"}
- ],
- "outputs": [
- {"type": "output", "name": "multi-sig", "amount": 100, "asset": "GOLD"}
- ]
- }
- ],
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 10250000000},
- {"name": "multi-sig", "asset": "GOLD", "amount": 100},
- {"name": "multi-sig", "asset": "BTM", "amount": 14000000000},
- {"name": "bob", "asset": "BTM", "amount": 15000000000}
- ]
- },
- {
- "coinbase_account": "none",
- "transactions": [
- {
- "passwords": ["alice", "bob"],
- "inputs": [
- {"type": "spend_account", "name": "multi-sig", "amount": 1000000000, "asset": "BTM"},
- {"type": "spend_account", "name": "multi-sig", "amount": 40, "asset": "GOLD"},
- {"type": "spend_account", "name": "bob", "amount": 10000000000, "asset": "BTM"},
- {"type": "spend_account", "name": "alice", "amount": 10000000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "alice", "amount": 20, "asset": "GOLD"},
- {"type": "output", "name": "bob", "amount": 20, "asset": "GOLD"},
- {"type": "output", "name": "multi-sig", "amount": 20000000000, "asset": "BTM"}
- ]
- }
- ],
- "post_states": [
- {"name": "multi-sig", "asset": "BTM", "amount": 33000000000},
- {"name": "multi-sig", "asset": "GOLD", "amount": 60},
- {"name": "alice", "asset": "BTM", "amount": 250000000},
- {"name": "alice", "asset": "GOLD", "amount": 20},
- {"name": "bob", "asset": "BTM", "amount": 5000000000},
- {"name": "bob", "asset": "GOLD", "amount": 20}
- ]
- }
- ]
-}
+++ /dev/null
-{
- "keys": [
- {"name": "alice", "password": "alice"},
- {"name": "bob", "password": "bob"},
- {"name": "none", "password": "none"}
- ],
- "accounts": [
- {"name": "alice", "keys": ["alice"], "quorum": 1},
- {"name": "bob", "keys": ["bob"], "quorum": 1},
- {"name": "none", "keys": ["none"], "quorum": 1}
- ],
- "blocks": [
- {
- "coinbase_account": "alice",
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 41250000000}
- ],
- "append": 100
- },
- {
- "coinbase_account": "none",
- "transactions": [
- {
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 30000000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "bob", "amount": 5000000000, "asset": "BTM"},
- {"type": "output", "name": "bob", "amount": 5000000000, "asset": "BTM"},
- {"type": "output", "name": "bob", "amount": 5000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 5000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 5000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 2000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 2000000000, "asset": "BTM"}
- ]
- }
- ],
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 25250000000},
- {"name": "bob", "asset": "BTM", "amount": 15000000000}
- ]
- },
- {
- "coinbase_account": "none",
- "transactions": [
- {
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 1000000000, "asset": "BTM"},
- {"type": "issue", "name": "alice", "amount": 100, "asset": "GOLD"}
- ],
- "outputs": [
- {"type": "output", "name": "alice", "amount": 100, "asset": "GOLD"}
- ]
- }
- ],
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 24250000000},
- {"name": "alice", "asset": "GOLD", "amount": 100},
- {"name": "bob", "asset": "BTM", "amount": 15000000000}
- ]
- },
- {
- "coinbase_account": "none",
- "transactions": [
- {
- "passwords": ["bob"],
- "inputs": [
- {"type": "spend_account", "name": "bob", "amount": 5000000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "alice", "amount": 1000000000, "asset": "BTM"},
- {"type": "output", "name": "bob", "amount": 3000000000, "asset": "BTM"}
- ]
- },
- {
- "passwords": ["alice", "bob"],
- "inputs": [
- {"type": "spend_account", "name": "bob", "amount": 2000000000, "asset": "BTM"},
- {"type": "spend_account", "name": "alice", "amount": 50, "asset": "GOLD"}
- ],
- "outputs": [
- {"type": "output", "name": "bob", "amount": 50, "asset": "GOLD"},
- {"type": "output", "name": "alice", "amount": 1000000000, "asset": "BTM"}
- ]
- }
- ],
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 26250000000},
- {"name": "alice", "asset": "GOLD", "amount": 50},
- {"name": "bob", "asset": "BTM", "amount": 11000000000},
- {"name": "bob", "asset": "GOLD", "amount": 50}
- ]
- },
- {
- "coinbase_account": "none",
- "transactions": [
- {
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 1000000000, "asset": "BTM"},
- {"type": "spend_account", "name": "alice", "amount": 20, "asset": "GOLD"}
- ],
- "outputs": [
- {"type": "retire", "name": "alice", "amount": 20, "asset": "GOLD"}
- ]
- }
- ],
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 25250000000},
- {"name": "alice", "asset": "GOLD", "amount": 30},
- {"name": "bob", "asset": "BTM", "amount": 11000000000},
- {"name": "bob", "asset": "GOLD", "amount": 50}
- ]
- }
- ]
-}
+++ /dev/null
-{
- "rollback": 102,
- "keys": [
- {"name": "alice", "password": "alice"},
- {"name": "bob", "password": "bob"},
- {"name": "none", "password": "none"}
- ],
- "accounts": [
- {"name": "alice", "keys": ["alice"], "quorum": 1},
- {"name": "bob", "keys": ["bob"], "quorum": 1},
- {"name": "multi-sig", "keys": ["alice", "bob"], "quorum": 2},
- {"name": "none", "keys": ["none"], "quorum": 1}
- ],
- "blocks": [
- {
- "coinbase_account": "alice",
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 41250000000}
- ],
- "append": 100
- },
- {
- "coinbase_account": "none",
- "transactions": [
- {
- "passwords": ["alice"],
- "inputs": [
- {"type": "spend_account", "name": "alice", "amount": 40000000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "bob", "amount": 5000000000, "asset": "BTM"},
- {"type": "output", "name": "bob", "amount": 5000000000, "asset": "BTM"},
- {"type": "output", "name": "bob", "amount": 5000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 5000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 2000000000, "asset": "BTM"},
- {"type": "output", "name": "alice", "amount": 2000000000, "asset": "BTM"},
- {"type": "output", "name": "multi-sig", "amount": 5000000000, "asset": "BTM"},
- {"type": "output", "name": "multi-sig", "amount": 5000000000, "asset": "BTM"},
- {"type": "output", "name": "multi-sig", "amount": 5000000000, "asset": "BTM"}
- ]
- }
- ],
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 10250000000},
- {"name": "bob", "asset": "BTM", "amount": 15000000000},
- {"name": "multi-sig", "asset": "BTM", "amount": 15000000000}
- ]
- },
- {
- "coinbase_account": "none",
- "transactions": [
- {
- "passwords": ["bob", "alice"],
- "inputs": [
- {"type": "spend_account", "name": "multi-sig", "amount": 1000000000, "asset": "BTM"},
- {"type": "issue", "name": "multi-sig", "amount": 100, "asset": "GOLD"}
- ],
- "outputs": [
- {"type": "output", "name": "multi-sig", "amount": 100, "asset": "GOLD"}
- ]
- }
- ],
- "post_states": [
- {"name": "alice", "asset": "BTM", "amount": 10250000000},
- {"name": "multi-sig", "asset": "GOLD", "amount": 100},
- {"name": "multi-sig", "asset": "BTM", "amount": 14000000000},
- {"name": "bob", "asset": "BTM", "amount": 15000000000}
- ]
- },
- {
- "coinbase_account": "none",
- "transactions": [
- {
- "passwords": ["alice", "bob"],
- "inputs": [
- {"type": "spend_account", "name": "multi-sig", "amount": 1000000000, "asset": "BTM"},
- {"type": "spend_account", "name": "multi-sig", "amount": 40, "asset": "GOLD"},
- {"type": "spend_account", "name": "bob", "amount": 10000000000, "asset": "BTM"},
- {"type": "spend_account", "name": "alice", "amount": 10000000000, "asset": "BTM"}
- ],
- "outputs": [
- {"type": "output", "name": "alice", "amount": 20, "asset": "GOLD"},
- {"type": "output", "name": "bob", "amount": 20, "asset": "GOLD"},
- {"type": "output", "name": "multi-sig", "amount": 20000000000, "asset": "BTM"}
- ]
- }
- ],
- "post_states": [
- {"name": "multi-sig", "asset": "BTM", "amount": 33000000000},
- {"name": "multi-sig", "asset": "GOLD", "amount": 60},
- {"name": "alice", "asset": "BTM", "amount": 250000000},
- {"name": "alice", "asset": "GOLD", "amount": 20},
- {"name": "bob", "asset": "BTM", "amount": 5000000000},
- {"name": "bob", "asset": "GOLD", "amount": 20}
- ]
- }
- ]
-}
+++ /dev/null
-// +build functional
-
-package test
-
-import (
- "encoding/json"
- "fmt"
- "io/ioutil"
- "os"
- "testing"
-
- log "github.com/sirupsen/logrus"
-
- "github.com/vapor/account"
- "github.com/vapor/asset"
- "github.com/vapor/blockchain/pseudohsm"
- "github.com/vapor/consensus"
- dbm "github.com/vapor/database/leveldb"
- "github.com/vapor/protocol/bc"
- "github.com/vapor/protocol/bc/types"
- "github.com/vapor/protocol/validation"
- "github.com/vapor/protocol/vm"
-)
-
-func init() {
- log.SetLevel(log.ErrorLevel)
-}
-
-type TxTestConfig struct {
- Keys []*keyInfo `json:"keys"`
- Accounts []*accountInfo `json:"accounts"`
- Transactions []*ttTransaction `json:"transactions"`
-}
-
-func (cfg *TxTestConfig) Run() error {
- dirPath, err := ioutil.TempDir(".", "pseudo_hsm")
- if err != nil {
- return err
- }
- defer os.RemoveAll(dirPath)
- hsm, err := pseudohsm.New(dirPath)
- if err != nil {
- return err
- }
-
- chainDB := dbm.NewDB("chain_db", "leveldb", "chain_db")
- defer os.RemoveAll("chain_db")
- chain, _, _, _ := MockChain(chainDB)
- txTestDB := dbm.NewDB("tx_test_db", "leveldb", "tx_test_db")
- defer os.RemoveAll("tx_test_db")
- accountManager := account.NewManager(txTestDB, chain)
- assets := asset.NewRegistry(txTestDB, chain)
-
- generator := NewTxGenerator(accountManager, assets, hsm)
- for _, key := range cfg.Keys {
- if err := generator.createKey(key.Name, key.Password); err != nil {
- return err
- }
- }
-
- for _, acc := range cfg.Accounts {
- if err := generator.createAccount(acc.Name, acc.Keys, acc.Quorum); err != nil {
- return err
- }
- }
-
- block := &bc.Block{
- BlockHeader: &bc.BlockHeader{
- Height: 1,
- Version: 1,
- },
- }
- for _, t := range cfg.Transactions {
- tx, err := t.create(generator)
- if err != nil {
- return err
- }
-
- tx.TxData.Version = t.Version
- tx.Tx = types.MapTx(&tx.TxData)
- status, err := validation.ValidateTx(tx.Tx, block)
- result := err == nil
- if result != t.Valid {
- return fmt.Errorf("tx %s validate failed, expected: %t, have: %t", t.Describe, t.Valid, result)
- }
- if status == nil {
- continue
- }
-
- gasOnlyTx := false
- if err != nil && status.GasValid {
- gasOnlyTx = true
- }
- if gasOnlyTx != t.GasOnly {
- return fmt.Errorf("gas only tx %s validate failed", t.Describe)
- }
- if result && t.TxFee != status.BTMValue {
- return fmt.Errorf("gas used dismatch, expected: %d, have: %d", t.TxFee, status.BTMValue)
- }
- }
- return nil
-}
-
-type ttTransaction struct {
- wtTransaction
- Describe string `json:"describe"`
- Version uint64 `json:"version"`
- Valid bool `json:"valid"`
- GasOnly bool `json:"gas_only"`
- TxFee uint64 `json:"tx_fee"`
-}
-
-// UnmarshalJSON unmarshal transaction with default version 1
-func (t *ttTransaction) UnmarshalJSON(data []byte) error {
- type typeAlias ttTransaction
- tx := &typeAlias{
- Version: 1,
- }
-
- err := json.Unmarshal(data, tx)
- if err != nil {
- return err
- }
- *t = ttTransaction(*tx)
- return nil
-}
-
-func (t *ttTransaction) create(g *TxGenerator) (*types.Tx, error) {
- g.Reset()
- for _, input := range t.Inputs {
- switch input.Type {
- case "spend_account":
- utxo, err := g.mockUtxo(input.AccountAlias, input.AssetAlias, input.Amount)
- if err != nil {
- return nil, err
- }
- if err := g.AddTxInputFromUtxo(utxo, input.AccountAlias); err != nil {
- return nil, err
- }
- case "issue":
- _, err := g.createAsset(input.AccountAlias, input.AssetAlias)
- if err != nil {
- return nil, err
- }
- if err := g.AddIssuanceInput(input.AssetAlias, input.Amount); err != nil {
- return nil, err
- }
- }
- }
-
- for _, output := range t.Outputs {
- switch output.Type {
- case "output":
- if err := g.AddTxOutput(output.AccountAlias, output.AssetAlias, output.Amount); err != nil {
- return nil, err
- }
- case "retire":
- if err := g.AddRetirement(output.AssetAlias, output.Amount); err != nil {
- return nil, err
- }
- }
- }
- return g.Sign(t.Passwords)
-}
-
-func TestTx(t *testing.T) {
- walk(t, txTestDir, func(t *testing.T, name string, test *TxTestConfig) {
- if err := test.Run(); err != nil {
- t.Fatal(err)
- }
- })
-}
-
-func TestCoinbaseMature(t *testing.T) {
- db := dbm.NewDB("test_coinbase_mature_db", "leveldb", "test_coinbase_mature_db")
- defer os.RemoveAll("test_coinbase_mature_db")
- chain, _, _, _ := MockChain(db)
-
- defaultCtrlProg := []byte{byte(vm.OP_TRUE)}
- if err := AppendBlocks(chain, 1); err != nil {
- t.Fatal(err)
- }
-
- height := chain.BestBlockHeight()
- block, err := chain.GetBlockByHeight(height)
- if err != nil {
- t.Fatal(err)
- }
-
- tx, err := CreateTxFromTx(block.Transactions[0], 0, 1000000000, defaultCtrlProg)
- if err != nil {
- t.Fatal(err)
- }
-
- txs := []*types.Tx{tx}
- matureHeight := chain.BestBlockHeight() + consensus.CoinbasePendingBlockNumber
- currentHeight := chain.BestBlockHeight()
- for h := currentHeight + 1; h < matureHeight; h++ {
- block, err := NewBlock(chain, txs, defaultCtrlProg)
- if err != nil {
- t.Fatal(err)
- }
- if _, err := chain.ProcessBlock(block); err == nil {
- t.Fatal("spent immature coinbase output success")
- }
- block, err = NewBlock(chain, nil, defaultCtrlProg)
- if err != nil {
- t.Fatal(err)
- }
- if _, err := chain.ProcessBlock(block); err != nil {
- t.Fatal(err)
- }
- }
-
- block, err = NewBlock(chain, txs, defaultCtrlProg)
- if err != nil {
- t.Fatal(err)
- }
- if _, err := chain.ProcessBlock(block); err != nil {
- t.Fatalf("spent mature coinbase output failed: %s", err)
- }
-}
-
-func TestCoinbaseTx(t *testing.T) {
- db := dbm.NewDB("test_coinbase_tx_db", "leveldb", "test_coinbase_tx_db")
- defer os.RemoveAll("test_coinbase_tx_db")
- chain, _, _, _ := MockChain(db)
-
- defaultCtrlProg := []byte{byte(vm.OP_TRUE)}
- if err := AppendBlocks(chain, 1); err != nil {
- t.Fatal(err)
- }
-
- block, err := chain.GetBlockByHeight(chain.BestBlockHeight())
- if err != nil {
- t.Fatal(err)
- }
-
- tx, err := CreateTxFromTx(block.Transactions[0], 0, 1000000000, defaultCtrlProg)
- if err != nil {
- t.Fatal(err)
- }
-
- block, err = NewBlock(chain, []*types.Tx{tx}, defaultCtrlProg)
- if err != nil {
- t.Fatal(err)
- }
-
- txFees := []uint64{100000, 5000000000000}
- for _, txFee := range txFees {
- coinbaseTx, err := CreateCoinbaseTx(defaultCtrlProg, block.Height, txFee)
- if err != nil {
- t.Fatal(err)
- }
-
- if err := ReplaceCoinbase(block, coinbaseTx); err != nil {
- t.Fatal(err)
- }
-
- if _, err := chain.ProcessBlock(block); err == nil {
- t.Fatalf("invalid coinbase tx validate success")
- }
- }
-}
package test
import (
- "crypto/rand"
"encoding/json"
"fmt"
"time"
return err
}
-func (g *TxGenerator) createAsset(accountAlias string, assetAlias string) (*asset.Asset, error) {
- acc, err := g.AccountManager.FindByAlias(accountAlias)
- if err != nil {
- return nil, err
- }
- return g.Assets.Define(acc.XPubs, len(acc.XPubs), nil, 0, assetAlias, nil)
-}
-
func (g *TxGenerator) mockUtxo(accountAlias, assetAlias string, amount uint64) (*account.UTXO, error) {
ctrlProg, err := g.createControlProgram(accountAlias, false)
if err != nil {
return g.AddTxInput(txInput, signInst)
}
-// AddIssuanceInput add a issue input
-func (g *TxGenerator) AddIssuanceInput(assetAlias string, amount uint64) error {
- asset, err := g.Assets.FindByAlias(assetAlias)
- if err != nil {
- return err
- }
-
- var nonce [8]byte
- _, err = rand.Read(nonce[:])
- if err != nil {
- return err
- }
- issuanceInput := types.NewIssuanceInput(nonce[:], amount, asset.IssuanceProgram, nil, asset.RawDefinitionByte)
- signInstruction := &txbuilder.SigningInstruction{}
- path := signers.GetBip0032Path(asset.Signer, signers.AssetKeySpace)
- signInstruction.AddRawWitnessKeys(asset.Signer.XPubs, path, asset.Signer.Quorum)
- g.Builder.RestrictMinTime(time.Now())
- return g.Builder.AddInput(issuanceInput, signInstruction)
-}
-
// AddTxOutput add a tx output
func (g *TxGenerator) AddTxOutput(accountAlias, assetAlias string, amount uint64) error {
assetAmount, err := g.assetAmount(assetAlias, uint64(amount))
+++ /dev/null
-// +build functional
-
-package test
-
-import (
- "testing"
-
- log "github.com/sirupsen/logrus"
-)
-
-func TestWallet(t *testing.T) {
- log.SetLevel(log.ErrorLevel)
- walk(t, walletTestDir, func(t *testing.T, name string, test *walletTestConfig) {
- if err := test.Run(); err != nil {
- t.Fatal(err)
- }
- })
-}
if err := generator.AddSpendInput(input.AccountAlias, input.AssetAlias, input.Amount); err != nil {
return nil, err
}
- case "issue":
- _, err := ctx.createAsset(input.AccountAlias, input.AssetAlias)
- if err != nil {
- return nil, err
- }
- if err := generator.AddIssuanceInput(input.AssetAlias, input.Amount); err != nil {
- return nil, err
- }
}
}
return nil
}
-func (ctx *walletTestContext) createAsset(accountAlias string, assetAlias string) (*asset.Asset, error) {
- acc, err := ctx.Wallet.AccountMgr.FindByAlias(accountAlias)
- if err != nil {
- return nil, err
- }
- return ctx.Wallet.AssetReg.Define(acc.XPubs, len(acc.XPubs), nil, 0, assetAlias, nil)
-}
-
func (ctx *walletTestContext) newBlock(txs []*types.Tx, coinbaseAccount string) (*types.Block, error) {
controlProgram, err := ctx.createControlProgram(coinbaseAccount, true)
if err != nil {
"github.com/vapor/account"
"github.com/vapor/asset"
"github.com/vapor/blockchain/query"
- "github.com/vapor/blockchain/signers"
"github.com/vapor/common"
"github.com/vapor/consensus"
"github.com/vapor/consensus/segwit"
Alias: &alias,
DefinitionMap: definitionMap,
RawDefinitionByte: definitionByte,
- Signer: &signers.Signer{Type: "external"},
}
if err := w.AssetReg.SaveAsset(externalAsset, alias); err != nil {
for _, arg := range arguments {
in.WitnessArguments = append(in.WitnessArguments, arg)
}
- case *bc.Issuance:
- in.Type = "issue"
- in.IssuanceProgram = orig.IssuanceProgram()
- arguments := orig.Arguments()
- for _, arg := range arguments {
- in.WitnessArguments = append(in.WitnessArguments, arg)
- }
- if assetDefinition := orig.AssetDefinition(); isValidJSON(assetDefinition) {
- assetDefinition := json.RawMessage(assetDefinition)
- in.AssetDefinition = &assetDefinition
- }
case *bc.Coinbase:
in.Type = "coinbase"
in.Arbitrary = e.Arbitrary
log "github.com/sirupsen/logrus"
"github.com/vapor/account"
- "github.com/vapor/asset"
"github.com/vapor/blockchain/query"
"github.com/vapor/crypto/sha3pool"
dbm "github.com/vapor/database/leveldb"
defer storeBatch.Write()
for _, tx := range b.Transactions {
- for _, orig := range tx.Inputs {
- if ii, ok := orig.TypedInput.(*types.IssuanceInput); ok {
- if isValidJSON(ii.AssetDefinition) {
- assetID := ii.AssetID()
- if assetExist := walletDB.Get(asset.ExtAssetKey(&assetID)); assetExist == nil {
- storeBatch.Set(asset.ExtAssetKey(&assetID), ii.AssetDefinition)
- }
- }
- }
+ for _, _ = range tx.Inputs {
+ // handle cross chain input here
}
}
}
"github.com/vapor/crypto/ed25519/chainkd"
dbm "github.com/vapor/database/leveldb"
"github.com/vapor/event"
+ "github.com/vapor/protocol/bc"
"github.com/vapor/protocol/bc/types"
"github.com/vapor/testutil"
)
controlProg.KeyIndex = 1
reg := asset.NewRegistry(testDB, nil)
- asset, err := reg.Define([]chainkd.XPub{xpub1.XPub}, 1, nil, 0, "TESTASSET", nil)
- if err != nil {
- t.Fatal(err)
- }
+ asset := bc.AssetID{V0: 5}
dispatcher := event.NewDispatcher()
w := mockWallet(testDB, accountManager, reg, nil, dispatcher, false)
btmUtxo := mockUTXO(controlProg, consensus.BTMAssetID)
utxos = append(utxos, btmUtxo)
- OtherUtxo := mockUTXO(controlProg, &asset.AssetID)
+ OtherUtxo := mockUTXO(controlProg, &asset)
utxos = append(utxos, OtherUtxo)
_, txData, err := mockTxData(utxos, testAccount)
if err != nil {
{
tx: types.NewTx(types.TxData{
Inputs: []*types.TxInput{
- types.NewIssuanceInput([]byte{}, 4125, []byte{0x51}, [][]byte{}, []byte{}),
- },
- Outputs: []*types.TxOutput{
- types.NewIntraChainOutput(*consensus.BTMAssetID, 4125, []byte{0x51}),
- },
- }),
- statusFail: false,
- wantUtxos: []*account.UTXO{},
- },
- {
- tx: types.NewTx(types.TxData{
- Inputs: []*types.TxInput{
types.NewSpendInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 1, 1, []byte{0x51}),
types.NewSpendInput([][]byte{}, bc.Hash{V0: 2}, bc.AssetID{V0: 1}, 3, 2, []byte{0x52}),
types.NewSpendInput([][]byte{}, bc.Hash{V0: 3}, *consensus.BTMAssetID, 5, 3, []byte{0x53}),
controlProg.KeyIndex = 1
reg := asset.NewRegistry(testDB, chain)
- asset, err := reg.Define([]chainkd.XPub{xpub1.XPub}, 1, nil, 0, "TESTASSET", nil)
- if err != nil {
- t.Fatal(err)
- }
+ asset := bc.AssetID{V0: 5}
utxos := []*account.UTXO{}
btmUtxo := mockUTXO(controlProg, consensus.BTMAssetID)
utxos = append(utxos, btmUtxo)
- OtherUtxo := mockUTXO(controlProg, &asset.AssetID)
+ OtherUtxo := mockUTXO(controlProg, &asset)
utxos = append(utxos, OtherUtxo)
_, txData, err := mockTxData(utxos, testAccount)
controlProg.KeyIndex = 1
reg := asset.NewRegistry(testDB, chain)
- asset, err := reg.Define([]chainkd.XPub{xpub1.XPub}, 1, nil, 0, "TESTASSET", nil)
- if err != nil {
- t.Fatal(err)
- }
+ asset := bc.AssetID{V0: 5}
utxos := []*account.UTXO{}
btmUtxo := mockUTXO(controlProg, consensus.BTMAssetID)
utxos = append(utxos, btmUtxo)
- OtherUtxo := mockUTXO(controlProg, &asset.AssetID)
+ OtherUtxo := mockUTXO(controlProg, &asset)
utxos = append(utxos, OtherUtxo)
_, txData, err := mockTxData(utxos, testAccount)