-
Notifications
You must be signed in to change notification settings - Fork 235
feat: Added Transaction size calculation methods #1795
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
ae51c62
98640ad
20b7212
9f7653f
aa66c50
97c2e9a
caf53f6
3c632c3
143d94a
d6226fc
80c6f1e
a309236
0bd3381
b4d3adc
5efa8d5
2fe2e85
77f9c7c
e061686
098356f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -28,6 +28,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if TYPE_CHECKING: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from hiero_sdk_python.client import Client | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from hiero_sdk_python.crypto.private_key import PrivateKey | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from hiero_sdk_python.key import PrivateKey | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from hiero_sdk_python.channels import _Channel | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from hiero_sdk_python.executable import _Method | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from hiero_sdk_python.transaction.transaction import TransactionReceipt | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -284,42 +285,31 @@ def freeze_with(self, client: "Client") -> FileAppendTransaction: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return self | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self.transaction_id is None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.transaction_id = client.generate_transaction_id() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._resolve_transaction_id(client) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Generate transaction IDs for all chunks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._transaction_ids = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| base_timestamp = self.transaction_id.valid_start | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for i in range(self.get_required_chunks()): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if i == 0: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # First chunk uses the original transaction ID | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chunk_transaction_id = self.transaction_id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Subsequent chunks get incremented timestamps | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Add i nanoseconds to space out chunks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chunk_valid_start = timestamp_pb2.Timestamp( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| seconds=base_timestamp.seconds, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nanos=base_timestamp.nanos + i | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chunk_transaction_id = TransactionId( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| account_id=self.transaction_id.account_id, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| valid_start=chunk_valid_start | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._transaction_ids.append(chunk_transaction_id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # We iterate through every node in the client's network | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # For each node, set the node_account_id and build the transaction body | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # This allows the transaction to be submitted to any node in the network | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for node in client.network.nodes: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.node_account_id = node._account_id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| transaction_body = self.build_transaction_body() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._transaction_body_bytes[node._account_id] = transaction_body.SerializeToString() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Set the node account id to the current node in the network | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.node_account_id = client.network.current_node._account_id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return self | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not self._transaction_ids: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| base_timestamp = self.transaction_id.valid_start | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for i in range(self.get_required_chunks()): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if i == 0: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # First chunk uses the original transaction ID | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chunk_transaction_id = self.transaction_id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Subsequent chunks get incremented timestamps | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Add i nanoseconds to space out chunks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chunk_valid_start = timestamp_pb2.Timestamp( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| seconds=base_timestamp.seconds, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nanos=base_timestamp.nanos + i | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chunk_transaction_id = TransactionId( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| account_id=self.transaction_id.account_id, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| valid_start=chunk_valid_start | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+291
to
+308
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, let's look at the file_append_transaction.py code around lines 307-310
head -n 320 src/hiero_sdk_python/file/file_append_transaction.py | tail -n 40Repository: hiero-ledger/hiero-sdk-python Length of output: 1610 🏁 Script executed: # Check the full freeze_with method and chunk ID generation
sed -n '270,320p' src/hiero_sdk_python/file/file_append_transaction.pyRepository: hiero-ledger/hiero-sdk-python Length of output: 2038 🏁 Script executed: # Look at the body_size_all_chunks implementation mentioned
sed -n '460,480p' src/hiero_sdk_python/file/file_append_transaction.pyRepository: hiero-ledger/hiero-sdk-python Length of output: 593 🏁 Script executed: # Check protobuf Timestamp definition - find where it's imported/defined
find src -name "timestamp_pb2.py" -o -name "*.proto" | head -20Repository: hiero-ledger/hiero-sdk-python Length of output: 55 🏁 Script executed: # Search for similar timestamp overflow handling in topic transactions
rg "chunk.*timestamp|nanos.*i|second.*total_nanos" src/hiero_sdk_python --type py -B 2 -A 2Repository: hiero-ledger/hiero-sdk-python Length of output: 8576 🏁 Script executed: # Check body_size property implementation
rg "def body_size|@property" src/hiero_sdk_python/file/file_append_transaction.py -A 5Repository: hiero-ledger/hiero-sdk-python Length of output: 287 🏁 Script executed: # Check how body_size is calculated - likely in parent Transaction class
rg "def body_size" src/hiero_sdk_python/transaction/transaction.py -A 10Repository: hiero-ledger/hiero-sdk-python Length of output: 268 🏁 Script executed: # Look for _current_chunk_index usage in FileAppendTransaction
rg "_current_chunk_index" src/hiero_sdk_python/file/file_append_transaction.py -B 2 -A 2Repository: hiero-ledger/hiero-sdk-python Length of output: 1017 🏁 Script executed: # Check the protobuf Timestamp field constraints
rg "class.*Timestamp|nanos.*999" src/hiero_sdk_python/hapi -r --type py | head -20Repository: hiero-ledger/hiero-sdk-python Length of output: 181 🏁 Script executed: # Check if there are any existing tests for chunk timestamp generation
fd "test.*file.*append" src/hiero_sdk_python --type fRepository: hiero-ledger/hiero-sdk-python Length of output: 55 🏁 Script executed: # Look at tests to see how chunk timestamps are validated
find . -path "*/test*" -name "*file*append*.py" -o -path "*/test*" -name "*append*.py" | head -5Repository: hiero-ledger/hiero-sdk-python Length of output: 173 🏁 Script executed: # Look at the chunk_index usage in build_transaction_body
rg "build_transaction_body|_current_chunk_index" src/hiero_sdk_python/file/file_append_transaction.py -B 3 -A 3Repository: hiero-ledger/hiero-sdk-python Length of output: 1529 🏁 Script executed: # Check what body_size calls and how it uses _current_chunk_index
sed -n '1,100p' src/hiero_sdk_python/file/file_append_transaction.py | grep -A 20 "def build_transaction_body"Repository: hiero-ledger/hiero-sdk-python Length of output: 55 🏁 Script executed: # Look at the full build_transaction_body implementation
sed -n '150,250p' src/hiero_sdk_python/file/file_append_transaction.pyRepository: hiero-ledger/hiero-sdk-python Length of output: 3615 🏁 Script executed: # Check if Timestamp class wraps protobuf Timestamp
cat src/hiero_sdk_python/timestamp.pyRepository: hiero-ledger/hiero-sdk-python Length of output: 5051 🏁 Script executed: # Look at what type transaction_id.valid_start is
rg "valid_start" src/hiero_sdk_python/transaction/transaction_id.py -B 2 -A 2 | head -30Repository: hiero-ledger/hiero-sdk-python Length of output: 1155 🏁 Script executed: # Check the unit tests for FileAppendTransaction
head -n 100 tests/unit/file_append_transaction_test.pyRepository: hiero-ledger/hiero-sdk-python Length of output: 3737 🏁 Script executed: # Check the exact protobuf Timestamp definition for nanos bounds
rg "nanos" src/hiero_sdk_python/hapi/services -l | head -5Repository: hiero-ledger/hiero-sdk-python Length of output: 147 🏁 Script executed: # Verify the protobuf constraints - check imported timestamp_pb2
python3 << 'EOF'
# Check what constraints protobuf enforces on Timestamp.nanos
from google.protobuf import descriptor
try:
from hiero_sdk_python.hapi.services import timestamp_pb2
print("Timestamp message fields:")
for field in timestamp_pb2.Timestamp.DESCRIPTOR.fields:
print(f" {field.name}: {field.type} (label: {field.label})")
except Exception as e:
print(f"Error: {e}")
EOFRepository: hiero-ledger/hiero-sdk-python Length of output: 114 🏁 Script executed: # Search for how body_size_all_chunks should work - check similar implementation in topic_message_submit_transaction
rg "body_size_all_chunks" src/hiero_sdk_python/consensus/topic_message_submit_transaction.py -A 15Repository: hiero-ledger/hiero-sdk-python Length of output: 545 🏁 Script executed: # Verify that _current_chunk_index is supposed to be used when calculating body_size
rg "_current_chunk_index|start_index.*chunk_size" src/hiero_sdk_python/file/file_append_transaction.py -B 2 -A 2Repository: hiero-ledger/hiero-sdk-python Length of output: 1018 🏁 Script executed: # Check if body_size_all_chunks in topic_message_submit_transaction also has the same issue
sed -n '450,480p' src/hiero_sdk_python/consensus/topic_message_submit_transaction.pyRepository: hiero-ledger/hiero-sdk-python Length of output: 55 🏁 Script executed: # Look at how execute() properly updates _current_chunk_index
sed -n '320,350p' src/hiero_sdk_python/file/file_append_transaction.pyRepository: hiero-ledger/hiero-sdk-python Length of output: 979 🏁 Script executed: # Verify protobuf Timestamp nanos maximum value by checking Google protobuf docs or imports
rg "timestamp_pb2" src/hiero_sdk_python -l | head -3 | xargs grep -l "Timestamp"Repository: hiero-ledger/hiero-sdk-python Length of output: 203 🏁 Script executed: # Check imports in file_append_transaction to see if using protobuf Timestamp or SDK Timestamp
head -n 30 src/hiero_sdk_python/file/file_append_transaction.pyRepository: hiero-ledger/hiero-sdk-python Length of output: 1265 🏁 Script executed: # Look at how the SDK's Timestamp.plus_nanos handles overflow properly
sed -n '95,110p' src/hiero_sdk_python/timestamp.pyRepository: hiero-ledger/hiero-sdk-python Length of output: 558 🏁 Script executed: # Check if there are any validation tests for timestamp bounds
rg "nanos.*99" tests/unit -l | head -3Repository: hiero-ledger/hiero-sdk-python Length of output: 55 🏁 Script executed: # Verify the actual behavior by checking what chunk_index should do
sed -n '195,220p' src/hiero_sdk_python/file/file_append_transaction.pyRepository: hiero-ledger/hiero-sdk-python Length of output: 1016 🏁 Script executed: # Check if there's loop update logic we might have missed
sed -n '468,476p' src/hiero_sdk_python/file/file_append_transaction.pyRepository: hiero-ledger/hiero-sdk-python Length of output: 367 BLOCKER: Add nanosecond carry logic to prevent timestamp overflow. Lines 307-310 add BLOCKER: Advance Lines 468-476: The loop iterates over transaction IDs but never updates Suggested fixesFor timestamp overflow: - chunk_valid_start = timestamp_pb2.Timestamp(
- seconds=base_timestamp.seconds,
- nanos=base_timestamp.nanos + i
- )
+ total_nanos = base_timestamp.nanos + i
+ chunk_valid_start = timestamp_pb2.Timestamp(
+ seconds=base_timestamp.seconds + total_nanos // 1_000_000_000,
+ nanos=total_nanos % 1_000_000_000,
+ )For body_size_all_chunks: original_index = self._current_chunk_index
for transaction_id in self._transaction_ids:
self.transaction_id = transaction_id
+ self._current_chunk_index = self._transaction_ids.index(transaction_id)
sizes.append(self.body_size)
self._current_chunk_index = original_index📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._transaction_ids.append(chunk_transaction_id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return super().freeze_with(client) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @overload | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def execute( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -461,4 +451,23 @@ def sign(self, private_key: "PrivateKey") -> FileAppendTransaction: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Call the parent sign method for the current transaction | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| super().sign(private_key) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return self | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return self | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @property | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def body_size_all_chunks(self) -> List[int]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Returns an array of body sizes for transactions with multiple chunks. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._require_frozen() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sizes = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| original_index = self._current_chunk_index | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| original_transaction_id = self.transaction_id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for transaction_id in self._transaction_ids: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.transaction_id = transaction_id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sizes.append(self.body_size) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._current_chunk_index = original_index | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.transaction_id = original_transaction_id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return sizes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
manishdait marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -124,6 +124,8 @@ def _get_channel(self): | |
| if self._root_certificates: | ||
| # Use the certificate that is provided | ||
| self._node_pem_cert = self._root_certificates | ||
| print("node cert ", self._node_pem_cert) | ||
|
|
||
|
Comment on lines
124
to
+128
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove the certificate debug dump. This branch runs in normal SDK usage whenever custom root certificates are configured, and it writes the full PEM bundle to stdout. That leaks certificate material into application/test logs and bypasses the SDK logger configuration. 🛡️ Proposed fix if self._address._is_transport_security():
if self._root_certificates:
# Use the certificate that is provided
self._node_pem_cert = self._root_certificates
- print("node cert ", self._node_pem_cert)
else: |
||
| else: | ||
| # Fetch pem_cert for the node | ||
| self._node_pem_cert = self._fetch_server_certificate_pem() | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,15 @@ | ||
| import pytest | ||
| from pytest import mark | ||
|
|
||
| from hiero_sdk_python.account.account_id import AccountId | ||
| from hiero_sdk_python.file.file_create_transaction import FileCreateTransaction | ||
| from hiero_sdk_python.file.file_append_transaction import FileAppendTransaction | ||
| from hiero_sdk_python.file.file_contents_query import FileContentsQuery | ||
| from hiero_sdk_python.file.file_id import FileId | ||
| from hiero_sdk_python.response_code import ResponseCode | ||
| from hiero_sdk_python.hbar import Hbar | ||
| from hiero_sdk_python.exceptions import PrecheckError | ||
| from hiero_sdk_python.transaction.transaction_id import TransactionId | ||
| from tests.integration.utils import env, IntegrationTestEnv | ||
|
|
||
| # Generate big contents for chunking tests - similar to JavaScript bigContents | ||
|
|
@@ -304,3 +306,40 @@ def test_integration_file_append_transaction_method_chaining(env): | |
|
|
||
| append_receipt = append_tx.execute(env.client) | ||
| assert append_receipt.status == ResponseCode.SUCCESS | ||
|
|
||
| @pytest.mark.integration | ||
| def test_file_append_chunk_transaction_can_execute_with_manual_freeze(env): | ||
| """Test file append transaction can execute with manual freeze.""" | ||
| create_receipt = ( | ||
| FileCreateTransaction() | ||
| .set_keys(env.client.operator_private_key.public_key()) | ||
| .set_contents(b"") | ||
| .execute(env.client) | ||
| ) | ||
|
|
||
| assert create_receipt.status == ResponseCode.SUCCESS | ||
| file_id = create_receipt.file_id | ||
|
|
||
| file_contents = FileContentsQuery().set_file_id(file_id).execute(env.client) | ||
| assert file_contents == b"" | ||
|
|
||
| content = "A" * (4000) # content with (4000/1024) bytes ie approx 4 chunks | ||
|
|
||
| tx = ( | ||
| FileAppendTransaction() | ||
| .set_file_id(file_id) | ||
| .set_chunk_size(1024) | ||
| .set_contents(content) | ||
| .set_transaction_id(TransactionId.generate(env.client.operator_account_id)) | ||
| .set_node_account_id(AccountId(0,0,3)) | ||
| .freeze() | ||
|
Comment on lines
+328
to
+335
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use a configured network node instead of hardcoding This only covers the manual-freeze path on environments that expose that exact node account. Pulling the node ID from 🧪 Proposed fix+ node_account_id = next(node._account_id for node in env.client.network.nodes)
+
tx = (
FileAppendTransaction()
.set_file_id(file_id)
.set_chunk_size(1024)
.set_contents(content)
.set_transaction_id(TransactionId.generate(env.client.operator_account_id))
- .set_node_account_id(AccountId(0,0,3))
+ .set_node_account_id(node_account_id)
.freeze()
) |
||
| ) | ||
|
|
||
| tx.sign(env.client.operator_private_key) | ||
|
|
||
| receipt = tx.execute(env.client) | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| assert receipt.status == ResponseCode.SUCCESS | ||
|
|
||
| file_contents = FileContentsQuery().set_file_id(file_id).execute(env.client) | ||
| assert file_contents == bytes(content, "utf-8") | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |
|
|
||
| import pytest | ||
|
|
||
| from hiero_sdk_python.account.account_id import AccountId | ||
| from hiero_sdk_python.consensus.topic_create_transaction import TopicCreateTransaction | ||
| from hiero_sdk_python.consensus.topic_delete_transaction import TopicDeleteTransaction | ||
| from hiero_sdk_python.consensus.topic_message_submit_transaction import ( | ||
|
|
@@ -16,6 +17,7 @@ | |
| from hiero_sdk_python.response_code import ResponseCode | ||
| from hiero_sdk_python.tokens.custom_fixed_fee import CustomFixedFee | ||
| from hiero_sdk_python.transaction.custom_fee_limit import CustomFeeLimit | ||
| from hiero_sdk_python.transaction.transaction_id import TransactionId | ||
| from tests.integration.utils import env | ||
|
|
||
| def create_topic(client, admin_key=None, submit_key=None, custom_fees=None): | ||
|
|
@@ -342,4 +344,37 @@ def test_integration_topic_message_submit_transaction_fails_if_required_chunk_gr | |
| with pytest.raises(ValueError, match="Message requires 4 chunks but max_chunks=2. Increase limit with set_max_chunks()."): | ||
| message_transaction.execute(env.client) | ||
|
|
||
| delete_topic(env.client, topic_id) | ||
| delete_topic(env.client, topic_id) | ||
|
|
||
|
|
||
| @pytest.mark.integration | ||
| def test_topic_message_submit_transaction_can_submit_a_large_message_manual_freeze(env): | ||
| """Test topic message submit transaction can submit large message with manual freeze.""" | ||
| topic_id = create_topic( | ||
| client=env.client, | ||
| admin_key=env.operator_key | ||
| ) | ||
|
|
||
| info = TopicInfoQuery().set_topic_id(topic_id).execute(env.client) | ||
| assert info.sequence_number == 0 | ||
|
|
||
| message = "A" * (1024 * 14) # message with (1024 * 14) bytes ie 14 chunks | ||
|
|
||
| message_tx = ( | ||
| TopicMessageSubmitTransaction() | ||
| .set_topic_id(topic_id) | ||
| .set_message(message) | ||
| .set_transaction_id(TransactionId.generate(env.client.operator_account_id)) | ||
| .set_node_account_id(AccountId(0,0,3)) | ||
| .freeze() | ||
|
Comment on lines
+363
to
+369
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use a node from Hard-coding a specific node account ID makes this manual-freeze test environment-dependent. If the configured integration network exposes a different node set, the test fails for the wrong reason instead of validating the manual-freeze path. 🛠️ Proposed fix+ node_account_id = env.client.network.nodes[0]._account_id
message_tx = (
TopicMessageSubmitTransaction()
.set_topic_id(topic_id)
.set_message(message)
.set_transaction_id(TransactionId.generate(env.client.operator_account_id))
- .set_node_account_id(AccountId(0,0,3))
+ .set_node_account_id(node_account_id)
.freeze()
) |
||
| ) | ||
|
|
||
| message_tx.sign(env.client.operator_private_key) | ||
| message_receipt = message_tx.execute(env.client) | ||
|
|
||
| assert message_receipt.status == ResponseCode.SUCCESS | ||
|
|
||
| info = TopicInfoQuery().set_topic_id(topic_id).execute(env.client) | ||
| assert info.sequence_number == 14 | ||
|
|
||
| delete_topic(env.client, topic_id) | ||
Uh oh!
There was an error while loading. Please reload this page.