diff --git a/config/consensus.go b/config/consensus.go index ffa7dadaa3..566451d2b2 100644 --- a/config/consensus.go +++ b/config/consensus.go @@ -342,6 +342,10 @@ type ConsensusParams struct { // CompactCertSecKQ is the security parameter (k+q) for the compact // certificate scheme. CompactCertSecKQ uint64 + + // EnableAssetCloseAmount adds an extra field to the ApplyData. The field contains the amount of the remaining + // asset that were sent to the close-to address. + EnableAssetCloseAmount bool } // ConsensusProtocols defines a set of supported protocol versions and their @@ -827,6 +831,9 @@ func initConsensusProtocols() { vFuture.CompactCertWeightThreshold = (1 << 32) * 30 / 100 vFuture.CompactCertSecKQ = 128 + // Enable AssetCloseAmount field + vFuture.EnableAssetCloseAmount = true + Consensus[protocol.ConsensusFuture] = vFuture } diff --git a/daemon/algod/api/algod.oas2.json b/daemon/algod/api/algod.oas2.json index 87a98306ae..595cd752fd 100644 --- a/daemon/algod/api/algod.oas2.json +++ b/daemon/algod/api/algod.oas2.json @@ -2148,6 +2148,10 @@ "description": "Closing amount for the transaction.", "type": "integer" }, + "asset-closing-amount": { + "description": "The number of the asset's unit that were transferred to the close-to address.", + "type": "integer" + }, "confirmed-round": { "description": "The round where this transaction was confirmed, if present.", "type": "integer" diff --git a/daemon/algod/api/algod.oas3.yml b/daemon/algod/api/algod.oas3.yml index b38d27985f..78fe01e8a6 100644 --- a/daemon/algod/api/algod.oas3.yml +++ b/daemon/algod/api/algod.oas3.yml @@ -463,6 +463,10 @@ "description": "The application index if the transaction was found and it created an application.", "type": "integer" }, + "asset-closing-amount": { + "description": "The number of the asset's unit that were transferred to the close-to address.", + "type": "integer" + }, "asset-index": { "description": "The asset index if the transaction was found and it created an asset.", "type": "integer" @@ -3129,6 +3133,10 @@ "description": "The application index if the transaction was found and it created an application.", "type": "integer" }, + "asset-closing-amount": { + "description": "The number of the asset's unit that were transferred to the close-to address.", + "type": "integer" + }, "asset-index": { "description": "The asset index if the transaction was found and it created an asset.", "type": "integer" @@ -3189,6 +3197,10 @@ "description": "The application index if the transaction was found and it created an application.", "type": "integer" }, + "asset-closing-amount": { + "description": "The number of the asset's unit that were transferred to the close-to address.", + "type": "integer" + }, "asset-index": { "description": "The asset index if the transaction was found and it created an asset.", "type": "integer" diff --git a/daemon/algod/api/server/v1/handlers/handlers.go b/daemon/algod/api/server/v1/handlers/handlers.go index 1d9e8fe68a..1e3b0f634d 100644 --- a/daemon/algod/api/server/v1/handlers/handlers.go +++ b/daemon/algod/api/server/v1/handlers/handlers.go @@ -315,6 +315,10 @@ func assetTransferTxEncode(tx transactions.Transaction, ad transactions.ApplyDat xfer.CloseTo = tx.AssetTransferTxnFields.AssetCloseTo.String() } + if ad.AssetClosingAmount != 0 { + xfer.CloseToAmount = ad.AssetClosingAmount + } + return v1.Transaction{ AssetTransfer: &xfer, } diff --git a/daemon/algod/api/server/v2/generated/private/routes.go b/daemon/algod/api/server/v2/generated/private/routes.go index 8c3a30f411..2f3dce9817 100644 --- a/daemon/algod/api/server/v2/generated/private/routes.go +++ b/daemon/algod/api/server/v2/generated/private/routes.go @@ -272,95 +272,95 @@ var swaggerSpec = []string{ "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", - "eU/r6w/X/x0AAP//DI8H3kOGAAA=", + "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", } // GetSwagger returns the Swagger specification corresponding to the generated code diff --git a/daemon/algod/api/server/v2/generated/private/types.go b/daemon/algod/api/server/v2/generated/private/types.go index e8a30a9289..9ec60c2cbd 100644 --- a/daemon/algod/api/server/v2/generated/private/types.go +++ b/daemon/algod/api/server/v2/generated/private/types.go @@ -529,6 +529,9 @@ type PendingTransactionResponse struct { // The application index if the transaction was found and it created an application. ApplicationIndex *uint64 `json:"application-index,omitempty"` + // The number of the asset's unit that were transferred to the close-to address. + AssetClosingAmount *uint64 `json:"asset-closing-amount,omitempty"` + // The asset index if the transaction was found and it created an asset. AssetIndex *uint64 `json:"asset-index,omitempty"` diff --git a/daemon/algod/api/server/v2/generated/routes.go b/daemon/algod/api/server/v2/generated/routes.go index a84f3ce68e..32f6e331d4 100644 --- a/daemon/algod/api/server/v2/generated/routes.go +++ b/daemon/algod/api/server/v2/generated/routes.go @@ -561,170 +561,171 @@ func RegisterHandlers(router interface { // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", } // GetSwagger returns the Swagger specification corresponding to the generated code diff --git a/daemon/algod/api/server/v2/generated/types.go b/daemon/algod/api/server/v2/generated/types.go index ea289a1a74..0dfe5b7b8d 100644 --- a/daemon/algod/api/server/v2/generated/types.go +++ b/daemon/algod/api/server/v2/generated/types.go @@ -529,6 +529,9 @@ type PendingTransactionResponse struct { // The application index if the transaction was found and it created an application. ApplicationIndex *uint64 `json:"application-index,omitempty"` + // The number of the asset's unit that were transferred to the close-to address. + AssetClosingAmount *uint64 `json:"asset-closing-amount,omitempty"` + // The asset index if the transaction was found and it created an asset. AssetIndex *uint64 `json:"asset-index,omitempty"` diff --git a/daemon/algod/api/server/v2/handlers.go b/daemon/algod/api/server/v2/handlers.go index 58925aafc9..acc5605c98 100644 --- a/daemon/algod/api/server/v2/handlers.go +++ b/daemon/algod/api/server/v2/handlers.go @@ -442,17 +442,18 @@ func (v2 *Handlers) PendingTransactionInformation(ctx echo.Context, txid string, // Encoding wasn't working well without embedding "real" objects. response := struct { - AssetIndex *uint64 `codec:"asset-index,omitempty"` - ApplicationIndex *uint64 `codec:"application-index,omitempty"` - CloseRewards *uint64 `codec:"close-rewards,omitempty"` - ClosingAmount *uint64 `codec:"closing-amount,omitempty"` - ConfirmedRound *uint64 `codec:"confirmed-round,omitempty"` - GlobalStateDelta *generated.StateDelta `codec:"global-state-delta,omitempty"` - LocalStateDelta *[]generated.AccountStateDelta `codec:"local-state-delta,omitempty"` - PoolError string `codec:"pool-error"` - ReceiverRewards *uint64 `codec:"receiver-rewards,omitempty"` - SenderRewards *uint64 `codec:"sender-rewards,omitempty"` - Txn transactions.SignedTxn `codec:"txn"` + AssetIndex *uint64 `codec:"asset-index,omitempty"` + AssetClosingAmount *uint64 `codec:"asset-closing-amount,omitempty"` + ApplicationIndex *uint64 `codec:"application-index,omitempty"` + CloseRewards *uint64 `codec:"close-rewards,omitempty"` + ClosingAmount *uint64 `codec:"closing-amount,omitempty"` + ConfirmedRound *uint64 `codec:"confirmed-round,omitempty"` + GlobalStateDelta *generated.StateDelta `codec:"global-state-delta,omitempty"` + LocalStateDelta *[]generated.AccountStateDelta `codec:"local-state-delta,omitempty"` + PoolError string `codec:"pool-error"` + ReceiverRewards *uint64 `codec:"receiver-rewards,omitempty"` + SenderRewards *uint64 `codec:"sender-rewards,omitempty"` + Txn transactions.SignedTxn `codec:"txn"` }{ Txn: txn.Txn, } @@ -467,6 +468,7 @@ func (v2 *Handlers) PendingTransactionInformation(ctx echo.Context, txid string, response.ConfirmedRound = &r response.ClosingAmount = &txn.ApplyData.ClosingAmount.Raw + response.AssetClosingAmount = &txn.ApplyData.AssetClosingAmount response.SenderRewards = &txn.ApplyData.SenderRewards.Raw response.ReceiverRewards = &txn.ApplyData.ReceiverRewards.Raw response.CloseRewards = &txn.ApplyData.CloseRewards.Raw diff --git a/daemon/algod/api/spec/v1/model.go b/daemon/algod/api/spec/v1/model.go index b337752241..0219603c09 100644 --- a/daemon/algod/api/spec/v1/model.go +++ b/daemon/algod/api/spec/v1/model.go @@ -675,6 +675,11 @@ type AssetTransferTransactionType struct { // // required: false CloseTo string `json:"closeto"` + + // CloseToAmount is amount of the remaining funds that were transferred to the close to address (if closing). + // + // required: false + CloseToAmount uint64 `json:"closetoamount"` } // AssetFreezeTransactionType contains the additional fields for an asset freeze transaction diff --git a/data/transactions/msgp_gen.go b/data/transactions/msgp_gen.go index 2fa9abe868..98c1b86f9c 100644 --- a/data/transactions/msgp_gen.go +++ b/data/transactions/msgp_gen.go @@ -740,52 +740,61 @@ func (z *ApplicationCallTxnFields) MsgIsZero() bool { func (z *ApplyData) MarshalMsg(b []byte) (o []byte) { o = msgp.Require(b, z.Msgsize()) // omitempty: check for empty values - zb0001Len := uint32(5) - var zb0001Mask uint8 /* 6 bits */ - if (*z).ClosingAmount.MsgIsZero() { + zb0001Len := uint32(6) + var zb0001Mask uint8 /* 7 bits */ + if (*z).AssetClosingAmount == 0 { zb0001Len-- zb0001Mask |= 0x2 } - if (*z).EvalDelta.MsgIsZero() { + if (*z).ClosingAmount.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x4 } - if (*z).CloseRewards.MsgIsZero() { + if (*z).EvalDelta.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x8 } - if (*z).ReceiverRewards.MsgIsZero() { + if (*z).CloseRewards.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x10 } - if (*z).SenderRewards.MsgIsZero() { + if (*z).ReceiverRewards.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x20 } + if (*z).SenderRewards.MsgIsZero() { + zb0001Len-- + zb0001Mask |= 0x40 + } // variable map header, size zb0001Len o = append(o, 0x80|uint8(zb0001Len)) if zb0001Len != 0 { if (zb0001Mask & 0x2) == 0 { // if not empty + // string "aca" + o = append(o, 0xa3, 0x61, 0x63, 0x61) + o = msgp.AppendUint64(o, (*z).AssetClosingAmount) + } + if (zb0001Mask & 0x4) == 0 { // if not empty // string "ca" o = append(o, 0xa2, 0x63, 0x61) o = (*z).ClosingAmount.MarshalMsg(o) } - if (zb0001Mask & 0x4) == 0 { // if not empty + if (zb0001Mask & 0x8) == 0 { // if not empty // string "dt" o = append(o, 0xa2, 0x64, 0x74) o = (*z).EvalDelta.MarshalMsg(o) } - if (zb0001Mask & 0x8) == 0 { // if not empty + if (zb0001Mask & 0x10) == 0 { // if not empty // string "rc" o = append(o, 0xa2, 0x72, 0x63) o = (*z).CloseRewards.MarshalMsg(o) } - if (zb0001Mask & 0x10) == 0 { // if not empty + if (zb0001Mask & 0x20) == 0 { // if not empty // string "rr" o = append(o, 0xa2, 0x72, 0x72) o = (*z).ReceiverRewards.MarshalMsg(o) } - if (zb0001Mask & 0x20) == 0 { // if not empty + if (zb0001Mask & 0x40) == 0 { // if not empty // string "rs" o = append(o, 0xa2, 0x72, 0x73) o = (*z).SenderRewards.MarshalMsg(o) @@ -820,6 +829,14 @@ func (z *ApplyData) UnmarshalMsg(bts []byte) (o []byte, err error) { return } } + if zb0001 > 0 { + zb0001-- + (*z).AssetClosingAmount, bts, err = msgp.ReadUint64Bytes(bts) + if err != nil { + err = msgp.WrapError(err, "struct-from-array", "AssetClosingAmount") + return + } + } if zb0001 > 0 { zb0001-- bts, err = (*z).SenderRewards.UnmarshalMsg(bts) @@ -881,6 +898,12 @@ func (z *ApplyData) UnmarshalMsg(bts []byte) (o []byte, err error) { err = msgp.WrapError(err, "ClosingAmount") return } + case "aca": + (*z).AssetClosingAmount, bts, err = msgp.ReadUint64Bytes(bts) + if err != nil { + err = msgp.WrapError(err, "AssetClosingAmount") + return + } case "rs": bts, err = (*z).SenderRewards.UnmarshalMsg(bts) if err != nil { @@ -925,13 +948,13 @@ func (_ *ApplyData) CanUnmarshalMsg(z interface{}) bool { // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message func (z *ApplyData) Msgsize() (s int) { - s = 1 + 3 + (*z).ClosingAmount.Msgsize() + 3 + (*z).SenderRewards.Msgsize() + 3 + (*z).ReceiverRewards.Msgsize() + 3 + (*z).CloseRewards.Msgsize() + 3 + (*z).EvalDelta.Msgsize() + s = 1 + 3 + (*z).ClosingAmount.Msgsize() + 4 + msgp.Uint64Size + 3 + (*z).SenderRewards.Msgsize() + 3 + (*z).ReceiverRewards.Msgsize() + 3 + (*z).CloseRewards.Msgsize() + 3 + (*z).EvalDelta.Msgsize() return } // MsgIsZero returns whether this is a zero value func (z *ApplyData) MsgIsZero() bool { - return ((*z).ClosingAmount.MsgIsZero()) && ((*z).SenderRewards.MsgIsZero()) && ((*z).ReceiverRewards.MsgIsZero()) && ((*z).CloseRewards.MsgIsZero()) && ((*z).EvalDelta.MsgIsZero()) + return ((*z).ClosingAmount.MsgIsZero()) && ((*z).AssetClosingAmount == 0) && ((*z).SenderRewards.MsgIsZero()) && ((*z).ReceiverRewards.MsgIsZero()) && ((*z).CloseRewards.MsgIsZero()) && ((*z).EvalDelta.MsgIsZero()) } // MarshalMsg implements msgp.Marshaler @@ -2905,115 +2928,124 @@ func (z *SignedTxn) MsgIsZero() bool { func (z *SignedTxnInBlock) MarshalMsg(b []byte) (o []byte) { o = msgp.Require(b, z.Msgsize()) // omitempty: check for empty values - zb0001Len := uint32(12) - var zb0001Mask uint16 /* 16 bits */ - if (*z).SignedTxnWithAD.ApplyData.ClosingAmount.MsgIsZero() { + zb0001Len := uint32(13) + var zb0001Mask uint32 /* 17 bits */ + if (*z).SignedTxnWithAD.ApplyData.AssetClosingAmount == 0 { zb0001Len-- zb0001Mask |= 0x10 } - if (*z).SignedTxnWithAD.ApplyData.EvalDelta.MsgIsZero() { + if (*z).SignedTxnWithAD.ApplyData.ClosingAmount.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x20 } - if (*z).HasGenesisHash == false { + if (*z).SignedTxnWithAD.ApplyData.EvalDelta.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x40 } - if (*z).HasGenesisID == false { + if (*z).HasGenesisHash == false { zb0001Len-- zb0001Mask |= 0x80 } - if (*z).SignedTxnWithAD.SignedTxn.Lsig.MsgIsZero() { + if (*z).HasGenesisID == false { zb0001Len-- zb0001Mask |= 0x100 } - if (*z).SignedTxnWithAD.SignedTxn.Msig.MsgIsZero() { + if (*z).SignedTxnWithAD.SignedTxn.Lsig.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x200 } - if (*z).SignedTxnWithAD.ApplyData.CloseRewards.MsgIsZero() { + if (*z).SignedTxnWithAD.SignedTxn.Msig.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x400 } - if (*z).SignedTxnWithAD.ApplyData.ReceiverRewards.MsgIsZero() { + if (*z).SignedTxnWithAD.ApplyData.CloseRewards.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x800 } - if (*z).SignedTxnWithAD.ApplyData.SenderRewards.MsgIsZero() { + if (*z).SignedTxnWithAD.ApplyData.ReceiverRewards.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x1000 } - if (*z).SignedTxnWithAD.SignedTxn.AuthAddr.MsgIsZero() { + if (*z).SignedTxnWithAD.ApplyData.SenderRewards.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x2000 } - if (*z).SignedTxnWithAD.SignedTxn.Sig.MsgIsZero() { + if (*z).SignedTxnWithAD.SignedTxn.AuthAddr.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x4000 } - if (*z).SignedTxnWithAD.SignedTxn.Txn.MsgIsZero() { + if (*z).SignedTxnWithAD.SignedTxn.Sig.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x8000 } + if (*z).SignedTxnWithAD.SignedTxn.Txn.MsgIsZero() { + zb0001Len-- + zb0001Mask |= 0x10000 + } // variable map header, size zb0001Len o = append(o, 0x80|uint8(zb0001Len)) if zb0001Len != 0 { if (zb0001Mask & 0x10) == 0 { // if not empty + // string "aca" + o = append(o, 0xa3, 0x61, 0x63, 0x61) + o = msgp.AppendUint64(o, (*z).SignedTxnWithAD.ApplyData.AssetClosingAmount) + } + if (zb0001Mask & 0x20) == 0 { // if not empty // string "ca" o = append(o, 0xa2, 0x63, 0x61) o = (*z).SignedTxnWithAD.ApplyData.ClosingAmount.MarshalMsg(o) } - if (zb0001Mask & 0x20) == 0 { // if not empty + if (zb0001Mask & 0x40) == 0 { // if not empty // string "dt" o = append(o, 0xa2, 0x64, 0x74) o = (*z).SignedTxnWithAD.ApplyData.EvalDelta.MarshalMsg(o) } - if (zb0001Mask & 0x40) == 0 { // if not empty + if (zb0001Mask & 0x80) == 0 { // if not empty // string "hgh" o = append(o, 0xa3, 0x68, 0x67, 0x68) o = msgp.AppendBool(o, (*z).HasGenesisHash) } - if (zb0001Mask & 0x80) == 0 { // if not empty + if (zb0001Mask & 0x100) == 0 { // if not empty // string "hgi" o = append(o, 0xa3, 0x68, 0x67, 0x69) o = msgp.AppendBool(o, (*z).HasGenesisID) } - if (zb0001Mask & 0x100) == 0 { // if not empty + if (zb0001Mask & 0x200) == 0 { // if not empty // string "lsig" o = append(o, 0xa4, 0x6c, 0x73, 0x69, 0x67) o = (*z).SignedTxnWithAD.SignedTxn.Lsig.MarshalMsg(o) } - if (zb0001Mask & 0x200) == 0 { // if not empty + if (zb0001Mask & 0x400) == 0 { // if not empty // string "msig" o = append(o, 0xa4, 0x6d, 0x73, 0x69, 0x67) o = (*z).SignedTxnWithAD.SignedTxn.Msig.MarshalMsg(o) } - if (zb0001Mask & 0x400) == 0 { // if not empty + if (zb0001Mask & 0x800) == 0 { // if not empty // string "rc" o = append(o, 0xa2, 0x72, 0x63) o = (*z).SignedTxnWithAD.ApplyData.CloseRewards.MarshalMsg(o) } - if (zb0001Mask & 0x800) == 0 { // if not empty + if (zb0001Mask & 0x1000) == 0 { // if not empty // string "rr" o = append(o, 0xa2, 0x72, 0x72) o = (*z).SignedTxnWithAD.ApplyData.ReceiverRewards.MarshalMsg(o) } - if (zb0001Mask & 0x1000) == 0 { // if not empty + if (zb0001Mask & 0x2000) == 0 { // if not empty // string "rs" o = append(o, 0xa2, 0x72, 0x73) o = (*z).SignedTxnWithAD.ApplyData.SenderRewards.MarshalMsg(o) } - if (zb0001Mask & 0x2000) == 0 { // if not empty + if (zb0001Mask & 0x4000) == 0 { // if not empty // string "sgnr" o = append(o, 0xa4, 0x73, 0x67, 0x6e, 0x72) o = (*z).SignedTxnWithAD.SignedTxn.AuthAddr.MarshalMsg(o) } - if (zb0001Mask & 0x4000) == 0 { // if not empty + if (zb0001Mask & 0x8000) == 0 { // if not empty // string "sig" o = append(o, 0xa3, 0x73, 0x69, 0x67) o = (*z).SignedTxnWithAD.SignedTxn.Sig.MarshalMsg(o) } - if (zb0001Mask & 0x8000) == 0 { // if not empty + if (zb0001Mask & 0x10000) == 0 { // if not empty // string "txn" o = append(o, 0xa3, 0x74, 0x78, 0x6e) o = (*z).SignedTxnWithAD.SignedTxn.Txn.MarshalMsg(o) @@ -3088,6 +3120,14 @@ func (z *SignedTxnInBlock) UnmarshalMsg(bts []byte) (o []byte, err error) { return } } + if zb0001 > 0 { + zb0001-- + (*z).SignedTxnWithAD.ApplyData.AssetClosingAmount, bts, err = msgp.ReadUint64Bytes(bts) + if err != nil { + err = msgp.WrapError(err, "struct-from-array", "AssetClosingAmount") + return + } + } if zb0001 > 0 { zb0001-- bts, err = (*z).SignedTxnWithAD.ApplyData.SenderRewards.UnmarshalMsg(bts) @@ -3195,6 +3235,12 @@ func (z *SignedTxnInBlock) UnmarshalMsg(bts []byte) (o []byte, err error) { err = msgp.WrapError(err, "ClosingAmount") return } + case "aca": + (*z).SignedTxnWithAD.ApplyData.AssetClosingAmount, bts, err = msgp.ReadUint64Bytes(bts) + if err != nil { + err = msgp.WrapError(err, "AssetClosingAmount") + return + } case "rs": bts, err = (*z).SignedTxnWithAD.ApplyData.SenderRewards.UnmarshalMsg(bts) if err != nil { @@ -3251,110 +3297,119 @@ func (_ *SignedTxnInBlock) CanUnmarshalMsg(z interface{}) bool { // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message func (z *SignedTxnInBlock) Msgsize() (s int) { - s = 1 + 4 + (*z).SignedTxnWithAD.SignedTxn.Sig.Msgsize() + 5 + (*z).SignedTxnWithAD.SignedTxn.Msig.Msgsize() + 5 + (*z).SignedTxnWithAD.SignedTxn.Lsig.Msgsize() + 4 + (*z).SignedTxnWithAD.SignedTxn.Txn.Msgsize() + 5 + (*z).SignedTxnWithAD.SignedTxn.AuthAddr.Msgsize() + 3 + (*z).SignedTxnWithAD.ApplyData.ClosingAmount.Msgsize() + 3 + (*z).SignedTxnWithAD.ApplyData.SenderRewards.Msgsize() + 3 + (*z).SignedTxnWithAD.ApplyData.ReceiverRewards.Msgsize() + 3 + (*z).SignedTxnWithAD.ApplyData.CloseRewards.Msgsize() + 3 + (*z).SignedTxnWithAD.ApplyData.EvalDelta.Msgsize() + 4 + msgp.BoolSize + 4 + msgp.BoolSize + s = 1 + 4 + (*z).SignedTxnWithAD.SignedTxn.Sig.Msgsize() + 5 + (*z).SignedTxnWithAD.SignedTxn.Msig.Msgsize() + 5 + (*z).SignedTxnWithAD.SignedTxn.Lsig.Msgsize() + 4 + (*z).SignedTxnWithAD.SignedTxn.Txn.Msgsize() + 5 + (*z).SignedTxnWithAD.SignedTxn.AuthAddr.Msgsize() + 3 + (*z).SignedTxnWithAD.ApplyData.ClosingAmount.Msgsize() + 4 + msgp.Uint64Size + 3 + (*z).SignedTxnWithAD.ApplyData.SenderRewards.Msgsize() + 3 + (*z).SignedTxnWithAD.ApplyData.ReceiverRewards.Msgsize() + 3 + (*z).SignedTxnWithAD.ApplyData.CloseRewards.Msgsize() + 3 + (*z).SignedTxnWithAD.ApplyData.EvalDelta.Msgsize() + 4 + msgp.BoolSize + 4 + msgp.BoolSize return } // MsgIsZero returns whether this is a zero value func (z *SignedTxnInBlock) MsgIsZero() bool { - return ((*z).SignedTxnWithAD.SignedTxn.Sig.MsgIsZero()) && ((*z).SignedTxnWithAD.SignedTxn.Msig.MsgIsZero()) && ((*z).SignedTxnWithAD.SignedTxn.Lsig.MsgIsZero()) && ((*z).SignedTxnWithAD.SignedTxn.Txn.MsgIsZero()) && ((*z).SignedTxnWithAD.SignedTxn.AuthAddr.MsgIsZero()) && ((*z).SignedTxnWithAD.ApplyData.ClosingAmount.MsgIsZero()) && ((*z).SignedTxnWithAD.ApplyData.SenderRewards.MsgIsZero()) && ((*z).SignedTxnWithAD.ApplyData.ReceiverRewards.MsgIsZero()) && ((*z).SignedTxnWithAD.ApplyData.CloseRewards.MsgIsZero()) && ((*z).SignedTxnWithAD.ApplyData.EvalDelta.MsgIsZero()) && ((*z).HasGenesisID == false) && ((*z).HasGenesisHash == false) + return ((*z).SignedTxnWithAD.SignedTxn.Sig.MsgIsZero()) && ((*z).SignedTxnWithAD.SignedTxn.Msig.MsgIsZero()) && ((*z).SignedTxnWithAD.SignedTxn.Lsig.MsgIsZero()) && ((*z).SignedTxnWithAD.SignedTxn.Txn.MsgIsZero()) && ((*z).SignedTxnWithAD.SignedTxn.AuthAddr.MsgIsZero()) && ((*z).SignedTxnWithAD.ApplyData.ClosingAmount.MsgIsZero()) && ((*z).SignedTxnWithAD.ApplyData.AssetClosingAmount == 0) && ((*z).SignedTxnWithAD.ApplyData.SenderRewards.MsgIsZero()) && ((*z).SignedTxnWithAD.ApplyData.ReceiverRewards.MsgIsZero()) && ((*z).SignedTxnWithAD.ApplyData.CloseRewards.MsgIsZero()) && ((*z).SignedTxnWithAD.ApplyData.EvalDelta.MsgIsZero()) && ((*z).HasGenesisID == false) && ((*z).HasGenesisHash == false) } // MarshalMsg implements msgp.Marshaler func (z *SignedTxnWithAD) MarshalMsg(b []byte) (o []byte) { o = msgp.Require(b, z.Msgsize()) // omitempty: check for empty values - zb0001Len := uint32(10) - var zb0001Mask uint16 /* 13 bits */ - if (*z).ApplyData.ClosingAmount.MsgIsZero() { + zb0001Len := uint32(11) + var zb0001Mask uint16 /* 14 bits */ + if (*z).ApplyData.AssetClosingAmount == 0 { zb0001Len-- zb0001Mask |= 0x8 } - if (*z).ApplyData.EvalDelta.MsgIsZero() { + if (*z).ApplyData.ClosingAmount.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x10 } - if (*z).SignedTxn.Lsig.MsgIsZero() { + if (*z).ApplyData.EvalDelta.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x20 } - if (*z).SignedTxn.Msig.MsgIsZero() { + if (*z).SignedTxn.Lsig.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x40 } - if (*z).ApplyData.CloseRewards.MsgIsZero() { + if (*z).SignedTxn.Msig.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x80 } - if (*z).ApplyData.ReceiverRewards.MsgIsZero() { + if (*z).ApplyData.CloseRewards.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x100 } - if (*z).ApplyData.SenderRewards.MsgIsZero() { + if (*z).ApplyData.ReceiverRewards.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x200 } - if (*z).SignedTxn.AuthAddr.MsgIsZero() { + if (*z).ApplyData.SenderRewards.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x400 } - if (*z).SignedTxn.Sig.MsgIsZero() { + if (*z).SignedTxn.AuthAddr.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x800 } - if (*z).SignedTxn.Txn.MsgIsZero() { + if (*z).SignedTxn.Sig.MsgIsZero() { zb0001Len-- zb0001Mask |= 0x1000 } + if (*z).SignedTxn.Txn.MsgIsZero() { + zb0001Len-- + zb0001Mask |= 0x2000 + } // variable map header, size zb0001Len o = append(o, 0x80|uint8(zb0001Len)) if zb0001Len != 0 { if (zb0001Mask & 0x8) == 0 { // if not empty + // string "aca" + o = append(o, 0xa3, 0x61, 0x63, 0x61) + o = msgp.AppendUint64(o, (*z).ApplyData.AssetClosingAmount) + } + if (zb0001Mask & 0x10) == 0 { // if not empty // string "ca" o = append(o, 0xa2, 0x63, 0x61) o = (*z).ApplyData.ClosingAmount.MarshalMsg(o) } - if (zb0001Mask & 0x10) == 0 { // if not empty + if (zb0001Mask & 0x20) == 0 { // if not empty // string "dt" o = append(o, 0xa2, 0x64, 0x74) o = (*z).ApplyData.EvalDelta.MarshalMsg(o) } - if (zb0001Mask & 0x20) == 0 { // if not empty + if (zb0001Mask & 0x40) == 0 { // if not empty // string "lsig" o = append(o, 0xa4, 0x6c, 0x73, 0x69, 0x67) o = (*z).SignedTxn.Lsig.MarshalMsg(o) } - if (zb0001Mask & 0x40) == 0 { // if not empty + if (zb0001Mask & 0x80) == 0 { // if not empty // string "msig" o = append(o, 0xa4, 0x6d, 0x73, 0x69, 0x67) o = (*z).SignedTxn.Msig.MarshalMsg(o) } - if (zb0001Mask & 0x80) == 0 { // if not empty + if (zb0001Mask & 0x100) == 0 { // if not empty // string "rc" o = append(o, 0xa2, 0x72, 0x63) o = (*z).ApplyData.CloseRewards.MarshalMsg(o) } - if (zb0001Mask & 0x100) == 0 { // if not empty + if (zb0001Mask & 0x200) == 0 { // if not empty // string "rr" o = append(o, 0xa2, 0x72, 0x72) o = (*z).ApplyData.ReceiverRewards.MarshalMsg(o) } - if (zb0001Mask & 0x200) == 0 { // if not empty + if (zb0001Mask & 0x400) == 0 { // if not empty // string "rs" o = append(o, 0xa2, 0x72, 0x73) o = (*z).ApplyData.SenderRewards.MarshalMsg(o) } - if (zb0001Mask & 0x400) == 0 { // if not empty + if (zb0001Mask & 0x800) == 0 { // if not empty // string "sgnr" o = append(o, 0xa4, 0x73, 0x67, 0x6e, 0x72) o = (*z).SignedTxn.AuthAddr.MarshalMsg(o) } - if (zb0001Mask & 0x800) == 0 { // if not empty + if (zb0001Mask & 0x1000) == 0 { // if not empty // string "sig" o = append(o, 0xa3, 0x73, 0x69, 0x67) o = (*z).SignedTxn.Sig.MarshalMsg(o) } - if (zb0001Mask & 0x1000) == 0 { // if not empty + if (zb0001Mask & 0x2000) == 0 { // if not empty // string "txn" o = append(o, 0xa3, 0x74, 0x78, 0x6e) o = (*z).SignedTxn.Txn.MarshalMsg(o) @@ -3429,6 +3484,14 @@ func (z *SignedTxnWithAD) UnmarshalMsg(bts []byte) (o []byte, err error) { return } } + if zb0001 > 0 { + zb0001-- + (*z).ApplyData.AssetClosingAmount, bts, err = msgp.ReadUint64Bytes(bts) + if err != nil { + err = msgp.WrapError(err, "struct-from-array", "AssetClosingAmount") + return + } + } if zb0001 > 0 { zb0001-- bts, err = (*z).ApplyData.SenderRewards.UnmarshalMsg(bts) @@ -3520,6 +3583,12 @@ func (z *SignedTxnWithAD) UnmarshalMsg(bts []byte) (o []byte, err error) { err = msgp.WrapError(err, "ClosingAmount") return } + case "aca": + (*z).ApplyData.AssetClosingAmount, bts, err = msgp.ReadUint64Bytes(bts) + if err != nil { + err = msgp.WrapError(err, "AssetClosingAmount") + return + } case "rs": bts, err = (*z).ApplyData.SenderRewards.UnmarshalMsg(bts) if err != nil { @@ -3564,13 +3633,13 @@ func (_ *SignedTxnWithAD) CanUnmarshalMsg(z interface{}) bool { // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message func (z *SignedTxnWithAD) Msgsize() (s int) { - s = 1 + 4 + (*z).SignedTxn.Sig.Msgsize() + 5 + (*z).SignedTxn.Msig.Msgsize() + 5 + (*z).SignedTxn.Lsig.Msgsize() + 4 + (*z).SignedTxn.Txn.Msgsize() + 5 + (*z).SignedTxn.AuthAddr.Msgsize() + 3 + (*z).ApplyData.ClosingAmount.Msgsize() + 3 + (*z).ApplyData.SenderRewards.Msgsize() + 3 + (*z).ApplyData.ReceiverRewards.Msgsize() + 3 + (*z).ApplyData.CloseRewards.Msgsize() + 3 + (*z).ApplyData.EvalDelta.Msgsize() + s = 1 + 4 + (*z).SignedTxn.Sig.Msgsize() + 5 + (*z).SignedTxn.Msig.Msgsize() + 5 + (*z).SignedTxn.Lsig.Msgsize() + 4 + (*z).SignedTxn.Txn.Msgsize() + 5 + (*z).SignedTxn.AuthAddr.Msgsize() + 3 + (*z).ApplyData.ClosingAmount.Msgsize() + 4 + msgp.Uint64Size + 3 + (*z).ApplyData.SenderRewards.Msgsize() + 3 + (*z).ApplyData.ReceiverRewards.Msgsize() + 3 + (*z).ApplyData.CloseRewards.Msgsize() + 3 + (*z).ApplyData.EvalDelta.Msgsize() return } // MsgIsZero returns whether this is a zero value func (z *SignedTxnWithAD) MsgIsZero() bool { - return ((*z).SignedTxn.Sig.MsgIsZero()) && ((*z).SignedTxn.Msig.MsgIsZero()) && ((*z).SignedTxn.Lsig.MsgIsZero()) && ((*z).SignedTxn.Txn.MsgIsZero()) && ((*z).SignedTxn.AuthAddr.MsgIsZero()) && ((*z).ApplyData.ClosingAmount.MsgIsZero()) && ((*z).ApplyData.SenderRewards.MsgIsZero()) && ((*z).ApplyData.ReceiverRewards.MsgIsZero()) && ((*z).ApplyData.CloseRewards.MsgIsZero()) && ((*z).ApplyData.EvalDelta.MsgIsZero()) + return ((*z).SignedTxn.Sig.MsgIsZero()) && ((*z).SignedTxn.Msig.MsgIsZero()) && ((*z).SignedTxn.Lsig.MsgIsZero()) && ((*z).SignedTxn.Txn.MsgIsZero()) && ((*z).SignedTxn.AuthAddr.MsgIsZero()) && ((*z).ApplyData.ClosingAmount.MsgIsZero()) && ((*z).ApplyData.AssetClosingAmount == 0) && ((*z).ApplyData.SenderRewards.MsgIsZero()) && ((*z).ApplyData.ReceiverRewards.MsgIsZero()) && ((*z).ApplyData.CloseRewards.MsgIsZero()) && ((*z).ApplyData.EvalDelta.MsgIsZero()) } // MarshalMsg implements msgp.Marshaler diff --git a/data/transactions/transaction.go b/data/transactions/transaction.go index 03270d7d68..4c30d1c3bc 100644 --- a/data/transactions/transaction.go +++ b/data/transactions/transaction.go @@ -104,6 +104,9 @@ type ApplyData struct { // Closing amount for transaction. ClosingAmount basics.MicroAlgos `codec:"ca"` + // Closing amount for asset transaction. + AssetClosingAmount uint64 `codec:"aca"` + // Rewards applied to the Sender, Receiver, and CloseRemainderTo accounts. SenderRewards basics.MicroAlgos `codec:"rs"` ReceiverRewards basics.MicroAlgos `codec:"rr"` @@ -117,6 +120,9 @@ func (ad ApplyData) Equal(o ApplyData) bool { if ad.ClosingAmount != o.ClosingAmount { return false } + if ad.AssetClosingAmount != o.AssetClosingAmount { + return false + } if ad.SenderRewards != o.SenderRewards { return false } diff --git a/ledger/apply/asset.go b/ledger/apply/asset.go index fa31a9ec2a..7f745bda03 100644 --- a/ledger/apply/asset.go +++ b/ledger/apply/asset.go @@ -330,6 +330,13 @@ func AssetTransfer(ct transactions.AssetTransferTxnFields, header transactions.H // and putIn will short circuit (so bypassFreeze doesn't matter) _, bypassFreeze := dst.AssetParams[ct.XferAsset] + // AssetCloseAmount was a late addition, checking that the current protocol version supports it. + if balances.ConsensusParams().EnableAssetCloseAmount { + // Add the close amount to ApplyData. + closeAmount := sndHolding.Amount + ad.AssetClosingAmount = closeAmount + } + // Move the balance out. err = takeOut(balances, source, ct.XferAsset, sndHolding.Amount, bypassFreeze) if err != nil { diff --git a/ledger/apply/asset_test.go b/ledger/apply/asset_test.go new file mode 100644 index 0000000000..44b6ab665b --- /dev/null +++ b/ledger/apply/asset_test.go @@ -0,0 +1,99 @@ +// Copyright (C) 2019-2021 Algorand, Inc. +// This file is part of go-algorand +// +// go-algorand is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// go-algorand is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with go-algorand. If not, see . + +package apply + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/algorand/go-algorand/config" + "github.com/algorand/go-algorand/data/basics" + "github.com/algorand/go-algorand/data/transactions" + "github.com/algorand/go-algorand/protocol" +) + +func TestAssetTransfer(t *testing.T) { + // Creator + secretSrc := keypair() + src := basics.Address(secretSrc.SignatureVerifier) + + secretDst := keypair() + dst := basics.Address(secretDst.SignatureVerifier) + + secretCls := keypair() + cls := basics.Address(secretCls.SignatureVerifier) + + var total, toSend, dstAmount uint64 + total = 1000000 + dstAmount = 500 + toSend = 200 + + // prepare data + var addrs = map[basics.Address]basics.AccountData{ + src: { + MicroAlgos: basics.MicroAlgos{Raw: 10000000}, + AssetParams: map[basics.AssetIndex]basics.AssetParams{ + 1: {Total: total}, + }, + Assets: map[basics.AssetIndex]basics.AssetHolding{ + 1: {Amount: total - dstAmount}, + }, + }, + dst: { + MicroAlgos: basics.MicroAlgos{Raw: 10000000}, + Assets: map[basics.AssetIndex]basics.AssetHolding{ + 1: {Amount: dstAmount}, + }, + }, + cls: { + MicroAlgos: basics.MicroAlgos{Raw: 10000000}, + Assets: map[basics.AssetIndex]basics.AssetHolding{ + 1: {Amount: 0}, + }, + }, + } + + mockBal := makeMockBalancesWithAccounts(protocol.ConsensusCurrentVersion, addrs) + + tx := transactions.Transaction{ + Type: protocol.AssetTransferTx, + Header: transactions.Header{ + Sender: dst, + Fee: basics.MicroAlgos{Raw: 1}, + FirstValid: basics.Round(100), + LastValid: basics.Round(1000), + }, + AssetTransferTxnFields: transactions.AssetTransferTxnFields{ + XferAsset: 1, + AssetAmount: toSend, + AssetReceiver: src, + AssetCloseTo: cls, + }, + } + + var ad transactions.ApplyData + err := AssetTransfer(tx.AssetTransferTxnFields, tx.Header, mockBal, transactions.SpecialAddresses{FeeSink: feeSink}, &ad) + require.NoError(t, err) + + if config.Consensus[protocol.ConsensusCurrentVersion].EnableAssetCloseAmount { + require.Equal(t, uint64(0), addrs[dst].Assets[1].Amount) + require.Equal(t, dstAmount-toSend, ad.AssetClosingAmount) + require.Equal(t, total-dstAmount+toSend, addrs[src].Assets[1].Amount) + require.Equal(t, dstAmount-toSend, addrs[cls].Assets[1].Amount) + } +} diff --git a/ledger/apply/keyreg_test.go b/ledger/apply/keyreg_test.go index dfd794f857..044d587a5f 100644 --- a/ledger/apply/keyreg_test.go +++ b/ledger/apply/keyreg_test.go @@ -95,11 +95,11 @@ func TestKeyregApply(t *testing.T) { SelectionPK: vrfSecrets.PK, }, } - err := Keyreg(tx.KeyregTxnFields, tx.Header, mockBalances{protocol.ConsensusCurrentVersion}, transactions.SpecialAddresses{FeeSink: feeSink}, nil) + err := Keyreg(tx.KeyregTxnFields, tx.Header, makeMockBalances(protocol.ConsensusCurrentVersion), transactions.SpecialAddresses{FeeSink: feeSink}, nil) require.NoError(t, err) tx.Sender = feeSink - err = Keyreg(tx.KeyregTxnFields, tx.Header, mockBalances{protocol.ConsensusCurrentVersion}, transactions.SpecialAddresses{FeeSink: feeSink}, nil) + err = Keyreg(tx.KeyregTxnFields, tx.Header, makeMockBalances(protocol.ConsensusCurrentVersion), transactions.SpecialAddresses{FeeSink: feeSink}, nil) require.Error(t, err) tx.Sender = src diff --git a/ledger/apply/mockBalances.go b/ledger/apply/mockBalances.go new file mode 100644 index 0000000000..89f5f68b8f --- /dev/null +++ b/ledger/apply/mockBalances.go @@ -0,0 +1,84 @@ +// Copyright (C) 2019-2021 Algorand, Inc. +// This file is part of go-algorand +// +// go-algorand is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// go-algorand is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with go-algorand. If not, see . + +package apply + +import ( + "github.com/algorand/go-algorand/config" + "github.com/algorand/go-algorand/data/basics" + "github.com/algorand/go-algorand/data/transactions/logic" + "github.com/algorand/go-algorand/protocol" +) + +type mockBalances struct { + protocol.ConsensusVersion + b map[basics.Address]basics.AccountData +} + +func makeMockBalances(cv protocol.ConsensusVersion) *mockBalances { + return &mockBalances{ + ConsensusVersion: cv, + b: map[basics.Address]basics.AccountData{}, + } +} + +func makeMockBalancesWithAccounts(cv protocol.ConsensusVersion, b map[basics.Address]basics.AccountData) *mockBalances { + return &mockBalances{ + ConsensusVersion: cv, + b: b, + } +} + +func (balances mockBalances) Round() basics.Round { + return basics.Round(8675309) +} + +func (balances mockBalances) Allocate(basics.Address, basics.AppIndex, bool, basics.StateSchema) error { + return nil +} + +func (balances mockBalances) Deallocate(basics.Address, basics.AppIndex, bool) error { + return nil +} + +func (balances mockBalances) StatefulEval(logic.EvalParams, basics.AppIndex, []byte) (bool, basics.EvalDelta, error) { + return false, basics.EvalDelta{}, nil +} + +func (balances mockBalances) PutWithCreatable(basics.Address, basics.AccountData, *basics.CreatableLocator, *basics.CreatableLocator) error { + return nil +} + +func (balances mockBalances) Get(addr basics.Address, withPendingRewards bool) (basics.AccountData, error) { + return balances.b[addr], nil +} + +func (balances mockBalances) GetCreator(idx basics.CreatableIndex, ctype basics.CreatableType) (basics.Address, bool, error) { + return basics.Address{}, true, nil +} + +func (balances mockBalances) Put(addr basics.Address, ad basics.AccountData) error { + balances.b[addr] = ad + return nil +} + +func (balances mockBalances) Move(src, dst basics.Address, amount basics.MicroAlgos, srcRewards, dstRewards *basics.MicroAlgos) error { + return nil +} + +func (balances mockBalances) ConsensusParams() config.ConsensusParams { + return config.Consensus[balances.ConsensusVersion] +} diff --git a/ledger/apply/payment_test.go b/ledger/apply/payment_test.go index 11371f3af0..c54dd8f334 100644 --- a/ledger/apply/payment_test.go +++ b/ledger/apply/payment_test.go @@ -26,7 +26,6 @@ import ( "github.com/algorand/go-algorand/crypto" "github.com/algorand/go-algorand/data/basics" "github.com/algorand/go-algorand/data/transactions" - "github.com/algorand/go-algorand/data/transactions/logic" "github.com/algorand/go-algorand/protocol" ) @@ -77,52 +76,8 @@ func TestAlgosEncoding(t *testing.T) { } } -type mockBalances struct { - protocol.ConsensusVersion -} - -func (balances mockBalances) Round() basics.Round { - return basics.Round(8675309) -} - -func (balances mockBalances) Allocate(basics.Address, basics.AppIndex, bool, basics.StateSchema) error { - return nil -} - -func (balances mockBalances) Deallocate(basics.Address, basics.AppIndex, bool) error { - return nil -} - -func (balances mockBalances) StatefulEval(logic.EvalParams, basics.AppIndex, []byte) (bool, basics.EvalDelta, error) { - return false, basics.EvalDelta{}, nil -} - -func (balances mockBalances) PutWithCreatable(basics.Address, basics.AccountData, *basics.CreatableLocator, *basics.CreatableLocator) error { - return nil -} - -func (balances mockBalances) Get(basics.Address, bool) (basics.AccountData, error) { - return basics.AccountData{}, nil -} - -func (balances mockBalances) GetCreator(idx basics.CreatableIndex, ctype basics.CreatableType) (basics.Address, bool, error) { - return basics.Address{}, true, nil -} - -func (balances mockBalances) Put(basics.Address, basics.AccountData) error { - return nil -} - -func (balances mockBalances) Move(src, dst basics.Address, amount basics.MicroAlgos, srcRewards, dstRewards *basics.MicroAlgos) error { - return nil -} - -func (balances mockBalances) ConsensusParams() config.ConsensusParams { - return config.Consensus[balances.ConsensusVersion] -} - func TestPaymentApply(t *testing.T) { - mockBalV0 := mockBalances{protocol.ConsensusCurrentVersion} + mockBalV0 := makeMockBalances(protocol.ConsensusCurrentVersion) secretSrc := keypair() src := basics.Address(secretSrc.SignatureVerifier) @@ -149,8 +104,8 @@ func TestPaymentApply(t *testing.T) { } func TestCheckSpender(t *testing.T) { - mockBalV0 := mockBalances{protocol.ConsensusCurrentVersion} - mockBalV7 := mockBalances{protocol.ConsensusV7} + mockBalV0 := makeMockBalances(protocol.ConsensusCurrentVersion) + mockBalV7 := makeMockBalances(protocol.ConsensusV7) secretSrc := keypair() src := basics.Address(secretSrc.SignatureVerifier)