From 9fc38bb223f3ab5a7266cb7caed03f5506262cbd Mon Sep 17 00:00:00 2001 From: dikel Date: Fri, 23 Dec 2022 13:09:22 +0200 Subject: [PATCH 01/14] feat: initial hip 583 commit Signed-off-by: dikel --- CHANGELOG.md | 11 + .../sdk/AccountCreateTransaction.java | 40 ++ .../hedera/hashgraph/sdk/PublicKeyECDSA.java | 18 +- .../com/hedera/hashgraph/sdk/RequestType.java | 451 ++++++++++++------ .../java/com/hedera/hashgraph/sdk/Status.java | 19 +- .../hashgraph/sdk/TransactionRecord.java | 17 +- sdk/src/main/proto/basic_types.proto | 29 +- .../main/proto/consensus_create_topic.proto | 1 + .../main/proto/consensus_delete_topic.proto | 1 + .../main/proto/consensus_get_topic_info.proto | 1 + sdk/src/main/proto/consensus_service.proto | 1 + .../main/proto/consensus_submit_message.proto | 1 + sdk/src/main/proto/consensus_topic_info.proto | 1 + .../main/proto/consensus_update_topic.proto | 1 + sdk/src/main/proto/contract_call.proto | 1 + sdk/src/main/proto/contract_call_local.proto | 1 + sdk/src/main/proto/contract_create.proto | 1 + sdk/src/main/proto/contract_delete.proto | 1 + .../main/proto/contract_get_bytecode.proto | 1 + sdk/src/main/proto/contract_get_info.proto | 1 + sdk/src/main/proto/contract_get_records.proto | 1 + sdk/src/main/proto/contract_update.proto | 4 +- sdk/src/main/proto/crypto_add_live_hash.proto | 1 + .../main/proto/crypto_approve_allowance.proto | 1 + sdk/src/main/proto/crypto_create.proto | 22 +- sdk/src/main/proto/crypto_delete.proto | 1 + .../main/proto/crypto_delete_allowance.proto | 1 + .../main/proto/crypto_delete_live_hash.proto | 1 + .../proto/crypto_get_account_balance.proto | 1 + .../proto/crypto_get_account_records.proto | 1 + sdk/src/main/proto/crypto_get_info.proto | 14 + sdk/src/main/proto/crypto_get_live_hash.proto | 1 + sdk/src/main/proto/crypto_get_stakers.proto | 1 + sdk/src/main/proto/crypto_service.proto | 1 + sdk/src/main/proto/crypto_transfer.proto | 1 + sdk/src/main/proto/crypto_update.proto | 21 + sdk/src/main/proto/custom_fees.proto | 19 + sdk/src/main/proto/duration.proto | 1 + sdk/src/main/proto/ethereum_transaction.proto | 1 + sdk/src/main/proto/exchange_rate.proto | 1 + sdk/src/main/proto/file_append.proto | 1 + sdk/src/main/proto/file_create.proto | 22 +- sdk/src/main/proto/file_delete.proto | 1 + sdk/src/main/proto/file_get_contents.proto | 1 + sdk/src/main/proto/file_get_info.proto | 12 + sdk/src/main/proto/file_service.proto | 1 + sdk/src/main/proto/file_update.proto | 16 +- sdk/src/main/proto/freeze.proto | 1 + sdk/src/main/proto/freeze_service.proto | 1 + sdk/src/main/proto/freeze_type.proto | 1 + sdk/src/main/proto/get_account_details.proto | 1 + sdk/src/main/proto/get_by_key.proto | 1 + sdk/src/main/proto/get_by_solidity_id.proto | 1 + .../proto/network_get_execution_time.proto | 1 + .../main/proto/network_get_version_info.proto | 1 + sdk/src/main/proto/network_service.proto | 1 + sdk/src/main/proto/node_stake_update.proto | 1 + sdk/src/main/proto/query.proto | 1 + sdk/src/main/proto/query_header.proto | 1 + sdk/src/main/proto/response.proto | 1 + sdk/src/main/proto/response_code.proto | 14 +- sdk/src/main/proto/response_header.proto | 1 + .../proto/schedulable_transaction_body.proto | 1 + sdk/src/main/proto/schedule_create.proto | 1 + sdk/src/main/proto/schedule_delete.proto | 1 + sdk/src/main/proto/schedule_get_info.proto | 1 + sdk/src/main/proto/schedule_service.proto | 1 + sdk/src/main/proto/schedule_sign.proto | 1 + .../main/proto/smart_contract_service.proto | 1 + sdk/src/main/proto/system_delete.proto | 1 + sdk/src/main/proto/system_undelete.proto | 1 + sdk/src/main/proto/throttle_definitions.proto | 1 + sdk/src/main/proto/timestamp.proto | 1 + sdk/src/main/proto/token_associate.proto | 1 + sdk/src/main/proto/token_burn.proto | 6 +- sdk/src/main/proto/token_create.proto | 1 + sdk/src/main/proto/token_delete.proto | 1 + sdk/src/main/proto/token_dissociate.proto | 1 + .../proto/token_fee_schedule_update.proto | 1 + sdk/src/main/proto/token_freeze_account.proto | 1 + .../proto/token_get_account_nft_infos.proto | 1 + sdk/src/main/proto/token_get_info.proto | 1 + sdk/src/main/proto/token_get_nft_info.proto | 1 + sdk/src/main/proto/token_get_nft_infos.proto | 1 + sdk/src/main/proto/token_grant_kyc.proto | 1 + sdk/src/main/proto/token_mint.proto | 6 +- sdk/src/main/proto/token_pause.proto | 1 + sdk/src/main/proto/token_revoke_kyc.proto | 1 + sdk/src/main/proto/token_service.proto | 1 + .../main/proto/token_unfreeze_account.proto | 1 + sdk/src/main/proto/token_unpause.proto | 1 + sdk/src/main/proto/token_update.proto | 1 + sdk/src/main/proto/token_wipe_account.proto | 6 +- sdk/src/main/proto/transaction.proto | 1 + sdk/src/main/proto/transaction_body.proto | 1 + sdk/src/main/proto/transaction_contents.proto | 1 + .../proto/transaction_get_fast_record.proto | 1 + .../main/proto/transaction_get_receipt.proto | 1 + .../main/proto/transaction_get_record.proto | 1 + sdk/src/main/proto/transaction_receipt.proto | 1 + sdk/src/main/proto/transaction_record.proto | 7 + sdk/src/main/proto/transaction_response.proto | 1 + sdk/src/main/proto/unchecked_submit.proto | 1 + sdk/src/main/proto/util_prng.proto | 1 + sdk/src/main/proto/util_service.proto | 1 + .../sdk/AccountCreateTransactionTest.java | 2 +- .../sdk/AccountCreateTransactionTest.snap | 4 +- .../hashgraph/sdk/ECDSAPublicKeyTest.java | 13 + .../hashgraph/sdk/TransactionRecordTest.java | 3 +- .../hashgraph/sdk/TransactionRecordTest.snap | 6 +- 110 files changed, 679 insertions(+), 188 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c157dbae7..2449db3ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Added + - `TransactionRecord.evmAddress` + - `PublicKeyECDSA.toEvmAddress()` + - `AccountCreateTransaction.setEvmAddress()` + +### Deprecated + +- `AccountCreateTransaction.setAliasEvmAddress()` use `AccountCreateTransaction.setEvmAddress() instead` + ## 2.19.0 ### Added diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountCreateTransaction.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountCreateTransaction.java index 7213129fa..a8b3790a0 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountCreateTransaction.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountCreateTransaction.java @@ -62,6 +62,9 @@ public final class AccountCreateTransaction extends Transaction * The ethereum account 20-byte EVM address to be used as the account's alias. This EVM address may be either @@ -395,12 +400,42 @@ public EvmAddress getAliasEvmAddress() { * @param aliasEvmAddress The ethereum account 20-byte EVM address * @return {@code this} */ + @Deprecated public AccountCreateTransaction setAliasEvmAddress(EvmAddress aliasEvmAddress) { requireNotFrozen(); this.aliasEvmAddress = aliasEvmAddress; return this; } + /** + * EOA 20-byte address to create that is derived from the keccak-256 hash of a ECDSA_SECP256K1 primitive key. + */ + @Nullable + public EvmAddress getEvmAddress() { + return evmAddress; + } + + /** + * NOT YET SUPPORTED ON MAINNET AS OF DEC/23/2022 + *

+ * The ethereum account 20-byte EVM address to be used as the account's alias. This EVM address may be either + * the encoded form of the shard.realm.num or the keccak-256 hash of a ECDSA_SECP256K1 primitive key. + *

+ * A given alias can map to at most one account on the network at a time. This uniqueness will be enforced + * relative to aliases currently on the network at alias assignment. + *

+ * If a transaction creates an account using an alias, any further crypto transfers to that alias will + * simply be deposited in that account, without creating anything, and with no creation fee being charged. + * + * @param evmAddress The ethereum account 20-byte EVM address + * @return {@code this} + */ + public AccountCreateTransaction setEvmAddress(EvmAddress evmAddress) { + requireNotFrozen(); + this.evmAddress = evmAddress; + return this; + } + /** * Build the transaction body. * @@ -435,6 +470,10 @@ CryptoCreateTransactionBody.Builder build() { builder.setStakedNodeId(stakedNodeId); } + if (evmAddress != null) { + builder.setEvmAddress(ByteString.copyFrom(evmAddress.toBytes())); + } + return builder; } @@ -480,6 +519,7 @@ void initFromTransactionBody() { aliasKey = PublicKey.fromAliasBytes(body.getAlias()); aliasEvmAddress = EvmAddress.fromAliasBytes(body.getAlias()); + evmAddress = EvmAddress.fromAliasBytes(body.getEvmAddress()); } @Override diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/PublicKeyECDSA.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/PublicKeyECDSA.java index 53c6ebaad..f347fdda9 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/PublicKeyECDSA.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/PublicKeyECDSA.java @@ -25,12 +25,15 @@ import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.signers.ECDSASigner; +import org.bouncycastle.jcajce.provider.digest.Keccak; +import org.bouncycastle.util.encoders.Hex; -import javax.annotation.Nullable; import java.io.IOException; import java.math.BigInteger; import java.util.Arrays; +import static com.hedera.hashgraph.sdk.Crypto.calcKeccak256; + /** * Encapsulate the ECDSA public key. */ @@ -85,7 +88,7 @@ ByteString extractSignatureFromProtobuf(SignaturePair pair) { @Override public boolean verify(byte[] message, byte[] signature) { - var hash = Crypto.calcKeccak256(message); + var hash = calcKeccak256(message); ECDSASigner signer = new ECDSASigner(); signer.init(false, new ECPublicKeyParameters( @@ -136,6 +139,17 @@ public byte[] toBytesRaw() { return Arrays.copyOf(keyData, keyData.length); } + public String toEvmAddress() { + // Calculate the Keccak-256 hash of the uncompressed key without "04" prefix + byte[] uncompressed = Key.ECDSA_SECP256K1_CURVE + .getCurve().decodePoint(toBytesRaw()).getEncoded(false); + byte[] keccakBytes = calcKeccak256(Arrays.copyOfRange(uncompressed, 1, uncompressed.length)); + + // Return the last 20 bytes prefixed by "0x" + String keccakString = Hex.toHexString(keccakBytes); + return "0x" + keccakString.substring(24); + } + @Override public boolean equals( Object o) { if (this == o) { diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/RequestType.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/RequestType.java index 1812872e2..1f5bd2ded 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/RequestType.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/RequestType.java @@ -393,160 +393,309 @@ public enum RequestType { } static RequestType valueOf(HederaFunctionality code) { - return switch (code) { - case NONE -> NONE; - case CryptoTransfer -> CRYPTO_TRANSFER; - case CryptoUpdate -> CRYPTO_UPDATE; - case CryptoDelete -> CRYPTO_DELETE; - case CryptoAddLiveHash -> CRYPTO_ADD_LIVE_HASH; - case CryptoDeleteLiveHash -> CRYPTO_DELETE_LIVE_HASH; - case ContractCall -> CONTRACT_CALL; - case ContractCreate -> CONTRACT_CREATE; - case ContractUpdate -> CONTRACT_UPDATE; - case FileCreate -> FILE_CREATE; - case FileAppend -> FILE_APPEND; - case FileUpdate -> FILE_UPDATE; - case FileDelete -> FILE_DELETE; - case CryptoGetAccountBalance -> CRYPTO_GET_ACCOUNT_BALANCE; - case CryptoGetAccountRecords -> CRYPTO_GET_ACCOUNT_RECORDS; - case CryptoGetInfo -> CRYPTO_GET_INFO; - case ContractCallLocal -> CONTRACT_CALL_LOCAL; - case ContractGetInfo -> CONTRACT_GET_INFO; - case ContractGetBytecode -> CONTRACT_GET_BYTECODE; - case GetBySolidityID -> GET_BY_SOLIDITY_ID; - case GetByKey -> GET_BY_KEY; - case CryptoGetLiveHash -> CRYPTO_GET_LIVE_HASH; - case CryptoGetStakers -> CRYPTO_GET_STAKERS; - case FileGetContents -> FILE_GET_CONTENTS; - case FileGetInfo -> FILE_GET_INFO; - case TransactionGetRecord -> TRANSACTION_GET_RECORD; - case ContractGetRecords -> CONTRACT_GET_RECORDS; - case CryptoCreate -> CRYPTO_CREATE; - case SystemDelete -> SYSTEM_DELETE; - case SystemUndelete -> SYSTEM_UNDELETE; - case ContractDelete -> CONTRACT_DELETE; - case Freeze -> FREEZE; - case CreateTransactionRecord -> CREATE_TRANSACTION_RECORD; - case CryptoAccountAutoRenew -> CRYPTO_ACCOUNT_AUTO_RENEW; - case ContractAutoRenew -> CONTRACT_AUTO_RENEW; - case GetVersionInfo -> GET_VERSION_INFO; - case TransactionGetReceipt -> TRANSACTION_GET_RECEIPT; - case ConsensusCreateTopic -> CONSENSUS_CREATE_TOPIC; - case ConsensusUpdateTopic -> CONSENSUS_UPDATE_TOPIC; - case ConsensusDeleteTopic -> CONSENSUS_DELETE_TOPIC; - case ConsensusGetTopicInfo -> CONSENSUS_GET_TOPIC_INFO; - case ConsensusSubmitMessage -> CONSENSUS_SUBMIT_MESSAGE; - case UncheckedSubmit -> UNCHECKED_SUBMIT; - case TokenCreate -> TOKEN_CREATE; - case TokenGetInfo -> TOKEN_GET_INFO; - case TokenFreezeAccount -> TOKEN_FREEZE_ACCOUNT; - case TokenUnfreezeAccount -> TOKEN_UNFREEZE_ACCOUNT; - case TokenGrantKycToAccount -> TOKEN_GRANT_KYC_TO_ACCOUNT; - case TokenRevokeKycFromAccount -> TOKEN_REVOKE_KYC_FROM_ACCOUNT; - case TokenDelete -> TOKEN_DELETE; - case TokenUpdate -> TOKEN_UPDATE; - case TokenMint -> TOKEN_MINT; - case TokenBurn -> TOKEN_BURN; - case TokenAccountWipe -> TOKEN_ACCOUNT_WIPE; - case TokenAssociateToAccount -> TOKEN_ASSOCIATE_TO_ACCOUNT; - case TokenDissociateFromAccount -> TOKEN_DISSOCIATE_FROM_ACCOUNT; - case ScheduleCreate -> SCHEDULE_CREATE; - case ScheduleDelete -> SCHEDULE_DELETE; - case ScheduleSign -> SCHEDULE_SIGN; - case ScheduleGetInfo -> SCHEDULE_GET_INFO; - case TokenGetAccountNftInfos -> TOKEN_GET_ACCOUNT_NFT_INFOS; - case TokenGetNftInfo -> TOKEN_GET_NFT_INFO; - case TokenGetNftInfos -> TOKEN_GET_NFT_INFOS; - case TokenFeeScheduleUpdate -> TOKEN_FEE_SCHEDULE_UPDATE; - case NetworkGetExecutionTime -> NETWORK_GET_EXECUTION_TIME; - case TokenPause -> TOKEN_PAUSE; - case TokenUnpause -> TOKEN_UNPAUSE; - case CryptoApproveAllowance -> CRYPTO_APPROVE_ALLOWANCE; - case CryptoDeleteAllowance -> CRYPTO_DELETE_ALLOWANCE; - case GetAccountDetails -> GET_ACCOUNT_DETAILS; - case EthereumTransaction -> ETHEREUM_TRANSACTION; - case NodeStakeUpdate -> NODE_STAKE_UPDATE; - case UtilPrng -> PRNG; - default -> throw new IllegalStateException("(BUG) unhandled HederaFunctionality"); - }; + switch (code) { + case NONE: + return NONE; + case CryptoTransfer: + return CRYPTO_TRANSFER; + case CryptoUpdate: + return CRYPTO_UPDATE; + case CryptoDelete: + return CRYPTO_DELETE; + case CryptoAddLiveHash: + return CRYPTO_ADD_LIVE_HASH; + case CryptoDeleteLiveHash: + return CRYPTO_DELETE_LIVE_HASH; + case ContractCall: + return CONTRACT_CALL; + case ContractCreate: + return CONTRACT_CREATE; + case ContractUpdate: + return CONTRACT_UPDATE; + case FileCreate: + return FILE_CREATE; + case FileAppend: + return FILE_APPEND; + case FileUpdate: + return FILE_UPDATE; + case FileDelete: + return FILE_DELETE; + case CryptoGetAccountBalance: + return CRYPTO_GET_ACCOUNT_BALANCE; + case CryptoGetAccountRecords: + return CRYPTO_GET_ACCOUNT_RECORDS; + case CryptoGetInfo: + return CRYPTO_GET_INFO; + case ContractCallLocal: + return CONTRACT_CALL_LOCAL; + case ContractGetInfo: + return CONTRACT_GET_INFO; + case ContractGetBytecode: + return CONTRACT_GET_BYTECODE; + case GetBySolidityID: + return GET_BY_SOLIDITY_ID; + case GetByKey: + return GET_BY_KEY; + case CryptoGetLiveHash: + return CRYPTO_GET_LIVE_HASH; + case CryptoGetStakers: + return CRYPTO_GET_STAKERS; + case FileGetContents: + return FILE_GET_CONTENTS; + case FileGetInfo: + return FILE_GET_INFO; + case TransactionGetRecord: + return TRANSACTION_GET_RECORD; + case ContractGetRecords: + return CONTRACT_GET_RECORDS; + case CryptoCreate: + return CRYPTO_CREATE; + case SystemDelete: + return SYSTEM_DELETE; + case SystemUndelete: + return SYSTEM_UNDELETE; + case ContractDelete: + return CONTRACT_DELETE; + case Freeze: + return FREEZE; + case CreateTransactionRecord: + return CREATE_TRANSACTION_RECORD; + case CryptoAccountAutoRenew: + return CRYPTO_ACCOUNT_AUTO_RENEW; + case ContractAutoRenew: + return CONTRACT_AUTO_RENEW; + case GetVersionInfo: + return GET_VERSION_INFO; + case TransactionGetReceipt: + return TRANSACTION_GET_RECEIPT; + case ConsensusCreateTopic: + return CONSENSUS_CREATE_TOPIC; + case ConsensusUpdateTopic: + return CONSENSUS_UPDATE_TOPIC; + case ConsensusDeleteTopic: + return CONSENSUS_DELETE_TOPIC; + case ConsensusGetTopicInfo: + return CONSENSUS_GET_TOPIC_INFO; + case ConsensusSubmitMessage: + return CONSENSUS_SUBMIT_MESSAGE; + case UncheckedSubmit: + return UNCHECKED_SUBMIT; + case TokenCreate: + return TOKEN_CREATE; + case TokenGetInfo: + return TOKEN_GET_INFO; + case TokenFreezeAccount: + return TOKEN_FREEZE_ACCOUNT; + case TokenUnfreezeAccount: + return TOKEN_UNFREEZE_ACCOUNT; + case TokenGrantKycToAccount: + return TOKEN_GRANT_KYC_TO_ACCOUNT; + case TokenRevokeKycFromAccount: + return TOKEN_REVOKE_KYC_FROM_ACCOUNT; + case TokenDelete: + return TOKEN_DELETE; + case TokenUpdate: + return TOKEN_UPDATE; + case TokenMint: + return TOKEN_MINT; + case TokenBurn: + return TOKEN_BURN; + case TokenAccountWipe: + return TOKEN_ACCOUNT_WIPE; + case TokenAssociateToAccount: + return TOKEN_ASSOCIATE_TO_ACCOUNT; + case TokenDissociateFromAccount: + return TOKEN_DISSOCIATE_FROM_ACCOUNT; + case ScheduleCreate: + return SCHEDULE_CREATE; + case ScheduleDelete: + return SCHEDULE_DELETE; + case ScheduleSign: + return SCHEDULE_SIGN; + case ScheduleGetInfo: + return SCHEDULE_GET_INFO; + case TokenGetAccountNftInfos: + return TOKEN_GET_ACCOUNT_NFT_INFOS; + case TokenGetNftInfo: + return TOKEN_GET_NFT_INFO; + case TokenGetNftInfos: + return TOKEN_GET_NFT_INFOS; + case TokenFeeScheduleUpdate: + return TOKEN_FEE_SCHEDULE_UPDATE; + case NetworkGetExecutionTime: + return NETWORK_GET_EXECUTION_TIME; + case TokenPause: + return TOKEN_PAUSE; + case TokenUnpause: + return TOKEN_UNPAUSE; + case CryptoApproveAllowance: + return CRYPTO_APPROVE_ALLOWANCE; + case CryptoDeleteAllowance: + return CRYPTO_DELETE_ALLOWANCE; + case GetAccountDetails: + return GET_ACCOUNT_DETAILS; + case EthereumTransaction: + return ETHEREUM_TRANSACTION; + case NodeStakeUpdate: + return NODE_STAKE_UPDATE; + case UtilPrng: + return PRNG; + default: + throw new IllegalStateException("(BUG) unhandled HederaFunctionality"); + } } @Override public String toString() { - return switch (this) { - case NONE -> "NONE"; - case CRYPTO_TRANSFER -> "CRYPTO_TRANSFER"; - case CRYPTO_UPDATE -> "CRYPTO_UPDATE"; - case CRYPTO_DELETE -> "CRYPTO_DELETE"; - case CRYPTO_ADD_LIVE_HASH -> "CRYPTO_ADD_LIVE_HASH"; - case CRYPTO_DELETE_LIVE_HASH -> "CRYPTO_DELETE_LIVE_HASH"; - case CONTRACT_CALL -> "CONTRACT_CALL"; - case CONTRACT_CREATE -> "CONTRACT_CREATE"; - case CONTRACT_UPDATE -> "CONTRACT_UPDATE"; - case FILE_CREATE -> "FILE_CREATE"; - case FILE_APPEND -> "FILE_APPEND"; - case FILE_UPDATE -> "FILE_UPDATE"; - case FILE_DELETE -> "FILE_DELETE"; - case CRYPTO_GET_ACCOUNT_BALANCE -> "CRYPTO_GET_ACCOUNT_BALANCE"; - case CRYPTO_GET_ACCOUNT_RECORDS -> "CRYPTO_GET_ACCOUNT_RECORDS"; - case CRYPTO_GET_INFO -> "CRYPTO_GET_INFO"; - case CONTRACT_CALL_LOCAL -> "CONTRACT_CALL_LOCAL"; - case CONTRACT_GET_INFO -> "CONTRACT_GET_INFO"; - case CONTRACT_GET_BYTECODE -> "CONTRACT_GET_BYTECODE"; - case GET_BY_SOLIDITY_ID -> "GET_BY_SOLIDITY_ID"; - case GET_BY_KEY -> "GET_BY_KEY"; - case CRYPTO_GET_LIVE_HASH -> "CRYPTO_GET_LIVE_HASH"; - case CRYPTO_GET_STAKERS -> "CRYPTO_GET_STAKERS"; - case FILE_GET_CONTENTS -> "FILE_GET_CONTENTS"; - case FILE_GET_INFO -> "FILE_GET_INFO"; - case TRANSACTION_GET_RECORD -> "TRANSACTION_GET_RECORD"; - case CONTRACT_GET_RECORDS -> "CONTRACT_GET_RECORDS"; - case CRYPTO_CREATE -> "CRYPTO_CREATE"; - case SYSTEM_DELETE -> "SYSTEM_DELETE"; - case SYSTEM_UNDELETE -> "SYSTEM_UNDELETE"; - case CONTRACT_DELETE -> "CONTRACT_DELETE"; - case FREEZE -> "FREEZE"; - case CREATE_TRANSACTION_RECORD -> "CREATE_TRANSACTION_RECORD"; - case CRYPTO_ACCOUNT_AUTO_RENEW -> "CRYPTO_ACCOUNT_AUTO_RENEW"; - case CONTRACT_AUTO_RENEW -> "CONTRACT_AUTO_RENEW"; - case GET_VERSION_INFO -> "GET_VERSION_INFO"; - case TRANSACTION_GET_RECEIPT -> "TRANSACTION_GET_RECEIPT"; - case CONSENSUS_CREATE_TOPIC -> "CONSENSUS_CREATE_TOPIC"; - case CONSENSUS_UPDATE_TOPIC -> "CONSENSUS_UPDATE_TOPIC"; - case CONSENSUS_DELETE_TOPIC -> "CONSENSUS_DELETE_TOPIC"; - case CONSENSUS_GET_TOPIC_INFO -> "CONSENSUS_GET_TOPIC_INFO"; - case CONSENSUS_SUBMIT_MESSAGE -> "CONSENSUS_SUBMIT_MESSAGE"; - case UNCHECKED_SUBMIT -> "UNCHECKED_SUBMIT"; - case TOKEN_CREATE -> "TOKEN_CREATE"; - case TOKEN_GET_INFO -> "TOKEN_GET_INFO"; - case TOKEN_FREEZE_ACCOUNT -> "TOKEN_FREEZE_ACCOUNT"; - case TOKEN_UNFREEZE_ACCOUNT -> "TOKEN_UNFREEZE_ACCOUNT"; - case TOKEN_GRANT_KYC_TO_ACCOUNT -> "TOKEN_GRANT_KYC_TO_ACCOUNT"; - case TOKEN_REVOKE_KYC_FROM_ACCOUNT -> "TOKEN_REVOKE_KYC_FROM_ACCOUNT"; - case TOKEN_DELETE -> "TOKEN_DELETE"; - case TOKEN_UPDATE -> "TOKEN_UPDATE"; - case TOKEN_MINT -> "TOKEN_MINT"; - case TOKEN_BURN -> "TOKEN_BURN"; - case TOKEN_ACCOUNT_WIPE -> "TOKEN_ACCOUNT_WIPE"; - case TOKEN_ASSOCIATE_TO_ACCOUNT -> "TOKEN_ASSOCIATE_TO_ACCOUNT"; - case TOKEN_DISSOCIATE_FROM_ACCOUNT -> "TOKEN_DISSOCIATE_FROM_ACCOUNT"; - case SCHEDULE_CREATE -> "SCHEDULE_CREATE"; - case SCHEDULE_DELETE -> "SCHEDULE_DELETE"; - case SCHEDULE_SIGN -> "SCHEDULE_SIGN"; - case SCHEDULE_GET_INFO -> "SCHEDULE_GET_INFO"; - case TOKEN_GET_ACCOUNT_NFT_INFOS -> "TOKEN_GET_ACCOUNT_NFT_INFOS"; - case TOKEN_GET_NFT_INFO -> "TOKEN_GET_NFT_INFO"; - case TOKEN_GET_NFT_INFOS -> "TOKEN_GET_NFT_INFOS"; - case TOKEN_FEE_SCHEDULE_UPDATE -> "TOKEN_FEE_SCHEDULE_UPDATE"; - case NETWORK_GET_EXECUTION_TIME -> "NETWORK_GET_EXECUTION_TIME"; - case TOKEN_PAUSE -> "TOKEN_PAUSE"; - case TOKEN_UNPAUSE -> "TOKEN_UNPAUSE"; - case CRYPTO_APPROVE_ALLOWANCE -> "CRYPTO_APPROVE_ALLOWANCE"; - case CRYPTO_DELETE_ALLOWANCE -> "CRYPTO_DELETE_ALLOWANCE"; - case GET_ACCOUNT_DETAILS -> "GET_ACCOUNT_DETAILS"; - case ETHEREUM_TRANSACTION -> "ETHEREUM_TRANSACTION"; - case NODE_STAKE_UPDATE -> "NODE_STAKE_UPDATE"; - case PRNG -> "PRNG"; - }; + switch (this) { + case NONE: + return "NONE"; + case CRYPTO_TRANSFER: + return "CRYPTO_TRANSFER"; + case CRYPTO_UPDATE: + return "CRYPTO_UPDATE"; + case CRYPTO_DELETE: + return "CRYPTO_DELETE"; + case CRYPTO_ADD_LIVE_HASH: + return "CRYPTO_ADD_LIVE_HASH"; + case CRYPTO_DELETE_LIVE_HASH: + return "CRYPTO_DELETE_LIVE_HASH"; + case CONTRACT_CALL: + return "CONTRACT_CALL"; + case CONTRACT_CREATE: + return "CONTRACT_CREATE"; + case CONTRACT_UPDATE: + return "CONTRACT_UPDATE"; + case FILE_CREATE: + return "FILE_CREATE"; + case FILE_APPEND: + return "FILE_APPEND"; + case FILE_UPDATE: + return "FILE_UPDATE"; + case FILE_DELETE: + return "FILE_DELETE"; + case CRYPTO_GET_ACCOUNT_BALANCE: + return "CRYPTO_GET_ACCOUNT_BALANCE"; + case CRYPTO_GET_ACCOUNT_RECORDS: + return "CRYPTO_GET_ACCOUNT_RECORDS"; + case CRYPTO_GET_INFO: + return "CRYPTO_GET_INFO"; + case CONTRACT_CALL_LOCAL: + return "CONTRACT_CALL_LOCAL"; + case CONTRACT_GET_INFO: + return "CONTRACT_GET_INFO"; + case CONTRACT_GET_BYTECODE: + return "CONTRACT_GET_BYTECODE"; + case GET_BY_SOLIDITY_ID: + return "GET_BY_SOLIDITY_ID"; + case GET_BY_KEY: + return "GET_BY_KEY"; + case CRYPTO_GET_LIVE_HASH: + return "CRYPTO_GET_LIVE_HASH"; + case CRYPTO_GET_STAKERS: + return "CRYPTO_GET_STAKERS"; + case FILE_GET_CONTENTS: + return "FILE_GET_CONTENTS"; + case FILE_GET_INFO: + return "FILE_GET_INFO"; + case TRANSACTION_GET_RECORD: + return "TRANSACTION_GET_RECORD"; + case CONTRACT_GET_RECORDS: + return "CONTRACT_GET_RECORDS"; + case CRYPTO_CREATE: + return "CRYPTO_CREATE"; + case SYSTEM_DELETE: + return "SYSTEM_DELETE"; + case SYSTEM_UNDELETE: + return "SYSTEM_UNDELETE"; + case CONTRACT_DELETE: + return "CONTRACT_DELETE"; + case FREEZE: + return "FREEZE"; + case CREATE_TRANSACTION_RECORD: + return "CREATE_TRANSACTION_RECORD"; + case CRYPTO_ACCOUNT_AUTO_RENEW: + return "CRYPTO_ACCOUNT_AUTO_RENEW"; + case CONTRACT_AUTO_RENEW: + return "CONTRACT_AUTO_RENEW"; + case GET_VERSION_INFO: + return "GET_VERSION_INFO"; + case TRANSACTION_GET_RECEIPT: + return "TRANSACTION_GET_RECEIPT"; + case CONSENSUS_CREATE_TOPIC: + return "CONSENSUS_CREATE_TOPIC"; + case CONSENSUS_UPDATE_TOPIC: + return "CONSENSUS_UPDATE_TOPIC"; + case CONSENSUS_DELETE_TOPIC: + return "CONSENSUS_DELETE_TOPIC"; + case CONSENSUS_GET_TOPIC_INFO: + return "CONSENSUS_GET_TOPIC_INFO"; + case CONSENSUS_SUBMIT_MESSAGE: + return "CONSENSUS_SUBMIT_MESSAGE"; + case UNCHECKED_SUBMIT: + return "UNCHECKED_SUBMIT"; + case TOKEN_CREATE: + return "TOKEN_CREATE"; + case TOKEN_GET_INFO: + return "TOKEN_GET_INFO"; + case TOKEN_FREEZE_ACCOUNT: + return "TOKEN_FREEZE_ACCOUNT"; + case TOKEN_UNFREEZE_ACCOUNT: + return "TOKEN_UNFREEZE_ACCOUNT"; + case TOKEN_GRANT_KYC_TO_ACCOUNT: + return "TOKEN_GRANT_KYC_TO_ACCOUNT"; + case TOKEN_REVOKE_KYC_FROM_ACCOUNT: + return "TOKEN_REVOKE_KYC_FROM_ACCOUNT"; + case TOKEN_DELETE: + return "TOKEN_DELETE"; + case TOKEN_UPDATE: + return "TOKEN_UPDATE"; + case TOKEN_MINT: + return "TOKEN_MINT"; + case TOKEN_BURN: + return "TOKEN_BURN"; + case TOKEN_ACCOUNT_WIPE: + return "TOKEN_ACCOUNT_WIPE"; + case TOKEN_ASSOCIATE_TO_ACCOUNT: + return "TOKEN_ASSOCIATE_TO_ACCOUNT"; + case TOKEN_DISSOCIATE_FROM_ACCOUNT: + return "TOKEN_DISSOCIATE_FROM_ACCOUNT"; + case SCHEDULE_CREATE: + return "SCHEDULE_CREATE"; + case SCHEDULE_DELETE: + return "SCHEDULE_DELETE"; + case SCHEDULE_SIGN: + return "SCHEDULE_SIGN"; + case SCHEDULE_GET_INFO: + return "SCHEDULE_GET_INFO"; + case TOKEN_GET_ACCOUNT_NFT_INFOS: + return "TOKEN_GET_ACCOUNT_NFT_INFOS"; + case TOKEN_GET_NFT_INFO: + return "TOKEN_GET_NFT_INFO"; + case TOKEN_GET_NFT_INFOS: + return "TOKEN_GET_NFT_INFOS"; + case TOKEN_FEE_SCHEDULE_UPDATE: + return "TOKEN_FEE_SCHEDULE_UPDATE"; + case NETWORK_GET_EXECUTION_TIME: + return "NETWORK_GET_EXECUTION_TIME"; + case TOKEN_PAUSE: + return "TOKEN_PAUSE"; + case TOKEN_UNPAUSE: + return "TOKEN_UNPAUSE"; + case CRYPTO_APPROVE_ALLOWANCE: + return "CRYPTO_APPROVE_ALLOWANCE"; + case CRYPTO_DELETE_ALLOWANCE: + return "CRYPTO_DELETE_ALLOWANCE"; + case GET_ACCOUNT_DETAILS: + return "GET_ACCOUNT_DETAILS"; + case ETHEREUM_TRANSACTION: + return "ETHEREUM_TRANSACTION"; + case NODE_STAKE_UPDATE: + return "NODE_STAKE_UPDATE"; + case PRNG: + return "PRNG"; + default: + return ""; + } } } diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/Status.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/Status.java index be4ef2f6e..1b8eef303 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/Status.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/Status.java @@ -618,7 +618,7 @@ public enum Status { INVALID_TOPIC_ID(ResponseCodeEnum.INVALID_TOPIC_ID), /** - * A provided admin key was invalid. + * A provided admin key was invalid. Verify the bytes for an Ed25519 public key are exactly 32 bytes; and the bytes for a compressed ECDSA(secp256k1) key are exactly 33 bytes, with the first byte either 0x02 or 0x03.. */ INVALID_ADMIN_KEY(ResponseCodeEnum.INVALID_ADMIN_KEY), @@ -1508,7 +1508,18 @@ public enum Status { * The combined balances of a contract and its auto-renew account (if any) or balance of an account did not cover * the auto-renewal fees in a transaction. */ - INSUFFICIENT_BALANCES_FOR_RENEWAL_FEES(ResponseCodeEnum.INSUFFICIENT_BALANCES_FOR_RENEWAL_FEES); + INSUFFICIENT_BALANCES_FOR_RENEWAL_FEES(ResponseCodeEnum.INSUFFICIENT_BALANCES_FOR_RENEWAL_FEES), + + /** + * A transaction's protobuf message includes unknown fields; could mean that a client + * expects not-yet-released functionality to be available. + */ + TRANSACTION_HAS_UNKNOWN_FIELDS(ResponseCodeEnum.TRANSACTION_HAS_UNKNOWN_FIELDS), + + /** + * The account cannot be modified. Account's key is not set + */ + ACCOUNT_IS_IMMUTABLE(ResponseCodeEnum.ACCOUNT_IS_IMMUTABLE); final ResponseCodeEnum code; @@ -2094,6 +2105,10 @@ static Status valueOf(ResponseCodeEnum code) { return MAX_CHILD_RECORDS_EXCEEDED; case INSUFFICIENT_BALANCES_FOR_RENEWAL_FEES: return INSUFFICIENT_BALANCES_FOR_RENEWAL_FEES; + case TRANSACTION_HAS_UNKNOWN_FIELDS: + return TRANSACTION_HAS_UNKNOWN_FIELDS; + case ACCOUNT_IS_IMMUTABLE: + return ACCOUNT_IS_IMMUTABLE; case UNRECOGNIZED: // NOTE: Protobuf deserialization will not give us the code on the wire throw new IllegalArgumentException( diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/TransactionRecord.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/TransactionRecord.java index 2ae150478..dfd1af486 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/TransactionRecord.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/TransactionRecord.java @@ -182,6 +182,12 @@ public final class TransactionRecord { @Nullable public final Integer prngNumber; + /** + * The new default EVM address of the account created by this transaction. + * This field is populated only when the EVM address is not specified in the related transaction body. + */ + public final ByteString evmAddress; + TransactionRecord( TransactionReceipt transactionReceipt, ByteString transactionHash, @@ -204,7 +210,8 @@ public final class TransactionRecord { ByteString ethereumHash, List paidStakingRewards, @Nullable ByteString prngBytes, - @Nullable Integer prngNumber + @Nullable Integer prngNumber, + ByteString evmAddress ) { this.receipt = transactionReceipt; this.transactionHash = transactionHash; @@ -231,6 +238,7 @@ public final class TransactionRecord { this.paidStakingRewards = paidStakingRewards; this.prngBytes = prngBytes; this.prngNumber = prngNumber; + this.evmAddress = evmAddress; } /** @@ -317,7 +325,8 @@ static TransactionRecord fromProtobuf( transactionRecord.getEthereumHash(), paidStakingRewards, transactionRecord.hasPrngBytes() ? transactionRecord.getPrngBytes() : null, - transactionRecord.hasPrngNumber() ? transactionRecord.getPrngNumber() : null + transactionRecord.hasPrngNumber() ? transactionRecord.getPrngNumber() : null, + transactionRecord.getEvmAddress() ); } @@ -373,7 +382,8 @@ com.hedera.hashgraph.sdk.proto.TransactionRecord toProtobuf() { .setMemo(transactionMemo) .setTransactionFee(transactionFee.toTinybars()) .setTransferList(transferList) - .setEthereumHash(ethereumHash); + .setEthereumHash(ethereumHash) + .setEvmAddress(evmAddress); for (var tokenEntry : tokenTransfers.entrySet()) { var tokenTransfersList = TokenTransferList.newBuilder() @@ -468,6 +478,7 @@ public String toString() { .add("paidStakingRewards", paidStakingRewards) .add("prngBytes", prngBytes != null ? Hex.toHexString(prngBytes.toByteArray()) : null) .add("prngNumber", prngNumber) + .add("evmAddress", Hex.toHexString(evmAddress.toByteArray())) .toString(); } diff --git a/sdk/src/main/proto/basic_types.proto b/sdk/src/main/proto/basic_types.proto index 7fe1a4317..094edc6bb 100644 --- a/sdk/src/main/proto/basic_types.proto +++ b/sdk/src/main/proto/basic_types.proto @@ -26,6 +26,7 @@ import "timestamp.proto"; import "google/protobuf/wrappers.proto"; option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; /** @@ -80,7 +81,7 @@ message AccountID { int64 realmNum = 2; /** - * The account number unique within its realm which can be either a non-negative integer or an alias public key. + * The account number unique within its realm which can be a non-negative integer, an alias public key or an EVM address. * For any AccountID fields in the query response, transaction record or transaction receipt only accountNum will * be populated. */ @@ -95,21 +96,23 @@ message AccountID { * a protobuf Key message for any primitive key type. Currently only primitive key bytes are supported as an alias * (ThresholdKey, KeyList, ContractID, and delegatable_contract_id are not supported) * - * May also be the ethereum account 20-byte EVM address to be used initially in place of the public key bytes. This EVM - * address may be either the encoded form of the shard.realm.num or the keccak-256 hash of a ECDSA_SECP256K1 primitive key. - * * At most one account can ever have a given alias and it is used for account creation if it * was automatically created using a crypto transfer. It will be null if an account is created normally. * It is immutable once it is set for an account. * * If a transaction auto-creates the account, any further transfers to that alias will simply be deposited * in that account, without creating anything, and with no creation fee being charged. - * - * If a transaction lazily-creates this account, a subsequent transaction will be required containing the public key bytes - * that map to the EVM address bytes. The provided public key bytes will then serve as the final alias bytes. */ bytes alias = 4; + /** + * The ethereum account 20-byte EVM address to be used initially in place of the public key bytes. This EVM + * address may be either the encoded form of the shard.realm.num or the keccak-256 hash of a ECDSA_SECP256K1 primitive key. + * + * If a transaction lazily-creates this account, a subsequent transaction will be required containing the public key bytes + * that map to the EVM address bytes. Lazy account creates will only support the keccak-256 hash of a ECDSA_SECP256K1 primitive key form. + */ + bytes evm_address = 5; } } @@ -1592,3 +1595,15 @@ message StakingInfo { int64 staked_node_id = 6; } } + +message VirtualAddress { + /** + * The 20-byte EVM address that is derived from the keccak-256 hash of a ECDSA_SECP256K1 primitive key. + */ + bytes address = 1; + + /** + * Flag if this address should now be set or is the default address on the account. + */ + bool is_default = 2; +} diff --git a/sdk/src/main/proto/consensus_create_topic.proto b/sdk/src/main/proto/consensus_create_topic.proto index a2a2b6643..cd2e46877 100644 --- a/sdk/src/main/proto/consensus_create_topic.proto +++ b/sdk/src/main/proto/consensus_create_topic.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/consensus_delete_topic.proto b/sdk/src/main/proto/consensus_delete_topic.proto index b7795e240..6b68113fd 100644 --- a/sdk/src/main/proto/consensus_delete_topic.proto +++ b/sdk/src/main/proto/consensus_delete_topic.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/consensus_get_topic_info.proto b/sdk/src/main/proto/consensus_get_topic_info.proto index 35d62600b..408641f19 100644 --- a/sdk/src/main/proto/consensus_get_topic_info.proto +++ b/sdk/src/main/proto/consensus_get_topic_info.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/consensus_service.proto b/sdk/src/main/proto/consensus_service.proto index 5271b566b..da1bfbf9c 100644 --- a/sdk/src/main/proto/consensus_service.proto +++ b/sdk/src/main/proto/consensus_service.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package import "query.proto"; import "response.proto"; diff --git a/sdk/src/main/proto/consensus_submit_message.proto b/sdk/src/main/proto/consensus_submit_message.proto index 33d680103..ece3155e9 100644 --- a/sdk/src/main/proto/consensus_submit_message.proto +++ b/sdk/src/main/proto/consensus_submit_message.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/consensus_topic_info.proto b/sdk/src/main/proto/consensus_topic_info.proto index 1636ffbd1..c31b2d625 100644 --- a/sdk/src/main/proto/consensus_topic_info.proto +++ b/sdk/src/main/proto/consensus_topic_info.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/consensus_update_topic.proto b/sdk/src/main/proto/consensus_update_topic.proto index ffaf92160..7a1acf9c4 100644 --- a/sdk/src/main/proto/consensus_update_topic.proto +++ b/sdk/src/main/proto/consensus_update_topic.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "google/protobuf/wrappers.proto"; diff --git a/sdk/src/main/proto/contract_call.proto b/sdk/src/main/proto/contract_call.proto index ef170a34a..e8f480897 100644 --- a/sdk/src/main/proto/contract_call.proto +++ b/sdk/src/main/proto/contract_call.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/contract_call_local.proto b/sdk/src/main/proto/contract_call_local.proto index af50b5e56..8d4520936 100644 --- a/sdk/src/main/proto/contract_call_local.proto +++ b/sdk/src/main/proto/contract_call_local.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/contract_create.proto b/sdk/src/main/proto/contract_create.proto index ff3a4e0b7..cfda42511 100644 --- a/sdk/src/main/proto/contract_create.proto +++ b/sdk/src/main/proto/contract_create.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/contract_delete.proto b/sdk/src/main/proto/contract_delete.proto index 61a3b30a2..2260a55eb 100644 --- a/sdk/src/main/proto/contract_delete.proto +++ b/sdk/src/main/proto/contract_delete.proto @@ -22,6 +22,7 @@ package proto; * ‍ */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/contract_get_bytecode.proto b/sdk/src/main/proto/contract_get_bytecode.proto index 5c124c879..ba6224ecc 100644 --- a/sdk/src/main/proto/contract_get_bytecode.proto +++ b/sdk/src/main/proto/contract_get_bytecode.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/contract_get_info.proto b/sdk/src/main/proto/contract_get_info.proto index af66c9b1e..d9c16b405 100644 --- a/sdk/src/main/proto/contract_get_info.proto +++ b/sdk/src/main/proto/contract_get_info.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "timestamp.proto"; diff --git a/sdk/src/main/proto/contract_get_records.proto b/sdk/src/main/proto/contract_get_records.proto index 3c3743e24..b4d68fab9 100644 --- a/sdk/src/main/proto/contract_get_records.proto +++ b/sdk/src/main/proto/contract_get_records.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/contract_update.proto b/sdk/src/main/proto/contract_update.proto index 7ddc52e5c..da789d1ae 100644 --- a/sdk/src/main/proto/contract_update.proto +++ b/sdk/src/main/proto/contract_update.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; @@ -72,8 +73,7 @@ message ContractUpdateTransactionBody { AccountID proxyAccountID = 6 [deprecated = true]; /** - * (NOT YET IMPLEMENTED) The new interval at which the contract will pay to extend its expiry - * (by the same interval) + * If an auto-renew account is in use, the lifetime to be added by each auto-renewal. */ Duration autoRenewPeriod = 7; diff --git a/sdk/src/main/proto/crypto_add_live_hash.proto b/sdk/src/main/proto/crypto_add_live_hash.proto index dc3d17309..826dd3d16 100644 --- a/sdk/src/main/proto/crypto_add_live_hash.proto +++ b/sdk/src/main/proto/crypto_add_live_hash.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; diff --git a/sdk/src/main/proto/crypto_approve_allowance.proto b/sdk/src/main/proto/crypto_approve_allowance.proto index 5ec1acd0e..417778817 100644 --- a/sdk/src/main/proto/crypto_approve_allowance.proto +++ b/sdk/src/main/proto/crypto_approve_allowance.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/crypto_create.proto b/sdk/src/main/proto/crypto_create.proto index ffd3e4875..88f4f2eaf 100644 --- a/sdk/src/main/proto/crypto_create.proto +++ b/sdk/src/main/proto/crypto_create.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; @@ -45,7 +46,8 @@ import "duration.proto"; * used to extend its expiration as long as possible. If it is has a zero balance when it expires, * then it is deleted. This transaction must be signed by the payer account. If receiverSigRequired * is false, then the transaction does not have to be signed by the keys in the keys field. If it is - * true, then it must be signed by them, in addition to the keys of the payer account. + * true, then it must be signed by them, in addition to the keys of the payer account. If the + * auto_renew_account field is set, the key of the referenced account must sign. * * An entity (account, file, or smart contract instance) must be created in a particular realm. If * the realmID is left null, then a new realm will be created with the given admin key. If a new @@ -153,10 +155,8 @@ message CryptoCreateTransactionBody { bool decline_reward = 17; /** - * The bytes to be used as the account's alias. The bytes will be 1 of 2 options. It will be the - * serialization of a protobuf Key message for an ED25519/ECDSA_SECP256K1 primitive key type. If the - * account is ECDSA_SECP256K1 based it may also be the public address, calcluated as the last 20 bytes of - * the keccak-256 hash of the ECDSA_SECP256K1 primitive key. Currently only primitive key bytes are + * The bytes to be used as the account's alias. It will be the + * serialization of a protobuf Key message for an ED25519/ECDSA_SECP256K1 primitive key type. Currently only primitive key bytes are * supported as the key for an account with an alias. ThresholdKey, KeyList, ContractID, and * delegatable_contract_id are not supported. * @@ -167,4 +167,16 @@ message CryptoCreateTransactionBody { * simply be deposited in that account, without creating anything, and with no creation fee being charged. */ bytes alias = 18; + + /** + * An account to charge for auto-renewal of this account . If not set, or set to an + * account with zero hbar balance, the account's own hbar balance will be used to + * cover auto-renewal fees. + */ + AccountID auto_renew_account = 19; + + /** + * EOA 20-byte address to create that is derived from the keccak-256 hash of a ECDSA_SECP256K1 primitive key. + */ + bytes evm_address = 20; } diff --git a/sdk/src/main/proto/crypto_delete.proto b/sdk/src/main/proto/crypto_delete.proto index fd7eae335..30719afe4 100644 --- a/sdk/src/main/proto/crypto_delete.proto +++ b/sdk/src/main/proto/crypto_delete.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/crypto_delete_allowance.proto b/sdk/src/main/proto/crypto_delete_allowance.proto index c7e544ad5..475df5f86 100644 --- a/sdk/src/main/proto/crypto_delete_allowance.proto +++ b/sdk/src/main/proto/crypto_delete_allowance.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/crypto_delete_live_hash.proto b/sdk/src/main/proto/crypto_delete_live_hash.proto index f75b32f28..41ba5dfbc 100644 --- a/sdk/src/main/proto/crypto_delete_live_hash.proto +++ b/sdk/src/main/proto/crypto_delete_live_hash.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/crypto_get_account_balance.proto b/sdk/src/main/proto/crypto_get_account_balance.proto index b522f704f..0147cadca 100644 --- a/sdk/src/main/proto/crypto_get_account_balance.proto +++ b/sdk/src/main/proto/crypto_get_account_balance.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/crypto_get_account_records.proto b/sdk/src/main/proto/crypto_get_account_records.proto index 9cb0d9a29..183297249 100644 --- a/sdk/src/main/proto/crypto_get_account_records.proto +++ b/sdk/src/main/proto/crypto_get_account_records.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/crypto_get_info.proto b/sdk/src/main/proto/crypto_get_info.proto index 869bc57c8..1eff7aa4f 100644 --- a/sdk/src/main/proto/crypto_get_info.proto +++ b/sdk/src/main/proto/crypto_get_info.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "timestamp.proto"; @@ -180,6 +181,19 @@ message CryptoGetInfoResponse { * Staking metadata for this account. */ StakingInfo staking_info = 22; + + + /** + * If present, the account that will be charged for auto-renewal of this account. If not set, + * or set to an account with zero hbar balance, the account's own hbar balance will be used to + * cover auto-renewal fees. + */ + AccountID auto_renew_account = 23; + + /** + * List of virtual addresses each of which is an EVM address that maps to an ECDSA key pair a user must prove ownership of. + */ + repeated VirtualAddress virtual_addresses = 24; } /** diff --git a/sdk/src/main/proto/crypto_get_live_hash.proto b/sdk/src/main/proto/crypto_get_live_hash.proto index 952d7dd48..1bf80ef32 100644 --- a/sdk/src/main/proto/crypto_get_live_hash.proto +++ b/sdk/src/main/proto/crypto_get_live_hash.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/crypto_get_stakers.proto b/sdk/src/main/proto/crypto_get_stakers.proto index 2fc9bdcf5..44f52eb5a 100644 --- a/sdk/src/main/proto/crypto_get_stakers.proto +++ b/sdk/src/main/proto/crypto_get_stakers.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/crypto_service.proto b/sdk/src/main/proto/crypto_service.proto index 861d8db95..226943555 100644 --- a/sdk/src/main/proto/crypto_service.proto +++ b/sdk/src/main/proto/crypto_service.proto @@ -22,6 +22,7 @@ package proto; * ‍ */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package import "query.proto"; import "response.proto"; diff --git a/sdk/src/main/proto/crypto_transfer.proto b/sdk/src/main/proto/crypto_transfer.proto index c1385d355..5c25747e3 100644 --- a/sdk/src/main/proto/crypto_transfer.proto +++ b/sdk/src/main/proto/crypto_transfer.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/crypto_update.proto b/sdk/src/main/proto/crypto_update.proto index 8c1d079a8..77f6741d6 100644 --- a/sdk/src/main/proto/crypto_update.proto +++ b/sdk/src/main/proto/crypto_update.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; @@ -36,6 +37,8 @@ import "google/protobuf/wrappers.proto"; * the key field, then the transaction must be signed by both the old key (from before the change) * and the new key. The old key must sign for security. The new key must sign as a safeguard to * avoid accidentally changing to an invalid key, and then having no way to recover. + * If the update transaction sets the auto_renew_account field to anything other + * than the sentinel 0.0.0, the key of the referenced account must sign. */ message CryptoUpdateTransactionBody { /** @@ -152,4 +155,22 @@ message CryptoUpdateTransactionBody { * If true, the account declines receiving a staking reward. The default value is false. */ google.protobuf.BoolValue decline_reward = 18; + + /** + * If set to the sentinel 0.0.0 AccountID, this field removes the account's auto-renew + * account. Otherwise it updates the account's auto-renew account to the referenced account. + */ + AccountID auto_renew_account = 19; + + oneof virtual_address_update { + /** + * The virtual address to be added. + */ + VirtualAddress add = 20; + + /** + * The 20-byte EVM address of the virtual address that is being removed. + */ + bytes remove = 21; + } } diff --git a/sdk/src/main/proto/custom_fees.proto b/sdk/src/main/proto/custom_fees.proto index cbb674160..bda20b468 100644 --- a/sdk/src/main/proto/custom_fees.proto +++ b/sdk/src/main/proto/custom_fees.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; @@ -79,6 +80,24 @@ message FixedFee { * value" includes both ℏ and units of fungible HTS tokens.) When the NFT sender does not receive * any fungible value, the ledger will assess the fallback fee, if present, to the new NFT owner. * Royalty fees can only be added to tokens of type type NON_FUNGIBLE_UNIQUE. + * + * **IMPORTANT:** Users must understand that native royalty fees are _strictly_ a convenience feature, + * and that the network cannot enforce inescapable royalties on the exchange of a non-fractional NFT. + * For example, if the counterparties agree to split their value transfer and NFT exchange into separate + * transactions, the network cannot possibly intervene. (And note the counterparties could use a smart + * contract to make this split transaction atomic if they do not trust each other.) + * + * Counterparties that _do_ wish to respect creator royalties should follow the pattern the network + * recognizes: The NFT sender and receiver should both sign a single `CryptoTransfer` that credits + * the sender with all the fungible value the receiver is exchanging for the NFT. + * + * Similarly, a marketplace using an approved spender account for an escrow transaction should credit + * the account selling the NFT in the same `CryptoTransfer` that deducts fungible value from the buying + * account. + * + * There is an [open HIP discussion](https://github.com/hashgraph/hedera-improvement-proposal/discussions/578) + * that proposes to broaden the class of transactions for which the network automatically collects + * royalties. If this interests or concerns you, please add your voice to that discussion. */ message RoyaltyFee { /** diff --git a/sdk/src/main/proto/duration.proto b/sdk/src/main/proto/duration.proto index 85c8c61a4..0883f7d59 100644 --- a/sdk/src/main/proto/duration.proto +++ b/sdk/src/main/proto/duration.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; /** diff --git a/sdk/src/main/proto/ethereum_transaction.proto b/sdk/src/main/proto/ethereum_transaction.proto index 3eab6c931..dad33e10b 100644 --- a/sdk/src/main/proto/ethereum_transaction.proto +++ b/sdk/src/main/proto/ethereum_transaction.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/exchange_rate.proto b/sdk/src/main/proto/exchange_rate.proto index 73302d46f..0a0c3f7b8 100644 --- a/sdk/src/main/proto/exchange_rate.proto +++ b/sdk/src/main/proto/exchange_rate.proto @@ -22,6 +22,7 @@ package proto; * ‍ */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "timestamp.proto"; diff --git a/sdk/src/main/proto/file_append.proto b/sdk/src/main/proto/file_append.proto index 7f957ad9d..c70cd18f4 100644 --- a/sdk/src/main/proto/file_append.proto +++ b/sdk/src/main/proto/file_append.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; diff --git a/sdk/src/main/proto/file_create.proto b/sdk/src/main/proto/file_create.proto index a3ecd65a1..9caaa812b 100644 --- a/sdk/src/main/proto/file_create.proto +++ b/sdk/src/main/proto/file_create.proto @@ -23,10 +23,12 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; import "timestamp.proto"; +import "duration.proto"; /** * Create a new file, containing the given contents. @@ -44,7 +46,8 @@ import "timestamp.proto"; * (including other threshold keys). In other words, the behavior is an AND for create/modify, OR * for delete. This is useful for acting as a revocation server. If it is desired to have the * behavior be AND for all 3 operations (or OR for all 3), then the list should have only a single - * Key, which is a threshold key, with N=1 for OR, N=M for AND. + * Key, which is a threshold key, with N=1 for OR, N=M for AND. If the auto_renew_account field + * is set, the key of the referenced account must sign. * * If a file is created without ANY keys in the keys field, the file is immutable and ONLY the * expirationTime of the file can be changed with a FileUpdate transaction. The file contents or its @@ -99,4 +102,21 @@ message FileCreateTransactionBody { * The memo associated with the file (UTF-8 encoding max 100 bytes) */ string memo = 8; + + /** + * An account to charge for auto-renewal of this file. If not set, or set to an + * account with zero hbar balance, the file's expiration must be manually extended + * using a FileUpdate transaction, since the network will not have authorization + * for any kind of auto-renewal fee collection. + */ + AccountID auto_renew_account = 9; + + /** + * If an auto-renew account is in use, the lifetime to be added by each + * auto-renewal. When both auto-renew account and auto-renew period are + * set in the create transaction, the initial expiry of the file will be + * the valid start of the create transaction plus the auto-renew period. + * (I.e., the expirationTime field will be ignored.) + */ + Duration auto_renew_period = 10; } diff --git a/sdk/src/main/proto/file_delete.proto b/sdk/src/main/proto/file_delete.proto index 1784e530f..f4b23c988 100644 --- a/sdk/src/main/proto/file_delete.proto +++ b/sdk/src/main/proto/file_delete.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/file_get_contents.proto b/sdk/src/main/proto/file_get_contents.proto index f7dc70df7..ee888d6af 100644 --- a/sdk/src/main/proto/file_get_contents.proto +++ b/sdk/src/main/proto/file_get_contents.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/file_get_info.proto b/sdk/src/main/proto/file_get_info.proto index ae4356eb4..54eb0a41f 100644 --- a/sdk/src/main/proto/file_get_info.proto +++ b/sdk/src/main/proto/file_get_info.proto @@ -23,12 +23,14 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "timestamp.proto"; import "basic_types.proto"; import "query_header.proto"; import "response_header.proto"; +import "duration.proto"; /** * Get all of the information about a file, except for its contents. When a file expires, it no @@ -96,6 +98,16 @@ message FileGetInfoResponse { * The ledger ID the response was returned from; please see HIP-198 for the network-specific IDs. */ bytes ledger_id = 7; + + /** + * If set, the account that is used to pay for auto-renewal of the file. + */ + AccountID auto_renew_account = 8; + + /** + * If an auto-renew account is in use, the added lifetime (in seconds) of each auto-renewal. + */ + Duration auto_renew_period = 9; } /** diff --git a/sdk/src/main/proto/file_service.proto b/sdk/src/main/proto/file_service.proto index e53b097aa..04087353f 100644 --- a/sdk/src/main/proto/file_service.proto +++ b/sdk/src/main/proto/file_service.proto @@ -22,6 +22,7 @@ package proto; * ‍ */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package import "query.proto"; import "response.proto"; diff --git a/sdk/src/main/proto/file_update.proto b/sdk/src/main/proto/file_update.proto index e04b02abf..71277b282 100644 --- a/sdk/src/main/proto/file_update.proto +++ b/sdk/src/main/proto/file_update.proto @@ -23,9 +23,11 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; +import "duration.proto"; import "timestamp.proto"; import "google/protobuf/wrappers.proto"; @@ -35,7 +37,8 @@ import "google/protobuf/wrappers.proto"; * in the top level of a key list (M-of-M) of the file being updated. If the keys themselves are * being updated, then the transaction must also be signed by all the new keys. If the keys contain * additional KeyList or ThresholdKey then M-of-M secondary KeyList or ThresholdKey signing - * requirements must be meet + * requirements must be meet If the update transaction sets the auto_renew_account_id field + * to anything other than the sentinel 0.0.0, the key of the referenced account must sign. */ message FileUpdateTransactionBody { /** @@ -62,4 +65,15 @@ message FileUpdateTransactionBody { * If set, the new memo to be associated with the file (UTF-8 encoding max 100 bytes) */ google.protobuf.StringValue memo = 5; + + /** + * If set to the sentinel 0.0.0 AccountID, this field removes the file's auto-renew + * account. Otherwise it updates the file's auto-renew account to the referenced account. + */ + AccountID auto_renew_account = 6; + + /** + * If an auto-renew account is in use, the lifetime to be added by each auto-renewal. + */ + Duration auto_renew_period = 7; } diff --git a/sdk/src/main/proto/freeze.proto b/sdk/src/main/proto/freeze.proto index ba7945f15..31fcbe655 100644 --- a/sdk/src/main/proto/freeze.proto +++ b/sdk/src/main/proto/freeze.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "duration.proto"; diff --git a/sdk/src/main/proto/freeze_service.proto b/sdk/src/main/proto/freeze_service.proto index b1f9b3a8f..b43d1f8de 100644 --- a/sdk/src/main/proto/freeze_service.proto +++ b/sdk/src/main/proto/freeze_service.proto @@ -22,6 +22,7 @@ package proto; * ‍ */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package import "transaction_response.proto"; import "transaction.proto"; diff --git a/sdk/src/main/proto/freeze_type.proto b/sdk/src/main/proto/freeze_type.proto index f250efec6..7abcf47f6 100644 --- a/sdk/src/main/proto/freeze_type.proto +++ b/sdk/src/main/proto/freeze_type.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; /** diff --git a/sdk/src/main/proto/get_account_details.proto b/sdk/src/main/proto/get_account_details.proto index 1190a3645..98ebe7f27 100644 --- a/sdk/src/main/proto/get_account_details.proto +++ b/sdk/src/main/proto/get_account_details.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "timestamp.proto"; diff --git a/sdk/src/main/proto/get_by_key.proto b/sdk/src/main/proto/get_by_key.proto index 1be4e7e47..e166b3367 100644 --- a/sdk/src/main/proto/get_by_key.proto +++ b/sdk/src/main/proto/get_by_key.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/get_by_solidity_id.proto b/sdk/src/main/proto/get_by_solidity_id.proto index 788343794..1c9d111c3 100644 --- a/sdk/src/main/proto/get_by_solidity_id.proto +++ b/sdk/src/main/proto/get_by_solidity_id.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/network_get_execution_time.proto b/sdk/src/main/proto/network_get_execution_time.proto index 965b7b78c..0c282f1a7 100644 --- a/sdk/src/main/proto/network_get_execution_time.proto +++ b/sdk/src/main/proto/network_get_execution_time.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/network_get_version_info.proto b/sdk/src/main/proto/network_get_version_info.proto index 0a21f2d46..64978788d 100644 --- a/sdk/src/main/proto/network_get_version_info.proto +++ b/sdk/src/main/proto/network_get_version_info.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/network_service.proto b/sdk/src/main/proto/network_service.proto index da853a084..49f06e5d5 100644 --- a/sdk/src/main/proto/network_service.proto +++ b/sdk/src/main/proto/network_service.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package import "query.proto"; import "response.proto"; diff --git a/sdk/src/main/proto/node_stake_update.proto b/sdk/src/main/proto/node_stake_update.proto index 95e13e70f..76097a3f4 100644 --- a/sdk/src/main/proto/node_stake_update.proto +++ b/sdk/src/main/proto/node_stake_update.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/query.proto b/sdk/src/main/proto/query.proto index 20d531be5..7c2e2fa97 100644 --- a/sdk/src/main/proto/query.proto +++ b/sdk/src/main/proto/query.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "get_by_key.proto"; diff --git a/sdk/src/main/proto/query_header.proto b/sdk/src/main/proto/query_header.proto index 12e955c3f..c96aa250a 100644 --- a/sdk/src/main/proto/query_header.proto +++ b/sdk/src/main/proto/query_header.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "transaction.proto"; diff --git a/sdk/src/main/proto/response.proto b/sdk/src/main/proto/response.proto index b82a8a601..62daa7fb6 100644 --- a/sdk/src/main/proto/response.proto +++ b/sdk/src/main/proto/response.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "get_by_key.proto"; diff --git a/sdk/src/main/proto/response_code.proto b/sdk/src/main/proto/response_code.proto index 0c51f17eb..23128bd62 100644 --- a/sdk/src/main/proto/response_code.proto +++ b/sdk/src/main/proto/response_code.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; /** @@ -616,7 +617,7 @@ enum ResponseCodeEnum { INVALID_TOPIC_ID = 150; /** - * A provided admin key was invalid. + * A provided admin key was invalid. Verify the bytes for an Ed25519 public key are exactly 32 bytes; and the bytes for a compressed ECDSA(secp256k1) key are exactly 33 bytes, with the first byte either 0x02 or 0x03.. */ INVALID_ADMIN_KEY = 155; @@ -1356,4 +1357,15 @@ enum ResponseCodeEnum { * the auto-renewal fees in a transaction. */ INSUFFICIENT_BALANCES_FOR_RENEWAL_FEES = 329; + + /** + * A transaction's protobuf message includes unknown fields; could mean that a client + * expects not-yet-released functionality to be available. + */ + TRANSACTION_HAS_UNKNOWN_FIELDS = 330; + + /** + * The account cannot be modified. Account's key is not set + */ + ACCOUNT_IS_IMMUTABLE = 331; } diff --git a/sdk/src/main/proto/response_header.proto b/sdk/src/main/proto/response_header.proto index 91cf8d772..f70a96a1e 100644 --- a/sdk/src/main/proto/response_header.proto +++ b/sdk/src/main/proto/response_header.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "transaction_response.proto"; diff --git a/sdk/src/main/proto/schedulable_transaction_body.proto b/sdk/src/main/proto/schedulable_transaction_body.proto index 72f7b6c23..c6d83cee0 100644 --- a/sdk/src/main/proto/schedulable_transaction_body.proto +++ b/sdk/src/main/proto/schedulable_transaction_body.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "system_delete.proto"; diff --git a/sdk/src/main/proto/schedule_create.proto b/sdk/src/main/proto/schedule_create.proto index a40ba965e..108541cd2 100644 --- a/sdk/src/main/proto/schedule_create.proto +++ b/sdk/src/main/proto/schedule_create.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/schedule_delete.proto b/sdk/src/main/proto/schedule_delete.proto index dd48e09ed..4f6de5647 100644 --- a/sdk/src/main/proto/schedule_delete.proto +++ b/sdk/src/main/proto/schedule_delete.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/schedule_get_info.proto b/sdk/src/main/proto/schedule_get_info.proto index ca3d504d2..e72376410 100644 --- a/sdk/src/main/proto/schedule_get_info.proto +++ b/sdk/src/main/proto/schedule_get_info.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/schedule_service.proto b/sdk/src/main/proto/schedule_service.proto index f5a28ce0a..2289f586d 100644 --- a/sdk/src/main/proto/schedule_service.proto +++ b/sdk/src/main/proto/schedule_service.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package import "query.proto"; import "response.proto"; diff --git a/sdk/src/main/proto/schedule_sign.proto b/sdk/src/main/proto/schedule_sign.proto index 3075a833f..784970377 100644 --- a/sdk/src/main/proto/schedule_sign.proto +++ b/sdk/src/main/proto/schedule_sign.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/smart_contract_service.proto b/sdk/src/main/proto/smart_contract_service.proto index 057322613..05fc6c9bc 100644 --- a/sdk/src/main/proto/smart_contract_service.proto +++ b/sdk/src/main/proto/smart_contract_service.proto @@ -22,6 +22,7 @@ package proto; * ‍ */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package import "transaction_response.proto"; import "query.proto"; diff --git a/sdk/src/main/proto/system_delete.proto b/sdk/src/main/proto/system_delete.proto index 776d4f849..a49b9ec81 100644 --- a/sdk/src/main/proto/system_delete.proto +++ b/sdk/src/main/proto/system_delete.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/system_undelete.proto b/sdk/src/main/proto/system_undelete.proto index 6abc09d9d..4eab2349a 100644 --- a/sdk/src/main/proto/system_undelete.proto +++ b/sdk/src/main/proto/system_undelete.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/throttle_definitions.proto b/sdk/src/main/proto/throttle_definitions.proto index f27b1c72c..4be3aef64 100644 --- a/sdk/src/main/proto/throttle_definitions.proto +++ b/sdk/src/main/proto/throttle_definitions.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/timestamp.proto b/sdk/src/main/proto/timestamp.proto index a4db87032..0ca2798a7 100644 --- a/sdk/src/main/proto/timestamp.proto +++ b/sdk/src/main/proto/timestamp.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; /** diff --git a/sdk/src/main/proto/token_associate.proto b/sdk/src/main/proto/token_associate.proto index 22ff74906..b1438b01a 100644 --- a/sdk/src/main/proto/token_associate.proto +++ b/sdk/src/main/proto/token_associate.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/token_burn.proto b/sdk/src/main/proto/token_burn.proto index 03b1c8208..fba56c492 100644 --- a/sdk/src/main/proto/token_burn.proto +++ b/sdk/src/main/proto/token_burn.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; @@ -36,8 +37,9 @@ import "basic_types.proto"; * to burn 100.55 tokens, one must provide amount of 10055. * For non fungible tokens the transaction body accepts serialNumbers list of integers as a parameter. * - * If neither the amount nor the serialNumbers get filled, a INVALID_TOKEN_BURN_AMOUNT response code - * will be returned. + * If the serialNumbers don't get filled for non-fungible token type, a INVALID_TOKEN_BURN_AMOUNT response + * code will be returned. + * If a zero amount is provided for a fungible token type, it will be treated as a regular transaction. * If both amount and serialNumbers get filled, a INVALID_TRANSACTION_BODY response code will be * returned. * If the serialNumbers' list count is greater than the batch size limit global dynamic property, a diff --git a/sdk/src/main/proto/token_create.proto b/sdk/src/main/proto/token_create.proto index e67e5c919..1d0aa598b 100644 --- a/sdk/src/main/proto/token_create.proto +++ b/sdk/src/main/proto/token_create.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "duration.proto"; diff --git a/sdk/src/main/proto/token_delete.proto b/sdk/src/main/proto/token_delete.proto index d1b251686..2f6f443f3 100644 --- a/sdk/src/main/proto/token_delete.proto +++ b/sdk/src/main/proto/token_delete.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/token_dissociate.proto b/sdk/src/main/proto/token_dissociate.proto index 1feadc9d7..d51043091 100644 --- a/sdk/src/main/proto/token_dissociate.proto +++ b/sdk/src/main/proto/token_dissociate.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/token_fee_schedule_update.proto b/sdk/src/main/proto/token_fee_schedule_update.proto index ecd715ea2..64ed13739 100644 --- a/sdk/src/main/proto/token_fee_schedule_update.proto +++ b/sdk/src/main/proto/token_fee_schedule_update.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/token_freeze_account.proto b/sdk/src/main/proto/token_freeze_account.proto index b2f383812..b25d64230 100644 --- a/sdk/src/main/proto/token_freeze_account.proto +++ b/sdk/src/main/proto/token_freeze_account.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/token_get_account_nft_infos.proto b/sdk/src/main/proto/token_get_account_nft_infos.proto index ec067cb34..3a22091bc 100644 --- a/sdk/src/main/proto/token_get_account_nft_infos.proto +++ b/sdk/src/main/proto/token_get_account_nft_infos.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/token_get_info.proto b/sdk/src/main/proto/token_get_info.proto index a72c27f9e..88897b3ab 100644 --- a/sdk/src/main/proto/token_get_info.proto +++ b/sdk/src/main/proto/token_get_info.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/token_get_nft_info.proto b/sdk/src/main/proto/token_get_nft_info.proto index 3c7e629a3..e88aeb432 100644 --- a/sdk/src/main/proto/token_get_nft_info.proto +++ b/sdk/src/main/proto/token_get_nft_info.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/token_get_nft_infos.proto b/sdk/src/main/proto/token_get_nft_infos.proto index 6e8ae03f9..7c782abcd 100644 --- a/sdk/src/main/proto/token_get_nft_infos.proto +++ b/sdk/src/main/proto/token_get_nft_infos.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/token_grant_kyc.proto b/sdk/src/main/proto/token_grant_kyc.proto index 67c50ea1e..a45d4d109 100644 --- a/sdk/src/main/proto/token_grant_kyc.proto +++ b/sdk/src/main/proto/token_grant_kyc.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/token_mint.proto b/sdk/src/main/proto/token_mint.proto index 82e0104cd..bd2c499e7 100644 --- a/sdk/src/main/proto/token_mint.proto +++ b/sdk/src/main/proto/token_mint.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; @@ -39,8 +40,9 @@ import "basic_types.proto"; * returned. * If the metadata list contains metadata which is too large, a METADATA_TOO_LONG response code will * be returned. - * If neither the amount nor the metadata list get filled, a INVALID_TOKEN_MINT_AMOUNT response code - * will be returned. + * If the metadata list is not filled for a non-fungible token type, a INVALID_TOKEN_MINT_AMOUNT response + * code will be returned. + * If a zero amount is provided for a fungible token type, it will be treated as a regular transaction. * If the metadata list count is greater than the batch size limit global dynamic property, a * BATCH_SIZE_LIMIT_EXCEEDED response code will be returned. */ diff --git a/sdk/src/main/proto/token_pause.proto b/sdk/src/main/proto/token_pause.proto index e9487a68d..261b913b6 100644 --- a/sdk/src/main/proto/token_pause.proto +++ b/sdk/src/main/proto/token_pause.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/token_revoke_kyc.proto b/sdk/src/main/proto/token_revoke_kyc.proto index f061bb2b8..5cb3bd099 100644 --- a/sdk/src/main/proto/token_revoke_kyc.proto +++ b/sdk/src/main/proto/token_revoke_kyc.proto @@ -24,6 +24,7 @@ package proto; option java_package = "com.hedera.hashgraph.sdk.proto"; option java_multiple_files = true; +// <<>> This comment is special code for setting PBJ Compiler java package import "basic_types.proto"; diff --git a/sdk/src/main/proto/token_service.proto b/sdk/src/main/proto/token_service.proto index 0ee25d8d1..a7d8e597c 100644 --- a/sdk/src/main/proto/token_service.proto +++ b/sdk/src/main/proto/token_service.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package import "query.proto"; import "response.proto"; diff --git a/sdk/src/main/proto/token_unfreeze_account.proto b/sdk/src/main/proto/token_unfreeze_account.proto index d67aedfc5..d490d128f 100644 --- a/sdk/src/main/proto/token_unfreeze_account.proto +++ b/sdk/src/main/proto/token_unfreeze_account.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/token_unpause.proto b/sdk/src/main/proto/token_unpause.proto index 6ba2f9e81..e8107f82e 100644 --- a/sdk/src/main/proto/token_unpause.proto +++ b/sdk/src/main/proto/token_unpause.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/token_update.proto b/sdk/src/main/proto/token_update.proto index f6fb507be..085f3f5d1 100644 --- a/sdk/src/main/proto/token_update.proto +++ b/sdk/src/main/proto/token_update.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/token_wipe_account.proto b/sdk/src/main/proto/token_wipe_account.proto index 2fe07cf82..a46c1dab6 100644 --- a/sdk/src/main/proto/token_wipe_account.proto +++ b/sdk/src/main/proto/token_wipe_account.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; @@ -44,8 +45,9 @@ import "basic_types.proto"; * * If both amount and serialNumbers get filled, a INVALID_TRANSACTION_BODY response code will be * returned. - * If neither the amount nor the serialNumbers get filled, a INVALID_WIPING_AMOUNT response code - * will be returned. + * If the serialNumbers don't get filled for a non-fungible token type, a INVALID_WIPING_AMOUNT response + * code will be returned. + * If a zero amount is provided for a fungible token type, it will be treated as a regular transaction. * If the serialNumbers list contains a non-positive integer as a serial number, a INVALID_NFT_ID * response code will be returned. * If the serialNumbers' list count is greater than the batch size limit global dynamic property, a diff --git a/sdk/src/main/proto/transaction.proto b/sdk/src/main/proto/transaction.proto index c76535cb5..138e3bf4e 100644 --- a/sdk/src/main/proto/transaction.proto +++ b/sdk/src/main/proto/transaction.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; diff --git a/sdk/src/main/proto/transaction_body.proto b/sdk/src/main/proto/transaction_body.proto index 50490baff..4044395a3 100644 --- a/sdk/src/main/proto/transaction_body.proto +++ b/sdk/src/main/proto/transaction_body.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "system_delete.proto"; diff --git a/sdk/src/main/proto/transaction_contents.proto b/sdk/src/main/proto/transaction_contents.proto index 43fac7634..01f291221 100644 --- a/sdk/src/main/proto/transaction_contents.proto +++ b/sdk/src/main/proto/transaction_contents.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/transaction_get_fast_record.proto b/sdk/src/main/proto/transaction_get_fast_record.proto index 4f44d186b..49c0e49f8 100644 --- a/sdk/src/main/proto/transaction_get_fast_record.proto +++ b/sdk/src/main/proto/transaction_get_fast_record.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "transaction_record.proto"; diff --git a/sdk/src/main/proto/transaction_get_receipt.proto b/sdk/src/main/proto/transaction_get_receipt.proto index 277bb4cd3..a38c5b74e 100644 --- a/sdk/src/main/proto/transaction_get_receipt.proto +++ b/sdk/src/main/proto/transaction_get_receipt.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "transaction_receipt.proto"; diff --git a/sdk/src/main/proto/transaction_get_record.proto b/sdk/src/main/proto/transaction_get_record.proto index 9b234a245..8f17b9944 100644 --- a/sdk/src/main/proto/transaction_get_record.proto +++ b/sdk/src/main/proto/transaction_get_record.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "transaction_record.proto"; diff --git a/sdk/src/main/proto/transaction_receipt.proto b/sdk/src/main/proto/transaction_receipt.proto index 838d02ece..3bdb61daf 100644 --- a/sdk/src/main/proto/transaction_receipt.proto +++ b/sdk/src/main/proto/transaction_receipt.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "basic_types.proto"; diff --git a/sdk/src/main/proto/transaction_record.proto b/sdk/src/main/proto/transaction_record.proto index b23a7e537..df6f9cb4b 100644 --- a/sdk/src/main/proto/transaction_record.proto +++ b/sdk/src/main/proto/transaction_record.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "timestamp.proto"; @@ -145,4 +146,10 @@ message TransactionRecord { */ int32 prng_number = 20; } + + /** + * The new default EVM address of the account created by this transaction. + * This field is populated only when the EVM address is not specified in the related transaction body. + */ + bytes evm_address = 21; } diff --git a/sdk/src/main/proto/transaction_response.proto b/sdk/src/main/proto/transaction_response.proto index 337f95a22..94b98db13 100644 --- a/sdk/src/main/proto/transaction_response.proto +++ b/sdk/src/main/proto/transaction_response.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; import "response_code.proto"; diff --git a/sdk/src/main/proto/unchecked_submit.proto b/sdk/src/main/proto/unchecked_submit.proto index 8831e522b..86f3e192b 100644 --- a/sdk/src/main/proto/unchecked_submit.proto +++ b/sdk/src/main/proto/unchecked_submit.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; /** diff --git a/sdk/src/main/proto/util_prng.proto b/sdk/src/main/proto/util_prng.proto index 309bacec4..11ca5d01c 100644 --- a/sdk/src/main/proto/util_prng.proto +++ b/sdk/src/main/proto/util_prng.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package option java_multiple_files = true; /** diff --git a/sdk/src/main/proto/util_service.proto b/sdk/src/main/proto/util_service.proto index 1a6796afe..c920c2869 100644 --- a/sdk/src/main/proto/util_service.proto +++ b/sdk/src/main/proto/util_service.proto @@ -23,6 +23,7 @@ package proto; */ option java_package = "com.hedera.hashgraph.sdk.proto"; +// <<>> This comment is special code for setting PBJ Compiler java package import "transaction_response.proto"; import "transaction.proto"; diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountCreateTransactionTest.java b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountCreateTransactionTest.java index 9d89cadb4..df4b2415e 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountCreateTransactionTest.java +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountCreateTransactionTest.java @@ -75,7 +75,7 @@ AccountCreateTransaction spawnTestTransaction2() { .setReceiverSignatureRequired(true) .setAutoRenewPeriod(Duration.ofHours(10)) .setStakedNodeId(4L) - .setAliasEvmAddress(EvmAddress.fromString("302a300506032b6570032100114e6abc371b82da")) + .setEvmAddress(EvmAddress.fromString("302a300506032b6570032100114e6abc371b82da")) .setMaxAutomaticTokenAssociations(100) .setMaxTransactionFee(Hbar.fromTinybars(100_000)) .freeze() diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountCreateTransactionTest.snap b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountCreateTransactionTest.snap index 5ba48b532..74b2c853b 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountCreateTransactionTest.snap +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountCreateTransactionTest.snap @@ -1,8 +1,8 @@ com.hedera.hashgraph.sdk.AccountCreateTransactionTest.shouldSerialize2=[ - "# com.hedera.hashgraph.sdk.proto.TransactionBody\ncrypto_create_account {\n alias: \"0*0\\005\\006\\003+ep\\003!\\000\\021Nj\\2747\\033\\202\\332\"\n auto_renew_period {\n seconds: 36000\n }\n initial_balance: 450\n key {\n ed25519: \"\\340\\310\\354\\'X\\245\\207\\237\\372\\302&\\241<\\fQky\\236r\\343QA\\240\\335\\202\\217\\224\\323y\\210\\244\\267\"\n }\n max_automatic_token_associations: 100\n memo: \"some dumb memo\"\n proxy_account_i_d {\n account_num: 1001\n realm_num: 0\n shard_num: 0\n }\n receive_record_threshold: 0\n receiver_sig_required: true\n send_record_threshold: 0\n staked_node_id: 4\n}\nnode_account_i_d {\n account_num: 5005\n realm_num: 0\n shard_num: 0\n}\ntransaction_fee: 100000\ntransaction_i_d {\n account_i_d {\n account_num: 5006\n realm_num: 0\n shard_num: 0\n }\n transaction_valid_start {\n seconds: 1554158542\n }\n}\ntransaction_valid_duration {\n seconds: 120\n}" + "# com.hedera.hashgraph.sdk.proto.TransactionBody\ncrypto_create_account {\n auto_renew_period {\n seconds: 36000\n }\n evm_address: \"0*0\\005\\006\\003+ep\\003!\\000\\021Nj\\2747\\033\\202\\332\"\n initial_balance: 450\n key {\n ed25519: \"\\340\\310\\354\\'X\\245\\207\\237\\372\\302&\\241<\\fQky\\236r\\343QA\\240\\335\\202\\217\\224\\323y\\210\\244\\267\"\n }\n max_automatic_token_associations: 100\n memo: \"some dumb memo\"\n proxy_account_i_d {\n account_num: 1001\n realm_num: 0\n shard_num: 0\n }\n receive_record_threshold: 0\n receiver_sig_required: true\n send_record_threshold: 0\n staked_node_id: 4\n}\nnode_account_i_d {\n account_num: 5005\n realm_num: 0\n shard_num: 0\n}\ntransaction_fee: 100000\ntransaction_i_d {\n account_i_d {\n account_num: 5006\n realm_num: 0\n shard_num: 0\n }\n transaction_valid_start {\n seconds: 1554158542\n }\n}\ntransaction_valid_duration {\n seconds: 120\n}" ] com.hedera.hashgraph.sdk.AccountCreateTransactionTest.shouldSerialize=[ "# com.hedera.hashgraph.sdk.proto.TransactionBody\ncrypto_create_account {\n alias: \"\\022 \\207v\\306\\2701\\241\\266\\032\\301\\r\\254\\003\\004\\242\\204=\\344qoT\\261\\221\\233\\271\\032&\\205\\320\\376?0H\"\n auto_renew_period {\n seconds: 36000\n }\n initial_balance: 450\n key {\n ed25519: \"\\340\\310\\354\\'X\\245\\207\\237\\372\\302&\\241<\\fQky\\236r\\343QA\\240\\335\\202\\217\\224\\323y\\210\\244\\267\"\n }\n max_automatic_token_associations: 100\n memo: \"some dumb memo\"\n proxy_account_i_d {\n account_num: 1001\n realm_num: 0\n shard_num: 0\n }\n receive_record_threshold: 0\n receiver_sig_required: true\n send_record_threshold: 0\n staked_account_id {\n account_num: 3\n realm_num: 0\n shard_num: 0\n }\n}\nnode_account_i_d {\n account_num: 5005\n realm_num: 0\n shard_num: 0\n}\ntransaction_fee: 100000\ntransaction_i_d {\n account_i_d {\n account_num: 5006\n realm_num: 0\n shard_num: 0\n }\n transaction_valid_start {\n seconds: 1554158542\n }\n}\ntransaction_valid_duration {\n seconds: 120\n}" -] \ No newline at end of file +] diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/ECDSAPublicKeyTest.java b/sdk/src/test/java/com/hedera/hashgraph/sdk/ECDSAPublicKeyTest.java index 65b8dbd06..0dbb6ae74 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/ECDSAPublicKeyTest.java +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/ECDSAPublicKeyTest.java @@ -140,4 +140,17 @@ void keyIsNotEd25519() { assertThat(key.isED25519()).isFalse(); } + + @Test + @DisplayName("to EVM address") + void toEvmAddress() { + // Generated by https://www.rfctools.com/ethereum-address-test-tool/ + String privateKeyString = "DEBAE3CA62AB3157110DBA79C8DE26540DC320EE9BE73A77D70BA175643A3500"; + String expectedEvmAddress = "0xd8eb8db03c699faa3f47adcdcd2ae91773b10f8b"; + + PrivateKey privateKey = PrivateKey.fromStringECDSA(privateKeyString); + PublicKeyECDSA key = (PublicKeyECDSA) privateKey.getPublicKey(); + + assertThat(key.toEvmAddress()).isEqualTo(expectedEvmAddress); + } } diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/TransactionRecordTest.java b/sdk/src/test/java/com/hedera/hashgraph/sdk/TransactionRecordTest.java index 7894cf427..7afa6c99e 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/TransactionRecordTest.java +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/TransactionRecordTest.java @@ -81,7 +81,8 @@ private static TransactionRecord spawnRecordExample(@Nullable ByteString prngByt ByteString.copyFrom("Some hash", StandardCharsets.UTF_8), List.of(new Transfer(AccountId.fromString("1.2.3"), Hbar.from(8))), prngBytes, - prngNumber + prngNumber, + ByteString.copyFrom("0x00", StandardCharsets.UTF_8) ); } diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/TransactionRecordTest.snap b/sdk/src/test/java/com/hedera/hashgraph/sdk/TransactionRecordTest.snap index 3adcdbc1b..7e77a37f0 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/TransactionRecordTest.snap +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/TransactionRecordTest.snap @@ -1,8 +1,8 @@ com.hedera.hashgraph.sdk.TransactionRecordTest.shouldSerialize2=[ - "TransactionRecord{receipt=TransactionReceipt{transactionId=null, status=SCHEDULE_ALREADY_DELETED, exchangeRate=ExchangeRate{hbars=3, cents=4, expirationTime=2019-04-01T22:42:22Z, exchangeRateInCents=1.3333333333333333}, accountId=1.2.3, fileId=4.5.6, contractId=3.2.1, topicId=9.8.7, tokenId=6.5.4, topicSequenceNumber=3, topicRunningHash=[54, 56, 54, 102, 55, 55, 50, 48, 54, 101, 54, 102, 55, 55, 50, 48, 54, 50, 55, 50, 54, 102, 55, 55, 54, 101, 50, 48, 54, 51, 54, 102, 55, 55], totalSupply=30, scheduleId=1.1.1, scheduledTransactionId=3.3.3@1554158542.0, serials=[1, 2, 3], duplicates=[], children=[]}, transactionHash=68656c6c6f, consensusTimestamp=2019-04-01T22:42:22Z, transactionId=3.3.3@1554158542.0, transactionMemo=memo, transactionFee=3000 tℏ, contractFunctionResult=ContractFunctionResult{contractId=1.2.3, evmAddress=1.2.98329e006610472e6b372c080833f6d79ed833cf, errorMessage=null, bloom=, gasUsed=0, logs=[], createdContractIds=[], stateChanges=[], gas=0, hbarAmount=0 tℏ, contractFunctionparametersBytes=, rawResult=00000000000000000000000000000000000000000000000000000000ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000011223344556677889900aabbccddeeff00112233ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001448656c6c6f2c20776f726c642c20616761696e21000000000000000000000000, senderAccountId=1.2.3}, transfers=[Transfer{accountId=4.4.4, amount=5 ℏ}], tokenTransfers={6.6.6={1.1.1=4}}, tokenNftTransfers={4.4.4=[TokenNftTransfer{tokenId=4.4.4, sender=1.2.3, receiver=3.2.1, serial=4, isApproved=true}]}, scheduleRef=3.3.3, assessedCustomFees=[AssessedCustomFee{amount=4, tokenId=4.5.6, feeCollectorAccountId=8.6.5, payerAccountIdList=[3.3.3]}], automaticTokenAssociations=[TokenAssociation{tokenId=5.4.3, accountId=8.7.6}], aliasKey=302d300706052b8104000a03220002703a9370b0443be6ae7c507b0aec81a55e94e4a863b9655360bd65358caa6588, children=[], duplicates=[], parentConsensusTimestamp=2019-04-01T22:42:22Z, ethereumHash=536f6d652068617368, paidStakingRewards=[Transfer{accountId=1.2.3, amount=8 ℏ}], prngBytes=null, prngNumber=4}" + "TransactionRecord{receipt=TransactionReceipt{transactionId=null, status=SCHEDULE_ALREADY_DELETED, exchangeRate=ExchangeRate{hbars=3, cents=4, expirationTime=2019-04-01T22:42:22Z, exchangeRateInCents=1.3333333333333333}, accountId=1.2.3, fileId=4.5.6, contractId=3.2.1, topicId=9.8.7, tokenId=6.5.4, topicSequenceNumber=3, topicRunningHash=[54, 56, 54, 102, 55, 55, 50, 48, 54, 101, 54, 102, 55, 55, 50, 48, 54, 50, 55, 50, 54, 102, 55, 55, 54, 101, 50, 48, 54, 51, 54, 102, 55, 55], totalSupply=30, scheduleId=1.1.1, scheduledTransactionId=3.3.3@1554158542.0, serials=[1, 2, 3], duplicates=[], children=[]}, transactionHash=68656c6c6f, consensusTimestamp=2019-04-01T22:42:22Z, transactionId=3.3.3@1554158542.0, transactionMemo=memo, transactionFee=3000 tℏ, contractFunctionResult=ContractFunctionResult{contractId=1.2.3, evmAddress=1.2.98329e006610472e6b372c080833f6d79ed833cf, errorMessage=null, bloom=, gasUsed=0, logs=[], createdContractIds=[], stateChanges=[], gas=0, hbarAmount=0 tℏ, contractFunctionparametersBytes=, rawResult=00000000000000000000000000000000000000000000000000000000ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000011223344556677889900aabbccddeeff00112233ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001448656c6c6f2c20776f726c642c20616761696e21000000000000000000000000, senderAccountId=1.2.3}, transfers=[Transfer{accountId=4.4.4, amount=5 ℏ}], tokenTransfers={6.6.6={1.1.1=4}}, tokenNftTransfers={4.4.4=[TokenNftTransfer{tokenId=4.4.4, sender=1.2.3, receiver=3.2.1, serial=4, isApproved=true}]}, scheduleRef=3.3.3, assessedCustomFees=[AssessedCustomFee{amount=4, tokenId=4.5.6, feeCollectorAccountId=8.6.5, payerAccountIdList=[3.3.3]}], automaticTokenAssociations=[TokenAssociation{tokenId=5.4.3, accountId=8.7.6}], aliasKey=302d300706052b8104000a03220002703a9370b0443be6ae7c507b0aec81a55e94e4a863b9655360bd65358caa6588, children=[], duplicates=[], parentConsensusTimestamp=2019-04-01T22:42:22Z, ethereumHash=536f6d652068617368, paidStakingRewards=[Transfer{accountId=1.2.3, amount=8 ℏ}], prngBytes=null, prngNumber=4, evmAddress=30783030}" ] com.hedera.hashgraph.sdk.TransactionRecordTest.shouldSerialize=[ - "TransactionRecord{receipt=TransactionReceipt{transactionId=null, status=SCHEDULE_ALREADY_DELETED, exchangeRate=ExchangeRate{hbars=3, cents=4, expirationTime=2019-04-01T22:42:22Z, exchangeRateInCents=1.3333333333333333}, accountId=1.2.3, fileId=4.5.6, contractId=3.2.1, topicId=9.8.7, tokenId=6.5.4, topicSequenceNumber=3, topicRunningHash=[54, 56, 54, 102, 55, 55, 50, 48, 54, 101, 54, 102, 55, 55, 50, 48, 54, 50, 55, 50, 54, 102, 55, 55, 54, 101, 50, 48, 54, 51, 54, 102, 55, 55], totalSupply=30, scheduleId=1.1.1, scheduledTransactionId=3.3.3@1554158542.0, serials=[1, 2, 3], duplicates=[], children=[]}, transactionHash=68656c6c6f, consensusTimestamp=2019-04-01T22:42:22Z, transactionId=3.3.3@1554158542.0, transactionMemo=memo, transactionFee=3000 tℏ, contractFunctionResult=ContractFunctionResult{contractId=1.2.3, evmAddress=1.2.98329e006610472e6b372c080833f6d79ed833cf, errorMessage=null, bloom=, gasUsed=0, logs=[], createdContractIds=[], stateChanges=[], gas=0, hbarAmount=0 tℏ, contractFunctionparametersBytes=, rawResult=00000000000000000000000000000000000000000000000000000000ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000011223344556677889900aabbccddeeff00112233ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001448656c6c6f2c20776f726c642c20616761696e21000000000000000000000000, senderAccountId=1.2.3}, transfers=[Transfer{accountId=4.4.4, amount=5 ℏ}], tokenTransfers={6.6.6={1.1.1=4}}, tokenNftTransfers={4.4.4=[TokenNftTransfer{tokenId=4.4.4, sender=1.2.3, receiver=3.2.1, serial=4, isApproved=true}]}, scheduleRef=3.3.3, assessedCustomFees=[AssessedCustomFee{amount=4, tokenId=4.5.6, feeCollectorAccountId=8.6.5, payerAccountIdList=[3.3.3]}], automaticTokenAssociations=[TokenAssociation{tokenId=5.4.3, accountId=8.7.6}], aliasKey=302d300706052b8104000a03220002703a9370b0443be6ae7c507b0aec81a55e94e4a863b9655360bd65358caa6588, children=[], duplicates=[], parentConsensusTimestamp=2019-04-01T22:42:22Z, ethereumHash=536f6d652068617368, paidStakingRewards=[Transfer{accountId=1.2.3, amount=8 ℏ}], prngBytes=766572792072616e646f6d206279746573, prngNumber=null}" -] \ No newline at end of file + "TransactionRecord{receipt=TransactionReceipt{transactionId=null, status=SCHEDULE_ALREADY_DELETED, exchangeRate=ExchangeRate{hbars=3, cents=4, expirationTime=2019-04-01T22:42:22Z, exchangeRateInCents=1.3333333333333333}, accountId=1.2.3, fileId=4.5.6, contractId=3.2.1, topicId=9.8.7, tokenId=6.5.4, topicSequenceNumber=3, topicRunningHash=[54, 56, 54, 102, 55, 55, 50, 48, 54, 101, 54, 102, 55, 55, 50, 48, 54, 50, 55, 50, 54, 102, 55, 55, 54, 101, 50, 48, 54, 51, 54, 102, 55, 55], totalSupply=30, scheduleId=1.1.1, scheduledTransactionId=3.3.3@1554158542.0, serials=[1, 2, 3], duplicates=[], children=[]}, transactionHash=68656c6c6f, consensusTimestamp=2019-04-01T22:42:22Z, transactionId=3.3.3@1554158542.0, transactionMemo=memo, transactionFee=3000 tℏ, contractFunctionResult=ContractFunctionResult{contractId=1.2.3, evmAddress=1.2.98329e006610472e6b372c080833f6d79ed833cf, errorMessage=null, bloom=, gasUsed=0, logs=[], createdContractIds=[], stateChanges=[], gas=0, hbarAmount=0 tℏ, contractFunctionparametersBytes=, rawResult=00000000000000000000000000000000000000000000000000000000ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000011223344556677889900aabbccddeeff00112233ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001448656c6c6f2c20776f726c642c20616761696e21000000000000000000000000, senderAccountId=1.2.3}, transfers=[Transfer{accountId=4.4.4, amount=5 ℏ}], tokenTransfers={6.6.6={1.1.1=4}}, tokenNftTransfers={4.4.4=[TokenNftTransfer{tokenId=4.4.4, sender=1.2.3, receiver=3.2.1, serial=4, isApproved=true}]}, scheduleRef=3.3.3, assessedCustomFees=[AssessedCustomFee{amount=4, tokenId=4.5.6, feeCollectorAccountId=8.6.5, payerAccountIdList=[3.3.3]}], automaticTokenAssociations=[TokenAssociation{tokenId=5.4.3, accountId=8.7.6}], aliasKey=302d300706052b8104000a03220002703a9370b0443be6ae7c507b0aec81a55e94e4a863b9655360bd65358caa6588, children=[], duplicates=[], parentConsensusTimestamp=2019-04-01T22:42:22Z, ethereumHash=536f6d652068617368, paidStakingRewards=[Transfer{accountId=1.2.3, amount=8 ℏ}], prngBytes=766572792072616e646f6d206279746573, prngNumber=null, evmAddress=30783030}" +] From 19377f98212f7734aa681b850dc71026142f1db0 Mon Sep 17 00:00:00 2001 From: dikel Date: Fri, 23 Dec 2022 13:11:59 +0200 Subject: [PATCH 02/14] chore: small changelog fix Signed-off-by: dikel --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2449db3ba..5d88bc38e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Deprecated -- `AccountCreateTransaction.setAliasEvmAddress()` use `AccountCreateTransaction.setEvmAddress() instead` +- `AccountCreateTransaction.setAliasEvmAddress()` use `AccountCreateTransaction.setEvmAddress()` instead ## 2.19.0 From 5446653bf80d77fa272e00163b1793bad24342d6 Mon Sep 17 00:00:00 2001 From: Nikola Genov Date: Mon, 9 Jan 2023 16:09:51 +0200 Subject: [PATCH 03/14] HIP-583 - AccountId fromEvmAddress Signed-off-by: Nikola Genov --- .../com/hedera/hashgraph/sdk/AccountId.java | 66 +++++++++++++------ .../hedera/hashgraph/sdk/AccountIdTest.java | 18 +++-- .../hedera/hashgraph/sdk/AccountIdTest.snap | 15 +++++ 3 files changed, 76 insertions(+), 23 deletions(-) diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java index 57dc0cd01..13f12d6da 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java @@ -26,7 +26,6 @@ import javax.annotation.Nonnegative; import javax.annotation.Nullable; -import java.util.Arrays; import java.util.Objects; import java.util.regex.Pattern; @@ -58,7 +57,7 @@ public final class AccountId implements Comparable { public final PublicKey aliasKey; @Nullable - public final EvmAddress aliasEvmAddress; + public final EvmAddress evmAddress; @Nullable private final String checksum; @@ -98,7 +97,7 @@ public AccountId(@Nonnegative long shard, @Nonnegative long realm, @Nonnegative this.num = num; this.checksum = checksum; this.aliasKey = null; - this.aliasEvmAddress = null; + this.evmAddress = null; } /** @@ -115,14 +114,14 @@ public AccountId(@Nonnegative long shard, @Nonnegative long realm, @Nonnegative @Nonnegative long num, @Nullable String checksum, @Nullable PublicKey aliasKey, - @Nullable EvmAddress aliasEvmAddress + @Nullable EvmAddress evmAddress ) { this.shard = shard; this.realm = realm; this.num = num; this.checksum = checksum; this.aliasKey = aliasKey; - this.aliasEvmAddress = aliasEvmAddress; + this.evmAddress = evmAddress; } /** @@ -156,6 +155,35 @@ public static AccountId fromString(String id) { } } + /** + * Retrieve the account id from an EVM address. + * + * @param evmAddress a string representing the EVM address + * @return the account id object + */ + public static AccountId fromEvmAddress(String evmAddress) { + return fromEvmAddress(evmAddress, 0, 0); + } + + /** + * Retrieve the account id from an EVM address. + * + * @param evmAddress a string representing the EVM address + * @param shard the shard part of the account id + * @param realm the shard realm of the account id + * @return the account id object + */ + public static AccountId fromEvmAddress(String evmAddress, @Nonnegative long shard, @Nonnegative long realm) { + return new AccountId( + shard, + realm, + 0, + null, + null, + EvmAddress.fromString(evmAddress) + ); + } + /** * Retrieve the account id from a solidity address. * @@ -215,8 +243,8 @@ AccountID toProtobuf() { .setRealmNum(realm); if (aliasKey != null) { accountIdBuilder.setAlias(aliasKey.toProtobufKey().toByteString()); - } else if (aliasEvmAddress != null) { - accountIdBuilder.setAlias(ByteString.copyFrom(aliasEvmAddress.toBytes())); + } else if (evmAddress != null) { + accountIdBuilder.setAlias(ByteString.copyFrom(evmAddress.toBytes())); }else { accountIdBuilder.setAccountNum(num); } @@ -240,7 +268,7 @@ public void validate(Client client) throws BadEntityIdException { * @throws BadEntityIdException when the account id and checksum are invalid */ public void validateChecksum(Client client) throws BadEntityIdException { - if (aliasKey == null && aliasEvmAddress == null) { + if (aliasKey == null && evmAddress == null) { EntityIdHelper.validate(shard, realm, num, client, checksum); } } @@ -268,8 +296,8 @@ public byte[] toBytes() { public String toString() { if (aliasKey != null) { return "" + shard + "." + realm + "." + aliasKey.toStringDER(); - } else if (aliasEvmAddress != null) { - return "" + shard + "." + realm + "." + aliasEvmAddress.toString(); + } else if (evmAddress != null) { + return "" + shard + "." + realm + "." + evmAddress.toString(); } else { return EntityIdHelper.toString(shard, realm, num); } @@ -282,8 +310,8 @@ public String toString() { * @return the account id with checksum */ public String toStringWithChecksum(Client client) { - if (aliasKey != null || aliasEvmAddress != null) { - throw new IllegalStateException("toStringWithChecksum cannot be applied to AccountId with aliasKey or aliasEvmAddress"); + if (aliasKey != null || evmAddress != null) { + throw new IllegalStateException("toStringWithChecksum cannot be applied to AccountId with aliasKey or evmAddress"); } else { return EntityIdHelper.toStringWithChecksum(shard, realm, num, client, checksum); } @@ -293,7 +321,7 @@ public String toStringWithChecksum(Client client) { public int hashCode() { return Objects.hash( shard, realm, num, - (aliasKey != null) ? aliasKey.toBytes() : ((aliasEvmAddress != null) ? aliasEvmAddress.toBytes() : null) + (aliasKey != null) ? aliasKey.toBytes() : ((evmAddress != null) ? evmAddress.toBytes() : null) ); } @@ -311,12 +339,12 @@ public boolean equals(Object o) { if ((aliasKey == null) != (otherId.aliasKey == null)) { return false; } - if ((aliasEvmAddress == null) != (otherId.aliasEvmAddress == null)) { + if ((evmAddress == null) != (otherId.evmAddress == null)) { return false; } return shard == otherId.shard && realm == otherId.realm && num == otherId.num && (aliasKey == null || aliasKey.equals(otherId.aliasKey)) && - (aliasEvmAddress == null || aliasEvmAddress.equals(otherId.aliasEvmAddress)); + (evmAddress == null || evmAddress.equals(otherId.evmAddress)); } @Override @@ -340,12 +368,12 @@ public int compareTo(AccountId o) { if (aliasKey != null) { return aliasKey.toStringDER().compareTo(o.aliasKey.toStringDER()); } - if ((aliasEvmAddress == null) != (o.aliasEvmAddress == null)) { - return aliasEvmAddress != null ? 1 : -1; + if ((evmAddress == null) != (o.evmAddress == null)) { + return evmAddress != null ? 1 : -1; } - if (aliasEvmAddress == null) { + if (evmAddress == null) { return 0; } - return aliasEvmAddress.toString().compareTo(o.aliasEvmAddress.toString()); + return evmAddress.toString().compareTo(o.evmAddress.toString()); } } diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.java b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.java index 7f32655f0..68a43d2a7 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.java +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.java @@ -143,7 +143,7 @@ void fromStringWithAliasKey() { } @Test - void fromStringWithAliasEvmAddress() { + void fromStringWithEvmAddress() { SnapshotMatcher.expect(AccountId.fromString("0.0.302a300506032b6570032100114e6abc371b82da").toString()).toMatchSnapshot(); } @@ -168,7 +168,7 @@ void toBytesAlias() throws InvalidProtocolBufferException { } @Test - void toBytesAliasEvmAddress() { + void toBytesEvmAddress() { SnapshotMatcher.expect(Hex.toHexString(AccountId.fromString("0.0.302a300506032b6570032100114e6abc371b82da").toBytes())).toMatchSnapshot(); } @@ -204,12 +204,12 @@ void toFromProtobufEcdsaAliasKey() { } @Test - void fromBytesAliasEvmAddress() throws InvalidProtocolBufferException { + void fromBytesEvmAddress() throws InvalidProtocolBufferException { SnapshotMatcher.expect(AccountId.fromBytes(AccountId.fromString("0.0.302a300506032b6570032100114e6abc371b82da").toBytes()).toString()).toMatchSnapshot(); } @Test - void toFromProtobufAliasEvmAddress() { + void toFromProtobufEvmAddress() { var id1 = AccountId.fromString("0.0.302a300506032b6570032100114e6abc371b82da"); var id2 = AccountId.fromProtobuf(id1.toProtobuf()); assertThat(id2).isEqualTo(id1); @@ -219,4 +219,14 @@ void toFromProtobufAliasEvmAddress() { void toSolidityAddress() { SnapshotMatcher.expect(new AccountId(5005).toSolidityAddress()).toMatchSnapshot(); } + + @Test + void fromEvmAddress() { + String evmAddress = "302a300506032b6570032100114e6abc371b82da"; + var id = AccountId.fromEvmAddress(evmAddress, 5, 9); + + assertThat(id.evmAddress.toString()).isEqualTo(evmAddress); + assertThat(id.shard).isEqualTo(5); + assertThat(id.realm).isEqualTo(9); + } } diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.snap b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.snap index e8785a43c..d1bb2f2fc 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.snap +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.snap @@ -13,6 +13,11 @@ com.hedera.hashgraph.sdk.AccountIdTest.fromBytesAliasEvmAddress=[ ] +com.hedera.hashgraph.sdk.AccountIdTest.fromBytesEvmAddress=[ + "0.0.302a300506032b6570032100114e6abc371b82da" +] + + com.hedera.hashgraph.sdk.AccountIdTest.fromSolidityAddress=[ "0.0.5005" ] @@ -53,6 +58,11 @@ com.hedera.hashgraph.sdk.AccountIdTest.fromStringWithChecksumOnTestnet=[ ] +com.hedera.hashgraph.sdk.AccountIdTest.fromStringWithEvmAddress=[ + "0.0.302a300506032b6570032100114e6abc371b82da" +] + + com.hedera.hashgraph.sdk.AccountIdTest.toBytes=[ "188d27" ] @@ -68,6 +78,11 @@ com.hedera.hashgraph.sdk.AccountIdTest.toBytesAliasEvmAddress=[ ] +com.hedera.hashgraph.sdk.AccountIdTest.toBytesEvmAddress=[ + "2214302a300506032b6570032100114e6abc371b82da" +] + + com.hedera.hashgraph.sdk.AccountIdTest.toSolidityAddress=[ "000000000000000000000000000000000000138d" ] \ No newline at end of file From ccbc2b8cd93614fab10bdcf5697175a587e2f259 Mon Sep 17 00:00:00 2001 From: dikel Date: Tue, 10 Jan 2023 12:15:37 +0200 Subject: [PATCH 04/14] add AccountCreateEvmAddress example Signed-off-by: dikel --- .../java/AccountCreateEvmAddressExample.java | 137 ++++++++++++++++++ .../sdk/AccountCreateTransaction.java | 45 +----- .../java/com/hedera/hashgraph/sdk/Key.java | 30 ++-- .../com/hedera/hashgraph/sdk/PublicKey.java | 7 + .../hedera/hashgraph/sdk/PublicKeyECDSA.java | 8 +- .../hashgraph/sdk/PublicKeyED25519.java | 5 + .../hashgraph/sdk/ECDSAPublicKeyTest.java | 6 +- 7 files changed, 178 insertions(+), 60 deletions(-) create mode 100644 examples/src/main/java/AccountCreateEvmAddressExample.java diff --git a/examples/src/main/java/AccountCreateEvmAddressExample.java b/examples/src/main/java/AccountCreateEvmAddressExample.java new file mode 100644 index 000000000..c480a7996 --- /dev/null +++ b/examples/src/main/java/AccountCreateEvmAddressExample.java @@ -0,0 +1,137 @@ +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.hedera.hashgraph.sdk.*; +import io.github.cdimascio.dotenv.Dotenv; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Objects; +import java.util.Collections; +import java.util.concurrent.TimeoutException; + +public class AccountCreateEvmAddressExample { + // see `.env.sample` in the repository root for how to specify these values + // or set environment variables with the same names + private static final AccountId OPERATOR_ID = AccountId.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_ID"))); + private static final PrivateKey OPERATOR_KEY = PrivateKey.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_KEY"))); + // HEDERA_NETWORK defaults to testnet if not specified in dotenv + private static final String HEDERA_NETWORK = Dotenv.load().get("HEDERA_NETWORK", "testnet"); + + private AccountCreateEvmAddressExample() { + } + + /* + Create an account and set an EVM address using the `AccountCreateTransaction` + Reference: [HIP-583 Expand alias support in CryptoCreate & CryptoTransfer Transactions](https://hips.hedera.com/hip/hip-583) + ## Example 1 + - Create an ECSDA private key + - Extract the ECDSA public key + - Extract the Ethereum public address + - Add function in the SDK to calculate the Ethereum Address + - Ethereum account address / public-address - This is the rightmost 20 bytes of the 32 byte Keccak-256 hash of the ECDSA public key of the account. This calculation is in the manner described by the Ethereum Yellow Paper. + - Use the `AccountCreateTransaction` and set the EVM address field to the Ethereum public address + - Sign the transaction with the key that us paying for the transaction + - Get the account ID from the receipt + - Get the `AccountInfo` and return the account details + - Verify the evm address provided for the account matches what is in the mirror node + */ + public static void main(String[] args) throws PrecheckStatusException, TimeoutException, ReceiptStatusException, InterruptedException, IOException { +// Client client = Client.forName(HEDERA_NETWORK); + + Client client = Client.forNetwork(Collections.singletonMap("127.0.0.1:50211", AccountId.fromString("0.0.3"))).setMirrorNetwork(List.of("127.0.0.1:5600")); + client.setOperator(AccountId.fromString("0.0.2"), PrivateKey.fromString("302e020100300506032b65700422042091132178e72057a1d7528025956fe39b0b847f200ab59b2fdd367017f3087137")); + + // Defaults the operator account ID and key such that all generated transactions will be paid for + // by this account and be signed by this key + client.setOperator(OPERATOR_ID, OPERATOR_KEY); + + /* + * Step 1 + * Create an ECSDA private key + */ + PrivateKey privateKey = PrivateKeyECDSA.generateECDSA(); + + /* + * Step 2 + * Extract the ECDSA public key + */ + PublicKey publicKey = privateKey.getPublicKey(); + + /* + * Step 3 + * Extract the Ethereum public address + */ + EvmAddress evmAddress = publicKey.toEvmAddress(); + System.out.println(evmAddress); + + /* + * Step 4 + * Use the `AccountCreateTransaction` and set the EVM address field to the Ethereum public address + */ + AccountCreateTransaction accountCreateTransaction = new AccountCreateTransaction() + .setEvmAddress(evmAddress) + .setInitialBalance(new Hbar(10)); + + /* + * Step 5 + * Sign the transaction with the key that is paying for the transaction + */ + TransactionResponse response = accountCreateTransaction.execute(client); + + /* + * Step 6 + * Get the account ID from the receipt + */ + AccountId newAccountId = response.getReceipt(client).accountId; + System.out.println(newAccountId); + + /* + * Step 7 + * Get the `AccountInfo` and return the account details + */ + AccountInfo info = new AccountInfoQuery() + .setAccountId(newAccountId) + .execute(client); + + + if (info.contractAccountId.equals(evmAddress.toString())) { + System.out.println("The addresses match"); + } else { + System.out.println("The addresses don't match"); + } + + /* + * Step 8 + * Verify the evm address provided for the account matches what is in the mirror node + */ + Thread.sleep(5000); + URL url = new URL("http://127.0.0.1:5551/api/v1/accounts?account.id=" + newAccountId); + HttpURLConnection con = (HttpURLConnection)url.openConnection(); + con.setRequestMethod("GET"); + con.setRequestProperty("Accept", "application/json"); + try(BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8))) { + StringBuilder builder = new StringBuilder(); + String responseLine; + while ((responseLine = br.readLine()) != null) { + builder.append(responseLine.trim()); + } + JsonObject jsonObject = JsonParser.parseString(builder.toString()).getAsJsonObject(); + String mirrorNodeEvmAddress = jsonObject + .getAsJsonArray("accounts") + .get(0).getAsJsonObject() + .get("evm_address") + .getAsString(); + + if (mirrorNodeEvmAddress.equals("0x" + evmAddress)) { + System.out.println("The addresses match"); + } else { + System.out.println("The addresses don't match"); + } + } + } +} diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountCreateTransaction.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountCreateTransaction.java index a8b3790a0..75e545d33 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountCreateTransaction.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountCreateTransaction.java @@ -59,9 +59,6 @@ public final class AccountCreateTransaction extends Transaction - * The ethereum account 20-byte EVM address to be used as the account's alias. This EVM address may be either - * the encoded form of the shard.realm.num or the keccak-256 hash of a ECDSA_SECP256K1 primitive key. - *

- * A given alias can map to at most one account on the network at a time. This uniqueness will be enforced - * relative to aliases currently on the network at alias assignment. - *

- * If a transaction creates an account using an alias, any further crypto transfers to that alias will - * simply be deposited in that account, without creating anything, and with no creation fee being charged. - * - * @param aliasEvmAddress The ethereum account 20-byte EVM address - * @return {@code this} - */ - @Deprecated - public AccountCreateTransaction setAliasEvmAddress(EvmAddress aliasEvmAddress) { - requireNotFrozen(); - this.aliasEvmAddress = aliasEvmAddress; - return this; - } - /** * EOA 20-byte address to create that is derived from the keccak-256 hash of a ECDSA_SECP256K1 primitive key. */ @@ -436,6 +400,12 @@ public AccountCreateTransaction setEvmAddress(EvmAddress evmAddress) { return this; } + public AccountCreateTransaction setEvmAddress(String evmAddress) { + // Remove the "0x" prefix + EvmAddress address = EvmAddress.fromString(evmAddress.substring(2)); + return this.setEvmAddress(address); + } + /** * Build the transaction body. * @@ -460,8 +430,6 @@ CryptoCreateTransactionBody.Builder build() { if (aliasKey != null) { builder.setAlias(aliasKey.toProtobufKey().toByteString()); - } else if (aliasEvmAddress != null) { - builder.setAlias(ByteString.copyFrom(aliasEvmAddress.toBytes())); } if (stakedAccountId != null) { @@ -518,7 +486,6 @@ void initFromTransactionBody() { } aliasKey = PublicKey.fromAliasBytes(body.getAlias()); - aliasEvmAddress = EvmAddress.fromAliasBytes(body.getAlias()); evmAddress = EvmAddress.fromAliasBytes(body.getEvmAddress()); } diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/Key.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/Key.java index d8559a008..a44346882 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/Key.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/Key.java @@ -52,30 +52,32 @@ public abstract class Key { */ static Key fromProtobufKey(com.hedera.hashgraph.sdk.proto.Key key) { switch (key.getKeyCase()) { - case ED25519: + case ED25519 -> { return new PublicKeyED25519(key.getEd25519().toByteArray()); - - case ECDSA_SECP256K1: + } + case ECDSA_SECP256K1 -> { if (key.getECDSASecp256K1().size() == 20) { return new EvmAddress(key.getECDSASecp256K1().toByteArray()); } else { return new PublicKeyECDSA(key.getECDSASecp256K1().toByteArray()); } - - case KEYLIST: + } + case KEYLIST -> { return KeyList.fromProtobuf(key.getKeyList(), null); - - case THRESHOLDKEY: + } + case THRESHOLDKEY -> { return KeyList.fromProtobuf(key.getThresholdKey().getKeys(), key.getThresholdKey().getThreshold()); - - case CONTRACTID: + } + case CONTRACTID -> { return ContractId.fromProtobuf(key.getContractID()); - - case DELEGATABLE_CONTRACT_ID: + } + case DELEGATABLE_CONTRACT_ID -> { return DelegateContractId.fromProtobuf(key.getDelegatableContractId()); - - default: - throw new IllegalStateException("Key#fromProtobuf: unhandled key case: " + key.getKeyCase()); + } + case KEY_NOT_SET -> { + return null; + } + default -> throw new IllegalStateException("Key#fromProtobuf: unhandled key case: " + key.getKeyCase()); } } diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/PublicKey.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/PublicKey.java index 744fe8f75..b8287d9b5 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/PublicKey.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/PublicKey.java @@ -278,4 +278,11 @@ public AccountId toAccountId(@Nonnegative long shard, @Nonnegative long realm) { * @return is this an ECDSA key */ public abstract boolean isECDSA(); + + /** + * Converts the key to EVM address + * + * @return the EVM address + */ + public abstract EvmAddress toEvmAddress(); } diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/PublicKeyECDSA.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/PublicKeyECDSA.java index f347fdda9..06e2f87d1 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/PublicKeyECDSA.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/PublicKeyECDSA.java @@ -139,15 +139,15 @@ public byte[] toBytesRaw() { return Arrays.copyOf(keyData, keyData.length); } - public String toEvmAddress() { + @Override + public EvmAddress toEvmAddress() { // Calculate the Keccak-256 hash of the uncompressed key without "04" prefix byte[] uncompressed = Key.ECDSA_SECP256K1_CURVE .getCurve().decodePoint(toBytesRaw()).getEncoded(false); byte[] keccakBytes = calcKeccak256(Arrays.copyOfRange(uncompressed, 1, uncompressed.length)); - // Return the last 20 bytes prefixed by "0x" - String keccakString = Hex.toHexString(keccakBytes); - return "0x" + keccakString.substring(24); + // Return the last 20 bytes + return EvmAddress.fromBytes(Arrays.copyOfRange(keccakBytes, 12, 32)); } @Override diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/PublicKeyED25519.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/PublicKeyED25519.java index 6009bb346..b87780b5d 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/PublicKeyED25519.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/PublicKeyED25519.java @@ -117,6 +117,11 @@ public byte[] toBytesRaw() { return keyData; } + @Override + public EvmAddress toEvmAddress() { + throw new IllegalStateException("unsupported operation on Ed25519PublicKey"); + } + @Override public boolean equals( Object o) { if (this == o) { diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/ECDSAPublicKeyTest.java b/sdk/src/test/java/com/hedera/hashgraph/sdk/ECDSAPublicKeyTest.java index 0dbb6ae74..eb6395104 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/ECDSAPublicKeyTest.java +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/ECDSAPublicKeyTest.java @@ -146,11 +146,11 @@ void keyIsNotEd25519() { void toEvmAddress() { // Generated by https://www.rfctools.com/ethereum-address-test-tool/ String privateKeyString = "DEBAE3CA62AB3157110DBA79C8DE26540DC320EE9BE73A77D70BA175643A3500"; - String expectedEvmAddress = "0xd8eb8db03c699faa3f47adcdcd2ae91773b10f8b"; + String expectedEvmAddress = "d8eb8db03c699faa3f47adcdcd2ae91773b10f8b"; PrivateKey privateKey = PrivateKey.fromStringECDSA(privateKeyString); - PublicKeyECDSA key = (PublicKeyECDSA) privateKey.getPublicKey(); + PublicKey key = privateKey.getPublicKey(); - assertThat(key.toEvmAddress()).isEqualTo(expectedEvmAddress); + assertThat(key.toEvmAddress()).hasToString(expectedEvmAddress); } } From 8991fb42bb88355a90770d9d3feba1e697a70196 Mon Sep 17 00:00:00 2001 From: Nikola Genov Date: Tue, 10 Jan 2023 16:15:49 +0200 Subject: [PATCH 05/14] HIP-583 - AccountId fromString - support raw EVM address Signed-off-by: Nikola Genov --- sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java | 3 +++ .../test/java/com/hedera/hashgraph/sdk/AccountIdTest.java | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java index 13f12d6da..1a8587bb4 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java @@ -132,6 +132,9 @@ public AccountId(@Nonnegative long shard, @Nonnegative long realm, @Nonnegative * @throws IllegalArgumentException when the account id and checksum are invalid */ public static AccountId fromString(String id) { + if ((id.startsWith("0x") && id.length() == 42) || id.length() == 40) + return fromEvmAddress(id); + try { return EntityIdHelper.fromString(id, AccountId::new); } catch (IllegalArgumentException error) { diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.java b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.java index 68a43d2a7..db4914b52 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.java +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.java @@ -215,6 +215,13 @@ void toFromProtobufEvmAddress() { assertThat(id2).isEqualTo(id1); } + @Test + void toFromProtobufRawEvmAddress() { + var id1 = AccountId.fromString("302a300506032b6570032100114e6abc371b82da"); + var id2 = AccountId.fromProtobuf(id1.toProtobuf()); + assertThat(id2).isEqualTo(id1); + } + @Test void toSolidityAddress() { SnapshotMatcher.expect(new AccountId(5005).toSolidityAddress()).toMatchSnapshot(); From c57191eafbd2d8d3b02a99745cff6b5d6c607269 Mon Sep 17 00:00:00 2001 From: dikel Date: Wed, 11 Jan 2023 14:46:11 +0200 Subject: [PATCH 06/14] add CreateAccountWithAlias, LazyCreateAccountTx and LazyCreateTransferTx examples Signed-off-by: dikel --- CHANGELOG.md | 4 + .../java/AccountCreateEvmAddressExample.java | 5 +- .../java/CreateAccountWithAliasExample.java | 255 ++++++++++++++++++ .../LazyCreateAccountTransactionExample.java | 130 +++++++++ .../LazyCreateTransferTransactionExample.java | 147 ++++++++++ 5 files changed, 537 insertions(+), 4 deletions(-) create mode 100644 examples/src/main/java/CreateAccountWithAliasExample.java create mode 100644 examples/src/main/java/LazyCreateAccountTransactionExample.java create mode 100644 examples/src/main/java/LazyCreateTransferTransactionExample.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d88bc38e..76794b2e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `TransactionRecord.evmAddress` - `PublicKeyECDSA.toEvmAddress()` - `AccountCreateTransaction.setEvmAddress()` + - `AccountCreateEvmAddressExample` + - `CreateAccountWithAliasExample` + - `LazyCreateAccountTransactionExample` + - `LazyCreateTransferTransactionExample` ### Deprecated diff --git a/examples/src/main/java/AccountCreateEvmAddressExample.java b/examples/src/main/java/AccountCreateEvmAddressExample.java index c480a7996..037dc679c 100644 --- a/examples/src/main/java/AccountCreateEvmAddressExample.java +++ b/examples/src/main/java/AccountCreateEvmAddressExample.java @@ -42,9 +42,7 @@ private AccountCreateEvmAddressExample() { */ public static void main(String[] args) throws PrecheckStatusException, TimeoutException, ReceiptStatusException, InterruptedException, IOException { // Client client = Client.forName(HEDERA_NETWORK); - Client client = Client.forNetwork(Collections.singletonMap("127.0.0.1:50211", AccountId.fromString("0.0.3"))).setMirrorNetwork(List.of("127.0.0.1:5600")); - client.setOperator(AccountId.fromString("0.0.2"), PrivateKey.fromString("302e020100300506032b65700422042091132178e72057a1d7528025956fe39b0b847f200ab59b2fdd367017f3087137")); // Defaults the operator account ID and key such that all generated transactions will be paid for // by this account and be signed by this key @@ -54,7 +52,7 @@ public static void main(String[] args) throws PrecheckStatusException, TimeoutEx * Step 1 * Create an ECSDA private key */ - PrivateKey privateKey = PrivateKeyECDSA.generateECDSA(); + PrivateKey privateKey = PrivateKey.generateECDSA(); /* * Step 2 @@ -98,7 +96,6 @@ public static void main(String[] args) throws PrecheckStatusException, TimeoutEx .setAccountId(newAccountId) .execute(client); - if (info.contractAccountId.equals(evmAddress.toString())) { System.out.println("The addresses match"); } else { diff --git a/examples/src/main/java/CreateAccountWithAliasExample.java b/examples/src/main/java/CreateAccountWithAliasExample.java new file mode 100644 index 000000000..2ae89017c --- /dev/null +++ b/examples/src/main/java/CreateAccountWithAliasExample.java @@ -0,0 +1,255 @@ +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.hedera.hashgraph.sdk.*; +import io.github.cdimascio.dotenv.Dotenv; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeoutException; + +public class CreateAccountWithAliasExample { + // see `.env.sample` in the repository root for how to specify these values + // or set environment variables with the same names + private static final AccountId OPERATOR_ID = AccountId.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_ID"))); + private static final PrivateKey OPERATOR_KEY = PrivateKey.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_KEY"))); + // HEDERA_NETWORK defaults to testnet if not specified in dotenv + private static final String HEDERA_NETWORK = Dotenv.load().get("HEDERA_NETWORK", "testnet"); + + private CreateAccountWithAliasExample() { + } + + /* + Create an account and set a public key alias. + Reference: [HIP-583 Expand alias support in CryptoCreate & CryptoTransfer Transactions](https://hips.hedera.com/hip/hip-583) + ## Example 1: + - Create an ECDSA private key + - Get the ECDSA public key + - Use the `AccountCreateTransaction` and populate the `setAliasKey` field + - Sign the `AccountCreateTransaction` using an existing Hedera account and key to pay for the transaction fee + - Execute the transaction + - Return the Hedera account ID from the receipt of the transaction + - Get the `AccountInfo` using the new account ID + - Get the `AccountInfo` using the account public key in `0.0.aliasPublicKey` format + - Show the public key and the public key alias are the same on the account + - Show this account has a corresponding EVM address in the mirror node + ## Example 2: + - Create an ED2519 private key + - Get the ED2519 public key + - Use the `AccountCreateTransaction` and populate the `setAliasKey` field + - Sign the `AccountCreateTransaction` using an existing Hedera account and key to pay for the transaction fee + - Execute the transaction + - Return the Hedera account ID from the receipt of the transaction + - Get the `AccountInfo` using the new account ID + - Get the `AccountInfo` using the account public key in `0.0.aliasPublicKey` format + - Show the public key and the public key alias are the same on the account + */ + public static void main(String[] args) throws PrecheckStatusException, TimeoutException, ReceiptStatusException, InterruptedException, IOException { +// Client client = Client.forName(HEDERA_NETWORK); + Client client = Client.forNetwork(Collections.singletonMap("127.0.0.1:50211", AccountId.fromString("0.0.3"))).setMirrorNetwork(List.of("127.0.0.1:5600")); + + // Defaults the operator account ID and key such that all generated transactions will be paid for + // by this account and be signed by this key + client.setOperator(OPERATOR_ID, OPERATOR_KEY); + + /* + * Example 1 + */ + System.out.println("Example 1"); + + /* + * Step 1 + * Create an ECSDA private key + */ + PrivateKey privateKey = PrivateKey.generateECDSA(); + + /* + * Step 2 + * Extract the ECDSA public key + */ + PublicKey publicKey = privateKey.getPublicKey(); + + /* + * Step 3 + * Use the `AccountCreateTransaction` and populate the `setAliasKey` field + */ + AccountCreateTransaction accountCreateTransaction = new AccountCreateTransaction() + .setAliasKey(publicKey) + .setInitialBalance(new Hbar(10)); + + /* + * Step 4 + * Execute the transaction + */ + TransactionResponse response = accountCreateTransaction.execute(client); + + /* + * Step 5 + * Return the Hedera account ID from the receipt of the transaction + */ + AccountId newAccountId = response.getReceipt(client).accountId; + System.out.println(newAccountId); + + /* + * Step 6 + * Get the `AccountInfo` using the new account ID + */ + AccountInfo accountInfo = new AccountInfoQuery() + .setAccountId(newAccountId) + .execute(client); + + /* + * Step 7 + * Get the `AccountInfo` using the account public key in `0.0.aliasPublicKey` format + */ + AccountId aliasPublicKey = publicKey.toAccountId(0, 0); + AccountInfo accountInfoAlias = new AccountInfoQuery() + .setAccountId(aliasPublicKey) + .execute(client); + + /* + * Step 8 + * Show the public key and the public key alias are the same on the account + */ + if (accountInfo.key.equals(accountInfo.aliasKey) + && accountInfo.key.equals(accountInfoAlias.key) + && accountInfoAlias.key.equals(accountInfoAlias.aliasKey) + ) { + System.out.println("The public key and the public key alias are the same"); + } else { + System.out.println("The public key and the public key alias differ"); + } + + /* + * Step 9 + * Show this account has a corresponding EVM address in the mirror node + */ + Thread.sleep(5000); + URL url = new URL("http://127.0.0.1:5551/api/v1/accounts?account.id=" + newAccountId); + HttpURLConnection con = (HttpURLConnection)url.openConnection(); + con.setRequestMethod("GET"); + con.setRequestProperty("Accept", "application/json"); + try(BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8))) { + StringBuilder builder = new StringBuilder(); + String responseLine; + while ((responseLine = br.readLine()) != null) { + builder.append(responseLine.trim()); + } + JsonObject jsonObject = JsonParser.parseString(builder.toString()).getAsJsonObject(); + String mirrorNodeEvmAddress = jsonObject + .getAsJsonArray("accounts") + .get(0).getAsJsonObject() + .get("evm_address") + .toString(); + + if (mirrorNodeEvmAddress != null) { + System.out.println("The account has a corresponding EVM address in the mirror node"); + } else { + System.out.println("The EVM address of the account is missing in the mirror node"); + } + } + + /* + * Example 2 + */ + System.out.println("Example 2"); + + /* + * Step 1 + * Create an ECSDA private key + */ + PrivateKey privateKey2 = PrivateKey.generateED25519(); + + /* + * Step 2 + * Extract the ECDSA public key + */ + PublicKey publicKey2 = privateKey2.getPublicKey(); + + /* + * Step 3 + * Use the `AccountCreateTransaction` and populate the `setAliasKey` field + */ + AccountCreateTransaction accountCreateTransaction2 = new AccountCreateTransaction() + .setAliasKey(publicKey2) + .setInitialBalance(new Hbar(10)); + + /* + * Step 4 + * Execute the transaction + */ + TransactionResponse response2 = accountCreateTransaction2.execute(client); + + /* + * Step 5 + * Return the Hedera account ID from the receipt of the transaction + */ + AccountId newAccountId2 = response2.getReceipt(client).accountId; + System.out.println(newAccountId2); + + /* + * Step 6 + * Get the `AccountInfo` using the new account ID + */ + AccountInfo accountInfo2 = new AccountInfoQuery() + .setAccountId(newAccountId2) + .execute(client); + + /* + * Step 7 + * Get the `AccountInfo` using the account public key in `0.0.aliasPublicKey` format + */ + AccountId aliasPublicKey2 = publicKey2.toAccountId(0, 0); + AccountInfo accountInfoAlias2 = new AccountInfoQuery() + .setAccountId(aliasPublicKey2) + .execute(client); + + /* + * Step 8 + * Show the public key and the public key alias are the same on the account + */ + if (accountInfo2.key.equals(accountInfo2.aliasKey) + && accountInfo2.key.equals(accountInfoAlias2.key) + && accountInfoAlias2.key.equals(accountInfoAlias2.aliasKey) + ) { + System.out.println("The public key and the public key alias are the same"); + } else { + System.out.println("The public key and the public key alias differ"); + } + + /* + * Step 9 + * Show this account has a corresponding EVM address in the mirror node + */ + Thread.sleep(5000); + URL url2 = new URL("http://127.0.0.1:5551/api/v1/accounts?account.id=" + newAccountId2); + HttpURLConnection con2 = (HttpURLConnection)url2.openConnection(); + con2.setRequestMethod("GET"); + con2.setRequestProperty("Accept", "application/json"); + try(BufferedReader br = new BufferedReader(new InputStreamReader(con2.getInputStream(), StandardCharsets.UTF_8))) { + StringBuilder builder = new StringBuilder(); + String responseLine; + while ((responseLine = br.readLine()) != null) { + builder.append(responseLine.trim()); + } + JsonObject jsonObject = JsonParser.parseString(builder.toString()).getAsJsonObject(); + String mirrorNodeEvmAddress = jsonObject + .getAsJsonArray("accounts") + .get(0).getAsJsonObject() + .get("evm_address") + .toString(); + + if (mirrorNodeEvmAddress.equals("null")) { + System.out.println("The EVM address of the account is missing in the mirror node"); + } else { + System.out.println("The account has a corresponding EVM address in the mirror node"); + } + } + } +} diff --git a/examples/src/main/java/LazyCreateAccountTransactionExample.java b/examples/src/main/java/LazyCreateAccountTransactionExample.java new file mode 100644 index 000000000..0e465dd72 --- /dev/null +++ b/examples/src/main/java/LazyCreateAccountTransactionExample.java @@ -0,0 +1,130 @@ +import com.hedera.hashgraph.sdk.*; +import io.github.cdimascio.dotenv.Dotenv; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeoutException; + +public class LazyCreateAccountTransactionExample { + // see `.env.sample` in the repository root for how to specify these values + // or set environment variables with the same names + private static final AccountId OPERATOR_ID = AccountId.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_ID"))); + private static final PrivateKey OPERATOR_KEY = PrivateKey.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_KEY"))); + // HEDERA_NETWORK defaults to testnet if not specified in dotenv + private static final String HEDERA_NETWORK = Dotenv.load().get("HEDERA_NETWORK", "testnet"); + + private LazyCreateAccountTransactionExample() { + } + + /* + Lazy-create a new account using a public-address via the `AccountCreateTransaction` transaction. + Reference: [HIP-583 Expand alias support in CryptoCreate & CryptoTransfer Transactions](https://hips.hedera.com/hip/hip-583) + ## Example 1: + - Create an ECSDA private key + - Extract the ECDSA public key + - Extract the Ethereum public address + - Add function in the SDK to calculate the Ethereum Address + - Ethereum account address / public-address - This is the rightmost 20 bytes of the 32 byte Keccak-256 hash of the ECDSA public key of the account. This calculation is in the manner described by the Ethereum Yellow Paper. + - Use the `AccountCreateTransaction` and populate `setEvmAddress(publicAddress)` field with the Ethereum public address + - Sign the `AccountCreateTransaction` transaction using an existing Hedera account and key to pay for the transaction fee + - The Hedera account that was created has a public address the user specified in the `AccountCreateTransaction` + - Will not have a Hedera account public key at this stage + - The account can only receive tokens or hbars + - This is referred to as a hollow account + - The alias property of the account will not have the public address + - Get the `AccountInfo` of the account and show that it is a hollow account i.e. does not have a public key + - To enhance the hollow account to have a public key the hollow account needs to be specified as a transaction fee payer in a HAPI transaction + - Any HAPI transaction can be used to apply the public key to the hollow account and create a complete Hedera account + - Use a HAPI transaction and set the hollow account as the transaction fee payer + - Sign with the ECDSA private key that corresponds to the public address on the hollow account + - Execute the transaction + - Get the `AccountInfo` and show that the account is now a complete account i.e. returns a public key of the account + */ + public static void main(String[] args) throws PrecheckStatusException, TimeoutException, ReceiptStatusException, InterruptedException, IOException { +// Client client = Client.forName(HEDERA_NETWORK); + Client client = Client.forNetwork(Collections.singletonMap("127.0.0.1:50211", AccountId.fromString("0.0.3"))).setMirrorNetwork(List.of("127.0.0.1:5600")); + + // Defaults the operator account ID and key such that all generated transactions will be paid for + // by this account and be signed by this key + client.setOperator(OPERATOR_ID, OPERATOR_KEY); + + /* + * Step 1 + * Create an ECSDA private key + */ + PrivateKey privateKey = PrivateKey.generateECDSA(); + + /* + * Step 2 + * Extract the ECDSA public key + */ + PublicKey publicKey = privateKey.getPublicKey(); + + /* + * Step 3 + * Extract the Ethereum public address + */ + EvmAddress evmAddress = publicKey.toEvmAddress(); + System.out.println(evmAddress); + + /* + * Step 4 + * Use the `AccountCreateTransaction` and set the EVM address field to the Ethereum public address + */ + AccountCreateTransaction accountCreateTransaction = new AccountCreateTransaction() + .setEvmAddress(evmAddress) + .setInitialBalance(new Hbar(10)); + + /* + * Step 5 + * Sign the transaction with the key that is paying for the transaction + */ + TransactionResponse response = accountCreateTransaction.execute(client); + + /* + * Step 6 + * Get the `AccountInfo` of the account and show that it is a hollow account i.e. does not have a public key + */ + AccountId newAccountId = response.getReceipt(client).accountId; + System.out.println(newAccountId); + + AccountInfo accountInfo = new AccountInfoQuery() + .setAccountId(newAccountId) + .execute(client); + + if (((KeyList) accountInfo.key).isEmpty()) { + System.out.println("The newly created account is a hollow account"); + } else { + System.out.println("Not a hollow account"); + } + + /* + * Step 7 + * Use a HAPI transaction and set the hollow account as the transaction fee payer + * - To enhance the hollow account to have a public key the hollow account needs to be specified as a transaction fee payer in a HAPI transaction + * - Any HAPI transaction can be used to apply the public key to the hollow account and create a complete Hedera account + */ + + TransactionReceipt receipt = new TopicCreateTransaction() + .setTransactionId(TransactionId.generate(newAccountId)) + .setTopicMemo("Memo") + .freezeWith(client) + .sign(privateKey) + .execute(client) + .getReceipt(client); + System.out.println("Topic id = " + receipt.topicId); + + /* + * Step 8 + * Get the `AccountInfo` and show that the account is now a complete account i.e. returns a public key of the account + */ + AccountInfo accountInfo2 = new AccountInfoQuery() + .setAccountId(newAccountId) + .execute(client); + + System.out.println("The public key of the newly created and now complete account: " + accountInfo2.key); + + } +} diff --git a/examples/src/main/java/LazyCreateTransferTransactionExample.java b/examples/src/main/java/LazyCreateTransferTransactionExample.java new file mode 100644 index 000000000..152307530 --- /dev/null +++ b/examples/src/main/java/LazyCreateTransferTransactionExample.java @@ -0,0 +1,147 @@ +import com.hedera.hashgraph.sdk.*; +import io.github.cdimascio.dotenv.Dotenv; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeoutException; + +public class LazyCreateTransferTransactionExample { + // see `.env.sample` in the repository root for how to specify these values + // or set environment variables with the same names + private static final AccountId OPERATOR_ID = AccountId.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_ID"))); + private static final PrivateKey OPERATOR_KEY = PrivateKey.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_KEY"))); + // HEDERA_NETWORK defaults to testnet if not specified in dotenv + private static final String HEDERA_NETWORK = Dotenv.load().get("HEDERA_NETWORK", "testnet"); + + private LazyCreateTransferTransactionExample() { + } + + /* + Lazy-create a new account using a public-address via a `TransferTransaction`. + Reference: [HIP-583 Expand alias support in CryptoCreate & CryptoTransfer Transactions](https://hips.hedera.com/hip/hip-583) + ## Example 2 + - Create an ECSDA private key + - Extract the ECDSA public key + - Extract the Ethereum public address + - Add function to calculate the Ethereum Address to in SDK + - Ethereum account address / public-address - This is the rightmost 20 bytes of the 32 byte Keccak-256 hash of the ECDSA public key of the account. This calculation is in the manner described by the Ethereum Yellow Paper. + - Use the `TransferTransaction` + - Populate the `FromAddress` with the sender Hedera AccountID + - Populate the `ToAddress` with Ethereum public address + - Note: Can transfer from public address to public address in the `TransferTransaction` for complete accounts. Transfers from hollow accounts will not work because the hollow account does not have a public key assigned to authorize transfers out of the account + - Sign the `TransferTransaction` transaction using an existing Hedera account and key paying for the transaction fee + - The `AccountCreateTransaction` is executed as a child transaction triggered by the `TransferTransaction` + - The Hedera Account that was created has a public address the user specified in the TransferTransaction ToAddress + - Will not have a public key at this stage + - Cannot do anything besides receive tokens or hbars + - The alias property of the account does not have the public address + - Referred to as a hollow account + - To get the new account ID ask for the child receipts or child records for the parent transaction ID of the `TransferTransaction` + - Get the `AccountInfo` and verify the account is a hollow account with the supplied public address (may need to verify with mirror node API) + - To enhance the hollow account to have a public key the hollow account needs to be specified as a transaction fee payer in a HAPI transaction + - Create a HAPI transaction and assign the new hollow account as the transaction fee payer + - Sign with the private key that corresponds to the public key on the hollow account + - Get the `AccountInfo` for the account and return the public key on the account to show it is a complete account + */ + public static void main(String[] args) throws PrecheckStatusException, TimeoutException, ReceiptStatusException, InterruptedException, IOException { +// Client client = Client.forName(HEDERA_NETWORK); + Client client = Client.forNetwork(Collections.singletonMap("127.0.0.1:50211", AccountId.fromString("0.0.3"))).setMirrorNetwork(List.of("127.0.0.1:5600")); + + // Defaults the operator account ID and key such that all generated transactions will be paid for + // by this account and be signed by this key + client.setOperator(OPERATOR_ID, OPERATOR_KEY); + + /* + * Step 1 + * Create an ECSDA private key + */ + PrivateKey privateKey = PrivateKey.generateECDSA(); + + /* + * Step 2 + * Extract the ECDSA public key + */ + PublicKey publicKey = privateKey.getPublicKey(); + + /* + * Step 3 + * Extract the Ethereum public address + */ + EvmAddress evmAddress = publicKey.toEvmAddress(); + System.out.println(evmAddress); + + /* + * Step 4 + * Use the `AccountCreateTransaction` and set the EVM address field to the Ethereum public address + */ + TransferTransaction transferTransaction = new TransferTransaction() + .addHbarTransfer(OPERATOR_ID, Hbar.from(10).negated()) + .addHbarTransfer(AccountId.fromEvmAddress(evmAddress.toString()), Hbar.from(10)) + .freezeWith(client); + + /* + * Step 5 + * Sign the `TransferTransaction` transaction using an existing Hedera account and key paying for the transaction fee + */ + TransactionResponse response = transferTransaction.execute(client); + + /* + * Step 6 + * To get the new account ID ask for the child receipts or child records for the parent transaction ID of the `TransferTransaction` + * - The `AccountCreateTransaction` is executed as a child transaction triggered by the `TransferTransaction` + */ + TransactionReceipt receipt = new TransactionReceiptQuery() + .setTransactionId(response.transactionId) + .setIncludeChildren(true) + .execute(client); + + AccountId newAccountId = receipt.children.get(0).accountId; + System.out.println(newAccountId); + + /* + * Step 7 + * Get the `AccountInfo` and verify the account is a hollow account with the supplied public address (may need to verify with mirror node API) + * The Hedera Account that was created has a public address the user specified in the TransferTransaction ToAddress + - Will not have a public key at this stage + - Cannot do anything besides receive tokens or hbars + - The alias property of the account does not have the public address + - Referred to as a hollow account + */ + AccountInfo accountInfo = new AccountInfoQuery() + .setAccountId(newAccountId) + .execute(client); + + if (((KeyList) accountInfo.key).isEmpty()) { + System.out.println("The newly created account is a hollow account"); + } else { + System.out.println("Not a hollow account"); + } + + /* + * Step 8 + * Create a HAPI transaction and assign the new hollow account as the transaction fee payer + * - To enhance the hollow account to have a public key the hollow account needs to be specified as a transaction fee payer in a HAPI transaction + */ + TransactionReceipt receipt2 = new TopicCreateTransaction() + .setTransactionId(TransactionId.generate(newAccountId)) + .setTopicMemo("Memo") + .freezeWith(client) + .sign(privateKey) + .execute(client) + .getReceipt(client); + System.out.println("Topic id = " + receipt2.topicId); + + /* + * + * Step 9 + * Get the `AccountInfo` for the account and return the public key on the account to show it is a complete account + */ + AccountInfo accountInfo2 = new AccountInfoQuery() + .setAccountId(newAccountId) + .execute(client); + + System.out.println("The public key of the newly created and now complete account: " + accountInfo2.key); + } +} From 837504192d22ce0d4eaba61404fd53e565839ec1 Mon Sep 17 00:00:00 2001 From: Nikola Genov Date: Wed, 11 Jan 2023 16:57:54 +0200 Subject: [PATCH 07/14] HIP-583 - AccountId fromEvmAddress overloads Signed-off-by: Nikola Genov --- .../LazyCreateTransferTransactionExample.java | 2 +- .../com/hedera/hashgraph/sdk/AccountId.java | 24 ++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/examples/src/main/java/LazyCreateTransferTransactionExample.java b/examples/src/main/java/LazyCreateTransferTransactionExample.java index 152307530..1a027abfc 100644 --- a/examples/src/main/java/LazyCreateTransferTransactionExample.java +++ b/examples/src/main/java/LazyCreateTransferTransactionExample.java @@ -78,7 +78,7 @@ public static void main(String[] args) throws PrecheckStatusException, TimeoutEx */ TransferTransaction transferTransaction = new TransferTransaction() .addHbarTransfer(OPERATOR_ID, Hbar.from(10).negated()) - .addHbarTransfer(AccountId.fromEvmAddress(evmAddress.toString()), Hbar.from(10)) + .addHbarTransfer(AccountId.fromEvmAddress(evmAddress), Hbar.from(10)) .freezeWith(client); /* diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java index 1a8587bb4..d36bef38b 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java @@ -177,13 +177,35 @@ public static AccountId fromEvmAddress(String evmAddress) { * @return the account id object */ public static AccountId fromEvmAddress(String evmAddress, @Nonnegative long shard, @Nonnegative long realm) { + return fromEvmAddress(EvmAddress.fromString(evmAddress), shard, realm); + } + + /** + * Retrieve the account id from an EVM address. + * + * @param evmAddress an EvmAddress instance + * @return the account id object + */ + public static AccountId fromEvmAddress(EvmAddress evmAddress) { + return fromEvmAddress(evmAddress, 0, 0); + } + + /** + * Retrieve the account id from an EVM address. + * + * @param evmAddress an EvmAddress instance + * @param shard the shard part of the account id + * @param realm the shard realm of the account id + * @return the account id object + */ + public static AccountId fromEvmAddress(EvmAddress evmAddress, @Nonnegative long shard, @Nonnegative long realm) { return new AccountId( shard, realm, 0, null, null, - EvmAddress.fromString(evmAddress) + evmAddress ); } From 9f956350f9b5c55cdb8ffba7b73333048e8333d4 Mon Sep 17 00:00:00 2001 From: Nikola Genov Date: Mon, 16 Jan 2023 15:28:32 +0200 Subject: [PATCH 08/14] HIP-583 - AccountCreationWays Example Signed-off-by: Nikola Genov --- .../main/java/AccountCreationWaysExample.java | 66 +++++++++++++++++++ .../com/hedera/hashgraph/sdk/EvmAddress.java | 3 +- .../hashgraph/sdk/TransferTransaction.java | 12 ++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 examples/src/main/java/AccountCreationWaysExample.java diff --git a/examples/src/main/java/AccountCreationWaysExample.java b/examples/src/main/java/AccountCreationWaysExample.java new file mode 100644 index 000000000..a8150c240 --- /dev/null +++ b/examples/src/main/java/AccountCreationWaysExample.java @@ -0,0 +1,66 @@ +import com.hedera.hashgraph.sdk.*; +import io.github.cdimascio.dotenv.Dotenv; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeoutException; + +public class AccountCreationWaysExample { + // see `.env.sample` in the repository root for how to specify these values + // or set environment variables with the same names + private static final AccountId OPERATOR_ID = AccountId.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_ID"))); + private static final PrivateKey OPERATOR_KEY = PrivateKey.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_KEY"))); + // HEDERA_NETWORK defaults to testnet if not specified in dotenv + private static final String HEDERA_NETWORK = Dotenv.load().get("HEDERA_NETWORK", "testnet"); + + private AccountCreationWaysExample() { + } + + /* + Reference: [HIP-583 Expand alias support in CryptoCreate & CryptoTransfer Transactions](https://hips.hedera.com/hip/hip-583) + ## In Hedera we have the concept of 4 different account representations + - an account can have an account ID in shard.realm.accountNumber format (0.0.10) + - an account can have a public key alias in 0.0.CIQNOWUYAGBLCCVX2VF75U6JMQDTUDXBOLZ5VJRDEWXQEGTI64DVCGQ format + - an account can have an AccountId that is represented in 0x000000000000000000000000000000000000000a (for account ID 0.0.10) long zero format + - an account can be represented by an Ethereum public address 0xb794f5ea0ba39494ce839613fffba74279579268 + */ + public static void main(String[] args) throws PrecheckStatusException, TimeoutException, ReceiptStatusException, InterruptedException, IOException { + //Client client = Client.forName(HEDERA_NETWORK); + Client client = Client.forNetwork(Collections.singletonMap("127.0.0.1:50211", AccountId.fromString("0.0.3"))).setMirrorNetwork(List.of("127.0.0.1:5600")); + + // Defaults the operator account ID and key such that all generated transactions will be paid for by this account and be signed by this key + client.setOperator(OPERATOR_ID, OPERATOR_KEY); + + /* + * Account ID - shard.realm.number format, i.e. `0.0.10` with the corresponding `0x000000000000000000000000000000000000000a` ethereum address + */ + AccountId hederaFormat = AccountId.fromString("0.0.10"); + System.out.println("Account ID: " + hederaFormat); + System.out.println("Account 0.0.10 corresponding Long-Zero address: " + hederaFormat.toSolidityAddress()); + + /* + * Hedera Long-Form Account ID - 0.0.aliasPublicKey, i.e. `0.0.CIQNOWUYAGBLCCVX2VF75U6JMQDTUDXBOLZ5VJRDEWXQEGTI64DVCGQ` + */ + PrivateKey privateKey = PrivateKey.generateECDSA(); + PublicKey publicKey = privateKey.getPublicKey(); + + // Assuming that the target shard and realm are known. + // For now they are virtually always 0. + AccountId aliasAccountId = publicKey.toAccountId(0, 0); + System.out.println("Hedera Long-Form Account ID: " + aliasAccountId.toString()); + + /* + * Hedera Account Long-Zero address - 0x000000000000000000000000000000000000000a (for accountId 0.0.10) + */ + AccountId longZeroAddress = AccountId.fromString("0x000000000000000000000000000000000000000a"); + System.out.println("Hedera Account Long-Zero address: " + longZeroAddress); + + /* + * Ethereum Account Address / public-address - 0xb794f5ea0ba39494ce839613fffba74279579268 + */ + AccountId evmAddress = AccountId.fromString("0xb794f5ea0ba39494ce839613fffba74279579268"); + System.out.println("Ethereum Account Address / public-address: " + evmAddress); + } +} diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/EvmAddress.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/EvmAddress.java index 6d214c14a..0122b213f 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/EvmAddress.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/EvmAddress.java @@ -41,7 +41,8 @@ public EvmAddress(byte[] bytes) { } public static EvmAddress fromString(String text) { - return new EvmAddress(Hex.decode(text)); + String address = text.startsWith("0x") ? text.substring(2) : text; + return new EvmAddress(Hex.decode(address)); } @Nullable diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/TransferTransaction.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/TransferTransaction.java index befc019e2..a32159297 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/TransferTransaction.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/TransferTransaction.java @@ -421,6 +421,18 @@ private TransferTransaction doAddHbarTransfer(AccountId accountId, Hbar value, b return this; } + /** + * Add a non approved hbar transfer to an EVM address. + * + * @param evmAddress the EVM address + * @param value the value + * @return the updated transaction + */ + public TransferTransaction addHbarTransfer(EvmAddress evmAddress, Hbar value) { + AccountId accountId = AccountId.fromEvmAddress(evmAddress); + return doAddHbarTransfer(accountId, value, false); + } + /** * Add a non approved hbar transfer. * From 95d734d9c91ced04c410947f7d93eb177936812a Mon Sep 17 00:00:00 2001 From: dikel Date: Tue, 17 Jan 2023 14:30:52 +0200 Subject: [PATCH 09/14] Change the HIP-583 examples to use Previewnet Signed-off-by: dikel --- .../java/AccountCreateEvmAddressExample.java | 6 ++-- .../java/CreateAccountWithAliasExample.java | 35 ++----------------- .../LazyCreateAccountTransactionExample.java | 3 +- .../LazyCreateTransferTransactionExample.java | 3 +- .../sdk/AccountCreateTransaction.java | 26 ++++++++++++-- .../hedera/hashgraph/sdk/AccountInfoTest.snap | 4 +-- .../hedera/hashgraph/sdk/FileInfoTest.snap | 4 +-- 7 files changed, 35 insertions(+), 46 deletions(-) diff --git a/examples/src/main/java/AccountCreateEvmAddressExample.java b/examples/src/main/java/AccountCreateEvmAddressExample.java index 037dc679c..15f72fcc1 100644 --- a/examples/src/main/java/AccountCreateEvmAddressExample.java +++ b/examples/src/main/java/AccountCreateEvmAddressExample.java @@ -41,8 +41,7 @@ private AccountCreateEvmAddressExample() { - Verify the evm address provided for the account matches what is in the mirror node */ public static void main(String[] args) throws PrecheckStatusException, TimeoutException, ReceiptStatusException, InterruptedException, IOException { -// Client client = Client.forName(HEDERA_NETWORK); - Client client = Client.forNetwork(Collections.singletonMap("127.0.0.1:50211", AccountId.fromString("0.0.3"))).setMirrorNetwork(List.of("127.0.0.1:5600")); + Client client = Client.forName(HEDERA_NETWORK); // Defaults the operator account ID and key such that all generated transactions will be paid for // by this account and be signed by this key @@ -107,7 +106,8 @@ public static void main(String[] args) throws PrecheckStatusException, TimeoutEx * Verify the evm address provided for the account matches what is in the mirror node */ Thread.sleep(5000); - URL url = new URL("http://127.0.0.1:5551/api/v1/accounts?account.id=" + newAccountId); + String link = "https://" + HEDERA_NETWORK + ".mirrornode.hedera.com/api/v1/accounts?account.id=" + newAccountId; + URL url = new URL(link); HttpURLConnection con = (HttpURLConnection)url.openConnection(); con.setRequestMethod("GET"); con.setRequestProperty("Accept", "application/json"); diff --git a/examples/src/main/java/CreateAccountWithAliasExample.java b/examples/src/main/java/CreateAccountWithAliasExample.java index 2ae89017c..e4a6ad480 100644 --- a/examples/src/main/java/CreateAccountWithAliasExample.java +++ b/examples/src/main/java/CreateAccountWithAliasExample.java @@ -51,8 +51,7 @@ private CreateAccountWithAliasExample() { - Show the public key and the public key alias are the same on the account */ public static void main(String[] args) throws PrecheckStatusException, TimeoutException, ReceiptStatusException, InterruptedException, IOException { -// Client client = Client.forName(HEDERA_NETWORK); - Client client = Client.forNetwork(Collections.singletonMap("127.0.0.1:50211", AccountId.fromString("0.0.3"))).setMirrorNetwork(List.of("127.0.0.1:5600")); + Client client = Client.forName(HEDERA_NETWORK); // Defaults the operator account ID and key such that all generated transactions will be paid for // by this account and be signed by this key @@ -131,7 +130,8 @@ public static void main(String[] args) throws PrecheckStatusException, TimeoutEx * Show this account has a corresponding EVM address in the mirror node */ Thread.sleep(5000); - URL url = new URL("http://127.0.0.1:5551/api/v1/accounts?account.id=" + newAccountId); + String link = "https://" + HEDERA_NETWORK + ".mirrornode.hedera.com/api/v1/accounts?account.id=" + newAccountId; + URL url = new URL(link); HttpURLConnection con = (HttpURLConnection)url.openConnection(); con.setRequestMethod("GET"); con.setRequestProperty("Accept", "application/json"); @@ -222,34 +222,5 @@ public static void main(String[] args) throws PrecheckStatusException, TimeoutEx } else { System.out.println("The public key and the public key alias differ"); } - - /* - * Step 9 - * Show this account has a corresponding EVM address in the mirror node - */ - Thread.sleep(5000); - URL url2 = new URL("http://127.0.0.1:5551/api/v1/accounts?account.id=" + newAccountId2); - HttpURLConnection con2 = (HttpURLConnection)url2.openConnection(); - con2.setRequestMethod("GET"); - con2.setRequestProperty("Accept", "application/json"); - try(BufferedReader br = new BufferedReader(new InputStreamReader(con2.getInputStream(), StandardCharsets.UTF_8))) { - StringBuilder builder = new StringBuilder(); - String responseLine; - while ((responseLine = br.readLine()) != null) { - builder.append(responseLine.trim()); - } - JsonObject jsonObject = JsonParser.parseString(builder.toString()).getAsJsonObject(); - String mirrorNodeEvmAddress = jsonObject - .getAsJsonArray("accounts") - .get(0).getAsJsonObject() - .get("evm_address") - .toString(); - - if (mirrorNodeEvmAddress.equals("null")) { - System.out.println("The EVM address of the account is missing in the mirror node"); - } else { - System.out.println("The account has a corresponding EVM address in the mirror node"); - } - } } } diff --git a/examples/src/main/java/LazyCreateAccountTransactionExample.java b/examples/src/main/java/LazyCreateAccountTransactionExample.java index 0e465dd72..b574bec1f 100644 --- a/examples/src/main/java/LazyCreateAccountTransactionExample.java +++ b/examples/src/main/java/LazyCreateAccountTransactionExample.java @@ -43,8 +43,7 @@ private LazyCreateAccountTransactionExample() { - Get the `AccountInfo` and show that the account is now a complete account i.e. returns a public key of the account */ public static void main(String[] args) throws PrecheckStatusException, TimeoutException, ReceiptStatusException, InterruptedException, IOException { -// Client client = Client.forName(HEDERA_NETWORK); - Client client = Client.forNetwork(Collections.singletonMap("127.0.0.1:50211", AccountId.fromString("0.0.3"))).setMirrorNetwork(List.of("127.0.0.1:5600")); + Client client = Client.forName(HEDERA_NETWORK); // Defaults the operator account ID and key such that all generated transactions will be paid for // by this account and be signed by this key diff --git a/examples/src/main/java/LazyCreateTransferTransactionExample.java b/examples/src/main/java/LazyCreateTransferTransactionExample.java index 1a027abfc..f14aa5673 100644 --- a/examples/src/main/java/LazyCreateTransferTransactionExample.java +++ b/examples/src/main/java/LazyCreateTransferTransactionExample.java @@ -46,8 +46,7 @@ private LazyCreateTransferTransactionExample() { - Get the `AccountInfo` for the account and return the public key on the account to show it is a complete account */ public static void main(String[] args) throws PrecheckStatusException, TimeoutException, ReceiptStatusException, InterruptedException, IOException { -// Client client = Client.forName(HEDERA_NETWORK); - Client client = Client.forNetwork(Collections.singletonMap("127.0.0.1:50211", AccountId.fromString("0.0.3"))).setMirrorNetwork(List.of("127.0.0.1:5600")); + Client client = Client.forName(HEDERA_NETWORK); // Defaults the operator account ID and key such that all generated transactions will be paid for // by this account and be signed by this key diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountCreateTransaction.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountCreateTransaction.java index 75e545d33..b2185d4f5 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountCreateTransaction.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountCreateTransaction.java @@ -400,10 +400,30 @@ public AccountCreateTransaction setEvmAddress(EvmAddress evmAddress) { return this; } + /** + * NOT YET SUPPORTED ON MAINNET AS OF DEC/23/2022 + *

+ * The ethereum account 20-byte EVM address to be used as the account's alias. This EVM address may be either + * the encoded form of the shard.realm.num or the keccak-256 hash of a ECDSA_SECP256K1 primitive key. + *

+ * A given alias can map to at most one account on the network at a time. This uniqueness will be enforced + * relative to aliases currently on the network at alias assignment. + *

+ * If a transaction creates an account using an alias, any further crypto transfers to that alias will + * simply be deposited in that account, without creating anything, and with no creation fee being charged. + * + * @param evmAddress The ethereum account 20-byte EVM address + * @return {@code this} + * @throws IllegalArgumentException when evmAddress is invalid or doesn't have "0x" prefix + */ public AccountCreateTransaction setEvmAddress(String evmAddress) { - // Remove the "0x" prefix - EvmAddress address = EvmAddress.fromString(evmAddress.substring(2)); - return this.setEvmAddress(address); + if (evmAddress.startsWith("0x") || evmAddress.length() == 42) { + // Remove the "0x" prefix + EvmAddress address = EvmAddress.fromString(evmAddress.substring(2)); + return this.setEvmAddress(address); + } else { + throw new IllegalArgumentException("evmAddress must be an a valid EVM address with \"0x\" prefix"); + } } /** diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountInfoTest.snap b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountInfoTest.snap index 11e3c7785..3520ebb5b 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountInfoTest.snap +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountInfoTest.snap @@ -14,5 +14,5 @@ com.hedera.hashgraph.sdk.AccountInfoTest.toBytes=[ com.hedera.hashgraph.sdk.AccountInfoTest.toProtobuf=[ - "# com.hedera.hashgraph.sdk.proto.CryptoGetInfoResponse$AccountInfo@57c9441\naccount_i_d {\n account_num: 1\n realm_num: 0\n shard_num: 0\n}\nauto_renew_period {\n seconds: 604800\n}\nbalance: 3\ndeleted: true\nethereum_nonce: 1001\nexpiration_time {\n nanos: 6000000\n seconds: 0\n}\ngenerate_receive_record_threshold: 5\ngenerate_send_record_threshold: 4\nkey {\n ed25519: \"\\340\\310\\354\\'X\\245\\207\\237\\372\\302&\\241<\\fQky\\236r\\343QA\\240\\335\\202\\217\\224\\323y\\210\\244\\267\"\n}\nledger_id: \"\\002\"\nlive_hashes {\n account_id {\n account_num: 10\n realm_num: 0\n shard_num: 0\n }\n duration {\n seconds: 950400\n }\n hash: \"\\000\\001\\002\"\n keys {\n keys {\n ed25519: \"\\340\\310\\354\\'X\\245\\207\\237\\372\\302&\\241<\\fQky\\236r\\343QA\\240\\335\\202\\217\\224\\323y\\210\\244\\267\"\n }\n }\n}\nowned_nfts: 0\nproxy_account_i_d {\n account_num: 8\n realm_num: 0\n shard_num: 0\n}\nproxy_received: 2\nreceiver_sig_required: true" -] \ No newline at end of file + "# com.hedera.hashgraph.sdk.proto.CryptoGetInfoResponse$AccountInfo@df1d71e3\naccount_i_d {\n account_num: 1\n realm_num: 0\n shard_num: 0\n}\nauto_renew_period {\n seconds: 604800\n}\nbalance: 3\ndeleted: true\nethereum_nonce: 1001\nexpiration_time {\n nanos: 6000000\n seconds: 0\n}\ngenerate_receive_record_threshold: 5\ngenerate_send_record_threshold: 4\nkey {\n ed25519: \"\\340\\310\\354\\'X\\245\\207\\237\\372\\302&\\241<\\fQky\\236r\\343QA\\240\\335\\202\\217\\224\\323y\\210\\244\\267\"\n}\nledger_id: \"\\002\"\nlive_hashes {\n account_id {\n account_num: 10\n realm_num: 0\n shard_num: 0\n }\n duration {\n seconds: 950400\n }\n hash: \"\\000\\001\\002\"\n keys {\n keys {\n ed25519: \"\\340\\310\\354\\'X\\245\\207\\237\\372\\302&\\241<\\fQky\\236r\\343QA\\240\\335\\202\\217\\224\\323y\\210\\244\\267\"\n }\n }\n}\nowned_nfts: 0\nproxy_account_i_d {\n account_num: 8\n realm_num: 0\n shard_num: 0\n}\nproxy_received: 2\nreceiver_sig_required: true" +] diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/FileInfoTest.snap b/sdk/src/test/java/com/hedera/hashgraph/sdk/FileInfoTest.snap index f82cadf2a..817e1c608 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/FileInfoTest.snap +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/FileInfoTest.snap @@ -14,5 +14,5 @@ com.hedera.hashgraph.sdk.FileInfoTest.toBytes=[ com.hedera.hashgraph.sdk.FileInfoTest.toProtobuf=[ - "# com.hedera.hashgraph.sdk.proto.FileGetInfoResponse$FileInfo@e51665b9\ndeleted: true\nexpiration_time {\n nanos: 3000000\n seconds: 0\n}\nfile_i_d {\n file_num: 1\n realm_num: 0\n shard_num: 0\n}\nkeys {\n keys {\n ed25519: \"\\340\\310\\354\\'X\\245\\207\\237\\372\\302&\\241<\\fQky\\236r\\343QA\\240\\335\\202\\217\\224\\323y\\210\\244\\267\"\n }\n}\nledger_id: \"\\000\"\nsize: 2" -] \ No newline at end of file + "# com.hedera.hashgraph.sdk.proto.FileGetInfoResponse$FileInfo@5de8e70f\ndeleted: true\nexpiration_time {\n nanos: 3000000\n seconds: 0\n}\nfile_i_d {\n file_num: 1\n realm_num: 0\n shard_num: 0\n}\nkeys {\n keys {\n ed25519: \"\\340\\310\\354\\'X\\245\\207\\237\\372\\302&\\241<\\fQky\\236r\\343QA\\240\\335\\202\\217\\224\\323y\\210\\244\\267\"\n }\n}\nledger_id: \"\\000\"\nsize: 2" +] From 196e239fd495c80c5a001399f59c1b9d23b010f4 Mon Sep 17 00:00:00 2001 From: Nikola Genov Date: Tue, 17 Jan 2023 16:40:21 +0200 Subject: [PATCH 10/14] HIP-583 - TransferUsingEvmAddressExample Signed-off-by: Nikola Genov --- CHANGELOG.md | 5 + .../main/java/AccountCreationWaysExample.java | 21 +-- .../java/TransferUsingEvmAddressExample.java | 129 ++++++++++++++++++ 3 files changed, 135 insertions(+), 20 deletions(-) create mode 100644 examples/src/main/java/TransferUsingEvmAddressExample.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 76794b2e3..22c43fd6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,10 +11,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `TransactionRecord.evmAddress` - `PublicKeyECDSA.toEvmAddress()` - `AccountCreateTransaction.setEvmAddress()` + - `AccountId.fromEvmAddress()` + - `AccountId.fromString()` now supports EVM address + - `TransferTransaction.addHbarTransfer()` now supports EVM address - `AccountCreateEvmAddressExample` - `CreateAccountWithAliasExample` - `LazyCreateAccountTransactionExample` - `LazyCreateTransferTransactionExample` + - `TransferUsingEvmAddressExample` + - `AccountCreationWaysExample` ### Deprecated diff --git a/examples/src/main/java/AccountCreationWaysExample.java b/examples/src/main/java/AccountCreationWaysExample.java index a8150c240..423b4d2f0 100644 --- a/examples/src/main/java/AccountCreationWaysExample.java +++ b/examples/src/main/java/AccountCreationWaysExample.java @@ -1,19 +1,6 @@ import com.hedera.hashgraph.sdk.*; -import io.github.cdimascio.dotenv.Dotenv; - -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.TimeoutException; public class AccountCreationWaysExample { - // see `.env.sample` in the repository root for how to specify these values - // or set environment variables with the same names - private static final AccountId OPERATOR_ID = AccountId.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_ID"))); - private static final PrivateKey OPERATOR_KEY = PrivateKey.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_KEY"))); - // HEDERA_NETWORK defaults to testnet if not specified in dotenv - private static final String HEDERA_NETWORK = Dotenv.load().get("HEDERA_NETWORK", "testnet"); private AccountCreationWaysExample() { } @@ -26,13 +13,7 @@ private AccountCreationWaysExample() { - an account can have an AccountId that is represented in 0x000000000000000000000000000000000000000a (for account ID 0.0.10) long zero format - an account can be represented by an Ethereum public address 0xb794f5ea0ba39494ce839613fffba74279579268 */ - public static void main(String[] args) throws PrecheckStatusException, TimeoutException, ReceiptStatusException, InterruptedException, IOException { - //Client client = Client.forName(HEDERA_NETWORK); - Client client = Client.forNetwork(Collections.singletonMap("127.0.0.1:50211", AccountId.fromString("0.0.3"))).setMirrorNetwork(List.of("127.0.0.1:5600")); - - // Defaults the operator account ID and key such that all generated transactions will be paid for by this account and be signed by this key - client.setOperator(OPERATOR_ID, OPERATOR_KEY); - + public static void main(String[] args) { /* * Account ID - shard.realm.number format, i.e. `0.0.10` with the corresponding `0x000000000000000000000000000000000000000a` ethereum address */ diff --git a/examples/src/main/java/TransferUsingEvmAddressExample.java b/examples/src/main/java/TransferUsingEvmAddressExample.java new file mode 100644 index 000000000..47d21cdfa --- /dev/null +++ b/examples/src/main/java/TransferUsingEvmAddressExample.java @@ -0,0 +1,129 @@ +import com.hedera.hashgraph.sdk.*; +import io.github.cdimascio.dotenv.Dotenv; + +import java.io.IOException; +import java.util.Objects; +import java.util.concurrent.TimeoutException; + +public class TransferUsingEvmAddressExample { + // see `.env.sample` in the repository root for how to specify these values + // or set environment variables with the same names + private static final AccountId OPERATOR_ID = AccountId.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_ID"))); + private static final PrivateKey OPERATOR_KEY = PrivateKey.fromString(Objects.requireNonNull(Dotenv.load().get("OPERATOR_KEY"))); + // HEDERA_NETWORK defaults to testnet if not specified in dotenv + private static final String HEDERA_NETWORK = Dotenv.load().get("HEDERA_NETWORK", "testnet"); + + private TransferUsingEvmAddressExample() { + } + + /* + Transfer HBAR or tokens to a Hedera account using their public-address. + Reference: [HIP-583 Expand alias support in CryptoCreate & CryptoTransfer Transactions](https://hips.hedera.com/hip/hip-583) + ## Example 1 + - Create an ECSDA private key + - Extract the ECDSA public key + - Extract the Ethereum public address + - Add function to calculate the Ethereum Address to example in SDK + - Ethereum account address / public-address - This is the rightmost 20 bytes of the 32 byte Keccak-256 hash of the ECDSA public key of the account. This calculation is in the manner described by the Ethereum Yellow Paper. + - Transfer tokens using the `TransferTransaction` to the Etherum Account Address + - The From field should be a complete account that has a public address + - The To field should be to a public address (to create a new account) + - Get the child receipt or child record to return the Hedera Account ID for the new account that was created + - Get the `AccountInfo` on the new account and show it is a hollow account by not having a public key + - This is a hollow account in this state + - Use the hollow account as a transaction fee payer in a HAPI transaction + - Sign the transaction with ECDSA private key + - Get the `AccountInfo` of the account and show the account is now a complete account by returning the public key on the account + */ + public static void main(String[] args) throws PrecheckStatusException, TimeoutException, ReceiptStatusException, InterruptedException, IOException { + Client client = Client.forName(HEDERA_NETWORK); + + // Defaults the operator account ID and key such that all generated transactions will be paid for by this account and be signed by this key + client.setOperator(OPERATOR_ID, OPERATOR_KEY); + + /* + * Step 1 + * Create an ECSDA private key + */ + PrivateKey privateKey = PrivateKey.generateECDSA(); + + /* + * Step 2 + * Extract the ECDSA public key + */ + PublicKey publicKey = privateKey.getPublicKey(); + + /* + * Step 3 + * Extract the Ethereum public address + */ + EvmAddress evmAddress = publicKey.toEvmAddress(); + System.out.println("Corresponding evm address: " + evmAddress); + + /* + * Step 4 + * Transfer tokens using the `TransferTransaction` to the Etherum Account Address + * - The From field should be a complete account that has a public address + * - The To field should be to a public address (to create a new account) + */ + TransferTransaction transferTx = new TransferTransaction() + .addHbarTransfer(OPERATOR_ID, Hbar.from(10).negated()) + .addHbarTransfer(evmAddress, Hbar.from(10)) + .freezeWith(client); + + TransferTransaction transferTxSign = transferTx.sign(OPERATOR_KEY); + TransactionResponse transferTxSubmit = transferTxSign.execute(client); + + /* + * Step 5 + * Get the child receipt or child record to return the Hedera Account ID for the new account that was created + */ + TransactionReceipt receipt = new TransactionReceiptQuery() + .setTransactionId(transferTxSubmit.transactionId) + .setIncludeChildren(true) + .execute(client); + + AccountId newAccountId = receipt.children.get(0).accountId; + System.out.println(newAccountId); + + /* + * Step 6 + * Get the `AccountInfo` on the new account and show it is a hollow account by not having a public key + */ + AccountInfo accountInfo = new AccountInfoQuery() + .setAccountId(newAccountId) + .execute(client); + + System.out.println("accountInfo: " + accountInfo); + + /* + * Step 7 + * Use the hollow account as a transaction fee payer in a HAPI transaction + */ + client.setOperator(newAccountId, privateKey); + PublicKey newPublicKey = PrivateKey.generateED25519().getPublicKey(); + + AccountCreateTransaction transaction = new AccountCreateTransaction() + .setKey(newPublicKey) + .freezeWith(client); + + /* + * Step 8 + * Sign the transaction with ECDSA private key + */ + AccountCreateTransaction transactionSign = transaction.sign(privateKey); + TransactionResponse transactionSubmit = transactionSign.execute(client); + TransactionReceipt status = transactionSubmit.getReceipt(client); + System.out.println(status); + + /* + * Step 9 + * Get the `AccountInfo` of the account and show the account is now a complete account by returning the public key on the account + */ + AccountInfo accountInfo2 = new AccountInfoQuery() + .setAccountId(newAccountId) + .execute(client); + + System.out.println("The public key of the newly created and now complete account: " + accountInfo2.key); + } +} From b05cd1825bb67f19d948c36f6f05c3e26e52f76e Mon Sep 17 00:00:00 2001 From: Nikola Genov Date: Mon, 30 Jan 2023 18:58:55 +0200 Subject: [PATCH 11/14] HIP-631 - initial commit Signed-off-by: Nikola Genov --- .../com/hedera/hashgraph/sdk/AccountId.java | 25 +++- .../hedera/hashgraph/sdk/VirtualAddress.java | 132 ++++++++++++++++++ .../hedera/hashgraph/sdk/AccountIdTest.java | 19 +++ 3 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 sdk/src/main/java/com/hedera/hashgraph/sdk/VirtualAddress.java diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java index 57dc0cd01..c574bb78e 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java @@ -25,9 +25,9 @@ import org.bouncycastle.util.encoders.Hex; import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.Arrays; -import java.util.Objects; +import java.util.*; import java.util.regex.Pattern; /** @@ -60,6 +60,9 @@ public final class AccountId implements Comparable { @Nullable public final EvmAddress aliasEvmAddress; + @Nonnull + public final List virtualAddresses; + @Nullable private final String checksum; @@ -99,6 +102,7 @@ public AccountId(@Nonnegative long shard, @Nonnegative long realm, @Nonnegative this.checksum = checksum; this.aliasKey = null; this.aliasEvmAddress = null; + this.virtualAddresses = new ArrayList<>(); } /** @@ -123,6 +127,7 @@ public AccountId(@Nonnegative long shard, @Nonnegative long realm, @Nonnegative this.checksum = checksum; this.aliasKey = aliasKey; this.aliasEvmAddress = aliasEvmAddress; + this.virtualAddresses = new ArrayList<>(); } /** @@ -213,6 +218,7 @@ AccountID toProtobuf() { var accountIdBuilder = AccountID.newBuilder() .setShardNum(shard) .setRealmNum(realm); + if (aliasKey != null) { accountIdBuilder.setAlias(aliasKey.toProtobufKey().toByteString()); } else if (aliasEvmAddress != null) { @@ -220,6 +226,12 @@ AccountID toProtobuf() { }else { accountIdBuilder.setAccountNum(num); } + + // TODO - waiting for protobuf update + //if (virtualAddresses != null && !virtualAddresses.isEmpty()) { + // accountIdBuilder.setVirtualAddresses(); + //} + return accountIdBuilder.build(); } @@ -293,7 +305,9 @@ public String toStringWithChecksum(Client client) { public int hashCode() { return Objects.hash( shard, realm, num, - (aliasKey != null) ? aliasKey.toBytes() : ((aliasEvmAddress != null) ? aliasEvmAddress.toBytes() : null) + (aliasKey != null) ? aliasKey.toBytes() : ((aliasEvmAddress != null) ? aliasEvmAddress.toBytes() : null), + // TODO - support multiple virtual addresses + !virtualAddresses.isEmpty() ? virtualAddresses.get(0).toBytes() : null ); } @@ -316,7 +330,10 @@ public boolean equals(Object o) { } return shard == otherId.shard && realm == otherId.realm && num == otherId.num && (aliasKey == null || aliasKey.equals(otherId.aliasKey)) && - (aliasEvmAddress == null || aliasEvmAddress.equals(otherId.aliasEvmAddress)); + (aliasEvmAddress == null || aliasEvmAddress.equals(otherId.aliasEvmAddress)) && + // TBD - if the addresses are the same but in different order should we consider them equal? + // Or should we sort the collections first? + virtualAddresses.equals(otherId.virtualAddresses); } @Override diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/VirtualAddress.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/VirtualAddress.java new file mode 100644 index 000000000..ea42f2b43 --- /dev/null +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/VirtualAddress.java @@ -0,0 +1,132 @@ +/*- + * + * Hedera Java SDK + * + * Copyright (C) 2020 - 2022 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.hedera.hashgraph.sdk; + +import com.google.common.base.MoreObjects; +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; + +import java.util.Objects; + +/** + * EVM virtual address. + */ +public final class VirtualAddress { + + /** + * The EVM address. + */ + public final String address; + + /** + * If true, then this is the default virtual address for a given account. + */ + public final boolean isDefault; + + /** + * Constructor. + * + * @param address the virtual address + * @param isDefault is it the default address + */ + public VirtualAddress( + String address, + boolean isDefault + ) { + this.address = address; + this.isDefault = isDefault; + } + + /** + * Retrieve the virtual address from a protobuf. + * + * @param virtualAddress the virtual address protobuf + * @return the virtual address object + */ + static VirtualAddress fromProtobuf(com.hedera.hashgraph.sdk.proto.VirtualAddress virtualAddress) { + return new VirtualAddress( + virtualAddress.getAddress().toString(), + virtualAddress.getIsDefault() + ); + } + + /** + * Retrieve the virtual address from a protobuf byte array. + * + * @param bytes a byte array representing the protobuf + * @return the virtual address object + * @throws InvalidProtocolBufferException when there is an issue with the protobuf + */ + public static VirtualAddress fromBytes(byte[] bytes) throws InvalidProtocolBufferException { + return fromProtobuf(com.hedera.hashgraph.sdk.proto.VirtualAddress.parseFrom(bytes).toBuilder().build()); + } + + /** + * Convert a virtual address object into a protobuf. + * + * @return the protobuf object + */ + com.hedera.hashgraph.sdk.proto.VirtualAddress toProtobuf() { + var virtualAddressBuilder = com.hedera.hashgraph.sdk.proto.VirtualAddress.newBuilder() + .setAddress(ByteString.fromHex(address)) + .setIsDefault(isDefault); + + return virtualAddressBuilder.build(); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("address", address) + .add("default", isDefault) + .toString(); + } + + /** + * Extract a byte array representation. + * + * @return a byte array representation + */ + public byte[] toBytes() { + return toProtobuf().toByteArray(); + } + + + @Override + public int hashCode() { + // TODO - should addresses "0x123abc" and "123abc" be considered equal??? + return Objects.hash(address, isDefault); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (!(o instanceof VirtualAddress)) { + return false; + } + + VirtualAddress otherAddress = (VirtualAddress)o; + // TODO - should addresses "0x123abc" and "123abc" be considered equal??? + return address.equals(otherAddress.address) && isDefault == otherAddress.isDefault; + } +} diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.java b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.java index 7f32655f0..247a2cbea 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.java +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.java @@ -19,6 +19,7 @@ */ package com.hedera.hashgraph.sdk; +import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import io.github.jsonSnapshot.SnapshotMatcher; import org.bouncycastle.util.encoders.Hex; @@ -219,4 +220,22 @@ void toFromProtobufAliasEvmAddress() { void toSolidityAddress() { SnapshotMatcher.expect(new AccountId(5005).toSolidityAddress()).toMatchSnapshot(); } + + @Test + void equalsVirtualAddresses() { + var id1 = new AccountId(1, 2, 3); + var id2 = new AccountId(1, 2, 3); + + var address1 = "302a300506032b6570032100114e6abc371b82d1"; + var address2 = "302a300506032b6570032100114e6abc371b82d2"; + + id1.virtualAddresses.add(new VirtualAddress(address1, true)); + id1.virtualAddresses.add(new VirtualAddress(address2, false)); + + // TODO - swap address 1 and 2 + id2.virtualAddresses.add(new VirtualAddress(address1, true)); + id2.virtualAddresses.add(new VirtualAddress(address2, false)); + + assertThat(id2).isEqualTo(id1); + } } From 41561e2d951494f19294b9244345d21cd3efbc27 Mon Sep 17 00:00:00 2001 From: Nikola Genov Date: Tue, 31 Jan 2023 11:32:17 +0200 Subject: [PATCH 12/14] Fix failing tests Signed-off-by: Nikola Genov --- .../com/hedera/hashgraph/sdk/FileAppendTransactionTest.snap | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/FileAppendTransactionTest.snap b/sdk/src/test/java/com/hedera/hashgraph/sdk/FileAppendTransactionTest.snap index 6708bb14b..c36432156 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/FileAppendTransactionTest.snap +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/FileAppendTransactionTest.snap @@ -1,15 +1,15 @@ com.hedera.hashgraph.sdk.FileAppendTransactionTest.shouldGetAllSignatures=[ - "[{0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=40d079bcb4a9fbdf102051328ee5f3903e166c1dd7c1e748efc95a2fdd640e421c0a8e23709b61e4d8110451adecd71cd16d1293ce0e57ea974de5b6b2ef070e, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=0cbdeaac11d392081289fb67a93a7fd995e86f55764e45b3e5eefd2f64056a38b50e8478e64cb1af5c310c321478e09b60d641a6e898820625d2674dc54ce80e, }, 0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=1490ad50f0fb5af40ee1d823e4f4b2603c135b3c7979b1b0ee6a323ba494e0b5cca833157c1106b976c876b060249e7ee2db30a8566d8682a42fac2f5f4a3406, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=23a657e362da4b3ea29673c26d8b17b967c53528449d99b3154e1b81676dc8d0aa229b824f9e613803b3262bc9cecc6dc6e2fc01a21830fb1641b5ed03722e07, }, }, {0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=4b4ed404ef9a37752c070c5eb364b0df0fbe06afb0b64e0743d27767c26b1045e8532308288e2f1a40cced0782b87f20b6cfdcd8b9890c600c0e2146a48ace00, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=95444670cecb07fc452a4e3f350eca481e5462e3349a6741cd4e6746b21c66e67825c169f3b4cf82ab1853f1cf0acedc84b2f565346dc173a93f054c19966b08, }, 0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=ce2b975f698ca802721c80a3792fca39d73609afaa8961bb91da569463c50eecb07d7e26e7e8febb5163474139e94533e8eb7016e0c149e0823d7102ed2b0502, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=ea31e49f64fd41773561f81459a2381e0194788853e28ffb683caded7a675d386b2a228c67ec83bfc448f14ee4fd2eae41569f06006c515621e1f26514c9bf0a, }, }, {0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=0aedd8f92e68278823397cb0eddc1c07f1fd80c223781280a0ffb0eef21b516444e4521294ad380e8a46c7f22f1723eef8872ccf4d8aa415345e0a7fe1485c06, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=8cf7f0ae116557d5f4a5bbee82dee3cfe950c0ecedbce5d2a7b729dd7614d47c436e6951c401870f85dadd696160ecee1ab8e65aa607ca942051e78b8f09a406, }, 0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=47c3e240259603f3e7fa41ced3eb9931bc4350367aa6529994c048fb0aca1853630bf8fbbdf9b2768c52b91b5f5d669a4adab06ef0851107f6e8012d948ba90b, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=d1a4d3349a1bc7cd0242e09ed9b1811ea99fb6123826b946651ee8c9dd593eb40591697fad4360e3941c9eea55cd2173189df349aa16b9a11db62ed28de8ad06, }, }, {0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=aa009ad11594bb981504f8d4063c9d90bfb0bccc4bda8f9e3ffd326fc39e599fae94ba98110342a449437f7c848e2a9dd6de0d008e8d00c8387ff094c93c2700, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=5a2b40589f128f3bac99649d0aec7230e3c993130f36814c742ae37104e93d22e2b548d97e471f583d1c81bbcf6f916cc03f20375499e3a37b2c6b13a5a94507, }, 0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=63800201fd378e81946c73104907b0b0aa70ff5913889b21b4eac730e535f8acbf08f63da5824419fc14155d6fc19f23a53bfd3324d8baa68dc5d00e8974de07, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=084bdc8f8580a2ebcc0a5140f766aca111b5488092a41871d104834dda27d6b99288423835bc7114860ce6c740300ebe9f8ab576e7646097eee7d6692b90d109, }, }, {0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=645d9d66e90a104462741e2f49fe77d2edce5d49a033c9c51768a2fba6deda96a71ad95e00416bb5a8a07cfaf543a1fee8730c11af4a380d6f30ec88d2271c0d, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=2bc0f7e72aa2e953741815ac95135e50ece67543683e6da3a26bc95534d9ca538d802d567fcb154bf98001663dc46d8674ff4e9361021fbe2a55e83f9442f802, }, 0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=e83759154409ce22146e31ff826a3ee4940916784e5953c4c0502ef5c2f9e7ca2d114223c3461a491dfebdcc11e511e91400007a1dc3827b7b98c7225239460f, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=595653b3f5cedf84e845f0dc2c503aad94b259eee4c10ad32cd86976b246cd81726ae8edc35e41e9ebae9e27a3ed96aff524b9b04481fad2722fdab8a4ee5a0f, }, }, {0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=dea30ba3201c32f5c23afac9d5b013c4e41a30d08205d21a09722f5aebb0760b2452ba254eea5008de68411560081e94ccd78c5008353aa6bb64779e79078702, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=903762ba6159fcf940281d810a268980cdf2fa35683626d52e41ad18202492fef5f8de2002c49cb56ac9d9e78177823f1f97741634237943459c31540f801502, }, 0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=c463b37297427a620f739b3a420512f897745a8451315de360391b2f6879e644ba3a8597e4f6e3a1a135bf354bb0911fe421e0174f48b650f54e3fe86247e507, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=342e41dbd4e3ef300192767ffeb9b062b1fae68027153a84f151fdb1d3ce43592f275d87a7b90a9d6db6a67d32c6ec9e585ce199ed199cdcac0b4ef4ac12200f, }, }, {0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=9e4dcb75574c75c7e54cc76ff08bf9e6c28cb2e74f79eb4ed8e4f968e6829bd994d9fadff9fb265988de757b858e4921c7b4db119c31f6156a79eb62ffc4110c, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=195fdc0b4c9730139ede43d8e80befe7bef91ab8fa2f271173bab926cff2c797117a28716112b6d1ab3b6c669a4b923f5885b40f67885b1a64d0445ad75bbe0e, }, 0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=0e3e02a08fd3a807c79c1ce2117612c2902557aa7c57da2494744f45b105f3f67b9977564f83baf2cd7dd4fe2cf0421f9367343a92d90199e97f22bc977f3d0f, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=a9ef610d944c989424477a2e31b970033bffcce8899116820f9eac06f2d06226cfe714e6a835135e2fb632dda80b439199e76870156acd6f81d4c3cf342a3706, }, }, ]" + "[{0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=1490ad50f0fb5af40ee1d823e4f4b2603c135b3c7979b1b0ee6a323ba494e0b5cca833157c1106b976c876b060249e7ee2db30a8566d8682a42fac2f5f4a3406, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=23a657e362da4b3ea29673c26d8b17b967c53528449d99b3154e1b81676dc8d0aa229b824f9e613803b3262bc9cecc6dc6e2fc01a21830fb1641b5ed03722e07, }, 0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=40d079bcb4a9fbdf102051328ee5f3903e166c1dd7c1e748efc95a2fdd640e421c0a8e23709b61e4d8110451adecd71cd16d1293ce0e57ea974de5b6b2ef070e, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=0cbdeaac11d392081289fb67a93a7fd995e86f55764e45b3e5eefd2f64056a38b50e8478e64cb1af5c310c321478e09b60d641a6e898820625d2674dc54ce80e, }, }, {0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=ce2b975f698ca802721c80a3792fca39d73609afaa8961bb91da569463c50eecb07d7e26e7e8febb5163474139e94533e8eb7016e0c149e0823d7102ed2b0502, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=ea31e49f64fd41773561f81459a2381e0194788853e28ffb683caded7a675d386b2a228c67ec83bfc448f14ee4fd2eae41569f06006c515621e1f26514c9bf0a, }, 0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=4b4ed404ef9a37752c070c5eb364b0df0fbe06afb0b64e0743d27767c26b1045e8532308288e2f1a40cced0782b87f20b6cfdcd8b9890c600c0e2146a48ace00, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=95444670cecb07fc452a4e3f350eca481e5462e3349a6741cd4e6746b21c66e67825c169f3b4cf82ab1853f1cf0acedc84b2f565346dc173a93f054c19966b08, }, }, {0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=47c3e240259603f3e7fa41ced3eb9931bc4350367aa6529994c048fb0aca1853630bf8fbbdf9b2768c52b91b5f5d669a4adab06ef0851107f6e8012d948ba90b, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=d1a4d3349a1bc7cd0242e09ed9b1811ea99fb6123826b946651ee8c9dd593eb40591697fad4360e3941c9eea55cd2173189df349aa16b9a11db62ed28de8ad06, }, 0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=0aedd8f92e68278823397cb0eddc1c07f1fd80c223781280a0ffb0eef21b516444e4521294ad380e8a46c7f22f1723eef8872ccf4d8aa415345e0a7fe1485c06, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=8cf7f0ae116557d5f4a5bbee82dee3cfe950c0ecedbce5d2a7b729dd7614d47c436e6951c401870f85dadd696160ecee1ab8e65aa607ca942051e78b8f09a406, }, }, {0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=63800201fd378e81946c73104907b0b0aa70ff5913889b21b4eac730e535f8acbf08f63da5824419fc14155d6fc19f23a53bfd3324d8baa68dc5d00e8974de07, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=084bdc8f8580a2ebcc0a5140f766aca111b5488092a41871d104834dda27d6b99288423835bc7114860ce6c740300ebe9f8ab576e7646097eee7d6692b90d109, }, 0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=aa009ad11594bb981504f8d4063c9d90bfb0bccc4bda8f9e3ffd326fc39e599fae94ba98110342a449437f7c848e2a9dd6de0d008e8d00c8387ff094c93c2700, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=5a2b40589f128f3bac99649d0aec7230e3c993130f36814c742ae37104e93d22e2b548d97e471f583d1c81bbcf6f916cc03f20375499e3a37b2c6b13a5a94507, }, }, {0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=e83759154409ce22146e31ff826a3ee4940916784e5953c4c0502ef5c2f9e7ca2d114223c3461a491dfebdcc11e511e91400007a1dc3827b7b98c7225239460f, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=595653b3f5cedf84e845f0dc2c503aad94b259eee4c10ad32cd86976b246cd81726ae8edc35e41e9ebae9e27a3ed96aff524b9b04481fad2722fdab8a4ee5a0f, }, 0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=645d9d66e90a104462741e2f49fe77d2edce5d49a033c9c51768a2fba6deda96a71ad95e00416bb5a8a07cfaf543a1fee8730c11af4a380d6f30ec88d2271c0d, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=2bc0f7e72aa2e953741815ac95135e50ece67543683e6da3a26bc95534d9ca538d802d567fcb154bf98001663dc46d8674ff4e9361021fbe2a55e83f9442f802, }, }, {0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=c463b37297427a620f739b3a420512f897745a8451315de360391b2f6879e644ba3a8597e4f6e3a1a135bf354bb0911fe421e0174f48b650f54e3fe86247e507, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=342e41dbd4e3ef300192767ffeb9b062b1fae68027153a84f151fdb1d3ce43592f275d87a7b90a9d6db6a67d32c6ec9e585ce199ed199cdcac0b4ef4ac12200f, }, 0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=dea30ba3201c32f5c23afac9d5b013c4e41a30d08205d21a09722f5aebb0760b2452ba254eea5008de68411560081e94ccd78c5008353aa6bb64779e79078702, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=903762ba6159fcf940281d810a268980cdf2fa35683626d52e41ad18202492fef5f8de2002c49cb56ac9d9e78177823f1f97741634237943459c31540f801502, }, }, {0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=0e3e02a08fd3a807c79c1ce2117612c2902557aa7c57da2494744f45b105f3f67b9977564f83baf2cd7dd4fe2cf0421f9367343a92d90199e97f22bc977f3d0f, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=a9ef610d944c989424477a2e31b970033bffcce8899116820f9eac06f2d06226cfe714e6a835135e2fb632dda80b439199e76870156acd6f81d4c3cf342a3706, }, 0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=9e4dcb75574c75c7e54cc76ff08bf9e6c28cb2e74f79eb4ed8e4f968e6829bd994d9fadff9fb265988de757b858e4921c7b4db119c31f6156a79eb62ffc4110c, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=195fdc0b4c9730139ede43d8e80befe7bef91ab8fa2f271173bab926cff2c797117a28716112b6d1ab3b6c669a4b923f5885b40f67885b1a64d0445ad75bbe0e, }, }, ]" ] com.hedera.hashgraph.sdk.FileAppendTransactionTest.shouldGetSignatures=[ - "{0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=a762395ad7e3fa298ed990785699133ca64d11a28fb4dfc83d6d95a9a2639b688d5afc288fcdb8168f4a85876b2b785e3303ddec38666bbae4f5436d6334540b, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=8bea3d52ad5badc4ebf5e20f874cf2e5dec3189d3a471c39fd1062743ba7729de1c484f1e8ac2f15343494799e97b5ac220734a261994d91ffed9e113c09d700, }, 0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=4b8fd70342b6c201f08177de53122be909d5d72f97d29fba69e7ac6ef04d96b19ac417c9b84fbb122bce9c8323bc38bd6165b5750ce16ee4a2f23e28d7123006, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=371b502056cbf34c1bd7f9891e82c7a53ab8d92ce1728f790acc9a09989196fbf4c1c111ca010a19f1af82f2480be92229b5a1aadfe4af9142bd212254c88b08, }, }" + "{0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=4b8fd70342b6c201f08177de53122be909d5d72f97d29fba69e7ac6ef04d96b19ac417c9b84fbb122bce9c8323bc38bd6165b5750ce16ee4a2f23e28d7123006, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=371b502056cbf34c1bd7f9891e82c7a53ab8d92ce1728f790acc9a09989196fbf4c1c111ca010a19f1af82f2480be92229b5a1aadfe4af9142bd212254c88b08, }, 0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=a762395ad7e3fa298ed990785699133ca64d11a28fb4dfc83d6d95a9a2639b688d5afc288fcdb8168f4a85876b2b785e3303ddec38666bbae4f5436d6334540b, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=8bea3d52ad5badc4ebf5e20f874cf2e5dec3189d3a471c39fd1062743ba7729de1c484f1e8ac2f15343494799e97b5ac220734a261994d91ffed9e113c09d700, }, }" ] com.hedera.hashgraph.sdk.FileAppendTransactionTest.shouldHash=[ - "[{0.0.555=d2f10044785bb7ecbfc024a171b28ec877a123a2b6f3b2a48db5595208ea8bd036e4c4babb682d87e06ce62d7c2b1bb3, 0.0.444=38603d6b2a449030ea49b7cbd7e19cd66b4e3f2891ca40df861b4840418cb08575b7ce25426b1192545d352a89f0f3da, }, {0.0.555=74ed3e44b14e41ad5964a52adde1c32932b9dd75f589d0985504bbc483dc778493866ae879769d693e2a6fa80c6a118c, 0.0.444=0939a5cbfb9bbbd545d3e9f961e7fc3bcbf49553ce7e3a00414b5b0964ca9aae0ea878e280efa217503aed65d1057880, }, {0.0.555=9ef69da0531b3828cfc5b14cb5df373ae46922ad192df9d488684b845ce4754b2a20c1e966d2835ea178890fdaac9a00, 0.0.444=1332b1dfb679ea2a91b21de2bed0d086c5139893fce55b0471e2b08ec2e0fbbcee48783eda0a1e876ee0a7086416c26a, }, {0.0.555=e62ca0554d6e40461dbecc035165d35716d61eae59a305414a91a6fb85f36ba3adc1f6b963c429366485fe514407d294, 0.0.444=2deb2d9674c3e238c53080ad4d139f172dc907ba4b898210ed9359f3db92f0880503cca4fec35cd6b47c71ba5dd46aa3, }, {0.0.555=8a7721e7a8d8eede13e0ab5adb5c9520af6099c909592f45f9dc89775f69e16a2bea4a392480f1b750c817787a94099f, 0.0.444=dbb52ed2eea79c5cc58bb0b898ce03f4ee7d4ba6ad94c0d718c0c6b46fd8cea9e2ab76c42221fce44933827e382df57f, }, {0.0.555=0292097e1f3bdd4390134f10b51b2c9928fcfbe4fd54de25d407ee8b93c6ede6dda4c4263786d983de47413f541834e0, 0.0.444=16c12a7acaa5754a1e1adfc40550e5d4b09195c2347dc4fda3882d7a2823dd212ea1682642f211290b8985d45be55a0b, }, {0.0.555=e4c53e598718933cc67491218c478c23be4637e9d89107a3c1699f04143c421fd6bf5f2ff11d31ea646103cd7cd00b57, 0.0.444=5571dfcd8a279d4c33c0e9199c865556ab3aec478ddbc1560dd9c41c53423decb95348fb54b63cbc744fd1e496b2a01f, }, ]" + "[{0.0.444=38603d6b2a449030ea49b7cbd7e19cd66b4e3f2891ca40df861b4840418cb08575b7ce25426b1192545d352a89f0f3da, 0.0.555=d2f10044785bb7ecbfc024a171b28ec877a123a2b6f3b2a48db5595208ea8bd036e4c4babb682d87e06ce62d7c2b1bb3, }, {0.0.444=0939a5cbfb9bbbd545d3e9f961e7fc3bcbf49553ce7e3a00414b5b0964ca9aae0ea878e280efa217503aed65d1057880, 0.0.555=74ed3e44b14e41ad5964a52adde1c32932b9dd75f589d0985504bbc483dc778493866ae879769d693e2a6fa80c6a118c, }, {0.0.444=1332b1dfb679ea2a91b21de2bed0d086c5139893fce55b0471e2b08ec2e0fbbcee48783eda0a1e876ee0a7086416c26a, 0.0.555=9ef69da0531b3828cfc5b14cb5df373ae46922ad192df9d488684b845ce4754b2a20c1e966d2835ea178890fdaac9a00, }, {0.0.444=2deb2d9674c3e238c53080ad4d139f172dc907ba4b898210ed9359f3db92f0880503cca4fec35cd6b47c71ba5dd46aa3, 0.0.555=e62ca0554d6e40461dbecc035165d35716d61eae59a305414a91a6fb85f36ba3adc1f6b963c429366485fe514407d294, }, {0.0.444=dbb52ed2eea79c5cc58bb0b898ce03f4ee7d4ba6ad94c0d718c0c6b46fd8cea9e2ab76c42221fce44933827e382df57f, 0.0.555=8a7721e7a8d8eede13e0ab5adb5c9520af6099c909592f45f9dc89775f69e16a2bea4a392480f1b750c817787a94099f, }, {0.0.444=16c12a7acaa5754a1e1adfc40550e5d4b09195c2347dc4fda3882d7a2823dd212ea1682642f211290b8985d45be55a0b, 0.0.555=0292097e1f3bdd4390134f10b51b2c9928fcfbe4fd54de25d407ee8b93c6ede6dda4c4263786d983de47413f541834e0, }, {0.0.444=5571dfcd8a279d4c33c0e9199c865556ab3aec478ddbc1560dd9c41c53423decb95348fb54b63cbc744fd1e496b2a01f, 0.0.555=e4c53e598718933cc67491218c478c23be4637e9d89107a3c1699f04143c421fd6bf5f2ff11d31ea646103cd7cd00b57, }, ]" ] From bda7b59f0255fe958caf1e1eef5723a66b973e69 Mon Sep 17 00:00:00 2001 From: Nikola Genov Date: Wed, 1 Feb 2023 15:07:58 +0200 Subject: [PATCH 13/14] HIP-631 protobuf update Signed-off-by: Nikola Genov --- .../com/hedera/hashgraph/sdk/RequestType.java | 451 ++++++------------ sdk/src/main/proto/contract_call_local.proto | 6 + sdk/src/main/proto/crypto_create.proto | 11 +- sdk/src/main/proto/crypto_get_info.proto | 28 +- sdk/src/main/proto/crypto_update.proto | 10 +- sdk/src/main/proto/file_create.proto | 18 - sdk/src/main/proto/file_get_info.proto | 11 - sdk/src/main/proto/file_update.proto | 12 - .../hedera/hashgraph/sdk/AccountInfoTest.snap | 2 +- .../hedera/hashgraph/sdk/FileInfoTest.snap | 4 +- 10 files changed, 180 insertions(+), 373 deletions(-) diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/RequestType.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/RequestType.java index 1f5bd2ded..1812872e2 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/RequestType.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/RequestType.java @@ -393,309 +393,160 @@ public enum RequestType { } static RequestType valueOf(HederaFunctionality code) { - switch (code) { - case NONE: - return NONE; - case CryptoTransfer: - return CRYPTO_TRANSFER; - case CryptoUpdate: - return CRYPTO_UPDATE; - case CryptoDelete: - return CRYPTO_DELETE; - case CryptoAddLiveHash: - return CRYPTO_ADD_LIVE_HASH; - case CryptoDeleteLiveHash: - return CRYPTO_DELETE_LIVE_HASH; - case ContractCall: - return CONTRACT_CALL; - case ContractCreate: - return CONTRACT_CREATE; - case ContractUpdate: - return CONTRACT_UPDATE; - case FileCreate: - return FILE_CREATE; - case FileAppend: - return FILE_APPEND; - case FileUpdate: - return FILE_UPDATE; - case FileDelete: - return FILE_DELETE; - case CryptoGetAccountBalance: - return CRYPTO_GET_ACCOUNT_BALANCE; - case CryptoGetAccountRecords: - return CRYPTO_GET_ACCOUNT_RECORDS; - case CryptoGetInfo: - return CRYPTO_GET_INFO; - case ContractCallLocal: - return CONTRACT_CALL_LOCAL; - case ContractGetInfo: - return CONTRACT_GET_INFO; - case ContractGetBytecode: - return CONTRACT_GET_BYTECODE; - case GetBySolidityID: - return GET_BY_SOLIDITY_ID; - case GetByKey: - return GET_BY_KEY; - case CryptoGetLiveHash: - return CRYPTO_GET_LIVE_HASH; - case CryptoGetStakers: - return CRYPTO_GET_STAKERS; - case FileGetContents: - return FILE_GET_CONTENTS; - case FileGetInfo: - return FILE_GET_INFO; - case TransactionGetRecord: - return TRANSACTION_GET_RECORD; - case ContractGetRecords: - return CONTRACT_GET_RECORDS; - case CryptoCreate: - return CRYPTO_CREATE; - case SystemDelete: - return SYSTEM_DELETE; - case SystemUndelete: - return SYSTEM_UNDELETE; - case ContractDelete: - return CONTRACT_DELETE; - case Freeze: - return FREEZE; - case CreateTransactionRecord: - return CREATE_TRANSACTION_RECORD; - case CryptoAccountAutoRenew: - return CRYPTO_ACCOUNT_AUTO_RENEW; - case ContractAutoRenew: - return CONTRACT_AUTO_RENEW; - case GetVersionInfo: - return GET_VERSION_INFO; - case TransactionGetReceipt: - return TRANSACTION_GET_RECEIPT; - case ConsensusCreateTopic: - return CONSENSUS_CREATE_TOPIC; - case ConsensusUpdateTopic: - return CONSENSUS_UPDATE_TOPIC; - case ConsensusDeleteTopic: - return CONSENSUS_DELETE_TOPIC; - case ConsensusGetTopicInfo: - return CONSENSUS_GET_TOPIC_INFO; - case ConsensusSubmitMessage: - return CONSENSUS_SUBMIT_MESSAGE; - case UncheckedSubmit: - return UNCHECKED_SUBMIT; - case TokenCreate: - return TOKEN_CREATE; - case TokenGetInfo: - return TOKEN_GET_INFO; - case TokenFreezeAccount: - return TOKEN_FREEZE_ACCOUNT; - case TokenUnfreezeAccount: - return TOKEN_UNFREEZE_ACCOUNT; - case TokenGrantKycToAccount: - return TOKEN_GRANT_KYC_TO_ACCOUNT; - case TokenRevokeKycFromAccount: - return TOKEN_REVOKE_KYC_FROM_ACCOUNT; - case TokenDelete: - return TOKEN_DELETE; - case TokenUpdate: - return TOKEN_UPDATE; - case TokenMint: - return TOKEN_MINT; - case TokenBurn: - return TOKEN_BURN; - case TokenAccountWipe: - return TOKEN_ACCOUNT_WIPE; - case TokenAssociateToAccount: - return TOKEN_ASSOCIATE_TO_ACCOUNT; - case TokenDissociateFromAccount: - return TOKEN_DISSOCIATE_FROM_ACCOUNT; - case ScheduleCreate: - return SCHEDULE_CREATE; - case ScheduleDelete: - return SCHEDULE_DELETE; - case ScheduleSign: - return SCHEDULE_SIGN; - case ScheduleGetInfo: - return SCHEDULE_GET_INFO; - case TokenGetAccountNftInfos: - return TOKEN_GET_ACCOUNT_NFT_INFOS; - case TokenGetNftInfo: - return TOKEN_GET_NFT_INFO; - case TokenGetNftInfos: - return TOKEN_GET_NFT_INFOS; - case TokenFeeScheduleUpdate: - return TOKEN_FEE_SCHEDULE_UPDATE; - case NetworkGetExecutionTime: - return NETWORK_GET_EXECUTION_TIME; - case TokenPause: - return TOKEN_PAUSE; - case TokenUnpause: - return TOKEN_UNPAUSE; - case CryptoApproveAllowance: - return CRYPTO_APPROVE_ALLOWANCE; - case CryptoDeleteAllowance: - return CRYPTO_DELETE_ALLOWANCE; - case GetAccountDetails: - return GET_ACCOUNT_DETAILS; - case EthereumTransaction: - return ETHEREUM_TRANSACTION; - case NodeStakeUpdate: - return NODE_STAKE_UPDATE; - case UtilPrng: - return PRNG; - default: - throw new IllegalStateException("(BUG) unhandled HederaFunctionality"); - } + return switch (code) { + case NONE -> NONE; + case CryptoTransfer -> CRYPTO_TRANSFER; + case CryptoUpdate -> CRYPTO_UPDATE; + case CryptoDelete -> CRYPTO_DELETE; + case CryptoAddLiveHash -> CRYPTO_ADD_LIVE_HASH; + case CryptoDeleteLiveHash -> CRYPTO_DELETE_LIVE_HASH; + case ContractCall -> CONTRACT_CALL; + case ContractCreate -> CONTRACT_CREATE; + case ContractUpdate -> CONTRACT_UPDATE; + case FileCreate -> FILE_CREATE; + case FileAppend -> FILE_APPEND; + case FileUpdate -> FILE_UPDATE; + case FileDelete -> FILE_DELETE; + case CryptoGetAccountBalance -> CRYPTO_GET_ACCOUNT_BALANCE; + case CryptoGetAccountRecords -> CRYPTO_GET_ACCOUNT_RECORDS; + case CryptoGetInfo -> CRYPTO_GET_INFO; + case ContractCallLocal -> CONTRACT_CALL_LOCAL; + case ContractGetInfo -> CONTRACT_GET_INFO; + case ContractGetBytecode -> CONTRACT_GET_BYTECODE; + case GetBySolidityID -> GET_BY_SOLIDITY_ID; + case GetByKey -> GET_BY_KEY; + case CryptoGetLiveHash -> CRYPTO_GET_LIVE_HASH; + case CryptoGetStakers -> CRYPTO_GET_STAKERS; + case FileGetContents -> FILE_GET_CONTENTS; + case FileGetInfo -> FILE_GET_INFO; + case TransactionGetRecord -> TRANSACTION_GET_RECORD; + case ContractGetRecords -> CONTRACT_GET_RECORDS; + case CryptoCreate -> CRYPTO_CREATE; + case SystemDelete -> SYSTEM_DELETE; + case SystemUndelete -> SYSTEM_UNDELETE; + case ContractDelete -> CONTRACT_DELETE; + case Freeze -> FREEZE; + case CreateTransactionRecord -> CREATE_TRANSACTION_RECORD; + case CryptoAccountAutoRenew -> CRYPTO_ACCOUNT_AUTO_RENEW; + case ContractAutoRenew -> CONTRACT_AUTO_RENEW; + case GetVersionInfo -> GET_VERSION_INFO; + case TransactionGetReceipt -> TRANSACTION_GET_RECEIPT; + case ConsensusCreateTopic -> CONSENSUS_CREATE_TOPIC; + case ConsensusUpdateTopic -> CONSENSUS_UPDATE_TOPIC; + case ConsensusDeleteTopic -> CONSENSUS_DELETE_TOPIC; + case ConsensusGetTopicInfo -> CONSENSUS_GET_TOPIC_INFO; + case ConsensusSubmitMessage -> CONSENSUS_SUBMIT_MESSAGE; + case UncheckedSubmit -> UNCHECKED_SUBMIT; + case TokenCreate -> TOKEN_CREATE; + case TokenGetInfo -> TOKEN_GET_INFO; + case TokenFreezeAccount -> TOKEN_FREEZE_ACCOUNT; + case TokenUnfreezeAccount -> TOKEN_UNFREEZE_ACCOUNT; + case TokenGrantKycToAccount -> TOKEN_GRANT_KYC_TO_ACCOUNT; + case TokenRevokeKycFromAccount -> TOKEN_REVOKE_KYC_FROM_ACCOUNT; + case TokenDelete -> TOKEN_DELETE; + case TokenUpdate -> TOKEN_UPDATE; + case TokenMint -> TOKEN_MINT; + case TokenBurn -> TOKEN_BURN; + case TokenAccountWipe -> TOKEN_ACCOUNT_WIPE; + case TokenAssociateToAccount -> TOKEN_ASSOCIATE_TO_ACCOUNT; + case TokenDissociateFromAccount -> TOKEN_DISSOCIATE_FROM_ACCOUNT; + case ScheduleCreate -> SCHEDULE_CREATE; + case ScheduleDelete -> SCHEDULE_DELETE; + case ScheduleSign -> SCHEDULE_SIGN; + case ScheduleGetInfo -> SCHEDULE_GET_INFO; + case TokenGetAccountNftInfos -> TOKEN_GET_ACCOUNT_NFT_INFOS; + case TokenGetNftInfo -> TOKEN_GET_NFT_INFO; + case TokenGetNftInfos -> TOKEN_GET_NFT_INFOS; + case TokenFeeScheduleUpdate -> TOKEN_FEE_SCHEDULE_UPDATE; + case NetworkGetExecutionTime -> NETWORK_GET_EXECUTION_TIME; + case TokenPause -> TOKEN_PAUSE; + case TokenUnpause -> TOKEN_UNPAUSE; + case CryptoApproveAllowance -> CRYPTO_APPROVE_ALLOWANCE; + case CryptoDeleteAllowance -> CRYPTO_DELETE_ALLOWANCE; + case GetAccountDetails -> GET_ACCOUNT_DETAILS; + case EthereumTransaction -> ETHEREUM_TRANSACTION; + case NodeStakeUpdate -> NODE_STAKE_UPDATE; + case UtilPrng -> PRNG; + default -> throw new IllegalStateException("(BUG) unhandled HederaFunctionality"); + }; } @Override public String toString() { - switch (this) { - case NONE: - return "NONE"; - case CRYPTO_TRANSFER: - return "CRYPTO_TRANSFER"; - case CRYPTO_UPDATE: - return "CRYPTO_UPDATE"; - case CRYPTO_DELETE: - return "CRYPTO_DELETE"; - case CRYPTO_ADD_LIVE_HASH: - return "CRYPTO_ADD_LIVE_HASH"; - case CRYPTO_DELETE_LIVE_HASH: - return "CRYPTO_DELETE_LIVE_HASH"; - case CONTRACT_CALL: - return "CONTRACT_CALL"; - case CONTRACT_CREATE: - return "CONTRACT_CREATE"; - case CONTRACT_UPDATE: - return "CONTRACT_UPDATE"; - case FILE_CREATE: - return "FILE_CREATE"; - case FILE_APPEND: - return "FILE_APPEND"; - case FILE_UPDATE: - return "FILE_UPDATE"; - case FILE_DELETE: - return "FILE_DELETE"; - case CRYPTO_GET_ACCOUNT_BALANCE: - return "CRYPTO_GET_ACCOUNT_BALANCE"; - case CRYPTO_GET_ACCOUNT_RECORDS: - return "CRYPTO_GET_ACCOUNT_RECORDS"; - case CRYPTO_GET_INFO: - return "CRYPTO_GET_INFO"; - case CONTRACT_CALL_LOCAL: - return "CONTRACT_CALL_LOCAL"; - case CONTRACT_GET_INFO: - return "CONTRACT_GET_INFO"; - case CONTRACT_GET_BYTECODE: - return "CONTRACT_GET_BYTECODE"; - case GET_BY_SOLIDITY_ID: - return "GET_BY_SOLIDITY_ID"; - case GET_BY_KEY: - return "GET_BY_KEY"; - case CRYPTO_GET_LIVE_HASH: - return "CRYPTO_GET_LIVE_HASH"; - case CRYPTO_GET_STAKERS: - return "CRYPTO_GET_STAKERS"; - case FILE_GET_CONTENTS: - return "FILE_GET_CONTENTS"; - case FILE_GET_INFO: - return "FILE_GET_INFO"; - case TRANSACTION_GET_RECORD: - return "TRANSACTION_GET_RECORD"; - case CONTRACT_GET_RECORDS: - return "CONTRACT_GET_RECORDS"; - case CRYPTO_CREATE: - return "CRYPTO_CREATE"; - case SYSTEM_DELETE: - return "SYSTEM_DELETE"; - case SYSTEM_UNDELETE: - return "SYSTEM_UNDELETE"; - case CONTRACT_DELETE: - return "CONTRACT_DELETE"; - case FREEZE: - return "FREEZE"; - case CREATE_TRANSACTION_RECORD: - return "CREATE_TRANSACTION_RECORD"; - case CRYPTO_ACCOUNT_AUTO_RENEW: - return "CRYPTO_ACCOUNT_AUTO_RENEW"; - case CONTRACT_AUTO_RENEW: - return "CONTRACT_AUTO_RENEW"; - case GET_VERSION_INFO: - return "GET_VERSION_INFO"; - case TRANSACTION_GET_RECEIPT: - return "TRANSACTION_GET_RECEIPT"; - case CONSENSUS_CREATE_TOPIC: - return "CONSENSUS_CREATE_TOPIC"; - case CONSENSUS_UPDATE_TOPIC: - return "CONSENSUS_UPDATE_TOPIC"; - case CONSENSUS_DELETE_TOPIC: - return "CONSENSUS_DELETE_TOPIC"; - case CONSENSUS_GET_TOPIC_INFO: - return "CONSENSUS_GET_TOPIC_INFO"; - case CONSENSUS_SUBMIT_MESSAGE: - return "CONSENSUS_SUBMIT_MESSAGE"; - case UNCHECKED_SUBMIT: - return "UNCHECKED_SUBMIT"; - case TOKEN_CREATE: - return "TOKEN_CREATE"; - case TOKEN_GET_INFO: - return "TOKEN_GET_INFO"; - case TOKEN_FREEZE_ACCOUNT: - return "TOKEN_FREEZE_ACCOUNT"; - case TOKEN_UNFREEZE_ACCOUNT: - return "TOKEN_UNFREEZE_ACCOUNT"; - case TOKEN_GRANT_KYC_TO_ACCOUNT: - return "TOKEN_GRANT_KYC_TO_ACCOUNT"; - case TOKEN_REVOKE_KYC_FROM_ACCOUNT: - return "TOKEN_REVOKE_KYC_FROM_ACCOUNT"; - case TOKEN_DELETE: - return "TOKEN_DELETE"; - case TOKEN_UPDATE: - return "TOKEN_UPDATE"; - case TOKEN_MINT: - return "TOKEN_MINT"; - case TOKEN_BURN: - return "TOKEN_BURN"; - case TOKEN_ACCOUNT_WIPE: - return "TOKEN_ACCOUNT_WIPE"; - case TOKEN_ASSOCIATE_TO_ACCOUNT: - return "TOKEN_ASSOCIATE_TO_ACCOUNT"; - case TOKEN_DISSOCIATE_FROM_ACCOUNT: - return "TOKEN_DISSOCIATE_FROM_ACCOUNT"; - case SCHEDULE_CREATE: - return "SCHEDULE_CREATE"; - case SCHEDULE_DELETE: - return "SCHEDULE_DELETE"; - case SCHEDULE_SIGN: - return "SCHEDULE_SIGN"; - case SCHEDULE_GET_INFO: - return "SCHEDULE_GET_INFO"; - case TOKEN_GET_ACCOUNT_NFT_INFOS: - return "TOKEN_GET_ACCOUNT_NFT_INFOS"; - case TOKEN_GET_NFT_INFO: - return "TOKEN_GET_NFT_INFO"; - case TOKEN_GET_NFT_INFOS: - return "TOKEN_GET_NFT_INFOS"; - case TOKEN_FEE_SCHEDULE_UPDATE: - return "TOKEN_FEE_SCHEDULE_UPDATE"; - case NETWORK_GET_EXECUTION_TIME: - return "NETWORK_GET_EXECUTION_TIME"; - case TOKEN_PAUSE: - return "TOKEN_PAUSE"; - case TOKEN_UNPAUSE: - return "TOKEN_UNPAUSE"; - case CRYPTO_APPROVE_ALLOWANCE: - return "CRYPTO_APPROVE_ALLOWANCE"; - case CRYPTO_DELETE_ALLOWANCE: - return "CRYPTO_DELETE_ALLOWANCE"; - case GET_ACCOUNT_DETAILS: - return "GET_ACCOUNT_DETAILS"; - case ETHEREUM_TRANSACTION: - return "ETHEREUM_TRANSACTION"; - case NODE_STAKE_UPDATE: - return "NODE_STAKE_UPDATE"; - case PRNG: - return "PRNG"; - default: - return ""; - } + return switch (this) { + case NONE -> "NONE"; + case CRYPTO_TRANSFER -> "CRYPTO_TRANSFER"; + case CRYPTO_UPDATE -> "CRYPTO_UPDATE"; + case CRYPTO_DELETE -> "CRYPTO_DELETE"; + case CRYPTO_ADD_LIVE_HASH -> "CRYPTO_ADD_LIVE_HASH"; + case CRYPTO_DELETE_LIVE_HASH -> "CRYPTO_DELETE_LIVE_HASH"; + case CONTRACT_CALL -> "CONTRACT_CALL"; + case CONTRACT_CREATE -> "CONTRACT_CREATE"; + case CONTRACT_UPDATE -> "CONTRACT_UPDATE"; + case FILE_CREATE -> "FILE_CREATE"; + case FILE_APPEND -> "FILE_APPEND"; + case FILE_UPDATE -> "FILE_UPDATE"; + case FILE_DELETE -> "FILE_DELETE"; + case CRYPTO_GET_ACCOUNT_BALANCE -> "CRYPTO_GET_ACCOUNT_BALANCE"; + case CRYPTO_GET_ACCOUNT_RECORDS -> "CRYPTO_GET_ACCOUNT_RECORDS"; + case CRYPTO_GET_INFO -> "CRYPTO_GET_INFO"; + case CONTRACT_CALL_LOCAL -> "CONTRACT_CALL_LOCAL"; + case CONTRACT_GET_INFO -> "CONTRACT_GET_INFO"; + case CONTRACT_GET_BYTECODE -> "CONTRACT_GET_BYTECODE"; + case GET_BY_SOLIDITY_ID -> "GET_BY_SOLIDITY_ID"; + case GET_BY_KEY -> "GET_BY_KEY"; + case CRYPTO_GET_LIVE_HASH -> "CRYPTO_GET_LIVE_HASH"; + case CRYPTO_GET_STAKERS -> "CRYPTO_GET_STAKERS"; + case FILE_GET_CONTENTS -> "FILE_GET_CONTENTS"; + case FILE_GET_INFO -> "FILE_GET_INFO"; + case TRANSACTION_GET_RECORD -> "TRANSACTION_GET_RECORD"; + case CONTRACT_GET_RECORDS -> "CONTRACT_GET_RECORDS"; + case CRYPTO_CREATE -> "CRYPTO_CREATE"; + case SYSTEM_DELETE -> "SYSTEM_DELETE"; + case SYSTEM_UNDELETE -> "SYSTEM_UNDELETE"; + case CONTRACT_DELETE -> "CONTRACT_DELETE"; + case FREEZE -> "FREEZE"; + case CREATE_TRANSACTION_RECORD -> "CREATE_TRANSACTION_RECORD"; + case CRYPTO_ACCOUNT_AUTO_RENEW -> "CRYPTO_ACCOUNT_AUTO_RENEW"; + case CONTRACT_AUTO_RENEW -> "CONTRACT_AUTO_RENEW"; + case GET_VERSION_INFO -> "GET_VERSION_INFO"; + case TRANSACTION_GET_RECEIPT -> "TRANSACTION_GET_RECEIPT"; + case CONSENSUS_CREATE_TOPIC -> "CONSENSUS_CREATE_TOPIC"; + case CONSENSUS_UPDATE_TOPIC -> "CONSENSUS_UPDATE_TOPIC"; + case CONSENSUS_DELETE_TOPIC -> "CONSENSUS_DELETE_TOPIC"; + case CONSENSUS_GET_TOPIC_INFO -> "CONSENSUS_GET_TOPIC_INFO"; + case CONSENSUS_SUBMIT_MESSAGE -> "CONSENSUS_SUBMIT_MESSAGE"; + case UNCHECKED_SUBMIT -> "UNCHECKED_SUBMIT"; + case TOKEN_CREATE -> "TOKEN_CREATE"; + case TOKEN_GET_INFO -> "TOKEN_GET_INFO"; + case TOKEN_FREEZE_ACCOUNT -> "TOKEN_FREEZE_ACCOUNT"; + case TOKEN_UNFREEZE_ACCOUNT -> "TOKEN_UNFREEZE_ACCOUNT"; + case TOKEN_GRANT_KYC_TO_ACCOUNT -> "TOKEN_GRANT_KYC_TO_ACCOUNT"; + case TOKEN_REVOKE_KYC_FROM_ACCOUNT -> "TOKEN_REVOKE_KYC_FROM_ACCOUNT"; + case TOKEN_DELETE -> "TOKEN_DELETE"; + case TOKEN_UPDATE -> "TOKEN_UPDATE"; + case TOKEN_MINT -> "TOKEN_MINT"; + case TOKEN_BURN -> "TOKEN_BURN"; + case TOKEN_ACCOUNT_WIPE -> "TOKEN_ACCOUNT_WIPE"; + case TOKEN_ASSOCIATE_TO_ACCOUNT -> "TOKEN_ASSOCIATE_TO_ACCOUNT"; + case TOKEN_DISSOCIATE_FROM_ACCOUNT -> "TOKEN_DISSOCIATE_FROM_ACCOUNT"; + case SCHEDULE_CREATE -> "SCHEDULE_CREATE"; + case SCHEDULE_DELETE -> "SCHEDULE_DELETE"; + case SCHEDULE_SIGN -> "SCHEDULE_SIGN"; + case SCHEDULE_GET_INFO -> "SCHEDULE_GET_INFO"; + case TOKEN_GET_ACCOUNT_NFT_INFOS -> "TOKEN_GET_ACCOUNT_NFT_INFOS"; + case TOKEN_GET_NFT_INFO -> "TOKEN_GET_NFT_INFO"; + case TOKEN_GET_NFT_INFOS -> "TOKEN_GET_NFT_INFOS"; + case TOKEN_FEE_SCHEDULE_UPDATE -> "TOKEN_FEE_SCHEDULE_UPDATE"; + case NETWORK_GET_EXECUTION_TIME -> "NETWORK_GET_EXECUTION_TIME"; + case TOKEN_PAUSE -> "TOKEN_PAUSE"; + case TOKEN_UNPAUSE -> "TOKEN_UNPAUSE"; + case CRYPTO_APPROVE_ALLOWANCE -> "CRYPTO_APPROVE_ALLOWANCE"; + case CRYPTO_DELETE_ALLOWANCE -> "CRYPTO_DELETE_ALLOWANCE"; + case GET_ACCOUNT_DETAILS -> "GET_ACCOUNT_DETAILS"; + case ETHEREUM_TRANSACTION -> "ETHEREUM_TRANSACTION"; + case NODE_STAKE_UPDATE -> "NODE_STAKE_UPDATE"; + case PRNG -> "PRNG"; + }; } } diff --git a/sdk/src/main/proto/contract_call_local.proto b/sdk/src/main/proto/contract_call_local.proto index 8d4520936..ecbbc48ab 100644 --- a/sdk/src/main/proto/contract_call_local.proto +++ b/sdk/src/main/proto/contract_call_local.proto @@ -162,6 +162,12 @@ message ContractFunctionResult { * ContractCreateTransactionBody or a ContractCallTransactionBody. */ AccountID sender_id = 13; + + /** + * Map used to track contract nonces for all contracts that have participated in the transaction. + * The keys would have the different contract IDs as strings in "shard.realm.num" format and the values are the new nonce values. + */ + map contract_nonces = 14; } /** diff --git a/sdk/src/main/proto/crypto_create.proto b/sdk/src/main/proto/crypto_create.proto index 51c44951e..877447f03 100644 --- a/sdk/src/main/proto/crypto_create.proto +++ b/sdk/src/main/proto/crypto_create.proto @@ -46,7 +46,7 @@ import "duration.proto"; * used to extend its expiration as long as possible. If it is has a zero balance when it expires, * then it is deleted. This transaction must be signed by the payer account. If receiverSigRequired * is false, then the transaction does not have to be signed by the keys in the keys field. If it is - * true, then it must be signed by them, in addition to the keys of the payer account. If the + * true, then it must be signed by them, in addition to the keys of the payer account. If the * auto_renew_account field is set, the key of the referenced account must sign. * * An entity (account, file, or smart contract instance) must be created in a particular realm. If @@ -163,18 +163,11 @@ message CryptoCreateTransactionBody { * A given alias can map to at most one account on the network at a time. This uniqueness will be enforced * relative to aliases currently on the network at alias assignment. * - * If a transaction creates an account using an alias, any further crypto transfers to that alias will + * If a transaction creates an account using an alias, any further crypto transfers to that alias will * simply be deposited in that account, without creating anything, and with no creation fee being charged. */ bytes alias = 18; - /** - * An account to charge for auto-renewal of this account . If not set, or set to an - * account with zero hbar balance, the account's own hbar balance will be used to - * cover auto-renewal fees. - */ - AccountID auto_renew_account = 19; - /** * EOA 20-byte address to create that is derived from the keccak-256 hash of a ECDSA_SECP256K1 primitive key. */ diff --git a/sdk/src/main/proto/crypto_get_info.proto b/sdk/src/main/proto/crypto_get_info.proto index e9c98078c..039057e79 100644 --- a/sdk/src/main/proto/crypto_get_info.proto +++ b/sdk/src/main/proto/crypto_get_info.proto @@ -140,9 +140,9 @@ message CryptoGetInfoResponse { repeated LiveHash liveHashes = 14; /** - * [DEPRECATED] The metadata of the tokens associated to the account. This field was - * deprecated by HIP-367, which allowed - * an account to be associated to an unlimited number of tokens. This scale makes it more + * [DEPRECATED] The metadata of the tokens associated to the account. This field was + * deprecated by HIP-367, which allowed + * an account to be associated to an unlimited number of tokens. This scale makes it more * efficient for users to consult mirror nodes to review their token associations. */ repeated TokenRelationship tokenRelationships = 15 [deprecated = true]; @@ -168,7 +168,7 @@ message CryptoGetInfoResponse { bytes alias = 19; /** - * The ledger ID the response was returned from; please see HIP-198 for the network-specific IDs. + * The ledger ID the response was returned from; please see HIP-198 for the network-specific IDs. */ bytes ledger_id = 20; @@ -182,18 +182,22 @@ message CryptoGetInfoResponse { */ StakingInfo staking_info = 22; + message VirtualAddressInfo { + /** + * A virtual address entry. + */ + VirtualAddress virtual_address = 1; - /** - * If present, the account that will be charged for auto-renewal of this account. If not set, - * or set to an account with zero hbar balance, the account's own hbar balance will be used to - * cover auto-renewal fees. - */ - AccountID auto_renew_account = 23; + /** + * The ethereum transaction nonce associated with this virtual address. + */ + int64 nonce = 2; + } /** - * List of virtual addresses each of which is an EVM address that maps to an ECDSA key pair a user must prove ownership of. + * List of virtual addresses each of which is an EVM address that maps to an ECDSA key pair a user must prove ownership of and their corresponding nonce value. */ - repeated VirtualAddress virtual_addresses = 24; + repeated VirtualAddressInfo virtual_addresses = 24; } /** diff --git a/sdk/src/main/proto/crypto_update.proto b/sdk/src/main/proto/crypto_update.proto index 8c30a9afa..9371256bf 100644 --- a/sdk/src/main/proto/crypto_update.proto +++ b/sdk/src/main/proto/crypto_update.proto @@ -36,8 +36,8 @@ import "google/protobuf/wrappers.proto"; * transaction must be signed by the existing key for this account. If the transaction is changing * the key field, then the transaction must be signed by both the old key (from before the change) * and the new key. The old key must sign for security. The new key must sign as a safeguard to - * avoid accidentally changing to an invalid key, and then having no way to recover. - * If the update transaction sets the auto_renew_account field to anything other + * avoid accidentally changing to an invalid key, and then having no way to recover. + * If the update transaction sets the auto_renew_account field to anything other * than the sentinel 0.0.0, the key of the referenced account must sign. */ message CryptoUpdateTransactionBody { @@ -156,12 +156,6 @@ message CryptoUpdateTransactionBody { */ google.protobuf.BoolValue decline_reward = 18; - /** - * If set to the sentinel 0.0.0 AccountID, this field removes the account's auto-renew - * account. Otherwise it updates the account's auto-renew account to the referenced account. - */ - AccountID auto_renew_account = 19; - oneof virtual_address_update { /** * The virtual address to be added. diff --git a/sdk/src/main/proto/file_create.proto b/sdk/src/main/proto/file_create.proto index 9caaa812b..b3df3a592 100644 --- a/sdk/src/main/proto/file_create.proto +++ b/sdk/src/main/proto/file_create.proto @@ -28,7 +28,6 @@ option java_multiple_files = true; import "basic_types.proto"; import "timestamp.proto"; -import "duration.proto"; /** * Create a new file, containing the given contents. @@ -102,21 +101,4 @@ message FileCreateTransactionBody { * The memo associated with the file (UTF-8 encoding max 100 bytes) */ string memo = 8; - - /** - * An account to charge for auto-renewal of this file. If not set, or set to an - * account with zero hbar balance, the file's expiration must be manually extended - * using a FileUpdate transaction, since the network will not have authorization - * for any kind of auto-renewal fee collection. - */ - AccountID auto_renew_account = 9; - - /** - * If an auto-renew account is in use, the lifetime to be added by each - * auto-renewal. When both auto-renew account and auto-renew period are - * set in the create transaction, the initial expiry of the file will be - * the valid start of the create transaction plus the auto-renew period. - * (I.e., the expirationTime field will be ignored.) - */ - Duration auto_renew_period = 10; } diff --git a/sdk/src/main/proto/file_get_info.proto b/sdk/src/main/proto/file_get_info.proto index 54eb0a41f..a408ebd88 100644 --- a/sdk/src/main/proto/file_get_info.proto +++ b/sdk/src/main/proto/file_get_info.proto @@ -30,7 +30,6 @@ import "timestamp.proto"; import "basic_types.proto"; import "query_header.proto"; import "response_header.proto"; -import "duration.proto"; /** * Get all of the information about a file, except for its contents. When a file expires, it no @@ -98,16 +97,6 @@ message FileGetInfoResponse { * The ledger ID the response was returned from; please see HIP-198 for the network-specific IDs. */ bytes ledger_id = 7; - - /** - * If set, the account that is used to pay for auto-renewal of the file. - */ - AccountID auto_renew_account = 8; - - /** - * If an auto-renew account is in use, the added lifetime (in seconds) of each auto-renewal. - */ - Duration auto_renew_period = 9; } /** diff --git a/sdk/src/main/proto/file_update.proto b/sdk/src/main/proto/file_update.proto index 71277b282..74e0490ec 100644 --- a/sdk/src/main/proto/file_update.proto +++ b/sdk/src/main/proto/file_update.proto @@ -27,7 +27,6 @@ option java_package = "com.hedera.hashgraph.sdk.proto"; option java_multiple_files = true; import "basic_types.proto"; -import "duration.proto"; import "timestamp.proto"; import "google/protobuf/wrappers.proto"; @@ -65,15 +64,4 @@ message FileUpdateTransactionBody { * If set, the new memo to be associated with the file (UTF-8 encoding max 100 bytes) */ google.protobuf.StringValue memo = 5; - - /** - * If set to the sentinel 0.0.0 AccountID, this field removes the file's auto-renew - * account. Otherwise it updates the file's auto-renew account to the referenced account. - */ - AccountID auto_renew_account = 6; - - /** - * If an auto-renew account is in use, the lifetime to be added by each auto-renewal. - */ - Duration auto_renew_period = 7; } diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountInfoTest.snap b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountInfoTest.snap index b89d98bc5..bbf76e3f1 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountInfoTest.snap +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountInfoTest.snap @@ -14,5 +14,5 @@ com.hedera.hashgraph.sdk.AccountInfoTest.toBytes=[ com.hedera.hashgraph.sdk.AccountInfoTest.toProtobuf=[ - "# com.hedera.hashgraph.sdk.proto.CryptoGetInfoResponse$AccountInfo@df1d71e3\naccount_i_d {\n account_num: 1\n realm_num: 0\n shard_num: 0\n}\nauto_renew_period {\n seconds: 604800\n}\nbalance: 3\ndeleted: true\nethereum_nonce: 1001\nexpiration_time {\n nanos: 6000000\n seconds: 0\n}\ngenerate_receive_record_threshold: 5\ngenerate_send_record_threshold: 4\nkey {\n ed25519: \"\\340\\310\\354\\'X\\245\\207\\237\\372\\302&\\241<\\fQky\\236r\\343QA\\240\\335\\202\\217\\224\\323y\\210\\244\\267\"\n}\nledger_id: \"\\002\"\nlive_hashes {\n account_id {\n account_num: 10\n realm_num: 0\n shard_num: 0\n }\n duration {\n seconds: 950400\n }\n hash: \"\\000\\001\\002\"\n keys {\n keys {\n ed25519: \"\\340\\310\\354\\'X\\245\\207\\237\\372\\302&\\241<\\fQky\\236r\\343QA\\240\\335\\202\\217\\224\\323y\\210\\244\\267\"\n }\n }\n}\nowned_nfts: 0\nproxy_account_i_d {\n account_num: 8\n realm_num: 0\n shard_num: 0\n}\nproxy_received: 2\nreceiver_sig_required: true" + "# com.hedera.hashgraph.sdk.proto.CryptoGetInfoResponse$AccountInfo@21386b1e\naccount_i_d {\n account_num: 1\n realm_num: 0\n shard_num: 0\n}\nauto_renew_period {\n seconds: 604800\n}\nbalance: 3\ndeleted: true\nethereum_nonce: 1001\nexpiration_time {\n nanos: 6000000\n seconds: 0\n}\ngenerate_receive_record_threshold: 5\ngenerate_send_record_threshold: 4\nkey {\n ed25519: \"\\340\\310\\354\\'X\\245\\207\\237\\372\\302&\\241<\\fQky\\236r\\343QA\\240\\335\\202\\217\\224\\323y\\210\\244\\267\"\n}\nledger_id: \"\\002\"\nlive_hashes {\n account_id {\n account_num: 10\n realm_num: 0\n shard_num: 0\n }\n duration {\n seconds: 950400\n }\n hash: \"\\000\\001\\002\"\n keys {\n keys {\n ed25519: \"\\340\\310\\354\\'X\\245\\207\\237\\372\\302&\\241<\\fQky\\236r\\343QA\\240\\335\\202\\217\\224\\323y\\210\\244\\267\"\n }\n }\n}\nowned_nfts: 0\nproxy_account_i_d {\n account_num: 8\n realm_num: 0\n shard_num: 0\n}\nproxy_received: 2\nreceiver_sig_required: true" ] \ No newline at end of file diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/FileInfoTest.snap b/sdk/src/test/java/com/hedera/hashgraph/sdk/FileInfoTest.snap index 817e1c608..f82cadf2a 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/FileInfoTest.snap +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/FileInfoTest.snap @@ -14,5 +14,5 @@ com.hedera.hashgraph.sdk.FileInfoTest.toBytes=[ com.hedera.hashgraph.sdk.FileInfoTest.toProtobuf=[ - "# com.hedera.hashgraph.sdk.proto.FileGetInfoResponse$FileInfo@5de8e70f\ndeleted: true\nexpiration_time {\n nanos: 3000000\n seconds: 0\n}\nfile_i_d {\n file_num: 1\n realm_num: 0\n shard_num: 0\n}\nkeys {\n keys {\n ed25519: \"\\340\\310\\354\\'X\\245\\207\\237\\372\\302&\\241<\\fQky\\236r\\343QA\\240\\335\\202\\217\\224\\323y\\210\\244\\267\"\n }\n}\nledger_id: \"\\000\"\nsize: 2" -] + "# com.hedera.hashgraph.sdk.proto.FileGetInfoResponse$FileInfo@e51665b9\ndeleted: true\nexpiration_time {\n nanos: 3000000\n seconds: 0\n}\nfile_i_d {\n file_num: 1\n realm_num: 0\n shard_num: 0\n}\nkeys {\n keys {\n ed25519: \"\\340\\310\\354\\'X\\245\\207\\237\\372\\302&\\241<\\fQky\\236r\\343QA\\240\\335\\202\\217\\224\\323y\\210\\244\\267\"\n }\n}\nledger_id: \"\\000\"\nsize: 2" +] \ No newline at end of file From 909693db7013320c5bdedb54f691841bb8803c2f Mon Sep 17 00:00:00 2001 From: Nikola Genov Date: Tue, 7 Feb 2023 15:18:14 +0200 Subject: [PATCH 14/14] Add AccountInfo virtualAddresses, ContractNonces and related changes Signed-off-by: Nikola Genov --- .../com/hedera/hashgraph/sdk/AccountId.java | 20 +-- .../com/hedera/hashgraph/sdk/AccountInfo.java | 26 +++- .../hashgraph/sdk/ContractFunctionResult.java | 9 ++ .../hedera/hashgraph/sdk/ContractNonce.java | 132 ++++++++++++++++ .../hashgraph/sdk/VirtualAddressInfo.java | 146 ++++++++++++++++++ sdk/src/main/proto/basic_types.proto | 17 ++ sdk/src/main/proto/contract_call_local.proto | 5 +- sdk/src/main/proto/crypto_get_info.proto | 13 +- .../hedera/hashgraph/sdk/AccountIdTest.java | 19 --- .../hedera/hashgraph/sdk/AccountIdTest.snap | 15 -- .../hedera/hashgraph/sdk/AccountInfoTest.snap | 4 +- .../sdk/FileAppendTransactionTest.snap | 6 +- .../hashgraph/sdk/TransactionRecordTest.snap | 6 +- 13 files changed, 347 insertions(+), 71 deletions(-) create mode 100644 sdk/src/main/java/com/hedera/hashgraph/sdk/ContractNonce.java create mode 100644 sdk/src/main/java/com/hedera/hashgraph/sdk/VirtualAddressInfo.java diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java index 4a210bce1..5515f78ba 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountId.java @@ -25,7 +25,6 @@ import org.bouncycastle.util.encoders.Hex; import javax.annotation.Nonnegative; -import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.*; import java.util.regex.Pattern; @@ -60,9 +59,6 @@ public final class AccountId implements Comparable { @Nullable public final EvmAddress evmAddress; - @Nonnull - public final List virtualAddresses; - @Nullable private final String checksum; @@ -102,7 +98,6 @@ public AccountId(@Nonnegative long shard, @Nonnegative long realm, @Nonnegative this.checksum = checksum; this.aliasKey = null; this.evmAddress = null; - this.virtualAddresses = new ArrayList<>(); } /** @@ -127,7 +122,6 @@ public AccountId(@Nonnegative long shard, @Nonnegative long realm, @Nonnegative this.checksum = checksum; this.aliasKey = aliasKey; this.evmAddress = evmAddress; - this.virtualAddresses = new ArrayList<>(); } /** @@ -281,11 +275,6 @@ AccountID toProtobuf() { accountIdBuilder.setAccountNum(num); } - // TODO - waiting for protobuf update - //if (virtualAddresses != null && !virtualAddresses.isEmpty()) { - // accountIdBuilder.setVirtualAddresses(); - //} - return accountIdBuilder.build(); } @@ -359,9 +348,7 @@ public String toStringWithChecksum(Client client) { public int hashCode() { return Objects.hash( shard, realm, num, - (aliasKey != null) ? aliasKey.toBytes() : ((evmAddress != null) ? evmAddress.toBytes() : null), - // TODO - support multiple virtual addresses - !virtualAddresses.isEmpty() ? virtualAddresses.get(0).toBytes() : null + (aliasKey != null) ? aliasKey.toBytes() : ((evmAddress != null) ? evmAddress.toBytes() : null) ); } @@ -384,10 +371,7 @@ public boolean equals(Object o) { } return shard == otherId.shard && realm == otherId.realm && num == otherId.num && (aliasKey == null || aliasKey.equals(otherId.aliasKey)) && - (evmAddress == null || evmAddress.equals(otherId.evmAddress)) && - // TBD - if the addresses are the same but in different order should we consider them equal? - // Or should we sort the collections first? - virtualAddresses.equals(otherId.virtualAddresses); + (evmAddress == null || evmAddress.equals(otherId.evmAddress)); } @Override diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountInfo.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountInfo.java index 6a4268d2a..88548f0b6 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountInfo.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/AccountInfo.java @@ -28,7 +28,6 @@ import org.threeten.bp.Instant; import javax.annotation.Nullable; -import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -158,6 +157,12 @@ public final class AccountInfo { @Nullable public final StakingInfo stakingInfo; + /** + * List of virtual addresses each of which is an EVM address that maps to an ECDSA key pair a user must prove ownership of. + */ + public final List virtualAddresses; + + /** * Constructor. * @@ -202,7 +207,8 @@ private AccountInfo( @Nullable PublicKey aliasKey, LedgerId ledgerId, long ethereumNonce, - @Nullable StakingInfo stakingInfo + @Nullable StakingInfo stakingInfo, + List virtualAddresses ) { this.accountId = accountId; this.contractAccountId = contractAccountId; @@ -228,6 +234,7 @@ private AccountInfo( this.tokenAllowances = Collections.emptyList(); this.tokenNftAllowances = Collections.emptyList(); this.stakingInfo = stakingInfo; + this.virtualAddresses = virtualAddresses; } /** @@ -257,6 +264,10 @@ static AccountInfo fromProtobuf(CryptoGetInfoResponse.AccountInfo accountInfo) { @Nullable var aliasKey = PublicKey.fromAliasBytes(accountInfo.getAlias()); + var virtualAddresses = J8Arrays.stream(accountInfo.getVirtualAddressesList().toArray()) + .map((virtualAddress) -> VirtualAddressInfo.fromProtobuf((com.hedera.hashgraph.sdk.proto.CryptoGetInfoResponse.AccountInfo.VirtualAddressInfo)virtualAddress)) + .collect(Collectors.toList()); + return new AccountInfo( accountId, accountInfo.getContractAccountID(), @@ -278,7 +289,8 @@ static AccountInfo fromProtobuf(CryptoGetInfoResponse.AccountInfo accountInfo) { aliasKey, LedgerId.fromByteString(accountInfo.getLedgerId()), accountInfo.getEthereumNonce(), - accountInfo.hasStakingInfo() ? StakingInfo.fromProtobuf(accountInfo.getStakingInfo()) : null + accountInfo.hasStakingInfo() ? StakingInfo.fromProtobuf(accountInfo.getStakingInfo()) : null, + virtualAddresses ); } @@ -303,6 +315,10 @@ CryptoGetInfoResponse.AccountInfo toProtobuf() { .map((liveHash) -> ((LiveHash) liveHash).toProtobuf()) .collect(Collectors.toList()); + var addresses = J8Arrays.stream(virtualAddresses.toArray()) + .map((virtualAddress) -> ((VirtualAddressInfo)virtualAddress).toProtobuf()) + .collect(Collectors.toList()); + var accountInfoBuilder = CryptoGetInfoResponse.AccountInfo.newBuilder() .setAccountID(accountId.toProtobuf()) .setDeleted(isDeleted) @@ -319,7 +335,8 @@ CryptoGetInfoResponse.AccountInfo toProtobuf() { .setOwnedNfts(ownedNfts) .setMaxAutomaticTokenAssociations(maxAutomaticTokenAssociations) .setLedgerId(ledgerId.toByteString()) - .setEthereumNonce(ethereumNonce); + .setEthereumNonce(ethereumNonce) + .addAllVirtualAddresses(addresses); if (contractAccountId != null) { accountInfoBuilder.setContractAccountID(contractAccountId); @@ -364,6 +381,7 @@ public String toString() { .add("ledgerId", ledgerId) .add("ethereumNonce", ethereumNonce) .add("stakingInfo", stakingInfo) + .add("virtualAddresses", virtualAddresses) .toString(); } diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/ContractFunctionResult.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/ContractFunctionResult.java index 3b988d10e..4b32840ba 100644 --- a/sdk/src/main/java/com/hedera/hashgraph/sdk/ContractFunctionResult.java +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/ContractFunctionResult.java @@ -82,6 +82,8 @@ public final class ContractFunctionResult { @Nullable public final AccountId senderAccountId; + public final List contractNonces; + /** * Constructor. * @@ -128,6 +130,8 @@ public final class ContractFunctionResult { contractFunctionParametersBytes = inner.getFunctionParameters().toByteArray(); senderAccountId = inner.hasSenderId() ? AccountId.fromProtobuf(inner.getSenderId()) : null; + + contractNonces = StreamSupport.stream(inner.getContractNoncesList()).map(ContractNonce::fromProtobuf).collect(Collectors.toList()); } /** @@ -411,6 +415,10 @@ com.hedera.hashgraph.sdk.proto.ContractFunctionResult toProtobuf() { contractFunctionResult.setSenderId(senderAccountId.toProtobuf()); } + for (var contractNonce : contractNonces) { + contractFunctionResult.addContractNonces(contractNonce.toProtobuf()); + } + // for (var stateChange : stateChanges) { // contractFunctionResult.addStateChanges(stateChange.toProtobuf()); // } @@ -434,6 +442,7 @@ public String toString() { .add("contractFunctionparametersBytes", Hex.toHexString(contractFunctionParametersBytes)) .add("rawResult", Hex.toHexString(rawResult.toByteArray())) .add("senderAccountId", senderAccountId) + .add("contractNonces", contractNonces) .toString(); } } diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/ContractNonce.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/ContractNonce.java new file mode 100644 index 000000000..6eaf6d278 --- /dev/null +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/ContractNonce.java @@ -0,0 +1,132 @@ +/*- + * + * Hedera Java SDK + * + * Copyright (C) 2020 - 2022 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.hedera.hashgraph.sdk; + +import com.google.common.base.MoreObjects; +import com.google.protobuf.InvalidProtocolBufferException; +import com.hedera.hashgraph.sdk.proto.ContractNonceInfo; + +import java.util.Objects; + +/** + * Info about a contract account's nonce value. + * A nonce of a contract is only incremented when that contract creates another contract. + */ +public final class ContractNonce { + + /** + * The ID of the contract. + */ + public final ContractId contractId; + + /** + * The current value of the contract account's nonce property. + */ + public final long nonce; + + /** + * Constructor. + * + * @param contractId the contract ID + * @param nonce the value of the contract account's nonce + */ + public ContractNonce( + ContractId contractId, + long nonce + ) { + this.contractId = contractId; + this.nonce = nonce; + } + + /** + * Retrieve the contract nonce from a protobuf. + * + * @param contractNonce the contract nonce protobuf + * @return the contract nonce object + */ + static ContractNonce fromProtobuf(ContractNonceInfo contractNonce) { + return new ContractNonce( + ContractId.fromProtobuf(contractNonce.getContractId()), + contractNonce.getNonce() + ); + } + + /** + * Retrieve the contract nonce from a protobuf byte array. + * + * @param bytes a byte array representing the protobuf + * @return the contract nonce object + * @throws InvalidProtocolBufferException when there is an issue with the protobuf + */ + public static ContractNonce fromBytes(byte[] bytes) throws InvalidProtocolBufferException { + return fromProtobuf(ContractNonceInfo.parseFrom(bytes).toBuilder().build()); + } + + /** + * Convert a contract nonce object into a protobuf. + * + * @return the protobuf object + */ + ContractNonceInfo toProtobuf() { + var contractNonceBuilder = ContractNonceInfo.newBuilder() + .setContractId(contractId.toProtobuf()) + .setNonce(nonce); + + return contractNonceBuilder.build(); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("contractId", contractId) + .add("nonce", nonce) + .toString(); + } + + /** + * Extract a byte array representation. + * + * @return a byte array representation + */ + public byte[] toBytes() { + return toProtobuf().toByteArray(); + } + + + @Override + public int hashCode() { + return Objects.hash(contractId, nonce); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (!(o instanceof ContractNonce)) { + return false; + } + + ContractNonce otherNonce = (ContractNonce)o; + + return contractId.equals(otherNonce.contractId) && nonce == otherNonce.nonce; + } +} diff --git a/sdk/src/main/java/com/hedera/hashgraph/sdk/VirtualAddressInfo.java b/sdk/src/main/java/com/hedera/hashgraph/sdk/VirtualAddressInfo.java new file mode 100644 index 000000000..8aeae53a3 --- /dev/null +++ b/sdk/src/main/java/com/hedera/hashgraph/sdk/VirtualAddressInfo.java @@ -0,0 +1,146 @@ +/*- + * + * Hedera Java SDK + * + * Copyright (C) 2020 - 2022 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.hedera.hashgraph.sdk; + +import com.google.common.base.MoreObjects; +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; + +import java.util.Objects; + +/** + * EVM virtual address. + */ +public final class VirtualAddressInfo { + + /** + * The EVM address. + */ + public final String address; + + /** + * If true, then this is the default virtual address for a given account. + */ + public final boolean isDefault; + + /** + * The EthereumTransaction type nonce associated with this virtual address. + */ + public final long nonce; + + /** + * Constructor. + * + * @param address the virtual address + * @param isDefault is it the default address + * @param nonce nonce associated with this virtual address + */ + public VirtualAddressInfo( + String address, + boolean isDefault, + long nonce + ) { + this.address = address; + this.isDefault = isDefault; + this.nonce = nonce; + } + + /** + * Retrieve the virtual address from a protobuf. + * + * @param virtualAddress the virtual address protobuf + * @return the virtual address object + */ + static VirtualAddressInfo fromProtobuf(com.hedera.hashgraph.sdk.proto.CryptoGetInfoResponse.AccountInfo.VirtualAddressInfo virtualAddress) { + return new VirtualAddressInfo( + virtualAddress.getAddress().toString(), + virtualAddress.getIsDefault(), + virtualAddress.getNonce() + ); + } + + /** + * Retrieve the virtual address from a protobuf byte array. + * + * @param bytes a byte array representing the protobuf + * @return the virtual address object + * @throws InvalidProtocolBufferException when there is an issue with the protobuf + */ + public static VirtualAddressInfo fromBytes(byte[] bytes) throws InvalidProtocolBufferException { + return fromProtobuf(com.hedera.hashgraph.sdk.proto.CryptoGetInfoResponse.AccountInfo.VirtualAddressInfo.parseFrom(bytes).toBuilder().build()); + } + + /** + * Convert a virtual address object into a protobuf. + * + * @return the protobuf object + */ + com.hedera.hashgraph.sdk.proto.CryptoGetInfoResponse.AccountInfo.VirtualAddressInfo toProtobuf() { + var virtualAddressBuilder = com.hedera.hashgraph.sdk.proto.CryptoGetInfoResponse.AccountInfo.VirtualAddressInfo.newBuilder() + .setAddress(ByteString.fromHex(address)) + .setIsDefault(isDefault) + .setNonce(nonce); + + return virtualAddressBuilder.build(); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("address", address) + .add("default", isDefault) + .add("nonce", nonce) + .toString(); + } + + /** + * Extract a byte array representation. + * + * @return a byte array representation + */ + public byte[] toBytes() { + return toProtobuf().toByteArray(); + } + + + @Override + public int hashCode() { + // TODO - should addresses "0x123abc" and "123abc" be considered equal??? + return Objects.hash(address, isDefault, nonce); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (!(o instanceof VirtualAddressInfo)) { + return false; + } + + VirtualAddressInfo otherAddress = (VirtualAddressInfo)o; + // TODO - should addresses "0x123abc" and "123abc" be considered equal??? + return + address.equals(otherAddress.address) && + isDefault == otherAddress.isDefault && + nonce == otherAddress.nonce; + } +} diff --git a/sdk/src/main/proto/basic_types.proto b/sdk/src/main/proto/basic_types.proto index 094edc6bb..cabfef74f 100644 --- a/sdk/src/main/proto/basic_types.proto +++ b/sdk/src/main/proto/basic_types.proto @@ -1607,3 +1607,20 @@ message VirtualAddress { */ bool is_default = 2; } + +/** + * Info about a contract account's nonce value. + * A nonce of a contract is only incremented when that contract creates another contract. + */ +message ContractNonceInfo { + + /** + * Id of the contract + */ + ContractID contract_id = 1; + + /** + * The current value of the contract account's nonce property + */ + int64 nonce = 2; +} \ No newline at end of file diff --git a/sdk/src/main/proto/contract_call_local.proto b/sdk/src/main/proto/contract_call_local.proto index ecbbc48ab..d9814d95f 100644 --- a/sdk/src/main/proto/contract_call_local.proto +++ b/sdk/src/main/proto/contract_call_local.proto @@ -164,10 +164,9 @@ message ContractFunctionResult { AccountID sender_id = 13; /** - * Map used to track contract nonces for all contracts that have participated in the transaction. - * The keys would have the different contract IDs as strings in "shard.realm.num" format and the values are the new nonce values. + * A list of updated contract account nonces containing the new nonce value for each contract account */ - map contract_nonces = 14; + repeated ContractNonceInfo contract_nonces = 14; } /** diff --git a/sdk/src/main/proto/crypto_get_info.proto b/sdk/src/main/proto/crypto_get_info.proto index 039057e79..773c4e8d0 100644 --- a/sdk/src/main/proto/crypto_get_info.proto +++ b/sdk/src/main/proto/crypto_get_info.proto @@ -184,14 +184,19 @@ message CryptoGetInfoResponse { message VirtualAddressInfo { /** - * A virtual address entry. + * The 20-byte EVM address that is derived from the keccak-256 hash of a ECDSA_SECP256K1 primitive key. */ - VirtualAddress virtual_address = 1; + bytes address = 1; /** - * The ethereum transaction nonce associated with this virtual address. + * Flag if this address should now be set or is the default address on the account. */ - int64 nonce = 2; + bool is_default = 2; + + /** + * The EthereumTransaction type nonce associated with this virtual address. + */ + int64 nonce = 3; } /** diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.java b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.java index d01967afa..db4914b52 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.java +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.java @@ -19,7 +19,6 @@ */ package com.hedera.hashgraph.sdk; -import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import io.github.jsonSnapshot.SnapshotMatcher; import org.bouncycastle.util.encoders.Hex; @@ -228,24 +227,6 @@ void toSolidityAddress() { SnapshotMatcher.expect(new AccountId(5005).toSolidityAddress()).toMatchSnapshot(); } - @Test - void equalsVirtualAddresses() { - var id1 = new AccountId(1, 2, 3); - var id2 = new AccountId(1, 2, 3); - - var address1 = "302a300506032b6570032100114e6abc371b82d1"; - var address2 = "302a300506032b6570032100114e6abc371b82d2"; - - id1.virtualAddresses.add(new VirtualAddress(address1, true)); - id1.virtualAddresses.add(new VirtualAddress(address2, false)); - - // TODO - swap address 1 and 2 - id2.virtualAddresses.add(new VirtualAddress(address1, true)); - id2.virtualAddresses.add(new VirtualAddress(address2, false)); - - assertThat(id2).isEqualTo(id1); - } - @Test void fromEvmAddress() { String evmAddress = "302a300506032b6570032100114e6abc371b82da"; diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.snap b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.snap index d1bb2f2fc..ba6d16f58 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.snap +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountIdTest.snap @@ -8,11 +8,6 @@ com.hedera.hashgraph.sdk.AccountIdTest.fromBytesAlias=[ ] -com.hedera.hashgraph.sdk.AccountIdTest.fromBytesAliasEvmAddress=[ - "0.0.302a300506032b6570032100114e6abc371b82da" -] - - com.hedera.hashgraph.sdk.AccountIdTest.fromBytesEvmAddress=[ "0.0.302a300506032b6570032100114e6abc371b82da" ] @@ -33,11 +28,6 @@ com.hedera.hashgraph.sdk.AccountIdTest.fromString=[ ] -com.hedera.hashgraph.sdk.AccountIdTest.fromStringWithAliasEvmAddress=[ - "0.0.302a300506032b6570032100114e6abc371b82da" -] - - com.hedera.hashgraph.sdk.AccountIdTest.fromStringWithAliasKey=[ "0.0.302a300506032b6570032100114e6abc371b82dab5c15ea149f02d34a012087b163516dd70f44acafabf7777" ] @@ -73,11 +63,6 @@ com.hedera.hashgraph.sdk.AccountIdTest.toBytesAlias=[ ] -com.hedera.hashgraph.sdk.AccountIdTest.toBytesAliasEvmAddress=[ - "2214302a300506032b6570032100114e6abc371b82da" -] - - com.hedera.hashgraph.sdk.AccountIdTest.toBytesEvmAddress=[ "2214302a300506032b6570032100114e6abc371b82da" ] diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountInfoTest.snap b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountInfoTest.snap index bbf76e3f1..becb516d7 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountInfoTest.snap +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/AccountInfoTest.snap @@ -1,10 +1,10 @@ com.hedera.hashgraph.sdk.AccountInfoTest.fromBytes=[ - "AccountInfo{accountId=0.0.1, contractAccountId=, deleted=true, proxyAccountId=0.0.8, proxyReceived=2 tℏ, key=302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7, balance=3 tℏ, sendRecordThreshold=4 tℏ, receiveRecordThreshold=5 tℏ, receiverSignatureRequired=true, expirationTime=1970-01-01T00:00:00.006Z, autoRenewPeriod=PT168H, liveHashes=[LiveHash{accountId=0.0.10, hash=[0, 1, 2], keys=KeyList{threshold=null, keys=[302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7]}, duration=PT264H}], tokenRelationships={}, accountMemo=, ownedNfts=0, maxAutomaticTokenAssociations=0, aliasKey=null, ledgerId=previewnet, ethereumNonce=1001, stakingInfo=null}" + "AccountInfo{accountId=0.0.1, contractAccountId=, deleted=true, proxyAccountId=0.0.8, proxyReceived=2 tℏ, key=302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7, balance=3 tℏ, sendRecordThreshold=4 tℏ, receiveRecordThreshold=5 tℏ, receiverSignatureRequired=true, expirationTime=1970-01-01T00:00:00.006Z, autoRenewPeriod=PT168H, liveHashes=[LiveHash{accountId=0.0.10, hash=[0, 1, 2], keys=KeyList{threshold=null, keys=[302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7]}, duration=PT264H}], tokenRelationships={}, accountMemo=, ownedNfts=0, maxAutomaticTokenAssociations=0, aliasKey=null, ledgerId=previewnet, ethereumNonce=1001, stakingInfo=null, virtualAddresses=[]}" ] com.hedera.hashgraph.sdk.AccountInfoTest.fromProtobufWithOtherOptions=[ - "AccountInfo{accountId=0.0.1, contractAccountId=, deleted=true, proxyAccountId=0.0.8, proxyReceived=2 tℏ, key=302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7, balance=3 tℏ, sendRecordThreshold=4 tℏ, receiveRecordThreshold=5 tℏ, receiverSignatureRequired=true, expirationTime=1970-01-01T00:00:00.006Z, autoRenewPeriod=PT168H, liveHashes=[LiveHash{accountId=0.0.10, hash=[0, 1, 2], keys=KeyList{threshold=null, keys=[302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7]}, duration=PT264H}], tokenRelationships={}, accountMemo=, ownedNfts=0, maxAutomaticTokenAssociations=0, aliasKey=null, ledgerId=previewnet, ethereumNonce=1001, stakingInfo=null}" + "AccountInfo{accountId=0.0.1, contractAccountId=, deleted=true, proxyAccountId=0.0.8, proxyReceived=2 tℏ, key=302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7, balance=3 tℏ, sendRecordThreshold=4 tℏ, receiveRecordThreshold=5 tℏ, receiverSignatureRequired=true, expirationTime=1970-01-01T00:00:00.006Z, autoRenewPeriod=PT168H, liveHashes=[LiveHash{accountId=0.0.10, hash=[0, 1, 2], keys=KeyList{threshold=null, keys=[302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7]}, duration=PT264H}], tokenRelationships={}, accountMemo=, ownedNfts=0, maxAutomaticTokenAssociations=0, aliasKey=null, ledgerId=previewnet, ethereumNonce=1001, stakingInfo=null, virtualAddresses=[]}" ] diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/FileAppendTransactionTest.snap b/sdk/src/test/java/com/hedera/hashgraph/sdk/FileAppendTransactionTest.snap index c36432156..6708bb14b 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/FileAppendTransactionTest.snap +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/FileAppendTransactionTest.snap @@ -1,15 +1,15 @@ com.hedera.hashgraph.sdk.FileAppendTransactionTest.shouldGetAllSignatures=[ - "[{0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=1490ad50f0fb5af40ee1d823e4f4b2603c135b3c7979b1b0ee6a323ba494e0b5cca833157c1106b976c876b060249e7ee2db30a8566d8682a42fac2f5f4a3406, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=23a657e362da4b3ea29673c26d8b17b967c53528449d99b3154e1b81676dc8d0aa229b824f9e613803b3262bc9cecc6dc6e2fc01a21830fb1641b5ed03722e07, }, 0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=40d079bcb4a9fbdf102051328ee5f3903e166c1dd7c1e748efc95a2fdd640e421c0a8e23709b61e4d8110451adecd71cd16d1293ce0e57ea974de5b6b2ef070e, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=0cbdeaac11d392081289fb67a93a7fd995e86f55764e45b3e5eefd2f64056a38b50e8478e64cb1af5c310c321478e09b60d641a6e898820625d2674dc54ce80e, }, }, {0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=ce2b975f698ca802721c80a3792fca39d73609afaa8961bb91da569463c50eecb07d7e26e7e8febb5163474139e94533e8eb7016e0c149e0823d7102ed2b0502, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=ea31e49f64fd41773561f81459a2381e0194788853e28ffb683caded7a675d386b2a228c67ec83bfc448f14ee4fd2eae41569f06006c515621e1f26514c9bf0a, }, 0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=4b4ed404ef9a37752c070c5eb364b0df0fbe06afb0b64e0743d27767c26b1045e8532308288e2f1a40cced0782b87f20b6cfdcd8b9890c600c0e2146a48ace00, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=95444670cecb07fc452a4e3f350eca481e5462e3349a6741cd4e6746b21c66e67825c169f3b4cf82ab1853f1cf0acedc84b2f565346dc173a93f054c19966b08, }, }, {0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=47c3e240259603f3e7fa41ced3eb9931bc4350367aa6529994c048fb0aca1853630bf8fbbdf9b2768c52b91b5f5d669a4adab06ef0851107f6e8012d948ba90b, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=d1a4d3349a1bc7cd0242e09ed9b1811ea99fb6123826b946651ee8c9dd593eb40591697fad4360e3941c9eea55cd2173189df349aa16b9a11db62ed28de8ad06, }, 0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=0aedd8f92e68278823397cb0eddc1c07f1fd80c223781280a0ffb0eef21b516444e4521294ad380e8a46c7f22f1723eef8872ccf4d8aa415345e0a7fe1485c06, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=8cf7f0ae116557d5f4a5bbee82dee3cfe950c0ecedbce5d2a7b729dd7614d47c436e6951c401870f85dadd696160ecee1ab8e65aa607ca942051e78b8f09a406, }, }, {0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=63800201fd378e81946c73104907b0b0aa70ff5913889b21b4eac730e535f8acbf08f63da5824419fc14155d6fc19f23a53bfd3324d8baa68dc5d00e8974de07, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=084bdc8f8580a2ebcc0a5140f766aca111b5488092a41871d104834dda27d6b99288423835bc7114860ce6c740300ebe9f8ab576e7646097eee7d6692b90d109, }, 0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=aa009ad11594bb981504f8d4063c9d90bfb0bccc4bda8f9e3ffd326fc39e599fae94ba98110342a449437f7c848e2a9dd6de0d008e8d00c8387ff094c93c2700, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=5a2b40589f128f3bac99649d0aec7230e3c993130f36814c742ae37104e93d22e2b548d97e471f583d1c81bbcf6f916cc03f20375499e3a37b2c6b13a5a94507, }, }, {0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=e83759154409ce22146e31ff826a3ee4940916784e5953c4c0502ef5c2f9e7ca2d114223c3461a491dfebdcc11e511e91400007a1dc3827b7b98c7225239460f, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=595653b3f5cedf84e845f0dc2c503aad94b259eee4c10ad32cd86976b246cd81726ae8edc35e41e9ebae9e27a3ed96aff524b9b04481fad2722fdab8a4ee5a0f, }, 0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=645d9d66e90a104462741e2f49fe77d2edce5d49a033c9c51768a2fba6deda96a71ad95e00416bb5a8a07cfaf543a1fee8730c11af4a380d6f30ec88d2271c0d, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=2bc0f7e72aa2e953741815ac95135e50ece67543683e6da3a26bc95534d9ca538d802d567fcb154bf98001663dc46d8674ff4e9361021fbe2a55e83f9442f802, }, }, {0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=c463b37297427a620f739b3a420512f897745a8451315de360391b2f6879e644ba3a8597e4f6e3a1a135bf354bb0911fe421e0174f48b650f54e3fe86247e507, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=342e41dbd4e3ef300192767ffeb9b062b1fae68027153a84f151fdb1d3ce43592f275d87a7b90a9d6db6a67d32c6ec9e585ce199ed199cdcac0b4ef4ac12200f, }, 0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=dea30ba3201c32f5c23afac9d5b013c4e41a30d08205d21a09722f5aebb0760b2452ba254eea5008de68411560081e94ccd78c5008353aa6bb64779e79078702, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=903762ba6159fcf940281d810a268980cdf2fa35683626d52e41ad18202492fef5f8de2002c49cb56ac9d9e78177823f1f97741634237943459c31540f801502, }, }, {0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=0e3e02a08fd3a807c79c1ce2117612c2902557aa7c57da2494744f45b105f3f67b9977564f83baf2cd7dd4fe2cf0421f9367343a92d90199e97f22bc977f3d0f, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=a9ef610d944c989424477a2e31b970033bffcce8899116820f9eac06f2d06226cfe714e6a835135e2fb632dda80b439199e76870156acd6f81d4c3cf342a3706, }, 0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=9e4dcb75574c75c7e54cc76ff08bf9e6c28cb2e74f79eb4ed8e4f968e6829bd994d9fadff9fb265988de757b858e4921c7b4db119c31f6156a79eb62ffc4110c, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=195fdc0b4c9730139ede43d8e80befe7bef91ab8fa2f271173bab926cff2c797117a28716112b6d1ab3b6c669a4b923f5885b40f67885b1a64d0445ad75bbe0e, }, }, ]" + "[{0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=40d079bcb4a9fbdf102051328ee5f3903e166c1dd7c1e748efc95a2fdd640e421c0a8e23709b61e4d8110451adecd71cd16d1293ce0e57ea974de5b6b2ef070e, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=0cbdeaac11d392081289fb67a93a7fd995e86f55764e45b3e5eefd2f64056a38b50e8478e64cb1af5c310c321478e09b60d641a6e898820625d2674dc54ce80e, }, 0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=1490ad50f0fb5af40ee1d823e4f4b2603c135b3c7979b1b0ee6a323ba494e0b5cca833157c1106b976c876b060249e7ee2db30a8566d8682a42fac2f5f4a3406, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=23a657e362da4b3ea29673c26d8b17b967c53528449d99b3154e1b81676dc8d0aa229b824f9e613803b3262bc9cecc6dc6e2fc01a21830fb1641b5ed03722e07, }, }, {0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=4b4ed404ef9a37752c070c5eb364b0df0fbe06afb0b64e0743d27767c26b1045e8532308288e2f1a40cced0782b87f20b6cfdcd8b9890c600c0e2146a48ace00, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=95444670cecb07fc452a4e3f350eca481e5462e3349a6741cd4e6746b21c66e67825c169f3b4cf82ab1853f1cf0acedc84b2f565346dc173a93f054c19966b08, }, 0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=ce2b975f698ca802721c80a3792fca39d73609afaa8961bb91da569463c50eecb07d7e26e7e8febb5163474139e94533e8eb7016e0c149e0823d7102ed2b0502, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=ea31e49f64fd41773561f81459a2381e0194788853e28ffb683caded7a675d386b2a228c67ec83bfc448f14ee4fd2eae41569f06006c515621e1f26514c9bf0a, }, }, {0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=0aedd8f92e68278823397cb0eddc1c07f1fd80c223781280a0ffb0eef21b516444e4521294ad380e8a46c7f22f1723eef8872ccf4d8aa415345e0a7fe1485c06, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=8cf7f0ae116557d5f4a5bbee82dee3cfe950c0ecedbce5d2a7b729dd7614d47c436e6951c401870f85dadd696160ecee1ab8e65aa607ca942051e78b8f09a406, }, 0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=47c3e240259603f3e7fa41ced3eb9931bc4350367aa6529994c048fb0aca1853630bf8fbbdf9b2768c52b91b5f5d669a4adab06ef0851107f6e8012d948ba90b, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=d1a4d3349a1bc7cd0242e09ed9b1811ea99fb6123826b946651ee8c9dd593eb40591697fad4360e3941c9eea55cd2173189df349aa16b9a11db62ed28de8ad06, }, }, {0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=aa009ad11594bb981504f8d4063c9d90bfb0bccc4bda8f9e3ffd326fc39e599fae94ba98110342a449437f7c848e2a9dd6de0d008e8d00c8387ff094c93c2700, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=5a2b40589f128f3bac99649d0aec7230e3c993130f36814c742ae37104e93d22e2b548d97e471f583d1c81bbcf6f916cc03f20375499e3a37b2c6b13a5a94507, }, 0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=63800201fd378e81946c73104907b0b0aa70ff5913889b21b4eac730e535f8acbf08f63da5824419fc14155d6fc19f23a53bfd3324d8baa68dc5d00e8974de07, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=084bdc8f8580a2ebcc0a5140f766aca111b5488092a41871d104834dda27d6b99288423835bc7114860ce6c740300ebe9f8ab576e7646097eee7d6692b90d109, }, }, {0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=645d9d66e90a104462741e2f49fe77d2edce5d49a033c9c51768a2fba6deda96a71ad95e00416bb5a8a07cfaf543a1fee8730c11af4a380d6f30ec88d2271c0d, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=2bc0f7e72aa2e953741815ac95135e50ece67543683e6da3a26bc95534d9ca538d802d567fcb154bf98001663dc46d8674ff4e9361021fbe2a55e83f9442f802, }, 0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=e83759154409ce22146e31ff826a3ee4940916784e5953c4c0502ef5c2f9e7ca2d114223c3461a491dfebdcc11e511e91400007a1dc3827b7b98c7225239460f, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=595653b3f5cedf84e845f0dc2c503aad94b259eee4c10ad32cd86976b246cd81726ae8edc35e41e9ebae9e27a3ed96aff524b9b04481fad2722fdab8a4ee5a0f, }, }, {0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=dea30ba3201c32f5c23afac9d5b013c4e41a30d08205d21a09722f5aebb0760b2452ba254eea5008de68411560081e94ccd78c5008353aa6bb64779e79078702, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=903762ba6159fcf940281d810a268980cdf2fa35683626d52e41ad18202492fef5f8de2002c49cb56ac9d9e78177823f1f97741634237943459c31540f801502, }, 0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=c463b37297427a620f739b3a420512f897745a8451315de360391b2f6879e644ba3a8597e4f6e3a1a135bf354bb0911fe421e0174f48b650f54e3fe86247e507, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=342e41dbd4e3ef300192767ffeb9b062b1fae68027153a84f151fdb1d3ce43592f275d87a7b90a9d6db6a67d32c6ec9e585ce199ed199cdcac0b4ef4ac12200f, }, }, {0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=9e4dcb75574c75c7e54cc76ff08bf9e6c28cb2e74f79eb4ed8e4f968e6829bd994d9fadff9fb265988de757b858e4921c7b4db119c31f6156a79eb62ffc4110c, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=195fdc0b4c9730139ede43d8e80befe7bef91ab8fa2f271173bab926cff2c797117a28716112b6d1ab3b6c669a4b923f5885b40f67885b1a64d0445ad75bbe0e, }, 0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=0e3e02a08fd3a807c79c1ce2117612c2902557aa7c57da2494744f45b105f3f67b9977564f83baf2cd7dd4fe2cf0421f9367343a92d90199e97f22bc977f3d0f, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=a9ef610d944c989424477a2e31b970033bffcce8899116820f9eac06f2d06226cfe714e6a835135e2fb632dda80b439199e76870156acd6f81d4c3cf342a3706, }, }, ]" ] com.hedera.hashgraph.sdk.FileAppendTransactionTest.shouldGetSignatures=[ - "{0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=4b8fd70342b6c201f08177de53122be909d5d72f97d29fba69e7ac6ef04d96b19ac417c9b84fbb122bce9c8323bc38bd6165b5750ce16ee4a2f23e28d7123006, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=371b502056cbf34c1bd7f9891e82c7a53ab8d92ce1728f790acc9a09989196fbf4c1c111ca010a19f1af82f2480be92229b5a1aadfe4af9142bd212254c88b08, }, 0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=a762395ad7e3fa298ed990785699133ca64d11a28fb4dfc83d6d95a9a2639b688d5afc288fcdb8168f4a85876b2b785e3303ddec38666bbae4f5436d6334540b, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=8bea3d52ad5badc4ebf5e20f874cf2e5dec3189d3a471c39fd1062743ba7729de1c484f1e8ac2f15343494799e97b5ac220734a261994d91ffed9e113c09d700, }, }" + "{0.0.555={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=a762395ad7e3fa298ed990785699133ca64d11a28fb4dfc83d6d95a9a2639b688d5afc288fcdb8168f4a85876b2b785e3303ddec38666bbae4f5436d6334540b, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=8bea3d52ad5badc4ebf5e20f874cf2e5dec3189d3a471c39fd1062743ba7729de1c484f1e8ac2f15343494799e97b5ac220734a261994d91ffed9e113c09d700, }, 0.0.444={302a300506032b6570032100e0c8ec2758a5879ffac226a13c0c516b799e72e35141a0dd828f94d37988a4b7=4b8fd70342b6c201f08177de53122be909d5d72f97d29fba69e7ac6ef04d96b19ac417c9b84fbb122bce9c8323bc38bd6165b5750ce16ee4a2f23e28d7123006, 302a300506032b657003210072a1a2b6b694902f095ac85c6a5fa96ab1a87933e3fc1fd66e57ac6af628ca2d=371b502056cbf34c1bd7f9891e82c7a53ab8d92ce1728f790acc9a09989196fbf4c1c111ca010a19f1af82f2480be92229b5a1aadfe4af9142bd212254c88b08, }, }" ] com.hedera.hashgraph.sdk.FileAppendTransactionTest.shouldHash=[ - "[{0.0.444=38603d6b2a449030ea49b7cbd7e19cd66b4e3f2891ca40df861b4840418cb08575b7ce25426b1192545d352a89f0f3da, 0.0.555=d2f10044785bb7ecbfc024a171b28ec877a123a2b6f3b2a48db5595208ea8bd036e4c4babb682d87e06ce62d7c2b1bb3, }, {0.0.444=0939a5cbfb9bbbd545d3e9f961e7fc3bcbf49553ce7e3a00414b5b0964ca9aae0ea878e280efa217503aed65d1057880, 0.0.555=74ed3e44b14e41ad5964a52adde1c32932b9dd75f589d0985504bbc483dc778493866ae879769d693e2a6fa80c6a118c, }, {0.0.444=1332b1dfb679ea2a91b21de2bed0d086c5139893fce55b0471e2b08ec2e0fbbcee48783eda0a1e876ee0a7086416c26a, 0.0.555=9ef69da0531b3828cfc5b14cb5df373ae46922ad192df9d488684b845ce4754b2a20c1e966d2835ea178890fdaac9a00, }, {0.0.444=2deb2d9674c3e238c53080ad4d139f172dc907ba4b898210ed9359f3db92f0880503cca4fec35cd6b47c71ba5dd46aa3, 0.0.555=e62ca0554d6e40461dbecc035165d35716d61eae59a305414a91a6fb85f36ba3adc1f6b963c429366485fe514407d294, }, {0.0.444=dbb52ed2eea79c5cc58bb0b898ce03f4ee7d4ba6ad94c0d718c0c6b46fd8cea9e2ab76c42221fce44933827e382df57f, 0.0.555=8a7721e7a8d8eede13e0ab5adb5c9520af6099c909592f45f9dc89775f69e16a2bea4a392480f1b750c817787a94099f, }, {0.0.444=16c12a7acaa5754a1e1adfc40550e5d4b09195c2347dc4fda3882d7a2823dd212ea1682642f211290b8985d45be55a0b, 0.0.555=0292097e1f3bdd4390134f10b51b2c9928fcfbe4fd54de25d407ee8b93c6ede6dda4c4263786d983de47413f541834e0, }, {0.0.444=5571dfcd8a279d4c33c0e9199c865556ab3aec478ddbc1560dd9c41c53423decb95348fb54b63cbc744fd1e496b2a01f, 0.0.555=e4c53e598718933cc67491218c478c23be4637e9d89107a3c1699f04143c421fd6bf5f2ff11d31ea646103cd7cd00b57, }, ]" + "[{0.0.555=d2f10044785bb7ecbfc024a171b28ec877a123a2b6f3b2a48db5595208ea8bd036e4c4babb682d87e06ce62d7c2b1bb3, 0.0.444=38603d6b2a449030ea49b7cbd7e19cd66b4e3f2891ca40df861b4840418cb08575b7ce25426b1192545d352a89f0f3da, }, {0.0.555=74ed3e44b14e41ad5964a52adde1c32932b9dd75f589d0985504bbc483dc778493866ae879769d693e2a6fa80c6a118c, 0.0.444=0939a5cbfb9bbbd545d3e9f961e7fc3bcbf49553ce7e3a00414b5b0964ca9aae0ea878e280efa217503aed65d1057880, }, {0.0.555=9ef69da0531b3828cfc5b14cb5df373ae46922ad192df9d488684b845ce4754b2a20c1e966d2835ea178890fdaac9a00, 0.0.444=1332b1dfb679ea2a91b21de2bed0d086c5139893fce55b0471e2b08ec2e0fbbcee48783eda0a1e876ee0a7086416c26a, }, {0.0.555=e62ca0554d6e40461dbecc035165d35716d61eae59a305414a91a6fb85f36ba3adc1f6b963c429366485fe514407d294, 0.0.444=2deb2d9674c3e238c53080ad4d139f172dc907ba4b898210ed9359f3db92f0880503cca4fec35cd6b47c71ba5dd46aa3, }, {0.0.555=8a7721e7a8d8eede13e0ab5adb5c9520af6099c909592f45f9dc89775f69e16a2bea4a392480f1b750c817787a94099f, 0.0.444=dbb52ed2eea79c5cc58bb0b898ce03f4ee7d4ba6ad94c0d718c0c6b46fd8cea9e2ab76c42221fce44933827e382df57f, }, {0.0.555=0292097e1f3bdd4390134f10b51b2c9928fcfbe4fd54de25d407ee8b93c6ede6dda4c4263786d983de47413f541834e0, 0.0.444=16c12a7acaa5754a1e1adfc40550e5d4b09195c2347dc4fda3882d7a2823dd212ea1682642f211290b8985d45be55a0b, }, {0.0.555=e4c53e598718933cc67491218c478c23be4637e9d89107a3c1699f04143c421fd6bf5f2ff11d31ea646103cd7cd00b57, 0.0.444=5571dfcd8a279d4c33c0e9199c865556ab3aec478ddbc1560dd9c41c53423decb95348fb54b63cbc744fd1e496b2a01f, }, ]" ] diff --git a/sdk/src/test/java/com/hedera/hashgraph/sdk/TransactionRecordTest.snap b/sdk/src/test/java/com/hedera/hashgraph/sdk/TransactionRecordTest.snap index 7e77a37f0..914227851 100644 --- a/sdk/src/test/java/com/hedera/hashgraph/sdk/TransactionRecordTest.snap +++ b/sdk/src/test/java/com/hedera/hashgraph/sdk/TransactionRecordTest.snap @@ -1,8 +1,8 @@ com.hedera.hashgraph.sdk.TransactionRecordTest.shouldSerialize2=[ - "TransactionRecord{receipt=TransactionReceipt{transactionId=null, status=SCHEDULE_ALREADY_DELETED, exchangeRate=ExchangeRate{hbars=3, cents=4, expirationTime=2019-04-01T22:42:22Z, exchangeRateInCents=1.3333333333333333}, accountId=1.2.3, fileId=4.5.6, contractId=3.2.1, topicId=9.8.7, tokenId=6.5.4, topicSequenceNumber=3, topicRunningHash=[54, 56, 54, 102, 55, 55, 50, 48, 54, 101, 54, 102, 55, 55, 50, 48, 54, 50, 55, 50, 54, 102, 55, 55, 54, 101, 50, 48, 54, 51, 54, 102, 55, 55], totalSupply=30, scheduleId=1.1.1, scheduledTransactionId=3.3.3@1554158542.0, serials=[1, 2, 3], duplicates=[], children=[]}, transactionHash=68656c6c6f, consensusTimestamp=2019-04-01T22:42:22Z, transactionId=3.3.3@1554158542.0, transactionMemo=memo, transactionFee=3000 tℏ, contractFunctionResult=ContractFunctionResult{contractId=1.2.3, evmAddress=1.2.98329e006610472e6b372c080833f6d79ed833cf, errorMessage=null, bloom=, gasUsed=0, logs=[], createdContractIds=[], stateChanges=[], gas=0, hbarAmount=0 tℏ, contractFunctionparametersBytes=, rawResult=00000000000000000000000000000000000000000000000000000000ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000011223344556677889900aabbccddeeff00112233ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001448656c6c6f2c20776f726c642c20616761696e21000000000000000000000000, senderAccountId=1.2.3}, transfers=[Transfer{accountId=4.4.4, amount=5 ℏ}], tokenTransfers={6.6.6={1.1.1=4}}, tokenNftTransfers={4.4.4=[TokenNftTransfer{tokenId=4.4.4, sender=1.2.3, receiver=3.2.1, serial=4, isApproved=true}]}, scheduleRef=3.3.3, assessedCustomFees=[AssessedCustomFee{amount=4, tokenId=4.5.6, feeCollectorAccountId=8.6.5, payerAccountIdList=[3.3.3]}], automaticTokenAssociations=[TokenAssociation{tokenId=5.4.3, accountId=8.7.6}], aliasKey=302d300706052b8104000a03220002703a9370b0443be6ae7c507b0aec81a55e94e4a863b9655360bd65358caa6588, children=[], duplicates=[], parentConsensusTimestamp=2019-04-01T22:42:22Z, ethereumHash=536f6d652068617368, paidStakingRewards=[Transfer{accountId=1.2.3, amount=8 ℏ}], prngBytes=null, prngNumber=4, evmAddress=30783030}" + "TransactionRecord{receipt=TransactionReceipt{transactionId=null, status=SCHEDULE_ALREADY_DELETED, exchangeRate=ExchangeRate{hbars=3, cents=4, expirationTime=2019-04-01T22:42:22Z, exchangeRateInCents=1.3333333333333333}, accountId=1.2.3, fileId=4.5.6, contractId=3.2.1, topicId=9.8.7, tokenId=6.5.4, topicSequenceNumber=3, topicRunningHash=[54, 56, 54, 102, 55, 55, 50, 48, 54, 101, 54, 102, 55, 55, 50, 48, 54, 50, 55, 50, 54, 102, 55, 55, 54, 101, 50, 48, 54, 51, 54, 102, 55, 55], totalSupply=30, scheduleId=1.1.1, scheduledTransactionId=3.3.3@1554158542.0, serials=[1, 2, 3], duplicates=[], children=[]}, transactionHash=68656c6c6f, consensusTimestamp=2019-04-01T22:42:22Z, transactionId=3.3.3@1554158542.0, transactionMemo=memo, transactionFee=3000 tℏ, contractFunctionResult=ContractFunctionResult{contractId=1.2.3, evmAddress=1.2.98329e006610472e6b372c080833f6d79ed833cf, errorMessage=null, bloom=, gasUsed=0, logs=[], createdContractIds=[], stateChanges=[], gas=0, hbarAmount=0 tℏ, contractFunctionparametersBytes=, rawResult=00000000000000000000000000000000000000000000000000000000ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000011223344556677889900aabbccddeeff00112233ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001448656c6c6f2c20776f726c642c20616761696e21000000000000000000000000, senderAccountId=1.2.3, contractNonces=[]}, transfers=[Transfer{accountId=4.4.4, amount=5 ℏ}], tokenTransfers={6.6.6={1.1.1=4}}, tokenNftTransfers={4.4.4=[TokenNftTransfer{tokenId=4.4.4, sender=1.2.3, receiver=3.2.1, serial=4, isApproved=true}]}, scheduleRef=3.3.3, assessedCustomFees=[AssessedCustomFee{amount=4, tokenId=4.5.6, feeCollectorAccountId=8.6.5, payerAccountIdList=[3.3.3]}], automaticTokenAssociations=[TokenAssociation{tokenId=5.4.3, accountId=8.7.6}], aliasKey=302d300706052b8104000a03220002703a9370b0443be6ae7c507b0aec81a55e94e4a863b9655360bd65358caa6588, children=[], duplicates=[], parentConsensusTimestamp=2019-04-01T22:42:22Z, ethereumHash=536f6d652068617368, paidStakingRewards=[Transfer{accountId=1.2.3, amount=8 ℏ}], prngBytes=null, prngNumber=4, evmAddress=30783030}" ] com.hedera.hashgraph.sdk.TransactionRecordTest.shouldSerialize=[ - "TransactionRecord{receipt=TransactionReceipt{transactionId=null, status=SCHEDULE_ALREADY_DELETED, exchangeRate=ExchangeRate{hbars=3, cents=4, expirationTime=2019-04-01T22:42:22Z, exchangeRateInCents=1.3333333333333333}, accountId=1.2.3, fileId=4.5.6, contractId=3.2.1, topicId=9.8.7, tokenId=6.5.4, topicSequenceNumber=3, topicRunningHash=[54, 56, 54, 102, 55, 55, 50, 48, 54, 101, 54, 102, 55, 55, 50, 48, 54, 50, 55, 50, 54, 102, 55, 55, 54, 101, 50, 48, 54, 51, 54, 102, 55, 55], totalSupply=30, scheduleId=1.1.1, scheduledTransactionId=3.3.3@1554158542.0, serials=[1, 2, 3], duplicates=[], children=[]}, transactionHash=68656c6c6f, consensusTimestamp=2019-04-01T22:42:22Z, transactionId=3.3.3@1554158542.0, transactionMemo=memo, transactionFee=3000 tℏ, contractFunctionResult=ContractFunctionResult{contractId=1.2.3, evmAddress=1.2.98329e006610472e6b372c080833f6d79ed833cf, errorMessage=null, bloom=, gasUsed=0, logs=[], createdContractIds=[], stateChanges=[], gas=0, hbarAmount=0 tℏ, contractFunctionparametersBytes=, rawResult=00000000000000000000000000000000000000000000000000000000ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000011223344556677889900aabbccddeeff00112233ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001448656c6c6f2c20776f726c642c20616761696e21000000000000000000000000, senderAccountId=1.2.3}, transfers=[Transfer{accountId=4.4.4, amount=5 ℏ}], tokenTransfers={6.6.6={1.1.1=4}}, tokenNftTransfers={4.4.4=[TokenNftTransfer{tokenId=4.4.4, sender=1.2.3, receiver=3.2.1, serial=4, isApproved=true}]}, scheduleRef=3.3.3, assessedCustomFees=[AssessedCustomFee{amount=4, tokenId=4.5.6, feeCollectorAccountId=8.6.5, payerAccountIdList=[3.3.3]}], automaticTokenAssociations=[TokenAssociation{tokenId=5.4.3, accountId=8.7.6}], aliasKey=302d300706052b8104000a03220002703a9370b0443be6ae7c507b0aec81a55e94e4a863b9655360bd65358caa6588, children=[], duplicates=[], parentConsensusTimestamp=2019-04-01T22:42:22Z, ethereumHash=536f6d652068617368, paidStakingRewards=[Transfer{accountId=1.2.3, amount=8 ℏ}], prngBytes=766572792072616e646f6d206279746573, prngNumber=null, evmAddress=30783030}" -] + "TransactionRecord{receipt=TransactionReceipt{transactionId=null, status=SCHEDULE_ALREADY_DELETED, exchangeRate=ExchangeRate{hbars=3, cents=4, expirationTime=2019-04-01T22:42:22Z, exchangeRateInCents=1.3333333333333333}, accountId=1.2.3, fileId=4.5.6, contractId=3.2.1, topicId=9.8.7, tokenId=6.5.4, topicSequenceNumber=3, topicRunningHash=[54, 56, 54, 102, 55, 55, 50, 48, 54, 101, 54, 102, 55, 55, 50, 48, 54, 50, 55, 50, 54, 102, 55, 55, 54, 101, 50, 48, 54, 51, 54, 102, 55, 55], totalSupply=30, scheduleId=1.1.1, scheduledTransactionId=3.3.3@1554158542.0, serials=[1, 2, 3], duplicates=[], children=[]}, transactionHash=68656c6c6f, consensusTimestamp=2019-04-01T22:42:22Z, transactionId=3.3.3@1554158542.0, transactionMemo=memo, transactionFee=3000 tℏ, contractFunctionResult=ContractFunctionResult{contractId=1.2.3, evmAddress=1.2.98329e006610472e6b372c080833f6d79ed833cf, errorMessage=null, bloom=, gasUsed=0, logs=[], createdContractIds=[], stateChanges=[], gas=0, hbarAmount=0 tℏ, contractFunctionparametersBytes=, rawResult=00000000000000000000000000000000000000000000000000000000ffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000011223344556677889900aabbccddeeff00112233ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001448656c6c6f2c20776f726c642c20616761696e21000000000000000000000000, senderAccountId=1.2.3, contractNonces=[]}, transfers=[Transfer{accountId=4.4.4, amount=5 ℏ}], tokenTransfers={6.6.6={1.1.1=4}}, tokenNftTransfers={4.4.4=[TokenNftTransfer{tokenId=4.4.4, sender=1.2.3, receiver=3.2.1, serial=4, isApproved=true}]}, scheduleRef=3.3.3, assessedCustomFees=[AssessedCustomFee{amount=4, tokenId=4.5.6, feeCollectorAccountId=8.6.5, payerAccountIdList=[3.3.3]}], automaticTokenAssociations=[TokenAssociation{tokenId=5.4.3, accountId=8.7.6}], aliasKey=302d300706052b8104000a03220002703a9370b0443be6ae7c507b0aec81a55e94e4a863b9655360bd65358caa6588, children=[], duplicates=[], parentConsensusTimestamp=2019-04-01T22:42:22Z, ethereumHash=536f6d652068617368, paidStakingRewards=[Transfer{accountId=1.2.3, amount=8 ℏ}], prngBytes=766572792072616e646f6d206279746573, prngNumber=null, evmAddress=30783030}" +] \ No newline at end of file