Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,51 @@ T setData(String text) {
// noinspection unchecked
return (T) this;
}

/**
* Checks whether {@code innerSignedTransactions} is not empty.
*
* @return {@code true} if {@code innerSignedTransactions} is not empty; otherwise {@code false}
*/
boolean hasInnerSignedTransactions(){
return (!innerSignedTransactions.isEmpty());
}

/**
* Assigns the data via {@code innerSignedTransactions}.
*
* @return {@code this}
* @throws IllegalArgumentException if {@code innerSignedTransactions} is empty
*/
T setDataFromInnerSignedTransactions() {
if (!innerSignedTransactions.isEmpty()) {
try {
for (var i = 0; i < innerSignedTransactions.size(); i += nodeAccountIds.isEmpty() ? 1 : nodeAccountIds.size()) {
ByteString content = extractContents(TransactionBody.parseFrom(innerSignedTransactions.get(i).getBodyBytes()));
data = data.concat(content);
}
return (T) this;
} catch (InvalidProtocolBufferException exc) {
throw new IllegalArgumentException(exc.getMessage());
}
}
return (T) this;
}

/**
* Extracts the content bytes from a {@link TransactionBody}.
* <p>
* This is a template method used by
* {@link #setDataFromInnerSignedTransactions()} to consolidate content from
* multiple inner signed transactions. Because different transaction types
* (e.g., FileCreate, FileUpdate, FileAppend) store their content in different
* fields of the protobuf body, child classes must implement this method to
* specify the correct field to extract.
*
* @param body The protobuf transaction body to extract data from.
* @return The {@link ByteString} representing the content of the transaction.
*/
protected abstract ByteString extractContents(TransactionBody body);

/**
* Retrieve the maximum number of chunks.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,23 +186,17 @@ void initFromTransactionBody() {
fileId = FileId.fromProtobuf(body.getFileID());
}

if (!innerSignedTransactions.isEmpty()) {
try {
for (var i = 0;
i < innerSignedTransactions.size();
i += nodeAccountIds.isEmpty() ? 1 : nodeAccountIds.size()) {
data = data.concat(TransactionBody.parseFrom(
innerSignedTransactions.get(i).getBodyBytes())
.getFileAppend()
.getContents());
}
} catch (InvalidProtocolBufferException exc) {
throw new IllegalArgumentException(exc.getMessage());
}
if (hasInnerSignedTransactions()) {
setDataFromInnerSignedTransactions();
} else {
data = body.getContents();
setData(body.getContents().toByteArray());
}
}

@Override
protected ByteString extractContents(TransactionBody body) {
return body.getFileAppend().getContents();
}

/**
* Build the transaction body.
Expand All @@ -214,7 +208,7 @@ FileAppendTransactionBody.Builder build() {
if (fileId != null) {
builder.setFileID(fileId.toProtobuf());
}
builder.setContents(data);
builder.setContents(getData());

return builder;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@
import com.hedera.hashgraph.sdk.proto.FileServiceGrpc;
import com.hedera.hashgraph.sdk.proto.SchedulableTransactionBody;
import com.hedera.hashgraph.sdk.proto.TransactionBody;
import com.hedera.hashgraph.sdk.proto.TransactionID;
import com.hedera.hashgraph.sdk.proto.TransactionResponse;
import io.grpc.MethodDescriptor;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
Expand All @@ -23,7 +22,7 @@
* Create a new file.
*
* If successful, the new file SHALL contain the (possibly empty) content
* provided in the `contents` field.<br/>
* provided in the `data` field in {@link ChunkedTransaction}.<br/>
* When the current consensus time exceeds the `expirationTime` value, the
* network SHALL expire the file, and MAY archive the state entry.
*
Expand Down Expand Up @@ -60,7 +59,7 @@
* After the file is created, the FileID for it SHALL be returned in the
* transaction receipt, and SHALL be recorded in the transaction record.
*/
public final class FileCreateTransaction extends Transaction<FileCreateTransaction> {
public final class FileCreateTransaction extends ChunkedTransaction<FileCreateTransaction> {

@Nullable
private Instant expirationTime = null;
Expand All @@ -70,7 +69,6 @@ public final class FileCreateTransaction extends Transaction<FileCreateTransacti
@Nullable
private KeyList keys = null;

private byte[] contents = {};
private String fileMemo = "";

/**
Expand Down Expand Up @@ -175,61 +173,51 @@ public FileCreateTransaction setKeys(Key... keys) {
}

/**
* Create the byte string.
*
* @return byte string representation
*/
public ByteString getContents() {
return ByteString.copyFrom(contents);
}
* Extract the files contents as a byte string.
*
* @return the files contents as a byte string
*/
public ByteString getContents() {
return getData();
}

/**
* <p>Set the given byte array as the file's contents.
*
* <p>This may be omitted to create an empty file.
*
* <p>Note that total size for a given transaction is limited to 6KiB (as of March 2020) by the
* network; if you exceed this you may receive a {@link PrecheckStatusException}
* with {@link com.hedera.hashgraph.sdk.Status#TRANSACTION_OVERSIZE}.
*
* <p>In this case, you can use {@link FileAppendTransaction}, which automatically breaks the contents
* into chunks for you, to append contents of arbitrary size.
*
* @param bytes the contents of the file.
* @return {@code this}
*/
public FileCreateTransaction setContents(byte[] bytes) {
requireNotFrozen();
Objects.requireNonNull(bytes);
contents = Arrays.copyOf(bytes, bytes.length);
return this;
}
* <p>
* Set the given byte array as the file's contents.
*
* <p>
* This may be omitted to create an empty file.
*
* @param bytes the contents of the file.
* @return {@code this}
*/
public FileCreateTransaction setContents(byte[] bytes) {
requireNotFrozen();
Objects.requireNonNull(bytes);
return setData(bytes);
}

/**
* <p>Encode the given {@link String} as UTF-8 and set it as the file's contents.
*
* <p>This may be omitted to create an empty file.
*
* <p>The string can later be recovered from {@link FileContentsQuery#execute(Client)}
* via {@link String#String(byte[], java.nio.charset.Charset)} using
* {@link java.nio.charset.StandardCharsets#UTF_8}.
*
* <p>Note that total size for a given transaction is limited to 6KiB (as of March 2020) by the
* network; if you exceed this you may receive a {@link PrecheckStatusException}
* with {@link com.hedera.hashgraph.sdk.Status#TRANSACTION_OVERSIZE}.
*
* <p>In this case, you can use {@link FileAppendTransaction}, which automatically breaks the contents
* into chunks for you, to append contents of arbitrary size.
*
* @param text the contents of the file.
* @return {@code this}
*/
public FileCreateTransaction setContents(String text) {
requireNotFrozen();
Objects.requireNonNull(text);
contents = text.getBytes(StandardCharsets.UTF_8);
return this;
}
* <p>
* Encode the given {@link String} as UTF-8 and set it as the file's contents.
*
* <p>
* This may be omitted to create an empty file.
*
* <p>
* The string can later be recovered from
* {@link FileContentsQuery#execute(Client)} via
* {@link String#String(byte[], java.nio.charset.Charset)} using
* {@link java.nio.charset.StandardCharsets#UTF_8}.
*
* @param text the contents of the file.
* @return {@code this}
*/
public FileCreateTransaction setContents(String text) {
requireNotFrozen();
Objects.requireNonNull(text);
return setData(text);
}

/**
* Extract the file's memo field.
Expand Down Expand Up @@ -274,8 +262,18 @@ void initFromTransactionBody() {
if (body.hasKeys()) {
keys = KeyList.fromProtobuf(body.getKeys(), null);
}
contents = body.getContents().toByteArray();
fileMemo = body.getMemo();

if (hasInnerSignedTransactions()) {
setDataFromInnerSignedTransactions();
} else {
setData(body.getContents().toByteArray());
}
}

@Override
protected ByteString extractContents(TransactionBody body) {
return body.getFileCreate().getContents();
}

/**
Expand All @@ -295,11 +293,22 @@ FileCreateTransactionBody.Builder build() {
if (keys != null) {
builder.setKeys(keys.toProtobuf());
}
builder.setContents(ByteString.copyFrom(contents));
builder.setContents(getData());
builder.setMemo(fileMemo);

return builder;
}

@Override
void onFreezeChunk(
TransactionBody.Builder body,
@Nullable TransactionID initialTransactionId,
int startIndex,
int endIndex,
int chunk,
int total) {
body.setFileCreate(build().setContents(data.substring(startIndex, endIndex)));
}

@Override
void onFreeze(TransactionBody.Builder bodyBuilder) {
Expand Down
Loading