github.com/Night-mk/quorum@v21.1.0+incompatible/private/engine/tessera/tessera_test.go (about) 1 package tessera 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io/ioutil" 7 "net/http" 8 "net/http/httptest" 9 "net/url" 10 "os" 11 "strings" 12 "testing" 13 14 "github.com/ethereum/go-ethereum/common" 15 "github.com/ethereum/go-ethereum/private/engine" 16 testifyassert "github.com/stretchr/testify/assert" 17 ) 18 19 var ( 20 emptyHash = common.EncryptedPayloadHash{} 21 arbitraryHash = common.BytesToEncryptedPayloadHash([]byte("arbitrary")) 22 arbitraryHash1 = common.BytesToEncryptedPayloadHash([]byte("arbitrary1")) 23 arbitraryNotFoundHash = common.BytesToEncryptedPayloadHash([]byte("not found")) 24 arbitraryHashNoPrivateMetadata = common.BytesToEncryptedPayloadHash([]byte("no private extra data")) 25 arbitraryPrivatePayload = []byte("arbitrary private payload") 26 arbitraryFrom = "arbitraryFrom" 27 arbitraryTo = []string{"arbitraryTo1", "arbitraryTo2"} 28 arbitraryPrivacyFlag = engine.PrivacyFlagPartyProtection 29 arbitraryExtra = &engine.ExtraMetadata{ 30 ACHashes: Must(common.Base64sToEncryptedPayloadHashes([]string{arbitraryHash.ToBase64()})).(common.EncryptedPayloadHashes), 31 ACMerkleRoot: common.StringToHash("arbitrary root hash"), 32 PrivacyFlag: arbitraryPrivacyFlag, 33 } 34 35 testServer *httptest.Server 36 testObject *tesseraPrivateTxManager 37 38 sendRequestCaptor = make(chan *capturedRequest) 39 receiveRequestCaptor = make(chan *capturedRequest) 40 sendSignedTxRequestCaptor = make(chan *capturedRequest) 41 sendSignedTxOctetStreamRequestCaptor = make(chan *capturedRequest) 42 ) 43 44 type capturedRequest struct { 45 err error 46 request interface{} 47 header http.Header 48 } 49 50 func TestMain(m *testing.M) { 51 setup() 52 retCode := m.Run() 53 teardown() 54 os.Exit(retCode) 55 } 56 57 func Must(o interface{}, err error) interface{} { 58 if err != nil { 59 panic(fmt.Sprintf("%s", err)) 60 } 61 return o 62 } 63 64 func setup() { 65 mux := http.NewServeMux() 66 mux.HandleFunc("/send", MockSendAPIHandlerFunc) 67 mux.HandleFunc("/transaction/", MockReceiveAPIHandlerFunc) 68 mux.HandleFunc("/sendsignedtx", MockSendSignedTxAPIHandlerFunc) 69 70 testServer = httptest.NewServer(mux) 71 72 testObject = New(&engine.Client{ 73 HttpClient: &http.Client{}, 74 BaseURL: testServer.URL, 75 }, []byte("2.0.0")) 76 } 77 78 func MockSendAPIHandlerFunc(response http.ResponseWriter, request *http.Request) { 79 actualRequest := new(sendRequest) 80 if err := json.NewDecoder(request.Body).Decode(actualRequest); err != nil { 81 go func(o *capturedRequest) { sendRequestCaptor <- o }(&capturedRequest{err: err}) 82 } else { 83 go func(o *capturedRequest) { sendRequestCaptor <- o }(&capturedRequest{request: actualRequest, header: request.Header}) 84 data, _ := json.Marshal(&sendResponse{ 85 Key: arbitraryHash.ToBase64(), 86 ManagedParties: []string{"ArbitraryPublicKey"}, 87 }) 88 response.Write(data) 89 } 90 } 91 92 func MockReceiveAPIHandlerFunc(response http.ResponseWriter, request *http.Request) { 93 path := string([]byte(request.RequestURI)[:strings.LastIndex(request.RequestURI, "?")]) 94 actualRequest, err := url.PathUnescape(strings.TrimPrefix(path, "/transaction/")) 95 if err != nil { 96 go func(o *capturedRequest) { sendRequestCaptor <- o }(&capturedRequest{err: err}) 97 } else { 98 go func(o *capturedRequest) { 99 receiveRequestCaptor <- o 100 }(&capturedRequest{request: actualRequest, header: request.Header}) 101 if actualRequest == arbitraryNotFoundHash.ToBase64() { 102 response.WriteHeader(http.StatusNotFound) 103 } else { 104 var data []byte 105 if actualRequest == arbitraryHashNoPrivateMetadata.ToBase64() { 106 data, _ = json.Marshal(&receiveResponse{ 107 Payload: arbitraryPrivatePayload, 108 ManagedParties: []string{"ArbitraryPublicKey"}, 109 }) 110 } else { 111 data, _ = json.Marshal(&receiveResponse{ 112 Payload: arbitraryPrivatePayload, 113 ExecHash: arbitraryExtra.ACMerkleRoot.ToBase64(), 114 AffectedContractTransactions: arbitraryExtra.ACHashes.ToBase64s(), 115 PrivacyFlag: arbitraryPrivacyFlag, 116 ManagedParties: []string{"ArbitraryPublicKey"}, 117 }) 118 } 119 response.Write(data) 120 } 121 } 122 } 123 124 func MockSendSignedTxAPIHandlerFunc(response http.ResponseWriter, request *http.Request) { 125 actualRequest := new(sendSignedTxRequest) 126 if err := json.NewDecoder(request.Body).Decode(actualRequest); err != nil { 127 go func(o *capturedRequest) { sendSignedTxRequestCaptor <- o }(&capturedRequest{err: err}) 128 } else { 129 go func(o *capturedRequest) { sendSignedTxRequestCaptor <- o }(&capturedRequest{request: actualRequest, header: request.Header}) 130 data, _ := json.Marshal(&sendSignedTxResponse{ 131 Key: arbitraryHash.ToBase64(), 132 }) 133 response.Write(data) 134 } 135 } 136 137 func MockSendSignedTxOctetStreamAPIHandlerFunc(response http.ResponseWriter, request *http.Request) { 138 actualRequest := new(sendSignedTxRequest) 139 reqHash, err := ioutil.ReadAll(request.Body) 140 if err != nil { 141 go func(o *capturedRequest) { sendSignedTxOctetStreamRequestCaptor <- o }(&capturedRequest{err: err}) 142 return 143 } 144 actualRequest.Hash = reqHash 145 actualRequest.To = strings.Split(request.Header["C11n-To"][0], ",") 146 147 go func(o *capturedRequest) { sendSignedTxOctetStreamRequestCaptor <- o }(&capturedRequest{request: actualRequest, header: request.Header}) 148 response.Write([]byte(common.BytesToEncryptedPayloadHash(reqHash).ToBase64())) 149 } 150 151 func teardown() { 152 testServer.Close() 153 } 154 155 func verifyRequestHeader(h http.Header, t *testing.T) { 156 if h.Get("Content-type") != "application/json" { 157 t.Errorf("expected Content-type header is application/json") 158 } 159 160 if h.Get("Accept") != "application/json" { 161 t.Errorf("expected Accept header is application/json") 162 } 163 } 164 165 func verifyRequestHeaderMultiTenancy(h http.Header, t *testing.T) { 166 if h.Get("Content-type") != "application/vnd.tessera-2.1+json" { 167 t.Errorf("expected Content-type header is application/vnd.tessera-2.1+json") 168 } 169 170 if h.Get("Accept") != "application/vnd.tessera-2.1+json" { 171 t.Errorf("expected Accept header is application/vnd.tessera-2.1+json") 172 } 173 } 174 175 func TestSend_whenTypical(t *testing.T) { 176 assert := testifyassert.New(t) 177 178 _, _, actualHash, err := testObject.Send(arbitraryPrivatePayload, arbitraryFrom, arbitraryTo, arbitraryExtra) 179 if err != nil { 180 t.Fatalf("%s", err) 181 } 182 capturedRequest := <-sendRequestCaptor 183 184 if capturedRequest.err != nil { 185 t.Fatalf("%s", capturedRequest.err) 186 } 187 188 verifyRequestHeader(capturedRequest.header, t) 189 190 actualRequest := capturedRequest.request.(*sendRequest) 191 192 assert.Equal(arbitraryPrivatePayload, actualRequest.Payload, "request.payload") 193 assert.Equal(arbitraryFrom, actualRequest.From, "request.from") 194 assert.Equal(arbitraryTo, actualRequest.To, "request.to") 195 assert.Equal(arbitraryPrivacyFlag, actualRequest.PrivacyFlag, "request.privacyFlag") 196 assert.Equal(arbitraryExtra.ACHashes.ToBase64s(), actualRequest.AffectedContractTransactions, "request.affectedContractTransactions") 197 assert.Equal(arbitraryExtra.ACMerkleRoot.ToBase64(), actualRequest.ExecHash, "request.execHash") 198 assert.Equal(arbitraryHash, actualHash, "returned hash") 199 } 200 201 func TestSend_whenTypical_MultiTenancy(t *testing.T) { 202 assert := testifyassert.New(t) 203 204 testObjectWithMT := New(&engine.Client{ 205 HttpClient: &http.Client{}, 206 BaseURL: testServer.URL, 207 }, []byte("2.1")) 208 209 _, _, actualHash, err := testObjectWithMT.Send(arbitraryPrivatePayload, arbitraryFrom, arbitraryTo, arbitraryExtra) 210 if err != nil { 211 t.Fatalf("%s", err) 212 } 213 capturedRequest := <-sendRequestCaptor 214 215 if capturedRequest.err != nil { 216 t.Fatalf("%s", capturedRequest.err) 217 } 218 219 verifyRequestHeaderMultiTenancy(capturedRequest.header, t) 220 221 actualRequest := capturedRequest.request.(*sendRequest) 222 223 assert.Equal(arbitraryPrivatePayload, actualRequest.Payload, "request.payload") 224 assert.Equal(arbitraryFrom, actualRequest.From, "request.from") 225 assert.Equal(arbitraryTo, actualRequest.To, "request.to") 226 assert.Equal(arbitraryPrivacyFlag, actualRequest.PrivacyFlag, "request.privacyFlag") 227 assert.Equal(arbitraryExtra.ACHashes.ToBase64s(), actualRequest.AffectedContractTransactions, "request.affectedContractTransactions") 228 assert.Equal(arbitraryExtra.ACMerkleRoot.ToBase64(), actualRequest.ExecHash, "request.execHash") 229 assert.Equal(arbitraryHash, actualHash, "returned hash") 230 } 231 232 func TestSend_whenTesseraVersionDoesNotSupportPrivacyEnhancements(t *testing.T) { 233 assert := testifyassert.New(t) 234 235 testObjectNoPE := New(&engine.Client{ 236 HttpClient: &http.Client{}, 237 BaseURL: testServer.URL, 238 }, []byte("0.10-SNAPSHOT")) 239 240 assert.False(testObjectNoPE.HasFeature(engine.PrivacyEnhancements), "the supplied version does not support privacy enhancements") 241 242 // trying to send a party protection transaction 243 _, _, _, err := testObjectNoPE.Send(arbitraryPrivatePayload, arbitraryFrom, arbitraryTo, arbitraryExtra) 244 if err != engine.ErrPrivateTxManagerDoesNotSupportPrivacyEnhancements { 245 t.Fatal("Expecting send to raise ErrPrivateTxManagerDoesNotSupportPrivacyEnhancements") 246 } 247 } 248 249 func TestSendRaw_whenTesseraVersionDoesNotSupportPrivacyEnhancements(t *testing.T) { 250 assert := testifyassert.New(t) 251 252 mux := http.NewServeMux() 253 mux.HandleFunc("/send", MockSendAPIHandlerFunc) 254 mux.HandleFunc("/transaction/", MockReceiveAPIHandlerFunc) 255 mux.HandleFunc("/sendsignedtx", MockSendSignedTxOctetStreamAPIHandlerFunc) 256 257 testServerNoPE := httptest.NewServer(mux) 258 defer testServerNoPE.Close() 259 260 testObjectNoPE := New(&engine.Client{ 261 HttpClient: &http.Client{}, 262 BaseURL: testServerNoPE.URL, 263 }, []byte("0.10-SNAPSHOT")) 264 265 assert.False(testObjectNoPE.HasFeature(engine.PrivacyEnhancements), "the supplied version does not support privacy enhancements") 266 267 // trying to send a party protection transaction 268 _, _, _, err := testObjectNoPE.SendSignedTx(arbitraryHash, arbitraryTo, arbitraryExtra) 269 if err != engine.ErrPrivateTxManagerDoesNotSupportPrivacyEnhancements { 270 t.Fatal("Expecting send to raise ErrPrivateTxManagerDoesNotSupportPrivacyEnhancements") 271 } 272 273 // send a standard private transaction and check that the old version of the /sendsignedtx is used (using octetstream content type) 274 275 // caching incomplete item 276 _, _, _, err = testObjectNoPE.ReceiveRaw(arbitraryHashNoPrivateMetadata) 277 if err != nil { 278 t.Fatalf("%s", err) 279 } 280 <-receiveRequestCaptor 281 282 // caching complete item 283 _, _, _, err = testObjectNoPE.SendSignedTx(arbitraryHashNoPrivateMetadata, arbitraryTo, &engine.ExtraMetadata{ 284 PrivacyFlag: engine.PrivacyFlagStandardPrivate}) 285 if err != nil { 286 t.Fatalf("%s", err) 287 } 288 req := <-sendSignedTxOctetStreamRequestCaptor 289 assert.Equal("application/octet-stream", req.header["Content-Type"][0]) 290 291 _, _, _, actualExtra, err := testObjectNoPE.Receive(arbitraryHashNoPrivateMetadata) 292 if err != nil { 293 t.Fatalf("%s", err) 294 } 295 assert.Equal(engine.PrivacyFlagStandardPrivate, actualExtra.PrivacyFlag, "cached privacy flag") 296 297 } 298 299 func TestReceive_whenTypical(t *testing.T) { 300 assert := testifyassert.New(t) 301 302 _, _, _, actualExtra, err := testObject.Receive(arbitraryHash1) 303 if err != nil { 304 t.Fatalf("%s", err) 305 } 306 capturedRequest := <-receiveRequestCaptor 307 308 if capturedRequest.err != nil { 309 t.Fatalf("%s", capturedRequest.err) 310 } 311 312 verifyRequestHeader(capturedRequest.header, t) 313 314 actualRequest := capturedRequest.request.(string) 315 316 assert.Equal(arbitraryHash1.ToBase64(), actualRequest, "requested hash") 317 assert.Equal(arbitraryExtra.ACHashes, actualExtra.ACHashes, "returned affected contract transaction hashes") 318 assert.Equal(arbitraryExtra.ACMerkleRoot, actualExtra.ACMerkleRoot, "returned merkle root") 319 assert.Equal(arbitraryExtra.PrivacyFlag, actualExtra.PrivacyFlag, "returned privacy flag") 320 } 321 322 func TestReceive_whenTypical_Multitenancy(t *testing.T) { 323 assert := testifyassert.New(t) 324 325 testObjectWithMT := New(&engine.Client{ 326 HttpClient: &http.Client{}, 327 BaseURL: testServer.URL, 328 }, []byte("2.1")) 329 330 _, _, _, actualExtra, err := testObjectWithMT.Receive(arbitraryHash1) 331 if err != nil { 332 t.Fatalf("%s", err) 333 } 334 capturedRequest := <-receiveRequestCaptor 335 336 if capturedRequest.err != nil { 337 t.Fatalf("%s", capturedRequest.err) 338 } 339 340 verifyRequestHeaderMultiTenancy(capturedRequest.header, t) 341 342 actualRequest := capturedRequest.request.(string) 343 344 assert.Equal(arbitraryHash1.ToBase64(), actualRequest, "requested hash") 345 assert.Equal(arbitraryExtra.ACHashes, actualExtra.ACHashes, "returned affected contract transaction hashes") 346 assert.Equal(arbitraryExtra.ACMerkleRoot, actualExtra.ACMerkleRoot, "returned merkle root") 347 assert.Equal(arbitraryExtra.PrivacyFlag, actualExtra.PrivacyFlag, "returned privacy flag") 348 } 349 350 func TestReceive_whenPayloadNotFound(t *testing.T) { 351 assert := testifyassert.New(t) 352 353 _, _, data, _, err := testObject.Receive(arbitraryNotFoundHash) 354 if err != nil { 355 t.Fatalf("%s", err) 356 } 357 capturedRequest := <-receiveRequestCaptor 358 359 if capturedRequest.err != nil { 360 t.Fatalf("%s", capturedRequest.err) 361 } 362 363 verifyRequestHeader(capturedRequest.header, t) 364 365 actualRequest := capturedRequest.request.(string) 366 367 assert.Equal(arbitraryNotFoundHash.ToBase64(), actualRequest, "requested hash") 368 assert.Nil(data, "returned payload when not found") 369 } 370 371 func TestReceive_whenEncryptedPayloadHashIsEmpty(t *testing.T) { 372 assert := testifyassert.New(t) 373 374 _, _, data, _, err := testObject.Receive(emptyHash) 375 if err != nil { 376 t.Fatalf("%s", err) 377 } 378 assert.Empty(receiveRequestCaptor, "no request is actually sent") 379 assert.Nil(data, "returned payload when not found") 380 } 381 382 func TestReceive_whenHavingPayloadButNoPrivateExtraMetadata(t *testing.T) { 383 assert := testifyassert.New(t) 384 385 _, _, _, actualExtra, err := testObject.Receive(arbitraryHashNoPrivateMetadata) 386 if err != nil { 387 t.Fatalf("%s", err) 388 } 389 capturedRequest := <-receiveRequestCaptor 390 391 if capturedRequest.err != nil { 392 t.Fatalf("%s", capturedRequest.err) 393 } 394 395 verifyRequestHeader(capturedRequest.header, t) 396 397 actualRequest := capturedRequest.request.(string) 398 399 assert.Equal(arbitraryHashNoPrivateMetadata.ToBase64(), actualRequest, "requested hash") 400 assert.Empty(actualExtra.ACHashes, "returned affected contract transaction hashes") 401 assert.True(common.EmptyHash(actualExtra.ACMerkleRoot), "returned merkle root") 402 } 403 404 func TestSendSignedTx_whenTypical(t *testing.T) { 405 assert := testifyassert.New(t) 406 407 _, _, _, err := testObject.SendSignedTx(arbitraryHash, arbitraryTo, arbitraryExtra) 408 if err != nil { 409 t.Fatalf("%s", err) 410 } 411 capturedRequest := <-sendSignedTxRequestCaptor 412 413 if capturedRequest.err != nil { 414 t.Fatalf("%s", capturedRequest.err) 415 } 416 417 verifyRequestHeader(capturedRequest.header, t) 418 419 actualRequest := capturedRequest.request.(*sendSignedTxRequest) 420 421 assert.Equal(arbitraryTo, actualRequest.To, "request.to") 422 assert.Equal(arbitraryExtra.ACHashes.ToBase64s(), actualRequest.AffectedContractTransactions, "request.affectedContractTransactions") 423 assert.Equal(arbitraryExtra.ACMerkleRoot.ToBase64(), actualRequest.ExecHash, "request.execHash") 424 } 425 426 func TestReceive_whenCachingRawPayload(t *testing.T) { 427 assert := testifyassert.New(t) 428 429 // caching incomplete item 430 _, _, _, err := testObject.ReceiveRaw(arbitraryHashNoPrivateMetadata) 431 if err != nil { 432 t.Fatalf("%s", err) 433 } 434 <-receiveRequestCaptor 435 436 // caching complete item 437 _, _, _, err = testObject.SendSignedTx(arbitraryHashNoPrivateMetadata, arbitraryTo, arbitraryExtra) 438 if err != nil { 439 t.Fatalf("%s", err) 440 } 441 <-sendSignedTxRequestCaptor 442 443 _, _, _, actualExtra, err := testObject.Receive(arbitraryHashNoPrivateMetadata) 444 if err != nil { 445 t.Fatalf("%s", err) 446 } 447 448 assert.Equal(arbitraryExtra.ACHashes, actualExtra.ACHashes, "cached affected contract transaction hashes") 449 assert.Equal(arbitraryExtra.ACMerkleRoot, actualExtra.ACMerkleRoot, "cached merkle root") 450 assert.Equal(arbitraryExtra.PrivacyFlag, actualExtra.PrivacyFlag, "cached privacy flag") 451 }