From abac88ea97cd072818860c1906d1bcdf75224b6f Mon Sep 17 00:00:00 2001 From: chris-j-h <39617426+chris-j-h@users.noreply.github.com> Date: Thu, 23 May 2019 23:37:52 +0100 Subject: [PATCH 1/3] Add logo favicon and other minor doc fixes/changes: (#723) - Fix incorrectly documented Tessera server config field name - Add Quorum logo favicon - Add 404.html from material theme to try fix 404 not displaying properly - FAQ ordering and phrasing changes - Fix formatting in Tessera TLS config docs --- docs/FAQ.md | 18 ++- .../Configuration/Configuration Overview.md | 6 +- docs/Privacy/Tessera/Configuration/TLS.md | 140 +++++++++--------- docs/images/logo-48x48.png | Bin 0 -> 1717 bytes docs/theme/404.html | 4 + mkdocs.yml | 1 + 6 files changed, 88 insertions(+), 81 deletions(-) create mode 100644 docs/images/logo-48x48.png create mode 100644 docs/theme/404.html diff --git a/docs/FAQ.md b/docs/FAQ.md index c3157a17f..863a72520 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -1,5 +1,7 @@ -??? question "I've ran into an issue with Quorum, where do I get support?" - There are two places Quorum engineering team monitors on an on-going basis: issues in this and related repositories and on Quorum Slack. Quorum Slack is the best place to query the community and get immediate help. Auto-inviter is available [here](https://clh7rniov2.execute-api.us-east-1.amazonaws.com/Express/). +??? question "I've run into an issue with Quorum, where do I get support?" + The [Quorum Slack channels](https://clh7rniov2.execute-api.us-east-1.amazonaws.com/Express/) are the best place to query the community and get immediate help. + + The Quorum engineering team monitors Slack as well as any issues raised on the Quorum GitHub repositories (e.g. [Quorum](https://github.com/jpmorganchase/quorum/), [Tessera](https://github.com/jpmorganchase/tessera), [Quorum-Examples](https://github.com/jpmorganchase/quorum-examples), etc.). ??? question "How does Quorum achieve Transaction Privacy?" Quorum achieves Transaction Privacy by: @@ -23,11 +25,8 @@ ??? question "Should I include originating node in private transaction?" No, you should not. In Quorum, including originating node's `privateFor` will result in an error. If you would like to create a private contract that is visible to the originating node only please use this format: `privateFor: []` per https://github.com/jpmorganchase/quorum/pull/165 -??? question "Is it possible to run a Quorum node without Transaction Manager?" - It is possible to run a node without a corresponding Transaction Manager, to do this instead of a matching Tessera/Constellation node's socket configuration should be set to `PRIVATE_CONFIG=ignore ...`. The node running such configuration is not going to broadcast matching private keys (please ensure that there is no transaction manager running for it) and will be unable to participate in any private transactions. - -??? info "Known Raft consensus node misconfiguration" - Please see https://github.com/jpmorganchase/quorum/issues/410 +??? question "Is it possible to run a Quorum node without a Transaction Manager?" + Starting a Quorum node with `PRIVATE_CONFIG=ignore` (instead of `PRIVATE_CONFIG=path/to/tm.ipc`) will start the node without a Transaction Manager. The node will not broadcast matching private keys (please ensure that there is no transaction manager running for it) and will be unable to participate in any private transactions. ??? question "Is there an official docker image for Quorum/Constellation/Tessera?" Yes! The [official docker containers](https://hub.docker.com/u/quorumengineering/): @@ -36,5 +35,8 @@ `quorumengineering/constellation:latest` `quorumengineering/tessera:latest` -??? question "Can I mix Quorum nodes with different consensus configuration?" +??? question "Can I create a network of Quorum nodes using different consensus mechanisms?" Unfortunately, that is not possible. Quorum nodes configured with raft will only be able to work correctly with other nodes running raft consensus. This applies to all other supported consensus algorithms. + +??? info "Known Raft consensus node misconfiguration" + Please see https://github.com/jpmorganchase/quorum/issues/410 diff --git a/docs/Privacy/Tessera/Configuration/Configuration Overview.md b/docs/Privacy/Tessera/Configuration/Configuration Overview.md index 12d60a0db..d61139755 100644 --- a/docs/Privacy/Tessera/Configuration/Configuration Overview.md +++ b/docs/Privacy/Tessera/Configuration/Configuration Overview.md @@ -59,7 +59,7 @@ HTTP: { "app": "", "enabled": , - "serverUri":"http://[host]:[port]/[path] + "serverAddress":"http://[host]:[port]/[path] "communicationType" : , // "REST" or "GRPC" } ``` @@ -68,7 +68,7 @@ HTTPS: { "app": "", "enabled": , - "serverUri":"https://[host]:[port]/[path] + "serverAddress":"https://[host]:[port]/[path] "communicationType" : , // "REST" or "GRPC" "sslConfig": { ...... @@ -80,7 +80,7 @@ Unix Socket: { "app": "", "enabled": , - "serverUri":"unix://[path], + "serverAddress":"unix://[path], "communicationType" : "REST" } ``` diff --git a/docs/Privacy/Tessera/Configuration/TLS.md b/docs/Privacy/Tessera/Configuration/TLS.md index cb92264eb..186ae7427 100644 --- a/docs/Privacy/Tessera/Configuration/TLS.md +++ b/docs/Privacy/Tessera/Configuration/TLS.md @@ -83,18 +83,18 @@ By setting `"generateKeyStoreIfNotExisted": "true"`, Tessera will check whether Below is a config sample for using the `.pem` file format: ```json "sslConfig" : { - "tls" : "STRICT", - "generateKeyStoreIfNotExisted" : "false", - "serverTlsKeyPath" : "server-key.pem", - "serverTlsCertificatePath" : "server-cert.pem", - "serverTrustCertificates" : ["server-trust.pem"] - "serverTrustMode" : "CA", - "clientTlsKeyPath" : "client-key.pem", - "clientTlsCertificatePath" : "client-cert.pem", - "clientTrustCertificates" : ["client-trust.pem"] - "clientTrustMode" : "TOFU", - "knownClientsFile" : "knownClients", - "knownServersFile" : "knownServers" + "tls" : "STRICT", + "generateKeyStoreIfNotExisted" : "false", + "serverTlsKeyPath" : "server-key.pem", + "serverTlsCertificatePath" : "server-cert.pem", + "serverTrustCertificates" : ["server-trust.pem"] + "serverTrustMode" : "CA", + "clientTlsKeyPath" : "client-key.pem", + "clientTlsCertificatePath" : "client-cert.pem", + "clientTrustCertificates" : ["client-trust.pem"] + "clientTrustMode" : "TOFU", + "knownClientsFile" : "knownClients", + "knownServersFile" : "knownServers" } ``` @@ -102,67 +102,67 @@ Below is a config sample for using the `.pem` file format: The Trust Mode for both client and server must also be specified. Multiple trust modes are supported: `TOFU`, `WHITELIST`, `CA`, `CA_OR_TOFU`, and `NONE`. * `TOFU` (Trust-on-first-use) - Only the first node that connects identifying as a certain host will be allowed to connect as the same host in the future. When connecting for the first time, the host and its certificate will be added to `knownClientsFile` (for server), or `knownServersFile` (for client). These files will be generated if not already existed, using the values specified in `knownClientsFile` and `knownServersFile`. + Only the first node that connects identifying as a certain host will be allowed to connect as the same host in the future. When connecting for the first time, the host and its certificate will be added to `knownClientsFile` (for server), or `knownServersFile` (for client). These files will be generated if not already existed, using the values specified in `knownClientsFile` and `knownServersFile`. - A config sample for `TOFU` trust mode is: + A config sample for `TOFU` trust mode is: - ```json - "sslConfig" : { - "tls" : "STRICT", - "generateKeyStoreIfNotExisted" : "true", - "serverKeyStore" : "server-keystore", - "serverKeyStorePassword" : "tessera", - "serverTrustMode" : "TOFU", - "clientKeyStore" : "client-keystore", - "clientKeyStorePassword" : "tessera", - "clientTrustMode" : "TOFU", - "knownClientsFile" : "knownClients", - "knownServersFile" : "knownServers" - } - ``` + ```json + "sslConfig" : { + "tls" : "STRICT", + "generateKeyStoreIfNotExisted" : "true", + "serverKeyStore" : "server-keystore", + "serverKeyStorePassword" : "tessera", + "serverTrustMode" : "TOFU", + "clientKeyStore" : "client-keystore", + "clientKeyStorePassword" : "tessera", + "clientTrustMode" : "TOFU", + "knownClientsFile" : "knownClients", + "knownServersFile" : "knownServers" + } + ``` * `WHITELIST` - Only nodes that have previously connected to this node and have been added to the `knownClients` file will be allowed to connect. Similarly, this node will only be allowed to make connections to nodes that have been added to the `knownServers` file. This trust mode will not add new entries to the `knownClients` or `knownServers` files. - - With this trust mode, the whitelist files (`knownClientsFile` and `knownServersFile`) must be provided. - - A config sample for `WHITELIST` trust mode is: - - ```json - "sslConfig" : { - "tls" : "STRICT", - "generateKeyStoreIfNotExisted" : "true", - "serverKeyStore" : "server-keystore", - "serverKeyStorePassword" : "tessera", - "serverTrustMode" : "WHITELIST", - "clientKeyStore" : "client-keystore", - "clientKeyStorePassword" : "tessera", - "clientTrustMode" : "WHITELIST", - "knownClientsFile" : "knownClients", - "knownServersFile" : "knownServers" - } - ``` + Only nodes that have previously connected to this node and have been added to the `knownClients` file will be allowed to connect. Similarly, this node will only be allowed to make connections to nodes that have been added to the `knownServers` file. This trust mode will not add new entries to the `knownClients` or `knownServers` files. + + With this trust mode, the whitelist files (`knownClientsFile` and `knownServersFile`) must be provided. + + A config sample for `WHITELIST` trust mode is: + + ```json + "sslConfig" : { + "tls" : "STRICT", + "generateKeyStoreIfNotExisted" : "true", + "serverKeyStore" : "server-keystore", + "serverKeyStorePassword" : "tessera", + "serverTrustMode" : "WHITELIST", + "clientKeyStore" : "client-keystore", + "clientKeyStorePassword" : "tessera", + "clientTrustMode" : "WHITELIST", + "knownClientsFile" : "knownClients", + "knownServersFile" : "knownServers" + } + ``` * `CA` - Only nodes with a valid certificate and chain of trust are allowed to connect. For this trust mode, trust stores must be provided and must contain a list of trust certificates. - - A config sample for `CA` trust mode is: - - ```json - "sslConfig" : { - "tls" : "STRICT", - "generateKeyStoreIfNotExisted" : "false", //You can't generate trust stores when using CA - "serverKeyStore" : "server-keystore", - "serverKeyStorePassword" : "tessera", - "serverTrustStore" : "server-truststore", - "serverTrustStorePassword" : "tessera", - "serverTrustMode" : "CA", - "clientKeyStore" : "client-keystore", - "clientKeyStorePassword" : "tessera", - "clientTrustStore" : "client-truststore", - "clientTrustStorePassword" : "tessera", - "clientTrustMode" : "CA", - "knownClientsFile" : "knownClients", - "knownServersFile" : "knownServers" - } - ``` + Only nodes with a valid certificate and chain of trust are allowed to connect. For this trust mode, trust stores must be provided and must contain a list of trust certificates. + + A config sample for `CA` trust mode is: + + ```json + "sslConfig" : { + "tls" : "STRICT", + "generateKeyStoreIfNotExisted" : "false", //You can't generate trust stores when using CA + "serverKeyStore" : "server-keystore", + "serverKeyStorePassword" : "tessera", + "serverTrustStore" : "server-truststore", + "serverTrustStorePassword" : "tessera", + "serverTrustMode" : "CA", + "clientKeyStore" : "client-keystore", + "clientKeyStorePassword" : "tessera", + "clientTrustStore" : "client-truststore", + "clientTrustStorePassword" : "tessera", + "clientTrustMode" : "CA", + "knownClientsFile" : "knownClients", + "knownServersFile" : "knownServers" + } + ``` diff --git a/docs/images/logo-48x48.png b/docs/images/logo-48x48.png new file mode 100644 index 0000000000000000000000000000000000000000..ac0dad1843806698354490052855144c50a7fb1e GIT binary patch literal 1717 zcmV;m21@yfP)MQ+TC>?r zGUIpVp8GSii5im!ALhd0-aB)5_xtWS=R5bV5LwGw*0PqhtYz(g+?qwCP0d{qI_PsW zcdd6W_q^_4vk0%ECp%<+A3iTc$(Kg0VaC1Ap}hSYs#k&PfquwoV&>B`@)vF_FNNW7V$)0hf0i^E%iT*tI-oPlRgSTI_t#A_>fs@i>63 zr!|kPnO9(W$Gtj?w}DiH@qo9gVWf6;H>?D!z@`DTLy>Sb(QqBDX^D3|n!|XG36wD3 zKx?{aZNNJp_zwecfcYHyiUYz5%e&fiYES(IQFsApi?6-kTe;ZA-})+N`y zsMh6v7*spo1i)qS>qrEk3*!86Bz`$U;~hGjR$=$^+;_K0AQg`7O1qpt&F>3Vq7#`H zV3V*Z?EFhEe^2bGl9y+IUE=a60iK10ATuj|KN_Kbp5GT%97+~}HU>QF%GfUNlk+E1 z>+H``zSPwSLf|U`yTxxu6@hu!jQC@W2=s9h7giyJLM4|3=4=N*x57F&u3?)@9_U0) zD-=8u8WLK8{B^L?qC6gn^Djr@>KKu^0BcMn`M=S5*Ze?^c9TtkSFzm)AYe7P1@do#jle#Iy#;c2CE{P!i#(f=Sml|&)A^JF<(3LDmB6kX zi$sC5mBfH?G^oXz0bl!@R5$GJvl36~`5hQP4r|BG)}@pvXAyE#+%KhEt|DOXSS_Hu z229eb3Y+l|<-uN9FKi3vQ1bh%5ZOZ#NovChdzQi`MM8y#!=J4O(F1sP0^=T7!7h9? z-~+D}Ajj~mAN>s)Y$@R>1->5kNvuqlAhpxOlp~L7vVm`s6#Yj0=wwkAAd<>iPSi05 zl&|$xM4$Pb))h@+ziT!oR8>_08Ww*Zi(=iUzT|%kYe-dPp+hV12E@!bt*ZcRg$c}H z&CU8V&1NUJVq7H;u+Go7N-3}6Azs&N66 zs?*P4@`*f=Q>@Az(iGMqquUU!N*~0P9 zIq(zgw$vJ7s%p5Giy3*X+G36u+qAp}I-VP2_y0^g7@vDW_P{=!%qCBA+;77BGvdmt zQB0PO8G(O*iAptcQ*n*{9y%W2c`y0~8@#RYRz4hQ5H06h|3ARL>)*JDpj2L-F*ODM1Nm%Iad-YWJ1HK1!L8TIR3p_Pte&Zi0gr) z?+PjK`BY^U>Fc6h#MC-TCQ{*&=QYU+Z(k4Pm_VnG1$k?nyjt3X?8+@GdE(IKxE7Jr z{WfPkUsH3xO&v-8u_e4>9Tx(BZNfXITBk#(kdAYzq+i3nf%VxWTwUm*Ye+Wn>^qSC z63;vB+t{)QnB8Ty@pr*K!?W*U$6?o-3T=DP>%sghE`ZO*p@kps@8lygnY@5U113y# z9=y@TGFj9z3+cD+0?Pxhm1(EA@QRd3()rorB$Xd7QWGAFt2fE;ITXaoYoua>g8%kV z7x1dNfQRcX4>j@qc7fN;a>4pYoqLw$fxt5a0{_ie|c}oxtvoV7%6nQFZdX5#x90?-W=5$J1vLJxZw7GQvoK?8Z)0 z0#Cs{fZfWVa|y*N`Ojfp3C|}nejVfb?7!2jWi4x2%Uag5wu1H-D4S>R>|YIC00000 LNkvXXu0mjf?Hfd2 literal 0 HcmV?d00001 diff --git a/docs/theme/404.html b/docs/theme/404.html new file mode 100644 index 000000000..52beb3b8b --- /dev/null +++ b/docs/theme/404.html @@ -0,0 +1,4 @@ +{% extends "base.html" %} +{% block content %} +

404 - Not found

+{% endblock %} diff --git a/mkdocs.yml b/mkdocs.yml index 669f42642..3ebbab025 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -62,6 +62,7 @@ theme: code: 'Roboto Mono' language: 'en' logo: 'images/logo.png' + favicon: 'images/logo-48x48.png' extra_css: - 'theme/assets/stylesheets/extra.css' From d1475ee2967ce03af9f9a013418957e2e463abab Mon Sep 17 00:00:00 2001 From: libby kent Date: Fri, 24 May 2019 15:46:49 -0400 Subject: [PATCH 2/3] Adding signer tests for EIP155, Homestead and private tx. (#682) Adding signer tests for EIP155, Homestead and private tx. --- core/types/transaction_signing_quorum_test.go | 356 ++++++++++++++++++ 1 file changed, 356 insertions(+) create mode 100644 core/types/transaction_signing_quorum_test.go diff --git a/core/types/transaction_signing_quorum_test.go b/core/types/transaction_signing_quorum_test.go new file mode 100644 index 000000000..4feeb3225 --- /dev/null +++ b/core/types/transaction_signing_quorum_test.go @@ -0,0 +1,356 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package types + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "fmt" + testifyassert "github.com/stretchr/testify/assert" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" +) + +// run all the tests in this file +// $> go test $(go list ./...) -run TestSignQuorum + +// private key material to test both 0 and 1 bit for the recoveryId (v). +// key with v sign == 28 (Homestead) +var k0v, _ = new(big.Int).SetString("25807260602402504536675820444142779248993100028628438487502323668296269534891", 10) + +// key with v sign == 27 (Homestead) +var k1v, _ = new(big.Int).SetString("10148397294747000913768625849546502595195728826990639993137198410557736548965", 10) + +// helper to deterministically create an ECDSA key from an int. +func createKey(c elliptic.Curve, k *big.Int) (*ecdsa.PrivateKey, error) { + sk := new(ecdsa.PrivateKey) + sk.PublicKey.Curve = c + sk.D = k + sk.PublicKey.X, sk.PublicKey.Y = c.ScalarBaseMult(k.Bytes()) + return sk, nil +} + +func signTx(key *ecdsa.PrivateKey, signer Signer) (*Transaction, common.Address, error) { + addr := crypto.PubkeyToAddress(key.PublicKey) + tx := NewTransaction(0, addr, new(big.Int), 0, new(big.Int), nil) + signedTx, err := SignTx(tx, signer, key) + //fmt.Printf("\ntx.data.V signTx after sign [%v] \n", signedTx.data.V) + return signedTx, addr, err +} + +/** + * As of quorum v2.2.3 commit be7cc31ce208525ea1822e7d0fee88bf7f14500b 30 April 2019 behavior + * + * Test public transactions signed by homestead Signer. Homestead sets the v param on a signed transaction to + * either 27 or 28. The v parameter is used for recovering the sender of the signed transation. + * + * 1. Homestead: should be 27, 28 + * $> go test -run TestSignQuorumHomesteadPublic + */ +func TestSignQuorumHomesteadPublic(t *testing.T) { + + assert := testifyassert.New(t) + + k0, _ := createKey(crypto.S256(), k0v) + k1, _ := createKey(crypto.S256(), k1v) + + homeSinger := HomesteadSigner{} + + // odd parity should be 27 for Homestead + signedTx, addr, _ := signTx(k1, homeSinger) + + assert.True(signedTx.data.V.Cmp(big.NewInt(27)) == 0, fmt.Sprintf("v wasn't 27 it was [%v]", signedTx.data.V)) + + // recover address from signed TX + from, _ := Sender(homeSinger, signedTx) + //fmt.Printf("from [%v] == addr [%v]\n\n", from, from == addr) + assert.True(from == addr, fmt.Sprintf("Expected from and address to be equal. Got %x want %x", from, addr)) + + // even parity should be 28 for Homestead + signedTx, addr, _ = signTx(k0, homeSinger) + assert.True(signedTx.data.V.Cmp(big.NewInt(28)) == 0, fmt.Sprintf("v wasn't 28 it was [%v]\n", signedTx.data.V)) + + // recover address from signed TX + from, _ = Sender(homeSinger, signedTx) + //fmt.Printf("from [%v] == addr [%v]\n", from, from == addr) + assert.True(from == addr, fmt.Sprintf("Expected from and address to be equal. Got %x want %x", from, addr)) + +} + +/** + * As of quorum v2.2.3 commit be7cc31ce208525ea1822e7d0fee88bf7f14500b 30 April 2019 behavior + * + * Test the public transactions signed by the EIP155Signer. + * The EIP155Signer was introduced to protect against replay + * attacks https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md and stores + * the CHAINID in the signed transaction's `v` parameter as `v = chainId * 2 + 35`. + * + * The EthEIP155Signer change breaks private quorum transactions when the chainId == 1 (mainnet chainId), + * as the v parameter on a public transaction and on a private transaction will both be 37, 38. + * + * $> go test -run TestSignQuorumEIP155Public + */ +func TestSignQuorumEIP155Public(t *testing.T) { + + assert := testifyassert.New(t) + + k0, _ := createKey(crypto.S256(), k0v) + k1, _ := createKey(crypto.S256(), k1v) + + // chainId 1 even EIP155Signer should be 37 conflicts with private transaction + var chainId int64 + chainId = 2 // 7 2 10 + + v0 := chainId*2 + 35 // sig[64] + 35 .. where sig[64] == 0 + v1 := chainId*2 + 36 // sig[64] + 35 .. where sig[64] == 1 + + // Will calculate v to be `v = CHAINID * 2 + 35` + // To compute V: + // 2 * 2 + 35 == 39 + // 2 * 2 + 36 == 40 + // To retrieve Sender, pull out 27, 28 Eth Frontier / Homestead values. + // 39 - (2 * 2) - 8 == 27 + // 40 - (2 * 2) - 8 == 28 + EIPsigner := NewEIP155Signer(big.NewInt(chainId)) + + signedTx, addr, _ := signTx(k0, EIPsigner) + + //fmt.Printf("After signing V is [%v] \n", signedTx.data.V) + assert.True(signedTx.data.V.Cmp(big.NewInt(v0)) == 0, fmt.Sprintf("v wasn't [%v] it was [%v]\n", v0, signedTx.data.V)) + from, _ := Sender(EIPsigner, signedTx) + + assert.True(from == addr, fmt.Sprintf("Expected from and address to be equal. Got %x want %x", from, addr)) + + // chainId 1 even EIP155Signer should be 38 conflicts with private transaction + assert.False(signedTx.IsPrivate(), fmt.Sprintf("Public transaction is set to a private transation v == [%v]", signedTx.data.V)) + + signedTx, addr, _ = signTx(k1, EIPsigner) + + assert.True(signedTx.data.V.Cmp(big.NewInt(v1)) == 0, fmt.Sprintf("v wasn't [%v], it was [%v]\n", v1, signedTx.data.V)) + from, _ = Sender(EIPsigner, signedTx) + + assert.True(from == addr, fmt.Sprintf("Expected from and address to be equal. Got %x want %x", from, addr)) + +} + +/** + * As of quorum v2.2.3 commit be7cc31ce208525ea1822e7d0fee88bf7f14500b 30 April 2019 behavior + * + * When the signer is EIP155Signer, chainId == 1 cannot be used because the EIP155 computed `v` value conflicts + * with the private `v` value that quorum uses to indicate a private transaction: v == 37 and v == 38. + * + * $> go test -run TestSignQuorumEIP155FailPublicChain1 + */ +func TestSignQuorumEIP155FailPublicChain1(t *testing.T) { + + assert := testifyassert.New(t) + + k0, _ := createKey(crypto.S256(), k0v) + k1, _ := createKey(crypto.S256(), k1v) + + // chainId 1 even EIP155Signer should be 37.38 which conflicts with private transaction + var chainId int64 + chainId = 1 + + v0 := chainId*2 + 35 // sig[64] + 35 .. where sig[64] == 0 + v1 := chainId*2 + 36 // sig[64] + 35 .. where sig[64] == 1 + + // Will calculate v to be `v = CHAINID * 2 + 35` + // To compute V: + // 2 * 1 + 35 == 37 + // 2 * 1 + 36 == 38 + // To retrieve Sender, pull out 27, 28 Eth Frontier / Homestead values. + // 37 - (1 * 2) - 8 == 27 + // 38 - (1 * 2) - 8 == 28 + EIPsigner := NewEIP155Signer(big.NewInt(chainId)) + + signedTx, addr, _ := signTx(k0, EIPsigner) + + // the calculated v value should equal `chainId * 2 + 35 ` + assert.True(signedTx.data.V.Cmp(big.NewInt(v0)) == 0, fmt.Sprintf("v wasn't [%v] it was "+ + "[%v]\n", v0, signedTx.data.V)) + // the sender will not be equal as HomesteadSigner{}.Sender(tx) is used because IsPrivate() will be true + // although it is a public tx. + // This is test to catch when / if this behavior changes. + assert.True(signedTx.IsPrivate(), "A public transaction with EIP155 and chainID 1 is expected to be "+ + "considered private, as its v param conflict with a private transaction. signedTx.IsPrivate() == [%v]", signedTx.IsPrivate()) + from, _ := Sender(EIPsigner, signedTx) + + assert.False(from == addr, fmt.Sprintf("Expected the sender of a public TX from chainId 1, \n "+ + "should not be recoverable from [%x] addr [%v] ", from, addr)) + + signedTx, addr, _ = signTx(k1, EIPsigner) + + // the calculated v value should equal `chainId * 2 + 35` + assert.True(signedTx.data.V.Cmp(big.NewInt(v1)) == 0, + fmt.Sprintf("v wasn't [%v] it was [%v]", v1, signedTx.data.V)) + + // the sender will not be equal as HomesteadSigner{}.Sender(tx) is used because IsPrivate() will be true + // although it is a public tx. + // This is test to catch when / if this behavior changes. + // we are signing the data with EIPsigner and chainID 1, so this would be considered a private tx. + assert.True(signedTx.IsPrivate(), "A public transaction with EIP155 and chainID 1 is expected to "+ + "to be considered private, as its v param conflict with a private transaction. "+ + "signedTx.IsPrivate() == [%v]", signedTx.IsPrivate()) + from, _ = Sender(EIPsigner, signedTx) + + assert.False(from == addr, fmt.Sprintf("Expected the sender of a public TX from chainId 1, "+ + "should not be recoverable from [%x] addr [%v] ", from, addr)) + +} + +/** +* As of quorum v2.2.3 commit be7cc31ce208525ea1822e7d0fee88bf7f14500b 30 April 2019 behavior +* +* Use Homestead to sign and EIPSigner to recover. +* +* SendTransaction creates a transaction for the given argument, signs it and submit it to the transaction pool. +* func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args SendTxArgs) (common.Hash, error) { +* Current implementation in `internal/ethapi/api.go` +* +* accounts/keystore/keystore.SignTx(): would hash and sign with homestead +* +* When a private tx (obtained from json params PrivateFor) is submitted `internal/ethapi/api.go`: +* +* 1. sign with HomesteadSigner, this will set the v parameter to +* 27 or 28. // there is no indication that this is a private tx yet. +* +* 2. when submitting a transaction `submitTransaction(ctx context.Context, b Backend, tx *types.Transaction, isPrivate bool)` + check isPrivate param, and call `tx.SetPrivate()`, this will update the `v` signature param (recoveryID) +* from 27 -> 37, 28 -> 38. // this is now considered a private tx. +* +* $> go test -run TestSignQuorumHomesteadEIP155SigningPrivateQuorum +*/ +func TestSignQuorumHomesteadEIP155SigningPrivateQuorum(t *testing.T) { + + assert := testifyassert.New(t) + + keys := []*big.Int{k0v, k1v} + + homeSinger := HomesteadSigner{} + recoverySigner := NewEIP155Signer(big.NewInt(18)) + + // check for both sig[64] == 0, and sig[64] == 1 + for i := 0; i < len(keys); i++ { + key, _ := createKey(crypto.S256(), keys[i]) + signedTx, addr, err := signTx(key, homeSinger) + + assert.Nil(err, err) + // set to privateTX after the intial signing, this explicitly sets the v param. + // Note: only works when the tx was signed with the homesteadSinger (v==27 | 28). + signedTx.SetPrivate() + + assert.True(signedTx.IsPrivate(), fmt.Sprintf("Expected the transaction to be private [%v]", signedTx.IsPrivate())) + // Try to recover Sender + from, err := Sender(recoverySigner, signedTx) + + assert.Nil(err, err) + assert.True(from == addr, fmt.Sprintf("Expected from and address to be equal. Got %x want %x", from, addr)) + } + +} + +/* + * As of quorum v2.2.3 commit be7cc31ce208525ea1822e7d0fee88bf7f14500b 30 April 2019 behavior + * Use Homestead to sign and Homestead to recover. + * + * Signing private transactions with HomesteadSigner, and recovering a private transaction with + * HomesteadSigner works, but the transaction has to be set to private `signedTx.SetPrivate()` after + * the signature and before recovering the address. + * + * $> go test -run TestSignQuorumHomesteadOnlyPrivateQuorum + */ +func TestSignQuorumHomesteadOnlyPrivateQuorum(t *testing.T) { + + assert := testifyassert.New(t) + + // check even and odd parity + keys := []*big.Int{k0v, k1v} + + homeSinger := HomesteadSigner{} + recoverySigner := HomesteadSigner{} + + for i := 0; i < len(keys); i++ { + key, _ := createKey(crypto.S256(), keys[i]) + signedTx, addr, err := signTx(key, homeSinger) + + assert.Nil(err, err) + + //fmt.Printf("Private tx.data.V Home [%v] \n", signedTx.data.V) + // set to privateTX after the initial signing. + signedTx.SetPrivate() + assert.True(signedTx.IsPrivate(), fmt.Sprintf("Expected the transaction to be "+ + "private [%v]", signedTx.IsPrivate())) + //fmt.Printf("Private tx.data.V Home [%v] \n", signedTx.data.V) + + // Try to recover Sender + from, err := Sender(recoverySigner, signedTx) + + assert.Nil(err, err) + assert.True(from == addr, fmt.Sprintf("Expected from and address to be equal. "+ + " Got %x want %x", from, addr)) + } + +} + +/* + * As of quorum v2.2.3 commit be7cc31ce208525ea1822e7d0fee88bf7f14500b 30 April 2019 behavior + * + * Use EIP155 to sign and EIP155 to recover (This is not a valid combination and does **not** work). + * + * Signing private transactions with EIP155Signer, and recovering a private transaction with + * EIP155Signer does **not** work. + * note: deriveChainId only checks for 27, 28 when using EIP155 + * note: In the case where the v param is not 27 or 28 when setting private it will always be set to 37 + * + * $> go test -run TestSignQuorumEIP155OnlyPrivateQuorum + */ +func TestSignQuorumEIP155OnlyPrivateQuorum(t *testing.T) { + + assert := testifyassert.New(t) + + // check even and odd parity + keys := []*big.Int{k0v, k1v} + + EIP155Signer := NewEIP155Signer(big.NewInt(0)) + + for i := 0; i < len(keys); i++ { + key, _ := createKey(crypto.S256(), keys[i]) + signedTx, addr, err := signTx(key, EIP155Signer) + + assert.Nil(err, err) + //fmt.Printf("Private tx.data.V Home [%v] \n", signedTx.data.V) + + // set to privateTX after the initial signing. + signedTx.SetPrivate() + + assert.True(signedTx.IsPrivate(), fmt.Sprintf("Expected the transaction to be private [%v]", signedTx.IsPrivate())) + //fmt.Printf("Private tx.data.V Home [%v] \n", signedTx.data.V) + + // Try to recover Sender + from, err := Sender(EIP155Signer, signedTx) + + assert.Nil(err, err) + assert.False(from == addr, fmt.Sprintf("Expected recovery to fail. from [%x] should not equal "+ + "addr [%x]", from, addr)) + + } + +} From 43806e165bfc877ae3dd1bb14f480def0ced18cf Mon Sep 17 00:00:00 2001 From: fixanoid Date: Wed, 29 May 2019 10:42:18 -0400 Subject: [PATCH 3/3] Adding Quorum compatibility table to FAQ (#726) --- docs/FAQ.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/FAQ.md b/docs/FAQ.md index 863a72520..a2621690a 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -40,3 +40,12 @@ ??? info "Known Raft consensus node misconfiguration" Please see https://github.com/jpmorganchase/quorum/issues/410 + +??? info "Quorum version compatibility table" + | | Adding new node v2.0.x | Adding new node v2.1.x | Adding new node v2.2.x | + | ----------------------------------- | ---------------------- | ---------------------- | ---------------------- | + | Existing chain consisting of v2.0.x | block sync
public txn
private txn
| block sync | block sync | + | Existing chain consisting of v2.1.x | block sync | block sync
public txn
private txn
| block sync
public txn
private txn
| + | Existing chain consisting of v2.2.x | block sync | block sync
public txn
private txn
| block sync
public txn
private txn
| + + **Note:** While every Quorum v2 client will be able to connect to any other v2 client, the usefullness will be severely degraded. Red color signifies that while connectivity is possible, red colored versions will be unable to send public or private txns to the rest of the net due to the EIP155 changes in the signer implemented in newer versions. \ No newline at end of file