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  }