Skip to content

Commit

Permalink
Merge pull request #679 from klaytn/release/v1.5.2
Browse files Browse the repository at this point in the history
[Master] release/v1.5.2 QA Sign-off
  • Loading branch information
KimKyungup committed Sep 22, 2020
2 parents 3d70fd0 + b1713ed commit 6e8ebe1
Show file tree
Hide file tree
Showing 165 changed files with 9,492 additions and 637 deletions.
18 changes: 16 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ executors:
docker:
- image: klaytn/build_base:1.1-go1.14.6-solc0.4.24
- image: localstack/localstack:0.10.9
- image: circleci/mysql:5.7
rpm-executor:
working_directory: /go/src/github.com/klaytn/klaytn
docker:
Expand Down Expand Up @@ -251,16 +252,28 @@ jobs:
test-linter:
executor: test-executor
steps:
- install-ssh-alpine
- checkout
- run:
name: "Run golangci-lint"
command: golangci-lint run --new-from-rev=dev --presets format,style -v --timeout 10m
command: golangci-lint run --new-from-rev=dev --presets complexity,format,performance -v --timeout 10m

test-datasync:
executor: test-executor
executor: test-others-executor
steps:
- install-ssh-alpine
- checkout
- run:
# Our primary container isn't MYSQL so run a sleep command until it's ready.
name: "Waiting for MySQL to be ready"
command: |
for i in `seq 1 10`;
do
nc -z 127.0.0.1 3306 && echo Success && exit 0
echo -n .
sleep 1
done
echo Failed waiting for MySQL && exit 1
- run:
name: "Run test datasync"
command: make test-datasync
Expand Down Expand Up @@ -481,6 +494,7 @@ workflows:
- test-others
- tag-verify
- tagger-verify
- test-linter
filters: *filter-version-not-release

- tag-verify:
Expand Down
3 changes: 2 additions & 1 deletion .circleci/scripts/build_announce.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ set -euox
VERSION=$(go run build/rpm/main.go version)~${CIRCLE_TAG##*-}

SHORT_SHA1=${CIRCLE_SHA1:0:7}
CIRCLE_PR_NUMBER=$(hub pr list -s open -L 10 -f "%I")
CIRCLE_PR=$(hub pr list -s open -L 10 -f "%I %sH %n" | grep $CIRCLE_SHA1)
CIRCLE_PR_NUMBER=${CIRCLE_PR%% *}

PACKAGES="kcn kpn ken kscn kspn ksen kbn kgen homi"
BAOBAB_PACKAGES="kcn kpn ken"
Expand Down
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# @global-owner1 and @global-owner2 will be requested for
# review when someone opens a pull request.
#* @global-owner1 @global-owner2
* @kjhman21 @KimKyungup @aidan-kwon @ehnuje @jeongkyun-oh @winnie-byun
* @kjhman21 @KimKyungup @aidan-kwon @ehnuje @jeongkyun-oh @winnie-byun @yoomee1313

# Order is important; the last matching pattern takes the most
# precedence. When someone opens a pull request that only
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ ARG PKG_DIR
ARG KLAYTN_RACE_DETECT=0
ENV KLAYTN_RACE_DETECT=$KLAYTN_RACE_DETECT

ARG KLAYTN_STATIC_LINK=1
ARG KLAYTN_STATIC_LINK=0
ENV KLAYTN_STATIC_LINK=$KLAYTN_STATIC_LINK

ARG KLAYTN_DISABLE_SYMBOL=0
Expand Down
4 changes: 0 additions & 4 deletions api/api_public_transaction_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,10 +296,6 @@ func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c
//submitTxCount++
//log.Error("### submitTransaction","tx",submitTxCount)

if tx.Type().IsRPCExcluded() {
return common.Hash{}, fmt.Errorf("%s cannot be submitted via RPC!", tx.Type().String())
}

if err := b.SendTx(ctx, tx); err != nil {
return common.Hash{}, err
}
Expand Down
70 changes: 52 additions & 18 deletions blockchain/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,16 @@ package blockchain
import (
"errors"
"fmt"
"github.com/hashicorp/golang-lru"
"io"
"math/big"
mrand "math/rand"
"reflect"
"strconv"
"sync"
"sync/atomic"
"time"

lru "github.com/hashicorp/golang-lru"
"github.com/klaytn/klaytn/blockchain/state"
"github.com/klaytn/klaytn/blockchain/types"
"github.com/klaytn/klaytn/blockchain/vm"
Expand All @@ -39,14 +48,6 @@ import (
"github.com/klaytn/klaytn/storage/statedb"
"github.com/rcrowley/go-metrics"
"gopkg.in/karalabe/cookiejar.v2/collections/prque"
"io"
"math/big"
mrand "math/rand"
"reflect"
"strconv"
"sync"
"sync/atomic"
"time"
)

var (
Expand Down Expand Up @@ -1609,7 +1610,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty
start := time.Now()

// Process block using the parent state as reference point.
receipts, logs, usedGas, err := bc.processor.Process(block, stateDB, bc.vmConfig)
receipts, logs, usedGas, internalTxTraces, err := bc.processor.Process(block, stateDB, bc.vmConfig)
if err != nil {
bc.reportBlock(block, receipts, err)
return i, events, coalescedLogs, err
Expand Down Expand Up @@ -1645,7 +1646,13 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty
"txs", len(block.Transactions()), "gas", block.GasUsed(), "elapsed", common.PrettyDuration(time.Since(bstart)))

coalescedLogs = append(coalescedLogs, logs...)
events = append(events, ChainEvent{block, block.Hash(), logs})
events = append(events, ChainEvent{
Block: block,
Hash: block.Hash(),
Logs: logs,
Receipts: receipts,
InternalTxTraces: internalTxTraces,
})
lastCanon = block

case SideStatTy:
Expand Down Expand Up @@ -2097,7 +2104,7 @@ func (bc *BlockChain) GetNonceInCache(addr common.Address) (uint64, bool) {
// and uses the input parameters for its environment. It returns the receipt
// for the transaction, gas used and an error if the transaction failed,
// indicating the block was invalid.
func (bc *BlockChain) ApplyTransaction(config *params.ChainConfig, author *common.Address, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg *vm.Config) (*types.Receipt, uint64, error) {
func (bc *BlockChain) ApplyTransaction(chainConfig *params.ChainConfig, author *common.Address, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, vmConfig *vm.Config) (*types.Receipt, uint64, *vm.InternalTxTrace, error) {

// TODO-Klaytn We reject transactions with unexpected gasPrice and do not put the transaction into TxPool.
// And we run transactions regardless of gasPrice if we push transactions in the TxPool.
Expand All @@ -2112,23 +2119,32 @@ func (bc *BlockChain) ApplyTransaction(config *params.ChainConfig, author *commo

// validation for each transaction before execution
if err := tx.Validate(statedb, blockNumber); err != nil {
return nil, 0, err
return nil, 0, nil, err
}

msg, err := tx.AsMessageWithAccountKeyPicker(types.MakeSigner(config, header.Number), statedb, blockNumber)
msg, err := tx.AsMessageWithAccountKeyPicker(types.MakeSigner(chainConfig, header.Number), statedb, blockNumber)
if err != nil {
return nil, 0, err
return nil, 0, nil, err
}
// Create a new context to be used in the EVM environment
context := NewEVMContext(msg, header, bc, author)
// Create a new environment which holds all relevant information
// about the transaction and calling mechanisms.
vmenv := vm.NewEVM(context, statedb, config, cfg)
vmenv := vm.NewEVM(context, statedb, chainConfig, vmConfig)
// Apply the transaction to the current state (included in the env)
_, gas, kerr := ApplyMessage(vmenv, msg)
err = kerr.ErrTxInvalid
if err != nil {
return nil, 0, err
return nil, 0, nil, err
}

var internalTrace *vm.InternalTxTrace
if vmConfig.EnableInternalTxTracing {
internalTrace, err = GetInternalTxTrace(vmConfig.Tracer)
if err != nil {
logger.Error("failed to get tracing result from a transaction", "txHash", tx.Hash().String(), "err", err)
return nil, 0, nil, err
}
}
// Update the state with pending changes
statedb.Finalise(true, false)
Expand All @@ -2141,7 +2157,25 @@ func (bc *BlockChain) ApplyTransaction(config *params.ChainConfig, author *commo
receipt.Logs = statedb.GetLogs(tx.Hash())
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})

return receipt, gas, err
return receipt, gas, internalTrace, err
}

func GetInternalTxTrace(tracer vm.Tracer) (*vm.InternalTxTrace, error) {
var (
internalTxTrace *vm.InternalTxTrace
err error
)
switch tracer := tracer.(type) {
case *vm.InternalTxTracer:
internalTxTrace, err = tracer.GetResult()
if err != nil {
return nil, err
}
default:
logger.Error("To trace internal transactions, VM tracer type should be vm.InternalTxTracer", "actualType", reflect.TypeOf(tracer).String())
return nil, ErrInvalidTracer
}
return internalTxTrace, nil
}

// CheckBlockChainVersion checks the version of the current database and upgrade if possible.
Expand Down
131 changes: 129 additions & 2 deletions blockchain/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@
package blockchain

import (
"crypto/ecdsa"
"fmt"
"github.com/stretchr/testify/assert"
"math/big"
"math/rand"
"strings"
"sync"
"testing"
"time"

"github.com/klaytn/klaytn/accounts/abi"
"github.com/stretchr/testify/assert"

"github.com/klaytn/klaytn/blockchain/state"
"github.com/klaytn/klaytn/blockchain/types"
"github.com/klaytn/klaytn/blockchain/vm"
Expand Down Expand Up @@ -156,7 +160,7 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
if err != nil {
return err
}
receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb, vm.Config{})
receipts, _, usedGas, _, err := blockchain.Processor().Process(block, statedb, vm.Config{})
if err != nil {
blockchain.reportBlock(block, receipts, err)
return err
Expand Down Expand Up @@ -1438,3 +1442,126 @@ func TestCheckBlockChainVersion(t *testing.T) {
assert.Error(t, CheckBlockChainVersion(memDB))
assert.Equal(t, uint64(BlockChainVersion+1), *memDB.ReadDatabaseVersion())
}

// the compiled code and abi is generated by contracts/internal_tx_contract/internal_tx_contract.sol
var testCode = "60806040526101ca806100136000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806312065fe01461005c578063b4ebea9914610087578063b6b55f25146100da575b600080fd5b34801561006857600080fd5b506100716100fa565b6040518082815260200191505060405180910390f35b34801561009357600080fd5b506100d8600480360381019080803563ffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610119565b005b6100f86004803603810190808035906020019092919050505061018d565b005b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b60008090505b8263ffffffff168163ffffffff161015610188578173ffffffffffffffffffffffffffffffffffffffff166108fc60019081150290604051600060405180830381858888f1935050505015801561017a573d6000803e3d6000fd5b50808060010191505061011f565b505050565b803414151561019b57600080fd5b505600a165627a7a72305820ee29ede1bae5608d4c660a11196b4846247aedee2657207fd39c7d736882e1400029"
var testAbiStr = `[{"constant":true,"inputs":[],"name":"getBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"times","type":"uint32"},{"name":"receiver","type":"address"}],"name":"sendKlay","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"inputs":[],"payable":true,"stateMutability":"payable","type":"constructor"}]`

func genInternalTxTransaction(t *testing.T, block *BlockGen, address common.Address, signer types.Signer, key *ecdsa.PrivateKey) {
// 1. Deploy internal transaction sample contract
nonce := block.TxNonce(address)
amount := new(big.Int).SetUint64(100000000)
gasLimit := big.NewInt(500000).Uint64()
gasPrice := big.NewInt(25000)

values := map[types.TxValueKeyType]interface{}{
types.TxValueKeyNonce: nonce,
types.TxValueKeyAmount: amount,
types.TxValueKeyGasLimit: gasLimit,
types.TxValueKeyGasPrice: gasPrice,
types.TxValueKeyHumanReadable: false,
types.TxValueKeyTo: (*common.Address)(nil),
types.TxValueKeyCodeFormat: params.CodeFormatEVM,
types.TxValueKeyFrom: address,
types.TxValueKeyData: common.Hex2Bytes(testCode),
}
tx, err := types.NewTransactionWithMap(types.TxTypeSmartContractDeploy, values)
assert.Nil(t, err)

err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{key})
assert.Nil(t, err)

block.AddTx(tx)

contractAddr := crypto.CreateAddress(address, nonce)

// 2. Contract Execution
abii, err := abi.JSON(strings.NewReader(testAbiStr))
assert.Equal(t, nil, err)

// the contract method "sendKlay" send 1 peb to address 3 times
data, err := abii.Pack("sendKlay", uint32(3), address)
assert.Equal(t, nil, err)

values = map[types.TxValueKeyType]interface{}{
types.TxValueKeyNonce: block.TxNonce(address),
types.TxValueKeyFrom: address,
types.TxValueKeyTo: contractAddr,
types.TxValueKeyAmount: big.NewInt(0),
types.TxValueKeyGasLimit: gasLimit,
types.TxValueKeyGasPrice: gasPrice,
types.TxValueKeyData: data,
}
tx, err = types.NewTransactionWithMap(types.TxTypeSmartContractExecution, values)
assert.Equal(t, nil, err)

err = tx.SignWithKeys(signer, []*ecdsa.PrivateKey{key})
assert.NoError(t, err)

block.AddTx(tx)
}

// TestCallTraceChainEventSubscription tests if the method insertChain posts a chain event correctly.
// Scenario:
// 1. Deploy a contract
// sendKlay(n uint32, receiver address): send 1 peb to `receiver` address `n` times.
// 2. Send a smart contract execution transaction
func TestCallTraceChainEventSubscription(t *testing.T) {
// configure and generate a sample block chain
var (
gendb = database.NewMemoryDBManager()
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(100000000000000000)
testGenesis = &Genesis{
Config: params.TestChainConfig,
Alloc: GenesisAlloc{address: {Balance: funds}},
}
genesis = testGenesis.MustCommit(gendb)
signer = types.NewEIP155Signer(testGenesis.Config.ChainID)
)
db := database.NewMemoryDBManager()
testGenesis.MustCommit(db)

// create new blockchain with enabled internal tx tracing option
blockchain, _ := NewBlockChain(db, nil, testGenesis.Config, gxhash.NewFaker(), vm.Config{Debug: true, EnableInternalTxTracing: true})
defer blockchain.Stop()

// subscribe a new chain event channel
chainEventCh := make(chan ChainEvent, 1)
subscription := blockchain.SubscribeChainEvent(chainEventCh)
defer subscription.Unsubscribe()

// generate blocks
blocks, _ := GenerateChain(testGenesis.Config, genesis, gxhash.NewFaker(), gendb, 1, func(i int, block *BlockGen) {
// Deploy a contract which can trigger internal transactions
genInternalTxTransaction(t, block, address, signer, key)
})

// insert the generated blocks into the test chain
if n, err := blockchain.InsertChain(blocks); err != nil {
t.Fatalf("failed to process block %d: %v", n, err)
}

timer := time.NewTimer(1 * time.Second)
defer timer.Stop()
// compare the published chain event with the expected test data
select {
case <-timer.C:
t.Fatal("Timeout. There is no chain event posted for 1 second")
case ev := <-chainEventCh:
// a contract deploy tx and a contract execution tx
assert.Equal(t, 2, len(ev.InternalTxTraces))

// compare contract deploy result
assert.Equal(t, address, *ev.InternalTxTraces[0].From)
assert.Equal(t, 0, len(ev.InternalTxTraces[0].Calls))
assert.Equal(t, "0x"+testCode, ev.InternalTxTraces[0].Input)
assert.Equal(t, fmt.Sprintf("0x%x", 100000000), ev.InternalTxTraces[0].Value)

// compare contract execution result
assert.Equal(t, address, *ev.InternalTxTraces[1].From)
assert.Equal(t, 3, len(ev.InternalTxTraces[1].Calls))
assert.Equal(t, fmt.Sprintf("0x%x", 0), ev.InternalTxTraces[1].Value)
}
}
2 changes: 1 addition & 1 deletion blockchain/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (b *BlockGen) AddTx(tx *types.Transaction) {
// the block in chain will be returned.
func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) {
b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs))
receipt, _, err := bc.ApplyTransaction(b.config, &params.AuthorAddressForTesting, b.statedb, b.header, tx, &b.header.GasUsed, &vm.Config{})
receipt, _, _, err := bc.ApplyTransaction(b.config, &params.AuthorAddressForTesting, b.statedb, b.header, tx, &b.header.GasUsed, &vm.Config{})
if err != nil {
panic(err)
}
Expand Down
3 changes: 3 additions & 0 deletions blockchain/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,7 @@ var (

// ErrAccountCreationPrevented is returned if account creation is inserted in the service chain's txpool.
ErrAccountCreationPrevented = errors.New("account creation is prevented for the service chain")

// ErrInvalidTracer is returned if the tracer type is not vm.InternalTxTracer
ErrInvalidTracer = errors.New("tracer type is invalid for internal transaction tracing")
)
Loading

0 comments on commit 6e8ebe1

Please sign in to comment.