Skip to content
This repository has been archived by the owner on Mar 21, 2024. It is now read-only.

Commit

Permalink
Add test case
Browse files Browse the repository at this point in the history
TestReportFound
  • Loading branch information
yahtoo committed Nov 22, 2018
1 parent 7acd499 commit 5d3f6c2
Show file tree
Hide file tree
Showing 2 changed files with 244 additions and 40 deletions.
8 changes: 6 additions & 2 deletions wallet/recovery.go
Expand Up @@ -203,11 +203,15 @@ func (m *recoveryManager) AddrResurrect(accts []*account.Account) error {

for _, acct := range accts {
m.state.stateForScope(acct)
if err := m.extendScanAddresses(acct.ID, true); err != nil {
if err := m.extendScanAddresses(acct.ID, false); err != nil {
return err
}

if err := m.extendScanAddresses(acct.ID, false); err != nil {
//Bip32 path no change field, no need to create addresses repeatedly.
if acct.DeriveRule == signers.BIP0032 {
continue
}
if err := m.extendScanAddresses(acct.ID, true); err != nil {
return err
}
}
Expand Down
276 changes: 238 additions & 38 deletions wallet/recovery_test.go
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/bytom/blockchain/txbuilder"
"github.com/bytom/consensus"
"github.com/bytom/crypto/ed25519/chainkd"
"github.com/bytom/errors"
"github.com/bytom/protocol/bc"
"github.com/bytom/protocol/bc/types"
)
Expand Down Expand Up @@ -127,6 +128,55 @@ func MockTxsP2PKH(acctMgr *account.Manager, xPub chainkd.XPub, multiTypeAccount
return txs, nil
}

func TestXPubsRecoveryLock(t *testing.T) {
dirPath, err := ioutil.TempDir(".", "")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dirPath)

testDB := dbm.NewDB("testdb", "leveldb", dirPath)
hsm, err := pseudohsm.New(dirPath)
if err != nil {
t.Fatal(err)
}

xpub, _, err := hsm.XCreate("test_pub", "password", "en")
if err != nil {
t.Fatal(err)
}

acctMgr := account.NewManager(testDB, nil)
recoveryMgr := newRecoveryManager(testDB, acctMgr)
recoveryMgr.state = newRecoveryState()
recoveryMgr.state.XPubs = []chainkd.XPub{xpub.XPub}
recoveryMgr.state.XPubsStatus = newBranchRecoveryState(acctRecoveryWindow)

recoveryMgr.state.StartTime = time.Now()
recoveryMgr.commitStatusInfo()

if err := recoveryMgr.AcctResurrect([]chainkd.XPub{xpub.XPub}); err != nil {
t.Fatal("TestXPubsRecoveryLock err:", err)
}

if err := recoveryMgr.AcctResurrect([]chainkd.XPub{xpub.XPub}); err != errors.Root(ErrRecoveryBusy) {
t.Fatal("TestXPubsRecoveryLock err:", err)
}

if err := recoveryMgr.LoadStatusInfo(); err != errors.Root(ErrRecoveryBusy) {
t.Fatal("TestXPubsRecoveryLock err:", err)
}

recoveryMgr.stopXPubsRec()
if err := recoveryMgr.LoadStatusInfo(); err != nil {
t.Fatal("TestXPubsRecoveryLock err:", err)
}
recoveryMgr.finished()
if err := recoveryMgr.AcctResurrect([]chainkd.XPub{xpub.XPub}); err != nil {
t.Fatal("TestXPubsRecoveryLock err:", err)
}
}

func TestExtendScanAddresses(t *testing.T) {
dirPath, err := ioutil.TempDir(".", "")
if err != nil {
Expand Down Expand Up @@ -205,36 +255,54 @@ func TestRecoveryFromXPubs(t *testing.T) {
txs, err := MockTxsP2PKH(acctMgr, xpub.XPub, false)
recAcctMgr := account.NewManager(recoveryDB, nil)
recoveryMgr := newRecoveryManager(recoveryDB, recAcctMgr)
if err := recoveryMgr.AcctResurrect([]chainkd.XPub{xpub.XPub}); err != nil {
t.Fatal("recovery from XPubs err:", err)
}

if err := recoveryMgr.FilterRecoveryTxs(MockBlock(txs)); err != nil {
t.Fatal("recovery from XPubs err:", err)
cases := []struct {
xPubs []chainkd.XPub
err error
}{
{[]chainkd.XPub{xpub.XPub}, nil},
{[]chainkd.XPub{xpub.XPub, xpub.XPub}, signers.ErrDupeXPub},
{[]chainkd.XPub{}, signers.ErrNoXPubs},
}

Accounts, err := acctMgr.ListAccounts("")
if err != nil {
t.Fatal("recovery from XPubs err:", err)
}
for _, c := range cases {
if err := recoveryMgr.AcctResurrect(c.xPubs); errors.Root(err) != c.err {
t.Fatal("recovery from XPubs err:", err)
}

for _, acct := range Accounts {
tmp, err := recAcctMgr.GetAccountByXPubsIndex(acct.XPubs, acct.KeyIndex)
if err != nil {
recoveryMgr.finished()
continue
}
if err := recoveryMgr.FilterRecoveryTxs(MockBlock(txs)); err != nil {
t.Fatal("recovery from XPubs err:", err)
}

if tmp == nil {
t.Fatal("accout recovery from xpubs err:", acct.KeyIndex)
Accounts, err := acctMgr.ListAccounts("")
if err != nil {
t.Fatal("recovery from XPubs err:", err)
}

if acctMgr.GetBip44ContractIndex(acct.ID, true) != recAcctMgr.GetBip44ContractIndex(tmp.ID, true) {
t.Fatal("bip44 internal address index recovery from xpubs err")
}
for _, acct := range Accounts {
tmp, err := recAcctMgr.GetAccountByXPubsIndex(acct.XPubs, acct.KeyIndex)
if err != nil {
t.Fatal("recovery from XPubs err:", err)
}

if tmp == nil {
t.Fatal("accout recovery from xpubs err:", acct.KeyIndex)
}

if acctMgr.GetBip44ContractIndex(acct.ID, true) != recAcctMgr.GetBip44ContractIndex(tmp.ID, true) {
t.Fatal("bip44 internal address index recovery from xpubs err")
}

if acctMgr.GetBip44ContractIndex(acct.ID, false) != recAcctMgr.GetBip44ContractIndex(tmp.ID, false) {
t.Fatal("bip44 external address index recovery from xpubs err")
if acctMgr.GetBip44ContractIndex(acct.ID, false) != recAcctMgr.GetBip44ContractIndex(tmp.ID, false) {
t.Fatal("bip44 external address index recovery from xpubs err")
}
}

recoveryMgr.finished()
}
}

Expand Down Expand Up @@ -276,32 +344,140 @@ func TestRecoveryByRescanAccount(t *testing.T) {
}

recoveryMgr := newRecoveryManager(recoveryDB, recAcctMgr)
if err := recoveryMgr.AddrResurrect(allAccounts); err != nil {
t.Fatal("recovery by rescan account err:", err)

acct := &account.Account{ID: "testA", Alias: "test1", Signer: &signers.Signer{XPubs: []chainkd.XPub{xpub.XPub}, KeyIndex: 1, DeriveRule: 3}}

cases := []struct {
accounts []*account.Account
err error
}{
{allAccounts, nil},
{[]*account.Account{acct}, signers.ErrDeriveRule},
}

recoveryMgr.FilterRecoveryTxs(MockBlock(txs))
Accounts, err := acctMgr.ListAccounts("")
for _, acct := range Accounts {
tmp, err := recAcctMgr.GetAccountByXPubsIndex(acct.XPubs, acct.KeyIndex)
for _, c := range cases {
if err := recoveryMgr.AddrResurrect(c.accounts); errors.Root(err) != c.err {
t.Fatal("recovery by rescan account err:", err)
}

if err != nil {
continue
}
recoveryMgr.FilterRecoveryTxs(MockBlock(txs))
accounts, err := acctMgr.ListAccounts("")
if err != nil {
t.Fatal("recovery from XPubs err:", err)
}

if tmp == nil {
t.Fatal("accout recovery from xpubs err:", acct.KeyIndex)
}
for _, acct := range accounts {
tmp, err := recAcctMgr.GetAccountByXPubsIndex(acct.XPubs, acct.KeyIndex)
if err != nil {
t.Fatal("recovery from XPubs err:", err)
}

if acctMgr.GetBip44ContractIndex(acct.ID, true) != recAcctMgr.GetBip44ContractIndex(tmp.ID, true) {
t.Fatal("bip44 internal address index recovery from xpubs err")
if tmp == nil {
t.Fatal("accout recovery from xpubs err:", acct.KeyIndex)
}

if acctMgr.GetBip44ContractIndex(acct.ID, true) != recAcctMgr.GetBip44ContractIndex(tmp.ID, true) {
t.Fatal("bip44 internal address index recovery from xpubs err")
}

if acctMgr.GetBip44ContractIndex(acct.ID, false) != recAcctMgr.GetBip44ContractIndex(tmp.ID, false) {
t.Fatal("bip44 external address index recovery from xpubs err")
}

if acctMgr.GetContractIndex(acct.ID) != recAcctMgr.GetContractIndex(tmp.ID) {
t.Fatal("bip32 address index recovery from xpubs err")
}
}
}

}

func TestReportFound(t *testing.T) {
dirPath, err := ioutil.TempDir(".", "")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dirPath)

testDB := dbm.NewDB("testdb", "leveldb", dirPath)
hsm, err := pseudohsm.New(dirPath)
if err != nil {
t.Fatal(err)
}

xpub1, _, err := hsm.XCreate("test_pub1", "password", "en")
if err != nil {
t.Fatal(err)
}

xpub2, _, err := hsm.XCreate("test_pub2", "password", "en")
if err != nil {
t.Fatal(err)
}

acctMgr := account.NewManager(testDB, nil)
recoveryMgr := newRecoveryManager(testDB, acctMgr)
acc1 := &account.Account{ID: "testA", Alias: "test1", Signer: &signers.Signer{XPubs: []chainkd.XPub{xpub1.XPub}, KeyIndex: 1, DeriveRule: signers.BIP0044}}
acc2 := &account.Account{ID: "testB", Alias: "test2", Signer: &signers.Signer{XPubs: []chainkd.XPub{xpub2.XPub}, KeyIndex: 1, DeriveRule: signers.BIP0032}}
acc3 := &account.Account{ID: "testC", Alias: "test3", Signer: &signers.Signer{XPubs: []chainkd.XPub{xpub2.XPub}, KeyIndex: 2, DeriveRule: signers.BIP0044}}

cp1 := &account.CtrlProgram{AccountID: acc1.ID, Address: "address1", KeyIndex: 10, Change: false}
cp2 := &account.CtrlProgram{AccountID: acc1.ID, Address: "address1", KeyIndex: 20, Change: true}
cp3 := &account.CtrlProgram{AccountID: acc2.ID, Address: "address1", KeyIndex: 30, Change: false}
cp4 := &account.CtrlProgram{AccountID: acc2.ID, Address: "address1", KeyIndex: 40, Change: true}
cp5 := &account.CtrlProgram{AccountID: acc3.ID, Address: "address1", KeyIndex: 50, Change: false}
cp6 := &account.CtrlProgram{AccountID: acc3.ID, Address: "address1", KeyIndex: 60, Change: true}

if err := acctMgr.SaveAccount(acc2); err != nil {
t.Fatal("ReportFound test err:", err)
}

if err := acctMgr.SaveAccount(acc3); err != nil {
t.Fatal("ReportFound test err:", err)
}

recoveryMgr.state.XPubsStatus = newBranchRecoveryState(acctRecoveryWindow)
recoveryMgr.state.XPubs = []chainkd.XPub{xpub1.XPub}
recoveryMgr.state.stateForScope(acc1)
recoveryMgr.state.stateForScope(acc2)
recoveryMgr.state.stateForScope(acc3)

if acctMgr.GetBip44ContractIndex(acct.ID, false) != recAcctMgr.GetBip44ContractIndex(tmp.ID, false) {
t.Fatal("bip44 external address index recovery from xpubs err")
cases := []struct {
acct *account.Account
cp *account.CtrlProgram
err error
status *addressRecoveryState
}{
{acc1, cp1, nil,
&addressRecoveryState{InternalBranch: &branchRecoveryState{addrRecoveryWindow, 1, 1}, ExternalBranch: &branchRecoveryState{addrRecoveryWindow, 139, 11}, Account: acc1}},
{acc2, cp3, nil,
&addressRecoveryState{InternalBranch: &branchRecoveryState{addrRecoveryWindow, 1, 1}, ExternalBranch: &branchRecoveryState{addrRecoveryWindow, 159, 31}, Account: acc2}},
{acc1, cp2, nil,
&addressRecoveryState{InternalBranch: &branchRecoveryState{addrRecoveryWindow, 149, 21}, ExternalBranch: &branchRecoveryState{addrRecoveryWindow, 139, 11}, Account: acc1}},
{acc2, cp4, nil,
&addressRecoveryState{InternalBranch: &branchRecoveryState{addrRecoveryWindow, 169, 41}, ExternalBranch: &branchRecoveryState{addrRecoveryWindow, 159, 31}, Account: acc2}},
{acc3, cp5, nil,
&addressRecoveryState{InternalBranch: &branchRecoveryState{addrRecoveryWindow, 1, 1}, ExternalBranch: &branchRecoveryState{addrRecoveryWindow, 179, 51}, Account: acc3}},
{acc3, cp6, nil,
&addressRecoveryState{InternalBranch: &branchRecoveryState{addrRecoveryWindow, 189, 61}, ExternalBranch: &branchRecoveryState{addrRecoveryWindow, 179, 51}, Account: acc3}},
}

for _, c := range cases {
if err := recoveryMgr.reportFound(c.acct, c.cp); err != c.err {
t.Fatal("ReportFound test err:", err, c.acct.ID)
}

if acctMgr.GetContractIndex(acct.ID) != recAcctMgr.GetContractIndex(tmp.ID) {
t.Fatal("bip32 address index recovery from xpubs err")
status, ok := recoveryMgr.state.AccountsStatus[c.acct.ID]
if !ok {
t.Fatal("ReportFound test err: can not find status")
}
if !reflect.DeepEqual(status, c.status) {
t.Log(c.status.Account, c.status.InternalBranch, c.status.ExternalBranch)
t.Log(status.Account, status.InternalBranch, status.ExternalBranch)
t.Fatal("ReportFound test err: recovery status error")
}
}
}
Expand Down Expand Up @@ -334,25 +510,49 @@ func TestLoadStatusInfo(t *testing.T) {
recoveryMgr.state.XPubsStatus = newBranchRecoveryState(acctRecoveryWindow)

recoveryMgr.state.StartTime = time.Now()
if err := recoveryMgr.LoadStatusInfo(); err != nil {
t.Fatal("TestLoadStatusInfo err:", err)
}

recoveryMgr.commitStatusInfo()

recoveryMgrRestore := newRecoveryManager(testDB, acctMgr)
recoveryMgrRestore.LoadStatusInfo()
if err := recoveryMgrRestore.LoadStatusInfo(); err != nil {
t.Fatal("TestLoadStatusInfo err:", err)
}

if !reflect.DeepEqual(recoveryMgrRestore.state.XPubsStatus, recoveryMgr.state.XPubsStatus) {
t.Fatalf("testLoadStatusInfo XPubsStatus reload err")
t.Fatalf("TestLoadStatusInfo XPubsStatus reload err")
}

if !reflect.DeepEqual(recoveryMgrRestore.state.XPubs, recoveryMgr.state.XPubs) {
t.Fatalf("testLoadStatusInfo XPubs reload err")
t.Fatalf("TestLoadStatusInfo XPubs reload err")
}

if !reflect.DeepEqual(recoveryMgrRestore.state.AccountsStatus, recoveryMgr.state.AccountsStatus) {
t.Fatalf("testLoadStatusInfo AccountsStatus reload err")
t.Fatalf("TestLoadStatusInfo AccountsStatus reload err")
}

if !recoveryMgrRestore.state.StartTime.Equal(recoveryMgr.state.StartTime) {
t.Fatalf("testLoadStatusInfo StartTime reload err")
t.Fatalf("TestLoadStatusInfo StartTime reload err")
}

acct := &account.Account{ID: "testA", Alias: "test1", Signer: &signers.Signer{XPubs: []chainkd.XPub{xpub.XPub}, KeyIndex: 1, DeriveRule: 3}}
recoveryMgr.state.AccountsStatus[acct.ID] = newAddressRecoveryState(addrRecoveryWindow, acct)
if err := recoveryMgr.commitStatusInfo(); err != nil {
t.Fatal("TestLoadStatusInfo err:", err)
}
if err := recoveryMgr.LoadStatusInfo(); err == nil {
t.Fatal("TestLoadStatusInfo err")
}

recoveryMgr.state = nil
if err := recoveryMgr.commitStatusInfo(); err != nil {
t.Fatal("TestLoadStatusInfo err:", err)
}

if err := recoveryMgr.LoadStatusInfo(); err == nil {
t.Fatal("TestLoadStatusInfo err")
}
}

Expand Down

0 comments on commit 5d3f6c2

Please sign in to comment.