github.com/aergoio/aergo@v1.3.1/types/blockchain_test.go (about)

     1  package types
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"math/big"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/golang/protobuf/proto"
    11  	"github.com/minio/sha256-simd"
    12  
    13  	"github.com/libp2p/go-libp2p-core/crypto"
    14  	"github.com/stretchr/testify/assert"
    15  )
    16  
    17  func TestBlockHash(t *testing.T) {
    18  	blockHash := func(block *Block) []byte {
    19  		header := block.Header
    20  		digest := sha256.New()
    21  		writeBlockHeaderOld(digest, header)
    22  		return digest.Sum(nil)
    23  	}
    24  
    25  	txIn := make([]*Tx, 0)
    26  	block := NewBlock(nil, nil, nil, txIn, nil, 0)
    27  
    28  	h1 := blockHash(block)
    29  	h2 := block.calculateBlockHash()
    30  
    31  	assert.Equal(t, h1, h2)
    32  }
    33  
    34  func genKeyPair(assert *assert.Assertions) (crypto.PrivKey, crypto.PubKey) {
    35  	privKey, pubKey, err := crypto.GenerateKeyPair(crypto.Secp256k1, 256)
    36  	assert.Nil(err)
    37  
    38  	return privKey, pubKey
    39  }
    40  
    41  func genSign(assert *assert.Assertions, block *Block, privKey crypto.PrivKey) []byte {
    42  	msg, err := block.Header.bytesForDigest()
    43  	assert.Nil(err)
    44  
    45  	sig, err := privKey.Sign(msg)
    46  	assert.Nil(err)
    47  
    48  	return sig
    49  }
    50  
    51  func TestBlockSignBasic(t *testing.T) {
    52  	signAssert := assert.New(t)
    53  
    54  	message := func(block *Block) []byte {
    55  		msg, err := block.Header.bytesForDigest()
    56  		signAssert.Nil(err)
    57  
    58  		return msg
    59  	}
    60  
    61  	sign := func(block *Block, privKey crypto.PrivKey) []byte {
    62  		sig, err := privKey.Sign(message(block))
    63  		signAssert.Nil(err)
    64  
    65  		return sig
    66  	}
    67  
    68  	verify := func(block *Block, sig []byte, pubKey crypto.PubKey) bool {
    69  		valid, err := pubKey.Verify(message(block), sig)
    70  		signAssert.Nil(err)
    71  
    72  		return valid
    73  	}
    74  
    75  	block := NewBlock(nil, nil, nil, make([]*Tx, 0), nil, 0)
    76  
    77  	privKey, pubKey := genKeyPair(signAssert)
    78  	sig := sign(block, privKey)
    79  	valid := verify(block, sig, pubKey)
    80  	signAssert.True(valid)
    81  }
    82  
    83  func TestBlockSign(t *testing.T) {
    84  	signAssert := assert.New(t)
    85  	block := NewBlock(nil, nil, nil, make([]*Tx, 0), nil, 0)
    86  
    87  	privKey, _ := genKeyPair(signAssert)
    88  	signAssert.Nil(block.Sign(privKey))
    89  
    90  	sig := genSign(signAssert, block, privKey)
    91  	signAssert.NotNil(sig)
    92  
    93  	signAssert.Equal(sig, block.Header.Sign)
    94  
    95  	valid, err := block.VerifySign()
    96  	signAssert.Nil(err)
    97  	signAssert.True(valid)
    98  }
    99  
   100  func TestMovingAverage(t *testing.T) {
   101  	size := int64(10)
   102  	mv := NewMovingAverage(int(size))
   103  
   104  	assert.Equal(t, int64(0), mv.calculateAvg())
   105  
   106  	var sum = int64(0)
   107  	var expAvg int64
   108  	for i := int64(1); i <= size; i++ {
   109  		avg := mv.Add(int64(i))
   110  		assert.Equal(t, i, int64(mv.count))
   111  
   112  		sum += i
   113  		expAvg = sum / i
   114  		assert.Equal(t, expAvg, avg)
   115  	}
   116  
   117  	for i := int64(size + 1); i <= (size + 10); i++ {
   118  		avg := mv.Add(int64(i))
   119  		assert.Equal(t, size, int64(mv.count))
   120  
   121  		sum = sum + i - (i - size)
   122  		expAvg = sum / size
   123  		assert.Equal(t, expAvg, avg)
   124  	}
   125  }
   126  
   127  func TestUpdateAvgVerifyTime(t *testing.T) {
   128  	var size = int64(10)
   129  	avgTime := NewAvgTime(int(size))
   130  
   131  	val := avgTime.Get()
   132  
   133  	assert.Equal(t, int64(0), int64(val))
   134  
   135  	var sum = int64(0)
   136  	var expAvg int64
   137  
   138  	for i := int64(1); i <= size; i++ {
   139  		avgTime.UpdateAverage(time.Duration(i))
   140  		newAvg := avgTime.Get()
   141  
   142  		sum += i
   143  		expAvg = sum / i
   144  		assert.Equal(t, expAvg, int64(newAvg))
   145  	}
   146  
   147  	for i := int64(size + 1); i <= (size + 10); i++ {
   148  		avgTime.UpdateAverage(time.Duration(i))
   149  		newAvg := avgTime.Get()
   150  
   151  		sum = sum + i - (i - size)
   152  		expAvg = sum / size
   153  		assert.Equal(t, expAvg, int64(newAvg))
   154  	}
   155  }
   156  
   157  func TestBlockLimit(t *testing.T) {
   158  	a := assert.New(t)
   159  
   160  	chainID := "0123456789012345678901234567890123456789"
   161  	dig := sha256.New()
   162  	dig.Write([]byte(chainID))
   163  	h := dig.Sum(nil)
   164  
   165  	addr, err := DecodeAddress("AmLquXjQSiDdR8FTDK78LJ16Ycrq3uNL6NQuiwqXRCGw9Riq2DE4")
   166  	a.Nil(err, "invalid coinbase account")
   167  
   168  	_, pub := genKeyPair(a)
   169  
   170  	block := &Block{
   171  		Header: &BlockHeader{
   172  			ChainID:          []byte(chainID), // len <= 40
   173  			PrevBlockHash:    h,               // 32byte
   174  			BlockNo:          math.MaxUint64,
   175  			Timestamp:        math.MinInt64,
   176  			BlocksRootHash:   h, // 32byte. Currenly not used but for the future use.
   177  			TxsRootHash:      h, // 32byte
   178  			ReceiptsRootHash: h, // 32byte
   179  			Confirms:         math.MaxUint64,
   180  			CoinbaseAccount:  addr,
   181  		},
   182  		Body: &BlockBody{Txs: make([]*Tx, 0)},
   183  	}
   184  	err = block.setPubKey(pub)
   185  	a.Nil(err, "PubKey set failed")
   186  
   187  	// The signature's max length is 72 (strict DER format). But usually it is
   188  	// 70 or 71. For header length measurement, generate a byte array of length
   189  	// 72 from a hash (sha256) value xrather than a real signature.
   190  	block.Header.Sign = h
   191  	block.Header.Sign = append(block.Header.Sign, h...)
   192  	block.Header.Sign = append(block.Header.Sign, h[:8]...)
   193  
   194  	// A block can include its sha256 hash value. Thus the size of blcok hash
   195  	// value should be considered when the block header limit estimated.
   196  	fmt.Println("block id:", block.ID())
   197  
   198  	hdrSize := proto.Size(block)
   199  	a.True(hdrSize <= DefaultMaxHdrSize, "too large header (> %v): %v", DefaultMaxHdrSize, hdrSize)
   200  
   201  	fmt.Println("hdr size", hdrSize)
   202  
   203  	const testSender = "AmPNYHyzyh9zweLwDyuoiUuTVCdrdksxkRWDjVJS76WQLExa2Jr4"
   204  	account, _ := DecodeAddress(testSender)
   205  	amount, ok := new(big.Int).SetString("999999999999999999", 10)
   206  	a.True(ok, "amount conversion failed")
   207  
   208  	//blk := &Block{}
   209  	tx := &Tx{
   210  		Body: &TxBody{
   211  			Nonce:     math.MaxUint64,
   212  			Account:   account,
   213  			Recipient: account,
   214  			Amount:    amount.Bytes(),
   215  			Payload:   []byte(`{"Name":"v1unstake"}`),
   216  			GasLimit:  math.MaxUint64,
   217  			GasPrice:  amount.Bytes(),
   218  			Sign:      block.GetHeader().GetSign(),
   219  			Type:      TxType_GOVERNANCE,
   220  		},
   221  	}
   222  	tx.Hash = tx.CalculateTxHash()
   223  
   224  	txSize := proto.Size(tx)
   225  
   226  	nTx := 10000
   227  	var i int
   228  
   229  	hdrLimit := 400
   230  	bodyLimit := 1000000
   231  	limit := hdrLimit + bodyLimit
   232  	s := 0
   233  	for i = 1; i <= nTx; i++ {
   234  		if s += proto.Size(tx); s > bodyLimit {
   235  			break
   236  		}
   237  		block.Body.Txs = append(block.Body.Txs, tx)
   238  	}
   239  
   240  	fmt.Println("estimate #1: ", block.Size(), "esimate #2: ", txSize*i+hdrSize, "actual: ", proto.Size(block))
   241  	a.True(block.Size() <= proto.Size(block), "block size violation")
   242  	a.True(block.Size() <= txSize*i+hdrSize, "block size violation")
   243  	a.True(block.Size() <= limit, "block size violation")
   244  }