Skip to content

Commit

Permalink
Added fix for INVALID_NODE_ACCOUNT (#780) (#783)
Browse files Browse the repository at this point in the history
Signed-off-by: Antonio Mindov <[email protected]>

Signed-off-by: Antonio Mindov <[email protected]>
  • Loading branch information
rokn authored Nov 30, 2022
1 parent ba4a6e9 commit 32d8d82
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 41 deletions.
123 changes: 82 additions & 41 deletions app/clients/hedera/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package hedera

import (
"fmt"

"github.com/hashgraph/hedera-sdk-go/v2"
"github.com/limechain/hedera-eth-bridge-validator/app/model/transfer"
"github.com/limechain/hedera-eth-bridge-validator/config"
Expand Down Expand Up @@ -125,50 +124,69 @@ func (hc Node) SubmitScheduledTokenBurnTransaction(tokenID hedera.TokenID, amoun
// SubmitTopicConsensusMessage submits the provided message bytes to the
// specified HCS `topicId`
func (hc Node) SubmitTopicConsensusMessage(topicId hedera.TopicID, message []byte) (*hedera.TransactionID, error) {
tx, err := hedera.NewTopicMessageSubmitTransaction().
SetTopicID(topicId).
SetMessage(message).
SetMaxRetry(hc.maxRetry).
FreezeWith(hc.client)
attempt := 0
for attempt <= hc.maxRetry {
attempt++
tx, err := hedera.NewTopicMessageSubmitTransaction().
SetTopicID(topicId).
SetMessage(message).
SetMaxRetry(hc.maxRetry).
FreezeWith(hc.client)

if err != nil {
return nil, err
}
if err != nil {
return nil, err
}

hc.logger.Debugf("Submit Topic Consensus Message, with transaction ID [%s] and Node Account IDs: %v",
tx.GetTransactionID(),
tx.GetNodeAccountIDs(),
)
hc.logger.Debugf("Submit Topic Consensus Message, with transaction ID [%s] and Node Account IDs: %v",
tx.GetTransactionID(),
tx.GetNodeAccountIDs(),
)

response, err := tx.Execute(hc.GetClient())
response, err := tx.Execute(hc.GetClient())
if shouldRetryTransaction(err) {
continue
}

if err != nil {
return nil, err
}
if err != nil {
return nil, err
}

_, err = hc.checkTransactionReceipt(response)
_, err = hc.checkTransactionReceipt(response)

return &response.TransactionID, err
return &response.TransactionID, err
}

return nil, fmt.Errorf("Too many retries to submit topic message to %s", topicId.String())
}

// SubmitScheduleSign submits a ScheduleSign transaction for a given ScheduleID
func (hc Node) SubmitScheduleSign(scheduleID hedera.ScheduleID) (*hedera.TransactionResponse, error) {
tx, err := hedera.NewScheduleSignTransaction().
SetScheduleID(scheduleID).
SetMaxRetry(hc.maxRetry).
FreezeWith(hc.GetClient())
attempt := 0
for attempt <= hc.maxRetry {
attempt++
tx, err := hedera.NewScheduleSignTransaction().
SetScheduleID(scheduleID).
SetMaxRetry(hc.maxRetry).
FreezeWith(hc.GetClient())

if err != nil {
return nil, err
if err != nil {
return nil, err
}

hc.logger.Debugf("Submit Schedule Sign, with transaction ID [%s], schedule ID: [%s] and Node Account IDs: %v",
tx.GetTransactionID(),
tx.GetScheduleID(),
tx.GetNodeAccountIDs(),
)
response, err := tx.Execute(hc.GetClient())
if shouldRetryTransaction(err) {
continue
}

return &response, err
}

hc.logger.Debugf("Submit Schedule Sign, with transaction ID [%s], schedule ID: [%s] and Node Account IDs: %v",
tx.GetTransactionID(),
tx.GetScheduleID(),
tx.GetNodeAccountIDs(),
)
response, err := tx.Execute(hc.GetClient())
return &response, err
return nil, fmt.Errorf("[%s] Too many retries", scheduleID)
}

// SubmitScheduledTokenTransferTransaction creates a token transfer transaction and submits it as a scheduled transaction
Expand Down Expand Up @@ -241,17 +259,27 @@ func (hc Node) submitScheduledTransferTransaction(payerAccountID hedera.AccountI
}

func (hc Node) submitScheduledTransaction(signedTransaction hedera.ITransaction, payerAccountID hedera.AccountID, memo string) (*hedera.TransactionResponse, error) {
scheduledTx, err := hedera.NewScheduleCreateTransaction().
SetScheduledTransaction(signedTransaction)
if err != nil {
return nil, err
attempt := 0
for attempt <= hc.maxRetry {
attempt++
scheduledTx, err := hedera.NewScheduleCreateTransaction().
SetScheduledTransaction(signedTransaction)
if err != nil {
return nil, err
}
scheduledTx = scheduledTx.
SetPayerAccountID(payerAccountID).
SetScheduleMemo(memo)

response, err := scheduledTx.Execute(hc.GetClient())
if shouldRetryTransaction(err) {
continue
}

return &response, err
}
scheduledTx = scheduledTx.
SetPayerAccountID(payerAccountID).
SetScheduleMemo(memo)

response, err := scheduledTx.Execute(hc.GetClient())
return &response, err
return nil, fmt.Errorf("[%s] Too many retries", memo)
}

func (hc Node) checkTransactionReceipt(txResponse hedera.TransactionResponse) (*hedera.TransactionReceipt, error) {
Expand All @@ -266,3 +294,16 @@ func (hc Node) checkTransactionReceipt(txResponse hedera.TransactionResponse) (*

return &receipt, err
}

func shouldRetryTransaction(err error) bool {
if err == nil {
return false
}

preCheckError, ok := err.(*hedera.ErrHederaPreCheckStatus)
if ok && preCheckError.Status == hedera.StatusInvalidNodeAccount {
return true
}

return false
}
41 changes: 41 additions & 0 deletions app/clients/hedera/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2022 LimeChain Ltd.
*
* 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 hedera

import (
"fmt"
"github.com/hashgraph/hedera-sdk-go/v2"
"github.com/stretchr/testify/assert"
"testing"
)

func Test_shouldRetryTransactionInvalidNodeAccount(t *testing.T) {
err := hedera.ErrHederaPreCheckStatus{Status: hedera.StatusInvalidNodeAccount}
assert.True(t, shouldRetryTransaction(&err))
}

func Test_shouldRetryNoError(t *testing.T) {
assert.False(t, shouldRetryTransaction(nil))
}

func Test_shouldRetryTransactionUnknownError(t *testing.T) {
err := fmt.Errorf("some error")
assert.False(t, shouldRetryTransaction(err))

err = &hedera.ErrHederaPreCheckStatus{Status: hedera.StatusAccountDeleted}
assert.False(t, shouldRetryTransaction(err))
}

0 comments on commit 32d8d82

Please sign in to comment.