merge with master

This commit is contained in:
vsmk98 2019-01-14 13:53:05 +08:00
commit 061c9b85ce
30 changed files with 448 additions and 41 deletions

View File

@ -1,6 +1,8 @@
# Building Quorum
Note: Building Quorum requires both a Go (version 1.9 or later) and a C compiler. You can install them using your favourite package manager.
Clone the repository and build the source:
```

View File

@ -2,7 +2,57 @@
## How does private state work?
Let's look at the EVM structure:
Original commit from Jeff explains the dual public and private state with INITIAL restrictions:
```
commit 763f939f4725daa136161868d3b01fa7a84eb71e
Author: Jeffrey Wilcke <jeffrey@ethereum.org>
Date: Mon Oct 31 12:46:40 2016 +0100
core, core/vm: dual state & read only EVM
This commit implements a dual state approach. The dual state approach
separates public and private state by making the core vm environment
context aware.
Although not currently implemented it will need to prohibit value
transfers and it must initialise all transactions from accounts on the
public state. This means that sending transactions increments the
account nonce on the public state and contract addresses are derived
from the public state when initialised by a transaction. For obvious
reasons, contract created by private contracts are still derived from
public state.
This is required in order to have consensus over the public state at all
times as non-private participants would still process the transaction on
the public state even though private payload can not be decrypted. This
means that participants of a private group must do the same in order to
have public consensus. However the creation of the contract and
interaction still occurs on the private state.
It implements support for the following calling model:
S: sender, (X): private, X: public, ->: direction, [ ]: read only mode
1. S -> A -> B
2. S -> (A) -> (B)
3. S -> (A) -> [ B -> C ]
It does not support
1. (S) -> A
2. (S) -> (A)
3. S -> (A) -> B
Implemented "read only" mode for the EVM. Read only mode is checked
during any opcode that could potentially modify the state. If such an
opcode is encountered during "read only", it throws an exception.
The EVM is flagged "read only" when a private contract calls in to
public state.
```
Some things have changed since, let's look at the EVM structure in some more detail:
```go
type EVM struct {

View File

@ -42,8 +42,8 @@ The official docker containers can be found under https://hub.docker.com/u/quoru
* [Constellation](https://github.com/jpmorganchase/constellation): Haskell implementation of peer-to-peer encrypted message exchange for transaction privacy
* [Tessera](https://github.com/jpmorganchase/tessera): Java implementation of peer-to-peer encrypted message exchange for transaction privacy
* Quorum supported consensuses
* [Raft Consensus Documentation](raft/doc.md)
* [Istanbul BFT Consensus Documentation](https://github.com/ethereum/EIPs/issues/650): [RPC API](https://github.com/getamis/go-ethereum/wiki/RPC-API) and [technical article](https://medium.com/getamis/istanbul-bft-ibft-c2758b7fe6ff)
* [Raft Consensus Documentation](docs/raft.md)
* [Istanbul BFT Consensus Documentation](https://github.com/ethereum/EIPs/issues/650): [RPC API](https://github.com/jpmorganchase/quorum/blob/master/docs/istanbul-rpc-api.md) and [technical article](https://medium.com/getamis/istanbul-bft-ibft-c2758b7fe6ff). <span style="background-color: #ffffbf">Please note</span> that updated istanbul-tools is now hosted in [this](https://github.com/jpmorganchase/istanbul-tools/) repository
* [Clique POA Consensus Documentation](https://github.com/ethereum/EIPs/issues/225) and a [guide to setup clique json](https://modalduality.org/posts/puppeth/) with [puppeth](https://blog.ethereum.org/2017/04/14/geth-1-6-puppeth-master/)
* [ZSL](https://github.com/jpmorganchase/quorum/wiki/ZSL) wiki page and [documentation](https://github.com/jpmorganchase/zsl-q/blob/master/README.md)
* [quorum-tools](https://github.com/jpmorganchase/quorum-tools): local cluster orchestration, and integration testing tool

View File

@ -820,17 +820,12 @@ func setIPC(ctx *cli.Context, cfg *node.Config) {
// makeDatabaseHandles raises out the number of allowed file handles per process
// for Geth and returns half of the allowance to assign to the database.
func makeDatabaseHandles() int {
limit, err := fdlimit.Current()
limit, err := fdlimit.Maximum()
if err != nil {
Fatalf("Failed to retrieve file descriptor allowance: %v", err)
}
if limit < 2048 {
if err := fdlimit.Raise(2048); err != nil {
Fatalf("Failed to raise file descriptor allowance: %v", err)
}
}
if limit > 2048 { // cap database file descriptors even if more is available
limit = 2048
if err := fdlimit.Raise(uint64(limit)); err != nil {
Fatalf("Failed to raise file descriptor allowance: %v", err)
}
return limit / 2 // Leave half for networking and other stuff
}

View File

@ -31,7 +31,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
set "gopkg.in/fatih/set.v0"
"gopkg.in/fatih/set.v0"
)
// Ethash proof-of-work protocol constants.
@ -285,9 +285,9 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *
if diff < 0 {
diff *= -1
}
limit := parent.GasLimit / params.GasLimitBoundDivisor
limit := parent.GasLimit / params.OriginalGasLimitBoundDivisor
if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit {
if uint64(diff) >= limit || header.GasLimit < params.OriginnalMinGasLimit {
return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit)
}
// Verify that the block number is parent's +1

View File

@ -119,3 +119,95 @@ func TestDualStateReadOnly(t *testing.T) {
t.Errorf("expected 0 got %x", value)
}
}
var (
calleeAddress = common.Address{2}
calleeContractCode = "600a6000526001601ff300" // a function that returns 10
callerAddress = common.Address{1}
// a functionn that calls the callee's function at its address and return the same value
//000000: PUSH1 0x01
//000002: PUSH1 0x00
//000004: PUSH1 0x00
//000006: PUSH1 0x00
//000008: PUSH20 0x0200000000000000000000000000000000000000
//000029: PUSH3 0x0186a0
//000033: STATICCALL
//000034: PUSH1 0x01
//000036: PUSH1 0x00
//000038: RETURN
//000039: STOP
callerContractCode = "6001600060006000730200000000000000000000000000000000000000620186a0fa60016000f300"
)
func verifyStaticCall(t *testing.T, privateState *state.StateDB, publicState *state.StateDB, expectedHash common.Hash) {
author := common.Address{}
msg := callmsg{
addr: author,
to: &callerAddress,
value: big.NewInt(1),
gas: 1000000,
gasPrice: new(big.Int),
data: nil,
}
ctx := NewEVMContext(msg, &dualStateTestHeader, nil, &author)
env := vm.NewEVM(ctx, publicState, privateState, &params.ChainConfig{
ByzantiumBlock: new(big.Int),
}, vm.Config{})
ret, _, err := env.Call(vm.AccountRef(author), callerAddress, msg.data, msg.gas, new(big.Int))
if err != nil {
t.Fatalf("Call error: %s", err)
}
value := common.Hash{ret[0]}
if value != expectedHash {
t.Errorf("expected %x got %x", expectedHash, value)
}
}
func TestStaticCall_whenPublicToPublic(t *testing.T) {
db := ethdb.NewMemDatabase()
publicState, _ := state.New(common.Hash{}, state.NewDatabase(db))
publicState.SetCode(callerAddress, common.Hex2Bytes(callerContractCode))
publicState.SetCode(calleeAddress, common.Hex2Bytes(calleeContractCode))
verifyStaticCall(t, publicState, publicState, common.Hash{10})
}
func TestStaticCall_whenPublicToPrivateInTheParty(t *testing.T) {
db := ethdb.NewMemDatabase()
privateState, _ := state.New(common.Hash{}, state.NewDatabase(db))
privateState.SetCode(calleeAddress, common.Hex2Bytes(calleeContractCode))
publicState, _ := state.New(common.Hash{}, state.NewDatabase(db))
publicState.SetCode(callerAddress, common.Hex2Bytes(callerContractCode))
verifyStaticCall(t, privateState, publicState, common.Hash{10})
}
func TestStaticCall_whenPublicToPrivateNotInTheParty(t *testing.T) {
db := ethdb.NewMemDatabase()
privateState, _ := state.New(common.Hash{}, state.NewDatabase(db))
publicState, _ := state.New(common.Hash{}, state.NewDatabase(db))
publicState.SetCode(callerAddress, common.Hex2Bytes(callerContractCode))
verifyStaticCall(t, privateState, publicState, common.Hash{0})
}
func TestStaticCall_whenPrivateToPublic(t *testing.T) {
db := ethdb.NewMemDatabase()
privateState, _ := state.New(common.Hash{}, state.NewDatabase(db))
privateState.SetCode(callerAddress, common.Hex2Bytes(callerContractCode))
publicState, _ := state.New(common.Hash{}, state.NewDatabase(db))
publicState.SetCode(calleeAddress, common.Hex2Bytes(calleeContractCode))
verifyStaticCall(t, privateState, publicState, common.Hash{10})
}

View File

@ -579,7 +579,8 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
return ErrInvalidGasPrice
}
// Heuristic limit, reject transactions over 32KB to prevent DOS attacks
if tx.Size() > 32*1024 {
// UPDATED to 64KB to support the deployment of bigger contract due to the pressing need for sophisticated/complex contract in financial/capital markets - Nathan Aw
if tx.Size() > 64*1024 {
return ErrOversizedData
}
// Transactions can't be negative. This may never happen using RLP decoded

View File

@ -278,8 +278,8 @@ func TestInvalidTransactions(t *testing.T) {
t.Error("expected", ErrGasLimit, "; got", err)
}
data := make([]byte, (32*1024)+1)
tx2, _ := types.SignTx(types.NewTransaction(2, common.Address{}, big.NewInt(100),100000, big.NewInt(1), data), types.HomesteadSigner{}, key)
data := make([]byte, (64*1024)+1)
tx2, _ := types.SignTx(types.NewTransaction(2, common.Address{}, big.NewInt(100), 100000, big.NewInt(1), data), types.HomesteadSigner{}, key)
if err := pool.AddRemote(tx2); err != ErrOversizedData {
t.Error("expected", ErrOversizedData, "; got", err)
}

View File

@ -63,6 +63,14 @@ func (b *Bloom) Add(d *big.Int) {
b.SetBytes(bin.Bytes())
}
// OrBloom executes an Or operation on the bloom
func (b *Bloom) OrBloom(bl []byte) {
bin := new(big.Int).SetBytes(b[:])
input := new(big.Int).SetBytes(bl[:])
bin.Or(bin, input)
b.SetBytes(bin.Bytes())
}
// Big converts b to a big integer.
func (b Bloom) Big() *big.Int {
return new(big.Int).SetBytes(b[:])

View File

@ -493,6 +493,9 @@ func (tx *Transaction) IsPrivate() bool {
}
func (tx *Transaction) SetPrivate() {
if tx.IsPrivate() {
return
}
if tx.data.V.Int64() == 28 {
tx.data.V.SetUint64(38)
} else {

View File

@ -334,6 +334,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
if evm.vmConfig.NoRecursion && evm.depth > 0 {
return nil, gas, nil
}
// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
return nil, gas, ErrDepth
@ -348,20 +349,21 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
var (
to = AccountRef(addr)
snapshot = evm.StateDB.Snapshot()
stateDb = getDualState(evm, addr)
snapshot = stateDb.Snapshot()
)
// Initialise a new contract and set the code that is to be used by the
// EVM. The contract is a scoped environment for this execution context
// only.
contract := NewContract(caller, to, new(big.Int), gas)
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
contract.SetCallCode(&addr, stateDb.GetCodeHash(addr), stateDb.GetCode(addr))
// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally
// when we're in Homestead this also counts for code storage gas errors.
ret, err = run(evm, contract, input)
if err != nil {
evm.StateDB.RevertToSnapshot(snapshot)
stateDb.RevertToSnapshot(snapshot)
if err != errExecutionReverted {
contract.UseGas(contract.Gas)
}

View File

@ -391,7 +391,10 @@ func opAddress(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *
func opBalance(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
slot := stack.peek()
slot.Set(evm.StateDB.GetBalance(common.BigToAddress(slot)))
addr := common.BigToAddress(slot)
// Quorum: get public/private state db based on addr
balance := getDualState(evm, addr).GetBalance(addr)
slot.Set(balance)
return nil, nil
}
@ -457,7 +460,9 @@ func opReturnDataCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory,
func opExtCodeSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
slot := stack.peek()
slot.SetUint64(uint64(evm.StateDB.GetCodeSize(common.BigToAddress(slot))))
addr := common.BigToAddress(slot)
// Quorum: get public/private state db based on addr
slot.SetUint64(uint64(getDualState(evm, addr).GetCodeSize(addr)))
return nil, nil
}
@ -489,7 +494,8 @@ func opExtCodeCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, sta
codeOffset = stack.pop()
length = stack.pop()
)
codeCopy := getDataBig(evm.StateDB.GetCode(addr), codeOffset, length)
// Quorum: get public/private state db based on addr
codeCopy := getDataBig(getDualState(evm, addr).GetCode(addr), codeOffset, length)
memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)
evm.interpreter.intPool.put(memOffset, codeOffset, length)
@ -571,7 +577,8 @@ func opMstore8(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *
func opSload(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
loc := stack.peek()
val := evm.StateDB.GetState(contract.Address(), common.BigToHash(loc))
// Quorum: get public/private state db based on addr
val := getDualState(evm, contract.Address()).GetState(contract.Address(), common.BigToHash(loc))
loc.SetBytes(val.Bytes())
return nil, nil
}
@ -579,7 +586,8 @@ func opSload(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *St
func opSstore(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
loc := common.BigToHash(stack.pop())
val := stack.pop()
evm.StateDB.SetState(contract.Address(), loc, common.BigToHash(val))
// Quorum: get public/private state db based on addr
getDualState(evm, contract.Address()).SetState(contract.Address(), loc, common.BigToHash(val))
evm.interpreter.intPool.put(val)
return nil, nil
@ -794,10 +802,12 @@ func opStop(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta
}
func opSuicide(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
balance := evm.StateDB.GetBalance(contract.Address())
evm.StateDB.AddBalance(common.BigToAddress(stack.pop()), balance)
// Quorum: get public/private state db based on addr
db := getDualState(evm, contract.Address())
balance := db.GetBalance(contract.Address())
db.AddBalance(common.BigToAddress(stack.pop()), balance)
evm.StateDB.Suicide(contract.Address())
db.Suicide(contract.Address())
return nil, nil
}

View File

@ -173,7 +173,6 @@ func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err er
// Get the operation from the jump table and validate the stack to ensure there are
// enough stack items available to perform the operation.
op = contract.GetOp(pc)
operation := in.cfg.JumpTable[op]
if !operation.valid {
return nil, fmt.Errorf("invalid opcode 0x%x", int(op))

View File

@ -3,6 +3,8 @@
* [Whitepaper](./Quorum%20Whitepaper%20v0.2.pdf) (PDF) - Quorum Whitepaper [demo video](https://vimeo.com/user5833792/review/210456842/a42d0fcb87)
* [Design](./design.md) - Quorum design overview
* [Raft Specific Documentation](./raft.md) - Overview of raft implementation
* [Istanbul RPC API](./istanbul-rpc-api.md) - Overview of Istanbul BFT APIs
* [Privacy](./privacy.md) - Sending private transactions [privacy video](https://vimeo.com/user5833792/review/210456729/8f70cfaaa5)
* [Running](./running.md) - Detailed instructions for running Quorum nodes (see also [Constellation](https://github.com/jpmorganchase/constellation), [Tessera](https://github.com/jpmorganchase/tessera))
* [API](./api.md) - new privacy API

View File

@ -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 a pre-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.__

86
docs/istanbul-rpc-api.md Normal file
View File

@ -0,0 +1,86 @@
# Istanbul RPC API
This is an up to date copy of original wiki entry located here https://github.com/getamis/go-ethereum/wiki/RPC-API
# Getting Started
1. Run Istanbul geth with `--rpcapi "istanbul"`
2. `geth attach`
## API Reference
### istanbul.candidates
Candidates returns the current candidates which the node tries to vote in or out.
```
istanbul.candidates
```
#### Returns
`map[string] boolean` - returns the current candidates map.
### istanbul.discard
Discard drops a currently running candidate, stopping the validator from casting further votes (either for or against).
```
istanbul.discard(address)
```
#### Parameters
`string` - the address of the candidate
### istanbul.getSnapshot
GetSnapshot retrieves the state snapshot at a given block.
```
istanbul.getSnapshot(blockHashOrBlockNumber)
```
#### Parameters
`String|Number` - The block number, the string "latest" or nil. nil is the same with string "latest" and means the latest block
#### Returns
`Object` - The snapshot object
### istanbul.getSnapshotAtHash
GetSnapshotAtHash retrieves the state snapshot at a given block.
```
istanbul.getSnapshotAtHash(blockHash)
```
#### Parameters
`String` - The block hash
#### Returns
`Object` - The snapshot object
### istanbul.getValidators
GetValidators retrieves the list of authorized validators at the specified block.
```
istanbul.getValidators(blockHashOrBlockNumber)
```
#### Parameters
`String|Number` - The block number, the string "latest" or nil. nil is the same with string "latest" and means the latest block
#### Returns
`[]string` - The validator address array
### istanbul.getValidatorsAtHash
GetValidatorsAtHash retrieves the list of authorized validators at the specified block.
```
istanbul.getValidatorsAtHash(blockHash)
```
#### Parameters
`String` - The block hash
#### Returns
`[]string` - The validator address array
### istanbul.propose
Propose injects a new authorization candidate that the validator will attempt to push through. If the number of vote is larger than 1/2 of validators to vote in/out, the candidate will be added/removed in validator set.
```
istanbul.propose(address, auth)
```
#### Parameters
`String` - The address of candidate
`bool` - `true` votes in and `false` votes out

View File

@ -150,7 +150,19 @@ func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state vm.M
vmError := func() error { return nil }
context := core.NewEVMContext(msg, header, b.eth.BlockChain(), nil)
return vm.NewEVM(context, statedb.state, statedb.privateState, b.eth.chainConfig, vmCfg), vmError, nil
// Set the private state to public state if contract address is not present in the private state
to := common.Address{}
if msg.To() != nil {
to = *msg.To()
}
privateState := statedb.privateState
if !privateState.Exist(to) {
privateState = statedb.state
}
return vm.NewEVM(context, statedb.state, privateState, b.eth.chainConfig, vmCfg), vmError, nil
}
func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {

View File

@ -378,12 +378,13 @@ func (s *Ethereum) Etherbase() (eb common.Address, err error) {
// set in js console via admin interface or wrapper from cli flags
func (s *Ethereum) SetEtherbase(etherbase common.Address) {
s.lock.Lock()
defer s.lock.Unlock()
if _, ok := s.engine.(consensus.Istanbul); ok {
log.Error("Cannot set etherbase in Istanbul consensus")
return
}
s.etherbase = etherbase
s.lock.Unlock()
s.miner.SetEtherbase(etherbase)
}

View File

@ -121,10 +121,14 @@ func (b *BloomIndexer) Reset(section uint64, lastSectionHead common.Hash) error
return err
}
// Process implements core.ChainIndexerBackend, adding a new header's bloom into
// the index.
// Process implements core.ChainIndexerBackend, executes an Or operation on header.bloom and private bloom
// (header.bloom | private bloom) and adds to index
func (b *BloomIndexer) Process(header *types.Header) {
b.gen.AddBloom(uint(header.Number.Uint64()-b.section*b.size), header.Bloom)
publicBloom := header.Bloom
privateBloom := core.GetPrivateBlockBloom(b.db, header.Number.Uint64())
publicBloom.OrBloom(privateBloom.Bytes())
b.gen.AddBloom(uint(header.Number.Uint64()-b.section*b.size), publicBloom)
b.head = header.Hash()
}

View File

@ -1171,12 +1171,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 {
@ -1321,6 +1326,35 @@ 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
}
}
} else {
return common.Hash{}, fmt.Errorf("transaction is not private")
}
return submitTransaction(ctx, s.b, tx, isPrivate)
}
// Sign calculates an ECDSA signature for:
// keccack256("\x19Ethereum Signed Message:\n" + len(message) + message).
//
@ -1694,6 +1728,7 @@ func (s *PublicBlockChainAPI) GetQuorumPayload(digestHex string) (string, error)
}
return fmt.Sprintf("0x%x", data), nil
}
//End-Quorum
func resolvePrivateFor(privateFor []string) []string{

View File

@ -399,6 +399,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',

View File

@ -344,6 +344,12 @@ func (self *worker) wait() {
log.Error("Failed writWriteBlockAndStating block to chain", "err", err)
continue
}
if err := core.WritePrivateBlockBloom(self.chainDb, block.NumberU64(), work.privateReceipts); err != nil {
log.Error("Failed writing private block bloom", "err", err)
continue
}
// Broadcast the block and announce chain insertion event
self.mux.Post(core.NewMinedBlockEvent{Block: block})
var (

View File

@ -35,7 +35,6 @@ func isNodePermissioned(nodename string, currentNode string, datadir string, dir
}
return true
}
log.Debug("isNodePermissioned", "connection", direction, "nodename", nodename[:NODE_NAME_LENGTH], "DENIED-BY", currentNode[:NODE_NAME_LENGTH])
}
log.Debug("isNodePermissioned", "connection", direction, "nodename", nodename[:NODE_NAME_LENGTH], "DENIED-BY", currentNode[:NODE_NAME_LENGTH])
return false

View File

@ -20,9 +20,15 @@ import "math/big"
var (
TargetGasLimit = GenesisGasLimit // The artificial target
)
const (
// these are original values from upstream Geth, used in ethash consensus
OriginnalMinGasLimit uint64 = 5000 // The bound divisor of the gas limit, used in update calculations.
OriginalGasLimitBoundDivisor uint64 = 1024 // Minimum the gas limit may ever be.
// modified values for Quorum
GasLimitBoundDivisor uint64 = 4096 // The bound divisor of the gas limit, used in update calculations.
MinGasLimit uint64 = 700000000 // Minimum the gas limit may ever be.
GenesisGasLimit uint64 = 800000000 // Gas limit of the Genesis block.

View File

@ -27,8 +27,8 @@ const (
VersionMeta = "stable" // Version metadata to append to the version string
QuorumVersionMajor = 2
QuorumVersionMinor = 1
QuorumVersionPatch = 1
QuorumVersionMinor = 2
QuorumVersionPatch = 0
)
// Version holds the textual version string.

View File

@ -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

View File

@ -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 {

View File

@ -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)
}

@ -1 +1 @@
Subproject commit 2bb0c3da3bbb15c528bcef2a7e5ac4bd73f81f87
Subproject commit 95b69d2641f50c48862941f425c007b1ed243259