X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=blockchain%2Ftxbuilder%2Factions.go;h=f5b40bc0b1b9cfbb0ae690e6db7d623007c5f828;hb=312e5053f0a820931cb5b0c68d418f8614f426b9;hp=6c4ee849920d77ad31fb5051359d4f5fb1480325;hpb=db158dcf09436b003defd333f1a665e7e051d820;p=bytom%2Fvapor.git diff --git a/blockchain/txbuilder/actions.go b/blockchain/txbuilder/actions.go index 6c4ee849..f5b40bc0 100644 --- a/blockchain/txbuilder/actions.go +++ b/blockchain/txbuilder/actions.go @@ -5,7 +5,10 @@ import ( 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" @@ -44,9 +47,9 @@ func (a *controlAddressAction) Build(ctx context.Context, b *TemplateBuilder) er if err != nil { return err } + redeemContract := address.ScriptAddress() program := []byte{} - switch address.(type) { case *common.AddressWitnessPubKeyHash: program, err = vmutil.P2WPKHProgram(redeemContract) @@ -59,7 +62,7 @@ func (a *controlAddressAction) Build(ctx context.Context, b *TemplateBuilder) er return err } - out := types.NewTxOutput(*a.AssetId, a.Amount, program) + out := types.NewIntraChainOutput(*a.AssetId, a.Amount, program) return b.AddOutput(out) } @@ -94,7 +97,7 @@ func (a *controlProgramAction) Build(ctx context.Context, b *TemplateBuilder) er return MissingFieldsError(missing...) } - out := types.NewTxOutput(*a.AssetId, a.Amount, a.Program) + out := types.NewIntraChainOutput(*a.AssetId, a.Amount, a.Program) return b.AddOutput(out) } @@ -130,10 +133,182 @@ func (a *retireAction) Build(ctx context.Context, b *TemplateBuilder) error { if err != nil { return err } - out := types.NewTxOutput(*a.AssetId, a.Amount, program) + out := types.NewIntraChainOutput(*a.AssetId, a.Amount, program) return b.AddOutput(out) } func (a *retireAction) ActionType() string { return "retire" } + +// DecodeCrossOutAction convert input data to action struct +func DecodeCrossOutAction(data []byte) (Action, error) { + a := new(crossOutAction) + err := stdjson.Unmarshal(data, a) + return a, err +} + +type crossOutAction struct { + bc.AssetAmount + Address string `json:"address"` +} + +func (a *crossOutAction) Build(ctx context.Context, b *TemplateBuilder) error { + var missing []string + if a.Address == "" { + missing = append(missing, "address") + } + if a.AssetId.IsZero() { + missing = append(missing, "asset_id") + } + if a.Amount == 0 { + missing = append(missing, "amount") + } + if len(missing) > 0 { + return MissingFieldsError(missing...) + } + + address, err := common.DecodeAddress(a.Address, consensus.BytomMainNetParams(&consensus.ActiveNetParams)) + 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 + } + + out := types.NewCrossChainOutput(*a.AssetId, a.Amount, program) + return b.AddOutput(out) +} + +func (a *crossOutAction) ActionType() string { + return "cross_chain_out" +} + +// DecodeVoteOutputAction convert input data to action struct +func DecodeVoteOutputAction(data []byte) (Action, error) { + a := new(voteOutputAction) + err := stdjson.Unmarshal(data, a) + return a, err +} + +type voteOutputAction struct { + bc.AssetAmount + Address string `json:"address"` + Vote json.HexBytes `json:"vote"` +} + +func (a *voteOutputAction) Build(ctx context.Context, b *TemplateBuilder) error { + var missing []string + if a.Address == "" { + missing = append(missing, "address") + } + if a.AssetId.IsZero() { + missing = append(missing, "asset_id") + } + if a.Amount == 0 { + missing = append(missing, "amount") + } + if len(a.Vote) == 0 { + missing = append(missing, "vote") + } + if len(missing) > 0 { + return MissingFieldsError(missing...) + } + + address, err := common.DecodeAddress(a.Address, &consensus.ActiveNetParams) + 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 + } + + out := types.NewVoteOutput(*a.AssetId, a.Amount, program, a.Vote) + return b.AddOutput(out) +} + +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 (a *crossInAction) Build(ctx context.Context, builder *TemplateBuilder) error { + var missing []string + if a.SourceID.IsZero() { + missing = append(missing, "source_id") + } + if a.AssetId.IsZero() { + missing = append(missing, "asset_id") + } + if a.Amount == 0 { + missing = append(missing, "amount") + } + + if len(missing) > 0 { + return MissingFieldsError(missing...) + } + + if err := a.checkAssetID(); err != nil { + return err + } + + // arguments will be set when materializeWitnesses + txin := types.NewCrossChainInput(nil, a.SourceID, *a.AssetId, a.Amount, a.SourcePos, a.VMVersion, a.RawDefinitionByte, a.IssuanceProgram) + tplIn := &SigningInstruction{} + fed := cfg.CommonConfig.Federation + tplIn.AddRawWitnessKeys(fed.Xpubs, cfg.FedAddressPath, fed.Quorum) + tplIn.AddDataWitness(cfg.FederationPMultiSigScript(cfg.CommonConfig)) + return builder.AddInput(txin, tplIn) +} + +func (a *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 +}