1package engine
2
3import (
4	"testing"
5
6	"github.com/keybase/client/go/libkb"
7	keybase1 "github.com/keybase/client/go/protocol/keybase1"
8	"github.com/stretchr/testify/require"
9)
10
11func TestMerkleClientHistorical(t *testing.T) {
12	tc := SetupEngineTest(t, "track")
13	defer tc.Cleanup()
14	fu := CreateAndSignupFakeUser(tc, "track")
15	m := NewMetaContextForTest(tc)
16
17	q := libkb.NewHTTPArgs()
18	q.Add("uid", libkb.UIDArg(fu.UID()))
19	mc := tc.G.MerkleClient
20	leaf, err := mc.LookupUser(m, q, nil, libkb.MerkleOpts{})
21
22	require.NoError(t, err)
23	root := mc.LastRoot(m)
24	require.NotNil(t, leaf)
25	require.NotNil(t, root)
26
27	var sigVersion libkb.SigVersion
28	for i := 0; i < 3; i++ {
29		// Cover both v1 and v2 case
30		if i%2 == 0 {
31			sigVersion = libkb.KeybaseSignatureV2
32		} else {
33			sigVersion = libkb.KeybaseSignatureV1
34		}
35		trackAlice(tc, fu, sigVersion)
36		untrackAlice(tc, fu, sigVersion)
37	}
38	leaf2, err := mc.LookupLeafAtHashMeta(m, fu.UID().AsUserOrTeam(), root.HashMeta())
39	require.NoError(t, err)
40	require.NotNil(t, leaf2)
41	require.True(t, leaf.Public().Eq(*leaf2.Public))
42
43	arg := keybase1.VerifyMerkleRootAndKBFSArg{
44		Root: keybase1.MerkleRootV2{
45			Seqno:    *root.Seqno(),
46			HashMeta: root.HashMeta(),
47		},
48		ExpectedKBFSRoot: keybase1.KBFSRoot{
49			TreeID: keybase1.MerkleTreeID_KBFS_PRIVATETEAM,
50		},
51	}
52	err = libkb.VerifyMerkleRootAndKBFS(m, arg)
53	require.NoError(t, err)
54}
55
56func TestFindNextMerkleRootAfterRevoke(t *testing.T) {
57	tc := SetupEngineTest(t, "merk")
58	defer tc.Cleanup()
59	fu := CreateAndSignupFakeUserPaper(tc, "merk")
60	for i := 0; i < 2; i++ {
61		v := libkb.KeybaseSignatureV2
62		trackAlice(tc, fu, v)
63		untrackAlice(tc, fu, v)
64	}
65
66	assertNumDevicesAndKeys(tc, fu, 2, 4)
67
68	devices, _ := getActiveDevicesAndKeys(tc, fu)
69	var paperDevice *libkb.Device
70	for _, device := range devices {
71		if device.Type == keybase1.DeviceTypeV2_PAPER {
72			paperDevice = device.Device
73		}
74	}
75
76	err := doRevokeDevice(tc, fu, paperDevice.ID, false, false)
77	require.NoError(t, err, "revoke worked")
78	assertNumDevicesAndKeys(tc, fu, 1, 2)
79
80	for i := 0; i < 2; i++ {
81		v := libkb.KeybaseSignatureV2
82		trackAlice(tc, fu, v)
83		untrackAlice(tc, fu, v)
84	}
85
86	m := NewMetaContextForTest(tc)
87
88	upak, _, err := tc.G.GetUPAKLoader().LoadV2(libkb.NewLoadUserArgWithMetaContext(m).WithUID(fu.UID()))
89	require.NoError(t, err, "upak loaded")
90	require.NotNil(t, upak, "upak wasn't nil")
91
92	var revokedKey *keybase1.PublicKeyV2NaCl
93	for _, key := range upak.Current.DeviceKeys {
94		if key.Base.Revocation != nil {
95			revokedKey = &key
96			break
97		}
98	}
99	require.NotNil(t, revokedKey, "we found a revoked key")
100	arg := keybase1.FindNextMerkleRootAfterRevokeArg{
101		Uid:  fu.UID(),
102		Kid:  revokedKey.Base.Kid,
103		Loc:  revokedKey.Base.Revocation.SigChainLocation,
104		Prev: revokedKey.Base.Revocation.PrevMerkleRootSigned,
105	}
106	res, err := libkb.FindNextMerkleRootAfterRevoke(m, arg)
107	require.NoError(t, err, "found the next root")
108	require.NotNil(t, res.Res, "we got a root back")
109	before := revokedKey.Base.Revocation.PrevMerkleRootSigned.Seqno
110	after := res.Res.Seqno
111	require.True(t, after > before, "we got a > seqno")
112	t.Logf("Found merkle root %d > %d", after, before)
113
114	// Make sure we can find this after fu is deleted
115	err = libkb.DeleteAccount(m, fu.NormalizedUsername(), &fu.Passphrase)
116	require.NoError(t, err)
117	err = m.LogoutKillSecrets()
118	require.NoError(t, err)
119
120	arg = keybase1.FindNextMerkleRootAfterRevokeArg{
121		Uid:  fu.UID(),
122		Kid:  revokedKey.Base.Kid,
123		Loc:  revokedKey.Base.Revocation.SigChainLocation,
124		Prev: revokedKey.Base.Revocation.PrevMerkleRootSigned,
125	}
126	res, err = libkb.FindNextMerkleRootAfterRevoke(m, arg)
127	require.NoError(t, err, "found the next root")
128	require.NotNil(t, res.Res, "we got a root back")
129	before = revokedKey.Base.Revocation.PrevMerkleRootSigned.Seqno
130	after = res.Res.Seqno
131	require.True(t, after > before, "we got a > seqno")
132	t.Logf("Found merkle root %d > %d", after, before)
133}
134