github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/blockchain/txbuilder/actions.go (about) 1 package txbuilder 2 3 import ( 4 "context" 5 stdjson "encoding/json" 6 "errors" 7 8 "github.com/bytom/bytom/common" 9 "github.com/bytom/bytom/consensus" 10 "github.com/bytom/bytom/encoding/json" 11 "github.com/bytom/bytom/protocol/bc" 12 "github.com/bytom/bytom/protocol/bc/types" 13 "github.com/bytom/bytom/protocol/vm/vmutil" 14 ) 15 16 // DecodeControlAddressAction convert input data to action struct 17 func DecodeControlAddressAction(data []byte) (Action, error) { 18 a := new(controlAddressAction) 19 err := stdjson.Unmarshal(data, a) 20 return a, err 21 } 22 23 type controlAddressAction struct { 24 bc.AssetAmount 25 Address string `json:"address"` 26 } 27 28 func (a *controlAddressAction) Build(ctx context.Context, b *TemplateBuilder) error { 29 var missing []string 30 if a.Address == "" { 31 missing = append(missing, "address") 32 } 33 if a.AssetId.IsZero() { 34 missing = append(missing, "asset_id") 35 } 36 if a.Amount == 0 { 37 missing = append(missing, "amount") 38 } 39 if len(missing) > 0 { 40 return MissingFieldsError(missing...) 41 } 42 43 address, err := common.DecodeAddress(a.Address, &consensus.ActiveNetParams) 44 if err != nil { 45 return err 46 } 47 redeemContract := address.ScriptAddress() 48 program := []byte{} 49 50 switch address.(type) { 51 case *common.AddressWitnessPubKeyHash: 52 program, err = vmutil.P2WPKHProgram(redeemContract) 53 case *common.AddressWitnessScriptHash: 54 program, err = vmutil.P2WSHProgram(redeemContract) 55 default: 56 return errors.New("unsupport address type") 57 } 58 if err != nil { 59 return err 60 } 61 62 out := types.NewOriginalTxOutput(*a.AssetId, a.Amount, program, nil) 63 return b.AddOutput(out) 64 } 65 66 func (a *controlAddressAction) ActionType() string { 67 return "control_address" 68 } 69 70 // DecodeControlProgramAction convert input data to action struct 71 func DecodeControlProgramAction(data []byte) (Action, error) { 72 a := new(controlProgramAction) 73 err := stdjson.Unmarshal(data, a) 74 return a, err 75 } 76 77 type controlProgramAction struct { 78 bc.AssetAmount 79 Program json.HexBytes `json:"control_program"` 80 } 81 82 func (a *controlProgramAction) Build(ctx context.Context, b *TemplateBuilder) error { 83 var missing []string 84 if len(a.Program) == 0 { 85 missing = append(missing, "control_program") 86 } 87 if a.AssetId.IsZero() { 88 missing = append(missing, "asset_id") 89 } 90 if a.Amount == 0 { 91 missing = append(missing, "amount") 92 } 93 if len(missing) > 0 { 94 return MissingFieldsError(missing...) 95 } 96 97 out := types.NewOriginalTxOutput(*a.AssetId, a.Amount, a.Program, nil) 98 return b.AddOutput(out) 99 } 100 101 func (a *controlProgramAction) ActionType() string { 102 return "control_program" 103 } 104 105 // DecodeRetireAction convert input data to action struct 106 func DecodeRetireAction(data []byte) (Action, error) { 107 a := new(retireAction) 108 err := stdjson.Unmarshal(data, a) 109 return a, err 110 } 111 112 type retireAction struct { 113 bc.AssetAmount 114 Arbitrary json.HexBytes `json:"arbitrary"` 115 } 116 117 func (a *retireAction) Build(ctx context.Context, b *TemplateBuilder) error { 118 var missing []string 119 if a.AssetId.IsZero() { 120 missing = append(missing, "asset_id") 121 } 122 if a.Amount == 0 { 123 missing = append(missing, "amount") 124 } 125 if len(missing) > 0 { 126 return MissingFieldsError(missing...) 127 } 128 129 program, err := vmutil.RetireProgram(a.Arbitrary) 130 if err != nil { 131 return err 132 } 133 out := types.NewOriginalTxOutput(*a.AssetId, a.Amount, program, nil) 134 return b.AddOutput(out) 135 } 136 137 func (a *retireAction) ActionType() string { 138 return "retire" 139 } 140 141 // DecodeRegisterAction convert input data to action struct 142 func DecodeRegisterAction(data []byte) (Action, error) { 143 a := new(registerAction) 144 return a, stdjson.Unmarshal(data, a) 145 } 146 147 type registerAction struct { 148 bc.AssetAmount 149 Contract json.HexBytes `json:"contract"` 150 } 151 152 func (a *registerAction) Build(ctx context.Context, b *TemplateBuilder) error { 153 var missing []string 154 if a.AssetId.IsZero() { 155 missing = append(missing, "asset_id") 156 } 157 if a.Amount == 0 { 158 missing = append(missing, "amount") 159 } 160 if len(a.Contract) == 0 { 161 missing = append(missing, "contract") 162 } 163 if len(missing) > 0 { 164 return MissingFieldsError(missing...) 165 } 166 167 if a.AssetId.String() != consensus.BTMAssetID.String() { 168 return errors.New("register contract action asset must be BTM") 169 } 170 171 if a.Amount < consensus.BCRPRequiredBTMAmount { 172 return errors.New("less than BCRP required BTM amount") 173 } 174 175 program, err := vmutil.RegisterProgram(a.Contract) 176 if err != nil { 177 return err 178 } 179 out := types.NewOriginalTxOutput(*a.AssetId, a.Amount, program, [][]byte{}) 180 return b.AddOutput(out) 181 } 182 183 func (a *registerAction) ActionType() string { 184 return "register_contract" 185 } 186 187 // DecodeVoteOutputAction convert input data to action struct 188 func DecodeVoteOutputAction(data []byte) (Action, error) { 189 a := new(voteOutputAction) 190 err := stdjson.Unmarshal(data, a) 191 return a, err 192 } 193 194 type voteOutputAction struct { 195 bc.AssetAmount 196 Address string `json:"address"` 197 Vote json.HexBytes `json:"vote"` 198 } 199 200 func (a *voteOutputAction) Build(ctx context.Context, b *TemplateBuilder) error { 201 var missing []string 202 if a.Address == "" { 203 missing = append(missing, "address") 204 } 205 if a.AssetId.IsZero() { 206 missing = append(missing, "asset_id") 207 } 208 if a.Amount == 0 { 209 missing = append(missing, "amount") 210 } 211 if len(a.Vote) == 0 { 212 missing = append(missing, "vote") 213 } 214 if len(missing) > 0 { 215 return MissingFieldsError(missing...) 216 } 217 218 address, err := common.DecodeAddress(a.Address, &consensus.ActiveNetParams) 219 if err != nil { 220 return err 221 } 222 223 redeemContract := address.ScriptAddress() 224 program := []byte{} 225 switch address.(type) { 226 case *common.AddressWitnessPubKeyHash: 227 program, err = vmutil.P2WPKHProgram(redeemContract) 228 case *common.AddressWitnessScriptHash: 229 program, err = vmutil.P2WSHProgram(redeemContract) 230 default: 231 return errors.New("unsupport address type") 232 } 233 if err != nil { 234 return err 235 } 236 237 out := types.NewVoteOutput(*a.AssetId, a.Amount, program, a.Vote, nil) 238 return b.AddOutput(out) 239 } 240 241 func (a *voteOutputAction) ActionType() string { 242 return "vote_output" 243 }