mirror of
https://github.com/AthanorLabs/atomic-swap.git
synced 2026-01-09 22:28:04 -05:00
113 lines
3.8 KiB
Go
113 lines
3.8 KiB
Go
// Copyright 2023 The AthanorLabs/atomic-swap Authors
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
package block
|
|
|
|
import (
|
|
"context"
|
|
"crypto/ecdsa"
|
|
"math/big"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/ethereum/go-ethereum/ethclient"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/athanorlabs/atomic-swap/tests"
|
|
)
|
|
|
|
// stampChecker collects all the pieces of data needed to create a transaction that calls
|
|
// check_stamp on the UTContract for unit tests.
|
|
type stampChecker struct {
|
|
t *testing.T
|
|
ec *ethclient.Client
|
|
ctx context.Context
|
|
chainID *big.Int
|
|
fromKey *ecdsa.PrivateKey
|
|
contract *UTContract
|
|
}
|
|
|
|
// checkStamp performs the setup of creating a check_stamp transaction so unit tests
|
|
// can concentrate on the return values of WaitForReceipt.
|
|
func (c *stampChecker) checkStamp(epochTimeStamp int64) (*ethtypes.Receipt, error) {
|
|
auth, err := bind.NewKeyedTransactorWithChainID(c.fromKey, c.chainID)
|
|
require.NoError(c.t, err)
|
|
tx, err := c.contract.CheckStamp(auth, big.NewInt(epochTimeStamp))
|
|
require.NoError(c.t, err)
|
|
return WaitForReceipt(c.ctx, c.ec, tx.Hash())
|
|
}
|
|
|
|
// curBlockHeader is a test helper function to get the latest block header
|
|
func (c *stampChecker) curBlockHeader() *ethtypes.Header {
|
|
hdr, err := c.ec.HeaderByNumber(c.ctx, nil)
|
|
require.NoError(c.t, err)
|
|
return hdr
|
|
}
|
|
|
|
// createStampChecker deploys the unit test contract (UTContract)
|
|
func createStampChecker(t *testing.T) *stampChecker {
|
|
ec, chainID := tests.NewEthClient(t)
|
|
ctx := context.Background()
|
|
|
|
fromKey := tests.GetTestKeyByIndex(t, 0)
|
|
|
|
auth, err := bind.NewKeyedTransactorWithChainID(fromKey, chainID)
|
|
require.NoError(t, err)
|
|
|
|
_, tx, contract, err := DeployUTContract(auth, ec)
|
|
require.NoError(t, err)
|
|
|
|
_, err = WaitForReceipt(ctx, ec, tx.Hash())
|
|
require.NoError(t, err)
|
|
|
|
return &stampChecker{
|
|
t: t,
|
|
ec: ec,
|
|
ctx: ctx,
|
|
chainID: chainID,
|
|
fromKey: fromKey,
|
|
contract: contract,
|
|
}
|
|
|
|
}
|
|
|
|
// Test WaitForReceipt with 2 transactions that are successfully mined:
|
|
// 1. contract creation
|
|
// 2. calling check_stamp with a value >= the mined block's timestamp
|
|
func TestWaitForReceipt_success(t *testing.T) {
|
|
checker := createStampChecker(t)
|
|
blockBefore := checker.curBlockHeader()
|
|
futureTime := time.Now().Add(time.Hour).Unix()
|
|
receipt, err := checker.checkStamp(futureTime)
|
|
require.NoError(t, err)
|
|
txBlockNum := receipt.BlockNumber
|
|
require.Greater(t, txBlockNum.Uint64(), blockBefore.Number.Uint64())
|
|
}
|
|
|
|
// Test our ErrorFromBlock method. This test is designed to create a transaction that will
|
|
// successfully be created and sent to the network, but then subsequently fail when it is
|
|
// mined into a block.
|
|
func TestWaitForReceipt_failWhenTransactionIsMined(t *testing.T) {
|
|
checker := createStampChecker(t)
|
|
|
|
// One second in the future rounding up
|
|
oneSecInFuture := time.Now().Add(1500 * time.Millisecond)
|
|
|
|
// We don't want a race condition between getting the current block and creating the
|
|
// check_stamp transaction. The transaction creation needs to be done when the
|
|
// current block timestamp is exactly equal to the time we pass. That way transaction
|
|
// creation will pass, but mining will fail. By waiting for the next block, we have
|
|
// a full second to create the new transaction and avoid any race condition.
|
|
hdr, err := WaitForEthBlockAfterTimestamp(checker.ctx, checker.ec, oneSecInFuture)
|
|
require.NoError(t, err)
|
|
|
|
_, err = checker.checkStamp(int64(hdr.Time))
|
|
require.Error(t, err)
|
|
// Ensure that we got the expected error
|
|
require.Contains(t, err.Error(), "revert block.timestamp was not less than stamp")
|
|
// Ensure that the expected error happened when the transaction was mined and not earlier
|
|
require.Contains(t, err.Error(), "failed transaction included in block")
|
|
}
|