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  }