-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Quorum private transaction support for Abigen (#819)
Support private transaction for abigen and update private abigen docs
- Loading branch information
Showing
12 changed files
with
259 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Abigen with Quorum | ||
|
||
### Overview | ||
|
||
Abigen is a source code generator that converts smart contract ABI definitions into type-safe Go packages. In addition to the original capabilities provided by Ethereum described [here](https://github.com/ethereum/go-ethereum/wiki/Native-DApps:-Go-bindings-to-Ethereum-contracts). Quorum Abigen also supports private transactions. | ||
|
||
### Implementation | ||
|
||
`PrivateFrom` and `PrivateFor` fields have been added to the `bind.TransactOpts` which allows users to specify the public keys of the transaction manager (Tessera/Constellation) used to send and receive private transactions. The existing `ethclient` has been extended with a private transaction manager client to support sending `/storeraw` request. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package ethclient | ||
|
||
import ( | ||
"bytes" | ||
"encoding/base64" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"net/url" | ||
) | ||
|
||
type privateTransactionManagerClient interface { | ||
storeRaw(data []byte, privateFrom string) ([]byte, error) | ||
} | ||
|
||
type privateTransactionManagerDefaultClient struct { | ||
rawurl string | ||
httpClient *http.Client | ||
} | ||
|
||
// Create a new client to interact with private transaction manager via a HTTP endpoint | ||
func newPrivateTransactionManagerClient(endpoint string) (privateTransactionManagerClient, error) { | ||
_, err := url.Parse(endpoint) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &privateTransactionManagerDefaultClient{ | ||
rawurl: endpoint, | ||
httpClient: &http.Client{}, | ||
}, nil | ||
} | ||
|
||
type storeRawReq struct { | ||
Payload string `json:"payload"` | ||
From string `json:"from,omitempty"` | ||
} | ||
|
||
type storeRawResp struct { | ||
Key string `json:"key"` | ||
} | ||
|
||
func (pc *privateTransactionManagerDefaultClient) storeRaw(data []byte, privateFrom string) ([]byte, error) { | ||
storeRawReq := &storeRawReq{ | ||
Payload: base64.StdEncoding.EncodeToString(data), | ||
From: privateFrom, | ||
} | ||
reqBodyBuf := new(bytes.Buffer) | ||
if err := json.NewEncoder(reqBodyBuf).Encode(storeRawReq); err != nil { | ||
return nil, err | ||
} | ||
resp, err := pc.httpClient.Post(pc.rawurl+"/storeraw", "application/json", reqBodyBuf) | ||
if err != nil { | ||
return nil, fmt.Errorf("unable to invoke /storeraw due to %s", err) | ||
} | ||
defer func() { | ||
_ = resp.Body.Close() | ||
}() | ||
if resp.StatusCode != http.StatusOK { | ||
return nil, fmt.Errorf("server returns %s", resp.Status) | ||
} | ||
// parse response | ||
var storeRawResp storeRawResp | ||
if err := json.NewDecoder(resp.Body).Decode(&storeRawResp); err != nil { | ||
return nil, err | ||
} | ||
encryptedPayloadHash, err := base64.StdEncoding.DecodeString(storeRawResp.Key) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return encryptedPayloadHash, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package ethclient | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"net/http/httptest" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
const ( | ||
arbitraryBase64Data = "YXJiaXRyYXJ5IGRhdGE=" // = "arbitrary data" | ||
) | ||
|
||
func TestPrivateTransactionManagerClient_storeRaw(t *testing.T) { | ||
// mock tessera client | ||
arbitraryServer := newStoreRawServer() | ||
defer arbitraryServer.Close() | ||
testObject, err := newPrivateTransactionManagerClient(arbitraryServer.URL) | ||
assert.NoError(t, err) | ||
|
||
key, err := testObject.storeRaw([]byte("arbitrary payload"), "arbitrary private from") | ||
|
||
assert.NoError(t, err) | ||
assert.Equal(t, "arbitrary data", string(key)) | ||
} | ||
|
||
func newStoreRawServer() *httptest.Server { | ||
arbitraryResponse := fmt.Sprintf(` | ||
{ | ||
"key": "%s" | ||
} | ||
`, arbitraryBase64Data) | ||
mux := http.NewServeMux() | ||
mux.HandleFunc("/storeraw", func(w http.ResponseWriter, req *http.Request) { | ||
if req.Method == "POST" { | ||
// parse request | ||
var storeRawReq storeRawReq | ||
if err := json.NewDecoder(req.Body).Decode(&storeRawReq); err != nil { | ||
http.Error(w, err.Error(), http.StatusBadRequest) | ||
return | ||
} | ||
// send response | ||
_, _ = fmt.Fprintf(w, "%s", arbitraryResponse) | ||
} else { | ||
http.Error(w, "Invalid request method", http.StatusMethodNotAllowed) | ||
} | ||
|
||
}) | ||
return httptest.NewServer(mux) | ||
} |
Oops, something went wrong.