Skip to content

Commit

Permalink
Merge branch 'release/v1.24.0'
Browse files Browse the repository at this point in the history
excalq committed Dec 6, 2022
2 parents f29a667 + f29b791 commit 4781c16
Showing 13 changed files with 383 additions and 230 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
# 1.24.0
## What's Changed
### Bugfixes
* BugFix: Fix disassemble endpoint by @zyablitsev in https://github.com/algorand/go-algorand-sdk/pull/436
### Enhancements
* Tests: Support for new cucumber app call txn decoding test by @jasonpaulos in https://github.com/algorand/go-algorand-sdk/pull/433
* Tests: Migrate v1 algod dependencies to v2 in cucumber tests by @algochoi in https://github.com/algorand/go-algorand-sdk/pull/434
* REST API: Add KV counts to NodeStatusResponse by @michaeldiamant in https://github.com/algorand/go-algorand-sdk/pull/437
* Enhancement: allowing zero length static array by @ahangsu in https://github.com/algorand/go-algorand-sdk/pull/438
* Enhancement: revert generic StateProof txn field by @shiqizng in https://github.com/algorand/go-algorand-sdk/pull/439
* Refactoring: Move old transaction dependencies to future.transaction by @algochoi in https://github.com/algorand/go-algorand-sdk/pull/435

## New Contributors
* @zyablitsev made their first contribution in https://github.com/algorand/go-algorand-sdk/pull/436

**Full Changelog**: https://github.com/algorand/go-algorand-sdk/compare/v1.23.0...v1.24.0

# 1.23.0
## What's Changed
### New Features
2 changes: 1 addition & 1 deletion client/v2/algod/tealDisassemble.go
Original file line number Diff line number Diff line change
@@ -18,6 +18,6 @@ type TealDisassemble struct {

// Do performs the HTTP request
func (s *TealDisassemble) Do(ctx context.Context, headers ...*common.Header) (response models.DisassembleResponse, err error) {
err = s.c.get(ctx, &response, "/v2/teal/disassemble", nil, headers)
err = s.c.post(ctx, &response, "/v2/teal/disassemble", nil, headers, s.source)
return
}
7 changes: 4 additions & 3 deletions client/v2/common/common.go
Original file line number Diff line number Diff line change
@@ -17,9 +17,10 @@ import (

// rawRequestPaths is a set of paths where the body should not be urlencoded
var rawRequestPaths = map[string]bool{
"/v2/transactions": true,
"/v2/teal/compile": true,
"/v2/teal/dryrun": true,
"/v2/transactions": true,
"/v2/teal/compile": true,
"/v2/teal/disassemble": true,
"/v2/teal/dryrun": true,
}

// Header is a struct for custom headers.
12 changes: 12 additions & 0 deletions client/v2/common/models/node_status_response.go
Original file line number Diff line number Diff line change
@@ -13,6 +13,10 @@ type NodeStatusResponse struct {
// that have been processed so far as part of the catchup
CatchpointProcessedAccounts uint64 `json:"catchpoint-processed-accounts,omitempty"`

// CatchpointProcessedKvs the number of key-values (KVs) from the current
// catchpoint that have been processed so far as part of the catchup
CatchpointProcessedKvs uint64 `json:"catchpoint-processed-kvs,omitempty"`

// CatchpointTotalAccounts the total number of accounts included in the current
// catchpoint
CatchpointTotalAccounts uint64 `json:"catchpoint-total-accounts,omitempty"`
@@ -21,10 +25,18 @@ type NodeStatusResponse struct {
// the current catchpoint catchup
CatchpointTotalBlocks uint64 `json:"catchpoint-total-blocks,omitempty"`

// CatchpointTotalKvs the total number of key-values (KVs) included in the current
// catchpoint
CatchpointTotalKvs uint64 `json:"catchpoint-total-kvs,omitempty"`

// CatchpointVerifiedAccounts the number of accounts from the current catchpoint
// that have been verified so far as part of the catchup
CatchpointVerifiedAccounts uint64 `json:"catchpoint-verified-accounts,omitempty"`

// CatchpointVerifiedKvs the number of key-values (KVs) from the current catchpoint
// that have been verified so far as part of the catchup
CatchpointVerifiedKvs uint64 `json:"catchpoint-verified-kvs,omitempty"`

// CatchupTime catchupTime in nanoseconds
CatchupTime uint64 `json:"catchup-time"`

37 changes: 36 additions & 1 deletion future/transaction.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
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"
)

// 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)
7 changes: 3 additions & 4 deletions future/transaction_test.go
Original file line number Diff line number Diff line change
@@ -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))
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ module github.com/algorand/go-algorand-sdk
go 1.17

require (
github.com/algorand/avm-abi v0.1.0
github.com/algorand/avm-abi v0.1.1
github.com/algorand/go-codec/codec v1.1.8
github.com/cucumber/godog v0.8.1
github.com/google/go-querystring v1.0.0
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
github.com/algorand/avm-abi v0.1.0 h1:znZFQXpSUVYz37vXbaH5OZG2VK4snTyXwnc/tV9CVr4=
github.com/algorand/avm-abi v0.1.0/go.mod h1:+CgwM46dithy850bpTeHh9MC99zpn2Snirb3QTl2O/g=
github.com/algorand/avm-abi v0.1.1 h1:dbyQKzXiyaEbzpmqXFB30yAhyqseBsyqXTyZbNbkh2Y=
github.com/algorand/avm-abi v0.1.1/go.mod h1:+CgwM46dithy850bpTeHh9MC99zpn2Snirb3QTl2O/g=
github.com/algorand/go-codec v1.1.8 h1:XDSreeeZY8gMst6Edz4RBkl08/DGMJOeHYkoXL2B7wI=
github.com/algorand/go-codec v1.1.8/go.mod h1:XhzVs6VVyWMLu6cApb9/192gBjGRVGm5cX5j203Heg4=
github.com/algorand/go-codec/codec v1.1.8 h1:lsFuhcOH2LiEhpBH3BVUUkdevVmwCRyvb7FCAAPeY6U=
5 changes: 5 additions & 0 deletions test/applications_integration_test.go
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@ func anAlgodVClientConnectedToPortWithToken(v int, host string, port int, token
portAsString := strconv.Itoa(port)
fullHost := "http://" + host + ":" + portAsString
algodV2client, err = algod.MakeClient(fullHost, token)
aclv2 = algodV2client
gh = []byte("MLWBXKMRJ5W3USARAFOHPQJAF4DN6KY3ZJVPIXKODKNN5ZXSZ2DQ")

return err
@@ -328,6 +329,10 @@ func parseBoxes(boxesStr string) (staticBoxes []types.AppBoxReference, err error
}
}

if len(nameBytes) == 0 {
nameBytes = nil
}

staticBoxes = append(staticBoxes,
types.AppBoxReference{
AppID: appID,
314 changes: 98 additions & 216 deletions test/steps_test.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions transaction/transaction.go
Original file line number Diff line number Diff line change
@@ -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"
2 changes: 1 addition & 1 deletion types/block.go
Original file line number Diff line number Diff line change
@@ -190,7 +190,7 @@ type (
// are a multiple of ConsensusParams.StateProofRounds. For blocks
// that are not a multiple of ConsensusParams.StateProofRounds,
// this value is zero.
StateProofVotersCommitment []byte `codec:"v"`
StateProofVotersCommitment GenericDigest `codec:"v"`

// StateProofOnlineTotalWeight is the total number of microalgos held by the online accounts
// during the StateProof round (or zero, if the merkle root is zero - no commitment for StateProof voters).
203 changes: 202 additions & 1 deletion types/stateproof.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,212 @@
package types

import (
"bytes"
"crypto/sha256"
"crypto/sha512"
)

// MessageHash represents the message that a state proof will attest to.
type MessageHash [32]byte

// StateProofType identifies a particular configuration of state proofs.
type StateProofType uint64

const (
// StateProofBasic is our initial state proof setup. using falcon keys and subset-sum hash
StateProofBasic StateProofType = 0

// NumStateProofTypes is the max number of types of state proofs
// that we support. This is used as an allocation bound for a map
// containing different stateproof types in msgpack encoding.
NumStateProofTypes int = 1

// MaxReveals is a bound on allocation and on numReveals to limit log computation
MaxReveals int = 640

// MaxEncodedTreeDepth is the maximum tree depth (root only depth 0) for a tree which
// is being encoded (either by msbpack or by the fixed length encoding)
MaxEncodedTreeDepth = 16

// MaxNumLeavesOnEncodedTree is the maximum number of leaves allowed for a tree which
// is being encoded (either by msbpack or by the fixed length encoding)
MaxNumLeavesOnEncodedTree = 1 << MaxEncodedTreeDepth
)

// GenericDigest is a digest that implements CustomSizeDigest, and can be used as hash output.
//msgp:allocbound GenericDigest MaxHashDigestSize
type GenericDigest []byte

// ToSlice is used inside the Tree itself when interacting with TreeDigest
func (d GenericDigest) ToSlice() []byte { return d }

// IsEqual compare two digests
func (d GenericDigest) IsEqual(other GenericDigest) bool {
return bytes.Equal(d, other)
}

// IsEmpty checks wether the generic digest is an empty one or not
func (d GenericDigest) IsEmpty() bool {
return len(d) == 0
}

// Sumhash512DigestSize The size in bytes of the sumhash checksum
const Sumhash512DigestSize = 64

//size of each hash
const (
Sha512_256Size = sha512.Size256
SumhashDigestSize = Sumhash512DigestSize
Sha256Size = sha256.Size
)

// HashType represents different hash functions
type HashType uint16

// types of hashes
const (
Sha512_256 HashType = iota
Sumhash
Sha256
MaxHashType
)

// HashFactory is responsible for generating new hashes accordingly to the type it stores.
//msgp:postunmarshalcheck HashFactory Validate
type HashFactory struct {
_struct struct{} `codec:",omitempty,omitemptyarray"`

HashType HashType `codec:"t"`
}

// Proof is used to convince a verifier about membership of leaves: h0,h1...hn
// at indexes i0,i1...in on a tree. The verifier has a trusted value of the tree
// root hash.
type Proof struct {
_struct struct{} `codec:",omitempty,omitemptyarray"`

// Path is bounded by MaxNumLeavesOnEncodedTree since there could be multiple reveals, and
// given the distribution of the elt positions and the depth of the tree,
// the path length can increase up to 2^MaxEncodedTreeDepth / 2
Path []GenericDigest `codec:"pth,allocbound=MaxNumLeavesOnEncodedTree/2"`
HashFactory HashFactory `codec:"hsh"`
// TreeDepth represents the depth of the tree that is being proven.
// It is the number of edges from the root to a leaf.
TreeDepth uint8 `codec:"td"`
}

const MerkleSignatureSchemeRootSize = SumhashDigestSize

// Commitment represents the root of the vector commitment tree built upon the MSS keys.
type Commitment [MerkleSignatureSchemeRootSize]byte

// Verifier is used to verify a merklesignature.Signature produced by merklesignature.Secrets.
type Verifier struct {
_struct struct{} `codec:",omitempty,omitemptyarray"`

Commitment Commitment `codec:"cmt"`
KeyLifetime uint64 `codec:"lf"`
}

// A Participant corresponds to an account whose AccountData.Status
// is Online, and for which the expected sigRound satisfies
// AccountData.VoteFirstValid <= sigRound <= AccountData.VoteLastValid.
//
// In the Algorand ledger, it is possible for multiple accounts to have
// the same PK. Thus, the PK is not necessarily unique among Participants.
// However, each account will produce a unique Participant struct, to avoid
// potential DoS attacks where one account claims to have the same VoteID PK
// as another account.
type Participant struct {
_struct struct{} `codec:",omitempty,omitemptyarray"`

// PK is the identifier used to verify the signature for a specific participant
PK Verifier `codec:"p"`

// Weight is AccountData.MicroAlgos.
Weight uint64 `codec:"w"`
}

// MerkleSignature represents a Falcon signature in a compressed-form
//msgp:allocbound MerkleSignature FalconMaxSignatureSize
type MerkleSignature []byte

// SingleLeafProof is used to convince a verifier about membership of a specific
// leaf h at index i on a tree. The verifier has a trusted value of the tree
// root hash. it corresponds to merkle verification path.
type SingleLeafProof struct {
_struct struct{} `codec:",omitempty,omitemptyarray"`

Proof
}

// FalconPublicKeySize pulled out of falcon.go
const FalconPublicKeySize = 0x701

// FalconPublicKey is a wrapper for cfalcon.PublicKeySizey (used for packing)
type FalconPublicKey [FalconPublicKeySize]byte

// FalconVerifier implements the type Verifier interface for the falcon signature scheme.
type FalconVerifier struct {
_struct struct{} `codec:",omitempty,omitemptyarray"`

PublicKey FalconPublicKey `codec:"k"`
}

// FalconSignatureStruct represents a signature in the merkle signature scheme using falcon signatures as an underlying crypto scheme.
// It consists of an ephemeral public key, a signature, a merkle verification path and an index.
// The merkle signature considered valid only if the Signature is verified under the ephemeral public key and
// the Merkle verification path verifies that the ephemeral public key is located at the given index of the tree
// (for the root given in the long-term public key).
// More details can be found on Algorand's spec
type FalconSignatureStruct struct {
_struct struct{} `codec:",omitempty,omitemptyarray"`

Signature MerkleSignature `codec:"sig"`
VectorCommitmentIndex uint64 `codec:"idx"`
Proof SingleLeafProof `codec:"prf"`
VerifyingKey FalconVerifier `codec:"vkey"`
}

// A sigslotCommit is a single slot in the sigs array that forms the state proof.
type sigslotCommit struct {
_struct struct{} `codec:",omitempty,omitemptyarray"`

// Sig is a signature by the participant on the expected message.
Sig FalconSignatureStruct `codec:"s"`

// L is the total weight of signatures in lower-numbered slots.
// This is initialized once the builder has collected a sufficient
// number of signatures.
L uint64 `codec:"l"`
}

// Reveal is a single array position revealed as part of a state
// proof. It reveals an element of the signature array and
// the corresponding element of the participants array.
type Reveal struct {
_struct struct{} `codec:",omitempty,omitemptyarray"`

SigSlot sigslotCommit `codec:"s"`
Part Participant `codec:"p"`
}

// StateProof represents a proof on Algorand's state.
type StateProof struct {
_struct struct{} `codec:",omitempty,omitemptyarray"`

SigCommit GenericDigest `codec:"c"`
SignedWeight uint64 `codec:"w"`
SigProofs Proof `codec:"S"`
PartProofs Proof `codec:"P"`
MerkleSignatureSaltVersion byte `codec:"v"`
// Reveals is a sparse map from the position being revealed
// to the corresponding elements from the sigs and participants
// arrays.
Reveals map[uint64]Reveal `codec:"r,allocbound=MaxReveals"`
PositionsToReveal []uint64 `codec:"pr,allocbound=MaxReveals"`
}

// Message represents the message that the state proofs are attesting to. This message can be
// used by lightweight client and gives it the ability to verify proofs on the Algorand's state.
// In addition to that proof, this message also contains fields that
@@ -25,6 +226,6 @@ type StateProofTxnFields struct {
_struct struct{} `codec:",omitempty,omitemptyarray"`

StateProofType StateProofType `codec:"sptype"`
StateProof interface{} `codec:"sp"`
StateProof StateProof `codec:"sp"`
Message Message `codec:"spmsg"`
}

0 comments on commit 4781c16

Please sign in to comment.