stdjson "encoding/json"
"errors"
+ "golang.org/x/crypto/sha3"
+
"github.com/vapor/common"
+ cfg "github.com/vapor/config"
"github.com/vapor/consensus"
"github.com/vapor/encoding/json"
"github.com/vapor/protocol/bc"
type crossOutAction struct {
bc.AssetAmount
- Address string `json:"address"`
+ Address string `json:"address"`
+ Program json.HexBytes `json:"control_program"`
}
func (a *crossOutAction) Build(ctx context.Context, b *TemplateBuilder) error {
var missing []string
- if a.Address == "" {
- missing = append(missing, "address")
+ if a.Address == "" && len(a.Program) == 0 {
+ missing = append(missing, "address or program")
}
if a.AssetId.IsZero() {
missing = append(missing, "asset_id")
return MissingFieldsError(missing...)
}
- address, err := common.DecodeAddress(a.Address, &consensus.MainNetParams)
- if err != nil {
- return err
- }
-
- redeemContract := address.ScriptAddress()
- program := []byte{}
- switch address.(type) {
- case *common.AddressWitnessPubKeyHash:
- program, err = vmutil.P2WPKHProgram(redeemContract)
- case *common.AddressWitnessScriptHash:
- program, err = vmutil.P2WSHProgram(redeemContract)
- default:
- return errors.New("unsupport address type")
- }
- if err != nil {
- return err
+ program := a.Program
+ if a.Address != "" {
+ address, err := common.DecodeAddress(a.Address, consensus.BytomMainNetParams(&consensus.ActiveNetParams))
+ if err != nil {
+ return err
+ }
+
+ redeemContract := address.ScriptAddress()
+ switch address.(type) {
+ case *common.AddressWitnessPubKeyHash:
+ program, err = vmutil.P2WPKHProgram(redeemContract)
+ case *common.AddressWitnessScriptHash:
+ program, err = vmutil.P2WSHProgram(redeemContract)
+ default:
+ return errors.New("unsupport address type")
+ }
+ if err != nil {
+ return err
+ }
}
out := types.NewCrossChainOutput(*a.AssetId, a.Amount, program)
func (a *voteOutputAction) ActionType() string {
return "vote_output"
}
+
+// DecodeCrossInAction convert input data to action struct
+func DecodeCrossInAction(data []byte) (Action, error) {
+ a := new(crossInAction)
+ err := stdjson.Unmarshal(data, a)
+ return a, err
+}
+
+type crossInAction struct {
+ bc.AssetAmount
+ SourceID bc.Hash `json:"source_id"`
+ SourcePos uint64 `json:"source_pos"`
+ VMVersion uint64 `json:"vm_version"`
+ RawDefinitionByte json.HexBytes `json:"raw_definition_byte"`
+ IssuanceProgram json.HexBytes `json:"issuance_program"`
+}
+
+func (c *crossInAction) Build(ctx context.Context, builder *TemplateBuilder) error {
+ var missing []string
+ if c.SourceID.IsZero() {
+ missing = append(missing, "source_id")
+ }
+ if c.AssetId.IsZero() {
+ missing = append(missing, "asset_id")
+ }
+ if c.Amount == 0 {
+ missing = append(missing, "amount")
+ }
+
+ if len(missing) > 0 {
+ return MissingFieldsError(missing...)
+ }
+
+ if err := c.checkAssetID(); err != nil {
+ return err
+ }
+
+ // arguments will be set when materializeWitnesses
+ txin := types.NewCrossChainInput(nil, c.SourceID, *c.AssetId, c.Amount, c.SourcePos, c.VMVersion, c.RawDefinitionByte, c.IssuanceProgram)
+ tplIn := &SigningInstruction{}
+ fed := cfg.CommonConfig.Federation
+
+ if !common.IsOpenFederationIssueAsset(c.RawDefinitionByte) {
+ tplIn.AddRawWitnessKeys(fed.Xpubs, cfg.FedAddressPath, fed.Quorum)
+ tplIn.AddDataWitness(cfg.FederationPMultiSigScript(cfg.CommonConfig))
+ }
+
+ return builder.AddInput(txin, tplIn)
+}
+
+func (c *crossInAction) ActionType() string {
+ return "cross_chain_in"
+}
+
+func (c *crossInAction) checkAssetID() error {
+ defHash := bc.NewHash(sha3.Sum256(c.RawDefinitionByte))
+ assetID := bc.ComputeAssetID(c.IssuanceProgram, c.VMVersion, &defHash)
+
+ if *c.AssetId != *consensus.BTMAssetID && assetID != *c.AssetAmount.AssetId {
+ return errors.New("incorrect asset_idincorrect asset_id")
+ }
+
+ return nil
+}