diff --git a/future/transaction.go b/future/transaction.go index 11697c6c..642a4f66 100644 --- a/future/transaction.go +++ b/future/transaction.go @@ -1,9 +1,12 @@ package future import ( + "bytes" "encoding/base64" "fmt" + "github.com/algorand/go-algorand-sdk/crypto" + "github.com/algorand/go-algorand-sdk/encoding/msgpack" "github.com/algorand/go-algorand-sdk/transaction" "github.com/algorand/go-algorand-sdk/types" ) @@ -11,9 +14,12 @@ import ( // MinTxnFee is v5 consensus params, in microAlgos const MinTxnFee = transaction.MinTxnFee +// NumOfAdditionalBytesAfterSigning is the number of bytes added to a txn after signing it +const NumOfAdditionalBytesAfterSigning = 75 + func setFee(tx types.Transaction, params types.SuggestedParams) (types.Transaction, error) { if !params.FlatFee { - eSize, err := transaction.EstimateSize(tx) + eSize, err := EstimateSize(tx) if err != nil { return types.Transaction{}, err } @@ -1273,6 +1279,35 @@ func MakeApplicationCallTxWithBoxes( return setFee(tx, sp) } +// AssignGroupID computes and return list of transactions with Group field set. +// - txns is a list of transactions to process +// - account specifies a sender field of transaction to return. Set to empty string to return all of them +func AssignGroupID(txns []types.Transaction, account string) (result []types.Transaction, err error) { + gid, err := crypto.ComputeGroupID(txns) + if err != nil { + return + } + var decoded types.Address + if account != "" { + decoded, err = types.DecodeAddress(account) + if err != nil { + return + } + } + for _, tx := range txns { + if account == "" || bytes.Compare(tx.Sender[:], decoded[:]) == 0 { + tx.Group = gid + result = append(result, tx) + } + } + return result, nil +} + +// EstimateSize returns the estimated length of the encoded transaction +func EstimateSize(txn types.Transaction) (uint64, error) { + return uint64(len(msgpack.Encode(txn))) + NumOfAdditionalBytesAfterSigning, nil +} + func parseTxnAccounts(accounts []string) (parsed []types.Address, err error) { for _, acct := range accounts { addr, err := types.DecodeAddress(acct) diff --git a/future/transaction_test.go b/future/transaction_test.go index 7f6da1eb..0bd207a7 100644 --- a/future/transaction_test.go +++ b/future/transaction_test.go @@ -7,7 +7,6 @@ import ( "github.com/algorand/go-algorand-sdk/crypto" "github.com/algorand/go-algorand-sdk/encoding/msgpack" "github.com/algorand/go-algorand-sdk/mnemonic" - "github.com/algorand/go-algorand-sdk/transaction" "github.com/algorand/go-algorand-sdk/types" "github.com/stretchr/testify/require" ) @@ -841,15 +840,15 @@ func TestComputeGroupID(t *testing.T) { require.Equal(t, byteFromBase64(goldenTxg), txg) // check transaction.AssignGroupID, do not validate correctness of Group field calculation - result, err := transaction.AssignGroupID([]types.Transaction{tx1, tx2}, "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4") + result, err := AssignGroupID([]types.Transaction{tx1, tx2}, "BH55E5RMBD4GYWXGX5W5PJ5JAHPGM5OXKDQH5DC4O2MGI7NW4H6VOE4CP4") require.NoError(t, err) require.Equal(t, 0, len(result)) - result, err = transaction.AssignGroupID([]types.Transaction{tx1, tx2}, address) + result, err = AssignGroupID([]types.Transaction{tx1, tx2}, address) require.NoError(t, err) require.Equal(t, 2, len(result)) - result, err = transaction.AssignGroupID([]types.Transaction{tx1, tx2}, "") + result, err = AssignGroupID([]types.Transaction{tx1, tx2}, "") require.NoError(t, err) require.Equal(t, 2, len(result)) } diff --git a/transaction/transaction.go b/transaction/transaction.go index d112c60f..5c1ba7e8 100644 --- a/transaction/transaction.go +++ b/transaction/transaction.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/base64" "fmt" + "github.com/algorand/go-algorand-sdk/crypto" "github.com/algorand/go-algorand-sdk/encoding/msgpack" "github.com/algorand/go-algorand-sdk/types"