github.com/algorand/go-algorand-sdk@v1.24.0/test/steps_test.go (about) 1 package test 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/base32" 7 "encoding/base64" 8 "encoding/gob" 9 "encoding/hex" 10 "encoding/json" 11 "flag" 12 "fmt" 13 "os" 14 "path" 15 "reflect" 16 "strconv" 17 "strings" 18 "testing" 19 "time" 20 21 "golang.org/x/crypto/ed25519" 22 23 "github.com/algorand/go-algorand-sdk/abi" 24 "github.com/algorand/go-algorand-sdk/auction" 25 "github.com/algorand/go-algorand-sdk/client/kmd" 26 algodV2 "github.com/algorand/go-algorand-sdk/client/v2/algod" 27 commonV2 "github.com/algorand/go-algorand-sdk/client/v2/common" 28 modelsV2 "github.com/algorand/go-algorand-sdk/client/v2/common/models" 29 indexerV2 "github.com/algorand/go-algorand-sdk/client/v2/indexer" 30 "github.com/algorand/go-algorand-sdk/crypto" 31 "github.com/algorand/go-algorand-sdk/encoding/msgpack" 32 "github.com/algorand/go-algorand-sdk/future" 33 "github.com/algorand/go-algorand-sdk/logic" 34 "github.com/algorand/go-algorand-sdk/mnemonic" 35 "github.com/algorand/go-algorand-sdk/types" 36 "github.com/cucumber/godog" 37 "github.com/cucumber/godog/colors" 38 ) 39 40 var txn types.Transaction 41 var stx []byte 42 var stxKmd []byte 43 var stxObj types.SignedTxn 44 var txid string 45 var account crypto.Account 46 var note []byte 47 var fee uint64 48 var fv uint64 49 var lv uint64 50 var to string 51 var gh []byte 52 var close string 53 var amt uint64 54 var gen string 55 var a types.Address 56 var msig crypto.MultisigAccount 57 var msigsig types.MultisigSig 58 var kcl kmd.Client 59 var aclv2 *algodV2.Client 60 var iclv2 *indexerV2.Client 61 var walletName string 62 var walletPswd string 63 var walletID string 64 var handle string 65 var versions []string 66 var msigExp kmd.ExportMultisigResponse 67 var pk string 68 var rekey string 69 var accounts []string 70 var e bool 71 var lastRound uint64 72 var sugParams types.SuggestedParams 73 var bid types.Bid 74 var sbid types.NoteField 75 var oldBid types.NoteField 76 var oldPk string 77 var newMn string 78 var mdk types.MasterDerivationKey 79 var microalgos types.MicroAlgos 80 var bytetxs [][]byte 81 var votekey string 82 var selkey string 83 var stateProofPK string 84 var votefst uint64 85 var votelst uint64 86 var votekd uint64 87 var nonpart bool 88 var data []byte 89 var sig types.Signature 90 var abiMethod abi.Method 91 var abiMethods []abi.Method 92 var abiJsonString string 93 var abiInterface abi.Interface 94 var abiContract abi.Contract 95 var txComposer future.AtomicTransactionComposer 96 var accountTxSigner future.BasicAccountTransactionSigner 97 var methodArgs []interface{} 98 var sigTxs [][]byte 99 var accountTxAndSigner future.TransactionWithSigner 100 var txTrace future.DryrunTxnResult 101 var trace string 102 var sourceMap logic.SourceMap 103 var srcMapping map[string]interface{} 104 var seeminglyProgram []byte 105 var sanityCheckError error 106 107 var assetTestFixture struct { 108 Creator string 109 AssetIndex uint64 110 AssetName string 111 AssetUnitName string 112 AssetURL string 113 AssetMetadataHash string 114 ExpectedParams modelsV2.AssetParams 115 QueriedParams modelsV2.AssetParams 116 LastTransactionIssued types.Transaction 117 } 118 119 var tealCompleResult struct { 120 status int 121 response modelsV2.CompileResponse 122 } 123 124 var tealDryrunResult struct { 125 status int 126 response modelsV2.DryrunResponse 127 } 128 129 var opt = godog.Options{ 130 Output: colors.Colored(os.Stdout), 131 Format: "progress", // can define default values 132 } 133 134 // Dev mode helper functions 135 const devModeInitialAmount = 10_000_000 136 137 /** 138 * waitForAlgodInDevMode is a Dev mode helper method 139 * to wait for blocks to be finalized. 140 * Since Dev mode produces blocks on a per transaction basis, it's possible 141 * algod generates a block _before_ the corresponding SDK call to wait for a block. 142 * Without _any_ wait, it's possible the SDK looks for the transaction before algod completes processing. 143 * So, the method performs a local sleep to simulate waiting for a block. 144 */ 145 func waitForAlgodInDevMode() { 146 time.Sleep(500 * time.Millisecond) 147 } 148 149 func initializeAccount(accountAddress string) error { 150 params, err := aclv2.SuggestedParams().Do(context.Background()) 151 if err != nil { 152 return err 153 } 154 155 txn, err = future.MakePaymentTxn(accounts[0], accountAddress, devModeInitialAmount, []byte{}, "", params) 156 if err != nil { 157 return err 158 } 159 160 res, err := kcl.SignTransaction(handle, walletPswd, txn) 161 if err != nil { 162 return err 163 } 164 165 _, err = aclv2.SendRawTransaction(res.SignedTransaction).Do(context.Background()) 166 if err != nil { 167 return err 168 } 169 waitForAlgodInDevMode() 170 return err 171 } 172 173 func init() { 174 godog.BindFlags("godog.", flag.CommandLine, &opt) 175 } 176 177 func TestMain(m *testing.M) { 178 flag.Parse() 179 opt.Paths = flag.Args() 180 181 status := godog.RunWithOptions("godogs", func(s *godog.Suite) { 182 FeatureContext(s) 183 AlgodClientV2Context(s) 184 IndexerUnitTestContext(s) 185 TransactionsUnitContext(s) 186 ApplicationsContext(s) 187 ApplicationsUnitContext(s) 188 ResponsesContext(s) 189 }, opt) 190 191 if st := m.Run(); st > status { 192 status = st 193 } 194 os.Exit(status) 195 } 196 197 func FeatureContext(s *godog.Suite) { 198 s.Step("I create a wallet", createWallet) 199 s.Step("the wallet should exist", walletExist) 200 s.Step("I get the wallet handle", getHandle) 201 s.Step("I can get the master derivation key", getMdk) 202 s.Step("I rename the wallet", renameWallet) 203 s.Step("I can still get the wallet information with the same handle", getWalletInfo) 204 s.Step("I renew the wallet handle", renewHandle) 205 s.Step("I release the wallet handle", releaseHandle) 206 s.Step("the wallet handle should not work", tryHandle) 207 s.Step(`payment transaction parameters (\d+) (\d+) (\d+) "([^"]*)" "([^"]*)" "([^"]*)" (\d+) "([^"]*)" "([^"]*)"`, txnParams) 208 s.Step(`mnemonic for private key "([^"]*)"`, mnForSk) 209 s.Step(`multisig addresses "([^"]*)"`, msigAddresses) 210 s.Step("I create the multisig payment transaction$", createMsigTxn) 211 s.Step("I create the multisig payment transaction with zero fee", createMsigTxnZeroFee) 212 s.Step("I sign the multisig transaction with the private key", signMsigTxn) 213 s.Step("I sign the transaction with the private key", signTxn) 214 s.Step(`^I add a rekeyTo field with address "([^"]*)"$`, iAddARekeyToFieldWithAddress) 215 s.Step(`^I add a rekeyTo field with the private key algorand address$`, iAddARekeyToFieldWithThePrivateKeyAlgorandAddress) 216 s.Step(`^I set the from address to "([^"]*)"$`, iSetTheFromAddressTo) 217 s.Step(`the signed transaction should equal the golden "([^"]*)"`, equalGolden) 218 s.Step(`the multisig transaction should equal the golden "([^"]*)"`, equalMsigGolden) 219 s.Step(`the multisig address should equal the golden "([^"]*)"`, equalMsigAddrGolden) 220 s.Step("I get versions with algod", aclV) 221 s.Step("v1 should be in the versions", v1InVersions) 222 s.Step("v2 should be in the versions", v2InVersions) 223 s.Step("I get versions with kmd", kclV) 224 s.Step("I import the multisig", importMsig) 225 s.Step("the multisig should be in the wallet", msigInWallet) 226 s.Step("I export the multisig", expMsig) 227 s.Step("the multisig should equal the exported multisig", msigEq) 228 s.Step("I delete the multisig", deleteMsig) 229 s.Step("the multisig should not be in the wallet", msigNotInWallet) 230 s.Step("^I generate a key using kmd for rekeying and fund it$", genRekeyKmd) 231 s.Step("^I generate a key using kmd$", genKeyKmd) 232 s.Step("the key should be in the wallet", keyInWallet) 233 s.Step("I delete the key", deleteKey) 234 s.Step("the key should not be in the wallet", keyNotInWallet) 235 s.Step("I generate a key", genKey) 236 s.Step("I import the key", importKey) 237 s.Step("the private key should be equal to the exported private key", skEqExport) 238 s.Step("a kmd client", kmdClient) 239 s.Step("wallet information", walletInfo) 240 s.Step(`default transaction with parameters (\d+) "([^"]*)"`, defaultTxn) 241 s.Step(`default multisig transaction with parameters (\d+) "([^"]*)"`, defaultMsigTxn) 242 s.Step("I get the private key", getSk) 243 s.Step("I send the transaction", sendTxn) 244 s.Step("I send the kmd-signed transaction", sendTxnKmd) 245 s.Step("I send the bogus kmd-signed transaction", sendTxnKmdFailureExpected) 246 s.Step("I send the multisig transaction", sendMsigTxn) 247 s.Step("the transaction should not go through", txnFail) 248 s.Step("I sign the transaction with kmd", signKmd) 249 s.Step("the signed transaction should equal the kmd signed transaction", signBothEqual) 250 s.Step("I sign the multisig transaction with kmd", signMsigKmd) 251 s.Step("the multisig transaction should equal the kmd signed multisig transaction", signMsigBothEqual) 252 s.Step(`^the node should be healthy`, nodeHealth) 253 s.Step(`^I get the ledger supply`, ledger) 254 s.Step(`^I create a bid`, createBid) 255 s.Step(`^I encode and decode the bid`, encDecBid) 256 s.Step(`^the bid should still be the same`, checkBid) 257 s.Step(`^I decode the address`, decAddr) 258 s.Step(`^I encode the address`, encAddr) 259 s.Step(`^the address should still be the same`, checkAddr) 260 s.Step(`^I convert the private key back to a mnemonic`, skToMn) 261 s.Step(`^the mnemonic should still be the same as "([^"]*)"`, checkMn) 262 s.Step(`^mnemonic for master derivation key "([^"]*)"`, mnToMdk) 263 s.Step(`^I convert the master derivation key back to a mnemonic`, mdkToMn) 264 s.Step(`^I create the flat fee payment transaction`, createTxnFlat) 265 s.Step(`^encoded multisig transaction "([^"]*)"`, encMsigTxn) 266 s.Step(`^I append a signature to the multisig transaction`, appendMsig) 267 s.Step(`^encoded multisig transactions "([^"]*)"`, encMtxs) 268 s.Step(`^I merge the multisig transactions`, mergeMsig) 269 s.Step(`^I convert (\d+) microalgos to algos and back`, microToAlgos) 270 s.Step(`^it should still be the same amount of microalgos (\d+)`, checkAlgos) 271 s.Step("I sign the bid", signBid) 272 s.Step(`default V2 key registration transaction "([^"]*)"`, createKeyregWithStateProof) 273 s.Step(`^I can get account information`, newAccInfo) 274 s.Step("asset test fixture", createAssetTestFixture) 275 s.Step(`^default asset creation transaction with total issuance (\d+)$`, defaultAssetCreateTxn) 276 s.Step(`^I update the asset index$`, getAssetIndex) 277 s.Step(`^I get the asset info$`, getAssetInfo) 278 s.Step(`^I should be unable to get the asset info`, failToGetAssetInfo) 279 s.Step(`^the asset info should match the expected asset info$`, checkExpectedVsActualAssetParams) 280 s.Step(`^I create a no-managers asset reconfigure transaction$`, createNoManagerAssetReconfigure) 281 s.Step(`^I create an asset destroy transaction$`, createAssetDestroy) 282 s.Step(`^I create a transaction for a second account, signalling asset acceptance$`, createAssetAcceptanceForSecondAccount) 283 s.Step(`^I create a transaction transferring (\d+) assets from creator to a second account$`, createAssetTransferTransactionToSecondAccount) 284 s.Step(`^the creator should have (\d+) assets remaining$`, theCreatorShouldHaveAssetsRemaining) 285 s.Step(`^I create a freeze transaction targeting the second account$`, createFreezeTransactionTargetingSecondAccount) 286 s.Step(`^I create a transaction transferring (\d+) assets from a second account to creator$`, createAssetTransferTransactionFromSecondAccountToCreator) 287 s.Step(`^I create an un-freeze transaction targeting the second account$`, createUnfreezeTransactionTargetingSecondAccount) 288 s.Step(`^default-frozen asset creation transaction with total issuance (\d+)$`, defaultAssetCreateTxnWithDefaultFrozen) 289 s.Step(`^I create a transaction revoking (\d+) assets from a second account to creator$`, createRevocationTransaction) 290 s.Step(`^I create a transaction transferring <amount> assets from creator to a second account$`, iCreateATransactionTransferringAmountAssetsFromCreatorToASecondAccount) // provide handler for when godog misreads 291 s.Step(`^base64 encoded data to sign "([^"]*)"$`, baseEncodedDataToSign) 292 s.Step(`^program hash "([^"]*)"$`, programHash) 293 s.Step(`^I perform tealsign$`, iPerformTealsign) 294 s.Step(`^the signature should be equal to "([^"]*)"$`, theSignatureShouldBeEqualTo) 295 s.Step(`^base64 encoded program "([^"]*)"$`, baseEncodedProgram) 296 s.Step(`^base64 encoded private key "([^"]*)"$`, baseEncodedPrivateKey) 297 s.Step("an algod v2 client$", algodClientV2) 298 s.Step("an indexer v2 client$", indexerClientV2) 299 s.Step(`^I compile a teal program "([^"]*)"$`, tealCompile) 300 s.Step(`^it is compiled with (\d+) and "([^"]*)" and "([^"]*)"$`, tealCheckCompile) 301 s.Step(`^base64 decoding the response is the same as the binary "([^"]*)"$`, tealCheckCompileAgainstFile) 302 s.Step(`^I dryrun a "([^"]*)" program "([^"]*)"$`, tealDryrun) 303 s.Step(`^I get execution result "([^"]*)"$`, tealCheckDryrun) 304 s.Step(`^I create the Method object from method signature "([^"]*)"$`, createMethodObjectFromSignature) 305 s.Step(`^I serialize the Method object into json$`, serializeMethodObjectIntoJson) 306 s.Step(`^the produced json should equal "([^"]*)" loaded from "([^"]*)"$`, checkSerializedMethodObject) 307 s.Step(`^I create the Method object with name "([^"]*)" first argument type "([^"]*)" second argument type "([^"]*)" and return type "([^"]*)"$`, createMethodObjectFromProperties) 308 s.Step(`^I create the Method object with name "([^"]*)" first argument name "([^"]*)" first argument type "([^"]*)" second argument name "([^"]*)" second argument type "([^"]*)" and return type "([^"]*)"$`, createMethodObjectWithArgNames) 309 s.Step(`^I create the Method object with name "([^"]*)" method description "([^"]*)" first argument type "([^"]*)" first argument description "([^"]*)" second argument type "([^"]*)" second argument description "([^"]*)" and return type "([^"]*)"$`, createMethodObjectWithDescription) 310 s.Step(`^the txn count should be (\d+)$`, checkTxnCount) 311 s.Step(`^the method selector should be "([^"]*)"$`, checkMethodSelector) 312 s.Step(`^I create an Interface object from the Method object with name "([^"]*)" and description "([^"]*)"$`, createInterfaceObject) 313 s.Step(`^I serialize the Interface object into json$`, serializeInterfaceObjectIntoJson) 314 s.Step(`^I create a Contract object from the Method object with name "([^"]*)" and description "([^"]*)"$`, createContractObject) 315 s.Step(`^I set the Contract\'s appID to (\d+) for the network "([^"]*)"$`, iSetTheContractsAppIDToForTheNetwork) 316 s.Step(`^I serialize the Contract object into json$`, serializeContractObjectIntoJson) 317 s.Step(`^the deserialized json should equal the original Method object`, deserializeMethodJson) 318 s.Step(`^the deserialized json should equal the original Interface object`, deserializeInterfaceJson) 319 s.Step(`^the deserialized json should equal the original Contract object`, deserializeContractJson) 320 s.Step(`^a new AtomicTransactionComposer$`, aNewAtomicTransactionComposer) 321 s.Step(`^suggested transaction parameters fee (\d+), flat-fee "([^"]*)", first-valid (\d+), last-valid (\d+), genesis-hash "([^"]*)", genesis-id "([^"]*)"$`, suggestedTransactionParameters) 322 s.Step(`^an application id (\d+)$`, anApplicationId) 323 s.Step(`^I make a transaction signer for the ([^"]*) account\.$`, iMakeATransactionSignerForTheAccount) 324 s.Step(`^I create a new method arguments array\.$`, iCreateANewMethodArgumentsArray) 325 s.Step(`^I append the encoded arguments "([^"]*)" to the method arguments array\.$`, iAppendTheEncodedArgumentsToTheMethodArgumentsArray) 326 s.Step(`^I add a method call with the ([^"]*) account, the current application, suggested params, on complete "([^"]*)", current transaction signer, current method arguments\.$`, addMethodCall) 327 s.Step(`^I add a method call with the ([^"]*) account, the current application, suggested params, on complete "([^"]*)", current transaction signer, current method arguments, approval-program "([^"]*)", clear-program "([^"]*)"\.$`, addMethodCallForUpdate) 328 s.Step(`^I add a method call with the ([^"]*) account, the current application, suggested params, on complete "([^"]*)", current transaction signer, current method arguments, approval-program "([^"]*)", clear-program "([^"]*)", global-bytes (\d+), global-ints (\d+), local-bytes (\d+), local-ints (\d+), extra-pages (\d+)\.$`, addMethodCallForCreate) 329 s.Step(`^I add a nonced method call with the ([^"]*) account, the current application, suggested params, on complete "([^"]*)", current transaction signer, current method arguments\.$`, addMethodCallWithNonce) 330 s.Step(`^I add the nonce "([^"]*)"$`, iAddTheNonce) 331 s.Step(`^I build the transaction group with the composer\. If there is an error it is "([^"]*)"\.$`, buildTheTransactionGroupWithTheComposer) 332 s.Step(`^The composer should have a status of "([^"]*)"\.$`, theComposerShouldHaveAStatusOf) 333 s.Step(`^I gather signatures with the composer\.$`, iGatherSignaturesWithTheComposer) 334 s.Step(`^the base64 encoded signed transactions should equal "([^"]*)"$`, theBaseEncodedSignedTransactionsShouldEqual) 335 s.Step(`^I build a payment transaction with sender "([^"]*)", receiver "([^"]*)", amount (\d+), close remainder to "([^"]*)"$`, iBuildAPaymentTransactionWithSenderReceiverAmountCloseRemainderTo) 336 s.Step(`^I create a transaction with signer with the current transaction\.$`, iCreateATransactionWithSignerWithTheCurrentTransaction) 337 s.Step(`^I append the current transaction with signer to the method arguments array\.$`, iAppendTheCurrentTransactionWithSignerToTheMethodArgumentsArray) 338 s.Step(`^a dryrun response file "([^"]*)" and a transaction at index "([^"]*)"$`, aDryrunResponseFileAndATransactionAtIndex) 339 s.Step(`^calling app trace produces "([^"]*)"$`, callingAppTraceProduces) 340 s.Step(`^I append to my Method objects list in the case of a non-empty signature "([^"]*)"$`, iAppendToMyMethodObjectsListInTheCaseOfANonemptySignature) 341 s.Step(`^I create an Interface object from my Method objects list$`, iCreateAnInterfaceObjectFromMyMethodObjectsList) 342 s.Step(`^I create a Contract object from my Method objects list$`, iCreateAContractObjectFromMyMethodObjectsList) 343 s.Step(`^I get the method from the Interface by name "([^"]*)"$`, iGetTheMethodFromTheInterfaceByName) 344 s.Step(`^I get the method from the Contract by name "([^"]*)"$`, iGetTheMethodFromTheContractByName) 345 s.Step(`^the produced method signature should equal "([^"]*)"\. If there is an error it begins with "([^"]*)"$`, theProducedMethodSignatureShouldEqualIfThereIsAnErrorItBeginsWith) 346 s.Step(`^a source map json file "([^"]*)"$`, aSourceMapJsonFile) 347 s.Step(`^the string composed of pc:line number equals "([^"]*)"$`, theStringComposedOfPclineNumberEquals) 348 s.Step(`^I compile a teal program "([^"]*)" with mapping enabled$`, iCompileATealProgramWithMappingEnabled) 349 s.Step(`^the resulting source map is the same as the json "([^"]*)"$`, theResultingSourceMapIsTheSameAsTheJson) 350 s.Step(`^getting the line associated with a pc "([^"]*)" equals "([^"]*)"$`, gettingTheLineAssociatedWithAPcEquals) 351 s.Step(`^getting the last pc associated with a line "([^"]*)" equals "([^"]*)"$`, gettingTheLastPcAssociatedWithALineEquals) 352 s.Step(`^a base64 encoded program bytes for heuristic sanity check "([^"]*)"$`, takeB64encodedBytes) 353 s.Step(`^I start heuristic sanity check over the bytes$`, heuristicCheckOverBytes) 354 s.Step(`^if the heuristic sanity check throws an error, the error contains "([^"]*)"$`, checkErrorIfMatching) 355 356 s.BeforeScenario(func(interface{}) { 357 stxObj = types.SignedTxn{} 358 abiMethods = nil 359 kcl.RenewWalletHandle(handle) 360 }) 361 } 362 363 func createWallet() error { 364 walletName = "Walletgo" 365 walletPswd = "" 366 resp, err := kcl.CreateWallet(walletName, walletPswd, "sqlite", types.MasterDerivationKey{}) 367 if err != nil { 368 return err 369 } 370 walletID = resp.Wallet.ID 371 return nil 372 } 373 374 func walletExist() error { 375 wallets, err := kcl.ListWallets() 376 if err != nil { 377 return err 378 } 379 for _, w := range wallets.Wallets { 380 if w.Name == walletName { 381 return nil 382 } 383 } 384 return fmt.Errorf("Wallet not found") 385 } 386 387 func getHandle() error { 388 h, err := kcl.InitWalletHandle(walletID, walletPswd) 389 if err != nil { 390 return err 391 } 392 handle = h.WalletHandleToken 393 return nil 394 } 395 396 func getMdk() error { 397 _, err := kcl.ExportMasterDerivationKey(handle, walletPswd) 398 return err 399 } 400 401 func renameWallet() error { 402 walletName = "Walletgo_new" 403 _, err := kcl.RenameWallet(walletID, walletPswd, walletName) 404 return err 405 } 406 407 func getWalletInfo() error { 408 resp, err := kcl.GetWallet(handle) 409 if resp.WalletHandle.Wallet.Name != walletName { 410 return fmt.Errorf("Wallet name not equal") 411 } 412 return err 413 } 414 415 func renewHandle() error { 416 _, err := kcl.RenewWalletHandle(handle) 417 return err 418 } 419 420 func releaseHandle() error { 421 _, err := kcl.ReleaseWalletHandle(handle) 422 return err 423 } 424 425 func tryHandle() error { 426 _, err := kcl.RenewWalletHandle(handle) 427 if err == nil { 428 return fmt.Errorf("should be an error; handle was released") 429 } 430 return nil 431 } 432 433 func iAddARekeyToFieldWithThePrivateKeyAlgorandAddress() error { 434 pk, err := crypto.GenerateAddressFromSK(account.PrivateKey) 435 if err != nil { 436 return err 437 } 438 439 err = txn.Rekey(pk.String()) 440 441 if err != nil { 442 return err 443 } 444 return nil 445 } 446 447 func txnParams(ifee, ifv, ilv int, igh, ito, iclose string, iamt int, igen, inote string) error { 448 var err error 449 if inote != "none" { 450 note, err = base64.StdEncoding.DecodeString(inote) 451 if err != nil { 452 return err 453 } 454 } else { 455 note, err = base64.StdEncoding.DecodeString("") 456 if err != nil { 457 return err 458 } 459 } 460 gh, err = base64.StdEncoding.DecodeString(igh) 461 if err != nil { 462 return err 463 } 464 to = ito 465 fee = uint64(ifee) 466 fv = uint64(ifv) 467 lv = uint64(ilv) 468 if iclose != "none" { 469 close = iclose 470 } else { 471 close = "" 472 } 473 amt = uint64(iamt) 474 if igen != "none" { 475 gen = igen 476 } else { 477 gen = "" 478 } 479 if err != nil { 480 return err 481 } 482 return nil 483 } 484 485 func mnForSk(mn string) error { 486 sk, err := mnemonic.ToPrivateKey(mn) 487 if err != nil { 488 return err 489 } 490 account.PrivateKey = sk 491 var buf bytes.Buffer 492 enc := gob.NewEncoder(&buf) 493 err = enc.Encode(sk.Public()) 494 if err != nil { 495 return err 496 } 497 addr := buf.Bytes()[4:] 498 499 n := copy(a[:], addr) 500 if n != 32 { 501 return fmt.Errorf("wrong address bytes length") 502 } 503 return err 504 } 505 func msigAddresses(addresses string) error { 506 var err error 507 addrlist := strings.Fields(addresses) 508 509 var addrStructs []types.Address 510 for _, a := range addrlist { 511 addr, err := types.DecodeAddress(a) 512 if err != nil { 513 return err 514 } 515 516 addrStructs = append(addrStructs, addr) 517 } 518 msig, err = crypto.MultisigAccountWithParams(1, 2, addrStructs) 519 520 return err 521 } 522 523 func iSetTheFromAddressTo(address string) error { 524 addr, err := types.DecodeAddress(address) 525 if err != nil { 526 return err 527 } 528 txn.Sender = addr 529 return nil 530 } 531 532 func createMsigTxn() error { 533 var err error 534 paramsToUse := types.SuggestedParams{ 535 Fee: types.MicroAlgos(fee), 536 GenesisID: gen, 537 GenesisHash: gh, 538 FirstRoundValid: types.Round(fv), 539 LastRoundValid: types.Round(lv), 540 FlatFee: false, 541 } 542 msigaddr, _ := msig.Address() 543 txn, err = future.MakePaymentTxn(msigaddr.String(), to, amt, note, close, paramsToUse) 544 if err != nil { 545 return err 546 } 547 return err 548 549 } 550 551 func createMsigTxnZeroFee() error { 552 var err error 553 paramsToUse := types.SuggestedParams{ 554 Fee: types.MicroAlgos(fee), 555 GenesisID: gen, 556 GenesisHash: gh, 557 FirstRoundValid: types.Round(fv), 558 LastRoundValid: types.Round(lv), 559 FlatFee: true, 560 } 561 msigaddr, _ := msig.Address() 562 txn, err = future.MakePaymentTxn(msigaddr.String(), to, amt, note, close, paramsToUse) 563 if err != nil { 564 return err 565 } 566 return err 567 568 } 569 570 func signMsigTxn() error { 571 var err error 572 txid, stx, err = crypto.SignMultisigTransaction(account.PrivateKey, msig, txn) 573 574 return err 575 } 576 577 func signTxn() error { 578 var err error 579 txid, stx, err = crypto.SignTransaction(account.PrivateKey, txn) 580 if err != nil { 581 return err 582 } 583 return nil 584 } 585 586 func iAddARekeyToFieldWithAddress(address string) error { 587 err := txn.Rekey(address) 588 if err != nil { 589 return err 590 } 591 return nil 592 } 593 594 func equalGolden(golden string) error { 595 goldenDecoded, err := base64.StdEncoding.DecodeString(golden) 596 if err != nil { 597 return err 598 } 599 600 if !bytes.Equal(goldenDecoded, stx) { 601 return fmt.Errorf(base64.StdEncoding.EncodeToString(stx)) 602 } 603 return nil 604 } 605 606 func equalMsigAddrGolden(golden string) error { 607 msigAddr, err := msig.Address() 608 if err != nil { 609 return err 610 } 611 if golden != msigAddr.String() { 612 return fmt.Errorf("NOT EQUAL") 613 } 614 return nil 615 } 616 617 func equalMsigGolden(golden string) error { 618 goldenDecoded, err := base64.StdEncoding.DecodeString(golden) 619 if err != nil { 620 return err 621 } 622 if !bytes.Equal(goldenDecoded, stx) { 623 return fmt.Errorf("NOT EQUAL") 624 } 625 return nil 626 } 627 628 func aclV() error { 629 v, err := aclv2.Versions().Do(context.Background()) 630 if err != nil { 631 return err 632 } 633 versions = v.Versions 634 return nil 635 } 636 637 func v1InVersions() error { 638 for _, b := range versions { 639 if b == "v1" { 640 return nil 641 } 642 } 643 return fmt.Errorf("v1 not found") 644 } 645 646 func v2InVersions() error { 647 for _, b := range versions { 648 if b == "v2" { 649 return nil 650 } 651 } 652 return fmt.Errorf("v2 not found") 653 } 654 655 func kclV() error { 656 v, err := kcl.Version() 657 versions = v.Versions 658 return err 659 } 660 661 func importMsig() error { 662 _, err := kcl.ImportMultisig(handle, msig.Version, msig.Threshold, msig.Pks) 663 return err 664 } 665 666 func msigInWallet() error { 667 msigs, err := kcl.ListMultisig(handle) 668 if err != nil { 669 return err 670 } 671 addrs := msigs.Addresses 672 for _, a := range addrs { 673 addr, err := msig.Address() 674 if err != nil { 675 return err 676 } 677 if a == addr.String() { 678 return nil 679 } 680 } 681 return fmt.Errorf("msig not found") 682 683 } 684 685 func expMsig() error { 686 addr, err := msig.Address() 687 if err != nil { 688 return err 689 } 690 msigExp, err = kcl.ExportMultisig(handle, walletPswd, addr.String()) 691 692 return err 693 } 694 695 func msigEq() error { 696 eq := true 697 698 if (msig.Pks == nil) != (msigExp.PKs == nil) { 699 eq = false 700 } 701 702 if len(msig.Pks) != len(msigExp.PKs) { 703 eq = false 704 } 705 706 for i := range msig.Pks { 707 708 if !bytes.Equal(msig.Pks[i], msigExp.PKs[i]) { 709 eq = false 710 } 711 } 712 713 if !eq { 714 return fmt.Errorf("exported msig not equal to original msig") 715 } 716 return nil 717 } 718 719 func deleteMsig() error { 720 addr, err := msig.Address() 721 kcl.DeleteMultisig(handle, walletPswd, addr.String()) 722 return err 723 } 724 725 func msigNotInWallet() error { 726 msigs, err := kcl.ListMultisig(handle) 727 if err != nil { 728 return err 729 } 730 addrs := msigs.Addresses 731 for _, a := range addrs { 732 addr, err := msig.Address() 733 if err != nil { 734 return err 735 } 736 if a == addr.String() { 737 return fmt.Errorf("msig found unexpectedly; should have been deleted") 738 } 739 } 740 return nil 741 742 } 743 744 func genKeyKmd() error { 745 p, err := kcl.GenerateKey(handle) 746 if err != nil { 747 return err 748 } 749 pk = p.Address 750 return nil 751 } 752 753 func genRekeyKmd() error { 754 p, err := kcl.GenerateKey(handle) 755 if err != nil { 756 return err 757 } 758 rekey = p.Address 759 initializeAccount(rekey) 760 return nil 761 } 762 763 func keyInWallet() error { 764 resp, err := kcl.ListKeys(handle) 765 if err != nil { 766 return err 767 } 768 for _, a := range resp.Addresses { 769 if pk == a { 770 return nil 771 } 772 } 773 return fmt.Errorf("key not found") 774 } 775 776 func deleteKey() error { 777 _, err := kcl.DeleteKey(handle, walletPswd, pk) 778 return err 779 } 780 781 func keyNotInWallet() error { 782 resp, err := kcl.ListKeys(handle) 783 if err != nil { 784 return err 785 } 786 for _, a := range resp.Addresses { 787 if pk == a { 788 return fmt.Errorf("key found unexpectedly; should have been deleted") 789 } 790 } 791 return nil 792 } 793 794 func genKey() error { 795 account = crypto.GenerateAccount() 796 a = account.Address 797 pk = a.String() 798 return nil 799 } 800 801 func importKey() error { 802 _, err := kcl.ImportKey(handle, account.PrivateKey) 803 return err 804 } 805 806 func skEqExport() error { 807 exp, err := kcl.ExportKey(handle, walletPswd, a.String()) 808 if err != nil { 809 return err 810 } 811 kcl.DeleteKey(handle, walletPswd, a.String()) 812 if bytes.Equal(exp.PrivateKey.Seed(), account.PrivateKey.Seed()) { 813 return nil 814 } 815 return fmt.Errorf("private keys not equal") 816 } 817 818 func kmdClient() error { 819 kmdToken := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 820 kmdAddress := "http://localhost:" + "60001" 821 var err error 822 kcl, err = kmd.MakeClient(kmdAddress, kmdToken) 823 return err 824 } 825 826 func algodClientV2() error { 827 algodToken := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 828 algodAddress := "http://localhost:" + "60000" 829 var err error 830 aclv2, err = algodV2.MakeClient(algodAddress, algodToken) 831 algodV2client = aclv2 832 if err != nil { 833 return err 834 } 835 _, err = aclv2.StatusAfterBlock(1).Do(context.Background()) 836 return err 837 } 838 839 func indexerClientV2() error { 840 indexerAddress := "http://localhost:" + "59999" 841 var err error 842 iclv2, err = indexerV2.MakeClient(indexerAddress, "") 843 indexerV2client = iclv2 844 return err 845 } 846 847 func walletInfo() error { 848 walletName = "unencrypted-default-wallet" 849 walletPswd = "" 850 wallets, err := kcl.ListWallets() 851 if err != nil { 852 return err 853 } 854 for _, w := range wallets.Wallets { 855 if w.Name == walletName { 856 walletID = w.ID 857 } 858 } 859 h, err := kcl.InitWalletHandle(walletID, walletPswd) 860 if err != nil { 861 return err 862 } 863 handle = h.WalletHandleToken 864 accs, err := kcl.ListKeys(handle) 865 accounts = accs.Addresses 866 return err 867 } 868 869 // Helper function for making default transactions. 870 func defaultTxnWithAddress(iamt int, inote string, senderAddress string) error { 871 var err error 872 if inote != "none" { 873 note, err = base64.StdEncoding.DecodeString(inote) 874 if err != nil { 875 return err 876 } 877 } else { 878 note, err = base64.StdEncoding.DecodeString("") 879 if err != nil { 880 return err 881 } 882 } 883 884 amt = uint64(iamt) 885 pk = senderAddress 886 params, err := aclv2.SuggestedParams().Do(context.Background()) 887 if err != nil { 888 return err 889 } 890 lastRound = uint64(params.FirstRoundValid) 891 txn, err = future.MakePaymentTxn(senderAddress, accounts[1], amt, note, "", params) 892 return err 893 } 894 895 func defaultTxn(iamt int, inote string) error { 896 return defaultTxnWithAddress(iamt, inote, accounts[0]) 897 } 898 899 func defaultMsigTxn(iamt int, inote string) error { 900 var err error 901 if inote != "none" { 902 note, err = base64.StdEncoding.DecodeString(inote) 903 if err != nil { 904 return err 905 } 906 } else { 907 note, err = base64.StdEncoding.DecodeString("") 908 if err != nil { 909 return err 910 } 911 } 912 913 amt = uint64(iamt) 914 pk = accounts[0] 915 916 var addrStructs []types.Address 917 for _, a := range accounts { 918 addr, err := types.DecodeAddress(a) 919 if err != nil { 920 return err 921 } 922 923 addrStructs = append(addrStructs, addr) 924 } 925 926 msig, err = crypto.MultisigAccountWithParams(1, 1, addrStructs) 927 if err != nil { 928 return err 929 } 930 params, err := aclv2.SuggestedParams().Do(context.Background()) 931 if err != nil { 932 return err 933 } 934 lastRound = uint64(params.FirstRoundValid) 935 addr, err := msig.Address() 936 if err != nil { 937 return err 938 } 939 txn, err = future.MakePaymentTxn(addr.String(), accounts[1], amt, note, "", params) 940 if err != nil { 941 return err 942 } 943 return nil 944 } 945 946 func getSk() error { 947 sk, err := kcl.ExportKey(handle, walletPswd, pk) 948 if err != nil { 949 return err 950 } 951 account.PrivateKey = sk.PrivateKey 952 return nil 953 } 954 955 func sendTxn() error { 956 tx, err := aclv2.SendRawTransaction(stx).Do(context.Background()) 957 if err != nil { 958 return err 959 } 960 txid = tx 961 return nil 962 } 963 964 func sendTxnKmd() error { 965 var err error 966 txid, err = aclv2.SendRawTransaction(stxKmd).Do(context.Background()) 967 return err 968 } 969 970 func sendTxnKmdFailureExpected() error { 971 tx, err := aclv2.SendRawTransaction(stxKmd).Do(context.Background()) 972 if err == nil { 973 e = false 974 return fmt.Errorf("expected an error when sending kmd-signed transaction but no error occurred") 975 } 976 e = true 977 txid = tx 978 return nil 979 } 980 981 func sendMsigTxn() error { 982 _, err := aclv2.SendRawTransaction(stx).Do(context.Background()) 983 if err != nil { 984 e = true 985 } 986 987 return nil 988 } 989 990 func txnFail() error { 991 if e { 992 return nil 993 } 994 return fmt.Errorf("sending the transaction should have failed") 995 } 996 997 func signKmd() error { 998 s, err := kcl.SignTransaction(handle, walletPswd, txn) 999 if err != nil { 1000 return err 1001 } 1002 stxKmd = s.SignedTransaction 1003 return nil 1004 } 1005 1006 func signBothEqual() error { 1007 if bytes.Equal(stx, stxKmd) { 1008 return nil 1009 } 1010 return fmt.Errorf("signed transactions not equal") 1011 } 1012 1013 func signMsigKmd() error { 1014 kcl.ImportMultisig(handle, msig.Version, msig.Threshold, msig.Pks) 1015 decoded, err := base32.StdEncoding.WithPadding(base32.NoPadding).DecodeString(pk) 1016 if err != nil { 1017 return fmt.Errorf("signMsigKmd: %w", err) 1018 } 1019 s, err := kcl.MultisigSignTransaction(handle, walletPswd, txn, decoded[:32], types.MultisigSig{}) 1020 if err != nil { 1021 return err 1022 } 1023 msgpack.Decode(s.Multisig, &msigsig) 1024 stxObj.Msig = msigsig 1025 stxObj.Sig = types.Signature{} 1026 stxObj.Txn = txn 1027 stxKmd = msgpack.Encode(stxObj) 1028 return nil 1029 } 1030 1031 func signMsigBothEqual() error { 1032 addr, err := msig.Address() 1033 if err != nil { 1034 return err 1035 } 1036 kcl.DeleteMultisig(handle, walletPswd, addr.String()) 1037 if bytes.Equal(stx, stxKmd) { 1038 return nil 1039 } 1040 return fmt.Errorf("signed transactions not equal") 1041 1042 } 1043 1044 func nodeHealth() error { 1045 err := aclv2.HealthCheck().Do(context.Background()) 1046 return err 1047 } 1048 1049 func ledger() error { 1050 _, err := aclv2.Supply().Do(context.Background()) 1051 return err 1052 } 1053 1054 func createBid() error { 1055 var err error 1056 account = crypto.GenerateAccount() 1057 bid, err = auction.MakeBid(account.Address.String(), 1, 2, 3, account.Address.String(), 4) 1058 return err 1059 } 1060 1061 func encDecBid() error { 1062 temp := msgpack.Encode(sbid) 1063 err := msgpack.Decode(temp, &sbid) 1064 return err 1065 } 1066 1067 func signBid() error { 1068 signedBytes, err := crypto.SignBid(account.PrivateKey, bid) 1069 if err != nil { 1070 return err 1071 } 1072 err = msgpack.Decode(signedBytes, &sbid) 1073 if err != nil { 1074 return err 1075 } 1076 err = msgpack.Decode(signedBytes, &oldBid) 1077 return err 1078 } 1079 1080 func checkBid() error { 1081 if sbid != oldBid { 1082 return fmt.Errorf("bid should still be the same") 1083 } 1084 return nil 1085 } 1086 1087 func decAddr() error { 1088 var err error 1089 oldPk = pk 1090 a, err = types.DecodeAddress(pk) 1091 return err 1092 } 1093 1094 func encAddr() error { 1095 pk = a.String() 1096 return nil 1097 } 1098 1099 func checkAddr() error { 1100 if pk != oldPk { 1101 return fmt.Errorf("A decoded and encoded address should equal the original address") 1102 } 1103 return nil 1104 } 1105 1106 func skToMn() error { 1107 var err error 1108 newMn, err = mnemonic.FromPrivateKey(account.PrivateKey) 1109 return err 1110 } 1111 1112 func checkMn(mn string) error { 1113 if mn != newMn { 1114 return fmt.Errorf("the mnemonic should equal the original mnemonic") 1115 } 1116 return nil 1117 } 1118 1119 func mnToMdk(mn string) error { 1120 var err error 1121 mdk, err = mnemonic.ToMasterDerivationKey(mn) 1122 return err 1123 } 1124 1125 func mdkToMn() error { 1126 var err error 1127 newMn, err = mnemonic.FromMasterDerivationKey(mdk) 1128 return err 1129 } 1130 1131 func createTxnFlat() error { 1132 var err error 1133 paramsToUse := types.SuggestedParams{ 1134 Fee: types.MicroAlgos(fee), 1135 GenesisID: gen, 1136 GenesisHash: gh, 1137 FirstRoundValid: types.Round(fv), 1138 LastRoundValid: types.Round(lv), 1139 FlatFee: true, 1140 } 1141 txn, err = future.MakePaymentTxn(a.String(), to, amt, note, close, paramsToUse) 1142 if err != nil { 1143 return err 1144 } 1145 return err 1146 } 1147 1148 func encMsigTxn(encoded string) error { 1149 var err error 1150 stx, err = base64.StdEncoding.DecodeString(encoded) 1151 if err != nil { 1152 return err 1153 } 1154 err = msgpack.Decode(stx, &stxObj) 1155 return err 1156 } 1157 1158 func appendMsig() error { 1159 var err error 1160 msig, err = crypto.MultisigAccountFromSig(stxObj.Msig) 1161 if err != nil { 1162 return err 1163 } 1164 _, stx, err = crypto.AppendMultisigTransaction(account.PrivateKey, msig, stx) 1165 return err 1166 } 1167 1168 func encMtxs(txs string) error { 1169 var err error 1170 enctxs := strings.Split(txs, " ") 1171 bytetxs = make([][]byte, len(enctxs)) 1172 for i := range enctxs { 1173 bytetxs[i], err = base64.StdEncoding.DecodeString(enctxs[i]) 1174 if err != nil { 1175 return err 1176 } 1177 } 1178 return nil 1179 } 1180 1181 func mergeMsig() (err error) { 1182 _, stx, err = crypto.MergeMultisigTransactions(bytetxs...) 1183 return 1184 } 1185 1186 func microToAlgos(ma int) error { 1187 microalgos = types.MicroAlgos(ma) 1188 microalgos = types.ToMicroAlgos(microalgos.ToAlgos()) 1189 return nil 1190 } 1191 1192 func checkAlgos(ma int) error { 1193 if types.MicroAlgos(ma) != microalgos { 1194 return fmt.Errorf("Converting to and from algos should not change the value") 1195 } 1196 return nil 1197 } 1198 1199 func newAccInfo() error { 1200 _, err := aclv2.AccountInformation(pk).Do(context.Background()) 1201 _, _ = kcl.DeleteKey(handle, walletPswd, pk) 1202 return err 1203 } 1204 1205 func createKeyregWithStateProof(keyregType string) (err error) { 1206 params, err := aclv2.SuggestedParams().Do(context.Background()) 1207 if err != nil { 1208 return err 1209 } 1210 lastRound = uint64(params.LastRoundValid) 1211 pk = accounts[0] 1212 if keyregType == "online" { 1213 nonpart = false 1214 votekey = "9mr13Ri8rFepxN3ghIUrZNui6LqqM5hEzB45Rri5lkU=" 1215 selkey = "dx717L3uOIIb/jr9OIyls1l5Ei00NFgRa380w7TnPr4=" 1216 votefst = uint64(0) 1217 votelst = uint64(30001) 1218 votekd = uint64(10000) 1219 stateProofPK = "mYR0GVEObMTSNdsKM6RwYywHYPqVDqg3E4JFzxZOreH9NU8B+tKzUanyY8AQ144hETgSMX7fXWwjBdHz6AWk9w==" 1220 } else if keyregType == "nonparticipation" { 1221 nonpart = true 1222 votekey = "" 1223 selkey = "" 1224 votefst = 0 1225 votelst = 0 1226 votekd = 0 1227 stateProofPK = "" 1228 } else if keyregType == "offline" { 1229 nonpart = false 1230 votekey = "" 1231 selkey = "" 1232 votefst = 0 1233 votelst = 0 1234 votekd = 0 1235 stateProofPK = "" 1236 } 1237 1238 txn, err = future.MakeKeyRegTxnWithStateProofKey(accounts[0], note, params, votekey, selkey, stateProofPK, votefst, votelst, votekd, nonpart) 1239 if err != nil { 1240 return err 1241 } 1242 1243 return err 1244 } 1245 1246 func createAssetTestFixture() error { 1247 assetTestFixture.Creator = "" 1248 assetTestFixture.AssetIndex = 1 1249 assetTestFixture.AssetName = "testcoin" 1250 assetTestFixture.AssetUnitName = "coins" 1251 assetTestFixture.AssetURL = "http://test" 1252 assetTestFixture.AssetMetadataHash = "fACPO4nRgO55j1ndAK3W6Sgc4APkcyFh" 1253 assetTestFixture.ExpectedParams = modelsV2.AssetParams{} 1254 assetTestFixture.QueriedParams = modelsV2.AssetParams{} 1255 assetTestFixture.LastTransactionIssued = types.Transaction{} 1256 return nil 1257 } 1258 1259 func convertTransactionAssetParamsToModelsAssetParam(input types.AssetParams) modelsV2.AssetParams { 1260 result := modelsV2.AssetParams{ 1261 Total: input.Total, 1262 Decimals: uint64(input.Decimals), 1263 DefaultFrozen: input.DefaultFrozen, 1264 Manager: input.Manager.String(), 1265 Reserve: input.Reserve.String(), 1266 Freeze: input.Freeze.String(), 1267 Clawback: input.Clawback.String(), 1268 UnitName: input.UnitName, 1269 Name: input.AssetName, 1270 Url: input.URL, 1271 MetadataHash: input.MetadataHash[:], 1272 } 1273 // input doesn't have Creator so that will remain empty 1274 return result 1275 } 1276 1277 func assetCreateTxnHelper(issuance int, frozenState bool) error { 1278 accountToUse := accounts[0] 1279 assetTestFixture.Creator = accountToUse 1280 creator := assetTestFixture.Creator 1281 params, err := aclv2.SuggestedParams().Do(context.Background()) 1282 if err != nil { 1283 return err 1284 } 1285 lastRound = uint64(params.FirstRoundValid) 1286 assetNote := []byte(nil) 1287 assetIssuance := uint64(issuance) 1288 manager := creator 1289 reserve := creator 1290 freeze := creator 1291 clawback := creator 1292 unitName := assetTestFixture.AssetUnitName 1293 assetName := assetTestFixture.AssetName 1294 url := assetTestFixture.AssetURL 1295 metadataHash := assetTestFixture.AssetMetadataHash 1296 assetCreateTxn, err := future.MakeAssetCreateTxn(creator, assetNote, params, assetIssuance, 0, frozenState, manager, reserve, freeze, clawback, unitName, assetName, url, metadataHash) 1297 assetTestFixture.LastTransactionIssued = assetCreateTxn 1298 txn = assetCreateTxn 1299 assetTestFixture.ExpectedParams = convertTransactionAssetParamsToModelsAssetParam(assetCreateTxn.AssetParams) 1300 //convertTransactionAssetParamsToModelsAssetParam leaves creator blank, repopulate 1301 assetTestFixture.ExpectedParams.Creator = creator 1302 return err 1303 } 1304 1305 func defaultAssetCreateTxn(issuance int) error { 1306 return assetCreateTxnHelper(issuance, false) 1307 } 1308 1309 func defaultAssetCreateTxnWithDefaultFrozen(issuance int) error { 1310 return assetCreateTxnHelper(issuance, true) 1311 } 1312 1313 func createNoManagerAssetReconfigure() error { 1314 creator := assetTestFixture.Creator 1315 params, err := aclv2.SuggestedParams().Do(context.Background()) 1316 if err != nil { 1317 return err 1318 } 1319 lastRound = uint64(params.FirstRoundValid) 1320 assetNote := []byte(nil) 1321 reserve := "" 1322 freeze := "" 1323 clawback := "" 1324 manager := creator // if this were "" as well, this wouldn't be a reconfigure txn, it would be a destroy txn 1325 assetReconfigureTxn, err := future.MakeAssetConfigTxn(creator, assetNote, params, assetTestFixture.AssetIndex, manager, reserve, freeze, clawback, false) 1326 assetTestFixture.LastTransactionIssued = assetReconfigureTxn 1327 txn = assetReconfigureTxn 1328 // update expected params 1329 assetTestFixture.ExpectedParams.Reserve = reserve 1330 assetTestFixture.ExpectedParams.Freeze = freeze 1331 assetTestFixture.ExpectedParams.Clawback = clawback 1332 return err 1333 } 1334 1335 func createAssetDestroy() error { 1336 creator := assetTestFixture.Creator 1337 params, err := aclv2.SuggestedParams().Do(context.Background()) 1338 if err != nil { 1339 return err 1340 } 1341 lastRound = uint64(params.FirstRoundValid) 1342 assetNote := []byte(nil) 1343 assetDestroyTxn, err := future.MakeAssetDestroyTxn(creator, assetNote, params, assetTestFixture.AssetIndex) 1344 assetTestFixture.LastTransactionIssued = assetDestroyTxn 1345 txn = assetDestroyTxn 1346 // update expected params 1347 assetTestFixture.ExpectedParams.Reserve = "" 1348 assetTestFixture.ExpectedParams.Freeze = "" 1349 assetTestFixture.ExpectedParams.Clawback = "" 1350 assetTestFixture.ExpectedParams.Manager = "" 1351 return err 1352 } 1353 1354 // used in getAssetIndex and similar to get the index of the most recently operated on asset 1355 func getMaxKey(numbers []modelsV2.Asset) uint64 { 1356 var maxNumber uint64 = 0 1357 for _, asset := range numbers { 1358 idx := asset.Index 1359 if idx > maxNumber { 1360 maxNumber = idx 1361 } 1362 } 1363 return maxNumber 1364 } 1365 1366 func getAssetIndex() error { 1367 accountResp, err := aclv2.AccountInformation(assetTestFixture.Creator).Do(context.Background()) 1368 if err != nil { 1369 return err 1370 } 1371 // get most recent asset index 1372 assetTestFixture.AssetIndex = getMaxKey(accountResp.CreatedAssets) 1373 return nil 1374 } 1375 1376 func getAssetInfo() error { 1377 response, err := aclv2.GetAssetByID(assetTestFixture.AssetIndex).Do(context.Background()) 1378 assetTestFixture.QueriedParams = response.Params 1379 return err 1380 } 1381 1382 func failToGetAssetInfo() error { 1383 _, err := aclv2.GetAssetByID(assetTestFixture.AssetIndex).Do(context.Background()) 1384 if err != nil { 1385 return nil 1386 } 1387 return fmt.Errorf("expected an error getting asset with index %v and creator %v, but no error was returned", 1388 assetTestFixture.AssetIndex, assetTestFixture.Creator) 1389 } 1390 1391 func checkExpectedVsActualAssetParams() error { 1392 expectedParams := assetTestFixture.ExpectedParams 1393 actualParams := assetTestFixture.QueriedParams 1394 nameMatch := expectedParams.Name == actualParams.Name 1395 if !nameMatch { 1396 return fmt.Errorf("expected asset name was %v but actual asset name was %v", 1397 expectedParams.Name, actualParams.Name) 1398 } 1399 unitMatch := expectedParams.UnitName == actualParams.UnitName 1400 if !unitMatch { 1401 return fmt.Errorf("expected unit name was %v but actual unit name was %v", 1402 expectedParams.UnitName, actualParams.UnitName) 1403 } 1404 urlMatch := expectedParams.Url == actualParams.Url 1405 if !urlMatch { 1406 return fmt.Errorf("expected URL was %v but actual URL was %v", 1407 expectedParams.Url, actualParams.Url) 1408 } 1409 hashMatch := reflect.DeepEqual(expectedParams.MetadataHash, actualParams.MetadataHash) 1410 if !hashMatch { 1411 return fmt.Errorf("expected MetadataHash was %v but actual MetadataHash was %v", 1412 expectedParams.MetadataHash, actualParams.MetadataHash) 1413 } 1414 issuanceMatch := expectedParams.Total == actualParams.Total 1415 if !issuanceMatch { 1416 return fmt.Errorf("expected total issuance was %v but actual issuance was %v", 1417 expectedParams.Total, actualParams.Total) 1418 } 1419 defaultFrozenMatch := expectedParams.DefaultFrozen == actualParams.DefaultFrozen 1420 if !defaultFrozenMatch { 1421 return fmt.Errorf("expected default frozen state %v but actual default frozen state was %v", 1422 expectedParams.DefaultFrozen, actualParams.DefaultFrozen) 1423 } 1424 managerMatch := expectedParams.Manager == actualParams.Manager 1425 if !managerMatch { 1426 return fmt.Errorf("expected asset manager was %v but actual asset manager was %v", 1427 expectedParams.Manager, actualParams.Manager) 1428 } 1429 reserveMatch := expectedParams.Reserve == actualParams.Reserve 1430 if !reserveMatch { 1431 return fmt.Errorf("expected asset reserve was %v but actual asset reserve was %v", 1432 expectedParams.Reserve, actualParams.Reserve) 1433 } 1434 freezeMatch := expectedParams.Freeze == actualParams.Freeze 1435 if !freezeMatch { 1436 return fmt.Errorf("expected freeze manager was %v but actual freeze manager was %v", 1437 expectedParams.Freeze, actualParams.Freeze) 1438 } 1439 clawbackMatch := expectedParams.Clawback == actualParams.Clawback 1440 if !clawbackMatch { 1441 return fmt.Errorf("expected revocation (clawback) manager was %v but actual revocation manager was %v", 1442 expectedParams.Clawback, actualParams.Clawback) 1443 } 1444 return nil 1445 } 1446 1447 func findAssetID(assets []modelsV2.AssetHolding, assetID uint64) (foundAsset modelsV2.AssetHolding, err error) { 1448 for _, asset := range assets { 1449 if asset.AssetId == assetID { 1450 return asset, nil 1451 } 1452 } 1453 return modelsV2.AssetHolding{}, fmt.Errorf("asset ID %d was not found", assetID) 1454 } 1455 1456 func theCreatorShouldHaveAssetsRemaining(expectedBal int) error { 1457 expectedBalance := uint64(expectedBal) 1458 accountResp, err := aclv2.AccountInformation(assetTestFixture.Creator).Do(context.Background()) 1459 if err != nil { 1460 return err 1461 } 1462 // Find asset ID 1463 holding, err := findAssetID(accountResp.Assets, assetTestFixture.AssetIndex) 1464 if err != nil { 1465 return fmt.Errorf("attempted to get balance of account %v for creator %v and index %v, but no balance was found for that index", assetTestFixture.Creator, assetTestFixture.Creator, assetTestFixture.AssetIndex) 1466 } 1467 if holding.Amount != expectedBalance { 1468 return fmt.Errorf("actual balance %v differed from expected balance %v", holding.Amount, expectedBalance) 1469 } 1470 return nil 1471 } 1472 1473 func createAssetAcceptanceForSecondAccount() error { 1474 accountToUse := accounts[1] 1475 params, err := aclv2.SuggestedParams().Do(context.Background()) 1476 if err != nil { 1477 return err 1478 } 1479 lastRound = uint64(params.FirstRoundValid) 1480 assetNote := []byte(nil) 1481 assetAcceptanceTxn, err := future.MakeAssetAcceptanceTxn(accountToUse, assetNote, params, assetTestFixture.AssetIndex) 1482 assetTestFixture.LastTransactionIssued = assetAcceptanceTxn 1483 txn = assetAcceptanceTxn 1484 return err 1485 } 1486 1487 func createAssetTransferTransactionToSecondAccount(amount int) error { 1488 recipient := accounts[1] 1489 creator := assetTestFixture.Creator 1490 params, err := aclv2.SuggestedParams().Do(context.Background()) 1491 if err != nil { 1492 return err 1493 } 1494 sendAmount := uint64(amount) 1495 closeAssetsTo := "" 1496 lastRound = uint64(params.FirstRoundValid) 1497 assetNote := []byte(nil) 1498 assetAcceptanceTxn, err := future.MakeAssetTransferTxn(creator, recipient, sendAmount, assetNote, params, closeAssetsTo, assetTestFixture.AssetIndex) 1499 assetTestFixture.LastTransactionIssued = assetAcceptanceTxn 1500 txn = assetAcceptanceTxn 1501 return err 1502 } 1503 1504 func createAssetTransferTransactionFromSecondAccountToCreator(amount int) error { 1505 recipient := assetTestFixture.Creator 1506 sender := accounts[1] 1507 params, err := aclv2.SuggestedParams().Do(context.Background()) 1508 if err != nil { 1509 return err 1510 } 1511 sendAmount := uint64(amount) 1512 closeAssetsTo := "" 1513 lastRound = uint64(params.FirstRoundValid) 1514 assetNote := []byte(nil) 1515 assetAcceptanceTxn, err := future.MakeAssetTransferTxn(sender, recipient, sendAmount, assetNote, params, closeAssetsTo, assetTestFixture.AssetIndex) 1516 assetTestFixture.LastTransactionIssued = assetAcceptanceTxn 1517 txn = assetAcceptanceTxn 1518 return err 1519 } 1520 1521 // sets up a freeze transaction, with freeze state `setting` against target account `target` 1522 // assumes creator is asset freeze manager 1523 func freezeTransactionHelper(target string, setting bool) error { 1524 params, err := aclv2.SuggestedParams().Do(context.Background()) 1525 if err != nil { 1526 return err 1527 } 1528 lastRound = uint64(params.FirstRoundValid) 1529 assetNote := []byte(nil) 1530 assetFreezeOrUnfreezeTxn, err := future.MakeAssetFreezeTxn(assetTestFixture.Creator, assetNote, params, assetTestFixture.AssetIndex, target, setting) 1531 assetTestFixture.LastTransactionIssued = assetFreezeOrUnfreezeTxn 1532 txn = assetFreezeOrUnfreezeTxn 1533 return err 1534 } 1535 1536 func createFreezeTransactionTargetingSecondAccount() error { 1537 return freezeTransactionHelper(accounts[1], true) 1538 } 1539 1540 func createUnfreezeTransactionTargetingSecondAccount() error { 1541 return freezeTransactionHelper(accounts[1], false) 1542 } 1543 1544 func createRevocationTransaction(amount int) error { 1545 params, err := aclv2.SuggestedParams().Do(context.Background()) 1546 if err != nil { 1547 return err 1548 } 1549 lastRound = uint64(params.FirstRoundValid) 1550 revocationAmount := uint64(amount) 1551 assetNote := []byte(nil) 1552 assetRevokeTxn, err := future.MakeAssetRevocationTxn(assetTestFixture.Creator, accounts[1], revocationAmount, assetTestFixture.Creator, assetNote, params, assetTestFixture.AssetIndex) 1553 assetTestFixture.LastTransactionIssued = assetRevokeTxn 1554 txn = assetRevokeTxn 1555 return err 1556 } 1557 1558 // godog misreads the step for this function, so provide a handler for when it does so 1559 func iCreateATransactionTransferringAmountAssetsFromCreatorToASecondAccount() error { 1560 return createAssetTransferTransactionToSecondAccount(500000) 1561 } 1562 1563 func baseEncodedDataToSign(dataEnc string) (err error) { 1564 data, err = base64.StdEncoding.DecodeString(dataEnc) 1565 return 1566 } 1567 1568 func programHash(addr string) (err error) { 1569 account.Address, err = types.DecodeAddress(addr) 1570 return 1571 } 1572 1573 func iPerformTealsign() (err error) { 1574 sig, err = crypto.TealSign(account.PrivateKey, data, account.Address) 1575 return 1576 } 1577 1578 func theSignatureShouldBeEqualTo(sigEnc string) error { 1579 expected, err := base64.StdEncoding.DecodeString(sigEnc) 1580 if err != nil { 1581 return err 1582 } 1583 if !bytes.Equal(expected, sig[:]) { 1584 return fmt.Errorf("%v != %v", expected, sig[:]) 1585 } 1586 return nil 1587 } 1588 1589 func baseEncodedProgram(programEnc string) error { 1590 program, err := base64.StdEncoding.DecodeString(programEnc) 1591 if err != nil { 1592 return err 1593 } 1594 account.Address = crypto.AddressFromProgram(program) 1595 return nil 1596 } 1597 1598 func baseEncodedPrivateKey(skEnc string) error { 1599 seed, err := base64.StdEncoding.DecodeString(skEnc) 1600 if err != nil { 1601 return err 1602 } 1603 account.PrivateKey = ed25519.NewKeyFromSeed(seed) 1604 return nil 1605 } 1606 1607 func tealCompile(filename string) (err error) { 1608 if len(filename) == 0 { 1609 return fmt.Errorf("empty teal program file name") 1610 } 1611 tealProgram, err := loadResource(filename) 1612 if err != nil { 1613 return err 1614 } 1615 result, err := aclv2.TealCompile(tealProgram).Do(context.Background()) 1616 if err == nil { 1617 tealCompleResult.status = 200 1618 tealCompleResult.response = result 1619 return 1620 } 1621 if _, ok := err.(commonV2.BadRequest); ok { 1622 tealCompleResult.status = 400 1623 tealCompleResult.response.Hash = "" 1624 tealCompleResult.response.Result = "" 1625 return nil 1626 } 1627 1628 return 1629 } 1630 1631 func tealCheckCompile(status int, result string, hash string) error { 1632 if status != tealCompleResult.status { 1633 return fmt.Errorf("status: %d != %d", status, tealCompleResult.status) 1634 } 1635 if result != tealCompleResult.response.Result { 1636 return fmt.Errorf("result: %s != %s", result, tealCompleResult.response.Result) 1637 } 1638 1639 if hash != tealCompleResult.response.Hash { 1640 return fmt.Errorf("hash: %s != %s", hash, tealCompleResult.response.Hash) 1641 } 1642 return nil 1643 } 1644 1645 func tealCheckCompileAgainstFile(expectedFile string) error { 1646 if len(expectedFile) == 0 { 1647 return fmt.Errorf("empty teal program file name") 1648 } 1649 1650 expectedTeal, err := loadResource(expectedFile) 1651 if err != nil { 1652 return err 1653 } 1654 1655 actualTeal, err := base64.StdEncoding.DecodeString(tealCompleResult.response.Result) 1656 if err != nil { 1657 return err 1658 } 1659 1660 if !bytes.Equal(actualTeal, expectedTeal) { 1661 return fmt.Errorf("Actual program does not match expected") 1662 } 1663 1664 return nil 1665 } 1666 1667 func tealDryrun(kind string, filename string) (err error) { 1668 if len(filename) == 0 { 1669 return fmt.Errorf("empty teal program file name") 1670 } 1671 tealProgram, err := loadResource(filename) 1672 if err != nil { 1673 return err 1674 } 1675 1676 txns := []types.SignedTxn{{}} 1677 sources := []modelsV2.DryrunSource{} 1678 switch kind { 1679 case "compiled": 1680 txns[0].Lsig.Logic = tealProgram 1681 case "source": 1682 sources = append(sources, modelsV2.DryrunSource{ 1683 FieldName: "lsig", 1684 Source: string(tealProgram), 1685 TxnIndex: 0, 1686 }) 1687 default: 1688 return fmt.Errorf("kind %s not in (source, compiled)", kind) 1689 } 1690 1691 ddr := modelsV2.DryrunRequest{ 1692 Txns: txns, 1693 Sources: sources, 1694 } 1695 1696 result, err := aclv2.TealDryrun(ddr).Do(context.Background()) 1697 if err != nil { 1698 return 1699 } 1700 1701 tealDryrunResult.response = result 1702 return 1703 } 1704 1705 func tealCheckDryrun(result string) error { 1706 txnResult := tealDryrunResult.response.Txns[0] 1707 var msgs []string 1708 if txnResult.AppCallMessages != nil && len(txnResult.AppCallMessages) > 0 { 1709 msgs = txnResult.AppCallMessages 1710 } else if txnResult.LogicSigMessages != nil && len(txnResult.LogicSigMessages) > 0 { 1711 msgs = txnResult.LogicSigMessages 1712 } 1713 if len(msgs) == 0 { 1714 return fmt.Errorf("received no messages") 1715 } 1716 1717 if msgs[len(msgs)-1] != result { 1718 return fmt.Errorf("dryrun status %s != %s", result, msgs[len(msgs)-1]) 1719 } 1720 return nil 1721 } 1722 1723 func createMethodObjectFromSignature(methodSig string) error { 1724 abiMethodLocal, err := abi.MethodFromSignature(methodSig) 1725 abiMethod = abiMethodLocal 1726 return err 1727 } 1728 1729 func serializeMethodObjectIntoJson() error { 1730 abiMethodJson, err := json.Marshal(abiMethod) 1731 if err != nil { 1732 return err 1733 } 1734 1735 abiJsonString = string(abiMethodJson) 1736 return nil 1737 } 1738 1739 func checkSerializedMethodObject(jsonFile, loadedFrom string) error { 1740 directory := path.Join("./features/unit/", loadedFrom) 1741 jsons, err := loadMockJsons(jsonFile, directory) 1742 if err != nil { 1743 return err 1744 } 1745 correctJson := string(jsons[0]) 1746 1747 var actualJson interface{} 1748 err = json.Unmarshal([]byte(abiJsonString), &actualJson) 1749 if err != nil { 1750 return err 1751 } 1752 1753 var expectedJson interface{} 1754 err = json.Unmarshal([]byte(correctJson), &expectedJson) 1755 if err != nil { 1756 return err 1757 } 1758 1759 if !reflect.DeepEqual(actualJson, expectedJson) { 1760 return fmt.Errorf("json strings %s != %s", correctJson, abiJsonString) 1761 } 1762 1763 return nil 1764 } 1765 1766 func createMethodObjectFromProperties(name, firstArgType, secondArgType, returnType string) error { 1767 args := []abi.Arg{ 1768 {Name: "", Type: firstArgType, Desc: ""}, 1769 {Name: "", Type: secondArgType, Desc: ""}, 1770 } 1771 abiMethod = abi.Method{ 1772 Name: name, 1773 Desc: "", 1774 Args: args, 1775 Returns: abi.Return{Type: returnType, Desc: ""}, 1776 } 1777 return nil 1778 } 1779 1780 func createMethodObjectWithArgNames(name, firstArgName, firstArgType, secondArgName, secondArgType, returnType string) error { 1781 args := []abi.Arg{ 1782 {Name: firstArgName, Type: firstArgType, Desc: ""}, 1783 {Name: secondArgName, Type: secondArgType, Desc: ""}, 1784 } 1785 abiMethod = abi.Method{ 1786 Name: name, 1787 Desc: "", 1788 Args: args, 1789 Returns: abi.Return{Type: returnType, Desc: ""}, 1790 } 1791 return nil 1792 } 1793 1794 func createMethodObjectWithDescription(name, nameDesc, firstArgType, firstDesc, secondArgType, secondDesc, returnType string) error { 1795 args := []abi.Arg{ 1796 {Name: "", Type: firstArgType, Desc: firstDesc}, 1797 {Name: "", Type: secondArgType, Desc: secondDesc}, 1798 } 1799 abiMethod = abi.Method{ 1800 Name: name, 1801 Desc: nameDesc, 1802 Args: args, 1803 Returns: abi.Return{Type: returnType, Desc: ""}, 1804 } 1805 return nil 1806 } 1807 1808 func checkTxnCount(givenTxnCount int) error { 1809 correctTxnCount := abiMethod.GetTxCount() 1810 if correctTxnCount != givenTxnCount { 1811 return fmt.Errorf("txn count %d != %d", givenTxnCount, correctTxnCount) 1812 } 1813 return nil 1814 } 1815 1816 func checkMethodSelector(givenMethodSelector string) error { 1817 correctMethodSelector := hex.EncodeToString(abiMethod.GetSelector()) 1818 if correctMethodSelector != givenMethodSelector { 1819 return fmt.Errorf("method selector %s != %s", givenMethodSelector, correctMethodSelector) 1820 } 1821 return nil 1822 } 1823 1824 func createInterfaceObject(name string, desc string) error { 1825 abiInterface = abi.Interface{ 1826 Name: name, 1827 Desc: desc, 1828 Methods: []abi.Method{abiMethod}, 1829 } 1830 return nil 1831 } 1832 1833 func serializeInterfaceObjectIntoJson() error { 1834 abiInterfaceJson, err := json.Marshal(abiInterface) 1835 if err != nil { 1836 return err 1837 } 1838 1839 abiJsonString = string(abiInterfaceJson) 1840 return nil 1841 } 1842 1843 func createContractObject(name string, desc string) error { 1844 abiContract = abi.Contract{ 1845 Name: name, 1846 Desc: desc, 1847 Networks: make(map[string]abi.ContractNetworkInfo), 1848 Methods: []abi.Method{abiMethod}, 1849 } 1850 return nil 1851 } 1852 1853 func iSetTheContractsAppIDToForTheNetwork(appID int, network string) error { 1854 if appID < 0 { 1855 return fmt.Errorf("App ID must not be negative. Got: %d", appID) 1856 } 1857 abiContract.Networks[network] = abi.ContractNetworkInfo{AppID: uint64(appID)} 1858 return nil 1859 } 1860 1861 func serializeContractObjectIntoJson() error { 1862 abiContractJson, err := json.Marshal(abiContract) 1863 if err != nil { 1864 return err 1865 } 1866 1867 abiJsonString = string(abiContractJson) 1868 return nil 1869 } 1870 1871 func iAppendToMyMethodObjectsListInTheCaseOfANonemptySignature(arg1 string) error { 1872 if arg1 == "" { 1873 return nil 1874 } 1875 1876 meth, err := abi.MethodFromSignature(arg1) 1877 abiMethods = append(abiMethods, meth) 1878 return err 1879 } 1880 1881 func iCreateAnInterfaceObjectFromMyMethodObjectsList() error { 1882 abiInterface = abi.Interface{ 1883 Name: "", 1884 Methods: abiMethods, 1885 } 1886 return nil 1887 } 1888 1889 func iGetTheMethodFromTheInterfaceByName(arg1 string) error { 1890 abiMethod, globalErrForExamination = abiInterface.GetMethodByName(arg1) 1891 return nil 1892 } 1893 1894 func iCreateAContractObjectFromMyMethodObjectsList() error { 1895 abiContract = abi.Contract{ 1896 Name: "", 1897 Methods: abiMethods, 1898 } 1899 return nil 1900 } 1901 1902 func iGetTheMethodFromTheContractByName(arg1 string) error { 1903 abiMethod, globalErrForExamination = abiContract.GetMethodByName(arg1) 1904 return nil 1905 } 1906 1907 func theProducedMethodSignatureShouldEqualIfThereIsAnErrorItBeginsWith(arg1, arg2 string) error { 1908 if abiMethod.Name != "" { 1909 if arg2 != "" { 1910 return fmt.Errorf("expected error condition but got a method") 1911 } 1912 if arg1 != abiMethod.GetSignature() { 1913 return fmt.Errorf("signature mismatch: %s != %s", arg1, abiMethod.GetSignature()) 1914 } 1915 } else if globalErrForExamination != nil { 1916 if arg2 == "" { 1917 return fmt.Errorf("got error %s, expected no error", globalErrForExamination) 1918 } 1919 1920 if !strings.Contains(globalErrForExamination.Error(), arg2) { 1921 return fmt.Errorf("produced error does not match expected: %q does not contain %q", globalErrForExamination.Error(), arg2) 1922 } 1923 1924 } else { 1925 return fmt.Errorf("both abi method and error string are empty") 1926 } 1927 1928 return nil 1929 } 1930 1931 // equality helper methods 1932 func checkEqualMethods(method1, method2 abi.Method) bool { 1933 if method1.Name != method2.Name || method1.Desc != method2.Desc { 1934 return false 1935 } 1936 1937 if method1.Returns.Type != method2.Returns.Type || method1.Returns.Desc != method2.Returns.Desc { 1938 return false 1939 } 1940 1941 if len(method1.Args) != len(method2.Args) { 1942 return false 1943 } 1944 1945 for i, arg1 := range method1.Args { 1946 arg2 := method2.Args[i] 1947 if arg1.Name != arg2.Name || arg1.Type != arg2.Type || arg1.Desc != arg2.Desc { 1948 return false 1949 } 1950 } 1951 return true 1952 } 1953 1954 func checkEqualInterfaces(interface1, interface2 abi.Interface) bool { 1955 if interface1.Name != interface2.Name || interface1.Desc != interface2.Desc { 1956 return false 1957 } 1958 1959 if len(interface1.Methods) != len(interface2.Methods) { 1960 return false 1961 } 1962 1963 for i, method := range interface1.Methods { 1964 if !checkEqualMethods(method, interface2.Methods[i]) { 1965 return false 1966 } 1967 } 1968 return true 1969 } 1970 1971 func checkEqualContracts(contract1, contract2 abi.Contract) bool { 1972 if contract1.Name != contract2.Name || contract1.Desc != contract2.Desc { 1973 return false 1974 } 1975 1976 if len(contract1.Networks) != len(contract2.Networks) { 1977 return false 1978 } 1979 1980 for network, info1 := range contract1.Networks { 1981 info2, ok := contract2.Networks[network] 1982 if !ok || info1 != info2 { 1983 return false 1984 } 1985 } 1986 1987 if len(contract1.Methods) != len(contract2.Methods) { 1988 return false 1989 } 1990 1991 for i, method := range contract1.Methods { 1992 if !checkEqualMethods(method, contract2.Methods[i]) { 1993 return false 1994 } 1995 } 1996 return true 1997 } 1998 1999 func deserializeMethodJson() error { 2000 var deserializedMethod abi.Method 2001 err := json.Unmarshal([]byte(abiJsonString), &deserializedMethod) 2002 if err != nil { 2003 return err 2004 } 2005 2006 if !checkEqualMethods(deserializedMethod, abiMethod) { 2007 return fmt.Errorf("Deserialized method does not match original method") 2008 } 2009 return nil 2010 } 2011 2012 func deserializeInterfaceJson() error { 2013 var deserializedInterface abi.Interface 2014 err := json.Unmarshal([]byte(abiJsonString), &deserializedInterface) 2015 if err != nil { 2016 return err 2017 } 2018 if !checkEqualInterfaces(deserializedInterface, abiInterface) { 2019 return fmt.Errorf("Deserialized interface does not match original interface") 2020 } 2021 return nil 2022 } 2023 2024 func deserializeContractJson() error { 2025 var deserializedContract abi.Contract 2026 err := json.Unmarshal([]byte(abiJsonString), &deserializedContract) 2027 if err != nil { 2028 return err 2029 } 2030 if !checkEqualContracts(deserializedContract, abiContract) { 2031 return fmt.Errorf("Deserialized contract does not match original contract") 2032 } 2033 return nil 2034 } 2035 2036 func aNewAtomicTransactionComposer() error { 2037 txComposer = future.AtomicTransactionComposer{} 2038 return nil 2039 } 2040 2041 func suggestedTransactionParameters(fee int, flatFee string, firstValid, LastValid int, genesisHash, genesisId string) error { 2042 if flatFee != "true" && flatFee != "false" { 2043 return fmt.Errorf("flatFee must be either 'true' or 'false'") 2044 } 2045 2046 genHash, err := base64.StdEncoding.DecodeString(genesisHash) 2047 if err != nil { 2048 return err 2049 } 2050 2051 sugParams = types.SuggestedParams{ 2052 Fee: types.MicroAlgos(fee), 2053 GenesisID: genesisId, 2054 GenesisHash: genHash, 2055 FirstRoundValid: types.Round(firstValid), 2056 LastRoundValid: types.Round(LastValid), 2057 FlatFee: flatFee == "true", 2058 } 2059 2060 return nil 2061 } 2062 2063 func anApplicationId(id int) error { 2064 if id < 0 { 2065 return fmt.Errorf("app id must be positive integer") 2066 } 2067 2068 applicationId = uint64(id) 2069 return nil 2070 } 2071 2072 func iMakeATransactionSignerForTheAccount(accountType string) error { 2073 if accountType == "signing" { 2074 accountTxSigner = future.BasicAccountTransactionSigner{ 2075 Account: account, 2076 } 2077 } else if accountType == "transient" { 2078 accountTxSigner = future.BasicAccountTransactionSigner{ 2079 Account: transientAccount, 2080 } 2081 } 2082 2083 return nil 2084 } 2085 2086 func iCreateANewMethodArgumentsArray() error { 2087 methodArgs = make([]interface{}, 0) 2088 return nil 2089 } 2090 2091 func iAppendTheEncodedArgumentsToTheMethodArgumentsArray(commaSeparatedB64Args string) error { 2092 if len(commaSeparatedB64Args) == 0 { 2093 return nil 2094 } 2095 2096 b64Args := strings.Split(commaSeparatedB64Args, ",") 2097 for _, b64Arg := range b64Args { 2098 if strings.Contains(b64Arg, ":") { 2099 // special case for inserting existing application ID 2100 parts := strings.Split(b64Arg, ":") 2101 if len(parts) != 2 || parts[0] != "ctxAppIdx" { 2102 return fmt.Errorf("Cannot process argument: %s", b64Arg) 2103 } 2104 parsedIndex, err := strconv.ParseUint(parts[1], 10, 64) 2105 if err != nil { 2106 return err 2107 } 2108 if parsedIndex >= uint64(len(applicationIds)) { 2109 return fmt.Errorf("Application index out of bounds: %d, number of app IDs is %d", parsedIndex, len(applicationIds)) 2110 } 2111 abiUint64, err := abi.TypeOf("uint64") 2112 if err != nil { 2113 return err 2114 } 2115 encodedUint64, err := abiUint64.Encode(applicationIds[parsedIndex]) 2116 if err != nil { 2117 return err 2118 } 2119 methodArgs = append(methodArgs, encodedUint64) 2120 continue 2121 } 2122 decodedArg, err := base64.StdEncoding.DecodeString(b64Arg) 2123 if err != nil { 2124 return err 2125 } 2126 methodArgs = append(methodArgs, decodedArg) 2127 } 2128 2129 return nil 2130 } 2131 2132 func addMethodCall(accountType, strOnComplete string) error { 2133 return addMethodCallHelper(accountType, strOnComplete, "", "", 0, 0, 0, 0, 0, false) 2134 } 2135 2136 func addMethodCallForUpdate(accountType, strOnComplete, approvalProgram, clearProgram string) error { 2137 return addMethodCallHelper(accountType, strOnComplete, approvalProgram, clearProgram, 0, 0, 0, 0, 0, false) 2138 } 2139 2140 func addMethodCallForCreate(accountType, strOnComplete, approvalProgram, clearProgram string, globalBytes, globalInts, localBytes, localInts, extraPages int) error { 2141 return addMethodCallHelper(accountType, strOnComplete, approvalProgram, clearProgram, globalBytes, globalInts, localBytes, localInts, extraPages, false) 2142 } 2143 2144 func addMethodCallWithNonce(accountType, strOnComplete string) error { 2145 return addMethodCallHelper(accountType, strOnComplete, "", "", 0, 0, 0, 0, 0, true) 2146 } 2147 2148 func addMethodCallHelper(accountType, strOnComplete, approvalProgram, clearProgram string, globalBytes, globalInts, localBytes, localInts, extraPages int, useNonce bool) error { 2149 var onComplete types.OnCompletion 2150 switch strOnComplete { 2151 case "create": 2152 onComplete = types.NoOpOC 2153 case "noop": 2154 onComplete = types.NoOpOC 2155 case "update": 2156 onComplete = types.UpdateApplicationOC 2157 case "call": 2158 onComplete = types.NoOpOC 2159 case "optin": 2160 onComplete = types.OptInOC 2161 case "clear": 2162 onComplete = types.ClearStateOC 2163 case "closeout": 2164 onComplete = types.CloseOutOC 2165 case "delete": 2166 onComplete = types.DeleteApplicationOC 2167 default: 2168 return fmt.Errorf("invalid onComplete value") 2169 } 2170 2171 var useAccount crypto.Account 2172 if accountType == "signing" { 2173 useAccount = account 2174 } else if accountType == "transient" { 2175 useAccount = transientAccount 2176 } 2177 2178 var approvalProgramBytes []byte 2179 var clearProgramBytes []byte 2180 var err error 2181 2182 if approvalProgram != "" { 2183 approvalProgramBytes, err = readTealProgram(approvalProgram) 2184 if err != nil { 2185 return err 2186 } 2187 } 2188 2189 if clearProgram != "" { 2190 clearProgramBytes, err = readTealProgram(clearProgram) 2191 if err != nil { 2192 return err 2193 } 2194 } 2195 2196 if globalInts < 0 || globalBytes < 0 || localInts < 0 || localBytes < 0 || extraPages < 0 { 2197 return fmt.Errorf("Values for globalInts, globalBytes, localInts, localBytes, and extraPages cannot be negative") 2198 } 2199 2200 // populate args from methodArgs 2201 if len(methodArgs) != len(abiMethod.Args) { 2202 return fmt.Errorf("Provided argument count is incorrect. Expected %d, got %d", len(abiMethod.Args), len(methodArgs)) 2203 } 2204 2205 var preparedArgs []interface{} 2206 for i, argSpec := range abiMethod.Args { 2207 if argSpec.IsTransactionArg() { 2208 // encodedArg is already a TransactionWithSigner 2209 preparedArgs = append(preparedArgs, methodArgs[i]) 2210 continue 2211 } 2212 2213 encodedArg, ok := methodArgs[i].([]byte) 2214 if !ok { 2215 return fmt.Errorf("Argument should be a byte slice") 2216 } 2217 2218 var typeToDecode abi.Type 2219 var err error 2220 2221 if argSpec.IsReferenceArg() { 2222 switch argSpec.Type { 2223 case abi.AccountReferenceType: 2224 typeToDecode, err = abi.TypeOf("address") 2225 case abi.ApplicationReferenceType, abi.AssetReferenceType: 2226 typeToDecode, err = abi.TypeOf("uint64") 2227 default: 2228 return fmt.Errorf("Unknown reference type: %s", argSpec.Type) 2229 } 2230 } else { 2231 typeToDecode, err = argSpec.GetTypeObject() 2232 } 2233 if err != nil { 2234 return err 2235 } 2236 2237 decodedArg, err := typeToDecode.Decode(encodedArg) 2238 if err != nil { 2239 return err 2240 } 2241 2242 preparedArgs = append(preparedArgs, decodedArg) 2243 } 2244 2245 methodCallParams := future.AddMethodCallParams{ 2246 AppID: applicationId, 2247 Method: abiMethod, 2248 MethodArgs: preparedArgs, 2249 Sender: useAccount.Address, 2250 SuggestedParams: sugParams, 2251 OnComplete: onComplete, 2252 ApprovalProgram: approvalProgramBytes, 2253 ClearProgram: clearProgramBytes, 2254 GlobalSchema: types.StateSchema{ 2255 NumUint: uint64(globalInts), 2256 NumByteSlice: uint64(globalBytes), 2257 }, 2258 LocalSchema: types.StateSchema{ 2259 NumUint: uint64(localInts), 2260 NumByteSlice: uint64(localBytes), 2261 }, 2262 ExtraPages: uint32(extraPages), 2263 Signer: accountTxSigner, 2264 } 2265 2266 if useNonce { 2267 methodCallParams.Note = note 2268 } 2269 2270 return txComposer.AddMethodCall(methodCallParams) 2271 } 2272 2273 func iAddTheNonce(nonce string) error { 2274 note = []byte("I should be unique thanks to this nonce: " + nonce) 2275 return nil 2276 } 2277 2278 func buildTheTransactionGroupWithTheComposer(errorType string) error { 2279 _, err := txComposer.BuildGroup() 2280 2281 switch errorType { 2282 case "": 2283 // no error expected 2284 return err 2285 case "zero group size error": 2286 if err == nil || err.Error() != "attempting to build group with zero transactions" { 2287 return fmt.Errorf("Expected error, but got: %v", err) 2288 } 2289 return nil 2290 default: 2291 return fmt.Errorf("Unknown error type: %s", errorType) 2292 } 2293 } 2294 2295 func theComposerShouldHaveAStatusOf(strStatus string) error { 2296 var status future.AtomicTransactionComposerStatus 2297 switch strStatus { 2298 case "BUILDING": 2299 status = future.BUILDING 2300 case "BUILT": 2301 status = future.BUILT 2302 case "SIGNED": 2303 status = future.SIGNED 2304 case "SUBMITTED": 2305 status = future.SUBMITTED 2306 case "COMMITTED": 2307 status = future.COMMITTED 2308 default: 2309 return fmt.Errorf("invalid status provided") 2310 } 2311 2312 if status != txComposer.GetStatus() { 2313 return fmt.Errorf("status does not match") 2314 } 2315 2316 return nil 2317 } 2318 2319 func iGatherSignaturesWithTheComposer() error { 2320 signedTxs, err := txComposer.GatherSignatures() 2321 sigTxs = signedTxs 2322 return err 2323 } 2324 2325 func theBaseEncodedSignedTransactionsShouldEqual(encodedTxsStr string) error { 2326 encodedTxs := strings.Split(encodedTxsStr, ",") 2327 if len(encodedTxs) != len(sigTxs) { 2328 return fmt.Errorf("Actual and expected number of signed transactions don't match") 2329 } 2330 2331 for i, encodedTx := range encodedTxs { 2332 gold, err := base64.StdEncoding.DecodeString(encodedTx) 2333 if err != nil { 2334 return err 2335 } 2336 stxStr := base64.StdEncoding.EncodeToString(sigTxs[i]) 2337 if !bytes.Equal(gold, sigTxs[i]) { 2338 return fmt.Errorf("Application signed transaction does not match the golden: %s != %s", stxStr, encodedTx) 2339 } 2340 } 2341 2342 return nil 2343 } 2344 2345 func iBuildAPaymentTransactionWithSenderReceiverAmountCloseRemainderTo(sender, receiver string, amount int, closeTo string) error { 2346 if amount < 0 { 2347 return fmt.Errorf("amount must be a positive integer") 2348 } 2349 2350 if sender == "transient" { 2351 sender = transientAccount.Address.String() 2352 } 2353 2354 if receiver == "transient" { 2355 receiver = transientAccount.Address.String() 2356 } 2357 2358 var err error 2359 txn, err = future.MakePaymentTxn(sender, receiver, uint64(amount), nil, closeTo, sugParams) 2360 tx = txn 2361 return err 2362 } 2363 2364 func iCreateATransactionWithSignerWithTheCurrentTransaction() error { 2365 accountTxAndSigner = future.TransactionWithSigner{ 2366 Signer: accountTxSigner, 2367 Txn: txn, 2368 } 2369 return nil 2370 } 2371 2372 func iAppendTheCurrentTransactionWithSignerToTheMethodArgumentsArray() error { 2373 methodArgs = append(methodArgs, accountTxAndSigner) 2374 return nil 2375 } 2376 2377 func theDecodedTransactionShouldEqualTheOriginal() error { 2378 var decodedTx types.SignedTxn 2379 err := msgpack.Decode(stx, &decodedTx) 2380 if err != nil { 2381 return err 2382 } 2383 2384 // This test isn't perfect as it's sensitive to non-meaningful changes (e.g. nil slice vs 0 2385 // length slice), but it's good enough for now. We may want a Transaction.Equals method in the 2386 // future. 2387 if !reflect.DeepEqual(tx, decodedTx.Txn) { 2388 return fmt.Errorf("Transactions unequal: %#v != %#v", tx, decodedTx.Txn) 2389 } 2390 2391 return nil 2392 } 2393 2394 func aDryrunResponseFileAndATransactionAtIndex(arg1, arg2 string) error { 2395 data, err := loadResource(arg1) 2396 if err != nil { 2397 return err 2398 } 2399 dr, err := future.NewDryrunResponseFromJson(data) 2400 if err != nil { 2401 return err 2402 } 2403 idx, err := strconv.Atoi(arg2) 2404 if err != nil { 2405 return err 2406 } 2407 txTrace = dr.Txns[idx] 2408 return nil 2409 } 2410 2411 func callingAppTraceProduces(arg1 string) error { 2412 cfg := future.DefaultStackPrinterConfig() 2413 cfg.TopOfStackFirst = false 2414 trace = txTrace.GetAppCallTrace(cfg) 2415 2416 data, err := loadResource(arg1) 2417 if err != nil { 2418 return err 2419 } 2420 if string(data) != trace { 2421 return fmt.Errorf("No matching trace: \n'%s'\nvs\n'%s'\n", string(data), trace) 2422 } 2423 return nil 2424 } 2425 2426 func aSourceMapJsonFile(srcMapJsonPath string) error { 2427 b, err := loadResource(srcMapJsonPath) 2428 if err != nil { 2429 return err 2430 } 2431 2432 ism := map[string]interface{}{} 2433 if err := json.Unmarshal(b, &ism); err != nil { 2434 return err 2435 } 2436 2437 sourceMap, err = logic.DecodeSourceMap(ism) 2438 2439 return err 2440 } 2441 2442 func theStringComposedOfPclineNumberEquals(expectedPcToLineString string) error { 2443 var buff []string 2444 for pc := 0; pc < len(sourceMap.PcToLine); pc++ { 2445 line := sourceMap.PcToLine[pc] 2446 buff = append(buff, fmt.Sprintf("%d:%d", pc, line)) 2447 } 2448 actualStr := strings.Join(buff, ";") 2449 if expectedPcToLineString != actualStr { 2450 return fmt.Errorf("Expected %s got %s", expectedPcToLineString, actualStr) 2451 } 2452 return nil 2453 } 2454 2455 func gettingTheLineAssociatedWithAPcEquals(strPc, strLine string) error { 2456 pc, _ := strconv.Atoi(strPc) 2457 expectedLine, _ := strconv.Atoi(strLine) 2458 2459 actualLine, ok := sourceMap.GetLineForPc(pc) 2460 if !ok { 2461 return fmt.Errorf("expected valid line, got !ok") 2462 } 2463 2464 if actualLine != expectedLine { 2465 return fmt.Errorf("expected %d got %d", expectedLine, actualLine) 2466 } 2467 2468 return nil 2469 } 2470 2471 func gettingTheLastPcAssociatedWithALineEquals(strLine, strPc string) error { 2472 expectedPc, _ := strconv.Atoi(strPc) 2473 line, _ := strconv.Atoi(strLine) 2474 2475 pcs := sourceMap.GetPcsForLine(line) 2476 actualPc := pcs[len(pcs)-1] 2477 2478 if actualPc != expectedPc { 2479 return fmt.Errorf("expected %d got %d", expectedPc, actualPc) 2480 } 2481 2482 return nil 2483 } 2484 2485 func iCompileATealProgramWithMappingEnabled(programPath string) error { 2486 fileContents, err := loadResource(programPath) 2487 if err != nil { 2488 return err 2489 } 2490 2491 result, err := aclv2.TealCompile(fileContents).Sourcemap(true).Do(context.Background()) 2492 if err != nil { 2493 return err 2494 } 2495 2496 if result.Sourcemap == nil { 2497 return fmt.Errorf("No source map returned") 2498 } 2499 2500 srcMapping = *result.Sourcemap 2501 return nil 2502 } 2503 2504 func theResultingSourceMapIsTheSameAsTheJson(expectedJsonPath string) error { 2505 2506 expectedJson, err := loadResource(expectedJsonPath) 2507 if err != nil { 2508 return err 2509 } 2510 2511 // Marshal the map to json then unmarshal it so we get alphabetic ordering 2512 expectedMap := map[string]interface{}{} 2513 err = json.Unmarshal(expectedJson, &expectedMap) 2514 if err != nil { 2515 return err 2516 } 2517 2518 expectedJson, err = json.Marshal(expectedMap) 2519 if err != nil { 2520 return err 2521 } 2522 2523 // Turn it back into a string 2524 actualJson, err := json.Marshal(srcMapping) 2525 if err != nil { 2526 return nil 2527 } 2528 2529 if !bytes.Equal(expectedJson, actualJson) { 2530 return fmt.Errorf("expected %s got %s", expectedJson, actualJson) 2531 } 2532 2533 return nil 2534 } 2535 2536 func takeB64encodedBytes(b64encodedBytes string) error { 2537 var err error 2538 seeminglyProgram, err = base64.StdEncoding.DecodeString(b64encodedBytes) 2539 if err != nil { 2540 return err 2541 } 2542 return nil 2543 } 2544 2545 func heuristicCheckOverBytes() error { 2546 _, sanityCheckError = crypto.MakeLogicSigAccountEscrowChecked(seeminglyProgram, nil) 2547 return nil 2548 } 2549 2550 func checkErrorIfMatching(errMsg string) error { 2551 if len(errMsg) == 0 { 2552 if sanityCheckError != nil { 2553 return fmt.Errorf("expected err message to be empty, but sanity check says %w", sanityCheckError) 2554 } 2555 } else { 2556 if sanityCheckError == nil || !strings.Contains(sanityCheckError.Error(), errMsg) { 2557 return fmt.Errorf("expected err to contain %s, but sanity check error not matching: %w", errMsg, sanityCheckError) 2558 } 2559 } 2560 return nil 2561 }