Skip to content

Commit

Permalink
Subnet evm geth v1.13.8 (ava-labs#550)
Browse files Browse the repository at this point in the history
* format as subnet-evm

* Add rules api (#1162)

* introduce e upgrade

* map upgrades

* check if upgrade is non-nil

* fix checkForks

* Fix tests

* revert test changes

* fix tests

* remove block no param from IsCancun

* add UT

* use avalanche defaults for timestamps

* sync API code from upstream

* add GetActiveRulesAt API

* use non-zero timestamps in genesis configs

* fix test timestamps

* add timestamp to ethapi genesis

* fix blockchain test genesis timestamp

* fix test

* review fixes

* fix deps

* use vmerrs

* mark TestExpDecaySampleNanosecondRegression flaky (#1163)

* sync geth v1.13.8 from subnet-evm

* format as coreth

* fix issues

* fix tests

* fix tests

* revert test to original

* comment out test

* comment out test

* bump avago dep

* rerun go mod tidy

* bump avago version to commit

* fix legacy lvls

* geth-v1.13.8 sync nits (ava-labs#553)

---------

Co-authored-by: Darioush Jalali <[email protected]>
  • Loading branch information
ceyonur and darioush authored May 15, 2024
1 parent 649f916 commit 40cd518
Show file tree
Hide file tree
Showing 196 changed files with 5,747 additions and 2,410 deletions.
1 change: 0 additions & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ run:
linters:
disable-all: true
enable:
- goconst
- goimports
- gosimple
- govet
Expand Down
2 changes: 1 addition & 1 deletion accounts/abi/abi.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ var revertSelector = crypto.Keccak256([]byte("Error(string)"))[:4]
var panicSelector = crypto.Keccak256([]byte("Panic(uint256)"))[:4]

// panicReasons map is for readable panic codes
// see this linkage for the deails
// see this linkage for the details
// https://docs.soliditylang.org/en/v0.8.21/control-structures.html#panic-via-assert-and-error-via-require
// the reason string list is copied from ether.js
// https://github.com/ethers-io/ethers.js/blob/fa3a883ff7c88611ce766f58bdd4b8ac90814470/src.ts/abi/interface.ts#L207-L218
Expand Down
24 changes: 24 additions & 0 deletions accounts/abi/abi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ var methods = map[string]Method{
}

func TestReader(t *testing.T) {
t.Parallel()
abi := ABI{
Methods: methods,
}
Expand Down Expand Up @@ -162,6 +163,7 @@ func TestReader(t *testing.T) {
}

func TestInvalidABI(t *testing.T) {
t.Parallel()
json := `[{ "type" : "function", "name" : "", "constant" : fals }]`
_, err := JSON(strings.NewReader(json))
if err == nil {
Expand All @@ -181,6 +183,7 @@ func TestInvalidABI(t *testing.T) {
// constructor(uint256 a, uint256 b) public{}
// }
func TestConstructor(t *testing.T) {
t.Parallel()
json := `[{ "inputs": [{"internalType": "uint256","name": "a","type": "uint256" },{ "internalType": "uint256","name": "b","type": "uint256"}],"stateMutability": "nonpayable","type": "constructor"}]`
method := NewMethod("", "", Constructor, "nonpayable", false, false, []Argument{{"a", Uint256, false}, {"b", Uint256, false}}, nil)
// Test from JSON
Expand Down Expand Up @@ -210,6 +213,7 @@ func TestConstructor(t *testing.T) {
}

func TestTestNumbers(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -247,6 +251,7 @@ func TestTestNumbers(t *testing.T) {
}

func TestMethodSignature(t *testing.T) {
t.Parallel()
m := NewMethod("foo", "foo", Function, "", false, false, []Argument{{"bar", String, false}, {"baz", String, false}}, nil)
exp := "foo(string,string)"
if m.Sig != exp {
Expand Down Expand Up @@ -285,6 +290,7 @@ func TestMethodSignature(t *testing.T) {
}

func TestOverloadedMethodSignature(t *testing.T) {
t.Parallel()
json := `[{"constant":true,"inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"i","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"}],"name":"bar","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"},{"indexed":false,"name":"j","type":"uint256"}],"name":"bar","type":"event"}]`
abi, err := JSON(strings.NewReader(json))
if err != nil {
Expand All @@ -308,6 +314,7 @@ func TestOverloadedMethodSignature(t *testing.T) {
}

func TestCustomErrors(t *testing.T) {
t.Parallel()
json := `[{ "inputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ],"name": "MyError", "type": "error"} ]`
abi, err := JSON(strings.NewReader(json))
if err != nil {
Expand All @@ -322,6 +329,7 @@ func TestCustomErrors(t *testing.T) {
}

func TestMultiPack(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -359,6 +367,7 @@ func ExampleJSON() {
}

func TestInputVariableInputLength(t *testing.T) {
t.Parallel()
const definition = `[
{ "type" : "function", "name" : "strOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" } ] },
{ "type" : "function", "name" : "bytesOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "bytes" } ] },
Expand Down Expand Up @@ -487,6 +496,7 @@ func TestInputVariableInputLength(t *testing.T) {
}

func TestInputFixedArrayAndVariableInputLength(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Error(err)
Expand Down Expand Up @@ -661,6 +671,7 @@ func TestInputFixedArrayAndVariableInputLength(t *testing.T) {
}

func TestDefaultFunctionParsing(t *testing.T) {
t.Parallel()
const definition = `[{ "name" : "balance", "type" : "function" }]`

abi, err := JSON(strings.NewReader(definition))
Expand All @@ -674,6 +685,7 @@ func TestDefaultFunctionParsing(t *testing.T) {
}

func TestBareEvents(t *testing.T) {
t.Parallel()
const definition = `[
{ "type" : "event", "name" : "balance" },
{ "type" : "event", "name" : "anon", "anonymous" : true},
Expand Down Expand Up @@ -750,6 +762,7 @@ func TestBareEvents(t *testing.T) {
//
// receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]}
func TestUnpackEvent(t *testing.T) {
t.Parallel()
const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]`
abi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
Expand Down Expand Up @@ -788,6 +801,7 @@ func TestUnpackEvent(t *testing.T) {
}

func TestUnpackEventIntoMap(t *testing.T) {
t.Parallel()
const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]`
abi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
Expand Down Expand Up @@ -838,6 +852,7 @@ func TestUnpackEventIntoMap(t *testing.T) {
}

func TestUnpackMethodIntoMap(t *testing.T) {
t.Parallel()
const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"send","outputs":[{"name":"amount","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"get","outputs":[{"name":"hash","type":"bytes"}],"payable":true,"stateMutability":"payable","type":"function"}]`
abi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
Expand Down Expand Up @@ -888,6 +903,7 @@ func TestUnpackMethodIntoMap(t *testing.T) {
}

func TestUnpackIntoMapNamingConflict(t *testing.T) {
t.Parallel()
// Two methods have the same name
var abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"get","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"send","outputs":[{"name":"amount","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"get","outputs":[{"name":"hash","type":"bytes"}],"payable":true,"stateMutability":"payable","type":"function"}]`
abi, err := JSON(strings.NewReader(abiJSON))
Expand Down Expand Up @@ -971,6 +987,7 @@ func TestUnpackIntoMapNamingConflict(t *testing.T) {
}

func TestABI_MethodById(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(jsondata))
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -1003,6 +1020,7 @@ func TestABI_MethodById(t *testing.T) {
}

func TestABI_EventById(t *testing.T) {
t.Parallel()
tests := []struct {
name string
json string
Expand Down Expand Up @@ -1069,6 +1087,7 @@ func TestABI_EventById(t *testing.T) {
}

func TestABI_ErrorByID(t *testing.T) {
t.Parallel()
abi, err := JSON(strings.NewReader(`[
{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"MyError1","type":"error"},
{"inputs":[{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"string","name":"b","type":"string"},{"internalType":"address","name":"c","type":"address"}],"internalType":"struct MyError.MyStruct","name":"x","type":"tuple"},{"internalType":"address","name":"y","type":"address"},{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"string","name":"b","type":"string"},{"internalType":"address","name":"c","type":"address"}],"internalType":"struct MyError.MyStruct","name":"z","type":"tuple"}],"name":"MyError2","type":"error"},
Expand Down Expand Up @@ -1099,6 +1118,7 @@ func TestABI_ErrorByID(t *testing.T) {
// TestDoubleDuplicateMethodNames checks that if transfer0 already exists, there won't be a name
// conflict and that the second transfer method will be renamed transfer1.
func TestDoubleDuplicateMethodNames(t *testing.T) {
t.Parallel()
abiJSON := `[{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"data","type":"bytes"}],"name":"transfer0","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"data","type":"bytes"},{"name":"customFallback","type":"string"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]`
contractAbi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
Expand Down Expand Up @@ -1128,6 +1148,7 @@ func TestDoubleDuplicateMethodNames(t *testing.T) {
// event send();
// }
func TestDoubleDuplicateEventNames(t *testing.T) {
t.Parallel()
abiJSON := `[{"anonymous": false,"inputs": [{"indexed": false,"internalType": "uint256","name": "a","type": "uint256"}],"name": "send","type": "event"},{"anonymous": false,"inputs": [],"name": "send0","type": "event"},{ "anonymous": false, "inputs": [],"name": "send","type": "event"}]`
contractAbi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
Expand Down Expand Up @@ -1155,6 +1176,7 @@ func TestDoubleDuplicateEventNames(t *testing.T) {
// event send(uint256, uint256);
// }
func TestUnnamedEventParam(t *testing.T) {
t.Parallel()
abiJSON := `[{ "anonymous": false, "inputs": [{ "indexed": false,"internalType": "uint256", "name": "","type": "uint256"},{"indexed": false,"internalType": "uint256","name": "","type": "uint256"}],"name": "send","type": "event"}]`
contractAbi, err := JSON(strings.NewReader(abiJSON))
if err != nil {
Expand Down Expand Up @@ -1188,7 +1210,9 @@ func TestUnpackRevert(t *testing.T) {
{"4e487b7100000000000000000000000000000000000000000000000000000000000000ff", "unknown panic code: 0xff", nil},
}
for index, c := range cases {
index, c := index, c
t.Run(fmt.Sprintf("case %d", index), func(t *testing.T) {
t.Parallel()
got, err := UnpackRevert(common.Hex2Bytes(c.input))
if c.expectErr != nil {
if err == nil {
Expand Down
4 changes: 2 additions & 2 deletions accounts/abi/argument.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func (arguments Arguments) isTuple() bool {
func (arguments Arguments) Unpack(data []byte) ([]interface{}, error) {
if len(data) == 0 {
if len(arguments.NonIndexed()) != 0 {
return nil, errors.New("abi: attempting to unmarshall an empty string while arguments are expected")
return nil, errors.New("abi: attempting to unmarshal an empty string while arguments are expected")
}
return make([]interface{}, 0), nil
}
Expand All @@ -105,7 +105,7 @@ func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte)
}
if len(data) == 0 {
if len(arguments.NonIndexed()) != 0 {
return errors.New("abi: attempting to unmarshall an empty string while arguments are expected")
return errors.New("abi: attempting to unmarshal an empty string while arguments are expected")
}
return nil // Nothing to unmarshal, return
}
Expand Down
4 changes: 2 additions & 2 deletions accounts/abi/bind/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func NewTransactor(keyin io.Reader, passphrase string) (*TransactOpts, error) {
}

// NewKeyStoreTransactor is a utility method to easily create a transaction signer from
// an decrypted key from a keystore.
// a decrypted key from a keystore.
//
// Deprecated: Use NewKeyStoreTransactorWithChainID instead.
func NewKeyStoreTransactor(keystore *keystore.KeyStore, account accounts.Account) (*TransactOpts, error) {
Expand Down Expand Up @@ -127,7 +127,7 @@ func NewTransactorWithChainID(keyin io.Reader, passphrase string, chainID *big.I
}

// NewKeyStoreTransactorWithChainID is a utility method to easily create a transaction signer from
// an decrypted key from a keystore.
// a decrypted key from a keystore.
func NewKeyStoreTransactorWithChainID(keystore *keystore.KeyStore, account accounts.Account, chainID *big.Int) (*TransactOpts, error) {
if chainID == nil {
return nil, ErrNoChainID
Expand Down
15 changes: 15 additions & 0 deletions accounts/abi/bind/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ var (
// on a backend that doesn't implement AcceptedContractCaller.
ErrNoAcceptedState = errors.New("backend does not support accepted state")

// ErrNoBlockHashState is raised when attempting to perform a block hash action
// on a backend that doesn't implement BlockHashContractCaller.
ErrNoBlockHashState = errors.New("backend does not support block hash state")

// ErrNoCodeAfterDeploy is returned by WaitDeployed if contract creation leaves
// an empty contract behind.
ErrNoCodeAfterDeploy = errors.New("no contract code after deployment")
Expand Down Expand Up @@ -74,6 +78,17 @@ type AcceptedContractCaller interface {
AcceptedCallContract(ctx context.Context, call interfaces.CallMsg) ([]byte, error)
}

// BlockHashContractCaller defines methods to perform contract calls on a specific block hash.
// Call will try to discover this interface when access to a block by hash is requested.
// If the backend does not support the block hash state, Call returns ErrNoBlockHashState.
type BlockHashContractCaller interface {
// CodeAtHash returns the code of the given account in the state at the specified block hash.
CodeAtHash(ctx context.Context, contract common.Address, blockHash common.Hash) ([]byte, error)

// CallContractAtHash executes an Ethereum contract call against the state at the specified block hash.
CallContractAtHash(ctx context.Context, call interfaces.CallMsg, blockHash common.Hash) ([]byte, error)
}

// ContractTransactor defines the methods needed to allow operating with a contract
// on a write only basis. Besides the transacting method, the remainder are helpers
// used when the user does not provide some needed values, but rather leaves it up
Expand Down
50 changes: 44 additions & 6 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ var (

var (
errBlockNumberUnsupported = errors.New("simulatedBackend cannot access blocks other than the latest block")
errBlockHashUnsupported = errors.New("simulatedBackend cannot access blocks by hash other than the latest block")
errBlockDoesNotExist = errors.New("block does not exist in blockchain")
errTransactionDoesNotExist = errors.New("transaction does not exist")
)
Expand Down Expand Up @@ -238,6 +239,24 @@ func (b *SimulatedBackend) CodeAt(ctx context.Context, contract common.Address,
return stateDB.GetCode(contract), nil
}

// CodeAtHash returns the code associated with a certain account in the blockchain.
func (b *SimulatedBackend) CodeAtHash(ctx context.Context, contract common.Address, blockHash common.Hash) ([]byte, error) {
b.mu.Lock()
defer b.mu.Unlock()

header, err := b.headerByHash(blockHash)
if err != nil {
return nil, err
}

stateDB, err := b.blockchain.StateAt(header.Root)
if err != nil {
return nil, err
}

return stateDB.GetCode(contract), nil
}

// BalanceAt returns the wei balance of a certain account in the blockchain.
func (b *SimulatedBackend) BalanceAt(ctx context.Context, contract common.Address, blockNumber *big.Int) (*big.Int, error) {
b.mu.Lock()
Expand Down Expand Up @@ -356,7 +375,11 @@ func (b *SimulatedBackend) blockByNumber(ctx context.Context, number *big.Int) (
func (b *SimulatedBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
b.mu.Lock()
defer b.mu.Unlock()
return b.headerByHash(hash)
}

// headerByHash retrieves a header from the database by hash without Lock.
func (b *SimulatedBackend) headerByHash(hash common.Hash) (*types.Header, error) {
if hash == b.acceptedBlock.Hash() {
return b.acceptedBlock.Header(), nil
}
Expand Down Expand Up @@ -472,6 +495,22 @@ func (b *SimulatedBackend) CallContract(ctx context.Context, call interfaces.Cal
if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number) != 0 {
return nil, errBlockNumberUnsupported
}
return b.callContractAtHead(ctx, call)
}

// CallContractAtHash executes a contract call on a specific block hash.
func (b *SimulatedBackend) CallContractAtHash(ctx context.Context, call interfaces.CallMsg, blockHash common.Hash) ([]byte, error) {
b.mu.Lock()
defer b.mu.Unlock()

if blockHash != b.blockchain.CurrentBlock().Hash() {
return nil, errBlockHashUnsupported
}
return b.callContractAtHead(ctx, call)
}

// callContractAtHead executes a contract call against the latest block state.
func (b *SimulatedBackend) callContractAtHead(ctx context.Context, call interfaces.CallMsg) ([]byte, error) {
stateDB, err := b.blockchain.State()
if err != nil {
return nil, err
Expand Down Expand Up @@ -622,7 +661,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call interfaces.Call
return 0, err
}
if failed {
if result != nil && result.Err != vmerrs.ErrOutOfGas {
if result != nil && !errors.Is(result.Err, vmerrs.ErrOutOfGas) {
if len(result.Revert()) > 0 {
return 0, newRevertError(result)
}
Expand All @@ -642,8 +681,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call interfaces.Cal
if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) {
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
}
head := b.blockchain.CurrentHeader()
if !b.blockchain.Config().IsApricotPhase3(head.Time) {
if !b.blockchain.Config().IsApricotPhase3(header.Time) {
// If there's no basefee, then it must be a non-1559 execution
if call.GasPrice == nil {
call.GasPrice = new(big.Int)
Expand All @@ -665,13 +703,13 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call interfaces.Cal
// Backfill the legacy gasPrice for EVM execution, unless we're all zeroes
call.GasPrice = new(big.Int)
if call.GasFeeCap.BitLen() > 0 || call.GasTipCap.BitLen() > 0 {
call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, head.BaseFee), call.GasFeeCap)
call.GasPrice = math.BigMin(new(big.Int).Add(call.GasTipCap, header.BaseFee), call.GasFeeCap)
}
}
}
// Ensure message is initialized properly.
if call.Gas == 0 {
call.Gas = 50000000
call.Gas = 10 * header.GasLimit
}
if call.Value == nil {
call.Value = new(big.Int)
Expand Down Expand Up @@ -846,7 +884,7 @@ func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error {
defer b.mu.Unlock()

if len(b.acceptedBlock.Transactions()) != 0 {
return errors.New("Could not adjust time on non-empty block")
return errors.New("could not adjust time on non-empty block")
}
block := b.blockchain.GetBlockByHash(b.acceptedBlock.ParentHash())
if block == nil {
Expand Down
Loading

0 comments on commit 40cd518

Please sign in to comment.