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  }