Removed the need to include public key in recently added API endpoints, as it can be derived from the registered name's owner.

This commit is contained in:
CalDescent 2021-10-29 17:08:26 +01:00
parent 7aa2fbee1c
commit f4c1671079
2 changed files with 35 additions and 21 deletions

View File

@ -27,6 +27,8 @@ import org.qortal.api.*;
import org.qortal.api.resource.TransactionsResource.ConfirmationStatus; import org.qortal.api.resource.TransactionsResource.ConfirmationStatus;
import org.qortal.arbitrary.ArbitraryDataReader; import org.qortal.arbitrary.ArbitraryDataReader;
import org.qortal.arbitrary.ArbitraryDataTransactionBuilder; import org.qortal.arbitrary.ArbitraryDataTransactionBuilder;
import org.qortal.data.account.AccountData;
import org.qortal.data.naming.NameData;
import org.qortal.data.transaction.ArbitraryTransactionData; import org.qortal.data.transaction.ArbitraryTransactionData;
import org.qortal.data.transaction.ArbitraryTransactionData.*; import org.qortal.data.transaction.ArbitraryTransactionData.*;
import org.qortal.data.transaction.TransactionData; import org.qortal.data.transaction.TransactionData;
@ -256,7 +258,7 @@ public class ArbitraryResource {
} }
@PUT @PUT
@Path("/{service}/{name}/{publickey}") @Path("/{service}/{name}")
@Operation( @Operation(
summary = "Build raw, unsigned, ARBITRARY transaction, based on a user-supplied path, using the PUT method", summary = "Build raw, unsigned, ARBITRARY transaction, based on a user-supplied path, using the PUT method",
description = "A PUT transaction replaces the data held for this name and service in its entirety.", description = "A PUT transaction replaces the data held for this name and service in its entirety.",
@ -283,15 +285,14 @@ public class ArbitraryResource {
) )
public String put(@PathParam("service") String serviceString, public String put(@PathParam("service") String serviceString,
@PathParam("name") String name, @PathParam("name") String name,
@PathParam("publickey") String publicKey58,
String path) { String path) {
Security.checkApiCallAllowed(request); Security.checkApiCallAllowed(request);
return this.upload(Method.PUT, Service.valueOf(serviceString), publicKey58, name, path); return this.upload(Method.PUT, Service.valueOf(serviceString), name, path);
} }
@PATCH @PATCH
@Path("/{service}/{name}/{publickey}") @Path("/{service}/{name}")
@Operation( @Operation(
summary = "Build raw, unsigned, ARBITRARY transaction, based on a user-supplied path, using the PATCH method", summary = "Build raw, unsigned, ARBITRARY transaction, based on a user-supplied path, using the PATCH method",
description = "A PATCH transaction calculates the delta between the current state on the on-chain state, " + description = "A PATCH transaction calculates the delta between the current state on the on-chain state, " +
@ -319,29 +320,47 @@ public class ArbitraryResource {
) )
public String patch(@PathParam("service") String serviceString, public String patch(@PathParam("service") String serviceString,
@PathParam("name") String name, @PathParam("name") String name,
@PathParam("publickey") String publicKey58,
String path) { String path) {
Security.checkApiCallAllowed(request); Security.checkApiCallAllowed(request);
return this.upload(Method.PATCH, Service.valueOf(serviceString), publicKey58, name, path); return this.upload(Method.PATCH, Service.valueOf(serviceString), name, path);
} }
private String upload(Method method, Service service, String publicKey58, String name, String path) { private String upload(Method method, Service service, String name, String path) {
// It's too dangerous to allow user-supplied file paths in weaker security contexts // It's too dangerous to allow user-supplied file paths in weaker security contexts
if (Settings.getInstance().isApiRestricted()) { if (Settings.getInstance().isApiRestricted()) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.NON_PRODUCTION); throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.NON_PRODUCTION);
} }
try { // Fetch public key from registered name
ArbitraryDataTransactionBuilder transactionBuilder = new ArbitraryDataTransactionBuilder( try (final Repository repository = RepositoryManager.getRepository()) {
publicKey58, Paths.get(path), name, method, service NameData nameData = repository.getNameRepository().fromName(name);
); if (nameData == null) {
String error = String.format("Name not registered: %s", name);
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.INVALID_CRITERIA, error);
}
ArbitraryTransactionData transactionData = transactionBuilder.build(); AccountData accountData = repository.getAccountRepository().getAccount(nameData.getOwner());
return Base58.encode(ArbitraryTransactionTransformer.toBytes(transactionData)); if (accountData == null) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.ADDRESS_UNKNOWN);
}
byte[] publicKey = accountData.getPublicKey();
String publicKey58 = Base58.encode(publicKey);
} catch (DataException | TransformationException e) { try {
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.INVALID_DATA, e.getMessage()); ArbitraryDataTransactionBuilder transactionBuilder = new ArbitraryDataTransactionBuilder(
publicKey58, Paths.get(path), name, method, service
);
ArbitraryTransactionData transactionData = transactionBuilder.build();
return Base58.encode(ArbitraryTransactionTransformer.toBytes(transactionData));
} catch (DataException | TransformationException e) {
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.INVALID_DATA, e.getMessage());
}
} catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE);
} }
} }

View File

@ -35,20 +35,15 @@ if [[ "${method}" == "PUT" || "${method}" == "PATCH" ]]; then
directory=$4 directory=$4
private_key=$5 private_key=$5
public_key=$(curl --silent --url "http://localhost:${port}/utils/publickey" --data "${private_key}")
if [ -z "${directory}" ]; then if [ -z "${directory}" ]; then
echo "Error: missing directory"; exit echo "Error: missing directory"; exit
fi fi
if [ -z "${private_key}" ]; then if [ -z "${private_key}" ]; then
echo "Error: missing private_key"; exit echo "Error: missing private_key"; exit
fi fi
if [ -z "${public_key}" ]; then
echo "Error: unable to convert private key to public key"; exit
fi
echo "Creating transaction - this can take a while..." echo "Creating transaction - this can take a while..."
tx_data=$(curl --silent --insecure -X ${method} "http://${host}:${port}/arbitrary/${service}/${name}/${public_key}" -d "${directory}") tx_data=$(curl --silent --insecure -X ${method} "http://${host}:${port}/arbitrary/${service}/${name}" -d "${directory}")
if [[ "${tx_data}" == *"error"* || "${tx_data}" == *"ERROR"* ]]; then if [[ "${tx_data}" == *"error"* || "${tx_data}" == *"ERROR"* ]]; then
echo "${tx_data}"; exit echo "${tx_data}"; exit
fi fi