github.com/datachainlab/burrow@v0.25.0/deploy/def/jobs.go (about) 1 package def 2 3 import ( 4 "regexp" 5 6 validation "github.com/go-ozzo/ozzo-validation" 7 "github.com/go-ozzo/ozzo-validation/is" 8 "github.com/hyperledger/burrow/deploy/def/rule" 9 "github.com/hyperledger/burrow/execution/evm/abi" 10 ) 11 12 // ------------------------------------------------------------------------ 13 // Proposal Jobs 14 // ------------------------------------------------------------------------ 15 16 type Proposal struct { 17 // (Optional), address of the account that signs the proposal or votes for the proposal 18 Source string `mapstructure:"source" json:"source" yaml:"source" toml:"source"` 19 // (Optional, advanced only) sequence to use when burrow keys signs the transaction (do not use unless you 20 // know what you're doing) 21 Sequence string `mapstructure:"sequence" json:"sequence" yaml:"sequence" toml:"sequence"` 22 // (Required), address of the account used for serialising proposals, the proposals system account 23 ProposalAddress string `mapstructure:"proposaladdress" json:"proposaladdress" yaml:"proposaladdress" toml:"proposaladdress"` 24 // (Optional), sequence of the ProposalAddress 25 ProposalSequence string `mapstructure:"proposalsequence" json:"proposalsequence" yaml:"proposalsequence" toml:"proposalsequence"` 26 // (Optional) 27 VotingPower string `mapstructure:"votingpower" json:"votingpower" yaml:"votingpower" toml:"votingpower"` 28 // (Required) the name of the proposal 29 Name string `mapstructure:"name" json:"name" yaml:"name" toml:"name"` 30 // (Required) the description of the proposal 31 Description string `mapstructure:"description" json:"description" yaml:"description" toml:"description"` 32 // (Required) the file path of the sub yaml to run 33 Jobs []*Job `mapstructure:"jobs" json:"jobs" yaml:"jobs" toml:"jobs"` 34 } 35 36 func (job *Proposal) Validate() error { 37 return validation.ValidateStruct(job, 38 validation.Field(&job.Sequence, rule.Uint64OrPlaceholder), 39 validation.Field(&job.VotingPower, rule.Uint64OrPlaceholder), 40 validation.Field(&job.Name, validation.Required), 41 validation.Field(&job.Description, validation.Required), 42 validation.Field(&job.Jobs, validation.Required), 43 ) 44 } 45 46 // ------------------------------------------------------------------------ 47 // Meta Jobs 48 // ------------------------------------------------------------------------ 49 50 // Used in the Target of UpdateAccount to determine whether to create a new account, e.g. new() or new(key1,ed25519) 51 var NewKeyRegex = regexp.MustCompile(`new\((?P<keyName>[[:alnum:]]+)?(,(?P<curveType>[[:alnum:]]+))?\)`) 52 53 func KeyNameCurveType(newKeyMatch []string) (keyName, curveType string) { 54 for i, name := range NewKeyRegex.SubexpNames() { 55 switch name { 56 case "keyName": 57 keyName = newKeyMatch[i] 58 case "curveType": 59 curveType = newKeyMatch[i] 60 } 61 } 62 return 63 } 64 65 type Meta struct { 66 // (Required) the file path of the sub yaml to run 67 File string `mapstructure:"file" json:"file" yaml:"file" toml:"file"` 68 Playbook *Playbook `json:"-" yaml:"-" toml:"-"` 69 } 70 71 func (job *Meta) Validate() error { 72 return validation.ValidateStruct(job, 73 validation.Field(&job.File, validation.Required), 74 ) 75 } 76 77 // ------------------------------------------------------------------------ 78 // Governance Jobs 79 // ------------------------------------------------------------------------ 80 81 type PermissionString string 82 83 func (ps PermissionString) Validate() error { 84 return rule.PermissionOrPlaceholder.Validate(ps) 85 } 86 87 // UpdateAccount updates an account by overwriting the given values, where values are omitted the existing values 88 // are preserved. Currently requires Root permission on Source account 89 type UpdateAccount struct { 90 // (Optional, if account job or global account set) address of the account from which to send (the 91 // public key for the account must be available to burrow keys) 92 Source string `mapstructure:"source" json:"source" yaml:"source" toml:"source"` 93 // (Required) The target account that will be governed - either an address or public key (its type will be determined by it's length) 94 // if altering power then either a public key must be provided or the requisite public key associated with the address 95 // must be available in an connected keys Signer 96 Target string `mapstructure:"target" json:"target" yaml:"target" toml:"target"` 97 // (Optional) the Tendermint validator power to set for this account 98 Power string `mapstructure:"power" json:"power" yaml:"power" toml:"power"` 99 // (Optional) The Burrow native token balance to set for this account 100 Native string `mapstructure:"native" json:"native" yaml:"native" toml:"native"` 101 // (Optional) the permissions to set for this account 102 Permissions []PermissionString `mapstructure:"permissions" json:"permissions" yaml:"permissions" toml:"permissions"` 103 // (Optional) the account permission roles to set for this account 104 Roles []string `mapstructure:"roles" json:"roles" yaml:"roles" toml:"roles"` 105 // (Optional, advanced only) sequence to use when burrow keys signs the transaction (do not use unless you 106 // know what you're doing) 107 Sequence string `mapstructure:"sequence" json:"sequence" yaml:"sequence" toml:"sequence"` 108 } 109 110 func (job *UpdateAccount) Validate() error { 111 return validation.ValidateStruct(job, 112 validation.Field(&job.Target, validation.Required, rule.Or(rule.Placeholder, is.Hexadecimal, 113 validation.Match(NewKeyRegex))), 114 validation.Field(&job.Permissions), 115 validation.Field(&job.Power, rule.Uint64OrPlaceholder), 116 validation.Field(&job.Native, rule.Uint64OrPlaceholder), 117 validation.Field(&job.Sequence, rule.Uint64OrPlaceholder), 118 ) 119 } 120 121 // ------------------------------------------------------------------------ 122 // Util Jobs 123 // ------------------------------------------------------------------------ 124 125 type Account struct { 126 // (Required) address of the account which should be used as the default (if source) is 127 // not given for future transactions. Will make sure the burrow keys has the public key 128 // for the account. Generally account should be the first job called unless it is used 129 // via a flag or environment variables to establish what default to use. 130 Address string `mapstructure:"address" json:"address" yaml:"address" toml:"address"` 131 } 132 133 func (job *Account) Validate() error { 134 return validation.ValidateStruct(job, 135 validation.Field(&job.Address, validation.Required), 136 ) 137 } 138 139 type Set struct { 140 // (Required) value which should be saved along with the jobName (which will be the key) 141 // this is useful to set variables which can be used throughout the jobs definition file (deploy.yaml). 142 // It should be noted that arrays and bools must be defined using strings as such "[1,2,3]" 143 // if they are intended to be used further in a assert job. 144 Value string `mapstructure:"val" json:"val" yaml:"val" toml:"val"` 145 } 146 147 func (job *Set) Validate() error { 148 return validation.ValidateStruct(job, 149 validation.Field(&job.Value, validation.Required), 150 ) 151 } 152 153 // ------------------------------------------------------------------------ 154 // Transaction Jobs 155 // ------------------------------------------------------------------------ 156 157 type Send struct { 158 // (Optional, if account job or global account set) address of the account from which to send (the 159 // public key for the account must be available to burrow keys) 160 Source string `mapstructure:"source" json:"source" yaml:"source" toml:"source"` 161 // (Required) address of the account to send the tokens 162 Destination string `mapstructure:"destination" json:"destination" yaml:"destination" toml:"destination"` 163 // (Required) amount of tokens to send from the `source` to the `destination` 164 Amount string `mapstructure:"amount" json:"amount" yaml:"amount" toml:"amount"` 165 // (Optional, advanced only) sequence to use when burrow keys signs the transaction (do not use unless you 166 // know what you're doing) 167 Sequence string `mapstructure:"sequence" json:"sequence" yaml:"sequence" toml:"sequence"` 168 } 169 170 func (job *Send) Validate() error { 171 return validation.ValidateStruct(job, 172 validation.Field(&job.Destination, validation.Required), 173 validation.Field(&job.Amount, rule.Uint64OrPlaceholder), 174 validation.Field(&job.Sequence, rule.Uint64OrPlaceholder), 175 ) 176 } 177 178 type RegisterName struct { 179 // (Optional, if account job or global account set) address of the account from which to send (the 180 // public key for the account must be available to burrow keys) 181 Source string `mapstructure:"source" json:"source" yaml:"source" toml:"source"` 182 // (Required - unless providing data file) name which will be registered 183 Name string `mapstructure:"name" json:"name" yaml:"name" toml:"name"` 184 // (Optional, if data_file is used; otherwise required) data which will be stored at the `name` key 185 Data string `mapstructure:"data" json:"data" yaml:"data" toml:"data"` 186 // (Optional) csv file in the form (name,data[,amount]) which can be used to bulk register names 187 DataFile string `mapstructure:"data_file" json:"data_file" yaml:"data_file" toml:"data_file"` 188 // (Optional) amount of blocks which the name entry will be reserved for the registering user 189 Amount string `mapstructure:"amount" json:"amount" yaml:"amount" toml:"amount"` 190 // (Optional) validators' fee 191 Fee string `mapstructure:"fee" json:"fee" yaml:"fee" toml:"fee"` 192 // (Optional, advanced only) sequence to use when burrow keys signs the transaction (do not use unless you 193 // know what you're doing) 194 Sequence string `mapstructure:"sequence" json:"sequence" yaml:"sequence" toml:"sequence"` 195 } 196 197 func (job *RegisterName) Validate() error { 198 return validation.ValidateStruct(job, 199 validation.Field(&job.Amount, rule.Uint64OrPlaceholder), 200 validation.Field(&job.Fee, rule.Uint64OrPlaceholder), 201 validation.Field(&job.Sequence, rule.Uint64OrPlaceholder), 202 ) 203 } 204 205 type Permission struct { 206 // (Optional, if account job or global account set) address of the account from which to send (the 207 // public key for the account must be available to burrow keys) 208 Source string `mapstructure:"source" json:"source" yaml:"source" toml:"source"` 209 // (Required) actions must be in the set ["set_base", "unset_base", "set_global", "add_role" "rm_role"] 210 Action string `mapstructure:"action" json:"action" yaml:"action" toml:"action"` 211 // (Required, unless add_role or rm_role action selected) the name of the permission flag which is to 212 // be updated 213 Permission string `mapstructure:"permission" json:"permission" yaml:"permission" toml:"permission"` 214 // (Required) the value of the permission or role which is to be updated 215 Value string `mapstructure:"value" json:"value" yaml:"value" toml:"value"` 216 // (Required) the target account which is to be updated 217 Target string `mapstructure:"target" json:"target" yaml:"target" toml:"target"` 218 // (Required, if add_role or rm_role action selected) the role which should be given to the account 219 Role string `mapstructure:"role" json:"role" yaml:"role" toml:"role"` 220 // (Optional, advanced only) sequence to use when burrow keys signs the transaction (do not use unless you 221 // know what you're doing) 222 Sequence string `mapstructure:"sequence" json:"sequence" yaml:"sequence" toml:"sequence"` 223 } 224 225 func (job *Permission) Validate() error { 226 return validation.ValidateStruct(job, 227 validation.Field(&job.Value, validation.In("true", "false", "")), 228 validation.Field(&job.Sequence, rule.Uint64OrPlaceholder), 229 ) 230 } 231 232 // ------------------------------------------------------------------------ 233 // Contracts Jobs 234 // ------------------------------------------------------------------------ 235 236 type PackageDeploy struct { 237 // TODO 238 } 239 240 type Build struct { 241 // (Required) the filepath to the contract file. this should be relative to the current path **or** 242 // relative to the contracts path established via the --dir. 243 // If contract has a "bin" file extension then it will not be sent to the 244 // compilers but rather will just be sent to the chain. Note, if you use a "call" job after deploying 245 // a binary contract then you will be **required** to utilize an abi field in the call job. 246 Contract string `mapstructure:"contract" json:"contract" yaml:"contract" toml:"contract"` 247 // (Optional) where to save the result of the compilation 248 BinPath string `mapstructure:"binpath" json:"binpath" yaml:"binpath" toml:"binpath"` 249 // (Optional) the name of contract to instantiate (it has to be one of the contracts present) 250 // in the file defined in Contract above. 251 // When none is provided, the system will choose the contract with the same name as that file. 252 // use "all" to override and deploy all contracts in order. if "all" is selected the result 253 // of the job will default to the address of the contract which was deployed that matches 254 // the name of the file (or the last one deployed if there are no matching names; not the "last" 255 // one deployed" strategy is non-deterministic and should not be used). 256 Instance string `mapstructure:"instance" json:"instance" yaml:"instance" toml:"instance"` 257 // (Optional) Path to store an extra copy of the bin file 258 Store string `mapstructure:"store" json:"store" yaml:"store" toml:"store"` 259 } 260 261 func (job *Build) Validate() error { 262 return validation.ValidateStruct(job, 263 validation.Field(&job.Contract, validation.Required), 264 ) 265 } 266 267 type Deploy struct { 268 // (Optional, if account job or global account set) address of the account from which to send (the 269 // public key for the account must be available to burrow keys) 270 Source string `mapstructure:"source" json:"source" yaml:"source" toml:"source"` 271 // (Required) the filepath to the contract file. this should be relative to the current path **or** 272 // relative to the contracts path established via the --dir. 273 // If contract has a "bin" file extension then it will not be sent to the 274 // compilers but rather will just be sent to the chain. Note, if you use a "call" job after deploying 275 // a binary contract then you will be **required** to utilize an abi field in the call job. 276 Contract string `mapstructure:"contract" json:"contract" yaml:"contract" toml:"contract"` 277 // (Optional) the name of contract to instantiate (it has to be one of the contracts present) 278 // in the file defined in Contract above. 279 // When none is provided, the system will choose the contract with the same name as that file. 280 // use "all" to override and deploy all contracts in order. if "all" is selected the result 281 // of the job will default to the address of the contract which was deployed that matches 282 // the name of the file (or the last one deployed if there are no matching names; not the "last" 283 // one deployed" strategy is non-deterministic and should not be used). 284 Instance string `mapstructure:"instance" json:"instance" yaml:"instance" toml:"instance"` 285 // (Optional) the file path for the linkReferences for contract 286 Libraries string `mapstructure:"libraries" json:"libraries" yaml:"libraries" toml:"libraries"` 287 // (Optional) TODO: additional arguments to send along with the contract code 288 Data interface{} `mapstructure:"data" json:"data" yaml:"data" toml:"data"` 289 // (Optional) amount of tokens to send to the contract which will (after deployment) reside in the 290 // contract's account 291 Amount string `mapstructure:"amount" json:"amount" yaml:"amount" toml:"amount"` 292 // (Optional) validators' fee 293 Fee string `mapstructure:"fee" json:"fee" yaml:"fee" toml:"fee"` 294 // (Optional) amount of gas which should be sent along with the contract deployment transaction 295 Gas string `mapstructure:"gas" json:"gas" yaml:"gas" toml:"gas"` 296 // (Optional, advanced only) sequence to use when burrow keys signs the transaction (do not use unless you 297 // know what you're doing) 298 Sequence string `mapstructure:"sequence" json:"sequence" yaml:"sequence" toml:"sequence"` 299 // (Optional) todo 300 Variables []*abi.Variable 301 // (Optional) Path to store an extra copy of the bin file 302 Store string `mapstructure:"store" json:"store" yaml:"store" toml:"store"` 303 } 304 305 func (job *Deploy) Validate() error { 306 return validation.ValidateStruct(job, 307 validation.Field(&job.Contract, validation.Required), 308 validation.Field(&job.Amount, rule.Uint64OrPlaceholder), 309 validation.Field(&job.Fee, rule.Uint64OrPlaceholder), 310 validation.Field(&job.Gas, rule.Uint64OrPlaceholder), 311 validation.Field(&job.Sequence, rule.Uint64OrPlaceholder), 312 ) 313 } 314 315 type Call struct { 316 // (Optional, if account job or global account set) address of the account from which to send (the 317 // public key for the account must be available to burrow keys) 318 Source string `mapstructure:"source" json:"source" yaml:"source" toml:"source"` 319 // (Required) address of the contract which should be called 320 Destination string `mapstructure:"destination" json:"destination" yaml:"destination" toml:"destination"` 321 // (Required unless testing fallback function) function inside the contract to be called 322 Function string `mapstructure:"function" json:"function" yaml:"function" toml:"function"` 323 // (Optional) data which should be called. will use the monax-abi tooling under the hood to formalize the 324 // transaction 325 Data interface{} `mapstructure:"data" json:"data" yaml:"data" toml:"data"` 326 // (Optional) amount of tokens to send to the contract 327 Amount string `mapstructure:"amount" json:"amount" yaml:"amount" toml:"amount"` 328 // (Optional) validators' fee 329 Fee string `mapstructure:"fee" json:"fee" yaml:"fee" toml:"fee"` 330 // (Optional) amount of gas which should be sent along with the call transaction 331 Gas string `mapstructure:"gas" json:"gas" yaml:"gas" toml:"gas"` 332 // (Optional, advanced only) sequence to use when burrow keys signs the transaction (do not use unless you 333 // know what you're doing) 334 Sequence string `mapstructure:"sequence" json:"sequence" yaml:"sequence" toml:"sequence"` 335 // (Optional) location of the bin file to use (can be relative path or in bin path) 336 // deployed contracts save ABI artifacts in the bin folder as *both* the name of the contract 337 // and the address where the contract was deployed to 338 Bin string `mapstructure:"bin" json:"bin" yaml:"bin" toml:"bin"` 339 // (Optional) by default the call job will "store" the return from the contract as the 340 // result of the job. If you would like to store the transaction hash instead of the 341 // return from the call job as the result of the call job then select "tx" on the save 342 // variable. Anything other than "tx" in this field will use the default. 343 Save string `mapstructure:"save" json:"save" yaml:"save" toml:"save"` 344 // (Optional) the call job's returned variables 345 Variables []*abi.Variable 346 } 347 348 func (job *Call) Validate() error { 349 return validation.ValidateStruct(job, 350 validation.Field(&job.Destination, validation.Required), 351 validation.Field(&job.Amount, rule.Uint64OrPlaceholder), 352 validation.Field(&job.Fee, rule.Uint64OrPlaceholder), 353 validation.Field(&job.Gas, rule.Uint64OrPlaceholder), 354 validation.Field(&job.Sequence, rule.Uint64OrPlaceholder), 355 ) 356 } 357 358 // ------------------------------------------------------------------------ 359 // State Jobs 360 // ------------------------------------------------------------------------ 361 362 type DumpState struct { 363 WithValidators bool `mapstructure:"include-validators" json:"include-validators" yaml:"include-validators" toml:"include-validators"` 364 ToIPFS bool `mapstructure:"to-ipfs" json:"to-ipfs" yaml:"to-ipfs" toml:"to-ipfs"` 365 ToFile bool `mapstructure:"to-file" json:"to-file" yaml:"to-file" toml:"to-file"` 366 IPFSHost string `mapstructure:"ipfs-host" json:"ipfs-host" yaml:"ipfs-host" toml:"ipfs-host"` 367 FilePath string `mapstructure:"file" json:"file" yaml:"file" toml:"file"` 368 } 369 370 func (job *DumpState) Validate() error { 371 // TODO: write validation logic 372 return nil 373 } 374 375 type RestoreState struct { 376 FromIPFS bool `mapstructure:"from-ipfs" json:"from-ipfs" yaml:"from-ipfs" toml:"from-ipfs"` 377 FromFile bool `mapstructure:"from-file" json:"from-file" yaml:"from-file" toml:"from-file"` 378 IPFSHost string `mapstructure:"ipfs-host" json:"ipfs-host" yaml:"ipfs-host" toml:"ipfs-host"` 379 FilePath string `mapstructure:"file" json:"file" yaml:"file" toml:"file"` 380 } 381 382 func (job *RestoreState) Validate() error { 383 // TODO: write validation logic 384 return nil 385 } 386 387 // ------------------------------------------------------------------------ 388 // Testing Jobs 389 // ------------------------------------------------------------------------ 390 391 // aka. Simulated Call. 392 type QueryContract struct { 393 // (Optional, if account job or global account set) address of the account from which to send (the 394 // public key for the account must be available to burrow keys) 395 Source string `mapstructure:"source" json:"source" yaml:"source" toml:"source"` 396 // (Required) address of the contract which should be called 397 Destination string `mapstructure:"destination" json:"destination" yaml:"destination" toml:"destination"` 398 // (Required) data which should be called. will use the monax-abi tooling under the hood to formalize the 399 // transaction. QueryContract will usually be used with "accessor" functions in contracts 400 Function string `mapstructure:"function" json:"function" yaml:"function" toml:"function"` 401 // (Optional) data to be used in the function arguments. Will use the monax-abi tooling under the hood to formalize the 402 // transaction. 403 Data interface{} `mapstructure:"data" json:"data" yaml:"data" toml:"data"` 404 // (Optional) location of the bin file to use (can be relative path or in abi path) 405 // deployed contracts save ABI artifacts in the abi folder as *both* the name of the contract 406 // and the address where the contract was deployed to 407 Bin string `mapstructure:"bin" json:"bin" yaml:"bin" toml:"bin"` 408 409 Variables []*abi.Variable 410 } 411 412 func (job *QueryContract) Validate() error { 413 return validation.ValidateStruct(job, 414 validation.Field(&job.Destination, validation.Required), 415 ) 416 } 417 418 type QueryAccount struct { 419 // (Required) address of the account which should be queried 420 Account string `mapstructure:"account" json:"account" yaml:"account" toml:"account"` 421 // (Required) field which should be queried. If users are trying to query the permissions of the 422 // account one can get either the `permissions.base` which will return the base permission of the 423 // account, or one can get the `permissions.set` which will return the setBit of the account. 424 Field string `mapstructure:"field" json:"field" yaml:"field" toml:"field"` 425 } 426 427 func (job *QueryAccount) Validate() error { 428 return validation.ValidateStruct(job, 429 validation.Field(&job.Account, validation.Required), 430 validation.Field(&job.Field, validation.Required), 431 ) 432 } 433 434 type QueryName struct { 435 // (Required) name which should be queried 436 Name string `mapstructure:"name" json:"name" yaml:"name" toml:"name"` 437 // (Required) field which should be quiried (generally will be "data" to get the registered "name") 438 Field string `mapstructure:"field" json:"field" yaml:"field" toml:"field"` 439 } 440 441 func (job *QueryName) Validate() error { 442 return validation.ValidateStruct(job, 443 validation.Field(&job.Name, validation.Required), 444 validation.Field(&job.Field, validation.Required), 445 ) 446 } 447 448 type QueryVals struct { 449 // (Required) should be of the set ["bonded_validators" or "unbonding_validators"] and it will 450 // return a comma separated listing of the addresses which fall into one of those categories 451 Query string `mapstructure:"field" json:"field" yaml:"field" toml:"field"` 452 } 453 454 func (job *QueryVals) Validate() error { 455 return validation.ValidateStruct(job, 456 validation.Field(&job.Query, validation.Required), 457 ) 458 } 459 460 type Assert struct { 461 // (Required) key which should be used for the assertion. This is usually known as the "expected" 462 // value in most testing suites 463 Key string `mapstructure:"key" json:"key" yaml:"key" toml:"key"` 464 // (Required) must be of the set ["eq", "ne", "ge", "gt", "le", "lt", "==", "!=", ">=", ">", "<=", "<"] 465 // establishes the relation to be tested by the assertion. If a strings key:value pair is being used 466 // only the equals or not-equals relations may be used as the key:value will try to be converted to 467 // ints for the remainder of the relations. if strings are passed to them then `monax pkgs do` will return an 468 // error 469 Relation string `mapstructure:"relation" json:"relation" yaml:"relation" toml:"relation"` 470 // (Required) value which should be used for the assertion. This is usually known as the "given" 471 // value in most testing suites. Generally it will be a variable expansion from one of the query 472 // jobs. 473 Value string `mapstructure:"val" json:"val" yaml:"val" toml:"val"` 474 } 475 476 func (job *Assert) Validate() error { 477 return validation.ValidateStruct(job, 478 validation.Field(&job.Relation, validation.Required, rule.Relation), 479 ) 480 }