diff --git a/cmd/goal/application.go b/cmd/goal/application.go index 00a35eeac5..dba25af8d3 100644 --- a/cmd/goal/application.go +++ b/cmd/goal/application.go @@ -460,9 +460,8 @@ var createAppCmd = &cobra.Command{ reportErrorf("Cannot create application txn: %v", err) } - // Fill in note and lease - tx.Note = parseNoteField(cmd) - tx.Lease = parseLease(cmd) + // Fill in common fields. + applyCommonFields(&tx, cmd) // Fill in rounds, fee, etc. fv, lv, _, err := client.ComputeValidityRounds(firstValid, lastValid, numValidRounds) @@ -535,9 +534,8 @@ var updateAppCmd = &cobra.Command{ reportErrorf("Cannot create application txn: %v", err) } - // Fill in note and lease - tx.Note = parseNoteField(cmd) - tx.Lease = parseLease(cmd) + // Fill in common fields. + applyCommonFields(&tx, cmd) // Fill in rounds, fee, etc. fv, lv, _, err := client.ComputeValidityRounds(firstValid, lastValid, numValidRounds) @@ -605,9 +603,8 @@ var optInAppCmd = &cobra.Command{ reportErrorf("Cannot create application txn: %v", err) } - // Fill in note and lease - tx.Note = parseNoteField(cmd) - tx.Lease = parseLease(cmd) + // Fill in common fields. + applyCommonFields(&tx, cmd) // Fill in rounds, fee, etc. fv, lv, _, err := client.ComputeValidityRounds(firstValid, lastValid, numValidRounds) @@ -675,9 +672,8 @@ var closeOutAppCmd = &cobra.Command{ reportErrorf("Cannot create application txn: %v", err) } - // Fill in note and lease - tx.Note = parseNoteField(cmd) - tx.Lease = parseLease(cmd) + // Fill in common fields. + applyCommonFields(&tx, cmd) // Fill in rounds, fee, etc. fv, lv, _, err := client.ComputeValidityRounds(firstValid, lastValid, numValidRounds) @@ -745,9 +741,8 @@ var clearAppCmd = &cobra.Command{ reportErrorf("Cannot create application txn: %v", err) } - // Fill in note and lease - tx.Note = parseNoteField(cmd) - tx.Lease = parseLease(cmd) + // Fill in common fields. + applyCommonFields(&tx, cmd) // Fill in rounds, fee, etc. fv, lv, _, err := client.ComputeValidityRounds(firstValid, lastValid, numValidRounds) @@ -815,9 +810,8 @@ var callAppCmd = &cobra.Command{ reportErrorf("Cannot create application txn: %v", err) } - // Fill in note and lease - tx.Note = parseNoteField(cmd) - tx.Lease = parseLease(cmd) + // Fill in common fields. + applyCommonFields(&tx, cmd) // Fill in rounds, fee, etc. fv, lv, _, err := client.ComputeValidityRounds(firstValid, lastValid, numValidRounds) @@ -885,9 +879,8 @@ var deleteAppCmd = &cobra.Command{ reportErrorf("Cannot create application txn: %v", err) } - // Fill in note and lease - tx.Note = parseNoteField(cmd) - tx.Lease = parseLease(cmd) + // Fill in common fields. + applyCommonFields(&tx, cmd) // Fill in rounds, fee, etc. fv, lv, _, err := client.ComputeValidityRounds(firstValid, lastValid, numValidRounds) @@ -1376,9 +1369,8 @@ var methodAppCmd = &cobra.Command{ reportErrorf("Cannot create application txn: %v", err) } - // Fill in note and lease - appCallTxn.Note = parseNoteField(cmd) - appCallTxn.Lease = parseLease(cmd) + // Fill in common fields. + applyCommonFields(&appCallTxn, cmd) // Fill in rounds, fee, etc. fv, lv, _, err := client.ComputeValidityRounds(firstValid, lastValid, numValidRounds) diff --git a/cmd/goal/asset.go b/cmd/goal/asset.go index 97606c4cba..ed8fc47bd7 100644 --- a/cmd/goal/asset.go +++ b/cmd/goal/asset.go @@ -288,8 +288,8 @@ var createAssetCmd = &cobra.Command{ reportErrorf("Cannot construct transaction: %s", err) } - tx.Note = parseNoteField(cmd) - tx.Lease = parseLease(cmd) + // Fill in common fields. + applyCommonFields(&tx, cmd) fv, lv, _, err := client.ComputeValidityRounds(firstValid, lastValid, numValidRounds) if err != nil { @@ -367,8 +367,8 @@ var destroyAssetCmd = &cobra.Command{ reportErrorf("Cannot construct transaction: %s", err) } - tx.Note = parseNoteField(cmd) - tx.Lease = parseLease(cmd) + // Fill in common fields. + applyCommonFields(&tx, cmd) firstValid, lastValid, _, err = client.ComputeValidityRounds(firstValid, lastValid, numValidRounds) if err != nil { @@ -460,8 +460,8 @@ var configAssetCmd = &cobra.Command{ reportErrorf("Cannot construct transaction: %s", err) } - tx.Note = parseNoteField(cmd) - tx.Lease = parseLease(cmd) + // Fill in common fields. + applyCommonFields(&tx, cmd) firstValid, lastValid, _, err = client.ComputeValidityRounds(firstValid, lastValid, numValidRounds) if err != nil { @@ -545,8 +545,8 @@ var sendAssetCmd = &cobra.Command{ reportErrorf("Cannot construct transaction: %s", err) } - tx.Note = parseNoteField(cmd) - tx.Lease = parseLease(cmd) + // Fill in common fields. + applyCommonFields(&tx, cmd) firstValid, lastValid, _, err = client.ComputeValidityRounds(firstValid, lastValid, numValidRounds) if err != nil { @@ -616,8 +616,8 @@ var freezeAssetCmd = &cobra.Command{ reportErrorf("Cannot construct transaction: %s", err) } - tx.Note = parseNoteField(cmd) - tx.Lease = parseLease(cmd) + // Fill in common fields. + applyCommonFields(&tx, cmd) firstValid, lastValid, _, err = client.ComputeValidityRounds(firstValid, lastValid, numValidRounds) if err != nil { @@ -703,8 +703,8 @@ var optinAssetCmd = &cobra.Command{ reportErrorf("Cannot construct transaction: %s", err) } - tx.Note = parseNoteField(cmd) - tx.Lease = parseLease(cmd) + // Fill in common fields. + applyCommonFields(&tx, cmd) firstValid, lastValid, _, err = client.ComputeValidityRounds(firstValid, lastValid, numValidRounds) if err != nil { diff --git a/cmd/goal/clerk.go b/cmd/goal/clerk.go index e467064ee1..46f93d658a 100644 --- a/cmd/goal/clerk.go +++ b/cmd/goal/clerk.go @@ -90,6 +90,7 @@ func init() { sendCmd.Flags().StringSliceVar(&argB64Strings, "argb64", nil, "base64 encoded args to pass to transaction logic") sendCmd.Flags().StringVarP(&logicSigFile, "logic-sig", "L", "", "LogicSig to apply to transaction") sendCmd.Flags().StringVar(&msigParams, "msig-params", "", "Multisig preimage parameters - [threshold] [Address 1] [Address 2] ...\nUsed to add the necessary fields in case the account was rekeyed to a multisig account") + sendCmd.MarkFlagRequired("to") sendCmd.MarkFlagRequired("amount") @@ -269,6 +270,15 @@ func getProgramArgs() [][]byte { return getB64Args(argB64Strings) } +func applyCommonFields(txn *transactions.Transaction, cmd *cobra.Command) { + // Parse notes and lease fields + txn.Note = parseNoteField(cmd) + txn.Lease = parseLease(cmd) + // DevMode fields: the default values would be ignored. + txn.DevMode.SkipValidation = skipValidation + txn.DevMode.SetNextBlockTime = setBlockTime +} + func parseNoteField(cmd *cobra.Command) []byte { if cmd.Flags().Changed("noteb64") { noteBytes, err := base64.StdEncoding.DecodeString(noteBase64) @@ -361,10 +371,6 @@ var sendCmd = &cobra.Command{ } toAddressResolved := accountList.getAddressByName(toAddress) - // Parse notes and lease fields - noteBytes := parseNoteField(cmd) - leaseBytes := parseLease(cmd) - // If closing an account, resolve that address as well var closeToAddressResolved string if closeToAddress != "" { @@ -387,8 +393,8 @@ var sendCmd = &cobra.Command{ reportErrorf(err.Error()) } payment, err := client.ConstructPayment( - fromAddressResolved, toAddressResolved, fee, amount, noteBytes, closeToAddressResolved, - leaseBytes, basics.Round(firstValid), basics.Round(lastValid), + fromAddressResolved, toAddressResolved, fee, amount, nil, closeToAddressResolved, + [32]byte{}, basics.Round(firstValid), basics.Round(lastValid), ) if err != nil { reportErrorf(errorConstructingTX, err) @@ -397,6 +403,9 @@ var sendCmd = &cobra.Command{ payment.RekeyTo = rekeyTo } + // Fill in common fields. + applyCommonFields(&payment, cmd) + // ConstructPayment fills in the suggested fee when fee=0. But if the user actually used --fee=0 on the // commandline, we ought to do what they asked (especially now that zero or low fees make sense in // combination with other txns that cover the groups's fee. diff --git a/cmd/goal/common.go b/cmd/goal/common.go index 3c4189dbf1..4e60d6ace3 100644 --- a/cmd/goal/common.go +++ b/cmd/goal/common.go @@ -49,6 +49,10 @@ var ( noWaitAfterSend bool dumpForDryrun bool dumpForDryrunAccts []string + + // devmode txn send options + setBlockTime int64 + skipValidation bool ) var dumpForDryrunFormat cmdutil.CobraStringValue = *cmdutil.MakeCobraStringValue("json", []string{"msgp"}) @@ -68,4 +72,8 @@ func addTxnFlags(cmd *cobra.Command) { cmd.Flags().Var(&dumpForDryrunFormat, "dryrun-dump-format", "Dryrun dump format: "+dumpForDryrunFormat.AllowedString()) cmd.Flags().StringSliceVar(&dumpForDryrunAccts, "dryrun-accounts", nil, "additional accounts to include into dryrun request obj") cmd.Flags().StringVarP(&signerAddress, "signer", "S", "", "Address of key to sign with, if different from transaction \"from\" address due to rekeying") + + // devmode options + cmd.Flags().Int64Var(&setBlockTime, "set-block-time", 0, "Add 'set_block_time: ' field to the txn.") + cmd.Flags().BoolVar(&skipValidation, "skip-validation", false, "Add 'skip_validation: true' field to the txn.") } diff --git a/cmd/goal/defaultNetworkTemplate.json b/cmd/goal/defaultNetworkTemplate.json new file mode 100644 index 0000000000..2a3bafdefb --- /dev/null +++ b/cmd/goal/defaultNetworkTemplate.json @@ -0,0 +1,45 @@ +{ + "Genesis": { + "NetworkName": "", + "FirstPartKeyRound": 0, + "LastPartKeyRound": 30000, + "Wallets": [ + { + "Name": "Wallet1", + "Stake": 40, + "Online": true + }, + { + "Name": "Wallet2", + "Stake": 40, + "Online": true + }, + { + "Name": "Wallet3", + "Stake": 20, + "Online": false + } + ] + }, + "Nodes": [ + { + "Name": "Node", + "IsRelay": false, + "Wallets": [ + { + "Name": "Wallet1", + "ParticipationOnly": false + }, + { + "Name": "Wallet2", + "ParticipationOnly": false + }, + { + "Name": "Wallet3", + "ParticipationOnly": false + } + ] + } + ] +} + diff --git a/cmd/goal/interact.go b/cmd/goal/interact.go index e578713d29..dffceddc87 100644 --- a/cmd/goal/interact.go +++ b/cmd/goal/interact.go @@ -591,9 +591,8 @@ var appExecuteCmd = &cobra.Command{ reportErrorf("Cannot create application txn: %v", err) } - // Fill in note and lease - tx.Note = parseNoteField(cmd) - tx.Lease = parseLease(cmd) + // Fill in common fields. + applyCommonFields(&tx, cmd) // Fill in rounds, fee, etc. fv, lv, _, err := client.ComputeValidityRounds(firstValid, lastValid, numValidRounds) diff --git a/cmd/goal/network.go b/cmd/goal/network.go index 35565fb6fa..078a6d9503 100644 --- a/cmd/goal/network.go +++ b/cmd/goal/network.go @@ -17,9 +17,12 @@ package main import ( + _ "embed" "fmt" + "io" "os" "path/filepath" + "strings" "github.com/spf13/cobra" @@ -35,6 +38,7 @@ var startNode string var noImportKeys bool var noClean bool var devModeOverride bool +var startOnCreation bool func init() { networkCmd.AddCommand(networkCreateCmd) @@ -43,10 +47,10 @@ func init() { networkCreateCmd.Flags().StringVarP(&networkName, "network", "n", "", "Specify the name to use for the private network") networkCreateCmd.Flags().StringVarP(&networkTemplateFile, "template", "t", "", "Specify the path to the template file for the network") - networkCreateCmd.MarkFlagRequired("template") networkCreateCmd.Flags().BoolVarP(&noImportKeys, "noimportkeys", "K", false, "Do not import root keys when creating the network (by default will import)") networkCreateCmd.Flags().BoolVar(&noClean, "noclean", false, "Prevents auto-cleanup on error - for diagnosing problems") networkCreateCmd.Flags().BoolVar(&devModeOverride, "devMode", false, "Forces the configuration to enable DevMode, returns an error if the template is not compatible with DevMode.") + networkCreateCmd.Flags().BoolVarP(&startOnCreation, "start", "s", false, "Automatically start the network after creating it.") networkStartCmd.Flags().StringVarP(&startNode, "node", "n", "", "Specify the name of a specific node to start") @@ -70,6 +74,9 @@ The basic idea is that we create one or more data directories and wallets to for }, } +//go:embed defaultNetworkTemplate.json +var defaultNetworkTemplate string + var networkCreateCmd = &cobra.Command{ Use: "create", Short: "Create a private named network from a template", @@ -80,10 +87,25 @@ var networkCreateCmd = &cobra.Command{ if err != nil { panic(err) } - networkTemplateFile, err := filepath.Abs(networkTemplateFile) - if err != nil { - panic(err) + + var templateReader io.Reader + + if networkTemplateFile == "" { + templateReader = strings.NewReader(defaultNetworkTemplate) + } else { + networkTemplateFile, err = filepath.Abs(networkTemplateFile) + if err != nil { + panic(err) + } + file, err := os.Open(networkTemplateFile) + if err != nil { + reportErrorf(errorCreateNetwork, err) + } + + defer file.Close() + templateReader = file } + // Make sure target directory does not exist or is empty if util.FileExists(networkRootDir) && !util.IsEmpty(networkRootDir) { reportErrorf(infoNetworkAlreadyExists, networkRootDir) @@ -101,7 +123,7 @@ var networkCreateCmd = &cobra.Command{ consensus, _ = config.PreloadConfigurableConsensusProtocols(dataDir) } - network, err := netdeploy.CreateNetworkFromTemplate(networkName, networkRootDir, networkTemplateFile, binDir, !noImportKeys, nil, consensus, devModeOverride) + network, err := netdeploy.CreateNetworkFromTemplate(networkName, networkRootDir, templateReader, binDir, !noImportKeys, nil, consensus, devModeOverride) if err != nil { if noClean { reportInfof(" ** failed ** - Preserving network rootdir '%s'", networkRootDir) @@ -112,6 +134,16 @@ var networkCreateCmd = &cobra.Command{ } reportInfof(infoNetworkCreated, network.Name(), networkRootDir) + + if startOnCreation { + fmt.Printf("startOnCreation true\n") + network, binDir := getNetworkAndBinDir() + err := network.Start(binDir, false) + if err != nil { + reportErrorf(errorStartingNetwork, err) + } + reportInfof(infoNetworkStarted, networkRootDir) + } }, } diff --git a/config/consensus.go b/config/consensus.go index 4f1ac86736..4866c03767 100644 --- a/config/consensus.go +++ b/config/consensus.go @@ -483,6 +483,9 @@ type ConsensusParams struct { // the rewardsLevel, but the rewardsLevel has no meaning because the account // has fewer than RewardUnit algos. UnfundedSenders bool + + // DevMode is a special consensus parameter that enables developer features. + DevMode bool } // PaysetCommitType enumerates possible ways for the block header to commit to @@ -1306,5 +1309,4 @@ func init() { for _, p := range Consensus { checkSetAllocBounds(p) } - } diff --git a/data/transactions/msgp_gen.go b/data/transactions/msgp_gen.go index 641e541c7b..a7b82fea0e 100644 --- a/data/transactions/msgp_gen.go +++ b/data/transactions/msgp_gen.go @@ -61,6 +61,14 @@ import ( // |-----> (*) Msgsize // |-----> (*) MsgIsZero // +// DevMode +// |-----> (*) MarshalMsg +// |-----> (*) CanMarshalMsg +// |-----> (*) UnmarshalMsg +// |-----> (*) CanUnmarshalMsg +// |-----> (*) Msgsize +// |-----> (*) MsgIsZero +// // EvalDelta // |-----> (*) MarshalMsg // |-----> (*) CanMarshalMsg @@ -1871,6 +1879,135 @@ func (z *BoxRef) MsgIsZero() bool { return ((*z).Index == 0) && (len((*z).Name) == 0) } +// MarshalMsg implements msgp.Marshaler +func (z *DevMode) MarshalMsg(b []byte) (o []byte) { + o = msgp.Require(b, z.Msgsize()) + // omitempty: check for empty values + zb0001Len := uint32(2) + var zb0001Mask uint8 /* 3 bits */ + if (*z).SetNextBlockTime == 0 { + zb0001Len-- + zb0001Mask |= 0x2 + } + if (*z).SkipValidation == false { + zb0001Len-- + zb0001Mask |= 0x4 + } + // variable map header, size zb0001Len + o = append(o, 0x80|uint8(zb0001Len)) + if zb0001Len != 0 { + if (zb0001Mask & 0x2) == 0 { // if not empty + // string "set_next_block_time" + o = append(o, 0xb3, 0x73, 0x65, 0x74, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65) + o = msgp.AppendInt64(o, (*z).SetNextBlockTime) + } + if (zb0001Mask & 0x4) == 0 { // if not empty + // string "skip_validation" + o = append(o, 0xaf, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e) + o = msgp.AppendBool(o, (*z).SkipValidation) + } + } + return +} + +func (_ *DevMode) CanMarshalMsg(z interface{}) bool { + _, ok := (z).(*DevMode) + return ok +} + +// UnmarshalMsg implements msgp.Unmarshaler +func (z *DevMode) UnmarshalMsg(bts []byte) (o []byte, err error) { + var field []byte + _ = field + var zb0001 int + var zb0002 bool + zb0001, zb0002, bts, err = msgp.ReadMapHeaderBytes(bts) + if _, ok := err.(msgp.TypeError); ok { + zb0001, zb0002, bts, err = msgp.ReadArrayHeaderBytes(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + if zb0001 > 0 { + zb0001-- + (*z).SkipValidation, bts, err = msgp.ReadBoolBytes(bts) + if err != nil { + err = msgp.WrapError(err, "struct-from-array", "SkipValidation") + return + } + } + if zb0001 > 0 { + zb0001-- + (*z).SetNextBlockTime, bts, err = msgp.ReadInt64Bytes(bts) + if err != nil { + err = msgp.WrapError(err, "struct-from-array", "SetNextBlockTime") + return + } + } + if zb0001 > 0 { + err = msgp.ErrTooManyArrayFields(zb0001) + if err != nil { + err = msgp.WrapError(err, "struct-from-array") + return + } + } + } else { + if err != nil { + err = msgp.WrapError(err) + return + } + if zb0002 { + (*z) = DevMode{} + } + for zb0001 > 0 { + zb0001-- + field, bts, err = msgp.ReadMapKeyZC(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + switch string(field) { + case "skip_validation": + (*z).SkipValidation, bts, err = msgp.ReadBoolBytes(bts) + if err != nil { + err = msgp.WrapError(err, "SkipValidation") + return + } + case "set_next_block_time": + (*z).SetNextBlockTime, bts, err = msgp.ReadInt64Bytes(bts) + if err != nil { + err = msgp.WrapError(err, "SetNextBlockTime") + return + } + default: + err = msgp.ErrNoField(string(field)) + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + } + o = bts + return +} + +func (_ *DevMode) CanUnmarshalMsg(z interface{}) bool { + _, ok := (z).(*DevMode) + return ok +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z *DevMode) Msgsize() (s int) { + s = 1 + 16 + msgp.BoolSize + 20 + msgp.Int64Size + return +} + +// MsgIsZero returns whether this is a zero value +func (z *DevMode) MsgIsZero() bool { + return ((*z).SkipValidation == false) && ((*z).SetNextBlockTime == 0) +} + // MarshalMsg implements msgp.Marshaler func (z *EvalDelta) MarshalMsg(b []byte) (o []byte) { o = msgp.Require(b, z.Msgsize()) @@ -4509,8 +4646,8 @@ func (z *StateProofTxnFields) MsgIsZero() bool { func (z *Transaction) MarshalMsg(b []byte) (o []byte) { o = msgp.Require(b, z.Msgsize()) // omitempty: check for empty values - zb0007Len := uint32(46) - var zb0007Mask uint64 /* 55 bits */ + zb0007Len := uint32(47) + var zb0007Mask uint64 /* 56 bits */ if (*z).AssetTransferTxnFields.AssetAmount == 0 { zb0007Len-- zb0007Mask |= 0x200 @@ -4595,106 +4732,110 @@ func (z *Transaction) MarshalMsg(b []byte) (o []byte) { zb0007Len-- zb0007Mask |= 0x20000000 } - if (*z).AssetFreezeTxnFields.FreezeAccount.MsgIsZero() { + if ((*z).DevMode.SkipValidation == false) && ((*z).DevMode.SetNextBlockTime == 0) { zb0007Len-- zb0007Mask |= 0x40000000 } - if (*z).AssetFreezeTxnFields.FreezeAsset.MsgIsZero() { + if (*z).AssetFreezeTxnFields.FreezeAccount.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x80000000 } - if (*z).Header.Fee.MsgIsZero() { + if (*z).AssetFreezeTxnFields.FreezeAsset.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x100000000 } - if (*z).Header.FirstValid.MsgIsZero() { + if (*z).Header.Fee.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x200000000 } - if (*z).Header.GenesisID == "" { + if (*z).Header.FirstValid.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x400000000 } - if (*z).Header.GenesisHash.MsgIsZero() { + if (*z).Header.GenesisID == "" { zb0007Len-- zb0007Mask |= 0x800000000 } - if (*z).Header.Group.MsgIsZero() { + if (*z).Header.GenesisHash.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x1000000000 } - if (*z).Header.LastValid.MsgIsZero() { + if (*z).Header.Group.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x2000000000 } - if (*z).Header.Lease == ([32]byte{}) { + if (*z).Header.LastValid.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x4000000000 } - if (*z).KeyregTxnFields.Nonparticipation == false { + if (*z).Header.Lease == ([32]byte{}) { zb0007Len-- zb0007Mask |= 0x8000000000 } - if len((*z).Header.Note) == 0 { + if (*z).KeyregTxnFields.Nonparticipation == false { zb0007Len-- zb0007Mask |= 0x10000000000 } - if (*z).PaymentTxnFields.Receiver.MsgIsZero() { + if len((*z).Header.Note) == 0 { zb0007Len-- zb0007Mask |= 0x20000000000 } - if (*z).Header.RekeyTo.MsgIsZero() { + if (*z).PaymentTxnFields.Receiver.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x40000000000 } - if (*z).KeyregTxnFields.SelectionPK.MsgIsZero() { + if (*z).Header.RekeyTo.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x80000000000 } - if (*z).Header.Sender.MsgIsZero() { + if (*z).KeyregTxnFields.SelectionPK.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x100000000000 } - if (*z).StateProofTxnFields.StateProof.MsgIsZero() { + if (*z).Header.Sender.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x200000000000 } - if (*z).StateProofTxnFields.Message.MsgIsZero() { + if (*z).StateProofTxnFields.StateProof.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x400000000000 } - if (*z).KeyregTxnFields.StateProofPK.MsgIsZero() { + if (*z).StateProofTxnFields.Message.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x800000000000 } - if (*z).StateProofTxnFields.StateProofType.MsgIsZero() { + if (*z).KeyregTxnFields.StateProofPK.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x1000000000000 } - if (*z).Type.MsgIsZero() { + if (*z).StateProofTxnFields.StateProofType.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x2000000000000 } - if (*z).KeyregTxnFields.VoteFirst.MsgIsZero() { + if (*z).Type.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x4000000000000 } - if (*z).KeyregTxnFields.VoteKeyDilution == 0 { + if (*z).KeyregTxnFields.VoteFirst.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x8000000000000 } - if (*z).KeyregTxnFields.VotePK.MsgIsZero() { + if (*z).KeyregTxnFields.VoteKeyDilution == 0 { zb0007Len-- zb0007Mask |= 0x10000000000000 } - if (*z).KeyregTxnFields.VoteLast.MsgIsZero() { + if (*z).KeyregTxnFields.VotePK.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x20000000000000 } - if (*z).AssetTransferTxnFields.XferAsset.MsgIsZero() { + if (*z).KeyregTxnFields.VoteLast.MsgIsZero() { zb0007Len-- zb0007Mask |= 0x40000000000000 } + if (*z).AssetTransferTxnFields.XferAsset.MsgIsZero() { + zb0007Len-- + zb0007Mask |= 0x80000000000000 + } // variable map header, size zb0007Len o = msgp.AppendMapHeader(o, zb0007Len) if zb0007Len != 0 { @@ -4861,126 +5002,153 @@ func (z *Transaction) MarshalMsg(b []byte) (o []byte) { o = (*z).PaymentTxnFields.CloseRemainderTo.MarshalMsg(o) } if (zb0007Mask & 0x40000000) == 0 { // if not empty + // string "dev_mode_options" + o = append(o, 0xb0, 0x64, 0x65, 0x76, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73) + // omitempty: check for empty values + zb0009Len := uint32(2) + var zb0009Mask uint8 /* 3 bits */ + if (*z).DevMode.SetNextBlockTime == 0 { + zb0009Len-- + zb0009Mask |= 0x2 + } + if (*z).DevMode.SkipValidation == false { + zb0009Len-- + zb0009Mask |= 0x4 + } + // variable map header, size zb0009Len + o = append(o, 0x80|uint8(zb0009Len)) + if (zb0009Mask & 0x2) == 0 { // if not empty + // string "set_next_block_time" + o = append(o, 0xb3, 0x73, 0x65, 0x74, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65) + o = msgp.AppendInt64(o, (*z).DevMode.SetNextBlockTime) + } + if (zb0009Mask & 0x4) == 0 { // if not empty + // string "skip_validation" + o = append(o, 0xaf, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e) + o = msgp.AppendBool(o, (*z).DevMode.SkipValidation) + } + } + if (zb0007Mask & 0x80000000) == 0 { // if not empty // string "fadd" o = append(o, 0xa4, 0x66, 0x61, 0x64, 0x64) o = (*z).AssetFreezeTxnFields.FreezeAccount.MarshalMsg(o) } - if (zb0007Mask & 0x80000000) == 0 { // if not empty + if (zb0007Mask & 0x100000000) == 0 { // if not empty // string "faid" o = append(o, 0xa4, 0x66, 0x61, 0x69, 0x64) o = (*z).AssetFreezeTxnFields.FreezeAsset.MarshalMsg(o) } - if (zb0007Mask & 0x100000000) == 0 { // if not empty + if (zb0007Mask & 0x200000000) == 0 { // if not empty // string "fee" o = append(o, 0xa3, 0x66, 0x65, 0x65) o = (*z).Header.Fee.MarshalMsg(o) } - if (zb0007Mask & 0x200000000) == 0 { // if not empty + if (zb0007Mask & 0x400000000) == 0 { // if not empty // string "fv" o = append(o, 0xa2, 0x66, 0x76) o = (*z).Header.FirstValid.MarshalMsg(o) } - if (zb0007Mask & 0x400000000) == 0 { // if not empty + if (zb0007Mask & 0x800000000) == 0 { // if not empty // string "gen" o = append(o, 0xa3, 0x67, 0x65, 0x6e) o = msgp.AppendString(o, (*z).Header.GenesisID) } - if (zb0007Mask & 0x800000000) == 0 { // if not empty + if (zb0007Mask & 0x1000000000) == 0 { // if not empty // string "gh" o = append(o, 0xa2, 0x67, 0x68) o = (*z).Header.GenesisHash.MarshalMsg(o) } - if (zb0007Mask & 0x1000000000) == 0 { // if not empty + if (zb0007Mask & 0x2000000000) == 0 { // if not empty // string "grp" o = append(o, 0xa3, 0x67, 0x72, 0x70) o = (*z).Header.Group.MarshalMsg(o) } - if (zb0007Mask & 0x2000000000) == 0 { // if not empty + if (zb0007Mask & 0x4000000000) == 0 { // if not empty // string "lv" o = append(o, 0xa2, 0x6c, 0x76) o = (*z).Header.LastValid.MarshalMsg(o) } - if (zb0007Mask & 0x4000000000) == 0 { // if not empty + if (zb0007Mask & 0x8000000000) == 0 { // if not empty // string "lx" o = append(o, 0xa2, 0x6c, 0x78) o = msgp.AppendBytes(o, ((*z).Header.Lease)[:]) } - if (zb0007Mask & 0x8000000000) == 0 { // if not empty + if (zb0007Mask & 0x10000000000) == 0 { // if not empty // string "nonpart" o = append(o, 0xa7, 0x6e, 0x6f, 0x6e, 0x70, 0x61, 0x72, 0x74) o = msgp.AppendBool(o, (*z).KeyregTxnFields.Nonparticipation) } - if (zb0007Mask & 0x10000000000) == 0 { // if not empty + if (zb0007Mask & 0x20000000000) == 0 { // if not empty // string "note" o = append(o, 0xa4, 0x6e, 0x6f, 0x74, 0x65) o = msgp.AppendBytes(o, (*z).Header.Note) } - if (zb0007Mask & 0x20000000000) == 0 { // if not empty + if (zb0007Mask & 0x40000000000) == 0 { // if not empty // string "rcv" o = append(o, 0xa3, 0x72, 0x63, 0x76) o = (*z).PaymentTxnFields.Receiver.MarshalMsg(o) } - if (zb0007Mask & 0x40000000000) == 0 { // if not empty + if (zb0007Mask & 0x80000000000) == 0 { // if not empty // string "rekey" o = append(o, 0xa5, 0x72, 0x65, 0x6b, 0x65, 0x79) o = (*z).Header.RekeyTo.MarshalMsg(o) } - if (zb0007Mask & 0x80000000000) == 0 { // if not empty + if (zb0007Mask & 0x100000000000) == 0 { // if not empty // string "selkey" o = append(o, 0xa6, 0x73, 0x65, 0x6c, 0x6b, 0x65, 0x79) o = (*z).KeyregTxnFields.SelectionPK.MarshalMsg(o) } - if (zb0007Mask & 0x100000000000) == 0 { // if not empty + if (zb0007Mask & 0x200000000000) == 0 { // if not empty // string "snd" o = append(o, 0xa3, 0x73, 0x6e, 0x64) o = (*z).Header.Sender.MarshalMsg(o) } - if (zb0007Mask & 0x200000000000) == 0 { // if not empty + if (zb0007Mask & 0x400000000000) == 0 { // if not empty // string "sp" o = append(o, 0xa2, 0x73, 0x70) o = (*z).StateProofTxnFields.StateProof.MarshalMsg(o) } - if (zb0007Mask & 0x400000000000) == 0 { // if not empty + if (zb0007Mask & 0x800000000000) == 0 { // if not empty // string "spmsg" o = append(o, 0xa5, 0x73, 0x70, 0x6d, 0x73, 0x67) o = (*z).StateProofTxnFields.Message.MarshalMsg(o) } - if (zb0007Mask & 0x800000000000) == 0 { // if not empty + if (zb0007Mask & 0x1000000000000) == 0 { // if not empty // string "sprfkey" o = append(o, 0xa7, 0x73, 0x70, 0x72, 0x66, 0x6b, 0x65, 0x79) o = (*z).KeyregTxnFields.StateProofPK.MarshalMsg(o) } - if (zb0007Mask & 0x1000000000000) == 0 { // if not empty + if (zb0007Mask & 0x2000000000000) == 0 { // if not empty // string "sptype" o = append(o, 0xa6, 0x73, 0x70, 0x74, 0x79, 0x70, 0x65) o = (*z).StateProofTxnFields.StateProofType.MarshalMsg(o) } - if (zb0007Mask & 0x2000000000000) == 0 { // if not empty + if (zb0007Mask & 0x4000000000000) == 0 { // if not empty // string "type" o = append(o, 0xa4, 0x74, 0x79, 0x70, 0x65) o = (*z).Type.MarshalMsg(o) } - if (zb0007Mask & 0x4000000000000) == 0 { // if not empty + if (zb0007Mask & 0x8000000000000) == 0 { // if not empty // string "votefst" o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x66, 0x73, 0x74) o = (*z).KeyregTxnFields.VoteFirst.MarshalMsg(o) } - if (zb0007Mask & 0x8000000000000) == 0 { // if not empty + if (zb0007Mask & 0x10000000000000) == 0 { // if not empty // string "votekd" o = append(o, 0xa6, 0x76, 0x6f, 0x74, 0x65, 0x6b, 0x64) o = msgp.AppendUint64(o, (*z).KeyregTxnFields.VoteKeyDilution) } - if (zb0007Mask & 0x10000000000000) == 0 { // if not empty + if (zb0007Mask & 0x20000000000000) == 0 { // if not empty // string "votekey" o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x6b, 0x65, 0x79) o = (*z).KeyregTxnFields.VotePK.MarshalMsg(o) } - if (zb0007Mask & 0x20000000000000) == 0 { // if not empty + if (zb0007Mask & 0x40000000000000) == 0 { // if not empty // string "votelst" o = append(o, 0xa7, 0x76, 0x6f, 0x74, 0x65, 0x6c, 0x73, 0x74) o = (*z).KeyregTxnFields.VoteLast.MarshalMsg(o) } - if (zb0007Mask & 0x40000000000000) == 0 { // if not empty + if (zb0007Mask & 0x80000000000000) == 0 { // if not empty // string "xaid" o = append(o, 0xa4, 0x78, 0x61, 0x69, 0x64) o = (*z).AssetTransferTxnFields.XferAsset.MarshalMsg(o) @@ -5015,6 +5183,78 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { return } } + if zb0007 > 0 { + zb0007-- + var zb0009 int + var zb0010 bool + zb0009, zb0010, bts, err = msgp.ReadMapHeaderBytes(bts) + if _, ok := err.(msgp.TypeError); ok { + zb0009, zb0010, bts, err = msgp.ReadArrayHeaderBytes(bts) + if err != nil { + err = msgp.WrapError(err, "struct-from-array", "DevMode") + return + } + if zb0009 > 0 { + zb0009-- + (*z).DevMode.SkipValidation, bts, err = msgp.ReadBoolBytes(bts) + if err != nil { + err = msgp.WrapError(err, "struct-from-array", "DevMode", "struct-from-array", "SkipValidation") + return + } + } + if zb0009 > 0 { + zb0009-- + (*z).DevMode.SetNextBlockTime, bts, err = msgp.ReadInt64Bytes(bts) + if err != nil { + err = msgp.WrapError(err, "struct-from-array", "DevMode", "struct-from-array", "SetNextBlockTime") + return + } + } + if zb0009 > 0 { + err = msgp.ErrTooManyArrayFields(zb0009) + if err != nil { + err = msgp.WrapError(err, "struct-from-array", "DevMode", "struct-from-array") + return + } + } + } else { + if err != nil { + err = msgp.WrapError(err, "struct-from-array", "DevMode") + return + } + if zb0010 { + (*z).DevMode = DevMode{} + } + for zb0009 > 0 { + zb0009-- + field, bts, err = msgp.ReadMapKeyZC(bts) + if err != nil { + err = msgp.WrapError(err, "struct-from-array", "DevMode") + return + } + switch string(field) { + case "skip_validation": + (*z).DevMode.SkipValidation, bts, err = msgp.ReadBoolBytes(bts) + if err != nil { + err = msgp.WrapError(err, "struct-from-array", "DevMode", "SkipValidation") + return + } + case "set_next_block_time": + (*z).DevMode.SetNextBlockTime, bts, err = msgp.ReadInt64Bytes(bts) + if err != nil { + err = msgp.WrapError(err, "struct-from-array", "DevMode", "SetNextBlockTime") + return + } + default: + err = msgp.ErrNoField(string(field)) + if err != nil { + err = msgp.WrapError(err, "struct-from-array", "DevMode") + return + } + } + } + } + } if zb0007 > 0 { zb0007-- bts, err = (*z).Header.Sender.UnmarshalMsg(bts) @@ -5049,14 +5289,14 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { } if zb0007 > 0 { zb0007-- - var zb0009 int - zb0009, err = msgp.ReadBytesBytesHeader(bts) + var zb0011 int + zb0011, err = msgp.ReadBytesBytesHeader(bts) if err != nil { err = msgp.WrapError(err, "struct-from-array", "Note") return } - if zb0009 > config.MaxTxnNoteBytes { - err = msgp.ErrOverflow(uint64(zb0009), uint64(config.MaxTxnNoteBytes)) + if zb0011 > config.MaxTxnNoteBytes { + err = msgp.ErrOverflow(uint64(zb0011), uint64(config.MaxTxnNoteBytes)) return } (*z).Header.Note, bts, err = msgp.ReadBytesBytes(bts, (*z).Header.Note) @@ -5276,35 +5516,35 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { if zb0007 > 0 { zb0007-- { - var zb0010 uint64 - zb0010, bts, err = msgp.ReadUint64Bytes(bts) + var zb0012 uint64 + zb0012, bts, err = msgp.ReadUint64Bytes(bts) if err != nil { err = msgp.WrapError(err, "struct-from-array", "OnCompletion") return } - (*z).ApplicationCallTxnFields.OnCompletion = OnCompletion(zb0010) + (*z).ApplicationCallTxnFields.OnCompletion = OnCompletion(zb0012) } } if zb0007 > 0 { zb0007-- - var zb0011 int - var zb0012 bool - zb0011, zb0012, bts, err = msgp.ReadArrayHeaderBytes(bts) + var zb0013 int + var zb0014 bool + zb0013, zb0014, bts, err = msgp.ReadArrayHeaderBytes(bts) if err != nil { err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs") return } - if zb0011 > encodedMaxApplicationArgs { - err = msgp.ErrOverflow(uint64(zb0011), uint64(encodedMaxApplicationArgs)) + if zb0013 > encodedMaxApplicationArgs { + err = msgp.ErrOverflow(uint64(zb0013), uint64(encodedMaxApplicationArgs)) err = msgp.WrapError(err, "struct-from-array", "ApplicationArgs") return } - if zb0012 { + if zb0014 { (*z).ApplicationCallTxnFields.ApplicationArgs = nil - } else if (*z).ApplicationCallTxnFields.ApplicationArgs != nil && cap((*z).ApplicationCallTxnFields.ApplicationArgs) >= zb0011 { - (*z).ApplicationCallTxnFields.ApplicationArgs = ((*z).ApplicationCallTxnFields.ApplicationArgs)[:zb0011] + } else if (*z).ApplicationCallTxnFields.ApplicationArgs != nil && cap((*z).ApplicationCallTxnFields.ApplicationArgs) >= zb0013 { + (*z).ApplicationCallTxnFields.ApplicationArgs = ((*z).ApplicationCallTxnFields.ApplicationArgs)[:zb0013] } else { - (*z).ApplicationCallTxnFields.ApplicationArgs = make([][]byte, zb0011) + (*z).ApplicationCallTxnFields.ApplicationArgs = make([][]byte, zb0013) } for zb0002 := range (*z).ApplicationCallTxnFields.ApplicationArgs { (*z).ApplicationCallTxnFields.ApplicationArgs[zb0002], bts, err = msgp.ReadBytesBytes(bts, (*z).ApplicationCallTxnFields.ApplicationArgs[zb0002]) @@ -5316,24 +5556,24 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { } if zb0007 > 0 { zb0007-- - var zb0013 int - var zb0014 bool - zb0013, zb0014, bts, err = msgp.ReadArrayHeaderBytes(bts) + var zb0015 int + var zb0016 bool + zb0015, zb0016, bts, err = msgp.ReadArrayHeaderBytes(bts) if err != nil { err = msgp.WrapError(err, "struct-from-array", "Accounts") return } - if zb0013 > encodedMaxAccounts { - err = msgp.ErrOverflow(uint64(zb0013), uint64(encodedMaxAccounts)) + if zb0015 > encodedMaxAccounts { + err = msgp.ErrOverflow(uint64(zb0015), uint64(encodedMaxAccounts)) err = msgp.WrapError(err, "struct-from-array", "Accounts") return } - if zb0014 { + if zb0016 { (*z).ApplicationCallTxnFields.Accounts = nil - } else if (*z).ApplicationCallTxnFields.Accounts != nil && cap((*z).ApplicationCallTxnFields.Accounts) >= zb0013 { - (*z).ApplicationCallTxnFields.Accounts = ((*z).ApplicationCallTxnFields.Accounts)[:zb0013] + } else if (*z).ApplicationCallTxnFields.Accounts != nil && cap((*z).ApplicationCallTxnFields.Accounts) >= zb0015 { + (*z).ApplicationCallTxnFields.Accounts = ((*z).ApplicationCallTxnFields.Accounts)[:zb0015] } else { - (*z).ApplicationCallTxnFields.Accounts = make([]basics.Address, zb0013) + (*z).ApplicationCallTxnFields.Accounts = make([]basics.Address, zb0015) } for zb0003 := range (*z).ApplicationCallTxnFields.Accounts { bts, err = (*z).ApplicationCallTxnFields.Accounts[zb0003].UnmarshalMsg(bts) @@ -5345,24 +5585,24 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { } if zb0007 > 0 { zb0007-- - var zb0015 int - var zb0016 bool - zb0015, zb0016, bts, err = msgp.ReadArrayHeaderBytes(bts) + var zb0017 int + var zb0018 bool + zb0017, zb0018, bts, err = msgp.ReadArrayHeaderBytes(bts) if err != nil { err = msgp.WrapError(err, "struct-from-array", "ForeignApps") return } - if zb0015 > encodedMaxForeignApps { - err = msgp.ErrOverflow(uint64(zb0015), uint64(encodedMaxForeignApps)) + if zb0017 > encodedMaxForeignApps { + err = msgp.ErrOverflow(uint64(zb0017), uint64(encodedMaxForeignApps)) err = msgp.WrapError(err, "struct-from-array", "ForeignApps") return } - if zb0016 { + if zb0018 { (*z).ApplicationCallTxnFields.ForeignApps = nil - } else if (*z).ApplicationCallTxnFields.ForeignApps != nil && cap((*z).ApplicationCallTxnFields.ForeignApps) >= zb0015 { - (*z).ApplicationCallTxnFields.ForeignApps = ((*z).ApplicationCallTxnFields.ForeignApps)[:zb0015] + } else if (*z).ApplicationCallTxnFields.ForeignApps != nil && cap((*z).ApplicationCallTxnFields.ForeignApps) >= zb0017 { + (*z).ApplicationCallTxnFields.ForeignApps = ((*z).ApplicationCallTxnFields.ForeignApps)[:zb0017] } else { - (*z).ApplicationCallTxnFields.ForeignApps = make([]basics.AppIndex, zb0015) + (*z).ApplicationCallTxnFields.ForeignApps = make([]basics.AppIndex, zb0017) } for zb0004 := range (*z).ApplicationCallTxnFields.ForeignApps { bts, err = (*z).ApplicationCallTxnFields.ForeignApps[zb0004].UnmarshalMsg(bts) @@ -5374,53 +5614,53 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { } if zb0007 > 0 { zb0007-- - var zb0017 int - var zb0018 bool - zb0017, zb0018, bts, err = msgp.ReadArrayHeaderBytes(bts) + var zb0019 int + var zb0020 bool + zb0019, zb0020, bts, err = msgp.ReadArrayHeaderBytes(bts) if err != nil { err = msgp.WrapError(err, "struct-from-array", "Boxes") return } - if zb0017 > encodedMaxBoxes { - err = msgp.ErrOverflow(uint64(zb0017), uint64(encodedMaxBoxes)) + if zb0019 > encodedMaxBoxes { + err = msgp.ErrOverflow(uint64(zb0019), uint64(encodedMaxBoxes)) err = msgp.WrapError(err, "struct-from-array", "Boxes") return } - if zb0018 { + if zb0020 { (*z).ApplicationCallTxnFields.Boxes = nil - } else if (*z).ApplicationCallTxnFields.Boxes != nil && cap((*z).ApplicationCallTxnFields.Boxes) >= zb0017 { - (*z).ApplicationCallTxnFields.Boxes = ((*z).ApplicationCallTxnFields.Boxes)[:zb0017] + } else if (*z).ApplicationCallTxnFields.Boxes != nil && cap((*z).ApplicationCallTxnFields.Boxes) >= zb0019 { + (*z).ApplicationCallTxnFields.Boxes = ((*z).ApplicationCallTxnFields.Boxes)[:zb0019] } else { - (*z).ApplicationCallTxnFields.Boxes = make([]BoxRef, zb0017) + (*z).ApplicationCallTxnFields.Boxes = make([]BoxRef, zb0019) } for zb0005 := range (*z).ApplicationCallTxnFields.Boxes { - var zb0019 int - var zb0020 bool - zb0019, zb0020, bts, err = msgp.ReadMapHeaderBytes(bts) + var zb0021 int + var zb0022 bool + zb0021, zb0022, bts, err = msgp.ReadMapHeaderBytes(bts) if _, ok := err.(msgp.TypeError); ok { - zb0019, zb0020, bts, err = msgp.ReadArrayHeaderBytes(bts) + zb0021, zb0022, bts, err = msgp.ReadArrayHeaderBytes(bts) if err != nil { err = msgp.WrapError(err, "struct-from-array", "Boxes", zb0005) return } - if zb0019 > 0 { - zb0019-- + if zb0021 > 0 { + zb0021-- (*z).ApplicationCallTxnFields.Boxes[zb0005].Index, bts, err = msgp.ReadUint64Bytes(bts) if err != nil { err = msgp.WrapError(err, "struct-from-array", "Boxes", zb0005, "struct-from-array", "Index") return } } - if zb0019 > 0 { - zb0019-- + if zb0021 > 0 { + zb0021-- (*z).ApplicationCallTxnFields.Boxes[zb0005].Name, bts, err = msgp.ReadBytesBytes(bts, (*z).ApplicationCallTxnFields.Boxes[zb0005].Name) if err != nil { err = msgp.WrapError(err, "struct-from-array", "Boxes", zb0005, "struct-from-array", "Name") return } } - if zb0019 > 0 { - err = msgp.ErrTooManyArrayFields(zb0019) + if zb0021 > 0 { + err = msgp.ErrTooManyArrayFields(zb0021) if err != nil { err = msgp.WrapError(err, "struct-from-array", "Boxes", zb0005, "struct-from-array") return @@ -5431,11 +5671,11 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { err = msgp.WrapError(err, "struct-from-array", "Boxes", zb0005) return } - if zb0020 { + if zb0022 { (*z).ApplicationCallTxnFields.Boxes[zb0005] = BoxRef{} } - for zb0019 > 0 { - zb0019-- + for zb0021 > 0 { + zb0021-- field, bts, err = msgp.ReadMapKeyZC(bts) if err != nil { err = msgp.WrapError(err, "struct-from-array", "Boxes", zb0005) @@ -5467,24 +5707,24 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { } if zb0007 > 0 { zb0007-- - var zb0021 int - var zb0022 bool - zb0021, zb0022, bts, err = msgp.ReadArrayHeaderBytes(bts) + var zb0023 int + var zb0024 bool + zb0023, zb0024, bts, err = msgp.ReadArrayHeaderBytes(bts) if err != nil { err = msgp.WrapError(err, "struct-from-array", "ForeignAssets") return } - if zb0021 > encodedMaxForeignAssets { - err = msgp.ErrOverflow(uint64(zb0021), uint64(encodedMaxForeignAssets)) + if zb0023 > encodedMaxForeignAssets { + err = msgp.ErrOverflow(uint64(zb0023), uint64(encodedMaxForeignAssets)) err = msgp.WrapError(err, "struct-from-array", "ForeignAssets") return } - if zb0022 { + if zb0024 { (*z).ApplicationCallTxnFields.ForeignAssets = nil - } else if (*z).ApplicationCallTxnFields.ForeignAssets != nil && cap((*z).ApplicationCallTxnFields.ForeignAssets) >= zb0021 { - (*z).ApplicationCallTxnFields.ForeignAssets = ((*z).ApplicationCallTxnFields.ForeignAssets)[:zb0021] + } else if (*z).ApplicationCallTxnFields.ForeignAssets != nil && cap((*z).ApplicationCallTxnFields.ForeignAssets) >= zb0023 { + (*z).ApplicationCallTxnFields.ForeignAssets = ((*z).ApplicationCallTxnFields.ForeignAssets)[:zb0023] } else { - (*z).ApplicationCallTxnFields.ForeignAssets = make([]basics.AssetIndex, zb0021) + (*z).ApplicationCallTxnFields.ForeignAssets = make([]basics.AssetIndex, zb0023) } for zb0006 := range (*z).ApplicationCallTxnFields.ForeignAssets { bts, err = (*z).ApplicationCallTxnFields.ForeignAssets[zb0006].UnmarshalMsg(bts) @@ -5512,14 +5752,14 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { } if zb0007 > 0 { zb0007-- - var zb0023 int - zb0023, err = msgp.ReadBytesBytesHeader(bts) + var zb0025 int + zb0025, err = msgp.ReadBytesBytesHeader(bts) if err != nil { err = msgp.WrapError(err, "struct-from-array", "ApprovalProgram") return } - if zb0023 > config.MaxAvailableAppProgramLen { - err = msgp.ErrOverflow(uint64(zb0023), uint64(config.MaxAvailableAppProgramLen)) + if zb0025 > config.MaxAvailableAppProgramLen { + err = msgp.ErrOverflow(uint64(zb0025), uint64(config.MaxAvailableAppProgramLen)) return } (*z).ApplicationCallTxnFields.ApprovalProgram, bts, err = msgp.ReadBytesBytes(bts, (*z).ApplicationCallTxnFields.ApprovalProgram) @@ -5530,14 +5770,14 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { } if zb0007 > 0 { zb0007-- - var zb0024 int - zb0024, err = msgp.ReadBytesBytesHeader(bts) + var zb0026 int + zb0026, err = msgp.ReadBytesBytesHeader(bts) if err != nil { err = msgp.WrapError(err, "struct-from-array", "ClearStateProgram") return } - if zb0024 > config.MaxAvailableAppProgramLen { - err = msgp.ErrOverflow(uint64(zb0024), uint64(config.MaxAvailableAppProgramLen)) + if zb0026 > config.MaxAvailableAppProgramLen { + err = msgp.ErrOverflow(uint64(zb0026), uint64(config.MaxAvailableAppProgramLen)) return } (*z).ApplicationCallTxnFields.ClearStateProgram, bts, err = msgp.ReadBytesBytes(bts, (*z).ApplicationCallTxnFields.ClearStateProgram) @@ -5607,6 +5847,76 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { err = msgp.WrapError(err, "Type") return } + case "dev_mode_options": + var zb0027 int + var zb0028 bool + zb0027, zb0028, bts, err = msgp.ReadMapHeaderBytes(bts) + if _, ok := err.(msgp.TypeError); ok { + zb0027, zb0028, bts, err = msgp.ReadArrayHeaderBytes(bts) + if err != nil { + err = msgp.WrapError(err, "DevMode") + return + } + if zb0027 > 0 { + zb0027-- + (*z).DevMode.SkipValidation, bts, err = msgp.ReadBoolBytes(bts) + if err != nil { + err = msgp.WrapError(err, "DevMode", "struct-from-array", "SkipValidation") + return + } + } + if zb0027 > 0 { + zb0027-- + (*z).DevMode.SetNextBlockTime, bts, err = msgp.ReadInt64Bytes(bts) + if err != nil { + err = msgp.WrapError(err, "DevMode", "struct-from-array", "SetNextBlockTime") + return + } + } + if zb0027 > 0 { + err = msgp.ErrTooManyArrayFields(zb0027) + if err != nil { + err = msgp.WrapError(err, "DevMode", "struct-from-array") + return + } + } + } else { + if err != nil { + err = msgp.WrapError(err, "DevMode") + return + } + if zb0028 { + (*z).DevMode = DevMode{} + } + for zb0027 > 0 { + zb0027-- + field, bts, err = msgp.ReadMapKeyZC(bts) + if err != nil { + err = msgp.WrapError(err, "DevMode") + return + } + switch string(field) { + case "skip_validation": + (*z).DevMode.SkipValidation, bts, err = msgp.ReadBoolBytes(bts) + if err != nil { + err = msgp.WrapError(err, "DevMode", "SkipValidation") + return + } + case "set_next_block_time": + (*z).DevMode.SetNextBlockTime, bts, err = msgp.ReadInt64Bytes(bts) + if err != nil { + err = msgp.WrapError(err, "DevMode", "SetNextBlockTime") + return + } + default: + err = msgp.ErrNoField(string(field)) + if err != nil { + err = msgp.WrapError(err, "DevMode") + return + } + } + } + } case "snd": bts, err = (*z).Header.Sender.UnmarshalMsg(bts) if err != nil { @@ -5632,14 +5942,14 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { return } case "note": - var zb0025 int - zb0025, err = msgp.ReadBytesBytesHeader(bts) + var zb0029 int + zb0029, err = msgp.ReadBytesBytesHeader(bts) if err != nil { err = msgp.WrapError(err, "Note") return } - if zb0025 > config.MaxTxnNoteBytes { - err = msgp.ErrOverflow(uint64(zb0025), uint64(config.MaxTxnNoteBytes)) + if zb0029 > config.MaxTxnNoteBytes { + err = msgp.ErrOverflow(uint64(zb0029), uint64(config.MaxTxnNoteBytes)) return } (*z).Header.Note, bts, err = msgp.ReadBytesBytes(bts, (*z).Header.Note) @@ -5805,33 +6115,33 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { } case "apan": { - var zb0026 uint64 - zb0026, bts, err = msgp.ReadUint64Bytes(bts) + var zb0030 uint64 + zb0030, bts, err = msgp.ReadUint64Bytes(bts) if err != nil { err = msgp.WrapError(err, "OnCompletion") return } - (*z).ApplicationCallTxnFields.OnCompletion = OnCompletion(zb0026) + (*z).ApplicationCallTxnFields.OnCompletion = OnCompletion(zb0030) } case "apaa": - var zb0027 int - var zb0028 bool - zb0027, zb0028, bts, err = msgp.ReadArrayHeaderBytes(bts) + var zb0031 int + var zb0032 bool + zb0031, zb0032, bts, err = msgp.ReadArrayHeaderBytes(bts) if err != nil { err = msgp.WrapError(err, "ApplicationArgs") return } - if zb0027 > encodedMaxApplicationArgs { - err = msgp.ErrOverflow(uint64(zb0027), uint64(encodedMaxApplicationArgs)) + if zb0031 > encodedMaxApplicationArgs { + err = msgp.ErrOverflow(uint64(zb0031), uint64(encodedMaxApplicationArgs)) err = msgp.WrapError(err, "ApplicationArgs") return } - if zb0028 { + if zb0032 { (*z).ApplicationCallTxnFields.ApplicationArgs = nil - } else if (*z).ApplicationCallTxnFields.ApplicationArgs != nil && cap((*z).ApplicationCallTxnFields.ApplicationArgs) >= zb0027 { - (*z).ApplicationCallTxnFields.ApplicationArgs = ((*z).ApplicationCallTxnFields.ApplicationArgs)[:zb0027] + } else if (*z).ApplicationCallTxnFields.ApplicationArgs != nil && cap((*z).ApplicationCallTxnFields.ApplicationArgs) >= zb0031 { + (*z).ApplicationCallTxnFields.ApplicationArgs = ((*z).ApplicationCallTxnFields.ApplicationArgs)[:zb0031] } else { - (*z).ApplicationCallTxnFields.ApplicationArgs = make([][]byte, zb0027) + (*z).ApplicationCallTxnFields.ApplicationArgs = make([][]byte, zb0031) } for zb0002 := range (*z).ApplicationCallTxnFields.ApplicationArgs { (*z).ApplicationCallTxnFields.ApplicationArgs[zb0002], bts, err = msgp.ReadBytesBytes(bts, (*z).ApplicationCallTxnFields.ApplicationArgs[zb0002]) @@ -5841,24 +6151,24 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { } } case "apat": - var zb0029 int - var zb0030 bool - zb0029, zb0030, bts, err = msgp.ReadArrayHeaderBytes(bts) + var zb0033 int + var zb0034 bool + zb0033, zb0034, bts, err = msgp.ReadArrayHeaderBytes(bts) if err != nil { err = msgp.WrapError(err, "Accounts") return } - if zb0029 > encodedMaxAccounts { - err = msgp.ErrOverflow(uint64(zb0029), uint64(encodedMaxAccounts)) + if zb0033 > encodedMaxAccounts { + err = msgp.ErrOverflow(uint64(zb0033), uint64(encodedMaxAccounts)) err = msgp.WrapError(err, "Accounts") return } - if zb0030 { + if zb0034 { (*z).ApplicationCallTxnFields.Accounts = nil - } else if (*z).ApplicationCallTxnFields.Accounts != nil && cap((*z).ApplicationCallTxnFields.Accounts) >= zb0029 { - (*z).ApplicationCallTxnFields.Accounts = ((*z).ApplicationCallTxnFields.Accounts)[:zb0029] + } else if (*z).ApplicationCallTxnFields.Accounts != nil && cap((*z).ApplicationCallTxnFields.Accounts) >= zb0033 { + (*z).ApplicationCallTxnFields.Accounts = ((*z).ApplicationCallTxnFields.Accounts)[:zb0033] } else { - (*z).ApplicationCallTxnFields.Accounts = make([]basics.Address, zb0029) + (*z).ApplicationCallTxnFields.Accounts = make([]basics.Address, zb0033) } for zb0003 := range (*z).ApplicationCallTxnFields.Accounts { bts, err = (*z).ApplicationCallTxnFields.Accounts[zb0003].UnmarshalMsg(bts) @@ -5868,24 +6178,24 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { } } case "apfa": - var zb0031 int - var zb0032 bool - zb0031, zb0032, bts, err = msgp.ReadArrayHeaderBytes(bts) + var zb0035 int + var zb0036 bool + zb0035, zb0036, bts, err = msgp.ReadArrayHeaderBytes(bts) if err != nil { err = msgp.WrapError(err, "ForeignApps") return } - if zb0031 > encodedMaxForeignApps { - err = msgp.ErrOverflow(uint64(zb0031), uint64(encodedMaxForeignApps)) + if zb0035 > encodedMaxForeignApps { + err = msgp.ErrOverflow(uint64(zb0035), uint64(encodedMaxForeignApps)) err = msgp.WrapError(err, "ForeignApps") return } - if zb0032 { + if zb0036 { (*z).ApplicationCallTxnFields.ForeignApps = nil - } else if (*z).ApplicationCallTxnFields.ForeignApps != nil && cap((*z).ApplicationCallTxnFields.ForeignApps) >= zb0031 { - (*z).ApplicationCallTxnFields.ForeignApps = ((*z).ApplicationCallTxnFields.ForeignApps)[:zb0031] + } else if (*z).ApplicationCallTxnFields.ForeignApps != nil && cap((*z).ApplicationCallTxnFields.ForeignApps) >= zb0035 { + (*z).ApplicationCallTxnFields.ForeignApps = ((*z).ApplicationCallTxnFields.ForeignApps)[:zb0035] } else { - (*z).ApplicationCallTxnFields.ForeignApps = make([]basics.AppIndex, zb0031) + (*z).ApplicationCallTxnFields.ForeignApps = make([]basics.AppIndex, zb0035) } for zb0004 := range (*z).ApplicationCallTxnFields.ForeignApps { bts, err = (*z).ApplicationCallTxnFields.ForeignApps[zb0004].UnmarshalMsg(bts) @@ -5895,53 +6205,53 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { } } case "apbx": - var zb0033 int - var zb0034 bool - zb0033, zb0034, bts, err = msgp.ReadArrayHeaderBytes(bts) + var zb0037 int + var zb0038 bool + zb0037, zb0038, bts, err = msgp.ReadArrayHeaderBytes(bts) if err != nil { err = msgp.WrapError(err, "Boxes") return } - if zb0033 > encodedMaxBoxes { - err = msgp.ErrOverflow(uint64(zb0033), uint64(encodedMaxBoxes)) + if zb0037 > encodedMaxBoxes { + err = msgp.ErrOverflow(uint64(zb0037), uint64(encodedMaxBoxes)) err = msgp.WrapError(err, "Boxes") return } - if zb0034 { + if zb0038 { (*z).ApplicationCallTxnFields.Boxes = nil - } else if (*z).ApplicationCallTxnFields.Boxes != nil && cap((*z).ApplicationCallTxnFields.Boxes) >= zb0033 { - (*z).ApplicationCallTxnFields.Boxes = ((*z).ApplicationCallTxnFields.Boxes)[:zb0033] + } else if (*z).ApplicationCallTxnFields.Boxes != nil && cap((*z).ApplicationCallTxnFields.Boxes) >= zb0037 { + (*z).ApplicationCallTxnFields.Boxes = ((*z).ApplicationCallTxnFields.Boxes)[:zb0037] } else { - (*z).ApplicationCallTxnFields.Boxes = make([]BoxRef, zb0033) + (*z).ApplicationCallTxnFields.Boxes = make([]BoxRef, zb0037) } for zb0005 := range (*z).ApplicationCallTxnFields.Boxes { - var zb0035 int - var zb0036 bool - zb0035, zb0036, bts, err = msgp.ReadMapHeaderBytes(bts) + var zb0039 int + var zb0040 bool + zb0039, zb0040, bts, err = msgp.ReadMapHeaderBytes(bts) if _, ok := err.(msgp.TypeError); ok { - zb0035, zb0036, bts, err = msgp.ReadArrayHeaderBytes(bts) + zb0039, zb0040, bts, err = msgp.ReadArrayHeaderBytes(bts) if err != nil { err = msgp.WrapError(err, "Boxes", zb0005) return } - if zb0035 > 0 { - zb0035-- + if zb0039 > 0 { + zb0039-- (*z).ApplicationCallTxnFields.Boxes[zb0005].Index, bts, err = msgp.ReadUint64Bytes(bts) if err != nil { err = msgp.WrapError(err, "Boxes", zb0005, "struct-from-array", "Index") return } } - if zb0035 > 0 { - zb0035-- + if zb0039 > 0 { + zb0039-- (*z).ApplicationCallTxnFields.Boxes[zb0005].Name, bts, err = msgp.ReadBytesBytes(bts, (*z).ApplicationCallTxnFields.Boxes[zb0005].Name) if err != nil { err = msgp.WrapError(err, "Boxes", zb0005, "struct-from-array", "Name") return } } - if zb0035 > 0 { - err = msgp.ErrTooManyArrayFields(zb0035) + if zb0039 > 0 { + err = msgp.ErrTooManyArrayFields(zb0039) if err != nil { err = msgp.WrapError(err, "Boxes", zb0005, "struct-from-array") return @@ -5952,11 +6262,11 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { err = msgp.WrapError(err, "Boxes", zb0005) return } - if zb0036 { + if zb0040 { (*z).ApplicationCallTxnFields.Boxes[zb0005] = BoxRef{} } - for zb0035 > 0 { - zb0035-- + for zb0039 > 0 { + zb0039-- field, bts, err = msgp.ReadMapKeyZC(bts) if err != nil { err = msgp.WrapError(err, "Boxes", zb0005) @@ -5986,24 +6296,24 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { } } case "apas": - var zb0037 int - var zb0038 bool - zb0037, zb0038, bts, err = msgp.ReadArrayHeaderBytes(bts) + var zb0041 int + var zb0042 bool + zb0041, zb0042, bts, err = msgp.ReadArrayHeaderBytes(bts) if err != nil { err = msgp.WrapError(err, "ForeignAssets") return } - if zb0037 > encodedMaxForeignAssets { - err = msgp.ErrOverflow(uint64(zb0037), uint64(encodedMaxForeignAssets)) + if zb0041 > encodedMaxForeignAssets { + err = msgp.ErrOverflow(uint64(zb0041), uint64(encodedMaxForeignAssets)) err = msgp.WrapError(err, "ForeignAssets") return } - if zb0038 { + if zb0042 { (*z).ApplicationCallTxnFields.ForeignAssets = nil - } else if (*z).ApplicationCallTxnFields.ForeignAssets != nil && cap((*z).ApplicationCallTxnFields.ForeignAssets) >= zb0037 { - (*z).ApplicationCallTxnFields.ForeignAssets = ((*z).ApplicationCallTxnFields.ForeignAssets)[:zb0037] + } else if (*z).ApplicationCallTxnFields.ForeignAssets != nil && cap((*z).ApplicationCallTxnFields.ForeignAssets) >= zb0041 { + (*z).ApplicationCallTxnFields.ForeignAssets = ((*z).ApplicationCallTxnFields.ForeignAssets)[:zb0041] } else { - (*z).ApplicationCallTxnFields.ForeignAssets = make([]basics.AssetIndex, zb0037) + (*z).ApplicationCallTxnFields.ForeignAssets = make([]basics.AssetIndex, zb0041) } for zb0006 := range (*z).ApplicationCallTxnFields.ForeignAssets { bts, err = (*z).ApplicationCallTxnFields.ForeignAssets[zb0006].UnmarshalMsg(bts) @@ -6025,14 +6335,14 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { return } case "apap": - var zb0039 int - zb0039, err = msgp.ReadBytesBytesHeader(bts) + var zb0043 int + zb0043, err = msgp.ReadBytesBytesHeader(bts) if err != nil { err = msgp.WrapError(err, "ApprovalProgram") return } - if zb0039 > config.MaxAvailableAppProgramLen { - err = msgp.ErrOverflow(uint64(zb0039), uint64(config.MaxAvailableAppProgramLen)) + if zb0043 > config.MaxAvailableAppProgramLen { + err = msgp.ErrOverflow(uint64(zb0043), uint64(config.MaxAvailableAppProgramLen)) return } (*z).ApplicationCallTxnFields.ApprovalProgram, bts, err = msgp.ReadBytesBytes(bts, (*z).ApplicationCallTxnFields.ApprovalProgram) @@ -6041,14 +6351,14 @@ func (z *Transaction) UnmarshalMsg(bts []byte) (o []byte, err error) { return } case "apsu": - var zb0040 int - zb0040, err = msgp.ReadBytesBytesHeader(bts) + var zb0044 int + zb0044, err = msgp.ReadBytesBytesHeader(bts) if err != nil { err = msgp.WrapError(err, "ClearStateProgram") return } - if zb0040 > config.MaxAvailableAppProgramLen { - err = msgp.ErrOverflow(uint64(zb0040), uint64(config.MaxAvailableAppProgramLen)) + if zb0044 > config.MaxAvailableAppProgramLen { + err = msgp.ErrOverflow(uint64(zb0044), uint64(config.MaxAvailableAppProgramLen)) return } (*z).ApplicationCallTxnFields.ClearStateProgram, bts, err = msgp.ReadBytesBytes(bts, (*z).ApplicationCallTxnFields.ClearStateProgram) @@ -6100,7 +6410,7 @@ func (_ *Transaction) CanUnmarshalMsg(z interface{}) bool { // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message func (z *Transaction) Msgsize() (s int) { - s = 3 + 5 + (*z).Type.Msgsize() + 4 + (*z).Header.Sender.Msgsize() + 4 + (*z).Header.Fee.Msgsize() + 3 + (*z).Header.FirstValid.Msgsize() + 3 + (*z).Header.LastValid.Msgsize() + 5 + msgp.BytesPrefixSize + len((*z).Header.Note) + 4 + msgp.StringPrefixSize + len((*z).Header.GenesisID) + 3 + (*z).Header.GenesisHash.Msgsize() + 4 + (*z).Header.Group.Msgsize() + 3 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 6 + (*z).Header.RekeyTo.Msgsize() + 8 + (*z).KeyregTxnFields.VotePK.Msgsize() + 7 + (*z).KeyregTxnFields.SelectionPK.Msgsize() + 8 + (*z).KeyregTxnFields.StateProofPK.Msgsize() + 8 + (*z).KeyregTxnFields.VoteFirst.Msgsize() + 8 + (*z).KeyregTxnFields.VoteLast.Msgsize() + 7 + msgp.Uint64Size + 8 + msgp.BoolSize + 4 + (*z).PaymentTxnFields.Receiver.Msgsize() + 4 + (*z).PaymentTxnFields.Amount.Msgsize() + 6 + (*z).PaymentTxnFields.CloseRemainderTo.Msgsize() + 5 + (*z).AssetConfigTxnFields.ConfigAsset.Msgsize() + 5 + (*z).AssetConfigTxnFields.AssetParams.Msgsize() + 5 + (*z).AssetTransferTxnFields.XferAsset.Msgsize() + 5 + msgp.Uint64Size + 5 + (*z).AssetTransferTxnFields.AssetSender.Msgsize() + 5 + (*z).AssetTransferTxnFields.AssetReceiver.Msgsize() + 7 + (*z).AssetTransferTxnFields.AssetCloseTo.Msgsize() + 5 + (*z).AssetFreezeTxnFields.FreezeAccount.Msgsize() + 5 + (*z).AssetFreezeTxnFields.FreezeAsset.Msgsize() + 5 + msgp.BoolSize + 5 + (*z).ApplicationCallTxnFields.ApplicationID.Msgsize() + 5 + msgp.Uint64Size + 5 + msgp.ArrayHeaderSize + s = 3 + 5 + (*z).Type.Msgsize() + 17 + 1 + 16 + msgp.BoolSize + 20 + msgp.Int64Size + 4 + (*z).Header.Sender.Msgsize() + 4 + (*z).Header.Fee.Msgsize() + 3 + (*z).Header.FirstValid.Msgsize() + 3 + (*z).Header.LastValid.Msgsize() + 5 + msgp.BytesPrefixSize + len((*z).Header.Note) + 4 + msgp.StringPrefixSize + len((*z).Header.GenesisID) + 3 + (*z).Header.GenesisHash.Msgsize() + 4 + (*z).Header.Group.Msgsize() + 3 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 6 + (*z).Header.RekeyTo.Msgsize() + 8 + (*z).KeyregTxnFields.VotePK.Msgsize() + 7 + (*z).KeyregTxnFields.SelectionPK.Msgsize() + 8 + (*z).KeyregTxnFields.StateProofPK.Msgsize() + 8 + (*z).KeyregTxnFields.VoteFirst.Msgsize() + 8 + (*z).KeyregTxnFields.VoteLast.Msgsize() + 7 + msgp.Uint64Size + 8 + msgp.BoolSize + 4 + (*z).PaymentTxnFields.Receiver.Msgsize() + 4 + (*z).PaymentTxnFields.Amount.Msgsize() + 6 + (*z).PaymentTxnFields.CloseRemainderTo.Msgsize() + 5 + (*z).AssetConfigTxnFields.ConfigAsset.Msgsize() + 5 + (*z).AssetConfigTxnFields.AssetParams.Msgsize() + 5 + (*z).AssetTransferTxnFields.XferAsset.Msgsize() + 5 + msgp.Uint64Size + 5 + (*z).AssetTransferTxnFields.AssetSender.Msgsize() + 5 + (*z).AssetTransferTxnFields.AssetReceiver.Msgsize() + 7 + (*z).AssetTransferTxnFields.AssetCloseTo.Msgsize() + 5 + (*z).AssetFreezeTxnFields.FreezeAccount.Msgsize() + 5 + (*z).AssetFreezeTxnFields.FreezeAsset.Msgsize() + 5 + msgp.BoolSize + 5 + (*z).ApplicationCallTxnFields.ApplicationID.Msgsize() + 5 + msgp.Uint64Size + 5 + msgp.ArrayHeaderSize for zb0002 := range (*z).ApplicationCallTxnFields.ApplicationArgs { s += msgp.BytesPrefixSize + len((*z).ApplicationCallTxnFields.ApplicationArgs[zb0002]) } @@ -6126,7 +6436,7 @@ func (z *Transaction) Msgsize() (s int) { // MsgIsZero returns whether this is a zero value func (z *Transaction) MsgIsZero() bool { - return ((*z).Type.MsgIsZero()) && ((*z).Header.Sender.MsgIsZero()) && ((*z).Header.Fee.MsgIsZero()) && ((*z).Header.FirstValid.MsgIsZero()) && ((*z).Header.LastValid.MsgIsZero()) && (len((*z).Header.Note) == 0) && ((*z).Header.GenesisID == "") && ((*z).Header.GenesisHash.MsgIsZero()) && ((*z).Header.Group.MsgIsZero()) && ((*z).Header.Lease == ([32]byte{})) && ((*z).Header.RekeyTo.MsgIsZero()) && ((*z).KeyregTxnFields.VotePK.MsgIsZero()) && ((*z).KeyregTxnFields.SelectionPK.MsgIsZero()) && ((*z).KeyregTxnFields.StateProofPK.MsgIsZero()) && ((*z).KeyregTxnFields.VoteFirst.MsgIsZero()) && ((*z).KeyregTxnFields.VoteLast.MsgIsZero()) && ((*z).KeyregTxnFields.VoteKeyDilution == 0) && ((*z).KeyregTxnFields.Nonparticipation == false) && ((*z).PaymentTxnFields.Receiver.MsgIsZero()) && ((*z).PaymentTxnFields.Amount.MsgIsZero()) && ((*z).PaymentTxnFields.CloseRemainderTo.MsgIsZero()) && ((*z).AssetConfigTxnFields.ConfigAsset.MsgIsZero()) && ((*z).AssetConfigTxnFields.AssetParams.MsgIsZero()) && ((*z).AssetTransferTxnFields.XferAsset.MsgIsZero()) && ((*z).AssetTransferTxnFields.AssetAmount == 0) && ((*z).AssetTransferTxnFields.AssetSender.MsgIsZero()) && ((*z).AssetTransferTxnFields.AssetReceiver.MsgIsZero()) && ((*z).AssetTransferTxnFields.AssetCloseTo.MsgIsZero()) && ((*z).AssetFreezeTxnFields.FreezeAccount.MsgIsZero()) && ((*z).AssetFreezeTxnFields.FreezeAsset.MsgIsZero()) && ((*z).AssetFreezeTxnFields.AssetFrozen == false) && ((*z).ApplicationCallTxnFields.ApplicationID.MsgIsZero()) && ((*z).ApplicationCallTxnFields.OnCompletion == 0) && (len((*z).ApplicationCallTxnFields.ApplicationArgs) == 0) && (len((*z).ApplicationCallTxnFields.Accounts) == 0) && (len((*z).ApplicationCallTxnFields.ForeignApps) == 0) && (len((*z).ApplicationCallTxnFields.Boxes) == 0) && (len((*z).ApplicationCallTxnFields.ForeignAssets) == 0) && ((*z).ApplicationCallTxnFields.LocalStateSchema.MsgIsZero()) && ((*z).ApplicationCallTxnFields.GlobalStateSchema.MsgIsZero()) && (len((*z).ApplicationCallTxnFields.ApprovalProgram) == 0) && (len((*z).ApplicationCallTxnFields.ClearStateProgram) == 0) && ((*z).ApplicationCallTxnFields.ExtraProgramPages == 0) && ((*z).StateProofTxnFields.StateProofType.MsgIsZero()) && ((*z).StateProofTxnFields.StateProof.MsgIsZero()) && ((*z).StateProofTxnFields.Message.MsgIsZero()) + return ((*z).Type.MsgIsZero()) && (((*z).DevMode.SkipValidation == false) && ((*z).DevMode.SetNextBlockTime == 0)) && ((*z).Header.Sender.MsgIsZero()) && ((*z).Header.Fee.MsgIsZero()) && ((*z).Header.FirstValid.MsgIsZero()) && ((*z).Header.LastValid.MsgIsZero()) && (len((*z).Header.Note) == 0) && ((*z).Header.GenesisID == "") && ((*z).Header.GenesisHash.MsgIsZero()) && ((*z).Header.Group.MsgIsZero()) && ((*z).Header.Lease == ([32]byte{})) && ((*z).Header.RekeyTo.MsgIsZero()) && ((*z).KeyregTxnFields.VotePK.MsgIsZero()) && ((*z).KeyregTxnFields.SelectionPK.MsgIsZero()) && ((*z).KeyregTxnFields.StateProofPK.MsgIsZero()) && ((*z).KeyregTxnFields.VoteFirst.MsgIsZero()) && ((*z).KeyregTxnFields.VoteLast.MsgIsZero()) && ((*z).KeyregTxnFields.VoteKeyDilution == 0) && ((*z).KeyregTxnFields.Nonparticipation == false) && ((*z).PaymentTxnFields.Receiver.MsgIsZero()) && ((*z).PaymentTxnFields.Amount.MsgIsZero()) && ((*z).PaymentTxnFields.CloseRemainderTo.MsgIsZero()) && ((*z).AssetConfigTxnFields.ConfigAsset.MsgIsZero()) && ((*z).AssetConfigTxnFields.AssetParams.MsgIsZero()) && ((*z).AssetTransferTxnFields.XferAsset.MsgIsZero()) && ((*z).AssetTransferTxnFields.AssetAmount == 0) && ((*z).AssetTransferTxnFields.AssetSender.MsgIsZero()) && ((*z).AssetTransferTxnFields.AssetReceiver.MsgIsZero()) && ((*z).AssetTransferTxnFields.AssetCloseTo.MsgIsZero()) && ((*z).AssetFreezeTxnFields.FreezeAccount.MsgIsZero()) && ((*z).AssetFreezeTxnFields.FreezeAsset.MsgIsZero()) && ((*z).AssetFreezeTxnFields.AssetFrozen == false) && ((*z).ApplicationCallTxnFields.ApplicationID.MsgIsZero()) && ((*z).ApplicationCallTxnFields.OnCompletion == 0) && (len((*z).ApplicationCallTxnFields.ApplicationArgs) == 0) && (len((*z).ApplicationCallTxnFields.Accounts) == 0) && (len((*z).ApplicationCallTxnFields.ForeignApps) == 0) && (len((*z).ApplicationCallTxnFields.Boxes) == 0) && (len((*z).ApplicationCallTxnFields.ForeignAssets) == 0) && ((*z).ApplicationCallTxnFields.LocalStateSchema.MsgIsZero()) && ((*z).ApplicationCallTxnFields.GlobalStateSchema.MsgIsZero()) && (len((*z).ApplicationCallTxnFields.ApprovalProgram) == 0) && (len((*z).ApplicationCallTxnFields.ClearStateProgram) == 0) && ((*z).ApplicationCallTxnFields.ExtraProgramPages == 0) && ((*z).StateProofTxnFields.StateProofType.MsgIsZero()) && ((*z).StateProofTxnFields.StateProof.MsgIsZero()) && ((*z).StateProofTxnFields.Message.MsgIsZero()) } // MarshalMsg implements msgp.Marshaler diff --git a/data/transactions/msgp_gen_test.go b/data/transactions/msgp_gen_test.go index 0ce6b29c38..98bdfd8d26 100644 --- a/data/transactions/msgp_gen_test.go +++ b/data/transactions/msgp_gen_test.go @@ -374,6 +374,66 @@ func BenchmarkUnmarshalBoxRef(b *testing.B) { } } +func TestMarshalUnmarshalDevMode(t *testing.T) { + partitiontest.PartitionTest(t) + v := DevMode{} + bts := v.MarshalMsg(nil) + left, err := v.UnmarshalMsg(bts) + if err != nil { + t.Fatal(err) + } + if len(left) > 0 { + t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left) + } + + left, err = msgp.Skip(bts) + if err != nil { + t.Fatal(err) + } + if len(left) > 0 { + t.Errorf("%d bytes left over after Skip(): %q", len(left), left) + } +} + +func TestRandomizedEncodingDevMode(t *testing.T) { + protocol.RunEncodingTest(t, &DevMode{}) +} + +func BenchmarkMarshalMsgDevMode(b *testing.B) { + v := DevMode{} + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + v.MarshalMsg(nil) + } +} + +func BenchmarkAppendMsgDevMode(b *testing.B) { + v := DevMode{} + bts := make([]byte, 0, v.Msgsize()) + bts = v.MarshalMsg(bts[0:0]) + b.SetBytes(int64(len(bts))) + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + bts = v.MarshalMsg(bts[0:0]) + } +} + +func BenchmarkUnmarshalDevMode(b *testing.B) { + v := DevMode{} + bts := v.MarshalMsg(nil) + b.ReportAllocs() + b.SetBytes(int64(len(bts))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := v.UnmarshalMsg(bts) + if err != nil { + b.Fatal(err) + } + } +} + func TestMarshalUnmarshalEvalDelta(t *testing.T) { partitiontest.PartitionTest(t) v := EvalDelta{} diff --git a/data/transactions/transaction.go b/data/transactions/transaction.go index 6c1b56fd29..c2488cb880 100644 --- a/data/transactions/transaction.go +++ b/data/transactions/transaction.go @@ -49,6 +49,22 @@ type SpecialAddresses struct { RewardsPool basics.Address } +// DevMode contains options which are only available to transactions submitted +// to networks that have dev mode enabled. +type DevMode struct { + _struct struct{} `codec:",omitempty,omitemptyarray"` + + // IgnoreSignatureCheck disables signature checking. + SkipValidation bool `codec:"skip_validation"` + + // SetNextBlockTime is used to set the block header timestamp. + SetNextBlockTime int64 `codec:"set_next_block_time"` +} + +func (dm DevMode) IsZero() bool { + return dm == DevMode{} +} + // Header captures the fields common to every transaction type. type Header struct { _struct struct{} `codec:",omitempty,omitemptyarray"` @@ -87,6 +103,10 @@ type Transaction struct { // Type of transaction Type protocol.TxType `codec:"type"` + // Fields that can be included when dev mode is enabled. + // TODO: should this be defined in the header or left here for higher visibility? + DevMode DevMode `codec:"dev_mode"` + // Common fields for all types of transactions Header @@ -299,9 +319,15 @@ var errNoteMustBeEmptyInStateproofTxn = errors.New("note must be empty in state- var errGroupMustBeZeroInStateproofTxn = errors.New("group must be zero in state-proof transaction") var errRekeyToMustBeZeroInStateproofTxn = errors.New("rekey must be zero in state-proof transaction") var errLeaseMustBeZeroInStateproofTxn = errors.New("lease must be zero in state-proof transaction") +var errNotDevModeNetwork = errors.New("devmode fields cannot be used with this network") // WellFormed checks that the transaction looks reasonable on its own (but not necessarily valid against the actual ledger). It does not check signatures. func (tx Transaction) WellFormed(spec SpecialAddresses, proto config.ConsensusParams) error { + // Prominently check that devmode fields are not being used. + if !tx.DevMode.IsZero() && !proto.DevMode { + return errNotDevModeNetwork + } + switch tx.Type { case protocol.PaymentTx: // in case that the fee sink is spending, check that this spend is to a valid address diff --git a/ledger/internal/eval.go b/ledger/internal/eval.go index ea5480b0b7..ffa998cd5b 100644 --- a/ledger/internal/eval.go +++ b/ledger/internal/eval.go @@ -1065,6 +1065,13 @@ func (eval *BlockEvaluator) transaction(txn transactions.SignedTxn, evalParams * // Only compute the TxID once txid := txn.ID() + if eval.proto.DevMode && eval.validate && txn.Txn.DevMode.SkipValidation { + eval.validate = false + defer func() { + eval.validate = true + }() + } + if eval.validate { err = txn.Txn.Alive(eval.block) if err != nil { @@ -1098,6 +1105,11 @@ func (eval *BlockEvaluator) transaction(txn transactions.SignedTxn, evalParams * return fmt.Errorf("transaction %v: %w", txid, err) } + // If multiple transactions set the time this logic uses the last one. + if eval.proto.DevMode && txn.Txn.DevMode.SetNextBlockTime != 0 { + eval.block.BlockHeader.TimeStamp = txn.Txn.DevMode.SetNextBlockTime + } + // Validate applyData if we are validating an existing block. // If we are validating and generating, we have no ApplyData yet. if eval.validate && !eval.generate { diff --git a/netdeploy/network.go b/netdeploy/network.go index 1d5e503de3..50e119c768 100644 --- a/netdeploy/network.go +++ b/netdeploy/network.go @@ -19,6 +19,7 @@ package netdeploy import ( "encoding/json" "fmt" + "io" "os" "path/filepath" "sort" @@ -57,25 +58,35 @@ type Network struct { // CreateNetworkFromTemplate uses the specified template to deploy a new private network // under the specified root directory. -func CreateNetworkFromTemplate(name, rootDir, templateFile, binDir string, importKeys bool, nodeExitCallback nodecontrol.AlgodExitErrorCallback, consensus config.ConsensusProtocols, overrideDevMode bool) (Network, error) { +func CreateNetworkFromTemplate(name, rootDir string, templateReader io.Reader, binDir string, importKeys bool, nodeExitCallback nodecontrol.AlgodExitErrorCallback, consensus config.ConsensusProtocols, overrideDevMode bool) (Network, error) { n := Network{ rootDir: rootDir, nodeExitCallback: nodeExitCallback, } n.cfg.Name = name - n.cfg.TemplateFile = templateFile - template, err := loadTemplate(templateFile) + var err error + var template NetworkTemplate + + err = loadTemplateFromReader(templateReader, &template) if err == nil { if overrideDevMode { template.Genesis.DevMode = true + if template.Genesis.NetworkName == "" { + template.Genesis.NetworkName = "devmodenet" + } if len(template.Nodes) > 0 { template.Nodes[0].IsRelay = false } + } else { + if template.Genesis.NetworkName == "" { + template.Genesis.NetworkName = "private network" + } } - err = template.Validate() + } else { + return n, err } - if err != nil { + if err = template.Validate(); err != nil { return n, err } diff --git a/netdeploy/networkTemplate.go b/netdeploy/networkTemplate.go index b0a913a445..f432e78726 100644 --- a/netdeploy/networkTemplate.go +++ b/netdeploy/networkTemplate.go @@ -172,6 +172,11 @@ func loadTemplate(templateFile string) (NetworkTemplate, error) { } func loadTemplateFromReader(reader io.Reader, template *NetworkTemplate) error { + + if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" { + // for arm machines, use smaller key dilution + template.Genesis.PartKeyDilution = 100 + } dec := json.NewDecoder(reader) return dec.Decode(template) } diff --git a/node/node.go b/node/node.go index 7b00751006..acd8bd04e5 100644 --- a/node/node.go +++ b/node/node.go @@ -186,6 +186,15 @@ func MakeFull(log logging.Logger, rootDir string, cfg config.Local, phonebookAdd if node.devMode { cfg.DisableNetworking = true + // TODO: Have a real security model. Some ideas: + // * devmode now uses a custom consensus.json file which sets this value. + // * private forks have a one time special block that changes the consensus version. + // * 'devmode' is like 'future' + // go ahead and put the "hack" in hackathon. + for idx, proto := range config.Consensus { + proto.DevMode = true + config.Consensus[idx] = proto + } } node.config = cfg diff --git a/test/framework/fixtures/libgoalFixture.go b/test/framework/fixtures/libgoalFixture.go index 7294bafc40..4c16ec8e26 100644 --- a/test/framework/fixtures/libgoalFixture.go +++ b/test/framework/fixtures/libgoalFixture.go @@ -19,6 +19,7 @@ package fixtures import ( "bufio" "fmt" + "io" "os" "os/exec" "path/filepath" @@ -96,7 +97,8 @@ func (f *LibGoalFixture) setup(test TestingTB, testName string, templateFile str os.RemoveAll(f.rootDir) templateFile = filepath.Join(f.testDataDir, templateFile) importKeys := false // Don't automatically import root keys when creating folders, we'll import on-demand - network, err := netdeploy.CreateNetworkFromTemplate("test", f.rootDir, templateFile, f.binDir, importKeys, f.nodeExitWithError, f.consensus, false) + var reader io.Reader + network, err := netdeploy.CreateNetworkFromTemplate("test", f.rootDir, reader, f.binDir, importKeys, f.nodeExitWithError, f.consensus, false) f.failOnError(err, "CreateNetworkFromTemplate failed: %v") f.network = network