mirror of https://github.com/poanetwork/quorum.git
add support for private sendRawTransaction - merge with latest quorum
This commit is contained in:
parent
47954d8a55
commit
c49a833eb9
51
docs/api.md
51
docs/api.md
|
@ -3,6 +3,8 @@
|
|||
|
||||
## Privacy APIs
|
||||
|
||||
#### eth.sendTransaction
|
||||
|
||||
__To support private transactions in Quorum, the `web3.eth.sendTransaction(object)` API method has been modified.__
|
||||
|
||||
```js
|
||||
|
@ -50,6 +52,55 @@ web3.eth.sendTransaction({
|
|||
```
|
||||
***
|
||||
|
||||
#### eth.sendRawPrivateTransaction
|
||||
|
||||
__To support sending raw transactions in Quorum, the `web3.eth.sendRawPrivateTransaction(string, object)` API method has been created.__
|
||||
|
||||
```js
|
||||
web3.eth.sendRawPrivateTransaction(signedTransactionData [, privateData] [, callback])
|
||||
```
|
||||
|
||||
Sends an already signed transaction. For example can be signed using: https://github.com/SilentCicero/ethereumjs-accounts
|
||||
|
||||
__Important:__ Please note that before calling this API, a `storeraw` api need to be called first to Quorum's private transaction manager. Instructions on how to do this can be found [here](https://github.com/jpmorganchase/tessera/wiki/Interface-&-API).
|
||||
|
||||
##### Parameters
|
||||
1. `String` - Signed transaction data in HEX format
|
||||
2. `Object` - Private data to send
|
||||
- `privateFor`: `List<String>` - When sending a private transaction, an array of the recipients' base64-encoded public keys.
|
||||
3. `Function` - (optional) If you pass a callback the HTTP request is made asynchronous. See [this note](#using-callbacks) for details.
|
||||
|
||||
##### Returns
|
||||
`String` - The 32 Bytes transaction hash as HEX string.
|
||||
If the transaction was a contract creation use [web3.eth.getTransactionReceipt()](#web3ethgettransactionreceipt) to get the contract address, after the transaction was mined.
|
||||
|
||||
|
||||
##### Example
|
||||
```js
|
||||
var Tx = require('ethereumjs-tx');
|
||||
var privateKey = new Buffer('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', 'hex')
|
||||
var rawTx = {
|
||||
nonce: '0x00',
|
||||
gasPrice: '0x09184e72a000',
|
||||
gasLimit: '0x2710',
|
||||
to: '0x0000000000000000000000000000000000000000',
|
||||
value: '0x00',
|
||||
// This data should be the hex value of the hash returned by Quorum's privacy transaction manager after invoking storeraw api
|
||||
data: '0x7f7465737432000000000000000000000000000000000000000000000000000000600057'
|
||||
}
|
||||
var tx = new Tx(rawTx);
|
||||
tx.sign(privateKey);
|
||||
var serializedTx = tx.serialize();
|
||||
//console.log(serializedTx.toString('hex'));
|
||||
//f889808609184e72a00082271094000000000000000000000000000000000000000080a47f74657374320000000000000000000000000000000000000000000000000000006000571ca08a8bbf888cfa37bbf0bb965423625641fc956967b81d12e23709cead01446075a01ce999b56a8a88504be365442ea61239198e23d1fce7d00fcfc5cd3b44b7215f
|
||||
web3.eth.sendRawPrivateTransaction('0x' + serializedTx.toString('hex'), {privateFor: ["ROAZBWtSacxXQrOe3FGAqJDyJjFePR5ce4TSIzmJ0Bc="]}, function(err, hash) {
|
||||
if (!err)
|
||||
console.log(hash); // "0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385"
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
|
||||
## JSON RPC Privacy API Reference
|
||||
|
||||
__In addition to the JSON-RPC provided by Ethereum, Quorum exposes below two API calls.__
|
||||
|
|
|
@ -1168,12 +1168,17 @@ type SendTxArgs struct {
|
|||
Input *hexutil.Bytes `json:"input"`
|
||||
|
||||
//Quorum
|
||||
PrivateFrom string `json:"privateFrom"`
|
||||
PrivateFor []string `json:"privateFor"`
|
||||
PrivateTxType string `json:"restriction"`
|
||||
PrivateFrom string `json:"privateFrom"`
|
||||
PrivateFor []string `json:"privateFor"`
|
||||
PrivateTxType string `json:"restriction"`
|
||||
//End-Quorum
|
||||
}
|
||||
|
||||
// SendRawTxArgs represents the arguments to submit a new signed private transaction into the transaction pool.
|
||||
type SendRawTxArgs struct {
|
||||
PrivateFor []string `json:"privateFor"`
|
||||
}
|
||||
|
||||
// setDefaults is a helper function that fills in default values for unspecified tx fields.
|
||||
func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error {
|
||||
if args.Gas == nil {
|
||||
|
@ -1315,6 +1320,33 @@ func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encod
|
|||
return submitTransaction(ctx, s.b, tx, tx.IsPrivate())
|
||||
}
|
||||
|
||||
// SendRawPrivateTransaction will add the signed transaction to the transaction pool.
|
||||
// The sender is responsible for signing the transaction and using the correct nonce.
|
||||
func (s *PublicTransactionPoolAPI) SendRawPrivateTransaction(ctx context.Context, encodedTx hexutil.Bytes, args SendRawTxArgs) (common.Hash, error) {
|
||||
|
||||
tx := new(types.Transaction)
|
||||
if err := rlp.DecodeBytes(encodedTx, tx); err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
|
||||
txHash := []byte(tx.Data())
|
||||
isPrivate := args.PrivateFor != nil
|
||||
|
||||
if isPrivate {
|
||||
if len(txHash) > 0 {
|
||||
//Send private transaction to privacy manager
|
||||
log.Info("sending private tx", "data", fmt.Sprintf("%x", txHash), "privatefor", args.PrivateFor)
|
||||
result, err := private.P.SendSignedTx(txHash, args.PrivateFor)
|
||||
log.Info("sent private tx", "result", fmt.Sprintf("%x", result), "privatefor", args.PrivateFor)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return submitTransaction(ctx, s.b, tx, isPrivate)
|
||||
}
|
||||
|
||||
// Sign calculates an ECDSA signature for:
|
||||
// keccack256("\x19Ethereum Signed Message:\n" + len(message) + message).
|
||||
//
|
||||
|
@ -1688,4 +1720,5 @@ func (s *PublicBlockChainAPI) GetQuorumPayload(digestHex string) (string, error)
|
|||
}
|
||||
return fmt.Sprintf("0x%x", data), nil
|
||||
}
|
||||
|
||||
//End-Quorum
|
||||
|
|
|
@ -396,6 +396,12 @@ const Eth_JS = `
|
|||
web3._extend({
|
||||
property: 'eth',
|
||||
methods: [
|
||||
new web3._extend.Method({
|
||||
name: 'sendRawPrivateTransaction',
|
||||
call: 'eth_sendRawPrivateTransaction',
|
||||
params: 2,
|
||||
inputFormatter: [null, null]
|
||||
}),
|
||||
new web3._extend.Method({
|
||||
name: 'sign',
|
||||
call: 'eth_sign',
|
||||
|
|
|
@ -33,6 +33,18 @@ func (g *Constellation) Send(data []byte, from string, to []string) (out []byte,
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (g *Constellation) SendSignedTx(data []byte, to []string) (out []byte, err error) {
|
||||
if g.isConstellationNotInUse {
|
||||
return nil, ErrConstellationIsntInit
|
||||
}
|
||||
out, err = g.node.SendSignedPayload(data, to)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
|
||||
func (g *Constellation) Receive(data []byte) ([]byte, error) {
|
||||
if g.isConstellationNotInUse {
|
||||
return nil, nil
|
||||
|
|
|
@ -106,6 +106,30 @@ func (c *Client) SendPayload(pl []byte, b64From string, b64To []string) ([]byte,
|
|||
return ioutil.ReadAll(base64.NewDecoder(base64.StdEncoding, res.Body))
|
||||
}
|
||||
|
||||
func (c *Client) SendSignedPayload(signedPayload []byte, b64To []string) ([]byte, error) {
|
||||
buf := bytes.NewBuffer(signedPayload)
|
||||
req, err := http.NewRequest("POST", "http+unix://c/sendsignedtx", buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("c11n-to", strings.Join(b64To, ","))
|
||||
req.Header.Set("Content-Type", "application/octet-stream")
|
||||
res, err := c.httpClient.Do(req)
|
||||
|
||||
if res != nil {
|
||||
defer res.Body.Close()
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("Non-200 status code: %+v", res)
|
||||
}
|
||||
|
||||
return ioutil.ReadAll(base64.NewDecoder(base64.StdEncoding, res.Body))
|
||||
}
|
||||
|
||||
func (c *Client) ReceivePayload(key []byte) ([]byte, error) {
|
||||
req, err := http.NewRequest("GET", "http+unix://c/receiveraw", nil)
|
||||
if err != nil {
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
type PrivateTransactionManager interface {
|
||||
Send(data []byte, from string, to []string) ([]byte, error)
|
||||
SendSignedTx(data []byte, to []string) ([]byte, error)
|
||||
Receive(data []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue