github.com/RobustRoundRobin/quorum@v20.10.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 }) 87 response.Write(data) 88 } 89 } 90 91 func MockReceiveAPIHandlerFunc(response http.ResponseWriter, request *http.Request) { 92 path := string([]byte(request.RequestURI)[:strings.LastIndex(request.RequestURI, "?")]) 93 actualRequest, err := url.PathUnescape(strings.TrimPrefix(path, "/transaction/")) 94 if err != nil { 95 go func(o *capturedRequest) { sendRequestCaptor <- o }(&capturedRequest{err: err}) 96 } else { 97 go func(o *capturedRequest) { 98 receiveRequestCaptor <- o 99 }(&capturedRequest{request: actualRequest, header: request.Header}) 100 if actualRequest == arbitraryNotFoundHash.ToBase64() { 101 response.WriteHeader(http.StatusNotFound) 102 } else { 103 var data []byte 104 if actualRequest == arbitraryHashNoPrivateMetadata.ToBase64() { 105 data, _ = json.Marshal(&receiveResponse{ 106 Payload: arbitraryPrivatePayload, 107 }) 108 } else { 109 data, _ = json.Marshal(&receiveResponse{ 110 Payload: arbitraryPrivatePayload, 111 ExecHash: arbitraryExtra.ACMerkleRoot.ToBase64(), 112 AffectedContractTransactions: arbitraryExtra.ACHashes.ToBase64s(), 113 PrivacyFlag: arbitraryPrivacyFlag, 114 }) 115 } 116 response.Write(data) 117 } 118 } 119 } 120 121 func MockSendSignedTxAPIHandlerFunc(response http.ResponseWriter, request *http.Request) { 122 actualRequest := new(sendSignedTxRequest) 123 if err := json.NewDecoder(request.Body).Decode(actualRequest); err != nil { 124 go func(o *capturedRequest) { sendSignedTxRequestCaptor <- o }(&capturedRequest{err: err}) 125 } else { 126 go func(o *capturedRequest) { sendSignedTxRequestCaptor <- o }(&capturedRequest{request: actualRequest, header: request.Header}) 127 data, _ := json.Marshal(&sendSignedTxResponse{ 128 Key: arbitraryHash.ToBase64(), 129 }) 130 response.Write(data) 131 } 132 } 133 134 func MockSendSignedTxOctetStreamAPIHandlerFunc(response http.ResponseWriter, request *http.Request) { 135 actualRequest := new(sendSignedTxRequest) 136 reqHash, err := ioutil.ReadAll(request.Body) 137 if err != nil { 138 go func(o *capturedRequest) { sendSignedTxOctetStreamRequestCaptor <- o }(&capturedRequest{err: err}) 139 return 140 } 141 actualRequest.Hash = reqHash 142 actualRequest.To = strings.Split(request.Header["C11n-To"][0], ",") 143 144 go func(o *capturedRequest) { sendSignedTxOctetStreamRequestCaptor <- o }(&capturedRequest{request: actualRequest, header: request.Header}) 145 response.Write([]byte(common.BytesToEncryptedPayloadHash(reqHash).ToBase64())) 146 } 147 148 func teardown() { 149 testServer.Close() 150 } 151 152 func verifyRequestHeader(h http.Header, t *testing.T) { 153 if h.Get("Content-type") != "application/json" { 154 t.Errorf("expected Content-type header is application/json") 155 } 156 157 if h.Get("Accept") != "application/json" { 158 t.Errorf("expected Accept header is application/json") 159 } 160 } 161 162 func TestSend_whenTypical(t *testing.T) { 163 assert := testifyassert.New(t) 164 165 actualHash, err := testObject.Send(arbitraryPrivatePayload, arbitraryFrom, arbitraryTo, arbitraryExtra) 166 if err != nil { 167 t.Fatalf("%s", err) 168 } 169 capturedRequest := <-sendRequestCaptor 170 171 if capturedRequest.err != nil { 172 t.Fatalf("%s", capturedRequest.err) 173 } 174 175 verifyRequestHeader(capturedRequest.header, t) 176 177 actualRequest := capturedRequest.request.(*sendRequest) 178 179 assert.Equal(arbitraryPrivatePayload, actualRequest.Payload, "request.payload") 180 assert.Equal(arbitraryFrom, actualRequest.From, "request.from") 181 assert.Equal(arbitraryTo, actualRequest.To, "request.to") 182 assert.Equal(arbitraryPrivacyFlag, actualRequest.PrivacyFlag, "request.privacyFlag") 183 assert.Equal(arbitraryExtra.ACHashes.ToBase64s(), actualRequest.AffectedContractTransactions, "request.affectedContractTransactions") 184 assert.Equal(arbitraryExtra.ACMerkleRoot.ToBase64(), actualRequest.ExecHash, "request.execHash") 185 assert.Equal(arbitraryHash, actualHash, "returned hash") 186 } 187 188 func TestSend_whenTesseraVersionDoesNotSupportPrivacyEnhancements(t *testing.T) { 189 assert := testifyassert.New(t) 190 191 testObjectNoPE := New(&engine.Client{ 192 HttpClient: &http.Client{}, 193 BaseURL: testServer.URL, 194 }, []byte("0.10-SNAPSHOT")) 195 196 assert.False(testObjectNoPE.HasFeature(engine.PrivacyEnhancements), "the supplied version does not support privacy enhancements") 197 198 // trying to send a party protection transaction 199 _, err := testObjectNoPE.Send(arbitraryPrivatePayload, arbitraryFrom, arbitraryTo, arbitraryExtra) 200 if err != engine.ErrPrivateTxManagerDoesNotSupportPrivacyEnhancements { 201 t.Fatal("Expecting send to raise ErrPrivateTxManagerDoesNotSupportPrivacyEnhancements") 202 } 203 } 204 205 func TestSendRaw_whenTesseraVersionDoesNotSupportPrivacyEnhancements(t *testing.T) { 206 assert := testifyassert.New(t) 207 208 mux := http.NewServeMux() 209 mux.HandleFunc("/send", MockSendAPIHandlerFunc) 210 mux.HandleFunc("/transaction/", MockReceiveAPIHandlerFunc) 211 mux.HandleFunc("/sendsignedtx", MockSendSignedTxOctetStreamAPIHandlerFunc) 212 213 testServerNoPE := httptest.NewServer(mux) 214 defer testServerNoPE.Close() 215 216 testObjectNoPE := New(&engine.Client{ 217 HttpClient: &http.Client{}, 218 BaseURL: testServerNoPE.URL, 219 }, []byte("0.10-SNAPSHOT")) 220 221 assert.False(testObjectNoPE.HasFeature(engine.PrivacyEnhancements), "the supplied version does not support privacy enhancements") 222 223 // trying to send a party protection transaction 224 _, err := testObjectNoPE.SendSignedTx(arbitraryHash, arbitraryTo, arbitraryExtra) 225 if err != engine.ErrPrivateTxManagerDoesNotSupportPrivacyEnhancements { 226 t.Fatal("Expecting send to raise ErrPrivateTxManagerDoesNotSupportPrivacyEnhancements") 227 } 228 229 // send a standard private transaction and check that the old version of the /sendsignedtx is used (using octetstream content type) 230 231 // caching incomplete item 232 _, _, err = testObjectNoPE.ReceiveRaw(arbitraryHashNoPrivateMetadata) 233 if err != nil { 234 t.Fatalf("%s", err) 235 } 236 <-receiveRequestCaptor 237 238 // caching complete item 239 _, err = testObjectNoPE.SendSignedTx(arbitraryHashNoPrivateMetadata, arbitraryTo, &engine.ExtraMetadata{ 240 PrivacyFlag: engine.PrivacyFlagStandardPrivate}) 241 if err != nil { 242 t.Fatalf("%s", err) 243 } 244 req := <-sendSignedTxOctetStreamRequestCaptor 245 assert.Equal("application/octet-stream", req.header["Content-Type"][0]) 246 247 _, actualExtra, err := testObjectNoPE.Receive(arbitraryHashNoPrivateMetadata) 248 if err != nil { 249 t.Fatalf("%s", err) 250 } 251 assert.Equal(engine.PrivacyFlagStandardPrivate, actualExtra.PrivacyFlag, "cached privacy flag") 252 253 } 254 255 func TestReceive_whenTypical(t *testing.T) { 256 assert := testifyassert.New(t) 257 258 _, actualExtra, err := testObject.Receive(arbitraryHash1) 259 if err != nil { 260 t.Fatalf("%s", err) 261 } 262 capturedRequest := <-receiveRequestCaptor 263 264 if capturedRequest.err != nil { 265 t.Fatalf("%s", capturedRequest.err) 266 } 267 268 verifyRequestHeader(capturedRequest.header, t) 269 270 actualRequest := capturedRequest.request.(string) 271 272 assert.Equal(arbitraryHash1.ToBase64(), actualRequest, "requested hash") 273 assert.Equal(arbitraryExtra.ACHashes, actualExtra.ACHashes, "returned affected contract transaction hashes") 274 assert.Equal(arbitraryExtra.ACMerkleRoot, actualExtra.ACMerkleRoot, "returned merkle root") 275 assert.Equal(arbitraryExtra.PrivacyFlag, actualExtra.PrivacyFlag, "returned privacy flag") 276 } 277 278 func TestReceive_whenPayloadNotFound(t *testing.T) { 279 assert := testifyassert.New(t) 280 281 data, _, err := testObject.Receive(arbitraryNotFoundHash) 282 if err != nil { 283 t.Fatalf("%s", err) 284 } 285 capturedRequest := <-receiveRequestCaptor 286 287 if capturedRequest.err != nil { 288 t.Fatalf("%s", capturedRequest.err) 289 } 290 291 verifyRequestHeader(capturedRequest.header, t) 292 293 actualRequest := capturedRequest.request.(string) 294 295 assert.Equal(arbitraryNotFoundHash.ToBase64(), actualRequest, "requested hash") 296 assert.Nil(data, "returned payload when not found") 297 } 298 299 func TestReceive_whenEncryptedPayloadHashIsEmpty(t *testing.T) { 300 assert := testifyassert.New(t) 301 302 data, _, err := testObject.Receive(emptyHash) 303 if err != nil { 304 t.Fatalf("%s", err) 305 } 306 assert.Empty(receiveRequestCaptor, "no request is actually sent") 307 assert.Nil(data, "returned payload when not found") 308 } 309 310 func TestReceive_whenHavingPayloadButNoPrivateExtraMetadata(t *testing.T) { 311 assert := testifyassert.New(t) 312 313 _, actualExtra, err := testObject.Receive(arbitraryHashNoPrivateMetadata) 314 if err != nil { 315 t.Fatalf("%s", err) 316 } 317 capturedRequest := <-receiveRequestCaptor 318 319 if capturedRequest.err != nil { 320 t.Fatalf("%s", capturedRequest.err) 321 } 322 323 verifyRequestHeader(capturedRequest.header, t) 324 325 actualRequest := capturedRequest.request.(string) 326 327 assert.Equal(arbitraryHashNoPrivateMetadata.ToBase64(), actualRequest, "requested hash") 328 assert.Empty(actualExtra.ACHashes, "returned affected contract transaction hashes") 329 assert.True(common.EmptyHash(actualExtra.ACMerkleRoot), "returned merkle root") 330 } 331 332 func TestSendSignedTx_whenTypical(t *testing.T) { 333 assert := testifyassert.New(t) 334 335 _, err := testObject.SendSignedTx(arbitraryHash, arbitraryTo, arbitraryExtra) 336 if err != nil { 337 t.Fatalf("%s", err) 338 } 339 capturedRequest := <-sendSignedTxRequestCaptor 340 341 if capturedRequest.err != nil { 342 t.Fatalf("%s", capturedRequest.err) 343 } 344 345 verifyRequestHeader(capturedRequest.header, t) 346 347 actualRequest := capturedRequest.request.(*sendSignedTxRequest) 348 349 assert.Equal(arbitraryTo, actualRequest.To, "request.to") 350 assert.Equal(arbitraryExtra.ACHashes.ToBase64s(), actualRequest.AffectedContractTransactions, "request.affectedContractTransactions") 351 assert.Equal(arbitraryExtra.ACMerkleRoot.ToBase64(), actualRequest.ExecHash, "request.execHash") 352 } 353 354 func TestReceive_whenCachingRawPayload(t *testing.T) { 355 assert := testifyassert.New(t) 356 357 // caching incomplete item 358 _, _, err := testObject.ReceiveRaw(arbitraryHashNoPrivateMetadata) 359 if err != nil { 360 t.Fatalf("%s", err) 361 } 362 <-receiveRequestCaptor 363 364 // caching complete item 365 _, err = testObject.SendSignedTx(arbitraryHashNoPrivateMetadata, arbitraryTo, arbitraryExtra) 366 if err != nil { 367 t.Fatalf("%s", err) 368 } 369 <-sendSignedTxRequestCaptor 370 371 _, actualExtra, err := testObject.Receive(arbitraryHashNoPrivateMetadata) 372 if err != nil { 373 t.Fatalf("%s", err) 374 } 375 376 assert.Equal(arbitraryExtra.ACHashes, actualExtra.ACHashes, "cached affected contract transaction hashes") 377 assert.Equal(arbitraryExtra.ACMerkleRoot, actualExtra.ACMerkleRoot, "cached merkle root") 378 assert.Equal(arbitraryExtra.PrivacyFlag, actualExtra.PrivacyFlag, "cached privacy flag") 379 }