Browse Source

Fixed deserialization issues with CreationRequest, added validation, and made small code tweaks for consistency with other endpoints.

add-create-bytes-endpoint
CalDescent 1 year ago
parent
commit
3fbcc50503
  1. 102
      src/main/java/org/qortal/api/model/AtCreationRequest.java
  2. 55
      src/main/java/org/qortal/api/resource/AtResource.java
  3. 78
      src/main/java/org/qortal/data/transaction/CreationRequest.java

102
src/main/java/org/qortal/api/model/AtCreationRequest.java

@ -0,0 +1,102 @@
package org.qortal.api.model;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlTransient;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.DecoderException;
@XmlAccessorType(XmlAccessType.FIELD)
public class AtCreationRequest {
@Schema(description = "CIYAM AT version", example = "2")
private short ciyamAtVersion;
@Schema(description = "base64-encoded code bytes", example = "")
private String codeBytesBase64;
@Schema(description = "base64-encoded data bytes", example = "")
private String dataBytesBase64;
private short numCallStackPages;
private short numUserStackPages;
private long minActivationAmount;
// Default constructor for JSON deserialization
public AtCreationRequest() {}
// Getters and setters
public short getCiyamAtVersion() {
return ciyamAtVersion;
}
public void setCiyamAtVersion(short ciyamAtVersion) {
this.ciyamAtVersion = ciyamAtVersion;
}
public String getCodeBytesBase64() {
return this.codeBytesBase64;
}
@XmlTransient
@Schema(hidden = true)
public byte[] getCodeBytes() {
if (this.codeBytesBase64 != null) {
try {
return Base64.decode(this.codeBytesBase64);
}
catch (DecoderException e) {
return null;
}
}
return null;
}
public String getDataBytesBase64() {
return this.dataBytesBase64;
}
@XmlTransient
@Schema(hidden = true)
public byte[] getDataBytes() {
if (this.dataBytesBase64 != null) {
try {
return Base64.decode(this.dataBytesBase64);
}
catch (DecoderException e) {
return null;
}
}
return null;
}
public short getNumCallStackPages() {
return numCallStackPages;
}
public void setNumCallStackPages(short numCallStackPages) {
this.numCallStackPages = numCallStackPages;
}
public short getNumUserStackPages() {
return numUserStackPages;
}
public void setNumUserStackPages(short numUserStackPages) {
this.numUserStackPages = numUserStackPages;
}
public long getMinActivationAmount() {
return minActivationAmount;
}
public void setMinActivationAmount(long minActivationAmount) {
this.minActivationAmount = minActivationAmount;
}
}

55
src/main/java/org/qortal/api/resource/AtResource.java

@ -9,7 +9,6 @@ import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
@ -28,7 +27,7 @@ import org.qortal.api.ApiException;
import org.qortal.api.ApiExceptionFactory;
import org.qortal.data.at.ATData;
import org.qortal.data.at.ATStateData;
import org.qortal.data.transaction.CreationRequest;
import org.qortal.api.model.AtCreationRequest;
import org.qortal.data.transaction.DeployAtTransactionData;
import org.qortal.repository.DataException;
import org.qortal.repository.Repository;
@ -39,10 +38,11 @@ import org.qortal.transaction.Transaction.ValidationResult;
import org.qortal.transform.TransformationException;
import org.qortal.transform.transaction.DeployAtTransactionTransformer;
import org.qortal.utils.Base58;
import java.util.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
@Path("/at")
@Tag(name = "Automated Transactions")
public class AtResource {
@ -163,21 +163,21 @@ public class AtResource {
}
@POST
@Path("/createMachineState")
@Path("/create")
@Operation(
summary = "Create MachineState bytes from the provided parameters",
summary = "Create base58-encoded AT creation bytes from the provided parameters",
requestBody = @RequestBody(
required = true,
content = @Content(
mediaType = MediaType.APPLICATION_JSON,
schema = @Schema(
implementation = CreationRequest.class
implementation = AtCreationRequest.class
)
)
),
responses = {
@ApiResponse(
description = "MachineState bytes",
description = "AT creation bytes suitable for use in a DEPLOY_AT transaction",
content = @Content(
mediaType = MediaType.TEXT_PLAIN,
schema = @Schema(
@ -187,27 +187,26 @@ public class AtResource {
)
}
)
public String createMachineState(String jsonBody) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
CreationRequest request = objectMapper.readValue(jsonBody, CreationRequest.class);
logger.info("ciyamAtVersion: {}", request.getCiyamAtVersion());
logger.info("codeBytes: {}", request.getCodeBytes());
logger.info("codeBytes: {}", request.getNumUserStackPages());
logger.info("codeBytes: {}", request.getDataBytes());
logger.info("codeBytes: {}", request.getNumCallStackPages());
logger.info("codeBytes: {}", request.getMinActivationAmount());
byte[] creationBytes = MachineState.toCreationBytes(
request.getCiyamAtVersion(),
request.getCodeBytes(),
request.getDataBytes(),
request.getNumCallStackPages(),
request.getNumUserStackPages(),
request.getMinActivationAmount()
);
return Base58.encode(creationBytes);
public String create(AtCreationRequest atCreationRequest) {
if (atCreationRequest.getCiyamAtVersion() < 2) {
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.INVALID_CRITERIA, "ciyamAtVersion must be at least 2");
}
if (atCreationRequest.getCodeBytes() == null) {
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.INVALID_CRITERIA, "Valid codeBytesBase64 must be supplied");
}
if (atCreationRequest.getDataBytes() == null) {
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.INVALID_CRITERIA, "Valid dataBytesBase64 must be supplied");
}
byte[] creationBytes = MachineState.toCreationBytes(
atCreationRequest.getCiyamAtVersion(),
atCreationRequest.getCodeBytes(),
atCreationRequest.getDataBytes(),
atCreationRequest.getNumCallStackPages(),
atCreationRequest.getNumUserStackPages(),
atCreationRequest.getMinActivationAmount()
);
return Base58.encode(creationBytes);
}
@POST
@Operation(

78
src/main/java/org/qortal/data/transaction/CreationRequest.java

@ -1,78 +0,0 @@
package org.qortal.data.transaction;
import java.util.Base64;
import com.fasterxml.jackson.annotation.JsonProperty;
public class CreationRequest {
private short ciyamAtVersion;
@JsonProperty("codeBytesBase64")
private String codeBytesBase64;
private String dataBytesBase64;
private short numCallStackPages;
private short numUserStackPages;
private long minActivationAmount;
// Default constructor for JSON deserialization
public CreationRequest() {}
// Getters and setters
public short getCiyamAtVersion() {
return ciyamAtVersion;
}
public void setCiyamAtVersion(short ciyamAtVersion) {
this.ciyamAtVersion = ciyamAtVersion;
}
public byte[] getCodeBytes() {
if (this.codeBytesBase64 != null) {
return Base64.getDecoder().decode(this.codeBytesBase64);
}
return new byte[0];
}
public void setCodeBytesBase64(String codeBytesBase64) {
this.codeBytesBase64 = codeBytesBase64;
}
public String getCodeBytes2() {
return codeBytesBase64;
}
public byte[] getDataBytes() {
if (this.dataBytesBase64 != null) {
return Base64.getDecoder().decode(this.dataBytesBase64);
}
return new byte[0];
}
public void setDataBytesBase64(String dataBytesBase64) {
this.dataBytesBase64 = dataBytesBase64;
}
public short getNumCallStackPages() {
return numCallStackPages;
}
public void setNumCallStackPages(short numCallStackPages) {
this.numCallStackPages = numCallStackPages;
}
public short getNumUserStackPages() {
return numUserStackPages;
}
public void setNumUserStackPages(short numUserStackPages) {
this.numUserStackPages = numUserStackPages;
}
public long getMinActivationAmount() {
return minActivationAmount;
}
public void setMinActivationAmount(long minActivationAmount) {
this.minActivationAmount = minActivationAmount;
}
}
Loading…
Cancel
Save