Skip to content

Commit

Permalink
Merge pull request #135 from ElrondNetwork/fix-for-pending-batch-txs-…
Browse files Browse the repository at this point in the history
…mismatch

Fix for pending batch txs mismatch
  • Loading branch information
dragos-rebegea authored Nov 19, 2021
2 parents f6df1ad + 558321d commit 4acd218
Show file tree
Hide file tree
Showing 25 changed files with 603 additions and 296 deletions.
95 changes: 72 additions & 23 deletions bridge/elrond/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,7 @@ func (c *client) GetPending(_ context.Context) (*bridge.Batch, error) {
var transactions []*bridge.DepositTransaction
for i := 1; i < len(responseData); i += numArgs {
if len(responseData) < i+idxAmount {
c.log.Warn("Elrond: got an unexpected number of arguments", "index", i, "total args", len(responseData))
break
return nil, fmt.Errorf("Elrond: got an unexpected number of arguments, index %d, total args: %d", i, len(responseData))
}

amount := new(big.Int).SetBytes(responseData[i+idxAmount])
Expand All @@ -157,10 +156,9 @@ func (c *client) GetPending(_ context.Context) (*bridge.Batch, error) {
Amount: amount,
DepositNonce: bridge.NewNonce(depositNonce),
BlockNonce: bridge.NewNonce(blockNonce),
Status: 0,
Error: nil,
}
c.log.Trace("created deposit transaction: " + tx.String())
c.log.Debug("Elrond: created deposit transaction: " + tx.String())
transactions = append(transactions, tx)
}

Expand All @@ -169,9 +167,12 @@ func (c *client) GetPending(_ context.Context) (*bridge.Batch, error) {
return nil, fmt.Errorf("%w in client.GetPending, parseIntFromByteSlice(responseData[0])", err)
}

c.log.Debug("Elrond: created batch", "batchID", batchId, "num transactions", len(transactions))

return &bridge.Batch{
Id: bridge.NewBatchId(batchId),
Transactions: transactions,
Statuses: make([]byte, len(transactions)),
}, nil
}

Expand All @@ -189,18 +190,26 @@ func parseIntFromByteSlice(buff []byte) (int64, error) {
}

// ProposeSetStatus will trigger the proposal of the ESDT safe set current transaction batch status operation
func (c *client) ProposeSetStatus(_ context.Context, batch *bridge.Batch) {
func (c *client) ProposeSetStatus(ctx context.Context, batch *bridge.Batch) {
builder := newBuilder(c.log).
Func("proposeEsdtSafeSetCurrentTransactionBatchStatus").
BatchId(batch.Id)

for _, tx := range batch.Transactions {
builder = builder.Int(big.NewInt(int64(tx.Status)))
newBatch, err := c.GetPending(ctx)
if err != nil {
c.log.Error("Elrond: get pending batch failed in ProposeSetStatus", "error", err)
return
}

batch.ResolveNewDeposits(len(newBatch.Statuses))

for _, stat := range batch.Statuses {
builder = builder.Int(big.NewInt(int64(stat)))
}

hash, err := c.sendTransaction(builder, c.gasMapConfig.ProposeStatus)
if err != nil {
c.log.Error("Elrond: send transaction failed", "error", err.Error())
c.log.Error("Elrond: send transaction failed", "error", err)
return
}

Expand All @@ -220,13 +229,17 @@ func (c *client) ProposeTransfer(_ context.Context, batch *bridge.Batch) (string
BigInt(tx.Amount)
}

batchData, errMarshal := json.Marshal(batch)
if errMarshal != nil {
c.log.Warn("Elrond: error not critical while serializing transaction", "error", errMarshal)
}

gasLimit := c.gasMapConfig.ProposeTransferBase + uint64(len(batch.Transactions))*c.gasMapConfig.ProposeTransferForEach
hash, err := c.sendTransaction(builder, gasLimit)

if err == nil {
c.log.Info("Elrond: Proposed transfer for batch ", batch.Id, " with hash ", hash)
c.log.Info("Elrond: Proposed transfer for batch ", batch.Id, "with hash", hash, "batch data", string(batchData))
} else {
c.log.Error("Elrond: Propose transfer errored", "error", err.Error())
c.log.Error("Elrond: Propose transfer errored", "batch data", string(batchData), "error", err)
}

return hash, err
Expand Down Expand Up @@ -265,13 +278,20 @@ func (c *client) GetActionIdForProposeTransfer(_ context.Context, batch *bridge.
}

// WasProposedSetStatus returns true if the proposed set status was triggered
func (c *client) WasProposedSetStatus(_ context.Context, batch *bridge.Batch) bool {
func (c *client) WasProposedSetStatus(ctx context.Context, batch *bridge.Batch) bool {
valueRequest := newValueBuilder(c.bridgeAddress, c.address.AddressAsBech32String(), c.log).
Func("wasSetCurrentTransactionBatchStatusActionProposed").
BatchId(batch.Id)

for _, tx := range batch.Transactions {
valueRequest = valueRequest.BigInt(big.NewInt(int64(tx.Status)))
newBatch, err := c.GetPending(ctx)
if err != nil {
c.log.Error("Elrond: get pending batch failed in WasProposedSetStatus", "error", err)
return false
}
batch.ResolveNewDeposits(len(newBatch.Statuses))

for _, stat := range batch.Statuses {
valueRequest = valueRequest.BigInt(big.NewInt(int64(stat)))
}

return c.executeBoolQuery(valueRequest.Build())
Expand Down Expand Up @@ -312,6 +332,8 @@ func (c *client) GetTransactionsStatuses(_ context.Context, batchId bridge.Batch
return nil, fmt.Errorf("%w status is finished, no results are given", ErrMalformedBatchResponse)
}

c.log.Debug("Elrond: got transaction status", "batchID", batchId, "status", results)

return results, nil
}

Expand All @@ -324,13 +346,20 @@ func getStatusFromBuff(buff []byte) (byte, error) {
}

// GetActionIdForSetStatusOnPendingTransfer returns the action ID for setting the status on the pending transfer batch
func (c *client) GetActionIdForSetStatusOnPendingTransfer(_ context.Context, batch *bridge.Batch) bridge.ActionId {
func (c *client) GetActionIdForSetStatusOnPendingTransfer(ctx context.Context, batch *bridge.Batch) bridge.ActionId {
valueRequest := newValueBuilder(c.bridgeAddress, c.address.AddressAsBech32String(), c.log).
Func("getActionIdForSetCurrentTransactionBatchStatus").
BatchId(batch.Id)

for _, tx := range batch.Transactions {
valueRequest = valueRequest.BigInt(big.NewInt(int64(tx.Status)))
newBatch, err := c.GetPending(ctx)
if err != nil {
c.log.Error("Elrond: get pending batch failed in WasProposedSetStatus", "error", err)
return bridge.NewActionId(0)
}
batch.ResolveNewDeposits(len(newBatch.Statuses))

for _, stat := range batch.Statuses {
valueRequest = valueRequest.BigInt(big.NewInt(int64(stat)))
}

response, err := c.executeUintQuery(valueRequest.Build())
Expand All @@ -339,6 +368,8 @@ func (c *client) GetActionIdForSetStatusOnPendingTransfer(_ context.Context, bat
return bridge.NewActionId(0)
}

c.log.Debug("Elrond: got actionID", "actionID", response)

return bridge.NewActionId(int64(response))
}

Expand All @@ -359,17 +390,22 @@ func (c *client) WasExecuted(_ context.Context, actionId bridge.ActionId, _ brid
}

// Sign will trigger the execution of a sign operation
func (c *client) Sign(_ context.Context, actionId bridge.ActionId, _ *bridge.Batch) (string, error) {
func (c *client) Sign(_ context.Context, actionId bridge.ActionId, batch *bridge.Batch) (string, error) {
builder := newBuilder(c.log).
Func("sign").
ActionId(actionId)

hash, err := c.sendTransaction(builder, c.gasMapConfig.Sign)

batchData, err := json.Marshal(batch)
if err != nil {
c.log.Warn("Elrond: error not critical while serializing transaction", "error", err)
}

if err == nil {
c.log.Info("Elrond: Signed", "hash", hash)
c.log.Info("Elrond: Signed", "hash", hash, "batch data", string(batchData))
} else {
c.log.Error("Elrond: Sign failed", "error", err.Error())
c.log.Error("Elrond: Sign failed", "batch data", string(batchData), "error", err)
}

return hash, err
Expand All @@ -384,17 +420,26 @@ func (c *client) Execute(_ context.Context, actionId bridge.ActionId, batch *bri
gasLimit := c.gasMapConfig.PerformActionBase + uint64(len(batch.Transactions))*c.gasMapConfig.PerformActionForEach
hash, err := c.sendTransaction(builder, gasLimit)

batchData, err := json.Marshal(batch)
if err != nil {
c.log.Warn("Elrond: error not critical while serializing transaction", "error", err)
}

if err == nil {
c.log.Info("Elrond: Executed action", "action ID", actionId, "hash", hash)
c.log.Info("Elrond: Executed action", "actionID", actionId, "batch data", string(batchData), "hash", hash)
} else {
c.log.Info("Elrond: Execution failed for action", "action ID", actionId, "hash", hash, "error", err.Error())
c.log.Info("Elrond: Execution failed for action",
"actionID", actionId,
"batch data", string(batchData),
"hash", hash,
"error", err)
}

return hash, err
}

// SignersCount returns the signers count
func (c *client) SignersCount(_ *bridge.Batch, actionId bridge.ActionId, _ bridge.SignaturesHolder) uint {
func (c *client) SignersCount(_ context.Context, _ *bridge.Batch, actionId bridge.ActionId, _ bridge.SignaturesHolder) uint {
valueRequest := newValueBuilder(c.bridgeAddress, c.address.AddressAsBech32String(), c.log).
Func("getActionSignerCount").
ActionId(actionId).
Expand All @@ -420,6 +465,8 @@ func (c *client) GetTokenId(address string) string {
c.log.Error(err.Error())
}

c.log.Debug("Elrond: get token ID", "address", address, "tokenID", tokenId)

return tokenId
}

Expand All @@ -435,6 +482,8 @@ func (c *client) GetErc20Address(tokenId string) string {
c.log.Error(err.Error())
}

c.log.Debug("Elrond: get erc20 address", "tokenID", tokenId, "address", address)

return address
}

Expand Down
34 changes: 18 additions & 16 deletions bridge/elrond/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ func TestGetPending(t *testing.T) {
Amount: big.NewInt(1),
DepositNonce: bridge.NewNonce(1),
BlockNonce: bridge.NewNonce(154947),
Status: 0,
Error: nil,
}
tx2 := &bridge.DepositTransaction{
Expand All @@ -160,12 +159,12 @@ func TestGetPending(t *testing.T) {
Amount: big.NewInt(2),
DepositNonce: bridge.NewNonce(2),
BlockNonce: bridge.NewNonce(154947),
Status: 0,
Error: nil,
}
expected := &bridge.Batch{
Id: bridge.NewBatchId(1),
Transactions: []*bridge.DepositTransaction{tx1, tx2},
Statuses: make([]byte, 2),
}

assert.Equal(t, expected, actual)
Expand Down Expand Up @@ -259,7 +258,7 @@ func TestProposeSetStatus(t *testing.T) {
proxy := &testProxy{
transactionCost: 1024,
queryResponseCode: "ok",
queryResponseData: [][]byte{},
queryResponseData: make([][]byte, 13),
}
c, _ := buildTestClient(proxy)

Expand All @@ -272,17 +271,16 @@ func TestProposeSetStatus(t *testing.T) {
TokenAddress: "0x3a41ed2dD119E44B802c87E84840F7C85206f4f1",
Amount: big.NewInt(42),
DepositNonce: bridge.NewNonce(1),
Status: bridge.Executed,
},
{
To: "erd1k2s324ww2g0yj38qn2ch2jwctdy8mnfxep94q9arncc6xecg3xaq6mjse8",
From: "0x132A150926691F08a693721503a38affeD18d524",
TokenAddress: "0x3a41ed2dD119E44B802c87E84840F7C85206f4f1",
Amount: big.NewInt(42),
DepositNonce: bridge.NewNonce(1),
Status: bridge.Rejected,
},
},
Statuses: []byte{bridge.Executed, bridge.Rejected},
}

c.ProposeSetStatus(context.TODO(), batch)
Expand All @@ -309,17 +307,16 @@ func TestExecute(t *testing.T) {
TokenAddress: "0x3a41ed2dD119E44B802c87E84840F7C85206f4f1",
Amount: big.NewInt(42),
DepositNonce: bridge.NewNonce(1),
Status: bridge.Executed,
},
{
To: "erd1k2s324ww2g0yj38qn2ch2jwctdy8mnfxep94q9arncc6xecg3xaq6mjse8",
From: "0x132A150926691F08a693721503a38affeD18d524",
TokenAddress: "0x3a41ed2dD119E44B802c87E84840F7C85206f4f1",
Amount: big.NewInt(42),
DepositNonce: bridge.NewNonce(1),
Status: bridge.Rejected,
},
},
Statuses: []byte{bridge.Executed, bridge.Rejected},
}
hash, _ := c.Execute(context.TODO(), bridge.NewActionId(42), batch, nil)

Expand All @@ -346,9 +343,9 @@ func TestWasProposedTransfer(t *testing.T) {
TokenAddress: "0x3a41ed2dD119E44B802c87E84840F7C85206f4f1",
Amount: big.NewInt(42),
DepositNonce: bridge.NewNonce(1),
Status: bridge.Executed,
},
},
Statuses: []byte{bridge.Executed},
}

got := c.WasProposedTransfer(context.TODO(), batch)
Expand Down Expand Up @@ -430,7 +427,7 @@ func TestSignersCount(t *testing.T) {
proxy := &testProxy{queryResponseCode: "ok", queryResponseData: [][]byte{{byte(42)}}}
c, _ := buildTestClient(proxy)

got := c.SignersCount(nil, bridge.NewActionId(0), nil)
got := c.SignersCount(context.TODO(), nil, bridge.NewActionId(0), nil)

assert.Equal(t, uint(42), got)
}
Expand All @@ -443,10 +440,9 @@ func TestWasProposedSetStatus(t *testing.T) {
batch := &bridge.Batch{
Id: bridge.NewBatchId(1),
Transactions: []*bridge.DepositTransaction{
{
Status: bridge.Rejected,
},
{},
},
Statuses: []byte{bridge.Rejected},
}
got := c.WasProposedSetStatus(context.TODO(), batch)

Expand All @@ -455,12 +451,17 @@ func TestWasProposedSetStatus(t *testing.T) {
assert.Equal(t, "04", proxy.lastQueryArgs[1])
})
t.Run("will return false when response is empty", func(t *testing.T) {
proxy := &testProxy{queryResponseCode: "ok", queryResponseData: [][]byte{{}}}
proxy := &testProxy{
queryResponseCode: "ok",
queryResponseData: make([][]byte, 7)}
c, _ := buildTestClient(proxy)

batch := &bridge.Batch{
Id: bridge.NewBatchId(0),
Transactions: []*bridge.DepositTransaction{},
Id: bridge.NewBatchId(0),
Transactions: []*bridge.DepositTransaction{
{},
},
Statuses: make([]byte, 1),
}
got := c.WasProposedSetStatus(context.TODO(), batch)

Expand Down Expand Up @@ -513,9 +514,9 @@ func TestGetActionIdForSetStatusOnPendingTransfer(t *testing.T) {
TokenAddress: "0x3a41ed2dD119E44B802c87E84840F7C85206f4f1",
Amount: big.NewInt(42),
DepositNonce: bridge.NewNonce(1),
Status: bridge.Executed,
},
},
Statuses: []byte{bridge.Executed},
}

got := c.GetActionIdForSetStatusOnPendingTransfer(context.TODO(), batch)
Expand Down Expand Up @@ -725,6 +726,7 @@ func TestClient_GetTransactionsStatuses(t *testing.T) {
c := &client{
proxy: proxy,
bridgeAddress: "erd1r69gk66fmedhhcg24g2c5kn2f2a5k4kvpr6jfw67dn2lyydd8cfswy6ede",
log: logger.GetOrCreate("test"),
}
c.address, _ = data.NewAddressFromBech32String("erd1r69gk66fmedhhcg24g2c5kn2f2a5k4kvpr6jfw67dn2lyydd8cfswy6ede")

Expand Down
Loading

0 comments on commit 4acd218

Please sign in to comment.