aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorJhih-Ming Huang <jm@byzantine-lab.io>2019-06-19 17:49:27 +0800
committerWei-Ning Huang <w@byzantine-lab.io>2019-09-17 16:57:30 +0800
commitc3c6574c9053a361bfe4f77bf4e1ae99d19f60dc (patch)
tree1a2b1db4b51bb084b5340d9875b968aaee87976c /core
parentaa9c5b22941aadfefcde64d2570d6c6863bc2ebe (diff)
downloadgo-tangerine-c3c6574c9053a361bfe4f77bf4e1ae99d19f60dc.tar
go-tangerine-c3c6574c9053a361bfe4f77bf4e1ae99d19f60dc.tar.gz
go-tangerine-c3c6574c9053a361bfe4f77bf4e1ae99d19f60dc.tar.bz2
go-tangerine-c3c6574c9053a361bfe4f77bf4e1ae99d19f60dc.tar.lz
go-tangerine-c3c6574c9053a361bfe4f77bf4e1ae99d19f60dc.tar.xz
go-tangerine-c3c6574c9053a361bfe4f77bf4e1ae99d19f60dc.tar.zst
go-tangerine-c3c6574c9053a361bfe4f77bf4e1ae99d19f60dc.zip
core: vm: remove opRand and use oracle contract to get random number
Diffstat (limited to 'core')
-rw-r--r--core/vm/evm.go2
-rw-r--r--core/vm/instructions.go24
-rw-r--r--core/vm/jump_table.go6
-rw-r--r--core/vm/opcodes.go3
-rw-r--r--core/vm/oracle.go4
-rw-r--r--core/vm/oracle_contracts.go32
-rw-r--r--core/vm/oracle_contracts_test.go48
7 files changed, 85 insertions, 34 deletions
diff --git a/core/vm/evm.go b/core/vm/evm.go
index 84b98d7c2..ea370f11f 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -103,7 +103,7 @@ type Context struct {
Difficulty *big.Int // Provides information for DIFFICULTY
Round *big.Int // Current round number.
- RandCallIndex uint64 // Number of times opRand is called
+ RandCallIndex uint64 // Number of times RandomContract is called
}
// EVM is the Ethereum Virtual Machine base object and provides
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index b096bfdd4..587acf002 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -17,7 +17,6 @@
package vm
import (
- "encoding/binary"
"errors"
"fmt"
"math/big"
@@ -25,7 +24,6 @@ import (
"github.com/tangerine-network/go-tangerine/common"
"github.com/tangerine-network/go-tangerine/common/math"
"github.com/tangerine-network/go-tangerine/core/types"
- "github.com/tangerine-network/go-tangerine/crypto"
"github.com/tangerine-network/go-tangerine/params"
"golang.org/x/crypto/sha3"
)
@@ -410,28 +408,6 @@ func opSha3(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
return nil, nil
}
-func opRand(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- evm := interpreter.evm
-
- nonce := evm.StateDB.GetNonce(evm.Origin)
- binaryOriginNonce := make([]byte, binary.MaxVarintLen64)
- binary.PutUvarint(binaryOriginNonce, nonce)
-
- binaryUsedIndex := make([]byte, binary.MaxVarintLen64)
- binary.PutUvarint(binaryUsedIndex, evm.RandCallIndex)
-
- evm.RandCallIndex += 1
-
- hash := crypto.Keccak256(
- evm.Randomness,
- evm.Origin.Bytes(),
- binaryOriginNonce,
- binaryUsedIndex)
-
- stack.push(interpreter.intPool.get().SetBytes(hash))
- return nil, nil
-}
-
func opAddress(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
stack.push(contract.Address().Big())
return nil, nil
diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go
index c1b57ea89..ba11b57f3 100644
--- a/core/vm/jump_table.go
+++ b/core/vm/jump_table.go
@@ -301,12 +301,6 @@ func newFrontierInstructionSet() [256]operation {
memorySize: memorySha3,
valid: true,
},
- RAND: {
- execute: opRand,
- gasCost: constGasFunc(params.RandGas),
- validateStack: makeStackFunc(0, 1),
- valid: true,
- },
ADDRESS: {
execute: opAddress,
gasCost: constGasFunc(GasQuickStep),
diff --git a/core/vm/opcodes.go b/core/vm/opcodes.go
index 8762d4b43..4349ffd29 100644
--- a/core/vm/opcodes.go
+++ b/core/vm/opcodes.go
@@ -71,7 +71,6 @@ const (
SAR
SHA3 = 0x20
- RAND = 0x2f
)
// 0x30 range - closure state.
@@ -252,7 +251,6 @@ var opCodeToString = map[OpCode]string{
// 0x20 range - crypto.
SHA3: "SHA3",
- RAND: "RAND",
// 0x30 range - closure state.
ADDRESS: "ADDRESS",
@@ -422,7 +420,6 @@ var stringToOp = map[string]OpCode{
"ADDMOD": ADDMOD,
"MULMOD": MULMOD,
"SHA3": SHA3,
- "RAND": RAND,
"ADDRESS": ADDRESS,
"BALANCE": BALANCE,
"ORIGIN": ORIGIN,
diff --git a/core/vm/oracle.go b/core/vm/oracle.go
index b2dac4521..2e27983b5 100644
--- a/core/vm/oracle.go
+++ b/core/vm/oracle.go
@@ -25,6 +25,7 @@ import (
)
var GovernanceContractAddress = common.HexToAddress("63751838d6485578b23e8b051d40861ecc416794")
+var RandomContractAddress = common.HexToAddress("03C90084388Be8E088425DA9835F7f43F8a319c7")
var GovernanceABI *OracleContractABI
@@ -44,6 +45,9 @@ var OracleContracts = map[common.Address]func() OracleContract{
coreDKGUtils: &defaultCoreDKGUtils{},
}
},
+ RandomContractAddress: func() OracleContract {
+ return &RandomContract{}
+ },
}
// Run oracle contract.
diff --git a/core/vm/oracle_contracts.go b/core/vm/oracle_contracts.go
index 484ed82b8..7e245e6bd 100644
--- a/core/vm/oracle_contracts.go
+++ b/core/vm/oracle_contracts.go
@@ -19,6 +19,7 @@ package vm
import (
"bytes"
+ "encoding/binary"
"errors"
"fmt"
"math"
@@ -2952,3 +2953,34 @@ func PackResetDKG(newSignedCRS []byte) ([]byte, error) {
data := append(method.Id(), res...)
return data, nil
}
+
+// RandomContract provides access to on chain randomness.
+type RandomContract struct {
+ evm *EVM
+ contract *Contract
+}
+
+func (*RandomContract) Run(evm *EVM, input []byte,
+ contract *Contract) (ret []byte, err error) {
+ nonce := evm.StateDB.GetNonce(evm.Origin)
+
+ cost := params.RandGas
+ if !contract.UseGas(cost) {
+ return nil, ErrOutOfGas
+ }
+
+ binaryOriginNonce := make([]byte, binary.MaxVarintLen64)
+ binary.PutUvarint(binaryOriginNonce, nonce)
+
+ binaryUsedIndex := make([]byte, binary.MaxVarintLen64)
+ binary.PutUvarint(binaryUsedIndex, evm.RandCallIndex)
+
+ evm.RandCallIndex += 1
+
+ ret = crypto.Keccak256(
+ evm.Randomness,
+ evm.Origin.Bytes(),
+ binaryOriginNonce,
+ binaryUsedIndex)
+ return
+}
diff --git a/core/vm/oracle_contracts_test.go b/core/vm/oracle_contracts_test.go
index 33fdba886..ddd75810e 100644
--- a/core/vm/oracle_contracts_test.go
+++ b/core/vm/oracle_contracts_test.go
@@ -1247,3 +1247,51 @@ func (g *OracleContractsTestSuite) TestResetDKG() {
func TestOracleContracts(t *testing.T) {
suite.Run(t, new(OracleContractsTestSuite))
}
+
+type RandomContractTestSuite struct {
+ suite.Suite
+
+ context Context
+ stateDB *state.StateDB
+ config *params.DexconConfig
+}
+
+func (r *RandomContractTestSuite) SetupTest() {
+ memDB := ethdb.NewMemDatabase()
+ stateDB, err := state.New(common.Hash{}, state.NewDatabase(memDB))
+ if err != nil {
+ panic(err)
+ }
+ r.stateDB = stateDB
+ r.context = Context{
+ CanTransfer: func(db StateDB, addr common.Address, amount *big.Int) bool {
+ return db.GetBalance(addr).Cmp(amount) >= 0
+ },
+ Transfer: func(db StateDB, sender common.Address, recipient common.Address, amount *big.Int) {
+ db.SubBalance(sender, amount)
+ db.AddBalance(recipient, amount)
+ },
+ }
+ r.config = params.TestnetChainConfig.Dexcon
+}
+
+func (r *RandomContractTestSuite) TestRun() {
+ evm := NewEVM(r.context, r.stateDB, params.TestChainConfig,
+ Config{IsBlockProposer: true})
+ contractAddr := RandomContractAddress
+ caller := r.config.Owner
+ randCallIndex := evm.RandCallIndex
+
+ ret, _, err := evm.Call(AccountRef(caller), contractAddr, nil, 64, big.NewInt(0))
+ r.Require().Nil(err)
+ r.Require().Equal(randCallIndex+1, evm.RandCallIndex)
+ r.Require().NotNil(ret)
+
+ _, _, err = evm.Call(AccountRef(caller), contractAddr, nil, 63, big.NewInt(0))
+ r.Require().Equal(err, ErrOutOfGas)
+ r.Require().Equal(randCallIndex+1, evm.RandCallIndex)
+}
+
+func TestRandomContract(t *testing.T) {
+ suite.Run(t, new(RandomContractTestSuite))
+}