-
Notifications
You must be signed in to change notification settings - Fork 492
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
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -798,6 +798,114 @@ func (node *AlgorandFullNode) checkForParticipationKeys() { | |
} | ||
} | ||
|
||
// ListParticipationKeys returns all participation keys currently installed on the node | ||
func (node *AlgorandFullNode) ListParticipationKeys() (partKeys []account.ParticipationRecord, err error) { | ||
return node.accountManager.Registry().GetAll(), nil | ||
AlgoStephenAkiki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
// GetParticipationKey retries the information of a participation id from the node | ||
func (node *AlgorandFullNode) GetParticipationKey(partKey account.ParticipationID) (account.ParticipationRecord, error) { | ||
return node.accountManager.Registry().Get(partKey), nil | ||
} | ||
|
||
// RemoveParticipationKey given a participation id, remove the records from the node | ||
func (node *AlgorandFullNode) RemoveParticipationKey(partKey account.ParticipationID) error { | ||
|
||
// Need to remove the file and then remove the entry in the registry | ||
// Let's first get the recorded information from the registry so we can lookup the file | ||
|
||
partRecord := node.accountManager.Registry().Get(partKey) | ||
|
||
if partRecord.IsZero() { | ||
return fmt.Errorf("could not find participation record in registry") | ||
AlgoStephenAkiki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
genID := node.GenesisID() | ||
|
||
outDir := filepath.Join(node.rootDir, genID) | ||
|
||
filename := config.PartKeyFilename(partRecord.ParticipationID.String(), uint64(partRecord.FirstValid), uint64(partRecord.LastValid)) | ||
fullyQualifiedFilename := filepath.Join(outDir, filepath.Base(filename)) | ||
|
||
_ = os.Remove(fullyQualifiedFilename) | ||
_ = node.accountManager.Registry().Delete(partKey) | ||
AlgoStephenAkiki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return nil | ||
} | ||
|
||
func createTemporaryParticipationKey(outDir string, partKeyBinary *[]byte) (string, error) { | ||
tempFile := filepath.Join(outDir, filepath.Base("tempPartKeyBinary.bin")) | ||
AlgoStephenAkiki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
file, err := os.Create(tempFile) | ||
|
||
if err != nil { | ||
return "", err | ||
} | ||
|
||
_, err = file.Write(*partKeyBinary) | ||
|
||
file.Close() | ||
|
||
if err != nil { | ||
os.Remove(tempFile) | ||
return "", err | ||
} | ||
|
||
return tempFile, nil | ||
} | ||
|
||
// InstallParticipationKey Given a participation key binary stream install the participation key | ||
func (node *AlgorandFullNode) InstallParticipationKey(partKeyBinary *[]byte) (account.ParticipationID, error) { | ||
genID := node.GenesisID() | ||
|
||
outDir := filepath.Join(node.rootDir, genID) | ||
|
||
fullyQualifiedTempFile, err := createTemporaryParticipationKey(outDir, partKeyBinary) | ||
// We need to make sure no tempfile is created/remains if there is an error | ||
// However, we will eventually rename this file but if we fail in-between | ||
// this point and the rename we want to ensure that we remove the temporary file | ||
// After we rename, this will fail anyway since the file will not exist | ||
|
||
// Explicitly ignore the error with a closure | ||
defer func(name string) { | ||
_ = os.Remove(name) | ||
}(fullyQualifiedTempFile) | ||
|
||
if err != nil { | ||
return account.ParticipationID{}, err | ||
} | ||
|
||
inputdb, err := db.MakeErasableAccessor(fullyQualifiedTempFile) | ||
if err != nil { | ||
return account.ParticipationID{}, err | ||
} | ||
defer inputdb.Close() | ||
|
||
partkey, err := account.RestoreParticipation(inputdb) | ||
if err != nil { | ||
return account.ParticipationID{}, err | ||
} | ||
defer partkey.Close() | ||
|
||
if partkey.Parent == (basics.Address{}) { | ||
return account.ParticipationID{}, fmt.Errorf("cannot install partkey with missing (zero) parent address") | ||
} | ||
|
||
// Tell the AccountManager about the Participation (dupes don't matter) so we ignore the return value | ||
_ = node.accountManager.AddParticipation(partkey) | ||
AlgoStephenAkiki marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On closer inspection,
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. |
||
|
||
newFilename := config.PartKeyFilename(partkey.ID().String(), uint64(partkey.FirstValid), uint64(partkey.LastValid)) | ||
newFullyQualifiedFilename := filepath.Join(outDir, filepath.Base(newFilename)) | ||
|
||
err = os.Rename(fullyQualifiedTempFile, newFullyQualifiedFilename) | ||
|
||
if err != nil { | ||
return account.ParticipationID{}, nil | ||
} | ||
|
||
return partkey.ID(), nil | ||
} | ||
|
||
func (node *AlgorandFullNode) loadParticipationKeys() error { | ||
// Generate a list of all potential participation key files | ||
genesisDir := filepath.Join(node.rootDir, node.genesisID) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
#!/usr/bin/env bash | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Other than a few nits, this test looks really nice. This is going to be a nice template for when the storage changes and we get new error cases to check for. |
||
# TIMEOUT=300 | ||
|
||
my_dir="$(dirname "$0")" | ||
#"$my_dir/rest.sh" "$@" | ||
AlgoStephenAkiki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
source "$my_dir/rest.sh" "$@" | ||
|
||
date "+$0 start %Y%m%d_%H%M%S" | ||
|
||
# Use admin token for both get and post | ||
export USE_ADMIN=true | ||
|
||
pushd "${TEMPDIR}" || exit | ||
|
||
FIRST_ROUND=0 | ||
# A really large (but arbitrary) last valid round | ||
LAST_ROUND=1200000 | ||
|
||
NAME_OF_TEMP_PARTKEY="tmp.${FIRST_ROUND}.${LAST_ROUND}.partkey" | ||
|
||
algokey part generate --first ${FIRST_ROUND} --last ${LAST_ROUND} --keyfile ${NAME_OF_TEMP_PARTKEY} --parent ${ACCOUNT} | ||
|
||
popd || exit | ||
|
||
call_and_verify "Get List of Keys" "/v2/participation" 200 'Address' | ||
|
||
call_post_and_verify "Install a basic participation key" "/v2/participation" 200 ${NAME_OF_TEMP_PARTKEY} 'partId' | ||
AlgoStephenAkiki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
call_and_verify "Get List of Keys" "/v2/participation" 200 'Address' | ||
AlgoStephenAkiki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
# Let's get a key from the previous response manually and request it specifically | ||
SAMPLE_ID=$(curl -q -s -H "Authorization: Bearer $ADMIN_TOKEN" "$NET/v2/participation" | python3 -c 'import json,sys;obj=json.load(sys.stdin);print(obj[0]["ID"])') | ||
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))') | ||
|
||
call_and_verify "Get a specific ID" "/v2/participation/${SAMPLE_ID}" 200 "${SAMPLE_ID}" | ||
|
||
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 | ||
|
||
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))') | ||
|
||
if [[ "$NEW_NUMBER_OF_IDS" -ge "$NUMBER_OF_IDS" ]]; then | ||
printf "\n\nFailed test. New number of IDs (%s) is greater than or equal to original IDs (%s)\n\n" "${NEW_NUMBER_OF_IDS}" "${NUMBER_OF_IDS}" | ||
exit 1 | ||
fi | ||
|
||
AlgoStephenAkiki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coming soon™