Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion daemon/algod/api/server/v2/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ func (v2 *Handlers) TealDryrun(ctx echo.Context) error {

var dr DryrunRequest
var gdr generated.DryrunRequest
err := decode(protocol.JSONHandle, data, &gdr)
err := decode(protocol.JSONStrictHandle, data, &gdr)
if err == nil {
dr, err = DryrunRequestFromGenerated(&gdr)
if err != nil {
Expand Down
100 changes: 100 additions & 0 deletions daemon/algod/api/server/v2/test/handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package test

import (
"bytes"
"encoding/json"
"errors"
"io"
"net/http"
Expand All @@ -27,16 +28,20 @@ import (
"github.com/labstack/echo/v4"
"github.com/stretchr/testify/require"

"github.com/algorand/go-algorand/agreement"
"github.com/algorand/go-algorand/crypto"
v2 "github.com/algorand/go-algorand/daemon/algod/api/server/v2"
"github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated"
generatedV2 "github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated"
"github.com/algorand/go-algorand/data/account"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
"github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/data/transactions/logic"
"github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/node"
"github.com/algorand/go-algorand/protocol"
"github.com/algorand/go-algorand/util/execpool"
)

func setupTestForMethodGet(t *testing.T) (v2.Handlers, echo.Context, *httptest.ResponseRecorder, []account.Root, []transactions.SignedTxn, func()) {
Expand Down Expand Up @@ -105,6 +110,101 @@ func TestGetBlock(t *testing.T) {
getBlockTest(t, 0, "bad format", 400)
}

func TestGetBlockJsonEncoding(t *testing.T) {
t.Parallel()

handler, c, rec, _, _, releasefunc := setupTestForMethodGet(t)
defer releasefunc()

l := handler.Node.Ledger()

genBlk, err := l.Block(0)
require.NoError(t, err)

// make an app call txn with eval delta
lsig := transactions.LogicSig{Logic: retOneProgram} // int 1
program := logic.Program(lsig.Logic)
lhash := crypto.HashObj(&program)
var sender basics.Address
copy(sender[:], lhash[:])
stx := transactions.SignedTxn{
Txn: transactions.Transaction{
Type: protocol.ApplicationCallTx,
Header: transactions.Header{
Sender: sender,
Fee: basics.MicroAlgos{Raw: 1000},
GenesisID: genBlk.GenesisID(),
GenesisHash: genBlk.GenesisHash(),
FirstValid: 1,
LastValid: 10,
},
ApplicationCallTxnFields: transactions.ApplicationCallTxnFields{
ApplicationID: 1,
OnCompletion: transactions.ClearStateOC,
},
},
Lsig: lsig,
}
ad := transactions.ApplyData{
EvalDelta: basics.EvalDelta{
LocalDeltas: map[uint64]basics.StateDelta{
1: {"key": basics.ValueDelta{Action: 1}},
},
},
}

// put it into a block
backlogPool := execpool.MakeBacklog(nil, 0, execpool.LowPriority, nil)
defer backlogPool.Shutdown()

totals, err := l.Totals(l.Latest())
require.NoError(t, err)
totalRewardUnits := totals.RewardUnits()
poolBal, err := l.Lookup(l.Latest(), poolAddr)
require.NoError(t, err)

var blk bookkeeping.Block
blk.BlockHeader = bookkeeping.BlockHeader{
GenesisID: genBlk.GenesisID(),
GenesisHash: genBlk.GenesisHash(),
Round: l.Latest() + 1,
Branch: genBlk.Hash(),
TimeStamp: 0,
RewardsState: genBlk.NextRewardsState(l.Latest()+1, proto, poolBal.MicroAlgos, totalRewardUnits),
UpgradeState: genBlk.UpgradeState,
}

blk.BlockHeader.TxnCounter = genBlk.TxnCounter

blk.RewardsPool = genBlk.RewardsPool
blk.FeeSink = genBlk.FeeSink
blk.CurrentProtocol = genBlk.CurrentProtocol
blk.TimeStamp = genBlk.TimeStamp + 1

txib, err := blk.EncodeSignedTxn(stx, ad)
blk.Payset = append(blk.Payset, txib)
blk.BlockHeader.TxnCounter++
blk.TxnRoot, err = blk.PaysetCommit()
require.NoError(t, err)

err = l.AddBlock(blk, agreement.Certificate{})
require.NoError(t, err)

// fetch the block and ensure it can be properly decoded with the standard JSON decoder
format := "json"
err = handler.GetBlock(c, 1, generatedV2.GetBlockParams{Format: &format})
require.NoError(t, err)
require.Equal(t, 200, rec.Code)
data := rec.Body.Bytes()

response := struct {
Block bookkeeping.Block `codec:"block"`
}{}

err = json.Unmarshal(data, &response)
require.NoError(t, err)
}

func TestGetSupply(t *testing.T) {
t.Parallel()

Expand Down
12 changes: 11 additions & 1 deletion daemon/algod/api/server/v2/test/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
"github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/data/transactions/logic"
"github.com/algorand/go-algorand/ledger/ledgercore"
"github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/node"
Expand Down Expand Up @@ -188,6 +189,7 @@ var sinkAddr = basics.Address{0x7, 0xda, 0xcb, 0x4b, 0x6d, 0x9e, 0xd1, 0x41, 0xb
var poolAddr = basics.Address{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
var genesisHash = crypto.Digest{0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}
var genesisID = "testingid"
var retOneProgram = []byte{2, 0x20, 1, 1, 0x22}

var proto = config.Consensus[protocol.ConsensusCurrentVersion]

Expand Down Expand Up @@ -256,7 +258,15 @@ func testingenv(t testing.TB, numAccounts, numTxs int, offlineAccounts bool) (*d

genesis[poolAddr] = basics.MakeAccountData(basics.NotParticipating, basics.MicroAlgos{Raw: 100000 * uint64(proto.RewardsRateRefreshInterval)})

bootstrap := data.MakeGenesisBalances(genesis, poolAddr, sinkAddr)
program := logic.Program(retOneProgram)
lhash := crypto.HashObj(&program)
var addr basics.Address
copy(addr[:], lhash[:])
ad := basics.MakeAccountData(basics.NotParticipating, basics.MicroAlgos{Raw: 100000 * uint64(proto.RewardsRateRefreshInterval)})
ad.AppLocalStates = map[basics.AppIndex]basics.AppLocalState{1: {}}
genesis[addr] = ad

bootstrap := data.MakeGenesisBalances(genesis, sinkAddr, poolAddr)

// generate test transactions
const inMem = true
Expand Down
2 changes: 1 addition & 1 deletion daemon/algod/api/server/v2/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ func getCodecHandle(formatPtr *string) (codec.Handle, string, error) {

switch format {
case "json":
return protocol.JSONHandle, "application/json", nil
return protocol.JSONStrictHandle, "application/json", nil
case "msgpack":
fallthrough
case "msgp":
Expand Down
26 changes: 20 additions & 6 deletions protocol/codec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ package protocol

import (
"reflect"
"strings"
"testing"

"github.com/algorand/go-algorand/test/partitiontest"
"github.com/algorand/go-codec/codec"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -167,21 +167,35 @@ func TestEncodeJSON(t *testing.T) {
v.Map[1] = []string{"test1"}

nonStrict := EncodeJSON(&v)
strings.Contains(string(nonStrict), `0:`)
strings.Contains(string(nonStrict), `1:`)
require.Contains(t, string(nonStrict), `0:`)
require.Contains(t, string(nonStrict), `1:`)

strict := EncodeJSONStrict(&v)
strings.Contains(string(strict), `"0":`)
strings.Contains(string(strict), `"1":`)
require.Contains(t, string(strict), `"0":`)
require.Contains(t, string(strict), `"1":`)

var nsv mp
err := DecodeJSON(nonStrict, &nsv)
require.NoError(t, err)

var sv mp
err = DecodeJSON(nonStrict, &sv)
err = DecodeJSON(strict, &sv)
require.NoError(t, err)

require.True(t, reflect.DeepEqual(v, nsv))
require.True(t, reflect.DeepEqual(v, sv))

decodeJSONStrict := func(b []byte, objptr interface{}) error {
dec := codec.NewDecoderBytes(b, JSONStrictHandle)
return dec.Decode(objptr)
}

nsv = mp{}
decodeJSONStrict(nonStrict, &nsv)

sv = mp{}
decodeJSONStrict(strict, &sv)

require.True(t, reflect.DeepEqual(v, nsv))
require.True(t, reflect.DeepEqual(v, sv))
}
4 changes: 1 addition & 3 deletions test/scripts/e2e_subs/serial/rest-proof-endpoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ while [[ "${NUM_TRANSACTIONS}" != "1" ]]; do

# check if the transaction was all alone in the round
call_and_verify "Checking block" "/v2/blocks/${ROUND}" 200 'txns'
#TODO: The check with jq can be re-enabled after fixing JSONStrictHandle.
#NUM_TRANSACTIONS=$(cat "${TEMPDIR}/curl_out.txt" | jq '.block.txns | length')
NUM_TRANSACTIONS=$(cat "${TEMPDIR}/curl_out.txt" | grep type | wc -l | tr -d ' ')
NUM_TRANSACTIONS=$(cat "${TEMPDIR}/curl_out.txt" | jq '.block.txns | length')
done

call_and_verify "The proof should not be null." "/v2/blocks/${ROUND}/transactions/${TXID}/proof" 200 '"proof":""'