fabric icon indicating copy to clipboard operation
fabric copied to clipboard

there is no mechanisms to abort chaincode even if it has an infinite loop

Open sachikoy opened this issue 8 years ago • 5 comments

Description

If chaincode includes an infinite loop, it keeps running and there is no mechanism to abort chaincode. This happens both in invoke and query transactions. If an infinite loop is within a Query transaction, then the validating peer detects timeout. However, the chaincode docker container keeps running even after VP returns the error.

I think the validating peer should monitor the chaincode, and abort it when it is not responding for a pre-defined period of time.

Describe How to Reproduce

write an infinite loop within invoke or query transaction.

func (this *MyCode) simpleLoop(db *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
        this.logger = shim.NewLogger("MyCode")
        x := 0
        for  ; ; {
                this.logger.Infof("simpleLoop, count=%d", x)
                x++
        }
}
...
func (this *MyCode) Query(db *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
                return this.simpleLoop(db, function, args)
}
func (this *MyCode) Invoke(db *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
                return this.simpleLoop(db, function, args)
}

sachikoy avatar Jul 16 '16 08:07 sachikoy

How about we start thinking about how to sidestep an unsolvable problem and use a deterministic, terminating language instead?

corecode avatar Jul 18 '16 11:07 corecode

The peer needs to act like a hypervisor. There are any number of things that a chaincode could do that might be construed as violating some resource constraint (heap, stack, cores, local storage, putstate, etc). If/when it does, the peer should be able to enforce restrictions/penalties (such as denying additional heap or terminating the process). Excessive runtime is just one such parameter.

I agree that the ideal is to provide a runtime language that is as conducive to writing deterministic/terminating programs as possible. However, I don't think we should solely rely on this to protect the kernel. For one thing, you always need to ensure that all operational constraints are adhered to (e.g. deterministic code could still ask for too much heap/putstate). Secondly, we don't only need to protect runtime: compile time can arguably be riskier for a platform (at least with GPLs).

ghaskins avatar Jul 18 '16 13:07 ghaskins

how about just stopping and destroying the container if a query/invoke times out ? Its kind of worst case but a timeout on a request borders on "unexpected / bad" behavior

muralisrini avatar Jul 18 '16 14:07 muralisrini

@muralisrini I agree with you. I think it is a simple and practical approach.

sachikoy avatar Jul 19 '16 04:07 sachikoy

There is gas for Ethereum. Could we use the similar concept?

snowsky avatar Sep 10 '17 01:09 snowsky