github.com/Tri-stone/burrow@v0.25.0/execution/state/events_test.go (about)

     1  package state
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/hyperledger/burrow/binary"
     8  	"github.com/hyperledger/burrow/crypto"
     9  	"github.com/hyperledger/burrow/crypto/sha3"
    10  	"github.com/hyperledger/burrow/execution/exec"
    11  	"github.com/stretchr/testify/require"
    12  	"github.com/tendermint/tendermint/libs/db"
    13  )
    14  
    15  func TestWriteState_AddBlock(t *testing.T) {
    16  	s := NewState(db.NewMemDB())
    17  	height := uint64(100)
    18  	numTxs := uint64(5)
    19  	events := uint64(10)
    20  	block := mkBlock(height, numTxs, events)
    21  	_, _, err := s.Update(func(ws Updatable) error {
    22  		return ws.AddBlock(block)
    23  	})
    24  	require.NoError(t, err)
    25  
    26  	txIndex := uint64(0)
    27  	eventIndex := uint64(0)
    28  	err = s.IterateStreamEvents(&exec.StreamKey{Height: height}, &exec.StreamKey{Height: height + 1},
    29  		func(ev *exec.StreamEvent) error {
    30  			switch {
    31  			case ev.BeginTx != nil:
    32  				eventIndex = 0
    33  			case ev.Event != nil:
    34  				require.Equal(t, mkEvent(height, txIndex, eventIndex).Header.TxHash.String(),
    35  					ev.Event.Header.TxHash.String(), "event TxHash mismatch at tx #%d event #%d",
    36  					txIndex, eventIndex)
    37  				eventIndex++
    38  			case ev.EndTx != nil:
    39  				txIndex++
    40  			}
    41  			return nil
    42  		})
    43  	require.NoError(t, err)
    44  	require.Equal(t, numTxs, txIndex, "should have observed all txs")
    45  	// non-increasing events
    46  	_, _, err = s.Update(func(ws Updatable) error {
    47  		return nil
    48  	})
    49  	require.NoError(t, err)
    50  
    51  	txExecutions, err := s.TxsAtHeight(height)
    52  	require.NoError(t, err)
    53  	require.NotNil(t, txExecutions)
    54  	require.Equal(t, numTxs, uint64(len(txExecutions)))
    55  }
    56  
    57  func TestNestedTxs(t *testing.T) {
    58  	s := NewState(db.NewMemDB())
    59  	height := uint64(2)
    60  	numTxs := uint64(4)
    61  	events := uint64(2)
    62  	nesting := uint64(3)
    63  	block := mkBlock(height, numTxs, events)
    64  	txes := block.TxExecutions
    65  	// Deeply nest transactions inside block
    66  	for i := uint64(0); i < nesting; i++ {
    67  		var next []*exec.TxExecution
    68  		for _, txe := range txes {
    69  			next = append(next, nestTxs(txe, height, events+i, numTxs+i)...)
    70  		}
    71  		txes = next
    72  	}
    73  	_, _, err := s.Update(func(ws Updatable) error {
    74  		return ws.AddBlock(block)
    75  	})
    76  	require.NoError(t, err)
    77  	txes, err = s.TxsAtHeight(height)
    78  	require.NoError(t, err)
    79  	txsCount := deepCountTxs(block.TxExecutions)
    80  	require.Equal(t, txsCount, deepCountTxs(txes))
    81  	// There is a geometric-arithmetic sum here... but empiricism FTW
    82  	require.Equal(t, 580, txsCount)
    83  }
    84  
    85  func TestReadState_TxByHash(t *testing.T) {
    86  	s := NewState(db.NewMemDB())
    87  	maxHeight := uint64(3)
    88  	numTxs := uint64(4)
    89  	events := uint64(2)
    90  	for height := uint64(0); height < maxHeight; height++ {
    91  		block := mkBlock(height, numTxs, events)
    92  		_, _, err := s.Update(func(ws Updatable) error {
    93  			return ws.AddBlock(block)
    94  		})
    95  		require.NoError(t, err)
    96  	}
    97  
    98  	hashSet := make(map[string]bool)
    99  	for height := uint64(0); height < maxHeight; height++ {
   100  		for txIndex := uint64(0); txIndex < numTxs; txIndex++ {
   101  			// Find this tx
   102  			tx := mkTx(height, txIndex, events)
   103  			txHash := tx.TxHash.String()
   104  			// Check we have no duplicates (indicates problem with how we are generating hashes for these tests
   105  			require.False(t, hashSet[txHash], "should be no duplicate tx hashes")
   106  			hashSet[txHash] = true
   107  			// Try and pull the Tx by its hash
   108  			txOut, err := s.TxByHash(tx.TxHash)
   109  			require.NoError(t, err)
   110  			require.NotNil(t, txOut, "should retrieve non-nil transaction by TxHash %v", tx.TxHash)
   111  			// Make sure we get the same tx
   112  			require.Equal(t, txHash, txOut.TxHash.String(), "TxHash does not match as string")
   113  			require.Equal(t, *tx, *txOut)
   114  		}
   115  	}
   116  }
   117  
   118  func deepCountTxs(txes []*exec.TxExecution) int {
   119  	sum := len(txes)
   120  	for _, txe := range txes {
   121  		sum += deepCountTxs(txe.TxExecutions)
   122  	}
   123  	return sum
   124  }
   125  
   126  func nestTxs(txe *exec.TxExecution, height, events, numTxs uint64) []*exec.TxExecution {
   127  	txes := make([]*exec.TxExecution, numTxs)
   128  	for i := uint64(0); i < numTxs; i++ {
   129  		txes[i] = mkTx(height, i, events)
   130  		txe.TxExecutions = append(txe.TxExecutions, txes[i])
   131  	}
   132  	return txes
   133  }
   134  
   135  func mkBlock(height, numTxs, events uint64) *exec.BlockExecution {
   136  	be := &exec.BlockExecution{
   137  		Height: height,
   138  	}
   139  	for ti := uint64(0); ti < numTxs; ti++ {
   140  		txe := mkTx(height, ti, events)
   141  		be.TxExecutions = append(be.TxExecutions, txe)
   142  	}
   143  	return be
   144  }
   145  
   146  func mkTx(height, txIndex, events uint64) *exec.TxExecution {
   147  	hash := make([]byte, 32)
   148  	binary.PutUint64BE(hash[:8], height)
   149  	binary.PutUint64BE(hash[8:16], txIndex)
   150  	binary.PutUint64BE(hash[16:24], events)
   151  	txe := &exec.TxExecution{
   152  		TxHeader: &exec.TxHeader{
   153  			TxHash: hash,
   154  			Height: height,
   155  			Index:  txIndex,
   156  		},
   157  	}
   158  	for e := uint64(0); e < events; e++ {
   159  		txe.Events = append(txe.Events, mkEvent(height, txIndex, e))
   160  	}
   161  	return txe
   162  }
   163  
   164  func mkEvent(height, tx, index uint64) *exec.Event {
   165  	return &exec.Event{
   166  		Header: &exec.Header{
   167  			Height:  height,
   168  			Index:   index,
   169  			TxHash:  sha3.Sha3([]byte(fmt.Sprintf("txhash%v%v%v", height, tx, index))),
   170  			EventID: fmt.Sprintf("eventID: %v%v%v", height, tx, index),
   171  		},
   172  		Log: &exec.LogEvent{
   173  			Address: crypto.Address{byte(height), byte(index)},
   174  			Topics:  []binary.Word256{{1, 2, 3}},
   175  		},
   176  	}
   177  }