github.com/deso-protocol/core@v1.2.9/lib/db_utils_test.go (about)

     1  package lib
     2  
     3  import (
     4  	"io/ioutil"
     5  	"log"
     6  	"math/big"
     7  	"os"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/btcsuite/btcd/btcec"
    12  	"github.com/dgraph-io/badger/v3"
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  func _GetTestBlockNode() *BlockNode {
    18  	bs := BlockNode{}
    19  
    20  	// Hash
    21  	bs.Hash = &BlockHash{
    22  		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
    23  		0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
    24  		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
    25  		0x30, 0x31,
    26  	}
    27  
    28  	// Height
    29  	bs.Height = 123456789
    30  
    31  	// DifficultyTarget
    32  	bs.DifficultyTarget = &BlockHash{
    33  		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
    34  		0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
    35  		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
    36  		0x30, 0x31,
    37  	}
    38  
    39  	// CumWork
    40  	bs.CumWork = big.NewInt(5)
    41  
    42  	// Header (make a copy)
    43  	bs.Header = NewMessage(MsgTypeHeader).(*MsgDeSoHeader)
    44  	headerBytes, _ := expectedBlockHeader.ToBytes(false)
    45  	bs.Header.FromBytes(headerBytes)
    46  
    47  	// Status
    48  	bs.Status = StatusBlockValidated
    49  
    50  	return &bs
    51  }
    52  
    53  func GetTestBadgerDb() (_db *badger.DB, _dir string) {
    54  	dir, err := ioutil.TempDir("", "badgerdb")
    55  	if err != nil {
    56  		log.Fatal(err)
    57  	}
    58  
    59  	// Open a badgerdb in a temporary directory.
    60  	opts := badger.DefaultOptions(dir)
    61  	opts.Dir = dir
    62  	opts.ValueDir = dir
    63  	db, err := badger.Open(opts)
    64  	if err != nil {
    65  		log.Fatal(err)
    66  	}
    67  
    68  	return db, dir
    69  }
    70  
    71  func TestBlockNodeSerialize(t *testing.T) {
    72  	assert := assert.New(t)
    73  	require := require.New(t)
    74  	_ = assert
    75  	_ = require
    76  
    77  	bs := _GetTestBlockNode()
    78  
    79  	serialized, err := SerializeBlockNode(bs)
    80  	require.NoError(err)
    81  	deserialized, err := DeserializeBlockNode(serialized)
    82  	require.NoError(err)
    83  
    84  	assert.Equal(bs, deserialized)
    85  }
    86  
    87  func TestBlockNodePutGet(t *testing.T) {
    88  	assert := assert.New(t)
    89  	require := require.New(t)
    90  	_ = assert
    91  	_ = require
    92  
    93  	// Create a test db and clean up the files at the end.
    94  	db, dir := GetTestBadgerDb()
    95  	defer os.RemoveAll(dir)
    96  
    97  	// Make a blockchain that looks as follows:
    98  	// b1 - -> b2 -> b3
    99  	//    \ -> b4
   100  	// I.e. there's a side chain in there.
   101  	b1 := _GetTestBlockNode()
   102  	b1.Height = 0
   103  	b2 := _GetTestBlockNode()
   104  	b2.Hash[0] = 0x99 // Make the hash of b2 sort lexographically later than b4 for kicks.
   105  	b2.Header.PrevBlockHash = b1.Hash
   106  	b2.Height = 1
   107  	b3 := _GetTestBlockNode()
   108  	b3.Hash[0] = 0x03
   109  	b3.Header.PrevBlockHash = b2.Hash
   110  	b3.Height = 2
   111  	b4 := _GetTestBlockNode()
   112  	b4.Hash[0] = 0x04
   113  	b4.Header.PrevBlockHash = b1.Hash
   114  	b4.Height = 1
   115  
   116  	err := PutHeightHashToNodeInfo(b1, db, false /*bitcoinNodes*/)
   117  	require.NoError(err)
   118  
   119  	err = PutHeightHashToNodeInfo(b2, db, false /*bitcoinNodes*/)
   120  	require.NoError(err)
   121  
   122  	err = PutHeightHashToNodeInfo(b3, db, false /*bitcoinNodes*/)
   123  	require.NoError(err)
   124  
   125  	err = PutHeightHashToNodeInfo(b4, db, false /*bitcoinNodes*/)
   126  	require.NoError(err)
   127  
   128  	blockIndex, err := GetBlockIndex(db, false /*bitcoinNodes*/)
   129  	require.NoError(err)
   130  
   131  	require.Len(blockIndex, 4)
   132  	b1Ret, exists := blockIndex[*b1.Hash]
   133  	require.True(exists, "b1 not found")
   134  
   135  	b2Ret, exists := blockIndex[*b2.Hash]
   136  	require.True(exists, "b2 not found")
   137  
   138  	b3Ret, exists := blockIndex[*b3.Hash]
   139  	require.True(exists, "b3 not found")
   140  
   141  	b4Ret, exists := blockIndex[*b4.Hash]
   142  	require.True(exists, "b4 not found")
   143  
   144  	// Make sure the hashes all line up.
   145  	require.Equal(b1.Hash[:], b1Ret.Hash[:])
   146  	require.Equal(b2.Hash[:], b2Ret.Hash[:])
   147  	require.Equal(b3.Hash[:], b3Ret.Hash[:])
   148  	require.Equal(b4.Hash[:], b4Ret.Hash[:])
   149  
   150  	// Make sure the nodes are connected properly.
   151  	require.Nil(b1Ret.Parent)
   152  	require.Equal(b2Ret.Parent, b1Ret)
   153  	require.Equal(b3Ret.Parent, b2Ret)
   154  	require.Equal(b4Ret.Parent, b1Ret)
   155  
   156  	// Check that getting the best chain works.
   157  	{
   158  		bestChain, err := GetBestChain(b3Ret, blockIndex)
   159  		require.NoError(err)
   160  		require.Len(bestChain, 3)
   161  		require.Equal(b1Ret, bestChain[0])
   162  		require.Equal(b2Ret, bestChain[1])
   163  		require.Equal(b3Ret, bestChain[2])
   164  	}
   165  }
   166  
   167  func TestInitDbWithGenesisBlock(t *testing.T) {
   168  	assert := assert.New(t)
   169  	require := require.New(t)
   170  	_ = assert
   171  	_ = require
   172  
   173  	// Create a test db and clean up the files at the end.
   174  	db, dir := GetTestBadgerDb()
   175  	defer os.RemoveAll(dir)
   176  
   177  	err := InitDbWithDeSoGenesisBlock(&DeSoTestnetParams, db, nil)
   178  	require.NoError(err)
   179  
   180  	// Check the block index.
   181  	blockIndex, err := GetBlockIndex(db, false /*bitcoinNodes*/)
   182  	require.NoError(err)
   183  	require.Len(blockIndex, 1)
   184  	genesisHash := *MustDecodeHexBlockHash(DeSoTestnetParams.GenesisBlockHashHex)
   185  	genesis, exists := blockIndex[genesisHash]
   186  	require.True(exists, "genesis block not found in index")
   187  	require.NotNil(genesis)
   188  	require.Equal(&genesisHash, genesis.Hash)
   189  
   190  	// Check the bestChain.
   191  	bestChain, err := GetBestChain(genesis, blockIndex)
   192  	require.NoError(err)
   193  	require.Len(bestChain, 1)
   194  	require.Equal(genesis, bestChain[0])
   195  }
   196  
   197  func TestPrivateMessages(t *testing.T) {
   198  	assert := assert.New(t)
   199  	require := require.New(t)
   200  	_ = assert
   201  	_ = require
   202  
   203  	// Create a test db and clean up the files at the end.
   204  	db, dir := GetTestBadgerDb()
   205  	defer os.RemoveAll(dir)
   206  
   207  	priv1, err := btcec.NewPrivateKey(btcec.S256())
   208  	require.NoError(err)
   209  	pk1 := priv1.PubKey().SerializeCompressed()
   210  
   211  	priv2, err := btcec.NewPrivateKey(btcec.S256())
   212  	require.NoError(err)
   213  	pk2 := priv2.PubKey().SerializeCompressed()
   214  
   215  	priv3, err := btcec.NewPrivateKey(btcec.S256())
   216  	require.NoError(err)
   217  	pk3 := priv3.PubKey().SerializeCompressed()
   218  
   219  	tstamp1 := uint64(1)
   220  	tstamp2 := uint64(2)
   221  	tstamp3 := uint64(12345)
   222  	tstamp4 := uint64(time.Now().UnixNano())
   223  	tstamp5 := uint64(time.Now().UnixNano())
   224  
   225  	message1Str := []byte("message1: abcdef")
   226  	message2Str := []byte("message2: ghi")
   227  	message3Str := []byte("message3: klmn\123\000\000\000_")
   228  	message4Str := append([]byte("message4: "), RandomBytes(100)...)
   229  	message5Str := append([]byte("message5: "), RandomBytes(123)...)
   230  
   231  	// pk1 -> pk2: message1Str, tstamp1
   232  	require.NoError(DbPutMessageEntry(
   233  		db, &MessageEntry{
   234  			SenderPublicKey:    pk1,
   235  			TstampNanos:        tstamp1,
   236  			RecipientPublicKey: pk2,
   237  			EncryptedText:      message1Str,
   238  		}))
   239  	// pk2 -> pk1: message2Str, tstamp2
   240  	require.NoError(DbPutMessageEntry(
   241  		db, &MessageEntry{
   242  			SenderPublicKey:    pk2,
   243  			TstampNanos:        tstamp2,
   244  			RecipientPublicKey: pk1,
   245  			EncryptedText:      message2Str,
   246  		}))
   247  	// pk3 -> pk1: message3Str, tstamp3
   248  	require.NoError(DbPutMessageEntry(
   249  		db, &MessageEntry{
   250  			SenderPublicKey:    pk3,
   251  			TstampNanos:        tstamp3,
   252  			RecipientPublicKey: pk1,
   253  			EncryptedText:      message3Str,
   254  		}))
   255  	// pk2 -> pk1: message4Str, tstamp4
   256  	require.NoError(DbPutMessageEntry(
   257  		db, &MessageEntry{
   258  			SenderPublicKey:    pk2,
   259  			TstampNanos:        tstamp4,
   260  			RecipientPublicKey: pk1,
   261  			EncryptedText:      message4Str,
   262  		}))
   263  	// pk1 -> pk3: message5Str, tstamp5
   264  	require.NoError(DbPutMessageEntry(
   265  		db, &MessageEntry{
   266  			SenderPublicKey:    pk1,
   267  			TstampNanos:        tstamp5,
   268  			RecipientPublicKey: pk3,
   269  			EncryptedText:      message5Str,
   270  		}))
   271  
   272  	// Define all the messages as they appear in the db.
   273  	message1 := &MessageEntry{
   274  		SenderPublicKey:    pk1,
   275  		RecipientPublicKey: pk2,
   276  		EncryptedText:      message1Str,
   277  		TstampNanos:        tstamp1,
   278  	}
   279  	message2 := &MessageEntry{
   280  		SenderPublicKey:    pk2,
   281  		RecipientPublicKey: pk1,
   282  		EncryptedText:      message2Str,
   283  		TstampNanos:        tstamp2,
   284  	}
   285  	message3 := &MessageEntry{
   286  		SenderPublicKey:    pk3,
   287  		RecipientPublicKey: pk1,
   288  		EncryptedText:      message3Str,
   289  		TstampNanos:        tstamp3,
   290  	}
   291  	message4 := &MessageEntry{
   292  		SenderPublicKey:    pk2,
   293  		RecipientPublicKey: pk1,
   294  		EncryptedText:      message4Str,
   295  		TstampNanos:        tstamp4,
   296  	}
   297  	message5 := &MessageEntry{
   298  		SenderPublicKey:    pk1,
   299  		RecipientPublicKey: pk3,
   300  		EncryptedText:      message5Str,
   301  		TstampNanos:        tstamp5,
   302  	}
   303  
   304  	// Fetch message3 directly using both public keys.
   305  	{
   306  		msg := DbGetMessageEntry(db, pk3, tstamp3)
   307  		require.Equal(message3, msg)
   308  	}
   309  	{
   310  		msg := DbGetMessageEntry(db, pk1, tstamp3)
   311  		require.Equal(message3, msg)
   312  	}
   313  
   314  	// Fetch all messages for pk1
   315  	{
   316  		messages, err := DbGetMessageEntriesForPublicKey(db, pk1)
   317  		require.NoError(err)
   318  
   319  		require.Equal([]*MessageEntry{
   320  			message1,
   321  			message2,
   322  			message3,
   323  			message4,
   324  			message5,
   325  		}, messages)
   326  	}
   327  
   328  	// Fetch all messages for pk2
   329  	{
   330  		messages, err := DbGetMessageEntriesForPublicKey(db, pk2)
   331  		require.NoError(err)
   332  
   333  		require.Equal([]*MessageEntry{
   334  			message1,
   335  			message2,
   336  			message4,
   337  		}, messages)
   338  	}
   339  
   340  	// Fetch all messages for pk3
   341  	{
   342  		messages, err := DbGetMessageEntriesForPublicKey(db, pk3)
   343  		require.NoError(err)
   344  
   345  		require.Equal([]*MessageEntry{
   346  			message3,
   347  			message5,
   348  		}, messages)
   349  	}
   350  
   351  	// Delete message3
   352  	require.NoError(DbDeleteMessageEntryMappings(db, pk1, tstamp3))
   353  
   354  	// Now all the messages returned should exclude message3
   355  	{
   356  		messages, err := DbGetMessageEntriesForPublicKey(db, pk1)
   357  		require.NoError(err)
   358  
   359  		require.Equal([]*MessageEntry{
   360  			message1,
   361  			message2,
   362  			message4,
   363  			message5,
   364  		}, messages)
   365  	}
   366  	{
   367  		messages, err := DbGetMessageEntriesForPublicKey(db, pk2)
   368  		require.NoError(err)
   369  
   370  		require.Equal([]*MessageEntry{
   371  			message1,
   372  			message2,
   373  			message4,
   374  		}, messages)
   375  	}
   376  	{
   377  		messages, err := DbGetMessageEntriesForPublicKey(db, pk3)
   378  		require.NoError(err)
   379  
   380  		require.Equal([]*MessageEntry{
   381  			message5,
   382  		}, messages)
   383  	}
   384  
   385  	// Delete all remaining messages, sometimes using the recipient rather
   386  	// than the sender public key
   387  	require.NoError(DbDeleteMessageEntryMappings(db, pk2, tstamp1))
   388  	require.NoError(DbDeleteMessageEntryMappings(db, pk1, tstamp2))
   389  	require.NoError(DbDeleteMessageEntryMappings(db, pk2, tstamp4))
   390  	require.NoError(DbDeleteMessageEntryMappings(db, pk1, tstamp5))
   391  
   392  	// Now all public keys should have zero messages.
   393  	{
   394  		messages, err := DbGetMessageEntriesForPublicKey(db, pk1)
   395  		require.NoError(err)
   396  		require.Equal(0, len(messages))
   397  	}
   398  	{
   399  		messages, err := DbGetMessageEntriesForPublicKey(db, pk2)
   400  		require.NoError(err)
   401  		require.Equal(0, len(messages))
   402  	}
   403  	{
   404  		messages, err := DbGetMessageEntriesForPublicKey(db, pk3)
   405  		require.NoError(err)
   406  		require.Equal(0, len(messages))
   407  	}
   408  }
   409  
   410  func TestFollows(t *testing.T) {
   411  	assert := assert.New(t)
   412  	require := require.New(t)
   413  	_ = assert
   414  	_ = require
   415  
   416  	// Create a test db and clean up the files at the end.
   417  	db, dir := GetTestBadgerDb()
   418  	defer os.RemoveAll(dir)
   419  
   420  	priv1, err := btcec.NewPrivateKey(btcec.S256())
   421  	require.NoError(err)
   422  	pk1 := priv1.PubKey().SerializeCompressed()
   423  
   424  	priv2, err := btcec.NewPrivateKey(btcec.S256())
   425  	require.NoError(err)
   426  	pk2 := priv2.PubKey().SerializeCompressed()
   427  
   428  	priv3, err := btcec.NewPrivateKey(btcec.S256())
   429  	require.NoError(err)
   430  	pk3 := priv3.PubKey().SerializeCompressed()
   431  
   432  	// Get the PKIDs for all the public keys
   433  	pkid1 := DBGetPKIDEntryForPublicKey(db, pk1).PKID
   434  	pkid2 := DBGetPKIDEntryForPublicKey(db, pk2).PKID
   435  	pkid3 := DBGetPKIDEntryForPublicKey(db, pk3).PKID
   436  
   437  	// PK2 follows everyone. Make sure "get" works properly.
   438  	require.Nil(DbGetFollowerToFollowedMapping(db, pkid2, pkid1))
   439  	require.NoError(DbPutFollowMappings(db, pkid2, pkid1))
   440  	require.NotNil(DbGetFollowerToFollowedMapping(db, pkid2, pkid1))
   441  	require.Nil(DbGetFollowerToFollowedMapping(db, pkid2, pkid3))
   442  	require.NoError(DbPutFollowMappings(db, pkid2, pkid3))
   443  	require.NotNil(DbGetFollowerToFollowedMapping(db, pkid2, pkid3))
   444  
   445  	// pkid3 only follows pkid1. Make sure "get" works properly.
   446  	require.Nil(DbGetFollowerToFollowedMapping(db, pkid3, pkid1))
   447  	require.NoError(DbPutFollowMappings(db, pkid3, pkid1))
   448  	require.NotNil(DbGetFollowerToFollowedMapping(db, pkid3, pkid1))
   449  
   450  	// Check PK1's followers.
   451  	{
   452  		pubKeys, err := DbGetPubKeysFollowingYou(db, pk1)
   453  		require.NoError(err)
   454  		for i := 0; i < len(pubKeys); i++ {
   455  			require.Contains([][]byte{pk2, pk3}, pubKeys[i])
   456  		}
   457  	}
   458  
   459  	// Check PK1's follows.
   460  	{
   461  		pubKeys, err := DbGetPubKeysYouFollow(db, pk1)
   462  		require.NoError(err)
   463  		require.Equal(len(pubKeys), 0)
   464  	}
   465  
   466  	// Check PK2's followers.
   467  	{
   468  		pubKeys, err := DbGetPubKeysFollowingYou(db, pk2)
   469  		require.NoError(err)
   470  		require.Equal(len(pubKeys), 0)
   471  	}
   472  
   473  	// Check PK2's follows.
   474  	{
   475  		pubKeys, err := DbGetPubKeysYouFollow(db, pk2)
   476  		require.NoError(err)
   477  		for i := 0; i < len(pubKeys); i++ {
   478  			require.Contains([][]byte{pk1, pk3}, pubKeys[i])
   479  		}
   480  	}
   481  
   482  	// Check PK3's followers.
   483  	{
   484  		pubKeys, err := DbGetPubKeysFollowingYou(db, pk3)
   485  		require.NoError(err)
   486  		for i := 0; i < len(pubKeys); i++ {
   487  			require.Contains([][]byte{pk2}, pubKeys[i])
   488  		}
   489  	}
   490  
   491  	// Check PK3's follows.
   492  	{
   493  		pubKeys, err := DbGetPubKeysYouFollow(db, pk3)
   494  		require.NoError(err)
   495  		for i := 0; i < len(pubKeys); i++ {
   496  			require.Contains([][]byte{pk1, pk1}, pubKeys[i])
   497  		}
   498  	}
   499  
   500  	// Delete PK2's follows.
   501  	require.NoError(DbDeleteFollowMappings(db, pkid2, pkid1))
   502  	require.NoError(DbDeleteFollowMappings(db, pkid2, pkid3))
   503  
   504  	// Check PK2's follows were actually deleted.
   505  	{
   506  		pubKeys, err := DbGetPubKeysYouFollow(db, pk2)
   507  		require.NoError(err)
   508  		require.Equal(len(pubKeys), 0)
   509  	}
   510  }