538 lines
45 KiB
Plaintext
538 lines
45 KiB
Plaintext
|
// Copyright 2017-2018 DERO Project. All rights reserved.
|
||
|
// Use of this source code in any form is governed by RESEARCH license.
|
||
|
// license can be found in the LICENSE file.
|
||
|
// GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8
|
||
|
//
|
||
|
//
|
||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
||
|
package walletapi
|
||
|
|
||
|
import "os"
|
||
|
import "fmt"
|
||
|
import "testing"
|
||
|
import "bytes"
|
||
|
import "crypto/rand"
|
||
|
import "path/filepath"
|
||
|
import "encoding/hex"
|
||
|
import "encoding/binary"
|
||
|
import "runtime/pprof"
|
||
|
|
||
|
import "github.com/deroproject/derosuite/globals"
|
||
|
import "github.com/deroproject/derosuite/crypto"
|
||
|
import "github.com/deroproject/derosuite/crypto/ringct"
|
||
|
import "github.com/deroproject/derosuite/transaction"
|
||
|
|
||
|
func init() {
|
||
|
globals.Init_rlog()
|
||
|
}
|
||
|
|
||
|
// this will test that the keys are placed properly and thus can be decoded by recievers
|
||
|
func Test_Creation_TX(t *testing.T) {
|
||
|
|
||
|
temp_db := filepath.Join(os.TempDir(), "dero_temporary_test_wallet.db")
|
||
|
|
||
|
os.Remove(temp_db)
|
||
|
|
||
|
w, err := Create_Encrypted_Wallet(temp_db, "QWER", *crypto.RandomScalar())
|
||
|
if err != nil {
|
||
|
t.Fatalf("Cannot create encrypted wallet, err %s", err)
|
||
|
}
|
||
|
|
||
|
defer os.Remove(temp_db) // cleanup after test
|
||
|
//sender,_ := Generate_Keys_From_Random() // we have a single sender
|
||
|
|
||
|
var receivers []*Account
|
||
|
|
||
|
randomBytes := make([]byte, 4)
|
||
|
|
||
|
for loop := 0; loop < 10; loop++ { // run the test randomly 200 times
|
||
|
rand.Read(randomBytes)
|
||
|
random_inputs := 1 + (binary.LittleEndian.Uint32(randomBytes) % 20) //minimum 1 input is necessary
|
||
|
rand.Read(randomBytes)
|
||
|
random_outputs := 1 + (binary.LittleEndian.Uint32(randomBytes) % 20) //minimum 1 output is necessary
|
||
|
|
||
|
if loop == 0 {
|
||
|
random_inputs = 100
|
||
|
}
|
||
|
|
||
|
if loop == 1 {
|
||
|
random_outputs = 200 // randomly place 200 outputs in single tx
|
||
|
}
|
||
|
|
||
|
if loop == 2 {
|
||
|
random_inputs = 500
|
||
|
random_outputs = 2
|
||
|
}
|
||
|
|
||
|
txw := TX_Wallet_Data{WAmount: 4000000000000}
|
||
|
txw.TXdata.Index_Global = 739
|
||
|
txw.TXdata.Height = 730
|
||
|
txw.WKey.Destination = crypto.HexToKey("dbdfd2a3e9da6911b0a3e37e8e448f2de2477f81760585c2f197736bac127e0f")
|
||
|
txw.WKey.Mask = crypto.HexToKey("01e4e85ab0b5e30dd86b5356f0f6b4177738b9e6b32041c4e4781a2f26083101")
|
||
|
txw.WKimage = crypto.HexToKey("d8fb3b4260aea6582400a5f48244ff3f7c4dc36420698e3decc5d28ba04733c2")
|
||
|
txw.TXdata.InKey.Destination = crypto.HexToKey("ed0da9e74d240088a07909ea354b8d140b753642e25495e0931b4623b25ff523")
|
||
|
txw.TXdata.InKey.Mask = crypto.HexToKey("dbddab6c6b3063074e7cfd1a7f83f184ad78e92c8ff25118c0ed4edc77015948")
|
||
|
|
||
|
var outs []ringct.Output_info
|
||
|
for i := uint32(0); i < random_outputs; i++ {
|
||
|
r, _ := Generate_Keys_From_Random()
|
||
|
receivers = append(receivers, r)
|
||
|
|
||
|
out := ringct.Output_info{Public_Spend_Key: receivers[i].GetAddress().SpendKey,
|
||
|
Public_View_Key: receivers[i].GetAddress().ViewKey}
|
||
|
|
||
|
if i == 0 { // balance the outputs
|
||
|
out.Amount = uint64(random_inputs) * txw.WAmount
|
||
|
}
|
||
|
outs = append(outs, out) // fill outs with random address
|
||
|
}
|
||
|
|
||
|
var ins []ringct.Input_info
|
||
|
for i := uint32(0); i < random_inputs; i++ {
|
||
|
|
||
|
ins = append(ins, ringct.Input_info{Amount: txw.WAmount, Key_image: crypto.Hash(txw.WKimage), Sk: txw.WKey, Index_Global: txw.TXdata.Index_Global})
|
||
|
|
||
|
//now we must the ring members
|
||
|
ins[i].Ring_Members = append(ins[i].Ring_Members, txw.TXdata.Index_Global)
|
||
|
ins[i].Pubs = append(ins[i].Pubs, txw.TXdata.InKey)
|
||
|
|
||
|
// lets add 5 ring members randomly
|
||
|
for j := uint64(0); j < 5; j++ {
|
||
|
ins[i].Ring_Members = append(ins[i].Ring_Members, txw.TXdata.Index_Global+j+1)
|
||
|
ins[i].Pubs = append(ins[i].Pubs, ringct.CtKey{Destination: *crypto.RandomScalar(), Mask: *crypto.RandomScalar()})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 739th main net consumed output
|
||
|
var payment_id []byte
|
||
|
|
||
|
if loop%2 == 0 {
|
||
|
payment_id = make([]byte, 32, 32) // test 32 byte payment id
|
||
|
} else {
|
||
|
payment_id = make([]byte, 8, 8) // make encrypted payment ID
|
||
|
}
|
||
|
|
||
|
if loop%3 == 0 {
|
||
|
payment_id = make([]byte, 0, 0) // test with out payment id
|
||
|
}
|
||
|
|
||
|
bulletproof := false
|
||
|
if loop%2 == 1 {
|
||
|
bulletproof = true
|
||
|
}
|
||
|
|
||
|
tx := w.Create_TX_v2(ins, outs, 0, 0, payment_id, bulletproof)
|
||
|
|
||
|
if !tx.RctSignature.Verify() {
|
||
|
t.Fatalf("TX ring signature verification failed")
|
||
|
}
|
||
|
|
||
|
// now check whether the outputs can be verified successfuly after serdes
|
||
|
var tx2 transaction.Transaction
|
||
|
tx2.DeserializeHeader(tx.Serialize())
|
||
|
tx2.Parse_Extra()
|
||
|
|
||
|
public_key := tx2.Extra_map[transaction.TX_PUBLIC_KEY].(crypto.Key)
|
||
|
|
||
|
if len(payment_id) == 8 { // test whether payment ID was encrypted and decrypted successfully
|
||
|
epayid := tx.PaymentID_map[transaction.TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID].([]byte)
|
||
|
|
||
|
derivation := crypto.KeyDerivation(&public_key, &receivers[0].Keys.Viewkey_Secret)
|
||
|
payid := EncryptDecryptPaymentID(derivation, public_key, epayid)
|
||
|
|
||
|
t.Logf("epay id %x decrypted %x", epayid, payid)
|
||
|
|
||
|
if !bytes.Equal(payment_id, payid) {
|
||
|
t.Fatalf("8 byte encrypted payment ID missing failed")
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if len(payment_id) == 32 { // test full 32 byte payment id
|
||
|
if !bytes.Equal(payment_id, tx.PaymentID_map[transaction.TX_EXTRA_NONCE_PAYMENT_ID].([]byte)) {
|
||
|
t.Fatalf("32 byte payment ID missing, failed")
|
||
|
}
|
||
|
}
|
||
|
for output_index := range outs {
|
||
|
|
||
|
tx_out_to_key := tx2.Vout[output_index].Target.(transaction.Txout_to_key)
|
||
|
if !receivers[output_index].Is_Output_Ours(public_key, uint64(output_index), tx_out_to_key.Key) {
|
||
|
t.Fatalf("Output mismatch index %d", output_index)
|
||
|
}
|
||
|
|
||
|
}
|
||
|
t.Logf("inputs %5d\toutputs %5d\t tx size %4d KB %+v", random_inputs, random_outputs, len(tx.Serialize())/1024, bulletproof)
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// this will test that the keys are placed properly and thus can be decoded by recievers
|
||
|
// this also forces the ring size from 2 to 10
|
||
|
func Test_Creation_TX_Size(t *testing.T) {
|
||
|
|
||
|
temp_db := filepath.Join(os.TempDir(), "dero_temporary_test_wallet.db")
|
||
|
|
||
|
os.Remove(temp_db)
|
||
|
|
||
|
w, err := Create_Encrypted_Wallet(temp_db, "QWER", *crypto.RandomScalar())
|
||
|
if err != nil {
|
||
|
t.Fatalf("Cannot create encrypted wallet, err %s", err)
|
||
|
}
|
||
|
|
||
|
defer os.Remove(temp_db) // cleanup after test
|
||
|
//sender,_ := Generate_Keys_From_Random() // we have a single sender
|
||
|
|
||
|
var receivers []*Account
|
||
|
|
||
|
randomBytes := make([]byte, 4)
|
||
|
|
||
|
for loop := 0; loop < 1; loop++ { // run the test randomly 200 times
|
||
|
rand.Read(randomBytes)
|
||
|
random_inputs := 1 + (binary.LittleEndian.Uint32(randomBytes) % 20) //minimum 1 input is necessary
|
||
|
rand.Read(randomBytes)
|
||
|
random_outputs := 1 + (binary.LittleEndian.Uint32(randomBytes) % 20) //minimum 1 output is necessary
|
||
|
|
||
|
random_inputs = 20 * uint32(loop+1)
|
||
|
random_outputs = 2
|
||
|
|
||
|
txw := TX_Wallet_Data{WAmount: 4000000000000}
|
||
|
txw.TXdata.Index_Global = 739
|
||
|
txw.TXdata.Height = 730
|
||
|
txw.WKey.Destination = crypto.HexToKey("dbdfd2a3e9da6911b0a3e37e8e448f2de2477f81760585c2f197736bac127e0f")
|
||
|
txw.WKey.Mask = crypto.HexToKey("01e4e85ab0b5e30dd86b5356f0f6b4177738b9e6b32041c4e4781a2f26083101")
|
||
|
txw.WKimage = crypto.HexToKey("d8fb3b4260aea6582400a5f48244ff3f7c4dc36420698e3decc5d28ba04733c2")
|
||
|
txw.TXdata.InKey.Destination = crypto.HexToKey("ed0da9e74d240088a07909ea354b8d140b753642e25495e0931b4623b25ff523")
|
||
|
txw.TXdata.InKey.Mask = crypto.HexToKey("dbddab6c6b3063074e7cfd1a7f83f184ad78e92c8ff25118c0ed4edc77015948")
|
||
|
|
||
|
var outs []ringct.Output_info
|
||
|
for i := uint32(0); i < random_outputs; i++ {
|
||
|
r, _ := Generate_Keys_From_Random()
|
||
|
receivers = append(receivers, r)
|
||
|
|
||
|
out := ringct.Output_info{Public_Spend_Key: receivers[i].GetAddress().SpendKey,
|
||
|
Public_View_Key: receivers[i].GetAddress().ViewKey}
|
||
|
|
||
|
if i == 0 { // balance the outputs
|
||
|
out.Amount = uint64(random_inputs) * txw.WAmount
|
||
|
}
|
||
|
outs = append(outs, out) // fill outs with random address
|
||
|
}
|
||
|
|
||
|
ring_sizes := []uint64{1, 2, 3, 4, 5, 6, 7, 8, 10}
|
||
|
|
||
|
for x := range ring_sizes {
|
||
|
|
||
|
var ins []ringct.Input_info
|
||
|
for i := uint32(0); i < random_inputs; i++ {
|
||
|
|
||
|
ins = append(ins, ringct.Input_info{Amount: txw.WAmount, Key_image: crypto.Hash(txw.WKimage), Sk: txw.WKey, Index_Global: txw.TXdata.Index_Global})
|
||
|
|
||
|
//now we must the ring members
|
||
|
ins[i].Ring_Members = append(ins[i].Ring_Members, txw.TXdata.Index_Global)
|
||
|
ins[i].Pubs = append(ins[i].Pubs, txw.TXdata.InKey)
|
||
|
|
||
|
// lets add 5 ring members randomly
|
||
|
for j := uint64(0); j < ring_sizes[x]; j++ {
|
||
|
ins[i].Ring_Members = append(ins[i].Ring_Members, txw.TXdata.Index_Global+j+1)
|
||
|
ins[i].Pubs = append(ins[i].Pubs, ringct.CtKey{Destination: *crypto.RandomScalar(), Mask: *crypto.RandomScalar()})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 739th main net consumed output
|
||
|
var payment_id []byte
|
||
|
|
||
|
if loop%2 == 0 {
|
||
|
payment_id = make([]byte, 32, 32) // test 32 byte payment id
|
||
|
} else {
|
||
|
payment_id = make([]byte, 8, 8) // make encrypted payment ID
|
||
|
}
|
||
|
|
||
|
if loop%3 == 0 {
|
||
|
payment_id = make([]byte, 0, 0) // test with out payment id
|
||
|
}
|
||
|
|
||
|
bulletproof := true
|
||
|
|
||
|
tx := w.Create_TX_v2(ins, outs, 0, 0, payment_id, bulletproof)
|
||
|
|
||
|
if !tx.RctSignature.Verify() {
|
||
|
t.Fatalf("TX ring signature verification failed")
|
||
|
}
|
||
|
|
||
|
// now check whether the outputs can be verified successfuly after serdes
|
||
|
var tx2 transaction.Transaction
|
||
|
tx2.DeserializeHeader(tx.Serialize())
|
||
|
tx2.Parse_Extra()
|
||
|
|
||
|
public_key := tx2.Extra_map[transaction.TX_PUBLIC_KEY].(crypto.Key)
|
||
|
|
||
|
if len(payment_id) == 8 { // test whether payment ID was encrypted and decrypted successfully
|
||
|
epayid := tx.PaymentID_map[transaction.TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID].([]byte)
|
||
|
|
||
|
derivation := crypto.KeyDerivation(&public_key, &receivers[0].Keys.Viewkey_Secret)
|
||
|
payid := EncryptDecryptPaymentID(derivation, public_key, epayid)
|
||
|
|
||
|
//t.Logf("epay id %x decrypted %x", epayid, payid)
|
||
|
|
||
|
if !bytes.Equal(payment_id, payid) {
|
||
|
t.Fatalf("8 byte encrypted payment ID missing failed")
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if len(payment_id) == 32 { // test full 32 byte payment id
|
||
|
if !bytes.Equal(payment_id, tx.PaymentID_map[transaction.TX_EXTRA_NONCE_PAYMENT_ID].([]byte)) {
|
||
|
t.Fatalf("32 byte payment ID missing, failed")
|
||
|
}
|
||
|
}
|
||
|
for output_index := range outs {
|
||
|
|
||
|
tx_out_to_key := tx2.Vout[output_index].Target.(transaction.Txout_to_key)
|
||
|
if !receivers[output_index].Is_Output_Ours(public_key, uint64(output_index), tx_out_to_key.Key) {
|
||
|
t.Fatalf("Output mismatch index %d", output_index)
|
||
|
}
|
||
|
|
||
|
}
|
||
|
t.Logf("inputs %5d\toutputs %5d\t ring size %5d tx size %4d KB %+v", random_inputs, random_outputs, ring_sizes[x], len(tx.Serialize())/1024, bulletproof)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/* Related logs here for improvig the test here
|
||
|
*
|
||
|
[wallet dERoiV]: integrated_address
|
||
|
Random payment ID: <0cbd6e050cf3b73c>
|
||
|
Matching integrated address: dERijfr9y7XhWkdEPp17RJLXVoHkr2ucMdEbgGgpskhLb33732LBifWMCZhPga3EcjXoYqfM9jRv3W3bnWUSpdmKL24FBjG6ctTAEg1jrhDHh
|
||
|
[wallet dERoiV]: address
|
||
|
dERoiVavtPjhWkdEPp17RJLXVoHkr2ucMdEbgGgpskhLb33732LBifWMCZhPga3EcjXoYqfM9jRv3W3bnWUSpdmK5Jur1PhN6P
|
||
|
[wallet dERoiV]: help
|
||
|
|
||
|
[wallet dERoiV]: transfer dERijfr9y7XhWkdEPp17RJLXVoHkr2ucMdEbgGgpskhLb33732LBifWMCZhPga3EcjXoYqfM9jRv3W3bnWUSpdmKL24FBjG6ctTAEg1jrhDHh 1
|
||
|
Wallet password:
|
||
|
Sending 1.000000000000. The transaction fee is 0.049197120000
|
||
|
Is this okay? (Y/Yes/N/No): y
|
||
|
Transaction successfully submitted, transaction <ea551b02b9f1e8aebe4d7b1b7f6bf173d76ae614cb9a066800773fee9e226fd7>
|
||
|
You can check its status by using the `show_transfers` command.
|
||
|
[wallet dERoiV]: get_tx_key ea551b02b9f1e8aebe4d7b1b7f6bf173d76ae614cb9a066800773fee9e226fd7
|
||
|
unknown command: ge_tx_key ea551b02b9f1e8aebe4d7b1b7f6bf173d76ae614cb9a066800773fee9e226fd7
|
||
|
[wallet dERoiV]: get_tx_key ea551b02b9f1e8aebe4d7b1b7f6bf173d76ae614cb9a066800773fee9e226fd7
|
||
|
Wallet password:
|
||
|
Tx key: af7b5a4e75410d585e7faeb254811ea1274f6d20205205213c79655fe3958c07
|
||
|
Height 2175, transaction <31b019dba022b29f8342f71c4ede91fea8b4236469786ae55f131af3432d3989>, received 31.661910734197
|
||
|
Height 2175, transaction <ea551b02b9f1e8aebe4d7b1b7f6bf173d76ae614cb9a066800773fee9e226fd7>, received 7.862704628648
|
||
|
* Height 2175, transaction <ea551b02b9f1e8aebe4d7b1b7f6bf173d76ae614cb9a066800773fee9e226fd7>, received 1.000000000000
|
||
|
Height 2175, transaction <ea551b02b9f1e8aebe4d7b1b7f6bf173d76ae614cb9a066800773fee9e226fd7>, spent 8.903560733970
|
||
|
Height 2175, transaction <ea551b02b9f1e8aebe4d7b1b7f6bf173d76ae614cb9a066800773fee9e226fd7>, spent 0.008341014678
|
||
|
|
||
|
*/
|
||
|
// this will test that the keys are placed properly and thus can be decoded by recievers
|
||
|
func Test_Creation_TX_Encrypted_PaymentID_check(t *testing.T) {
|
||
|
temp_db := filepath.Join(os.TempDir(), "dero_temporary_test_wallet.db")
|
||
|
|
||
|
os.Remove(temp_db)
|
||
|
|
||
|
w, err := Create_Encrypted_Wallet(temp_db, "QWER", crypto.HexToKey("aebcbe93d8c386f954bbc2122d9d6423b7e5b77a6ad31c6a43855e15b9760c0d"))
|
||
|
if err != nil {
|
||
|
t.Fatalf("Cannot create encrypted wallet, err %s", err)
|
||
|
}
|
||
|
|
||
|
defer os.Remove(temp_db) // cleanup after test
|
||
|
|
||
|
tx_created_by_oldwallet_hex := "020002020005e1e401c90cc556b33ac30ec7b09288b613edc262773a1b426e244288bd7083703f64f9ba70932c005aab8a020005a441a597019b06db9001c90fb8b71bdf1694dc432a501201d9072f03b57e8ffc4b438525874af2b19fbefd7402000251ae0c92c8ef002020afe3ba8bbc7893a3421dd766aac5e4838c96e44b1aa9390002d0d5b3be45fada433dcb2787e289ac5656ec24f8c595ad5b761629b9d5204d172c0100e7e904ef8ceffbb04e14bb8bccfcbf219e33e878cc8087120b751b5c5423a502090112ac08ed7db374000280f481a3b701b59b6e44f8868a02e0b83eac1bd1101cd10f2ff62e2aaadc6d6d38ad6d4dd90a5d81bfb3011eef1b918ba1229e701c5baa418c0ce329f2aaba840da4ca46cfc40e957969a0890f12e82bb6e4cceabfd47f6d1d67069b52c05fc474c117a6510d3ba22a6b1d7313ed8bdda62a193e8638e1ff94cf3fc51bbb4421d1749c259b0c0f2b1aa6e3389e50d25f178240c7ca0ab147218971ba8555767debff4ad6ae001e8d5d500c9c7d49d8b00c0101e4ec13d6eae6c91df46fb082d4165016b2f00c2529d45b561bbecd12e84ec45df0cfc19572da72af45826d07cf9ff1c227cbcc325877b202c7b4cee9c31e8a39210aa2286e52b8d16bf958615b466c267168de6c7995854d27f455c0277adbb041961c201a0d0860e856f39fd311da5f748c0c382133de4fd17c7ab44d559b03f00fe10345c0daae4c9f1fd8c08f1f6e117d02830e8698e536b3d5bd1df197a320f0811456ba0d28e071b2eb75f5523c8635074ae15c24dd59e20912fede1af9297d7035524b43cde58f825bc8ed2659ca530594a064a249582416f4c93692cfd44e9668a1e928a406e54d8f891070e25d5f09e33fc80eec42a5599c1814f5b9361d698be0be4fefebc1a9a3b814297823a10fb885e33117ad8f48ffc06e2ddb071d14df5917cb4520e69a962bc6927eea8b0803e52985f168c655f79335687ead4e82fcd720c8546e42a76212c8c7a14eda016c4f6edcb3dda0aacb66e6e1dd777d689bead64d8d48af1d74a48d4213aa460e38255a3b73914d64a12d1e2044989f8862fed2be7a0a625ca0ac26a371affa0830850aaaadce63edb3db84f96aff87bdbd74e75c9aac4f5a83450595d47cd609acee9d3c3c3db7c774543e49d498e63932fb61a71a4b2753806b0f8558f40401a1f0454b568a923f59e5f85e6f33eb71fffa6300667fee110cf86276d80d510705a491bd7c86c317adf3b94353751602ad493f1ad4d627936b990bb74579230c5644c9085346a8513a21fa73b0c06b145ae02fe2c2ad619e8843a7e32d81210e3e4c6d05756b10b5aa0b380a18adb30b64a28f58e5c27892922866beb2ae200e9c9dbe6e62bbd5a21119ecbb1571aa918e8c7647b963062dfb6e38bab61dfd04b5deab8a7b24223541d3d05a3dd5e9f15e134036befc0778ee89ca65cb025b0e02e8d92c10725152b50f5d242238f15fe81eafdbf79f3144442648109dee850c167b7915fdd9f996f4890b2ffc30b8c0fec3a1d30f7bfc3e5a21f93f15d7fa066375326b30fa277de3a1d6b55b0bc5435044d99b8f0b3860ca0378e6d747420eea963f3f34ab1a6283b0338fbc0be94427a3f3ef8121282b067c82f416595c087dec5aad206c426d758016f240c1fffe5b3fb053d51a4fe795b09a80d409fc02fccdc92c51711c67a6b79f3c4a4bc87f006af05125de1eb8cd0f99929d205b03e8828db099b7c177f033abb297840dcd7d8723a61c3f96c6e3c348b973992b0f0bf5fbb3dda2eac764462c289b16dc01578b46e642a9678b4edf6f5625d28e0338b8c5a331d703fdf0595e40dea4d6e845110dfeb7a649712871a08dbe99f7054251821ac6634ca4af736b479eedb2fd87a566cf3990fb1591137f71834daa0b350c7041ade602a375a530b129209a9af357e3a0485124d049d1b9e1c906c804ff2d7566a2f3c659995dd65b1f42d943b65afb60210182749060e2709ed82902bb772e105f6730da8db97dc4203dd1833e9b24e64511eefc7a123616ff28130c5d48343f2defee057f65ef059df97ba01f4820275b90ad2458a7cc7fc568ff0cf28aa734aeaeedde3b5574c3819d020d725408860b174210ba7b67b2043d470e2ebe6f75631a1e2fad92968edb26a1adfdf06667f09d5e25ce6c48bb8368870185222b356126ee4de0c6728ace83226bc46b22a0f5ce0b81a8bf4264117830089ffaea98bf4326515d5f8cd0a44bb4af9a29c3756db5eb3453b282d00a6a1d06654623a5db5693cd50fd087e9422f235414aaf8ce6d26a064090969f5f49950cff06838c3947843384371769d4d51326447b5da564b36f5c256e7348f08c140d91231c88ef4ec28ab90789b8054ee972b48bbe06bb7556dbe0ac59ffc7d02b0c90d2ca7476134d2504e98eb548ce35488e976de0c565b3035aefefbf11b9bb034f8df46a67e2cab724f268fd3c5b6797fed72bc21fc373cba12e3ba1e9a54d0690481fbd521765fb7bc392680af376a366276606140f2e47903b9905ea0aa806662d23ce1154a2f0c35e5139874e9c58caff19a6d5eaa9a7aac5f30378f59f09df16f5102944fd5f9fabd39f6fd2b166dea8bca27c9e6df7c163f00b01cdab08ebf5f9559a0343af81edb0f7e8b0aa14314a7ad47a9a314421457e3b765d1d07ad5868082a6bdabdbc12c4eca16243c2fdc25c3b3f4566d6169b6c9cbe50320c16fd4e319fbe81115d9d041f6c660f8dcb418e07e58e6954484e35886f1c900c8dfa96b696cda674d0dc359f45e9502b9e13b26bab8100e8e59f75f13973460e2eb4ae27ca2359bdca01146a827caf3b6456774b6637
|
||
|
tx_created_by_oldwallet, _ := hex.DecodeString(tx_created_by_oldwallet_hex)
|
||
|
|
||
|
var tx transaction.Transaction
|
||
|
|
||
|
err = tx.DeserializeHeader(tx_created_by_oldwallet)
|
||
|
if err != nil {
|
||
|
t.Fatalf("TX could not be deserialized. This needs to be fixed urgently as encrypted payment ID functionalyi is broken")
|
||
|
}
|
||
|
|
||
|
// the tx is sending payment to itself with encrypted payment
|
||
|
tx.Parse_Extra()
|
||
|
|
||
|
public_key := tx.Extra_map[transaction.TX_PUBLIC_KEY].(crypto.Key)
|
||
|
|
||
|
payment_id := "0cbd6e050cf3b73c"
|
||
|
|
||
|
// lets locate and decode payment id, see whether it matches with expected value
|
||
|
epayid := tx.PaymentID_map[transaction.TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID].([]byte)
|
||
|
|
||
|
derivation := crypto.KeyDerivation(&public_key, &w.account.Keys.Viewkey_Secret)
|
||
|
payid := EncryptDecryptPaymentID(derivation, public_key, epayid)
|
||
|
|
||
|
t.Logf("epay id %x decrypted %x original payment ID %s ", epayid, payid, payment_id)
|
||
|
|
||
|
if payment_id != fmt.Sprintf("%x", payid) {
|
||
|
t.Fatalf("8 byte encrypted payment ID missing failed, Critical, encrypted payment Id failed")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// this will create the transaction and benchmark the verification times
|
||
|
// this also forces the ring size from 2 to 10
|
||
|
func benchmark_TX_Verification(b *testing.B, num_inputs uint32, num_outputs uint32, num_ring_size int) (tx *transaction.Transaction) {
|
||
|
|
||
|
temp_db := filepath.Join(os.TempDir(), "dero_temporary_test_wallet.db")
|
||
|
|
||
|
os.Remove(temp_db)
|
||
|
|
||
|
w, err := Create_Encrypted_Wallet(temp_db, "QWER", *crypto.RandomScalar())
|
||
|
if err != nil {
|
||
|
b.Fatalf("Cannot create encrypted wallet, err %s", err)
|
||
|
}
|
||
|
|
||
|
defer os.Remove(temp_db) // cleanup after test
|
||
|
//sender,_ := Generate_Keys_From_Random() // we have a single sender
|
||
|
|
||
|
var receivers []*Account
|
||
|
|
||
|
randomBytes := make([]byte, 4)
|
||
|
|
||
|
rand.Read(randomBytes)
|
||
|
random_inputs := 1 + (binary.LittleEndian.Uint32(randomBytes) % 20) //minimum 1 input is necessary
|
||
|
rand.Read(randomBytes)
|
||
|
random_outputs := 1 + (binary.LittleEndian.Uint32(randomBytes) % 20) //minimum 1 output is necessary
|
||
|
|
||
|
random_inputs = num_inputs
|
||
|
random_outputs = num_outputs
|
||
|
|
||
|
txw := TX_Wallet_Data{WAmount: 4000000000000}
|
||
|
txw.TXdata.Index_Global = 739
|
||
|
txw.TXdata.Height = 730
|
||
|
txw.WKey.Destination = crypto.HexToKey("dbdfd2a3e9da6911b0a3e37e8e448f2de2477f81760585c2f197736bac127e0f")
|
||
|
txw.WKey.Mask = crypto.HexToKey("01e4e85ab0b5e30dd86b5356f0f6b4177738b9e6b32041c4e4781a2f26083101")
|
||
|
txw.WKimage = crypto.HexToKey("d8fb3b4260aea6582400a5f48244ff3f7c4dc36420698e3decc5d28ba04733c2")
|
||
|
txw.TXdata.InKey.Destination = crypto.HexToKey("ed0da9e74d240088a07909ea354b8d140b753642e25495e0931b4623b25ff523")
|
||
|
txw.TXdata.InKey.Mask = crypto.HexToKey("dbddab6c6b3063074e7cfd1a7f83f184ad78e92c8ff25118c0ed4edc77015948")
|
||
|
|
||
|
var outs []ringct.Output_info
|
||
|
for i := uint32(0); i < random_outputs; i++ {
|
||
|
r, _ := Generate_Keys_From_Random()
|
||
|
receivers = append(receivers, r)
|
||
|
|
||
|
out := ringct.Output_info{Public_Spend_Key: receivers[i].GetAddress().SpendKey,
|
||
|
Public_View_Key: receivers[i].GetAddress().ViewKey}
|
||
|
|
||
|
if i == 0 { // balance the outputs
|
||
|
out.Amount = uint64(random_inputs) * txw.WAmount
|
||
|
}
|
||
|
outs = append(outs, out) // fill outs with random address
|
||
|
}
|
||
|
|
||
|
ring_size := uint64(num_ring_size)
|
||
|
|
||
|
var ins []ringct.Input_info
|
||
|
for i := uint32(0); i < random_inputs; i++ {
|
||
|
|
||
|
ins = append(ins, ringct.Input_info{Amount: txw.WAmount, Key_image: crypto.Hash(txw.WKimage), Sk: txw.WKey, Index_Global: txw.TXdata.Index_Global})
|
||
|
|
||
|
//now we must the ring members
|
||
|
ins[i].Ring_Members = append(ins[i].Ring_Members, txw.TXdata.Index_Global)
|
||
|
ins[i].Pubs = append(ins[i].Pubs, txw.TXdata.InKey)
|
||
|
|
||
|
// lets add 5 ring members randomly
|
||
|
for j := uint64(0); j < ring_size; j++ {
|
||
|
ins[i].Ring_Members = append(ins[i].Ring_Members, txw.TXdata.Index_Global+j+1)
|
||
|
ins[i].Pubs = append(ins[i].Pubs, ringct.CtKey{Destination: *crypto.RandomScalar(), Mask: *crypto.RandomScalar()})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// 739th main net consumed output
|
||
|
var payment_id []byte
|
||
|
|
||
|
bulletproof := true
|
||
|
|
||
|
tx = w.Create_TX_v2(ins, outs, 0, 0, payment_id, bulletproof)
|
||
|
|
||
|
return tx
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
func Benchmark_TX_Verification_inputs_10_outputs_2_mixin_7(b *testing.B){
|
||
|
benchmark_TX_Verification(b,10,2,7)
|
||
|
}
|
||
|
func Benchmark_TX_Verification_inputs_10_outputs_4_mixin_7(b *testing.B){
|
||
|
benchmark_TX_Verification(b,10,4,7)
|
||
|
}
|
||
|
func Benchmark_TX_Verification_inputs_10_outputs_7_mixin_7(b *testing.B){
|
||
|
benchmark_TX_Verification(b,10,7,7)
|
||
|
}
|
||
|
func Benchmark_TX_Verification_inputs_10_outputs_9_mixin_7(b *testing.B){
|
||
|
benchmark_TX_Verification(b,10,9,7)
|
||
|
}
|
||
|
func Benchmark_TX_Verification_inputs_10_outputs_11_mixin_7(b *testing.B){
|
||
|
benchmark_TX_Verification(b,10,11,7)
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
func Benchmark_TX_Verification(b *testing.B){
|
||
|
|
||
|
cpufile,err := os.Create("/tmp/cpuprofile.prof")
|
||
|
if err != nil{
|
||
|
|
||
|
}
|
||
|
if err := pprof.StartCPUProfile(cpufile); err != nil {
|
||
|
}
|
||
|
defer pprof.StopCPUProfile()
|
||
|
|
||
|
input := uint32(20)
|
||
|
output := uint32(2)
|
||
|
mixin := 7
|
||
|
|
||
|
b.Run(fmt.Sprintf("in %d/ out %d/mixin %d", input, output,mixin), func(b *testing.B) {
|
||
|
tx := benchmark_TX_Verification(b,input,output,mixin)
|
||
|
b.Logf("tx size %d bytes %d KB", len(tx.Serialize()), len(tx.Serialize())/1024)
|
||
|
b.ResetTimer()
|
||
|
for n := 0; n < b.N; n++ {
|
||
|
if !tx.RctSignature.Verify() {
|
||
|
b.Fatalf("TX ring signature verification failed")
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
// verify and confirm few parameters for the network
|
||
|
func Benchmark_TX_Verification(b *testing.B) {
|
||
|
|
||
|
cpufile, err := os.Create("/tmp/cpuprofile.prof")
|
||
|
if err != nil {
|
||
|
|
||
|
}
|
||
|
if err := pprof.StartCPUProfile(cpufile); err != nil {
|
||
|
}
|
||
|
defer pprof.StopCPUProfile()
|
||
|
|
||
|
for input := uint32(10); input < 400; input += 50 {
|
||
|
for output := uint32(1); output < 9; output += 2 {
|
||
|
for mixin := 5; mixin < 15; mixin += 3 {
|
||
|
b.Run(fmt.Sprintf("in %d/ out %d/mixin %d", input, output, mixin), func(b *testing.B) {
|
||
|
benchmark_TX_Verification(b, input, output, mixin)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* specific testing if required
|
||
|
// inputs
|
||
|
func Benchmark_TX_Verification_inputs_10_outputs_2_mixin_8(b *testing.B){
|
||
|
benchmark_TX_Verification(b,10,2,8)
|
||
|
}
|
||
|
*/
|