github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/libkb/merkle_client_test.go (about) 1 package libkb 2 3 import ( 4 "encoding/json" 5 "reflect" 6 "testing" 7 "time" 8 9 keybase1 "github.com/keybase/client/go/protocol/keybase1" 10 "github.com/stretchr/testify/require" 11 ) 12 13 func TestMerkleRootPayloadUnmarshalWithSkips(t *testing.T) { 14 raw := `{"body":{"kbfs":{"private":{"root":null,"version":null},"public":{"root":null,"version":null}},"key":{"fingerprint":"a05161510ee696601ba0ec7b3fd53b4871528cef","key_id":"3FD53B4871528CEF"},"legacy_uid_root":"75ac465f4cef9a32e593692c4c2db371401ed2cd7781b74a8210b49da116c514","prev":"a172068e89cfb73316e35ebee41adc3f42e882d042272553397e54208b7537e616cc16284ca714f442f459948af4660d43abc82a74b39a0b17c939739477856d","root":"04ae5a2268d8220a8a8a2392585bedeee6be1e81ad06d3b3355d0128725b52cf0f219e28f16781514e399b10dc0fb3a642a1b5ed66ba99b5e1f73df1be6e2d0b","seqno":228223,"skips":{"162687":"","195455":"","211839":"","220031":"","224127":"","226175":"","227199":"","227711":"fb99c7ba0844733318de3aaea7e19144c4ebc20365b5b90e8c443103c6975bd7","227967":"00b799c5df435ad5d746d52431f45f9522f137194d0ff8def84370b1ae5b5848","228095":"4ffd2cfdb108bdffaf61dd9e9c74a2ade6509509b96b852c2372f7fd25ed9188","228159":"cc57e780c9314377766855f324435e09e88c3d6f48c0ccdefb4da24915f50503","228191":"7032b5a573c3bece570fe5f3cfaa01a42ba673163898a4534c8a89dc0fb0954b","228207":"30ca14d7cdbfc444a141e82e2f02223d7e3226ab4626cfa00bc57fb5adf62ff7","228215":"e598fb8705203a24b6b1c722ddf61c9ca7055fe0d9c9f887186fec7148a2852d","228219":"bf7b127bf77224285492241654c3d1aea63a441fed64ac5d2a2e96ce89e3fa95","228221":"339edfa9f4fc2c6a5236bf390ef9906043684c579ccc36ef7b8ef88e330090cc","228222":"923f78febf3cc1134c382eb909d7bfc89968b40c94ca3f6a8402a0beef4199a1","97151":""},"txid":"e984c08f00430dab7200db56a84e8515","type":"merkle_root","version":1},"ctime":1484154393,"tag":"signature"}` 15 var r MerkleRootPayloadUnpacked 16 err := json.Unmarshal([]byte(raw), &r) 17 if err != nil { 18 t.Fatal(err) 19 } 20 var h NodeHash 21 h, err = NodeHashFromHex(`fb99c7ba0844733318de3aaea7e19144c4ebc20365b5b90e8c443103c6975bd7`) 22 if err != nil { 23 t.Fatal(err) 24 } 25 if !hashEq(h, r.Body.Skips[227711]) { 26 t.Fatal("should have had hash equality") 27 } 28 } 29 30 func TestMerkleRootPayloadUnmarshalWithoutSkips(t *testing.T) { 31 raw := `{"body":{"kbfs":{"private":{"root":"iKNlcGvEICJOVuOROjr8mEPkhETSMBpVZBJ41nBYBuodK/OrXGFaoWjEQINGJ9t9R8Eu4kLPLihrqqB21NDlieEMizSPcogzKeR3Q4Hsmt/uid87xpmvrZc4LhAQOX62sCEf3KTaSWjZG0Gjbm9uxBgfGYN0/evl0mbBib/jafJ/5yJIcDizzhiicHLEQMW85WnignmXsa5mLomnmduzUSksYOxUZU1bvJwn9Isj5Tyw2AL4t4t3nzgF1VEricihIF5N7+Pih/HlO0HAFE6ic27NHi2hdAKidHPOWHespKF2AQ==","version":1},"public":{"root":"hqFoxEBK5PjCumUTQuUrwDPI08l8x+QgiEqq5AbRVQGimEjDozDf6ax5mKh/A3qGv5Sjgxqkni36/rKxE6JBODpXJwJjonByxEBpdeld3+IbKVY7ACqtETV9cXP1UPO+Sxj+zJ2PdmmuelBZIYcW3FgcGiPJm15d/rpnSq2ob4m7u8B1wgWeLpcbonNuzR42oXQBonRzzlh3rJehdgE=","version":1}},"key":{"fingerprint":"03e146cdaf8136680ad566912a32340cec8c9492","key_id":"2A32340CEC8C9492"},"legacy_uid_root":"0c58a74abcb1db656146ebf667b5ea5cc55e208fbb534cd1b1e9454890358e5e","prev":"f82f0d1c236703205690110203e34cd9fc5dfb7a6bef386e81a1c9301b101deea176fae530ca654424cdd72565f1dc196af1eaed203b7dd0a100d672080b1961","root":"976a48126ced7ba136ef1a33e337c9ad22ca233eb19d46a5a1de482653b0ac25e35d3e55f1cb1fc5a29e62df5612581909afe8a26dc44710da5094445f009af0","seqno":796746,"txid":"db7ad0824c5753c28bc849d60e711815","type":"merkle_root","version":1},"ctime":1484239402,"tag":"signature"}` 32 var r MerkleRootPayloadUnpacked 33 err := json.Unmarshal([]byte(raw), &r) 34 if err != nil { 35 t.Fatal(err) 36 } 37 if r.Body.Skips != nil { 38 t.Fatal("expected an empty skip table") 39 } 40 } 41 42 func TestMerkleSkipVectors(t *testing.T) { 43 tc := SetupTest(t, "TestMerkleSkipVectors", 1) 44 defer tc.Cleanup() 45 for i, v := range merkleSkipTestVectors { 46 ss, err := readSkipSequenceFromStringList(v.data) 47 if err != nil { 48 t.Fatal(err) 49 } 50 err = ss.verify(NewMetaContextForTest(tc), skipTestVectorsThisRoot, skipTestVectorsLastRoot) 51 52 tc.G.Log.Info("Iteration %d: test %s: %v", i, v.name, err) 53 54 if v.e == merkleErrorNone && err != nil { 55 t.Fatalf("Expected no error in test %s, but got %s", v.name, err) 56 } 57 58 if v.e == merkleErrorNone { 59 continue 60 } 61 me, ok := err.(MerkleClientError) 62 if !ok { 63 t.Fatalf("Got an unexpected error type in test %s: %T (%v)", v.name, err, err) 64 } 65 if me.t != v.e { 66 t.Fatalf("Got wrong error type in test %s: %v != %v", v.name, me.t, v.e) 67 } 68 } 69 } 70 71 func TestComputeSetBitsBigEndian(t *testing.T) { 72 tests := []struct { 73 x uint 74 expected []uint 75 }{ 76 {0, nil}, 77 {1, []uint{1}}, 78 {10, []uint{2, 8}}, 79 {500, []uint{4, 16, 32, 64, 128, 256}}, 80 {1023, []uint{1, 2, 4, 8, 16, 32, 64, 128, 256, 512}}, 81 {1024, []uint{1024}}, 82 {1025, []uint{1, 1024}}, 83 {20000, []uint{32, 512, 1024, 2048, 16384}}, 84 } 85 for _, test := range tests { 86 got := computeSetBitsBigEndian(test.x) 87 if !reflect.DeepEqual(got, test.expected) { 88 t.Fatalf("Failed on input %d, expected %v, got %v.", test.x, test.expected, got) 89 } 90 } 91 } 92 93 func TestComputeLogPatternMerkleSkips(t *testing.T) { 94 tests := []struct { 95 start int 96 end int 97 expected []uint 98 }{ 99 {100, 2033, []uint{1009, 497, 241, 113, 105, 101}}, 100 {100, 102, nil}, 101 {100, 103, []uint{101}}, 102 } 103 for _, test := range tests { 104 got, err := computeLogPatternMerkleSkips(keybase1.Seqno(test.start), keybase1.Seqno(test.end)) 105 require.NoError(t, err) 106 if !reflect.DeepEqual(got, test.expected) { 107 t.Fatalf("Failed on input (%d, %d), expected %v, got %v.", test.start, test.end, test.expected, got) 108 } 109 } 110 111 _, err := computeLogPatternMerkleSkips(keybase1.Seqno(1000), keybase1.Seqno(999)) 112 require.Error(t, err) 113 require.Contains(t, err.Error(), "startSeqno > endSeqno") 114 } 115 116 func TestComputeExpectedRootSkips(t *testing.T) { 117 tests := []struct { 118 root int 119 expected []uint 120 }{ 121 {0, nil}, 122 {1, nil}, 123 {100, []uint{99, 98, 96, 92, 84, 68, 36}}, 124 {255, []uint{254, 253, 251, 247, 239, 223, 191, 127}}, 125 {256, []uint{255, 254, 252, 248, 240, 224, 192, 128}}, 126 {257, []uint{256, 255, 253, 249, 241, 225, 193, 129, 1}}, 127 {1000, []uint{999, 998, 996, 992, 984, 968, 936, 872, 744, 488}}, 128 {2048, []uint{2047, 2046, 2044, 2040, 2032, 2016, 1984, 1920, 1792, 1536, 1024}}, 129 } 130 for _, test := range tests { 131 got := computeExpectedRootSkips(uint(test.root)) 132 if !reflect.DeepEqual(got, test.expected) { 133 t.Fatalf("Failed on input (%d), expected %v, got %v.", test.root, test.expected, got) 134 } 135 } 136 } 137 138 func TestFetchRootFromServer(t *testing.T) { 139 tc := SetupTest(t, "MerkleClient", 0) 140 defer tc.Cleanup() 141 142 mc := tc.G.GetMerkleClient() 143 144 root, err := mc.FetchRootFromServer(NewMetaContextForTest(tc), 0) 145 require.NoError(t, err) 146 require.NotNil(t, root) 147 148 origAPI := tc.G.API 149 150 // Ensure these calls do not go to the server but still succeed (by switching the api interface) 151 tc.G.API = &ErrorMockAPI{} 152 153 rootNew, err := mc.FetchRootFromServer(NewMetaContextForTest(tc), 30*time.Second) 154 require.NoError(t, err) 155 require.Equal(t, *root, *rootNew) 156 157 rootNew, err = mc.FetchRootFromServerByMinSeqno(NewMetaContextForTest(tc), *root.Seqno()) 158 require.NoError(t, err) 159 require.Equal(t, *root, *rootNew) 160 161 rootNew, err = mc.FetchRootFromServerByMinSeqno(NewMetaContextForTest(tc), *root.Seqno()-3) 162 require.NoError(t, err) 163 require.Equal(t, *root, *rootNew) 164 165 // These calls should instead result in api calls to the server and fail 166 rootNew, err = mc.FetchRootFromServer(NewMetaContextForTest(tc), 0) 167 require.Error(t, err) 168 require.Equal(t, errMockAPI, err) 169 require.Nil(t, rootNew) 170 171 rootNew, err = mc.FetchRootFromServer(NewMetaContextForTest(tc), 1*time.Nanosecond) 172 require.Error(t, err) 173 require.Equal(t, errMockAPI, err) 174 require.Nil(t, rootNew) 175 176 rootNew, err = mc.FetchRootFromServerByMinSeqno(NewMetaContextForTest(tc), *root.Seqno()+3) 177 require.Error(t, err) 178 require.Equal(t, errMockAPI, err) 179 require.Nil(t, rootNew) 180 181 // if we put the api back, the call should succeed again 182 tc.G.API = origAPI 183 _, err = mc.FetchRootFromServerByMinSeqno(NewMetaContextForTest(tc), 0) 184 require.NoError(t, err) 185 }