Merge remote-tracking branch 'remotes/origin/master' into geth-upgrade-1.8.18

# Conflicts:
#	consensus/ethash/consensus.go
#	eth/bloombits.go
#	params/protocol_params.go
This commit is contained in:
amalraj.manigmail.com 2019-01-25 22:24:03 +08:00
commit 2914b3c99d
27 changed files with 533 additions and 84 deletions

37
.bintray.json Normal file
View File

@ -0,0 +1,37 @@
{
"package": {
"name": "geth",
"repo": "quorum",
"subject": "_ORGANIZATION_",
"vcs_url": "https://github.com/jpmorganchase/quorum",
"licenses": [
"LGPL-3.0"
]
},
"version": {
"name": "_TRAVIS_TAG_",
"desc": "Quorum: _TRAVIS_TAG_, Geth: _GETH_VERSION_, Commit: _TRAVIS_COMMIT_, Build Number: _TRAVIS_BUILD_NUMBER_",
"released": "_RELEASED_DATE_",
"vcs_tag": "_TRAVIS_TAG_",
"gpgSign": true,
"attributes": [
{
"name": "Travis",
"values": [
"_TRAVIS_JOB_WEB_URL_"
],
"type": "string"
}
]
},
"files": [
{
"includePattern": "/dist/(.*.tar.gz)",
"uploadPattern": "_TRAVIS_TAG_/$1",
"matrixParams": {
"override": 1
}
}
],
"publish": true
}

View File

@ -2,27 +2,94 @@
language: go
go_import_path: github.com/ethereum/go-ethereum
sudo: false
go: 1.9.x
sudo: true
branches:
only:
- /.*/ # everything including tags
env:
global:
- BINTRAY_ORGANIZATION=quorumengineering
- BINTRAY_USER=quorumbot
# Bintray API Key
- secure: "QHiPcd3zQoJEsT3VSpxoLVTYwbiYzS8H18EpY7Tk0EqCIfswS2AvRlyRXUxNvCf9ktzpaeXV4b5cPYJ67dwdp5V/O/ARaK5AL6ZjjrTPR1avPnmz/X2VeQEP0aWk1UGMs1nBUj5rzMbIIxlVhpbiITTLAI4Ao0+xRcBi215mDbv271Z7mACEZfXxjaoJA0/3IkbKz9pu1nC7bTjaaExCDAeLp2p8fHi2YQPnBll/7dkn/m1rnsIY9M3KWNCx6xBmQOr1hulrrB6tZoHwFBoDsVTFJFLckPfrWUZsYUgtfWJMQWc6ntv1gFl0f9x6s5fYEphCU2m1JYjEczlQ03B5ro9EyPGKjO7vQxAaFd5nVd2Xf34ZbssEIyXxlSnP/4Gv1GXl9L9aU1Hth9ckYvT5gYP5t/Nw3CDbKD0HelPBvkf8jZwfdlotzFPS2bOZNdl/rJLWgQrX18a/mC3BH9l4TSRz13tbRfo6YcC3Y/uOvG1n4GxzcVaWojAxn86SkknOczPTf2pk9F3JOcGVSYA2R4kGQAe+ErJH2X5g2sh1D5cCYDjQyl5rzWg6P3eK//HYW+mg2+TQ8k2iQVVSwFwrR0Yn4P+5cRDCW9mjtktgq1rTtslj41gSH49Avqr9oXGM2rqdcJPdN8dnmLMrAtmeSUNMMoexiRMmlF2OQKLrW3k="
matrix:
include:
- os: linux
dist: trusty
sudo: required
go: 1.9.x
- if: tag IS blank
os: linux
dist: xenial
script:
- sudo modprobe fuse
- sudo chmod 666 /dev/fuse
- sudo chown root:$USER /etc/fuse.conf
- go run build/ci.go install
- go run build/ci.go test -coverage $TEST_PACKAGES
- os: osx
- if: tag IS blank
os: osx
osx_image: xcode9.2 # so we don't have to deal with Kernel Extension Consent UI which is never possible in CI
go: 1.9.x
sudo: required
script:
- brew update
- brew install caskroom/cask/brew-cask
- brew cask install osxfuse
- go run build/ci.go install
- go run build/ci.go test -coverage $TEST_PACKAGES
- if: tag IS present
os: linux
dist: xenial
env: OUTPUT_FILE=geth_${TRAVIS_TAG}_linux_amd64.tar.gz
script:
- build/env.sh go run build/ci.go install ./cmd/geth
- sudo mkdir -p /dist
- cd build/bin
- sudo tar cfvz /dist/${OUTPUT_FILE} geth
- if: tag IS present
os: osx
osx_image: xcode9.2
env: OUTPUT_FILE=geth_${TRAVIS_TAG}_darwin_amd64.tar.gz
script:
- build/env.sh go run build/ci.go install ./cmd/geth
- sudo mkdir -p /dist
- cd build/bin
- sudo tar cfvz /dist/${OUTPUT_FILE} geth
before_deploy:
- |
echo "Prepare Bintray descriptor"
export GETH_VERSION=$(cat ${TRAVIS_BUILD_DIR}/VERSION)
export RELEASED_DATE=$(date +'%Y-%m-%d')
sed -e "s/_TRAVIS_TAG_/${TRAVIS_TAG}/g" \
-e "s/_TRAVIS_BUILD_NUMBER_/${TRAVIS_BUILD_NUMBER}/g" \
-e "s/_GETH_VERSION_/${GETH_VERSION}/g" \
-e "s/_RELEASED_DATE_/${RELEASED_DATE}/g" \
-e "s/_TRAVIS_COMMIT_/${TRAVIS_COMMIT}/g" \
-e "s/_TRAVIS_JOB_WEB_URL_/${TRAVIS_JOB_WEB_URL//\//\\/}/g" \
-e "s/_ORGANIZATION_/${BINTRAY_ORGANIZATION}/g" \
${TRAVIS_BUILD_DIR}/.bintray.json > /tmp/bintray.json
after_deploy:
- |
published=""
while [ "$published" == "" ]; do
echo "Sleep 5s to wait until ${OUTPUT_FILE} is published"
sleep 5
result=$(curl -u ${BINTRAY_USER}:${BINTRAY_API_KEY} "https://api.bintray.com/packages/${BINTRAY_ORGANIZATION}/quorum/geth/versions/${TRAVIS_TAG}/files")
echo "$result"
if [[ "$result" == *"${OUTPUT_FILE}"* ]]; then
published="done"
fi
done
- |
echo "Add ${OUTPUT_FILE} to Download List"
curl -u ${BINTRAY_USER}:${BINTRAY_API_KEY} \
-H "Content-type: application/json" \
-X PUT \
--data "{\"list_in_downloads\": true}" \
https://api.bintray.com/file_metadata/${BINTRAY_ORGANIZATION}/quorum/${TRAVIS_TAG}/${OUTPUT_FILE}
deploy:
provider: bintray
file: /tmp/bintray.json
user: ${BINTRAY_USER}
key: ${BINTRAY_API_KEY}
skip_cleanup: true
on:
tags: true

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 {
@ -60,53 +110,3 @@ func (env *EVM) Pop() {
Note the invariant that `StateDB` always points to the current state db.
The other interesting note is read only mode. Any time we call from the private state into the public state (`env.privateState != statedb`), we require anything deeper to be *read only*. Private state transactions can't affect public state, so we throw an EVM exception on any mutating operation (`SELFDESTRUCT, CREATE, SSTORE, LOG0, LOG1, LOG2, LOG3, LOG4`). Question: have any more mutating operations been added? Question: could we not mutate deeper private state?
Original commit explanation:
```
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.
```

View File

@ -1,7 +1,8 @@
# <img src="logo.png" width="100" height="100"/>
# <img src="https://raw.githubusercontent.com/jpmorganchase/quorum/master/logo.png" width="100" height="100"/>
<a href="https://clh7rniov2.execute-api.us-east-1.amazonaws.com/Express/" target="_blank" rel="noopener"><img title="Quorum Slack" src="https://clh7rniov2.execute-api.us-east-1.amazonaws.com/Express/badge.svg" alt="Quorum Slack" /></a>
[![Build Status](https://travis-ci.org/jpmorganchase/quorum.svg?branch=master)](https://travis-ci.org/jpmorganchase/quorum)
[![Download](https://api.bintray.com/packages/quorumengineering/quorum/geth/images/download.svg)](https://bintray.com/quorumengineering/quorum/geth/_latestVersion)
Quorum is an Ethereum-based distributed ledger protocol with transaction/contract privacy and new consensus mechanisms.
@ -42,8 +43,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

@ -871,17 +871,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

@ -301,9 +301,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

@ -257,7 +257,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
ret, st.gas, vmerr = evm.Call(sender, to, data, st.gas, st.value)
}
if vmerr != nil {
log.Debug("VM returned with error", "err", vmerr)
log.Info("VM returned with error", "err", vmerr)
// The only possible consensus-error would be if there wasn't
// sufficient balance to make the transfer happen. The first
// balance transfer may never fail.

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

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

@ -374,6 +374,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
@ -381,20 +382,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, true)
if err != nil {
evm.StateDB.RevertToSnapshot(snapshot)
stateDb.RevertToSnapshot(snapshot)
if err != errExecutionReverted {
contract.UseGas(contract.Gas)
}

View File

@ -204,7 +204,6 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
// 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

@ -153,7 +153,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

@ -421,12 +421,13 @@ func (s *Ethereum) shouldPreserve(block *types.Block) bool {
// SetEtherbase sets the mining reward address.
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

@ -115,10 +115,14 @@ func (b *BloomIndexer) Reset(ctx context.Context, section uint64, lastSectionHea
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(ctx context.Context, header *types.Header) error {
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()
return nil
}

View File

@ -1174,6 +1174,11 @@ type SendTxArgs struct {
//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,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).
//

View File

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

@ -18,7 +18,17 @@ package params
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,7 +27,7 @@ const (
VersionMeta = "stable" // Version metadata to append to the version string
QuorumVersionMajor = 2
QuorumVersionMinor = 1
QuorumVersionMinor = 2
QuorumVersionPatch = 1
)

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