aionnetwork / avm Goto Github PK
View Code? Open in Web Editor NEWEnabling Java code to run in a blockchain environment
Home Page: https://theoan.com/
License: MIT License
Enabling Java code to run in a blockchain environment
Home Page: https://theoan.com/
License: MIT License
This space left intentionally blank.
Issue created by yulongaion (on Wednesday May 09, 2018 at 14:30 GMT)
Specifically for object and array allocation.
Some idea:
Issue created by yulongaion (on Tuesday May 22, 2018 at 19:24 GMT)
Issue created by romaion (on Tuesday May 15, 2018 at 13:37 GMT)
Issue created by jeff-aion (on Tuesday May 22, 2018 at 13:22 GMT)
Most of the Throwable
hierarchy is without implementation: sub-classes exist just be a type for deriving meaning at the point of catch. These cases are handled by generating the list, within #25. There are 4 special-cases, though, that do have implementations:
ExceptionInInitializerError
ClassNotFoundException
EnumConstantNotPresentException
TypeNotPresentException
These are currently being handled as empty generated classes but this is just a stop-gap to get the larger exception re-writing working. These cases do need to be replaced with hand-written implementations.
Issue created by yulongaion (on Friday May 11, 2018 at 17:35 GMT)
Issue created by yulongaion (on Wednesday May 23, 2018 at 16:10 GMT)
Issue created by JunhanHu-aion (on Wednesday May 16, 2018 at 20:31 GMT)
Stack behaviour
Issue created by romaion (on Tuesday May 22, 2018 at 19:46 GMT)
Issue created by romaion (on Wednesday May 16, 2018 at 15:09 GMT)
Issue created by romaion (on Friday May 18, 2018 at 18:42 GMT)
Issue created by yulongaion (on Friday May 11, 2018 at 17:41 GMT)
Issue created by JunhanHu-aion (on Wednesday May 23, 2018 at 21:18 GMT)
Issue created by jeff-aion (on Monday May 14, 2018 at 15:04 GMT)
One of the trickier aspects of our shadow java.lang
design is exception handling. In many cases (NullPointerException
, as a simple and common case), the JVM instantiates and throws the exception within its own implementation, not appearing in the bytecode, whatsoever. This means that we can't change these through instrumentation.
However, we can wrap this exception where it is caught, via instrumentation. This is using an approach similar to the one described in #23: the exception is on the stack so call a static helper to wrap it, which will replace this value with the wrapped type.
Note that this case needs to safely ignore pre-wrapped instances, which could be very common. This could happen if an exception is caught, thrown, and re-caught. Beyond making sure that the helper is aware of this possibility, it also means that we need to duplicate any exception table entry which specifies an exception we want to shadow (since we want to treat the original and the wrapper as being equivalent).
In terms of implementation, this should be relatively simple, within our existing basic block design: we will need to tag any blocks which represent the target of a java.lang
exception target, with needing this sort of call-out injected. Then, we can statically duplicate all of these ranges when re-serializing the bytes. This should mean at most 1 additional bytecode per catch block.
Issue created by jeff-aion (on Monday May 07, 2018 at 17:19 GMT)
Ideally, we want to bill the contract for heap allocations it performs, during its run. We don't have a deterministic or high-precision way of measuring/interpreting object lifespan, so we will just have to settle for allocation-time cost.
Another consideration is that we need the value computed to be portable and deterministic, so relying on physical measurements/estimates provided by the VM are probably not appropriate.
We also need to decide if we will be counting any of the allocations which occur within the JDK or Aion runtime, as a consequence of executing higher-level actions within the contract. I suspect that accounting for this will not be feasible, nor portable, as small changes in implementations or versions are unlikely to faithfully maintain these costs.
Issue created by yulongaion (on Friday May 18, 2018 at 14:48 GMT)
ByteArrary
with byte[]
Issue created by romaion (on Tuesday May 22, 2018 at 15:26 GMT)
Investigate if it possible to avoid accessing blockchain during class loading on 'CREATE phase'.
Assumption is that during 'define class' some static code gets executed and and may access blockchain.
During that initial validation of the input code, we make sure that there are no gaps in the user-defined class hierarchy, right? That is, we make sure that every root of the forest is a class we know is defined and valid, within our runtime or shadow base?
Issue created by yulongaion (on Monday May 14, 2018 at 14:28 GMT)
Instead of instrumenting the RT classes, it might be better to apply constant fees. This would simplify the our instrumentation procedure and leave us flexibility to upgrade the RT without breaking compatibility.
Issue created by yulongaion (on Wednesday May 23, 2018 at 16:15 GMT)
An asynchronous exception occurred because:
- The stop method of class Thread or ThreadGroup was invoked, or
- An internal error occurred in the Java Virtual Machine implementation.
Virtual Machine Errors:
- InternalError
- OutOfMemoryError
- StackOverflowError
- UnknownError
- ...
Issue created by jeff-aion (on Thursday May 10, 2018 at 16:03 GMT)
One of the topics discussed in #4 and #6 is that of heap limit nondeterminism.
We need an answer to this problem since it is otherwise possible to construct a contract which would only work on some nodes, based on heap geometries they have chosen. This problem would be further exasperated as concurrent contract execution is enabled.
The core of the problem is that the real limit of memory to a Java process is based on live objects, not allocated objects. This value cannot be truly known at any point.
Therefore, we must impose some restriction which can be known. A possibility is the abstract cost of allocates issued directly from within the contract code. This is something a contract writer could reason about, would be a deterministic function of the execution path taken, could be measured along the same lines of much of our bytecode-level instrumentation, and would be isolated from implementation details of the JVM or our runtime.
Issue created by yulongaion (on Wednesday May 23, 2018 at 15:21 GMT)
Investigate all returnAddress
type usage.
As Jeff suggested before, we probably need to disable jsr, ret, and jsr_w instructions, which were used for finally
prior to Java SE 6.0.
Issue created by jeff-aion (on Tuesday May 08, 2018 at 22:00 GMT)
Work such as #9 require that we can read a stream of bytecodes into a high-level representation. For our purposes, we will just be returning a list of basic blocks (each of which is a list of bytecodes and other information, such as exceptions in a try, etc).
We will define a basic block as the place where execution can begin (start of method, target of goto, target of if, target of exception handler, etc) or the byte after the end of an exception try range (probably also the beginning of execution but this isn't strictly required) since want a block to know about start/end exception ranges.
Note that this item is purely tracking the work required to make the read-only support required by #9. Re-writing capabilities will come later.
Issue created by yulongaion (on Friday May 11, 2018 at 18:29 GMT)
One of the problems we have is that the shadow implementation is not compatible with the java.lang.Object
because of method signature.
Potential solution could be adding prefix to the methods of shadow classes, and apply the rules when replacing method invoke during class analysis.
Issue created by jeff-aion (on Wednesday May 16, 2018 at 18:58 GMT)
We realized that we don't get all the labels we were expecting, required to generate a list of blocks, if we changed our accept
flag to ClassReader.SKIP_DEBUG
(it was normally just ClassReader.SKIP_FRAMES
).
After some investigation, we found that this is because many of the labels were being generated for line number debug data. We don't want to rely on this and is probably only giving us the shape we expected, by accident.
For the most part, removing these debug labels will bring us closer to what we expected, but there are still fall-through cases which we may not find (since fall-throughs probably don't have labels - nobody jumps to them). This may only matter for branching bytecodes, but we should also verify that other control flow codes must provide the labels we require.
Issue created by jeff-aion (on Wednesday May 09, 2018 at 23:01 GMT)
This first requirement for writing instrumented classes is to cover the per-block energy cost.
This will be heavily based on the reading support from #11, even accepting the data it produces as input.
We may need to further generalize this solution in the future but, for now, we will handle this case specifically (the difficulty in this problem is more how to generalize the mutative instrumentation, as opposed to implementing each case - hence, we will probably directly implement each case).
The approach for this to allow the external bytecode fee schedule to ask for the per-method block lists (provided by #11), walk it to determine a cost for each block, save that value on the block, then pass those lists back into the ClassRewriter where it will use these values to build the instrumented code.
Note that this means that we will have 2 versions of the same block, which should refer to exactly the same bytecode extends, but the previous one will have the energy cost attached. This means that we can pass all method calls straight through the writer, except the first bytecode in a block, which will need to first add the bytecodes to call-out to charge for the block.
This should avoid needing to exhaustively duplicate all ASM logic, as we will piggy-back on it for all cases except the block prefix instrumentation. As long as we remember to always inject this after the last label before the first bytecode in the block, ASM should correctly update control flow targets when it serializes and assigns concrete offsets to the labels.
Issue created by romaion (on Tuesday May 22, 2018 at 19:45 GMT)
Issue created by JunhanHu-aion (on Wednesday May 23, 2018 at 20:48 GMT)
Issue created by jeff-aion (on Friday May 18, 2018 at 15:04 GMT)
Both #25 and #33 (and probably other concerns in the future) need to dynamically "fake-up" types to address various linking concerns. These classes can descend from hand-written classes which actually contain the logic but these generated classes still must exist as distinct types.
The way forward, for both of these classes, is to build a way to generate and load these "stub" classes.
Issue created by nancyaion (on Tuesday May 08, 2018 at 18:13 GMT)
APIs design and implementation of the static analysis of the bytecode, to divide it into blocks, calculate the cost of each block and inject the instrumental code.
Issue created by yulongaion (on Friday May 04, 2018 at 18:30 GMT)
This space left intentionally blank.
Issue created by nancyaion (on Tuesday May 22, 2018 at 14:36 GMT)
This space left intentionally blank.
Issue created by yulongaion (on Wednesday May 23, 2018 at 16:04 GMT)
To enable strict floating point mode.
Issue created by romaion (on Wednesday May 16, 2018 at 13:47 GMT)
Issue created by yulongaion (on Friday May 18, 2018 at 15:59 GMT)
lib
org.aion.avm.core
org.aion.avm.rt
examples
+---lib/org-aion-avm-rt.jar
+---com.example.helloworld
+---com
+---example
+---hellworld
+---Main.java
+module-info.java
+---com.example.simpletoken
+---com
+---example
+---simpletoken
+---Main.java
+module-info.java
+---build.xml
Issue created by yulongaion (on Friday May 11, 2018 at 20:19 GMT)
An ldc instruction with operand CP is type safe iff CP refers to a constant pool entry denoting an entity of type Type, where Type is either int, float, String, Class, java.lang.invoke.MethodType, or java.lang.invoke.MethodHandle, and one can validly push Type onto the incoming operand stack yielding the outgoing type state.
TODO: apply type shadowing for the reference type
Issue created by jeff-aion (on Friday May 11, 2018 at 19:38 GMT)
Carved from #13 to describe the work we must do in order to track the static heap usage, within the context of a block. This refers to uses of new
which allocate an object, type known at instrumentation time due to constant pool reference, whose cost can be statically attributed to a parent block.
Issue created by nancyaion (on Wednesday May 16, 2018 at 17:33 GMT)
ClassHierarchyForest will have a forest data structure, which is consisted of multiple hierarchy trees (temporarily) and after all classes are added to it, it should be one tree with a root node of the shadowing "java.lang.object".
It also has a hashmap of the class name to the tree node, for accelerating the search.
This class provides,
add a new class relationship (and the classes) to the tree;
get the tree roots (maybe more than one);
get the parent class;
get the child classes;
...
Issue created by yulongaion (on Friday May 04, 2018 at 18:31 GMT)
Approaches:
Issue created by yulongaion (on Friday May 04, 2018 at 18:29 GMT)
Issue created by yulongaion (on Wednesday May 16, 2018 at 20:52 GMT)
Issue created by JunhanHu-aion (on Wednesday May 16, 2018 at 21:17 GMT)
Issue created by yulongaion (on Friday May 04, 2018 at 18:28 GMT)
Issue created by yulongaion (on Thursday May 10, 2018 at 22:09 GMT)
Throwable
/Exception
/Error
java.lang.Throwable
hierarchyNOTE: many runtime exception are thrown by the JVM
This space left intentionally blank.
This space left intentionally blank.
This space left intentionally blank.
Issue created by yulongaion (on Wednesday May 09, 2018 at 14:02 GMT)
Write a test case to verify the behavior the following opcodes
push
push
push
jump 0
Make sure it won't break our assumption over the total stack size measurement
Issue created by yulongaion (on Monday May 07, 2018 at 18:31 GMT)
We need to ensure DApps get the same behavior in terms of stack usage, stackoverflow or not, for all the nodes.
Possible directions:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.