Skip to content

Commit

Permalink
allow vm reader eof error to avoid hard-fork in testnet (#1092)
Browse files Browse the repository at this point in the history
  • Loading branch information
laizy authored Oct 11, 2019
1 parent 2848bcd commit 5709315
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 14 deletions.
3 changes: 2 additions & 1 deletion core/store/ledgerstore/ledger_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,8 @@ func (this *LedgerStoreImp) saveBlock(block *types.Block, stateMerkleRoot common
}

if result.MerkleRoot != stateMerkleRoot {
return errors.NewErr("state merkle root mismatch!")
return fmt.Errorf("state merkle root mismatch. expected: %s, got: %s",
result.MerkleRoot.ToHexString(), stateMerkleRoot.ToHexString())
}

return this.submitBlock(block, result)
Expand Down
1 change: 1 addition & 0 deletions smartcontract/smart_contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ func NewVmFeatureFlag(blockHeight uint32) vm.VmFeatureFlag {
var feature vm.VmFeatureFlag
enableHeight := config.GetOpcodeUpdateCheckHeight(config.DefConfig.P2PNode.NetworkId)
feature.DisableHasKey = blockHeight <= enableHeight
feature.AllowReaderEOF = blockHeight <= enableHeight

return feature
}
Expand Down
24 changes: 14 additions & 10 deletions vm/neovm/execution_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,18 @@ type ExecutionContext struct {
Code []byte
OpReader *utils.VmReader
InstructionPointer int
vmFlags VmFeatureFlag
}

func NewExecutionContext(code []byte) *ExecutionContext {
var executionContext ExecutionContext
executionContext.Code = code
executionContext.OpReader = utils.NewVmReader(code)
executionContext.InstructionPointer = 0
return &executionContext
func NewExecutionContext(code []byte, flag VmFeatureFlag) *ExecutionContext {
var context ExecutionContext
context.Code = code
context.OpReader = utils.NewVmReader(code)
context.OpReader.AllowEOF = flag.AllowReaderEOF
context.vmFlags = flag

context.InstructionPointer = 0
return &context
}

func (ec *ExecutionContext) GetInstructionPointer() int {
Expand All @@ -62,8 +66,8 @@ func (self *ExecutionContext) ReadOpCode() (val OpCode, eof bool) {
}

func (ec *ExecutionContext) Clone() *ExecutionContext {
executionContext := NewExecutionContext(ec.Code)
executionContext.InstructionPointer = ec.InstructionPointer
_ = executionContext.SetInstructionPointer(int64(ec.GetInstructionPointer()))
return executionContext
context := NewExecutionContext(ec.Code, ec.vmFlags)
context.InstructionPointer = ec.InstructionPointer
_ = context.SetInstructionPointer(int64(ec.GetInstructionPointer()))
return context
}
5 changes: 3 additions & 2 deletions vm/neovm/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@ import (
)

type VmFeatureFlag struct {
DisableHasKey bool // disable haskey, dcall, values opcode
DisableHasKey bool // disable haskey, dcall, values opcode
AllowReaderEOF bool // allow VmReader.ReadBytes got EOF and return 0 bytes
}

func NewExecutor(code []byte, feature VmFeatureFlag) *Executor {
var engine Executor
engine.EvalStack = NewValueStack(STACK_LIMIT)
engine.AltStack = NewValueStack(STACK_LIMIT)
context := NewExecutionContext(code)
context := NewExecutionContext(code, feature)
engine.Context = context
engine.State = BREAK
engine.Features = feature
Expand Down
9 changes: 8 additions & 1 deletion vm/neovm/utils/vm_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
type VmReader struct {
reader *bytes.Reader
BaseStream []byte
AllowEOF bool // allow VmReader.ReadBytes got EOF and return 0 bytes
}

func NewVmReader(b []byte) *VmReader {
Expand All @@ -43,10 +44,16 @@ func (r *VmReader) ReadByte() (byte, error) {

func (r *VmReader) ReadBytes(count int) ([]byte, error) {
// first check to avoid memory attack
if r.reader.Len() < count {
amount := r.reader.Len()
if r.AllowEOF {
amount = 1 * 1024 * 1024
}
if amount < count {
return nil, io.EOF
}
b := make([]byte, count)
// when reader does not has enough bytes, it will return the actual length and error is nil
// this is a bug previously(it should use io.ReadFull), but we have to keep it to avoid hard fork
_, err := r.reader.Read(b)
if err != nil {
return nil, err
Expand Down

0 comments on commit 5709315

Please sign in to comment.