forked from TrueCloudLab/neoneo-go
0090577446
It's useless and it's just another copy of the key. If really needed, it can be derived from the key.
224 lines
6.7 KiB
Go
224 lines
6.7 KiB
Go
package wallet
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/nspcc-dev/neo-go/internal/keytestcases"
|
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestNewAccount(t *testing.T) {
|
|
acc, err := NewAccount()
|
|
require.NoError(t, err)
|
|
require.NotNil(t, acc)
|
|
}
|
|
|
|
func TestDecryptAccount(t *testing.T) {
|
|
for _, testCase := range keytestcases.Arr {
|
|
acc := &Account{EncryptedWIF: testCase.EncryptedWif}
|
|
assert.Nil(t, acc.PrivateKey())
|
|
err := acc.Decrypt(testCase.Passphrase, keys.NEP2ScryptParams())
|
|
if testCase.Invalid {
|
|
assert.Error(t, err)
|
|
continue
|
|
}
|
|
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, acc.PrivateKey())
|
|
assert.Equal(t, testCase.PrivateKey, acc.privateKey.String())
|
|
}
|
|
// No encrypted key.
|
|
acc := &Account{}
|
|
require.Error(t, acc.Decrypt("qwerty", keys.NEP2ScryptParams()))
|
|
}
|
|
|
|
func TestNewFromWif(t *testing.T) {
|
|
for _, testCase := range keytestcases.Arr {
|
|
acc, err := NewAccountFromWIF(testCase.Wif)
|
|
if testCase.Invalid {
|
|
assert.Error(t, err)
|
|
continue
|
|
}
|
|
|
|
assert.NoError(t, err)
|
|
compareFields(t, testCase, acc)
|
|
}
|
|
}
|
|
|
|
func TestNewAccountFromEncryptedWIF(t *testing.T) {
|
|
for _, tc := range keytestcases.Arr {
|
|
acc, err := NewAccountFromEncryptedWIF(tc.EncryptedWif, tc.Passphrase, keys.NEP2ScryptParams())
|
|
if tc.Invalid {
|
|
assert.Error(t, err)
|
|
continue
|
|
}
|
|
|
|
assert.NoError(t, err)
|
|
compareFields(t, tc, acc)
|
|
}
|
|
}
|
|
|
|
func TestContract_MarshalJSON(t *testing.T) {
|
|
var c Contract
|
|
|
|
data := []byte(`{"script":"AQI=","parameters":[{"name":"name0", "type":"Signature"}],"deployed":false}`)
|
|
require.NoError(t, json.Unmarshal(data, &c))
|
|
require.Equal(t, []byte{1, 2}, c.Script)
|
|
|
|
result, err := json.Marshal(c)
|
|
require.NoError(t, err)
|
|
require.JSONEq(t, string(data), string(result))
|
|
|
|
data = []byte(`1`)
|
|
require.Error(t, json.Unmarshal(data, &c))
|
|
|
|
data = []byte(`{"script":"ERROR","parameters":[1],"deployed":false}`)
|
|
require.Error(t, json.Unmarshal(data, &c))
|
|
}
|
|
|
|
func TestContractSignTx(t *testing.T) {
|
|
acc, err := NewAccount()
|
|
require.NoError(t, err)
|
|
require.True(t, acc.CanSign())
|
|
|
|
accNoContr := *acc
|
|
accNoContr.Contract = nil
|
|
tx := &transaction.Transaction{
|
|
Script: []byte{1, 2, 3},
|
|
Signers: []transaction.Signer{{
|
|
Account: acc.Contract.ScriptHash(),
|
|
Scopes: transaction.CalledByEntry,
|
|
}},
|
|
}
|
|
require.Error(t, accNoContr.SignTx(0, tx))
|
|
|
|
acc2, err := NewAccount()
|
|
require.NoError(t, err)
|
|
require.True(t, acc2.CanSign())
|
|
|
|
require.Error(t, acc2.SignTx(0, tx))
|
|
|
|
pubs := keys.PublicKeys{acc.privateKey.PublicKey(), acc2.privateKey.PublicKey()}
|
|
multiS, err := smartcontract.CreateDefaultMultiSigRedeemScript(pubs)
|
|
require.NoError(t, err)
|
|
multiAcc := NewAccountFromPrivateKey(acc.privateKey)
|
|
require.NoError(t, multiAcc.ConvertMultisig(2, pubs))
|
|
multiAcc2 := NewAccountFromPrivateKey(acc2.privateKey)
|
|
require.NoError(t, multiAcc2.ConvertMultisig(2, pubs))
|
|
|
|
tx = &transaction.Transaction{
|
|
Script: []byte{1, 2, 3},
|
|
Signers: []transaction.Signer{{
|
|
Account: acc2.Contract.ScriptHash(),
|
|
Scopes: transaction.CalledByEntry,
|
|
}, {
|
|
Account: acc.Contract.ScriptHash(),
|
|
Scopes: transaction.None,
|
|
}, {
|
|
Account: hash.Hash160(multiS),
|
|
Scopes: transaction.None,
|
|
}},
|
|
}
|
|
require.Error(t, acc.SignTx(0, tx)) // Can't append, no witness for acc2.
|
|
|
|
require.NoError(t, acc2.SignTx(0, tx)) // Append script for acc2.
|
|
require.Equal(t, 1, len(tx.Scripts))
|
|
require.Equal(t, 66, len(tx.Scripts[0].InvocationScript))
|
|
|
|
require.NoError(t, acc2.SignTx(0, tx)) // Sign again, effectively a no-op.
|
|
require.Equal(t, 1, len(tx.Scripts))
|
|
require.Equal(t, 66, len(tx.Scripts[0].InvocationScript))
|
|
|
|
acc2.Locked = true
|
|
require.False(t, acc2.CanSign())
|
|
require.Error(t, acc2.SignTx(0, tx)) // Locked account.
|
|
|
|
acc2.Locked = false
|
|
acc2.privateKey = nil
|
|
require.False(t, acc2.CanSign())
|
|
require.Error(t, acc2.SignTx(0, tx)) // No private key.
|
|
|
|
tx.Scripts = append(tx.Scripts, transaction.Witness{
|
|
VerificationScript: acc.Contract.Script,
|
|
})
|
|
require.NoError(t, acc.SignTx(0, tx)) // Add invocation script for existing witness.
|
|
require.Equal(t, 66, len(tx.Scripts[1].InvocationScript))
|
|
|
|
require.NoError(t, multiAcc.SignTx(0, tx))
|
|
require.Equal(t, 3, len(tx.Scripts))
|
|
require.Equal(t, 66, len(tx.Scripts[2].InvocationScript))
|
|
|
|
require.NoError(t, multiAcc2.SignTx(0, tx)) // Append to existing script.
|
|
require.Equal(t, 3, len(tx.Scripts))
|
|
require.Equal(t, 132, len(tx.Scripts[2].InvocationScript))
|
|
}
|
|
|
|
func TestContract_ScriptHash(t *testing.T) {
|
|
script := []byte{0, 1, 2, 3}
|
|
c := &Contract{Script: script}
|
|
|
|
require.Equal(t, hash.Hash160(script), c.ScriptHash())
|
|
}
|
|
|
|
func TestAccount_ConvertMultisig(t *testing.T) {
|
|
// test is based on a wallet1_solo.json accounts from neo-local
|
|
a, err := NewAccountFromWIF("KxyjQ8eUa4FHt3Gvioyt1Wz29cTUrE4eTqX3yFSk1YFCsPL8uNsY")
|
|
require.NoError(t, err)
|
|
|
|
hexs := []string{
|
|
"02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2", // <- this is our key
|
|
"02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e",
|
|
"02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62",
|
|
"03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699",
|
|
}
|
|
|
|
t.Run("invalid number of signatures", func(t *testing.T) {
|
|
pubs := convertPubs(t, hexs)
|
|
require.Error(t, a.ConvertMultisig(0, pubs))
|
|
})
|
|
|
|
t.Run("account key is missing from multisig", func(t *testing.T) {
|
|
pubs := convertPubs(t, hexs[1:])
|
|
require.Error(t, a.ConvertMultisig(1, pubs))
|
|
})
|
|
|
|
t.Run("1/1 multisig", func(t *testing.T) {
|
|
pubs := convertPubs(t, hexs[:1])
|
|
require.NoError(t, a.ConvertMultisig(1, pubs))
|
|
require.Equal(t, "NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP", a.Address)
|
|
})
|
|
|
|
t.Run("3/4 multisig", func(t *testing.T) {
|
|
pubs := convertPubs(t, hexs)
|
|
require.NoError(t, a.ConvertMultisig(3, pubs))
|
|
require.Equal(t, "NVTiAjNgagDkTr5HTzDmQP9kPwPHN5BgVq", a.Address)
|
|
})
|
|
}
|
|
|
|
func convertPubs(t *testing.T, hexKeys []string) []*keys.PublicKey {
|
|
pubs := make([]*keys.PublicKey, len(hexKeys))
|
|
for i := range pubs {
|
|
var err error
|
|
pubs[i], err = keys.NewPublicKeyFromString(hexKeys[i])
|
|
require.NoError(t, err)
|
|
}
|
|
return pubs
|
|
}
|
|
|
|
func compareFields(t *testing.T, tk keytestcases.Ktype, acc *Account) {
|
|
want, have := tk.Address, acc.Address
|
|
require.Equalf(t, want, have, "expected address %s got %s", want, have)
|
|
want, have = tk.Wif, acc.privateKey.WIF()
|
|
require.Equalf(t, want, have, "expected wif %s got %s", want, have)
|
|
want, have = tk.PublicKey, hex.EncodeToString(acc.publicKey)
|
|
require.Equalf(t, want, have, "expected pub key %s got %s", want, have)
|
|
want, have = tk.PrivateKey, acc.privateKey.String()
|
|
require.Equalf(t, want, have, "expected priv key %s got %s", want, have)
|
|
}
|