import (
"context"
- "encoding/hex"
"encoding/json"
"github.com/bytom/blockchain/signers"
"github.com/bytom/common"
"github.com/bytom/consensus"
"github.com/bytom/crypto/ed25519/chainkd"
- chainjson "github.com/bytom/encoding/json"
"github.com/bytom/errors"
"github.com/bytom/protocol/bc"
"github.com/bytom/protocol/bc/types"
type spendUTXOAction struct {
accounts *Manager
- OutputID *bc.Hash `json:"output_id"`
- UseUnconfirmed bool `json:"use_unconfirmed"`
- Arguments []contractArgument `json:"arguments"`
-}
-
-// contractArgument for smart contract
-type contractArgument struct {
- Type string `json:"type"`
- RawData json.RawMessage `json:"raw_data"`
-}
-
-// rawTxSigArgument is signature-related argument for run contract
-type rawTxSigArgument struct {
- RootXPub chainkd.XPub `json:"xpub"`
- Path []chainjson.HexBytes `json:"derivation_path"`
-}
-
-// dataArgument is the other argument for run contract
-type dataArgument struct {
- Value string `json:"value"`
+ OutputID *bc.Hash `json:"output_id"`
+ UseUnconfirmed bool `json:"use_unconfirmed"`
+ Arguments []txbuilder.ContractArgument `json:"arguments"`
}
func (a *spendUTXOAction) Build(ctx context.Context, b *txbuilder.TemplateBuilder) error {
}
sigInst = &txbuilder.SigningInstruction{}
- for _, arg := range a.Arguments {
- switch arg.Type {
- case "raw_tx_signature":
- rawTxSig := &rawTxSigArgument{}
- if err = json.Unmarshal(arg.RawData, rawTxSig); err != nil {
- return err
- }
-
- // convert path form chainjson.HexBytes to byte
- var path [][]byte
- for _, p := range rawTxSig.Path {
- path = append(path, []byte(p))
- }
- sigInst.AddRawWitnessKeys([]chainkd.XPub{rawTxSig.RootXPub}, path, 1)
-
- case "data":
- data := &dataArgument{}
- if err = json.Unmarshal(arg.RawData, data); err != nil {
- return err
- }
-
- value, err := hex.DecodeString(data.Value)
- if err != nil {
- return err
- }
- sigInst.WitnessComponents = append(sigInst.WitnessComponents, txbuilder.DataWitness(value))
-
- default:
- return errors.New("contract argument type is not exist")
- }
+ if err := txbuilder.AddContractArgs(sigInst, a.Arguments); err != nil {
+ return err
}
+
return b.AddInput(txInput, sigInst)
}
package account
import (
- "encoding/hex"
- "encoding/json"
"testing"
"github.com/bytom/blockchain/txbuilder"
- "github.com/bytom/crypto/ed25519/chainkd"
- chainjson "github.com/bytom/encoding/json"
"github.com/bytom/protocol/bc"
- "github.com/bytom/testutil"
)
func TestMergeSpendAction(t *testing.T) {
}
}
}
-
-func TestSpendUTXOArguments(t *testing.T) {
- hexXpub, err := hex.DecodeString("ba76bb52574b3f40315f2c01f1818a9072ced56e9d4b68acbef56a4d0077d08e5e34837963e4cdc54eb251aa34aad01e6ae48b140f6a2743fbb0a0abd9cf8aac")
- if err != nil {
- t.Fatal(err)
- }
-
- var xpub chainkd.XPub
- copy(xpub[:], hexXpub)
-
- rawTxSig := rawTxSigArgument{RootXPub: xpub, Path: []chainjson.HexBytes{{1, 1, 0, 0, 0, 0, 0, 0, 0}, {1, 0, 0, 0, 0, 0, 0, 0}}}
- rawTxSigMsg, err := json.Marshal(rawTxSig)
- if err != nil {
- t.Fatal(err)
- }
-
- data := dataArgument{Value: "7468697320697320612074657374"}
- dataMsg, err := json.Marshal(data)
- if err != nil {
- t.Fatal(err)
- }
-
- cases := []struct {
- rawAction string
- wantResult *spendUTXOAction
- }{
- {
- rawAction: `{ "type": "spend_account_unspent_output", "output_id": "e304de887423e4e684e483f5ae65236d47018b56cac94ef3fb8b5dd40c897e11",
- "arguments": [{"type": "raw_tx_signature", "raw_data": {"derivation_path": ["010100000000000000", "0100000000000000"],
- "xpub": "ba76bb52574b3f40315f2c01f1818a9072ced56e9d4b68acbef56a4d0077d08e5e34837963e4cdc54eb251aa34aad01e6ae48b140f6a2743fbb0a0abd9cf8aac"}}]}`,
- wantResult: &spendUTXOAction{
- OutputID: &bc.Hash{16358444424161912038, 9575923798912607085, 5116523856555233011, 18125684290607480337},
- Arguments: []contractArgument{
- {
- Type: "raw_tx_signature",
- RawData: rawTxSigMsg,
- },
- },
- },
- },
- {
- rawAction: `{ "type": "spend_account_unspent_output", "output_id": "8669b5c2e0701ec1ca45cd413e46c4f1d5f794f9d9144f904f3e7da8c68c6410",
- "arguments": [{"type": "data", "raw_data": {"value": "7468697320697320612074657374"}}]}`,
- wantResult: &spendUTXOAction{
- OutputID: &bc.Hash{9685472322230689473, 14575281449155871985, 15417955650135936912, 5710139541391434768},
- Arguments: []contractArgument{
- {
- Type: "data",
- RawData: dataMsg,
- },
- },
- },
- },
- {
- rawAction: `{ "type": "spend_account_unspent_output", "output_id": "8669b5c2e0701ec1ca45cd413e46c4f1d5f794f9d9144f904f3e7da8c68c6410",
- "arguments": [{"type": "signature", "raw_data": {"value": "7468697320697320612074657374"}}]}`,
- wantResult: &spendUTXOAction{
- OutputID: &bc.Hash{9685472322230689473, 14575281449155871985, 15417955650135936912, 5710139541391434768},
- },
- },
- {
- rawAction: `{ "type": "spend_account_unspent_output", "output_id": "8669b5c2e0701ec1ca45cd413e46c4f1d5f794f9d9144f904f3e7da8c68c6410"}`,
- wantResult: &spendUTXOAction{
- OutputID: &bc.Hash{9685472322230689473, 14575281449155871985, 15417955650135936912, 5710139541391434768},
- Arguments: nil,
- },
- },
- }
-
- for _, c := range cases {
- var spendUTXOReq *spendUTXOAction
- if err := json.Unmarshal([]byte(c.rawAction), &spendUTXOReq); err != nil {
- t.Fatalf("unmarshal spendUTXOAction error:%v", err)
- }
-
- if !testutil.DeepEqual(spendUTXOReq.OutputID, c.wantResult.OutputID) {
- t.Fatalf("OutputID gotResult=%v, wantResult=%v", spendUTXOReq.OutputID, c.wantResult.OutputID)
- }
-
- if spendUTXOReq.Arguments == nil {
- if c.wantResult.Arguments != nil {
- t.Fatalf("Arguments gotResult is nil, wantResult[%v] is not nil", c.wantResult.Arguments)
- }
- continue
- }
-
- for _, arg := range spendUTXOReq.Arguments {
- switch arg.Type {
- case "raw_tx_signature":
- rawTxSig := &rawTxSigArgument{}
- if err := json.Unmarshal(arg.RawData, rawTxSig); err != nil {
- t.Fatalf("unmarshal rawTxSigArgument error:%v", err)
- }
-
- wantRawTxSig := &rawTxSigArgument{}
- if err := json.Unmarshal(c.wantResult.Arguments[0].RawData, wantRawTxSig); err != nil {
- t.Fatalf("unmarshal want rawTxSigArgument error:%v", err)
- }
-
- if !testutil.DeepEqual(rawTxSig, wantRawTxSig) {
- t.Fatalf("rawTxSigArgument gotResult=%v, wantResult=%v", rawTxSig, wantRawTxSig)
- }
-
- case "data":
- data := &dataArgument{}
- if err := json.Unmarshal(arg.RawData, data); err != nil {
- t.Fatalf("unmarshal dataArgument error:%v", err)
- }
-
- wantData := &dataArgument{}
- if err := json.Unmarshal(c.wantResult.Arguments[0].RawData, wantData); err != nil {
- t.Fatalf("unmarshal want dataArgument error:%v", err)
- }
-
- if !testutil.DeepEqual(data, wantData) {
- t.Fatalf("dataArgument gotResult=%v, wantResult=%v", data, wantData)
- }
-
- default:
- if arg.Type == "raw_tx_signature" || arg.Type == "data" {
- t.Fatalf("argument type [%v] is not exist", arg.Type)
- }
- }
- }
- }
-}
"github.com/bytom/asset"
"github.com/bytom/crypto/ed25519/chainkd"
+ chainjson "github.com/bytom/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"`
+ Alias string `json:"alias"`
+ RootXPubs []chainkd.XPub `json:"root_xpubs"`
+ Quorum int `json:"quorum"`
+ Definition map[string]interface{} `json:"definition"`
+ IssuanceProgram chainjson.HexBytes `json:"issuance_program"`
}) Response {
ass, err := a.wallet.AssetReg.Define(
ins.RootXPubs,
ins.Quorum,
ins.Definition,
strings.ToUpper(strings.TrimSpace(ins.Alias)),
+ ins.IssuanceProgram,
)
if err != nil {
return NewErrorResponse(err)
// Transaction error namespace (7xx)
// Build transaction error namespace (70x ~ 72x)
- account.ErrInsufficient: {400, "BTM700", "Funds of account are insufficient"},
- account.ErrImmature: {400, "BTM701", "Available funds of account are immature"},
- account.ErrReserved: {400, "BTM702", "Available UTXOs of account have been reserved"},
- account.ErrMatchUTXO: {400, "BTM703", "Not found UTXO with given hash"},
- ErrBadActionType: {400, "BTM704", "Invalid action type"},
- ErrBadAction: {400, "BTM705", "Invalid action object"},
- ErrBadActionConstruction: {400, "BTM706", "Invalid action construction"},
- txbuilder.ErrMissingFields: {400, "BTM707", "One or more fields are missing"},
- txbuilder.ErrBadAmount: {400, "BTM708", "Invalid asset amount"},
- account.ErrFindAccount: {400, "BTM709", "Not found account"},
- asset.ErrFindAsset: {400, "BTM710", "Not found asset"},
+ account.ErrInsufficient: {400, "BTM700", "Funds of account are insufficient"},
+ account.ErrImmature: {400, "BTM701", "Available funds of account are immature"},
+ account.ErrReserved: {400, "BTM702", "Available UTXOs of account have been reserved"},
+ account.ErrMatchUTXO: {400, "BTM703", "Not found UTXO with given hash"},
+ ErrBadActionType: {400, "BTM704", "Invalid action type"},
+ ErrBadAction: {400, "BTM705", "Invalid action object"},
+ ErrBadActionConstruction: {400, "BTM706", "Invalid action construction"},
+ txbuilder.ErrMissingFields: {400, "BTM707", "One or more fields are missing"},
+ txbuilder.ErrBadAmount: {400, "BTM708", "Invalid asset amount"},
+ account.ErrFindAccount: {400, "BTM709", "Not found account"},
+ asset.ErrFindAsset: {400, "BTM710", "Not found asset"},
+ txbuilder.ErrBadContractArgType: {400, "BTM711", "Invalid contract argument type"},
// Submit transaction error namespace (73x ~ 79x)
// Validation error (73x ~ 75x)
}
// Define defines a new Asset.
-func (reg *Registry) Define(xpubs []chainkd.XPub, quorum int, definition map[string]interface{}, alias string) (*Asset, error) {
- if len(xpubs) == 0 {
- return nil, errors.Wrap(signers.ErrNoXPubs)
- }
+func (reg *Registry) Define(xpubs []chainkd.XPub, quorum int, definition map[string]interface{}, alias string, issuanceProgram chainjson.HexBytes) (*Asset, error) {
+ var err error
+ var assetSigner *signers.Signer
alias = strings.ToUpper(strings.TrimSpace(alias))
if alias == "" {
return nil, ErrInternalAsset
}
- nextAssetIndex := reg.getNextAssetIndex()
- assetSigner, err := signers.Create("asset", xpubs, quorum, nextAssetIndex)
- if err != nil {
- return nil, err
- }
-
rawDefinition, err := serializeAssetDef(definition)
if err != nil {
return nil, ErrSerializing
}
- path := signers.Path(assetSigner, signers.AssetKeySpace)
- derivedXPubs := chainkd.DeriveXPubs(assetSigner.XPubs, path)
- derivedPKs := chainkd.XPubKeys(derivedXPubs)
- issuanceProgram, vmver, err := multisigIssuanceProgram(derivedPKs, assetSigner.Quorum)
- if err != nil {
- return nil, err
+ 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)
+ if err != nil {
+ return nil, err
+ }
+
+ path := signers.Path(assetSigner, signers.AssetKeySpace)
+ derivedXPubs := chainkd.DeriveXPubs(assetSigner.XPubs, path)
+ derivedPKs := chainkd.XPubKeys(derivedXPubs)
+ issuanceProgram, vmver, err = multisigIssuanceProgram(derivedPKs, assetSigner.Quorum)
+ if err != nil {
+ return nil, err
+ }
}
defHash := bc.NewHash(sha3.Sum256(rawDefinition))
func TestDefineAssetWithLowercase(t *testing.T) {
reg := mockNewRegistry(t)
alias := "lower"
- asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, alias)
+ asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, alias, nil)
if err != nil {
t.Fatal(err)
}
func TestDefineAssetWithSpaceTrimed(t *testing.T) {
reg := mockNewRegistry(t)
alias := " WITH SPACE "
- asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, alias)
+ asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, alias, nil)
if err != nil {
t.Fatal(err)
}
func TestDefineAsset(t *testing.T) {
ctx := context.Background()
reg := mockNewRegistry(t)
- asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, "asset-alias")
+ asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, "asset-alias", nil)
if err != nil {
testutil.FatalErr(t, err)
}
func TestDefineBtmAsset(t *testing.T) {
reg := mockNewRegistry(t)
- _, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, consensus.BTMAlias)
+ _, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, consensus.BTMAlias, nil)
if err == nil {
testutil.FatalErr(t, err)
}
ctx := context.Background()
reg := mockNewRegistry(t)
keys := []chainkd.XPub{testutil.TestXPub}
- asset, err := reg.Define(keys, 1, nil, "TESTASSET")
+ asset, err := reg.Define(keys, 1, nil, "TESTASSET", nil)
if err != nil {
testutil.FatalErr(t, err)
oldAlias := "OLD_ALIAS"
newAlias := "NEW_ALIAS"
- asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, oldAlias)
+ asset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, oldAlias, nil)
if err != nil {
testutil.FatalErr(t, err)
}
firstAlias := "FIRST_ALIAS"
secondAlias := "SECOND_ALIAS"
- firstAsset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, firstAlias)
+ firstAsset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, firstAlias, nil)
if err != nil {
testutil.FatalErr(t, err)
}
- secondAsset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, secondAlias)
+ secondAsset, err := reg.Define([]chainkd.XPub{testutil.TestXPub}, 1, nil, secondAlias, nil)
if err != nil {
testutil.FatalErr(t, err)
}
type issueAction struct {
assets *Registry
bc.AssetAmount
+ Arguments []txbuilder.ContractArgument `json:"arguments"`
}
func (a *issueAction) Build(ctx context.Context, builder *txbuilder.TemplateBuilder) error {
return err
}
- assetDef := asset.RawDefinitionByte
-
- txin := types.NewIssuanceInput(nonce[:], a.Amount, asset.IssuanceProgram, nil, assetDef)
-
+ txin := types.NewIssuanceInput(nonce[:], a.Amount, asset.IssuanceProgram, nil, asset.RawDefinitionByte)
tplIn := &txbuilder.SigningInstruction{}
- path := signers.Path(asset.Signer, signers.AssetKeySpace)
- tplIn.AddRawWitnessKeys(asset.Signer.XPubs, path, asset.Signer.Quorum)
+ if a.Arguments == nil {
+ path := signers.Path(asset.Signer, signers.AssetKeySpace)
+ tplIn.AddRawWitnessKeys(asset.Signer.XPubs, path, asset.Signer.Quorum)
+ } else {
+ if err := txbuilder.AddContractArgs(tplIn, a.Arguments); err != nil {
+ return err
+ }
+ }
log.Info("Issue action build")
builder.RestrictMinTime(time.Now())
import (
"context"
+ "encoding/hex"
+ "encoding/json"
"time"
log "github.com/sirupsen/logrus"
+ "github.com/bytom/crypto/ed25519/chainkd"
"github.com/bytom/errors"
"github.com/bytom/math/checked"
"github.com/bytom/protocol/bc"
ErrAction = errors.New("errors occurred in one or more actions")
//ErrMissingFields means missing required fields
ErrMissingFields = errors.New("required field is missing")
+ //ErrBadContractArgType means invalid contract argument type
+ ErrBadContractArgType = errors.New("invalid contract argument type")
)
// Build builds or adds on to a transaction.
func MissingFieldsError(name ...string) error {
return errors.WithData(ErrMissingFields, "missing_fields", name)
}
+
+// AddContractArgs add contract arguments
+func AddContractArgs(sigInst *SigningInstruction, arguments []ContractArgument) error {
+ for _, arg := range arguments {
+ switch arg.Type {
+ case "raw_tx_signature":
+ rawTxSig := &RawTxSigArgument{}
+ if err := json.Unmarshal(arg.RawData, rawTxSig); err != nil {
+ return err
+ }
+
+ // convert path form chainjson.HexBytes to byte
+ var path [][]byte
+ for _, p := range rawTxSig.Path {
+ path = append(path, []byte(p))
+ }
+ sigInst.AddRawWitnessKeys([]chainkd.XPub{rawTxSig.RootXPub}, path, 1)
+
+ case "data":
+ data := &DataArgument{}
+ if err := json.Unmarshal(arg.RawData, data); err != nil {
+ return err
+ }
+
+ value, err := hex.DecodeString(data.Value)
+ if err != nil {
+ return err
+ }
+ sigInst.WitnessComponents = append(sigInst.WitnessComponents, DataWitness(value))
+
+ default:
+ return ErrBadContractArgType
+ }
+ }
+
+ return nil
+}
import (
"context"
"encoding/hex"
+ "encoding/json"
"math"
"testing"
"time"
"github.com/bytom/crypto"
"github.com/bytom/crypto/ed25519"
"github.com/bytom/crypto/ed25519/chainkd"
- "github.com/bytom/encoding/json"
+ chainjson "github.com/bytom/encoding/json"
"github.com/bytom/errors"
"github.com/bytom/protocol/bc"
"github.com/bytom/protocol/bc/types"
Keys: []keyID{
{
XPub: pubkey1,
- DerivationPath: []json.HexBytes{{0, 0, 0, 0}},
+ DerivationPath: []chainjson.HexBytes{{0, 0, 0, 0}},
},
{
XPub: pubkey2,
- DerivationPath: []json.HexBytes{{0, 0, 0, 0}},
+ DerivationPath: []chainjson.HexBytes{{0, 0, 0, 0}},
},
{
XPub: pubkey3,
- DerivationPath: []json.HexBytes{{0, 0, 0, 0}},
+ DerivationPath: []chainjson.HexBytes{{0, 0, 0, 0}},
},
},
Program: prog,
- Sigs: []json.HexBytes{sig1, sig2, sig3},
+ Sigs: []chainjson.HexBytes{sig1, sig2, sig3},
},
},
}}
// Test with exact amount of signatures required, in correct order
component := tpl.SigningInstructions[0].WitnessComponents[0].(*SignatureWitness)
- component.Sigs = []json.HexBytes{sig1, sig2}
+ component.Sigs = []chainjson.HexBytes{sig1, sig2}
err = materializeWitnesses(tpl)
if err != nil {
testutil.FatalErr(t, err)
WitnessComponents: []witnessComponent{
&RawTxSigWitness{
Quorum: 1,
- Sigs: []json.HexBytes{sig},
+ Sigs: []chainjson.HexBytes{sig},
},
DataWitness(data),
},
t.Errorf("tx:%v result is equal to want:%v", tx, tpl.Transaction)
}
}
+
+func TestAddContractArgs(t *testing.T) {
+ hexXpub, err := hex.DecodeString("ba76bb52574b3f40315f2c01f1818a9072ced56e9d4b68acbef56a4d0077d08e5e34837963e4cdc54eb251aa34aad01e6ae48b140f6a2743fbb0a0abd9cf8aac")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ var xpub chainkd.XPub
+ copy(xpub[:], hexXpub)
+
+ rawTxSig := RawTxSigArgument{RootXPub: xpub, Path: []chainjson.HexBytes{{1, 1, 0, 0, 0, 0, 0, 0, 0}, {1, 0, 0, 0, 0, 0, 0, 0}}}
+ rawTxSigMsg, err := json.Marshal(rawTxSig)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ data := DataArgument{Value: "7468697320697320612074657374"}
+ dataMsg, err := json.Marshal(data)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ cases := []struct {
+ arguments []ContractArgument
+ wantResult error
+ }{
+ {
+ arguments: []ContractArgument{
+ {
+ Type: "raw_tx_signature",
+ RawData: rawTxSigMsg,
+ },
+ {
+ Type: "data",
+ RawData: dataMsg,
+ },
+ },
+ wantResult: nil,
+ },
+ {
+ arguments: []ContractArgument{
+ {
+ Type: "data",
+ RawData: dataMsg,
+ },
+ {
+ Type: "raw_tx_signature",
+ RawData: rawTxSigMsg,
+ },
+ },
+ wantResult: nil,
+ },
+ {
+ arguments: []ContractArgument{
+ {
+ Type: "data",
+ RawData: dataMsg,
+ },
+ {
+ Type: "err_data",
+ RawData: rawTxSigMsg,
+ },
+ },
+ wantResult: ErrBadContractArgType,
+ },
+ }
+
+ sigInst := &SigningInstruction{}
+ for _, c := range cases {
+ err := AddContractArgs(sigInst, c.arguments)
+ if err != c.wantResult {
+ t.Fatalf("got result=%v, want result=%v", err, c.wantResult)
+ }
+ }
+}
import (
"context"
+ "encoding/json"
+ "github.com/bytom/crypto/ed25519/chainkd"
chainjson "github.com/bytom/encoding/json"
"github.com/bytom/protocol/bc"
"github.com/bytom/protocol/bc/types"
ControlProgram chainjson.HexBytes `json:"control_program,omitempty"`
Address string `json:"address,omitempty"`
}
+
+// ContractArgument for smart contract
+type ContractArgument struct {
+ Type string `json:"type"`
+ RawData json.RawMessage `json:"raw_data"`
+}
+
+// RawTxSigArgument is signature-related argument for run contract
+type RawTxSigArgument struct {
+ RootXPub chainkd.XPub `json:"xpub"`
+ Path []chainjson.HexBytes `json:"derivation_path"`
+}
+
+// DataArgument is the other argument for run contract
+type DataArgument struct {
+ Value string `json:"value"`
+}
"github.com/spf13/cobra"
jww "github.com/spf13/jwalterweatherman"
+ "encoding/hex"
"github.com/bytom/crypto/ed25519/chainkd"
"github.com/bytom/util"
)
createAssetCmd.PersistentFlags().IntVarP(&assetQuorum, "quorom", "q", 1, "quorum must be greater than 0 and less than or equal to the number of signers")
createAssetCmd.PersistentFlags().StringVarP(&assetToken, "access", "a", "", "access token")
createAssetCmd.PersistentFlags().StringVarP(&assetDefiniton, "definition", "d", "", "definition for the asset")
+ createAssetCmd.PersistentFlags().StringVarP(&issuanceProgram, "issueprogram", "i", "", "issue program for the asset")
listAssetsCmd.PersistentFlags().StringVar(&assetID, "id", "", "ID of asset")
}
var (
- assetID = ""
- assetQuorum = 1
- assetToken = ""
- assetDefiniton = ""
+ assetID = ""
+ assetQuorum = 1
+ assetToken = ""
+ assetDefiniton = ""
+ issuanceProgram = ""
)
var createAssetCmd = &cobra.Command{
Use: "create-asset <alias> <xpub(s)>",
Short: "Create an asset",
- Args: cobra.MinimumNArgs(2),
+ Args: cobra.RangeArgs(1, 2),
Run: func(cmd *cobra.Command, args []string) {
var ins assetIns
ins.Definition = map[string]interface{}{definition[0]: definition[1]}
}
+ if issuanceProgram != "" {
+ issueProg, err := hex.DecodeString(issuanceProgram)
+ if err != nil {
+ jww.ERROR.Println(err)
+ os.Exit(util.ErrLocalExe)
+ }
+ ins.IssuanceProgram = issueProg
+ }
+
data, exitCode := util.ClientCall("/create-asset", &ins)
if exitCode != util.Success {
os.Exit(exitCode)
"github.com/bytom/crypto/ed25519/chainkd"
"github.com/bytom/encoding/json"
+ chainjson "github.com/bytom/encoding/json"
"github.com/bytom/util"
)
// accountIns is used for account related request.
type accountIns struct {
- RootXPubs []chainkd.XPub `json:"root_xpubs"`
- Quorum int `json:"quorum"`
- Alias string `json:"alias"`
- AccessToken string `json:"access_token"`
+ RootXPubs []chainkd.XPub `json:"root_xpubs"`
+ Quorum int `json:"quorum"`
+ Alias string `json:"alias"`
+ AccessToken string `json:"access_token"`
}
// assetIns is used for asset related request.
type assetIns struct {
- RootXPubs []chainkd.XPub `json:"root_xpubs"`
- Quorum int `json:"quorum"`
- Alias string `json:"alias"`
- Definition map[string]interface{} `json:"definition"`
- AccessToken string `json:"access_token"`
+ RootXPubs []chainkd.XPub `json:"root_xpubs"`
+ Quorum int `json:"quorum"`
+ Alias string `json:"alias"`
+ Definition map[string]interface{} `json:"definition"`
+ IssuanceProgram chainjson.HexBytes `json:"issuance_program"`
+ AccessToken string `json:"access_token"`
}
type requestQuery struct {
if err != nil {
return nil, err
}
- return g.Assets.Define(acc.XPubs, len(acc.XPubs), nil, assetAlias)
+ return g.Assets.Define(acc.XPubs, len(acc.XPubs), nil, assetAlias, nil)
}
func (g *TxGenerator) mockUtxo(accountAlias, assetAlias string, amount uint64) (*account.UTXO, error) {
if err != nil {
return nil, err
}
- return ctx.Wallet.AssetReg.Define(acc.XPubs, len(acc.XPubs), nil, assetAlias)
+ return ctx.Wallet.AssetReg.Define(acc.XPubs, len(acc.XPubs), nil, assetAlias, nil)
}
func (ctx *walletTestContext) newBlock(txs []*types.Tx, coinbaseAccount string) (*types.Block, error) {
controlProg.KeyIndex = 1
reg := asset.NewRegistry(testDB, nil)
- asset, err := reg.Define([]chainkd.XPub{xpub1.XPub}, 1, nil, "TESTASSET")
+ asset, err := reg.Define([]chainkd.XPub{xpub1.XPub}, 1, nil, "TESTASSET", nil)
if err != nil {
t.Fatal(err)
}
controlProg.KeyIndex = 1
reg := asset.NewRegistry(testDB, chain)
- asset, err := reg.Define([]chainkd.XPub{xpub1.XPub}, 1, nil, "TESTASSET")
+ asset, err := reg.Define([]chainkd.XPub{xpub1.XPub}, 1, nil, "TESTASSET", nil)
if err != nil {
t.Fatal(err)
}