Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented New REST interfaces #3099

Merged
merged 4 commits into from
Oct 21, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions daemon/algod/api/server/v2/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ var (
errFailedToAbortCatchup = "failed to abort catchup : %v"
errFailedToStartCatchup = "failed to start catchup : %v"
errOperationNotAvailableDuringCatchup = "operation not available during catchup"
errRESTPayloadZeroLength = "payload was of zero length"
)
6 changes: 3 additions & 3 deletions daemon/algod/api/server/v2/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ func (v2 *Handlers) GetParticipationKeys(ctx echo.Context) error {
"Address": participationRecord.Account.String(),
"FirstValid": participationRecord.FirstValid,
"LastValid": participationRecord.LastValid,
// TODO add this
// TODO Coming soon (tm)
"VoteID": crypto.OneTimeSignatureVerifier{},
// TODO add this
// TODO Coming soon (tm)
"SelectionID": crypto.VRFVerifier{},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"VoteKeyDilution": participationRecord.KeyDilution,
}
Expand All @@ -117,7 +117,7 @@ func (v2 *Handlers) AddParticipationKey(ctx echo.Context) error {
partKeyBinary := buf.Bytes()

if len(partKeyBinary) == 0 {
err := fmt.Errorf("binary was of length zero")
err := fmt.Errorf(errRESTPayloadZeroLength)
return badRequest(ctx, err, err.Error(), v2.Log)
}

Expand Down
37 changes: 34 additions & 3 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -56,6 +57,7 @@ import (
"github.com/algorand/go-algorand/util/metrics"
"github.com/algorand/go-algorand/util/timers"
"github.com/algorand/go-deadlock"
uuid "github.com/satori/go.uuid"
)

// StatusReport represents the current basic status of the node
Expand Down Expand Up @@ -805,6 +807,12 @@ func (node *AlgorandFullNode) ListParticipationKeys() (partKeys []account.Partic

// GetParticipationKey retries the information of a participation id from the node
func (node *AlgorandFullNode) GetParticipationKey(partKey account.ParticipationID) (account.ParticipationRecord, error) {
rval := node.accountManager.Registry().Get(partKey)

if rval.IsZero() {
return account.ParticipationRecord{}, account.ErrParticipationIDNotFound
}

return node.accountManager.Registry().Get(partKey), nil
}

Expand All @@ -817,7 +825,7 @@ func (node *AlgorandFullNode) RemoveParticipationKey(partKey account.Participati
partRecord := node.accountManager.Registry().Get(partKey)

if partRecord.IsZero() {
return fmt.Errorf("could not find participation record in registry")
return nil
}

genID := node.GenesisID()
Expand All @@ -827,14 +835,32 @@ func (node *AlgorandFullNode) RemoveParticipationKey(partKey account.Participati
filename := config.PartKeyFilename(partRecord.ParticipationID.String(), uint64(partRecord.FirstValid), uint64(partRecord.LastValid))
fullyQualifiedFilename := filepath.Join(outDir, filepath.Base(filename))

err := node.accountManager.Registry().Delete(partKey)
if err != nil {
return err
}

err = node.accountManager.Registry().Flush()
if err != nil {
return err
}

// Only after deleting and flushing do we want to remove the file
_ = os.Remove(fullyQualifiedFilename)
_ = node.accountManager.Registry().Delete(partKey)

return nil
}

func createTemporaryParticipationKey(outDir string, partKeyBinary *[]byte) (string, error) {
tempFile := filepath.Join(outDir, filepath.Base("tempPartKeyBinary.bin"))
var sb strings.Builder

// Create a temporary filename with a UUID so that we can call this function twice
// in a row without worrying about collisions
sb.WriteString("tempPartKeyBinary.")
sb.WriteString(uuid.NewV4().String())
sb.WriteString(".bin")

tempFile := filepath.Join(outDir, filepath.Base(sb.String()))

file, err := os.Create(tempFile)

Expand Down Expand Up @@ -894,6 +920,11 @@ func (node *AlgorandFullNode) InstallParticipationKey(partKeyBinary *[]byte) (ac
// Tell the AccountManager about the Participation (dupes don't matter) so we ignore the return value
_ = node.accountManager.AddParticipation(partkey)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On closer inspection, AddParticipation returns a bool not an error.:

// The return value indicates if the key has been added (true) or    
// if this is a duplicate key (false).     

The code would currently overwrite the duplicate key, I think that's probably fine. In the future when we stop writing the file to begin with, it would just be a no-op.


err = node.accountManager.Registry().Flush()
if err != nil {
return account.ParticipationID{}, err
}

newFilename := config.PartKeyFilename(partkey.ID().String(), uint64(partkey.FirstValid), uint64(partkey.LastValid))
newFullyQualifiedFilename := filepath.Join(outDir, filepath.Base(newFilename))

Expand Down
5 changes: 2 additions & 3 deletions test/scripts/e2e_subs/rest-participation-key.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
# TIMEOUT=300

my_dir="$(dirname "$0")"
#"$my_dir/rest.sh" "$@"
source "$my_dir/rest.sh" "$@"

date "+$0 start %Y%m%d_%H%M%S"
Expand Down Expand Up @@ -36,8 +35,8 @@ call_and_verify "Get a specific ID" "/v2/participation/${SAMPLE_ID}" 200 "${SAMP

call_delete_and_verify "Delete the specific ID" "/v2/participation/${SAMPLE_ID}" 200

# Verify that it got called previously and will return an error now since it isn't there
call_delete_and_verify "Delete the specific ID" "/v2/participation/${SAMPLE_ID}" 400
# Verify that it got called previously and will NOT return an error now even though it isn't there
call_delete_and_verify "Delete the specific ID" "/v2/participation/${SAMPLE_ID}" 200

NEW_NUMBER_OF_IDS=$(curl -q -s -H "Authorization: Bearer $ADMIN_TOKEN" "$NET/v2/participation" | python3 -c 'import json,sys;obj=json.load(sys.stdin);print(len(obj))')

Expand Down
141 changes: 42 additions & 99 deletions test/scripts/e2e_subs/rest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -113,78 +113,30 @@ function curl_post_test {
local FILENAME_TO_UPLOAD="$1"
shift


local SUBSTRING

local START=$SECONDS

set +e
local CODE
if [[ "$USE_ADMIN" = true ]]; then
CODE=$(call_post_admin "$QUERY" "${TEMPDIR}/curl_out.txt" "$FILENAME_TO_UPLOAD")
else
CODE=$(call_post "$QUERY" "${TEMPDIR}/curl_out.txt" "$FILENAME_TO_UPLOAD")
fi
if [[ $? != 0 ]]; then
cat $CURL_TEMPFILE
fail_and_exit "$DESCRIPTION" "$QUERY" "curl had a non-zero exit code."
fi
set -e

RES=$(cat "${TEMPDIR}/curl_out.txt")
if [[ "$CODE" != "$EXPECTED_CODE" ]]; then
fail_and_exit "$DESCRIPTION" "$QUERY" "unexpected HTTP status code expected $EXPECTED_CODE (actual $CODE): $RES"
fi

#local ELAPSED=$(($SECONDS - $START))
#if [[ $ELAPSED -gt $MAX_TIME ]]; then
# fail_and_exit "$DESCRIPTION" "$QUERY" "query duration too long, $ELAPSED > $MAX_TIME"
#fi
verify $? "$CODE" "$DESCRIPTION" "$QUERY" "$EXPECTED_CODE" "$MATCH_RESULT" "$@"

# Check result substrings
for SUBSTRING in "$@"; do
echo "CHECKING '$SUBSTRING'"
if [[ $MATCH_RESULT = true ]]; then
if [[ "$RES" != *"$SUBSTRING"* ]]; then
fail_and_exit "$DESCRIPTION" "$QUERY" "unexpected response. should contain '$SUBSTRING', actual: $RES"
fi
else
if [[ "$RES" == *"$SUBSTRING"* ]]; then
fail_and_exit "$DESCRIPTION" "$QUERY" "unexpected response. should NOT contain '$SUBSTRING', actual: $RES"
fi
fi
done
}

# $1 - test description.
# $2 - query
# $3 - expected status code
# $4... - substring that should be in the response
function call_delete_and_verify {
local DESCRIPTION="$1"
shift
local QUERY="$1"
shift
local EXPECTED_CODE="$1"
shift

curl_delete_test "$DESCRIPTION" "$QUERY" "$EXPECTED_CODE"
}

# CURL Test - query and verify results
# $1 - test description.
# $2 - query
# $3 - expected status code
function curl_delete_test {
function call_delete_and_verify {
local DESCRIPTION="$1"
shift
local QUERY="$1"
shift
local EXPECTED_CODE="$1"
shift

local START=$SECONDS

set +e

local CODE
Expand All @@ -194,21 +146,8 @@ function curl_delete_test {
CODE=$(call_delete "$QUERY" "${TEMPDIR}/curl_out.txt" )
fi

if [[ $? != 0 ]]; then
cat $CURL_TEMPFILE
fail_and_exit "$DESCRIPTION" "$QUERY" "curl had a non-zero exit code."
fi
set -e

RES=$(cat "${TEMPDIR}/curl_out.txt")
if [[ "$CODE" != "$EXPECTED_CODE" ]]; then
fail_and_exit "$DESCRIPTION" "$QUERY" "unexpected HTTP status code expected $EXPECTED_CODE (actual $CODE): $RES"
fi
verify $? "$CODE" "$DESCRIPTION" "$QUERY" "$EXPECTED_CODE" "false"

#local ELAPSED=$(($SECONDS - $START))
#if [[ $ELAPSED -gt $MAX_TIME ]]; then
# fail_and_exit "$DESCRIPTION" "$QUERY" "query duration too long, $ELAPSED > $MAX_TIME"
#fi
}


Expand All @@ -227,9 +166,6 @@ function curl_test {
shift
local MATCH_RESULT="$1"
shift
local SUBSTRING

local START=$SECONDS

set +e

Expand All @@ -240,35 +176,8 @@ function curl_test {
CODE=$(call "$QUERY" "${TEMPDIR}/curl_out.txt" )
fi

if [[ $? != 0 ]]; then
cat $CURL_TEMPFILE
fail_and_exit "$DESCRIPTION" "$QUERY" "curl had a non-zero exit code."
fi
set -e

RES=$(cat "${TEMPDIR}/curl_out.txt")
if [[ "$CODE" != "$EXPECTED_CODE" ]]; then
fail_and_exit "$DESCRIPTION" "$QUERY" "unexpected HTTP status code expected $EXPECTED_CODE (actual $CODE): $RES"
fi

#local ELAPSED=$(($SECONDS - $START))
#if [[ $ELAPSED -gt $MAX_TIME ]]; then
# fail_and_exit "$DESCRIPTION" "$QUERY" "query duration too long, $ELAPSED > $MAX_TIME"
#fi
verify $? "$CODE" "$DESCRIPTION" "$QUERY" "$EXPECTED_CODE" "$MATCH_RESULT" "$@"

# Check result substrings
for SUBSTRING in "$@"; do
echo "CHECKING '$SUBSTRING'"
if [[ $MATCH_RESULT = true ]]; then
if [[ "$RES" != *"$SUBSTRING"* ]]; then
fail_and_exit "$DESCRIPTION" "$QUERY" "unexpected response. should contain '$SUBSTRING', actual: $RES"
fi
else
if [[ "$RES" == *"$SUBSTRING"* ]]; then
fail_and_exit "$DESCRIPTION" "$QUERY" "unexpected response. should NOT contain '$SUBSTRING', actual: $RES"
fi
fi
done
}


Expand Down Expand Up @@ -303,9 +212,6 @@ function curl_test {
shift
local MATCH_RESULT="$1"
shift
local SUBSTRING

local START=$SECONDS

set +e

Expand All @@ -320,6 +226,38 @@ function curl_test {
cat $CURL_TEMPFILE
fail_and_exit "$DESCRIPTION" "$QUERY" "curl had a non-zero exit code."
fi

verify $? "$CODE" "$DESCRIPTION" "$QUERY" "$EXPECTED_CODE" "$MATCH_RESULT" "$@"

}

# verify - Common verification code
# $1 - return code of CURL sub-shell command
# $2 - HTTP status code
# $3 - description of test
# $4 - query to execute
# $5 - expected HTTP status code to check
# $6 - match result
# $7... - substring(s) that should be in the response
function verify {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!

local SUCCESS=$1
shift
local CODE=$1
shift
local DESCRIPTION="$1"
shift
local QUERY="$1"
shift
local EXPECTED_CODE="$1"
shift
local MATCH_RESULT="$1"
shift

if [[ $SUCCESS != 0 ]]; then
cat $CURL_TEMPFILE
fail_and_exit "$DESCRIPTION" "$QUERY" "curl had a non-zero exit code."
fi

set -e

RES=$(cat "${TEMPDIR}/curl_out.txt")
Expand All @@ -332,6 +270,9 @@ function curl_test {
# fail_and_exit "$DESCRIPTION" "$QUERY" "query duration too long, $ELAPSED > $MAX_TIME"
#fi


local SUBSTRING

# Check result substrings
for SUBSTRING in "$@"; do
echo "CHECKING '$SUBSTRING'"
Expand All @@ -345,4 +286,6 @@ function curl_test {
fi
fi
done
}


}