github.com/incognitochain/go-incognito-sdk@v1.0.1/privacy/coin_test.go (about)

     1  package privacy
     2  
     3  import (
     4  	"errors"
     5  	"github.com/incognitochain/go-incognito-sdk/common"
     6  	"github.com/stretchr/testify/assert"
     7  	"io/ioutil"
     8  	"log"
     9  	"math/big"
    10  	"testing"
    11  )
    12  
    13  var _ = func() (_ struct{}) {
    14  	return
    15  }()
    16  
    17  func TestMain(m *testing.M) {
    18  	log.SetOutput(ioutil.Discard)
    19  	m.Run()
    20  }
    21  
    22  /*
    23  	Unit test for CommitAll Coin
    24  */
    25  
    26  func TestCoinCommitAll(t *testing.T) {
    27  	for i := 0; i < 1000; i++ {
    28  		coin := new(Coin).Init()
    29  		seedKey := RandomScalar().ToBytesS()
    30  		privateKey := GeneratePrivateKey(seedKey)
    31  		publicKey := GeneratePublicKey(privateKey)
    32  
    33  		// init other fields for coin
    34  		coin.publicKey.FromBytesS(publicKey)
    35  
    36  		coin.snDerivator = RandomScalar()
    37  		coin.randomness = RandomScalar()
    38  		coin.value = new(big.Int).SetBytes(RandBytes(2)).Uint64()
    39  		coin.serialNumber = new(Point).Derive(PedCom.G[0], new(Scalar).FromBytesS(privateKey), coin.snDerivator)
    40  		coin.CommitAll()
    41  		coin.info = []byte("Incognito chain")
    42  
    43  		cmTmp := coin.GetPublicKey()
    44  		shardID := common.GetShardIDFromLastByte(coin.GetPubKeyLastByte())
    45  		cmTmp.Add(cmTmp, new(Point).ScalarMult(PedCom.G[PedersenValueIndex], new(Scalar).FromUint64(uint64(coin.GetValue()))))
    46  		cmTmp.Add(cmTmp, new(Point).ScalarMult(PedCom.G[PedersenSndIndex], coin.snDerivator))
    47  		cmTmp.Add(cmTmp, new(Point).ScalarMult(PedCom.G[PedersenShardIDIndex], new(Scalar).FromUint64(uint64(shardID))))
    48  		cmTmp.Add(cmTmp, new(Point).ScalarMult(PedCom.G[PedersenRandomnessIndex], coin.GetRandomness()))
    49  
    50  		res := IsPointEqual(cmTmp, coin.GetCoinCommitment())
    51  		assert.Equal(t, true, res)
    52  	}
    53  }
    54  
    55  func TestCoinMarshalJSON(t *testing.T) {
    56  
    57  	for i := 0; i < 1000; i++ {
    58  		coin := new(Coin).Init()
    59  		seedKey := RandomScalar().ToBytesS()
    60  		privateKey := GeneratePrivateKey(seedKey)
    61  		publicKey := GeneratePublicKey(privateKey)
    62  
    63  		// init other fields for coin
    64  		coin.publicKey.FromBytesS(publicKey)
    65  		coin.snDerivator = RandomScalar()
    66  		coin.randomness = RandomScalar()
    67  		coin.value = uint64(100)
    68  		coin.serialNumber = PedCom.G[0].Derive(PedCom.G[0], new(Scalar).FromBytesS(privateKey), coin.snDerivator)
    69  		coin.CommitAll()
    70  		coin.info = []byte("Incognito chain")
    71  
    72  		bytesJSON, err := coin.MarshalJSON()
    73  		assert.Equal(t, nil, err)
    74  
    75  		coin2 := new(Coin)
    76  		err2 := coin2.UnmarshalJSON(bytesJSON)
    77  		assert.Equal(t, nil, err2)
    78  		assert.Equal(t, coin, coin2)
    79  	}
    80  }
    81  
    82  /*
    83  	Unit test for Bytes/SetBytes Coin function
    84  */
    85  
    86  func TestCoinBytesSetBytes(t *testing.T) {
    87  
    88  	for i := 0; i < 1000; i++ {
    89  		coin := new(Coin).Init()
    90  		seedKey := RandomScalar().ToBytesS()
    91  		privateKey := GeneratePrivateKey(seedKey)
    92  		publicKey := GeneratePublicKey(privateKey)
    93  
    94  		// init other fields for coin
    95  		coin.publicKey.FromBytesS(publicKey)
    96  		coin.snDerivator = RandomScalar()
    97  		coin.randomness = RandomScalar()
    98  		coin.value = uint64(100)
    99  		coin.serialNumber = PedCom.G[0].Derive(PedCom.G[0], new(Scalar).FromBytesS(privateKey), coin.snDerivator)
   100  		coin.CommitAll()
   101  		coin.info = []byte("Incognito chain")
   102  
   103  		// convert coin object to bytes array
   104  		coinBytes := coin.Bytes()
   105  
   106  		assert.Greater(t, len(coinBytes), 0)
   107  
   108  		// new coin object and set bytes from bytes array
   109  		coin2 := new(Coin)
   110  		err := coin2.SetBytes(coinBytes)
   111  
   112  		assert.Equal(t, nil, err)
   113  		assert.Equal(t, coin, coin2)
   114  	}
   115  }
   116  
   117  func TestCoinBytesSetBytesWithMissingFields(t *testing.T) {
   118  	for i := 0; i < 1000; i++ {
   119  		coin := new(Coin).Init()
   120  		seedKey := RandomScalar().ToBytesS()
   121  		privateKey := GeneratePrivateKey(seedKey)
   122  		publicKey := GeneratePublicKey(privateKey)
   123  
   124  		// init other fields for coin
   125  		coin.publicKey.FromBytesS(publicKey)
   126  		coin.snDerivator = RandomScalar()
   127  		coin.randomness = RandomScalar()
   128  		coin.value = uint64(100)
   129  		coin.serialNumber = PedCom.G[0].Derive(PedCom.G[0], new(Scalar).FromBytesS(privateKey), coin.snDerivator)
   130  		//coin.CommitAll()
   131  		coin.info = []byte("Incognito chain")
   132  
   133  		// convert coin object to bytes array
   134  		coinBytes := coin.Bytes()
   135  
   136  		assert.Greater(t, len(coinBytes), 0)
   137  
   138  		// new coin object and set bytes from bytes array
   139  		coin2 := new(Coin).Init()
   140  		err := coin2.SetBytes(coinBytes)
   141  
   142  		assert.Equal(t, nil, err)
   143  		assert.Equal(t, coin, coin2)
   144  	}
   145  }
   146  
   147  func TestCoinBytesSetBytesWithInvalidBytes(t *testing.T) {
   148  	// init coin with fully fields
   149  	// init public key
   150  	coin := new(Coin).Init()
   151  	seedKey := RandomScalar().ToBytesS()
   152  	privateKey := GeneratePrivateKey(seedKey)
   153  	publicKey := GeneratePublicKey(privateKey)
   154  
   155  	// init other fields for coin
   156  	coin.publicKey.FromBytesS(publicKey)
   157  	coin.snDerivator = RandomScalar()
   158  	coin.randomness = RandomScalar()
   159  	coin.value = uint64(100)
   160  	coin.serialNumber = PedCom.G[0].Derive(PedCom.G[0], new(Scalar).FromBytesS(privateKey), coin.snDerivator)
   161  	coin.CommitAll()
   162  	coin.info = []byte("Incognito chain")
   163  
   164  	// convert coin object to bytes array
   165  	coinBytes := coin.Bytes()
   166  	assert.Greater(t, len(coinBytes), 0)
   167  
   168  	// edit coinBytes
   169  	coinBytes[len(coinBytes)-2] = byte(12)
   170  
   171  	// new coin object and set bytes from bytes array
   172  	coin2 := new(Coin).Init()
   173  	err := coin2.SetBytes(coinBytes)
   174  
   175  	assert.Equal(t, nil, err)
   176  	assert.NotEqual(t, coin, coin2)
   177  }
   178  
   179  func TestCoinBytesSetBytesWithEmptyBytes(t *testing.T) {
   180  	// new coin object and set bytes from bytes array
   181  	coin2 := new(Coin).Init()
   182  	err := coin2.SetBytes([]byte{})
   183  
   184  	assert.Equal(t, errors.New("coinBytes is empty"), err)
   185  }
   186  
   187  /*
   188  	Unit test for Bytes/SetBytes InputCoin function
   189  */
   190  
   191  func TestInputCoinBytesSetBytes(t *testing.T) {
   192  	for i := 0; i < 1000; i++ {
   193  		coin := new(InputCoin).Init()
   194  		seedKey := RandomScalar().ToBytesS()
   195  		privateKey := GeneratePrivateKey(seedKey)
   196  		publicKey := GeneratePublicKey(privateKey)
   197  
   198  		// init other fields for coin
   199  		coin.CoinDetails.publicKey.FromBytesS(publicKey)
   200  
   201  		coin.CoinDetails.snDerivator = RandomScalar()
   202  		coin.CoinDetails.randomness = RandomScalar()
   203  		coin.CoinDetails.value = uint64(100)
   204  		coin.CoinDetails.serialNumber = PedCom.G[0].Derive(PedCom.G[0], new(Scalar).FromBytesS(privateKey), coin.CoinDetails.snDerivator)
   205  		coin.CoinDetails.CommitAll()
   206  		coin.CoinDetails.info = []byte("Incognito chain")
   207  
   208  		// convert coin object to bytes array
   209  		coinBytes := coin.Bytes()
   210  
   211  		assert.Greater(t, len(coinBytes), 0)
   212  
   213  		// new coin object and set bytes from bytes array
   214  		coin2 := new(InputCoin)
   215  		err := coin2.SetBytes(coinBytes)
   216  
   217  		assert.Equal(t, nil, err)
   218  		assert.Equal(t, coin, coin2)
   219  	}
   220  }
   221  
   222  func TestInputCoinBytesSetBytesWithMissingFields(t *testing.T) {
   223  	coin := new(InputCoin).Init()
   224  	seedKey := RandomScalar().ToBytesS()
   225  	privateKey := GeneratePrivateKey(seedKey)
   226  	publicKey := GeneratePublicKey(privateKey)
   227  
   228  	coin.CoinDetails.publicKey.FromBytesS(publicKey)
   229  
   230  	coin.CoinDetails.snDerivator = RandomScalar()
   231  	coin.CoinDetails.randomness = RandomScalar()
   232  	coin.CoinDetails.value = uint64(100)
   233  	coin.CoinDetails.serialNumber = PedCom.G[0].Derive(PedCom.G[0], new(Scalar).FromBytesS(privateKey), coin.CoinDetails.snDerivator)
   234  	//coin.CoinDetails.CommitAll()
   235  	coin.CoinDetails.info = []byte("Incognito chain")
   236  
   237  	// convert coin object to bytes array
   238  	coinBytes := coin.Bytes()
   239  	assert.Greater(t, len(coinBytes), 0)
   240  
   241  	// new coin object and set bytes from bytes array
   242  	coin2 := new(InputCoin).Init()
   243  	err := coin2.SetBytes(coinBytes)
   244  
   245  	assert.Equal(t, nil, err)
   246  	assert.Equal(t, coin, coin2)
   247  }
   248  
   249  func TestInputCoinBytesSetBytesWithInvalidBytes(t *testing.T) {
   250  	coin := new(InputCoin).Init()
   251  	seedKey := RandomScalar().ToBytesS()
   252  	privateKey := GeneratePrivateKey(seedKey)
   253  	publicKey := GeneratePublicKey(privateKey)
   254  
   255  	coin.CoinDetails.publicKey.FromBytesS(publicKey)
   256  
   257  	coin.CoinDetails.snDerivator = RandomScalar()
   258  	coin.CoinDetails.randomness = RandomScalar()
   259  	coin.CoinDetails.value = uint64(100)
   260  	coin.CoinDetails.serialNumber = PedCom.G[0].Derive(PedCom.G[0], new(Scalar).FromBytesS(privateKey), coin.CoinDetails.snDerivator)
   261  	//coin.CoinDetails.CommitAll()
   262  	coin.CoinDetails.info = []byte("Incognito chain")
   263  
   264  	// convert coin object to bytes array
   265  	coinBytes := coin.Bytes()
   266  	assert.Greater(t, len(coinBytes), 0)
   267  
   268  	// edit coinBytes
   269  	coinBytes[len(coinBytes)-2] = byte(12)
   270  
   271  	// new coin object and set bytes from bytes array
   272  	coin2 := new(InputCoin).Init()
   273  	err := coin2.SetBytes(coinBytes)
   274  
   275  	assert.Equal(t, nil, err)
   276  	assert.NotEqual(t, coin, coin2)
   277  }
   278  
   279  func TestInputCoinBytesSetBytesWithEmptyBytes(t *testing.T) {
   280  	// new coin object and set bytes from bytes array
   281  	coin2 := new(InputCoin).Init()
   282  	err := coin2.SetBytes([]byte{})
   283  
   284  	assert.Equal(t, errors.New("coinBytes is empty"), err)
   285  }
   286  
   287  /*
   288  	Unit test for Bytes/SetBytes OutputCoin function
   289  */
   290  
   291  func TestOutputCoinBytesSetBytes(t *testing.T) {
   292  	coin := new(OutputCoin).Init()
   293  	seedKey := RandomScalar().ToBytesS()
   294  	privateKey := GeneratePrivateKey(seedKey)
   295  	publicKey := GeneratePublicKey(privateKey)
   296  	paymentAddr := GeneratePaymentAddress(privateKey)
   297  
   298  	coin.CoinDetails.publicKey.FromBytesS(publicKey)
   299  
   300  	coin.CoinDetails.snDerivator = RandomScalar()
   301  	coin.CoinDetails.randomness = RandomScalar()
   302  	coin.CoinDetails.value = uint64(100)
   303  	coin.CoinDetails.serialNumber = PedCom.G[0].Derive(PedCom.G[0], new(Scalar).FromBytesS(privateKey), coin.CoinDetails.snDerivator)
   304  	//coin.CoinDetails.CommitAll()
   305  	coin.CoinDetails.info = []byte("Incognito chain")
   306  	coin.Encrypt(paymentAddr.Tk)
   307  
   308  	// convert coin object to bytes array
   309  	coinBytes := coin.Bytes()
   310  
   311  	assert.Greater(t, len(coinBytes), 0)
   312  
   313  	// new coin object and set bytes from bytes array
   314  	coin2 := new(OutputCoin)
   315  	err := coin2.SetBytes(coinBytes)
   316  
   317  	assert.Equal(t, nil, err)
   318  	assert.Equal(t, coin, coin2)
   319  }
   320  
   321  func TestOutputCoinBytesSetBytesWithMissingFields(t *testing.T) {
   322  	coin := new(OutputCoin).Init()
   323  	seedKey := RandomScalar().ToBytesS()
   324  	privateKey := GeneratePrivateKey(seedKey)
   325  	publicKey := GeneratePublicKey(privateKey)
   326  	paymentAddr := GeneratePaymentAddress(privateKey)
   327  
   328  	coin.CoinDetails.publicKey.FromBytesS(publicKey)
   329  
   330  	coin.CoinDetails.snDerivator = RandomScalar()
   331  	coin.CoinDetails.randomness = RandomScalar()
   332  	coin.CoinDetails.value = uint64(100)
   333  	//coin.CoinDetails.serialNumber = PedCom.G[0].Derive(PedCom.G[0], new(Scalar).FromBytes(SliceToArray(privateKey)), coin.CoinDetails.snDerivator)
   334  	//coin.CoinDetails.CommitAll()
   335  	coin.CoinDetails.info = []byte("Incognito chain")
   336  	coin.Encrypt(paymentAddr.Tk)
   337  
   338  	// convert coin object to bytes array
   339  	coinBytes := coin.Bytes()
   340  	assert.Greater(t, len(coinBytes), 0)
   341  
   342  	// new coin object and set bytes from bytes array
   343  	coin2 := new(OutputCoin).Init()
   344  	err := coin2.SetBytes(coinBytes)
   345  
   346  	assert.Equal(t, nil, err)
   347  	assert.Equal(t, coin, coin2)
   348  }
   349  
   350  func TestOutputCoinBytesSetBytesWithInvalidBytes(t *testing.T) {
   351  	coin := new(OutputCoin).Init()
   352  	seedKey := RandomScalar().ToBytesS()
   353  	privateKey := GeneratePrivateKey(seedKey)
   354  	publicKey := GeneratePublicKey(privateKey)
   355  	paymentAddr := GeneratePaymentAddress(privateKey)
   356  
   357  	coin.CoinDetails.publicKey.FromBytesS(publicKey)
   358  
   359  	coin.CoinDetails.snDerivator = RandomScalar()
   360  	coin.CoinDetails.randomness = RandomScalar()
   361  	coin.CoinDetails.value = uint64(100)
   362  	//coin.CoinDetails.serialNumber = PedCom.G[0].Derive(PedCom.G[0], new(Scalar).FromBytes(SliceToArray(privateKey)), coin.CoinDetails.snDerivator)
   363  	//coin.CoinDetails.CommitAll()
   364  	coin.CoinDetails.info = []byte("Incognito chain")
   365  	coin.Encrypt(paymentAddr.Tk)
   366  
   367  	// convert coin object to bytes array
   368  	coinBytes := coin.Bytes()
   369  	assert.Greater(t, len(coinBytes), 0)
   370  
   371  	// edit coinBytes
   372  	coinBytes[len(coinBytes)-2] = byte(12)
   373  
   374  	// new coin object and set bytes from bytes array
   375  	coin2 := new(OutputCoin).Init()
   376  	err := coin2.SetBytes(coinBytes)
   377  
   378  	assert.Equal(t, nil, err)
   379  	assert.NotEqual(t, coin, coin2)
   380  }
   381  
   382  func TestOutputCoinBytesSetBytesWithEmptyBytes(t *testing.T) {
   383  	// new coin object and set bytes from bytes array
   384  	coin2 := new(OutputCoin).Init()
   385  	err := coin2.SetBytes([]byte{})
   386  
   387  	assert.Equal(t, errors.New("coinBytes is empty"), err)
   388  }
   389  
   390  /*
   391  	Unit test for Encrypt/Decrypt OutputCoin
   392  */
   393  func TestOutputCoinEncryptDecrypt(t *testing.T) {
   394  	// prepare key
   395  	seedKey := RandomScalar().ToBytesS()
   396  	privateKey := GeneratePrivateKey(seedKey)
   397  	paymentAddress := GeneratePaymentAddress(privateKey)
   398  	viewingKey := GenerateViewingKey(privateKey)
   399  
   400  	for i := 0; i < 100; i++ {
   401  		// new output coin with value and randomness
   402  		coin := new(OutputCoin).Init()
   403  		coin.CoinDetails.randomness = RandomScalar()
   404  		coin.CoinDetails.value = new(big.Int).SetBytes(RandBytes(2)).Uint64()
   405  		coin.CoinDetails.publicKey.FromBytesS(paymentAddress.Pk)
   406  
   407  		// encrypt output coins
   408  		err := coin.Encrypt(paymentAddress.Tk)
   409  		assert.Equal(t, (*PrivacyError)(nil), err)
   410  
   411  		// convert output coin to bytes array
   412  		coinBytes := coin.Bytes()
   413  
   414  		// create new output coin to test
   415  		coin2 := new(OutputCoin)
   416  		err2 := coin2.SetBytes(coinBytes)
   417  		assert.Equal(t, nil, err2)
   418  
   419  		err3 := coin2.Decrypt(viewingKey)
   420  		assert.Equal(t, (*PrivacyError)(nil), err3)
   421  
   422  		assert.Equal(t, coin.CoinDetails.randomness, coin2.CoinDetails.randomness)
   423  		assert.Equal(t, coin.CoinDetails.value, coin2.CoinDetails.value)
   424  	}
   425  }
   426  
   427  func TestOutputCoinEncryptDecryptWithUnmatchedKey(t *testing.T) {
   428  	// prepare key
   429  	seedKey := RandomScalar().ToBytesS()
   430  	privateKey := GeneratePrivateKey(seedKey)
   431  	paymentAddress := GeneratePaymentAddress(privateKey)
   432  	viewingKey := GenerateViewingKey(privateKey)
   433  
   434  	// new output coin with value and randomness
   435  	coin := new(OutputCoin).Init()
   436  	coin.CoinDetails.randomness = RandomScalar()
   437  	coin.CoinDetails.value = new(big.Int).SetBytes(RandBytes(2)).Uint64()
   438  	coin.CoinDetails.publicKey.FromBytesS(paymentAddress.Pk)
   439  
   440  	// encrypt output coins
   441  	err := coin.Encrypt(paymentAddress.Tk)
   442  	assert.Equal(t, (*PrivacyError)(nil), err)
   443  
   444  	// convert output coin to bytes array
   445  	coinBytes := coin.Bytes()
   446  
   447  	// create new output coin to test
   448  	coin2 := new(OutputCoin)
   449  	err2 := coin2.SetBytes(coinBytes)
   450  	assert.Equal(t, nil, err2)
   451  
   452  	// edit receiving key to be unmatched with transmission key
   453  	viewingKey.Rk[0] = 12
   454  	err3 := coin2.Decrypt(viewingKey)
   455  	assert.Equal(t, (*PrivacyError)(nil), err3)
   456  	assert.NotEqual(t, coin.CoinDetails.randomness, coin2.CoinDetails.randomness)
   457  	assert.NotEqual(t, coin.CoinDetails.value, coin2.CoinDetails.value)
   458  }