Initial Merge

1) wire
2) GUI
   - Serpent Editor
   - Network Overview
   - Connection Console
3) Serpent Compiler
This commit is contained in:
romanman 2014-05-02 10:03:53 +03:00
parent 341f555a53
commit af1adefecb
337 changed files with 22009 additions and 0 deletions

View File

@ -0,0 +1,49 @@
package org.ethereum.geodb;
import com.maxmind.geoip.Location;
import com.maxmind.geoip.LookupService;
import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.exception.GeoIp2Exception;
import com.maxmind.geoip2.model.CityResponse;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URISyntaxException;
import java.net.URL;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 24/04/14 20:11
*/
public class IpGeoDB {
static{
try {
URL geiIpDBFile = ClassLoader.getSystemResource("GeoLiteCity.dat");
File file = new File(geiIpDBFile.toURI());
cl = new LookupService(file);
} catch (Throwable e) {
e.printStackTrace();
}
}
private static LookupService cl;
public static Location getLocationForIp(InetAddress ip){
try {
return cl.getLocation(ip);
} catch (Throwable e) {
// todo: think about this exception, maybe you can do something more reasonable
System.out.println(e.getMessage());
// e.printStackTrace();
}
return null;
}
}

View File

@ -0,0 +1,103 @@
package org.ethereum.gui;
import org.ethereum.net.client.ClientPeer;
import org.fife.ui.rsyntaxtextarea.*;
import org.fife.ui.rtextarea.RTextScrollPane;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.util.TimerTask;
/**
* A simple example showing how to modify the fonts and colors used in an
* RSyntaxTextArea. There are two methods to do this - via the Java API, and via
* an XML file. The latter method is preferred since it's more modular, and
* provides a way for your users to customize RSTA in your application.<p>
*
* This example uses RSyntaxTextArea 2.0.1.<p>
*
* Project Home: http://fifesoft.com/rsyntaxtextarea<br>
* Downloads: https://sourceforge.net/projects/rsyntaxtextarea
*/
public class ConnectionConsole extends JFrame implements PeerListener{
private static final long serialVersionUID = 1L;
private RSyntaxTextArea textArea;
public ConnectionConsole() {
final ConnectionConsole thisConsole = this;
java.net.URL url = ClassLoader.getSystemResource("ethereum-icon.png");
Toolkit kit = Toolkit.getDefaultToolkit();
Image img = kit.createImage(url);
this.setIconImage(img);
JPanel cp = new JPanel(new BorderLayout());
textArea = new RSyntaxTextArea(16, 47);
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_LISP);
textArea.setCodeFoldingEnabled(true);
textArea.setAntiAliasingEnabled(true);
RTextScrollPane sp = new RTextScrollPane(textArea);
cp.add(sp);
setContentPane(cp);
setTitle("Connection Console");
// setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setLocation(775, 390);
this.addComponentListener(new ComponentAdapter() {
@Override
public void componentShown(ComponentEvent e) {
Thread t = new Thread() {
public void run() {
// new ClientPeer(thisConsole).connect("54.201.28.117", 30303);
new ClientPeer(thisConsole).connect("82.217.72.169", 30303);
}
};
t.start();
}
});
}
@Override
public void console(final String output) {
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
textArea.append(output);
textArea.append("\n");
textArea.setCaretPosition(textArea.getText().length());
}
});
}
public static void main(String[] args) {
// Start all Swing applications on the EDT.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ConnectionConsole().setVisible(true);
}
});
}
}

View File

@ -0,0 +1,11 @@
package org.ethereum.gui;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 30/04/14 11:32
*/
public interface PeerListener {
public void console(String output);
}

View File

@ -0,0 +1,166 @@
package org.ethereum.gui;
import com.maxmind.geoip.Location;
import com.maxmind.geoip2.model.CityResponse;
import org.ethereum.geodb.IpGeoDB;
import org.ethereum.util.Utils;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 25/04/14 07:04
*/
public class PeersTableModel extends AbstractTableModel {
List<PeerInfo> peerInfoList = new ArrayList<PeerInfo>();
public PeersTableModel() {
generateRandomData();
}
public String getColumnName(int column) {
if (column == 0) return "Location";
if (column == 1) return "IP";
if (column == 2) return "Live";
else return "";
}
public boolean isCellEditable(int row, int column) {
return false;
}
public Class getColumnClass(int column) {
if (column == 0) return ImageIcon.class;
if (column == 1) return String.class;
if (column == 2) return ImageIcon.class;
else return String.class;
}
public Object getValueAt(int row, int column) {
PeerInfo peerInfo = peerInfoList.get(row);
if (column == 0){
String countryCode = peerInfo.getLocation().countryCode;
URL flagURL = ClassLoader.getSystemResource("flags/" + countryCode + ".png");
ImageIcon flagIcon = new ImageIcon(flagURL);
return flagIcon;
}
if (column == 1) return peerInfo.getIp().getHostAddress();
if (column == 2) {
Random random = new Random();
boolean isConnected = random.nextBoolean();
ImageIcon flagIcon = null;
if (peerInfo.connected){
flagIcon = Utils.getImageIcon("connected.png");
} else {
flagIcon = Utils.getImageIcon("disconnected.png");
}
return flagIcon;
}
else return "";
}
public int getRowCount() {
return this.peerInfoList.size();
}
public int getColumnCount() {
return 3;
}
// todo: delete it when stabilized
private void generateRandomData(){
List<String> ips = new ArrayList<String>();
ips.add("206.223.168.190");
ips.add("94.210.200.192");
ips.add("88.69.198.198");
ips.add("62.78.198.208");
ips.add("71.202.162.40");
ips.add("78.55.236.218");
ips.add("94.197.120.80");
ips.add("85.65.126.45");
ips.add("110.77.217.185");
ips.add("64.231.9.30");
ips.add("162.243.203.121");
ips.add("82.217.72.169");
ips.add("99.231.80.166");
ips.add("131.104.252.4");
ips.add("54.204.10.41");
ips.add("54.201.28.117");
ips.add("82.240.16.5");
ips.add("74.79.23.119");
for (String peer : ips){
try {
InetAddress addr = InetAddress.getByName(peer);
Location cr = IpGeoDB.getLocationForIp(addr);
peerInfoList.add(new PeerInfo(cr, addr));
} catch (UnknownHostException e) {e.printStackTrace(); }
}
}
private class PeerInfo{
Location location;
InetAddress ip;
boolean connected;
private PeerInfo(Location location, InetAddress ip) {
this.location = location;
this.ip = ip;
Random random = new Random();
connected = random.nextBoolean();
}
private InetAddress getIp() {
return ip;
}
private Location getLocation() {
return location;
}
private boolean isConnected() {
return connected;
}
}
}

View File

@ -0,0 +1,121 @@
package org.ethereum.gui;
import org.ethereum.serpent.SerpentCompiler;
import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.TokenMakerFactory;
import org.fife.ui.rtextarea.RTextScrollPane;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 24/04/14 11:32
*/
public class SerpentEditor extends JFrame {
private String codeSample = "\n\n\n" +
"" +
"if !contract.storage[msg.data[0]]:\n" +
" contract.storage[msg.data[0]] = msg.data[1]\n" +
" return(1)\n" +
"else:\n" +
" return(0)\n";
private static final long serialVersionUID = 1L;
public SerpentEditor() {
final JPanel cp = new JPanel(new BorderLayout());
final JFrame mainWindow = this;
java.net.URL url = ClassLoader.getSystemResource("ethereum-icon.png");
Toolkit kit = Toolkit.getDefaultToolkit();
Image img = kit.createImage(url);
this.setIconImage(img);
this.setLocation(30, 80);
AbstractTokenMakerFactory atmf = (AbstractTokenMakerFactory)TokenMakerFactory.getDefaultInstance();
atmf.putMapping("text/serpent", "org.ethereum.gui.SerpentTokenMaker");
final RSyntaxTextArea codeArea = new RSyntaxTextArea(32, 80);
codeArea.setSyntaxEditingStyle("text/serpent");
codeArea.setCodeFoldingEnabled(true);
codeArea.setAntiAliasingEnabled(true);
codeArea.setText(codeSample);
RTextScrollPane sp = new RTextScrollPane(codeArea);
sp.setFoldIndicatorEnabled(true);
cp.setLayout(new BorderLayout());
final JSplitPane splitPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
splitPanel.setOneTouchExpandable(true);
splitPanel.setDividerSize(5);
splitPanel.setContinuousLayout(true);
cp.add(splitPanel, BorderLayout.CENTER);
splitPanel.add(sp);
final JTextArea result = new JTextArea();
result.setLineWrap(true);
result.setWrapStyleWord(true);
result.setVisible(false);
splitPanel.add(result);
JPanel controlsPanel = new JPanel();
FlowLayout fl = new FlowLayout(FlowLayout.LEADING, 30, 5);
fl.setAlignment(FlowLayout.RIGHT);
controlsPanel.setLayout(fl);
JButton buildButton = new JButton("Build");
buildButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String asmResult = "";
try {
asmResult = SerpentCompiler.compile(codeArea.getText());
} catch (Throwable th) {th.printStackTrace();}
splitPanel.setDividerLocation(0.7);
result.setVisible(true);
result.setText(asmResult);
}
});
controlsPanel.add(buildButton);
cp.add(controlsPanel, BorderLayout.SOUTH);
setContentPane(cp);
setTitle("Serpent Editor");
// setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
// setLocationRelativeTo(null);
}
public static void main(String[] args) {
// Start all Swing applications on the EDT.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new SerpentEditor().setVisible(true);
}
});
}
}

View File

@ -0,0 +1,508 @@
package org.ethereum.gui;
import javax.swing.text.Segment;
import org.fife.ui.rsyntaxtextarea.*;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 24/04/14 11:52
*/
public class SerpentTokenMaker extends AbstractTokenMaker {
// http://fifesoft.com/rsyntaxtextarea/doc/CustomSyntaxHighlighting.html
protected final String operators = ".@:*<>=?|!";
private int currentTokenStart;
private int currentTokenType;
private boolean bracketVariable; // Whether a variable is of the format %{...}
/**
* Constructor.
*/
public SerpentTokenMaker() {
super(); // Initializes tokensToHighlight.
}
/**
* Checks the token to give it the exact ID it deserves before
* being passed up to the super method.
*
* @param segment <code>Segment</code> to get text from.
* @param start Start offset in <code>segment</code> of token.
* @param end End offset in <code>segment</code> of token.
* @param tokenType The token's type.
* @param startOffset The offset in the document at which the token occurs.
*/
@Override
public void addToken(Segment segment, int start, int end, int tokenType, int startOffset) {
switch (tokenType) {
// Since reserved words, functions, and data types are all passed
// into here as "identifiers," we have to see what the token
// really is...
case Token.IDENTIFIER:
int value = wordsToHighlight.get(segment, start,end);
if (value!=-1)
tokenType = value;
break;
}
super.addToken(segment, start, end, tokenType, startOffset);
}
/**
* Returns the text to place at the beginning and end of a
* line to "comment" it in a this programming language.
*
* @return The start and end strings to add to a line to "comment"
* it out.
*/
@Override
public String[] getLineCommentStartAndEnd() {
return new String[] { "#", null };
}
/**
* Returns whether tokens of the specified type should have "mark
* occurrences" enabled for the current programming language.
*
* @param type The token type.
* @return Whether tokens of this type should have "mark occurrences"
* enabled.
*/
@Override
public boolean getMarkOccurrencesOfTokenType(int type) {
return type==Token.IDENTIFIER || type==Token.VARIABLE;
}
/**
* Returns the words to highlight for Windows batch files.
*
* @return A <code>TokenMap</code> containing the words to highlight for
* Windows batch files.
* @see org.fife.ui.rsyntaxtextarea.AbstractTokenMaker#getWordsToHighlight
*/
@Override
public TokenMap getWordsToHighlight() {
TokenMap tokenMap = new TokenMap(true); // Ignore case.
int reservedWord = Token.RESERVED_WORD;
tokenMap.put("set", reservedWord);
tokenMap.put("if", reservedWord);
tokenMap.put("else", reservedWord);
tokenMap.put("elif", reservedWord);
tokenMap.put("seq", reservedWord);
tokenMap.put("while", reservedWord);
tokenMap.put("byte", reservedWord);
tokenMap.put("access", reservedWord);
tokenMap.put("arrset", reservedWord);
tokenMap.put("set_and_inc", reservedWord);
tokenMap.put("array", reservedWord);
tokenMap.put("getch", reservedWord);
tokenMap.put("setch", reservedWord);
tokenMap.put("string", reservedWord);
tokenMap.put("send", reservedWord);
tokenMap.put("create", reservedWord);
tokenMap.put("sha3", reservedWord);
tokenMap.put("sha3bytes", reservedWord);
tokenMap.put("sload", reservedWord);
tokenMap.put("sstore", reservedWord);
tokenMap.put("calldataload", reservedWord);
tokenMap.put("id", reservedWord);
tokenMap.put("return", reservedWord);
tokenMap.put("suicide", reservedWord);
tokenMap.put("stop", reservedWord);
int function = Token.FUNCTION;
tokenMap.put("msg", function);
tokenMap.put("contract", function);
tokenMap.put("block", function);
tokenMap.put("tx", function);
return tokenMap;
}
/**
* Returns a peerInfoList of tokens representing the given text.
*
* @param text The text to break into tokens.
* @param startTokenType The token with which to start tokenizing.
* @param startOffset The offset at which the line of tokens begins.
* @return A linked peerInfoList of tokens representing <code>text</code>.
*/
public Token getTokenList(Segment text, int startTokenType, final int startOffset) {
resetTokenList();
char[] array = text.array;
int offset = text.offset;
int count = text.count;
int end = offset + count;
// See, when we find a token, its starting position is always of the form:
// 'startOffset + (currentTokenStart-offset)'; but since startOffset and
// offset are constant, tokens' starting positions become:
// 'newStartOffset+currentTokenStart' for one less subtraction operation.
int newStartOffset = startOffset - offset;
currentTokenStart = offset;
currentTokenType = startTokenType;
//beginning:
for (int i=offset; i<end; i++) {
char c = array[i];
switch (currentTokenType) {
case Token.NULL:
currentTokenStart = i; // Starting a new token here.
switch (c) {
case ' ':
case '\t':
currentTokenType = Token.WHITESPACE;
break;
case '"':
currentTokenType = Token.ERROR_STRING_DOUBLE;
break;
case '%':
currentTokenType = Token.VARIABLE;
break;
// The "separators".
case '(':
case ')':
addToken(text, currentTokenStart,i, Token.SEPARATOR, newStartOffset+currentTokenStart);
currentTokenType = Token.NULL;
break;
// The "separators2".
case ',':
case ';':
addToken(text, currentTokenStart,i, Token.IDENTIFIER, newStartOffset+currentTokenStart);
currentTokenType = Token.NULL;
break;
// Newer version of EOL comments, or a label
case ':':
// If this will be the first token added, it is
// a new-style comment or a label
if (firstToken==null) {
if (i<end-1 && array[i+1]==':') { // new-style comment
currentTokenType = Token.COMMENT_EOL;
}
else { // Label
currentTokenType = Token.PREPROCESSOR;
}
}
else { // Just a colon
currentTokenType = Token.IDENTIFIER;
}
break;
// Newer version of EOL comments, or a label
default:
// Just to speed things up a tad, as this will usually be the case (if spaces above failed).
if (RSyntaxUtilities.isLetterOrDigit(c) || c=='\\') {
currentTokenType = Token.IDENTIFIER;
break;
}
int indexOf = operators.indexOf(c,0);
if (indexOf>-1) {
addToken(text, currentTokenStart,i, Token.OPERATOR, newStartOffset+currentTokenStart);
currentTokenType = Token.NULL;
break;
}
else {
currentTokenType = Token.IDENTIFIER;
break;
}
} // End of switch (c).
break;
case Token.WHITESPACE:
switch (c) {
case ' ':
case '\t':
break; // Still whitespace.
case '"':
addToken(text, currentTokenStart,i-1, Token.WHITESPACE, newStartOffset+currentTokenStart);
currentTokenStart = i;
currentTokenType = Token.ERROR_STRING_DOUBLE;
break;
case '%':
addToken(text, currentTokenStart,i-1, Token.WHITESPACE, newStartOffset+currentTokenStart);
currentTokenStart = i;
currentTokenType = Token.VARIABLE;
break;
// The "separators".
case '(':
case ')':
addToken(text, currentTokenStart,i-1, Token.WHITESPACE, newStartOffset+currentTokenStart);
addToken(text, i,i, Token.SEPARATOR, newStartOffset+i);
currentTokenType = Token.NULL;
break;
// The "separators2".
case ',':
case ';':
addToken(text, currentTokenStart,i-1, Token.WHITESPACE, newStartOffset+currentTokenStart);
addToken(text, i,i, Token.IDENTIFIER, newStartOffset+i);
currentTokenType = Token.NULL;
break;
// Newer version of EOL comments, or a label
case ':':
addToken(text, currentTokenStart,i-1, Token.WHITESPACE, newStartOffset+currentTokenStart);
currentTokenStart = i;
// If the previous (whitespace) token was the first token
// added, this is a new-style comment or a label
if (firstToken.getNextToken()==null) {
if (i<end-1 && array[i+1]==':') { // new-style comment
currentTokenType = Token.COMMENT_EOL;
}
else { // Label
currentTokenType = Token.PREPROCESSOR;
}
}
else { // Just a colon
currentTokenType = Token.IDENTIFIER;
}
break;
default: // Add the whitespace token and start anew.
addToken(text, currentTokenStart,i-1, Token.WHITESPACE, newStartOffset+currentTokenStart);
currentTokenStart = i;
// Just to speed things up a tad, as this will usually be the case (if spaces above failed).
if (RSyntaxUtilities.isLetterOrDigit(c) || c=='\\') {
currentTokenType = Token.IDENTIFIER;
break;
}
int indexOf = operators.indexOf(c,0);
if (indexOf>-1) {
addToken(text, currentTokenStart,i, Token.OPERATOR, newStartOffset+currentTokenStart);
currentTokenType = Token.NULL;
break;
}
else {
currentTokenType = Token.IDENTIFIER;
}
} // End of switch (c).
break;
default: // Should never happen
case Token.IDENTIFIER:
switch (c) {
case ' ':
case '\t':
// Check for REM comments.
if (i-currentTokenStart==3 &&
(array[i-3]=='r' || array[i-3]=='R') &&
(array[i-2]=='e' || array[i-2]=='E') &&
(array[i-1]=='m' || array[i-1]=='M')) {
currentTokenType = Token.COMMENT_EOL;
break;
}
addToken(text, currentTokenStart,i-1, Token.IDENTIFIER, newStartOffset+currentTokenStart);
currentTokenStart = i;
currentTokenType = Token.WHITESPACE;
break;
case '"':
addToken(text, currentTokenStart,i-1, Token.IDENTIFIER, newStartOffset+currentTokenStart);
currentTokenStart = i;
currentTokenType = Token.ERROR_STRING_DOUBLE;
break;
case '%':
addToken(text, currentTokenStart,i-1, Token.IDENTIFIER, newStartOffset+currentTokenStart);
currentTokenStart = i;
currentTokenType = Token.VARIABLE;
break;
// Should be part of identifiers, but not at end of "REM".
case '\\':
// Check for REM comments.
if (i-currentTokenStart==3 &&
(array[i-3]=='r' || array[i-3]=='R') &&
(array[i-2]=='e' || array[i-2]=='E') &&
(array[i-1]=='m' || array[i-1]=='M')) {
currentTokenType = Token.COMMENT_EOL;
}
break;
// case '.':
case '_':
break; // Characters good for identifiers.
// The "separators".
case '(':
case ')':
addToken(text, currentTokenStart,i-1, Token.IDENTIFIER, newStartOffset+currentTokenStart);
addToken(text, i,i, Token.SEPARATOR, newStartOffset+i);
currentTokenType = Token.NULL;
break;
// The "separators2".
case ',':
case ';':
addToken(text, currentTokenStart,i-1, Token.IDENTIFIER, newStartOffset+currentTokenStart);
addToken(text, i,i, Token.IDENTIFIER, newStartOffset+i);
currentTokenType = Token.NULL;
break;
default:
// Just to speed things up a tad, as this will usually be the case.
if (RSyntaxUtilities.isLetterOrDigit(c) || c=='\\') {
break;
}
int indexOf = operators.indexOf(c);
if (indexOf>-1) {
addToken(text, currentTokenStart,i-1, Token.IDENTIFIER, newStartOffset+currentTokenStart);
addToken(text, i,i, Token.OPERATOR, newStartOffset+i);
currentTokenType = Token.NULL;
break;
}
// Otherwise, fall through and assume we're still okay as an IDENTIFIER...
} // End of switch (c).
break;
case Token.COMMENT_EOL:
i = end - 1;
addToken(text, currentTokenStart,i, Token.COMMENT_EOL, newStartOffset+currentTokenStart);
// We need to set token type to null so at the bottom we don't add one more token.
currentTokenType = Token.NULL;
break;
case Token.PREPROCESSOR: // Used for labels
i = end - 1;
addToken(text, currentTokenStart,i, Token.PREPROCESSOR, newStartOffset+currentTokenStart);
// We need to set token type to null so at the bottom we don't add one more token.
currentTokenType = Token.NULL;
break;
case Token.ERROR_STRING_DOUBLE:
if (c=='"') {
addToken(text, currentTokenStart,i, Token.LITERAL_STRING_DOUBLE_QUOTE, newStartOffset+currentTokenStart);
currentTokenStart = i + 1;
currentTokenType = Token.NULL;
}
// Otherwise, we're still an unclosed string...
break;
case Token.VARIABLE:
if (i==currentTokenStart+1) { // first character after '%'.
bracketVariable = false;
switch (c) {
case '{':
bracketVariable = true;
break;
default:
if (RSyntaxUtilities.isLetter(c) || c==' ') { // No tab, just space; spaces are okay in variable names.
break;
}
else if (RSyntaxUtilities.isDigit(c)) { // Single-digit command-line argument ("%1").
addToken(text, currentTokenStart,i, Token.VARIABLE, newStartOffset+currentTokenStart);
currentTokenType = Token.NULL;
break;
}
else { // Anything else, ???.
addToken(text, currentTokenStart,i-1, Token.VARIABLE, newStartOffset+currentTokenStart); // ???
i--;
currentTokenType = Token.NULL;
break;
}
} // End of switch (c).
}
else { // Character other than first after the '%'.
if (bracketVariable==true) {
if (c=='}') {
addToken(text, currentTokenStart,i, Token.VARIABLE, newStartOffset+currentTokenStart);
currentTokenType = Token.NULL;
}
}
else {
if (c=='%') {
addToken(text, currentTokenStart,i, Token.VARIABLE, newStartOffset+currentTokenStart);
currentTokenType = Token.NULL;
}
}
break;
}
break;
} // End of switch (currentTokenType).
} // End of for (int i=offset; i<end; i++).
// Deal with the (possibly there) last token.
if (currentTokenType != Token.NULL) {
// Check for REM comments.
if (end-currentTokenStart==3 &&
(array[end-3]=='r' || array[end-3]=='R') &&
(array[end-2]=='e' || array[end-2]=='E') &&
(array[end-1]=='m' || array[end-1]=='M')) {
currentTokenType = Token.COMMENT_EOL;
}
addToken(text, currentTokenStart,end-1, currentTokenType, newStartOffset+currentTokenStart);
}
addNullToken();
// Return the first token in our linked peerInfoList.
return firstToken;
}
}

View File

@ -0,0 +1,158 @@
package org.ethereum.gui;
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import javax.swing.*;
import org.fife.ui.rtextarea.*;
import org.fife.ui.rsyntaxtextarea.*;
/**
* A simple example showing how to modify the fonts and colors used in an
* RSyntaxTextArea. There are two methods to do this - via the Java API, and via
* an XML file. The latter method is preferred since it's more modular, and
* provides a way for your users to customize RSTA in your application.<p>
*
* This example uses RSyntaxTextArea 2.0.1.<p>
*
* Project Home: http://fifesoft.com/rsyntaxtextarea<br>
* Downloads: https://sourceforge.net/projects/rsyntaxtextarea
*/
public class SyntaxSchemeDemo extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private RSyntaxTextArea textArea;
private static final String text = "public class ExampleSource {\n\n"
+ " // Check out the crazy modified styles!\n"
+ " public static void main(String[] args) {\n"
+ " System.out.println(\"Hello, world!\");\n" + " }\n\n"
+ "}\n";
public SyntaxSchemeDemo() {
java.net.URL url = ClassLoader.getSystemResource("ethereum-icon.png");
Toolkit kit = Toolkit.getDefaultToolkit();
Image img = kit.createImage(url);
this.setIconImage(img);
JPanel cp = new JPanel(new BorderLayout());
textArea = new RSyntaxTextArea(20, 60);
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
textArea.setCodeFoldingEnabled(true);
textArea.setAntiAliasingEnabled(true);
RTextScrollPane sp = new RTextScrollPane(textArea);
cp.add(sp);
// JPanel buttons = new JPanel();
// buttons.setLayout(new FlowLayout());
// buttons.add(new JButton("build"));
//
// cp.add(buttons, BorderLayout.SOUTH);
textArea.setText(text);
JMenuBar mb = new JMenuBar();
JMenu menu = new JMenu("File");
mb.add(menu);
JMenuItem changeStyleProgrammaticallyItem = new JMenuItem(
"Change Style Programmatically");
changeStyleProgrammaticallyItem
.setActionCommand("ChangeProgrammatically");
changeStyleProgrammaticallyItem.addActionListener(this);
menu.add(changeStyleProgrammaticallyItem);
JMenuItem changeStyleViaThemesItem = new JMenuItem(
"Change Style via Theme XML");
changeStyleViaThemesItem.setActionCommand("ChangeViaThemes");
changeStyleViaThemesItem.addActionListener(this);
menu.add(changeStyleViaThemesItem);
// setJMenuBar(mb);
setContentPane(cp);
setTitle("Connection Console");
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
}
/**
* Listens for the selection of a menu item and performs an action
* accordingly.
*/
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if ("ChangeProgrammatically".equals(command)) {
changeStyleProgrammatically();
} else if ("ChangeViaThemes".equals(command)) {
changeStyleViaThemeXml();
}
}
/**
* Changes the styles used in the editor programmatically.
*/
private void changeStyleProgrammatically() {
// Set the font for all token types.
setFont(textArea, new Font("Comic Sans MS", Font.PLAIN, 16));
// Change a few things here and there.
SyntaxScheme scheme = textArea.getSyntaxScheme();
scheme.getStyle(Token.RESERVED_WORD).background = Color.pink;
scheme.getStyle(Token.DATA_TYPE).foreground = Color.blue;
scheme.getStyle(Token.LITERAL_STRING_DOUBLE_QUOTE).underline = true;
scheme.getStyle(Token.COMMENT_EOL).font = new Font("Georgia",
Font.ITALIC, 12);
textArea.revalidate();
}
/**
* Changes the styles used by the editor via an XML file specification. This
* method is preferred because of its ease and modularity.
*/
private void changeStyleViaThemeXml() {
try {
Theme theme = Theme.load(getClass().getResourceAsStream(
"/eclipse_theme.xml"));
theme.apply(textArea);
} catch (IOException ioe) { // Never happens
ioe.printStackTrace();
}
}
/**
* Set the font for all token types.
*
* @param textArea The text area to modify.
* @param font The font to use.
*/
public static void setFont(RSyntaxTextArea textArea, Font font) {
if (font != null) {
SyntaxScheme ss = textArea.getSyntaxScheme();
ss = (SyntaxScheme) ss.clone();
for (int i = 0; i < ss.getStyleCount(); i++) {
if (ss.getStyle(i) != null) {
ss.getStyle(i).font = font;
}
}
textArea.setSyntaxScheme(ss);
textArea.setFont(font);
}
}
public static void main(String[] args) {
// Start all Swing applications on the EDT.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new SyntaxSchemeDemo().setVisible(true);
}
});
}
}

View File

@ -0,0 +1,126 @@
package org.ethereum.gui;
import samples.PeersTableMain;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 30/04/14 06:29
*/
public class ToolBar extends JFrame {
public ToolBar() throws HeadlessException {
final JPanel cp = new JPanel(new FlowLayout());
cp.setBackground(Color.WHITE);
java.net.URL url = ClassLoader.getSystemResource("ethereum-icon.png");
Toolkit kit = Toolkit.getDefaultToolkit();
Image img = kit.createImage(url);
this.setIconImage(img);
this.setSize(350, 130);
this.setLocation(460, 25);
this.setAlwaysOnTop(true);
this.setResizable(false);
this.setBackground(Color.WHITE);
setTitle("EthereumJ Studio");
setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setContentPane(cp);
java.net.URL imageURL_1 = ClassLoader.getSystemResource("buttons/feedly.png");
ImageIcon image_1 = new ImageIcon(imageURL_1);
java.net.URL imageURL_2 = ClassLoader.getSystemResource("buttons/winamp.png");
ImageIcon image_2 = new ImageIcon(imageURL_2);
java.net.URL imageURL_3 = ClassLoader.getSystemResource("buttons/browser.png");
ImageIcon image_3 = new ImageIcon(imageURL_3);
JToggleButton editorToggle = new JToggleButton("");
editorToggle.setIcon(image_1);
editorToggle.setContentAreaFilled(true);
editorToggle.setToolTipText("Serpent Editor");
editorToggle.setBackground(Color.WHITE);
editorToggle.setBorderPainted(false);
editorToggle.setFocusPainted(false);
editorToggle.setCursor(new Cursor(Cursor.HAND_CURSOR));
editorToggle.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new SerpentEditor().setVisible(true);
}
});
}
});
JToggleButton logToggle = new JToggleButton();
logToggle.setIcon(image_2);
logToggle.setToolTipText("Log Console");
logToggle.setContentAreaFilled(true);
logToggle.setBackground(Color.WHITE);
logToggle.setBorderPainted(false);
logToggle.setFocusPainted(false);
logToggle.setCursor(new Cursor(Cursor.HAND_CURSOR));
logToggle.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ConnectionConsole().setVisible(true);
}
});
}
});
JToggleButton peersToggle = new JToggleButton();
peersToggle.setIcon(image_3);
peersToggle.setToolTipText("Peers");
peersToggle.setContentAreaFilled(true);
peersToggle.setBackground(Color.WHITE);
peersToggle.setBorderPainted(false);
peersToggle.setFocusPainted(false);
peersToggle.setCursor(new Cursor(Cursor.HAND_CURSOR));
peersToggle.addActionListener( new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
PeersTableMain mainFrame = new PeersTableMain();
mainFrame.setVisible( true );
// mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
cp.add(editorToggle);
cp.add(logToggle);
cp.add(peersToggle);
}
public static void main(String args[]){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ToolBar().setVisible(true);
}
});
}
}

View File

@ -0,0 +1,42 @@
package org.ethereum.manager;
import com.maxmind.geoip.Location;
import com.maxmind.geoip2.model.CityResponse;
import com.maxmind.geoip2.record.Country;
import org.ethereum.geodb.IpGeoDB;
import org.ethereum.net.vo.PeerData;
import java.util.*;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 21/04/14 20:35
*/
public class MainData {
private Set<PeerData> peers = Collections.synchronizedSet(new HashSet<PeerData>());
private List blocks = Collections.synchronizedList(new ArrayList());
private List transactions = Collections.synchronizedList(new ArrayList());
public static MainData instance = new MainData();
public void addPeers(List newPeers){
this.peers.addAll(newPeers);
for (PeerData peerData : this.peers){
Location location = IpGeoDB.getLocationForIp(peerData.getInetAddress());
if (location != null)
System.out.println("Hello: " + " [" + peerData.getInetAddress().toString()
+ "] " + location.countryName);
}
}
public void addBlocks(List blocks){}
public void addTransactions(List transactions){}
}

View File

@ -0,0 +1,121 @@
package org.ethereum.net;
/**
* www.openchain.info
* User: Roman Mandeleil
* Created on: 04/04/14 00:51
*/
public class MessageDeserializer {
/**
* Get exactly one message payload
*/
public static void deserialize(byte [] msgData, int level, int startPos, int endPos){
if (msgData == null || msgData.length == 0) return ;
int pos = startPos;
while(pos < endPos){
// It's a list with a payload more than 55 bytes
// data[0] - 0xF7 = how many next bytes allocated
// for the length of the list
if ((msgData[pos] & 0xFF) >= 0xF7){
byte lenghtOfLenght = (byte) (msgData[pos] - 0xF7);
byte pow = (byte) (lenghtOfLenght - 1);
int length = 0;
for (int i = 1; i <= lenghtOfLenght; ++i){
length += msgData[pos + i] << (8 * pow);
pow--;
}
// now we can parse an item for data[1]..data[length]
System.out.println("-- level: [" + level + "] Found big list length: " + length);
deserialize(msgData, level + 1, pos + lenghtOfLenght + 1, pos + lenghtOfLenght + length);
pos += lenghtOfLenght + length + 1 ;
continue;
}
// It's a list with a payload less than 55 bytes
if ((msgData[pos] & 0xFF) >= 0xC0 && (msgData[pos] & 0xFF) < 0xF7){
byte length = (byte) (msgData[pos] - 0xC0);
System.out.println("-- level: [" + level + "] Found small list length: " + length);
deserialize(msgData, level + 1, pos + 1, pos + length + 1);
pos += 1 + length;
continue;
}
// It's an item with a payload more than 55 bytes
// data[0] - 0xB7 = how much next bytes allocated for
// the length of the string
if ((msgData[pos] & 0xFF) >= 0xB7 && (msgData[pos] & 0xFF) < 0xC0) {
byte lenghtOfLenght = (byte) (msgData[pos] - 0xB7);
byte pow = (byte) (lenghtOfLenght - 1);
int length = 0;
for (int i = 1; i <= lenghtOfLenght; ++i){
length += msgData[pos + i] << (8 * pow);
pow--;
}
// now we can parse an item for data[1]..data[length]
System.out.println("-- level: [" + level + "] Found big item length: " + length);
pos += lenghtOfLenght + length + 1 ;
continue;
}
// It's an item less than 55 bytes long,
// data[0] - 0x80 == lenght of the item
if ((msgData[pos] & 0xFF) > 0x80 && (msgData[pos] & 0xFF) < 0xB7) {
byte length = (byte) (msgData[pos] - 0x80);
System.out.println("-- level: [" + level + "] Found small item length: " + length);
pos += 1 + length;
continue;
}
// null item
if ((msgData[pos] & 0xFF) == 0x80){
System.out.println("-- level: [" + level + "] Found null item: ");
pos += 1;
continue;
}
// single byte item
if ((msgData[pos] & 0xFF) < 0x80) {
System.out.println("-- level: [" + level + "] Found single item: ");
pos += 1;
continue;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,76 @@
package org.ethereum.net.client;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.ReadTimeoutHandler;
import org.ethereum.gui.PeerListener;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 10/04/14 12:28
*/
public class ClientPeer {
PeerListener peerListener;
public ClientPeer() {
}
public ClientPeer(PeerListener peerListener) {
this.peerListener = peerListener;
}
public void connect(String host, int port){
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(workerGroup);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.SO_KEEPALIVE, true);
final EthereumProtocolHandler handler;
if (peerListener != null){
handler = new EthereumProtocolHandler(peerListener);
peerListener.console("connecting to: " + host + ":" + port);
}
else
handler = new EthereumProtocolHandler();
b.handler(new ChannelInitializer<NioSocketChannel>() {
@Override
public void initChannel(NioSocketChannel ch) throws Exception {
ch.pipeline().addLast("readTimeoutHandler", new ReadTimeoutHandler(15));
ch.pipeline().addLast(new EthereumFrameDecoder());
ch.pipeline().addLast(handler);
}
});
// Start the client.
ChannelFuture f = b.connect(host, port).sync(); // (5)
// Wait until the connection is closed.
f.channel().closeFuture().sync();
} catch (InterruptedException ie){
System.out.println("-- ClientPeer: catch (InterruptedException ie) --");
ie.printStackTrace();
} finally {
workerGroup.shutdownGracefully();
}
}
}

View File

@ -0,0 +1,55 @@
package org.ethereum.net.client;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundBuffer;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.ReplayingDecoder;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 13/04/14 21:51
*/
public class EthereumFrameDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
// No header for Eth. message
if (in.readableBytes() < 8) return;
long magicBytes = in.readUnsignedInt();
long msgSize = in.readUnsignedInt();
if (!((magicBytes >> 24 & 0xFF) == 0x22 &&
(magicBytes >> 16 & 0xFF) == 0x40 &&
(magicBytes >> 8 & 0xFF) == 0x08 &&
(magicBytes & 0xFF) == 0x91 )){
System.out.println("Not ethereum packet");
ctx.close();
}
// Don't have the full packet yet
if (msgSize > in.readableBytes()) {
in.resetReaderIndex();
return;
}
byte[] decoded = new byte[(int)msgSize];
in.readBytes(decoded);
out.add(decoded);
// Chop the achieved data.
in.markReaderIndex();
}
}

View File

@ -0,0 +1,413 @@
package org.ethereum.net.client;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOption;
import io.netty.channel.FixedRecvByteBufAllocator;
import org.bouncycastle.util.encoders.Hex;
import org.ethereum.gui.PeerListener;
import org.ethereum.manager.MainData;
import org.ethereum.net.RLP;
import org.ethereum.net.message.*;
import org.ethereum.net.rlp.RLPList;
import org.ethereum.net.vo.BlockData;
import org.ethereum.util.Utils;
import java.util.*;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 10/04/14 08:19
*/
public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
final Timer timer = new Timer();
private final static byte[] MAGIC_PREFIX = {(byte)0x22, (byte)0x40, (byte)0x08, (byte)0x91};
private final static byte[] HELLO_MESSAGE = StaticMessages.HELLO_MESSAGE.getPayload();
private final static byte[] HELLO_MESSAGE_LEN = calcPacketLength(HELLO_MESSAGE);
private long lastPongTime = 0;
private boolean tearDown = false;
// hello data
private boolean handShaked = false;
private byte protocolVersion;
private byte networkId;
private String clientId;
private byte capabilities;
private short peerPort;
private byte[] peerId;
PeerListener peerListener;
public EthereumProtocolHandler() { }
public EthereumProtocolHandler(PeerListener peerListener) {
this.peerListener = peerListener;
}
@Override
public void channelActive(final ChannelHandlerContext ctx) {
// TODO: send hello
// TODO: send ping schedule another ping
// TODO: ByteBuf vs Stream vs new byte ???
final ByteBuf buffer = ctx.alloc().buffer(HELLO_MESSAGE.length + 8);
buffer.writeBytes(MAGIC_PREFIX);
buffer.writeBytes(HELLO_MESSAGE_LEN);
buffer.writeBytes(HELLO_MESSAGE);
ctx.writeAndFlush(buffer);
// sample for pinging in background
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
if (lastPongTime == 0) lastPongTime = System.currentTimeMillis();
if (tearDown) this.cancel();
long currTime = System.currentTimeMillis();
if (currTime - lastPongTime > 30000){
System.out.println("No ping answer for [30 sec]");
throw new Error("No ping return for 30 [sec]");
// TODO: shutdown the handler
}
System.out.println("[Send: PING]");
if (peerListener != null) peerListener.console("[Send: PING]");
sendPing(ctx);
}
}, 2000, 5000);
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
System.out.println("[Send: GET_PEERS]");
sendGetPeers(ctx);
}
}, 2000, 60000);
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
System.out.println("[Send: GET_TRANSACTIONS]");
sendGetTransactions(ctx);
}
}, 2000, 30000);
timer.schedule(new TimerTask() {
public void run() {
System.out.println("[Send: GET_CHAIN]");
sendGetChain(ctx);
}
}, 10000);
/*
timer.schedule(new TimerTask() {
public void run() {
System.out.println("[Send: TX]");
sendTx(ctx);
}
}, 10000);
*/
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
byte[] payload = (byte[]) msg;
System.out.print("msg: ");
Utils.printHexStringForByteArray(payload);
byte command = RLP.getCommandCode(payload);
// got HELLO
if ((int) (command & 0xFF) == 0x00) {
System.out.println("[Recv: HELLO]" );
RLPList rlpList = new RLPList();
RLP.parseObjects(payload, rlpList);
HelloMessage helloMessage = new HelloMessage(rlpList);
this.protocolVersion = helloMessage.getProtocolVersion();
this.networkId = helloMessage.getNetworkId();
this.clientId = helloMessage.getClientId();
this.capabilities = helloMessage.getCapabilities();
this.peerPort = helloMessage.getPeerPort();
this.peerId = helloMessage.getPeerId();
System.out.println(helloMessage.toString());
if (peerListener != null) peerListener.console(helloMessage.toString());
}
// got DISCONNECT
if ((int) (command & 0xFF) == 0x01) {
System.out.println("[Recv: DISCONNECT]");
if (peerListener != null) peerListener.console("[Recv: DISCONNECT]");
RLPList rlpList = new RLPList();
RLP.parseObjects(payload, rlpList);
DisconnectMessage disconnectMessage = new DisconnectMessage(rlpList);
System.out.println(disconnectMessage);
if (peerListener != null) peerListener.console(disconnectMessage.toString());
}
// got PING send pong
if ((int) (command & 0xFF) == 0x02) {
System.out.println("[Recv: PING]");
if (peerListener != null) peerListener.console("[Recv: PING]");
sendPong(ctx);
}
// got PONG mark it
if ((int) (command & 0xFF) == 0x03) {
System.out.println("[Recv: PONG]" );
if (peerListener != null) peerListener.console("[Recv: PONG]");
this.lastPongTime = System.currentTimeMillis();
}
// got GETPEERS send peers
if ((int) (command & 0xFF) == 0x10) {
System.out.println("[Recv: GETPEERS]" );
if (peerListener != null) peerListener.console("[Recv: GETPEERS]");
String answer = "22 40 08 91 00 00 00 50 F8 4E 11 F8 4B C5 36 81 " +
"CC 0A 29 82 76 5F B8 40 D8 D6 0C 25 80 FA 79 5C " +
"FC 03 13 EF DE BA 86 9D 21 94 E7 9E 7C B2 B5 22 " +
"F7 82 FF A0 39 2C BB AB 8D 1B AC 30 12 08 B1 37 " +
"E0 DE 49 98 33 4F 3B CF 73 FA 11 7E F2 13 F8 74 " +
"17 08 9F EA F8 4C 21 B0 ";
byte[] answerBytes = Utils.hexStringToByteArr(answer);
ByteBuf buffer = ctx.alloc().buffer(answerBytes.length);
buffer.writeBytes(answerBytes);
ctx.writeAndFlush(buffer);
// send getpeers
answer = "22 40 08 91 00 00 00 02 C1 10 ";
answerBytes = Utils.hexStringToByteArr(answer);
buffer = ctx.alloc().buffer(answerBytes.length);
buffer.writeBytes(answerBytes);
ctx.writeAndFlush(buffer);
}
// got PEERS
if ((int) (command & 0xFF) == 0x11) {
System.out.println("[Recv: PEERS]");
if (peerListener != null) peerListener.console("[Recv: PEERS]");
RLPList rlpList = new RLPList();
RLP.parseObjects(payload, rlpList);
PeersMessage peersMessage = new PeersMessage(rlpList);
MainData.instance.addPeers(peersMessage.getPeers());
System.out.println(peersMessage);
if (peerListener != null) peerListener.console(peersMessage.toString());
}
// got TRANSACTIONS
if ((int) (command & 0xFF) == 0x12) {
System.out.println("Recv: TRANSACTIONS]");
if (peerListener != null) peerListener.console("Recv: TRANSACTIONS]");
RLPList rlpList = new RLPList();
RLP.parseObjects(payload, rlpList);
TransactionsMessage transactionsMessage = new TransactionsMessage(rlpList);
MainData.instance.addTransactions(transactionsMessage.getTransactions());
// todo: if you got transactions send it to your peers
System.out.println(transactionsMessage);
if (peerListener != null) peerListener.console(transactionsMessage.toString());
}
// got BLOCKS
if ((int) (command & 0xFF) == 0x13) {
System.out.println("[Recv: BLOCKS]");
if (peerListener != null) peerListener.console("[Recv: BLOCKS]");
RLPList rlpList = new RLPList();
RLP.parseObjects(payload, rlpList);
BlocksMessage blocksMessage = new BlocksMessage(rlpList);
List<BlockData> list = blocksMessage.getBlockDataList();
MainData.instance.addBlocks(list);
System.out.println(blocksMessage);
if (peerListener != null) peerListener.console(blocksMessage.toString());
}
// got GETCHAIN
if ((int) (command & 0xFF) == 0x14) {
System.out.println("[Recv: GET_CHAIN]");
if (peerListener != null) peerListener.console("[Recv: GET_CHAIN]");
RLPList rlpList = new RLPList();
RLP.parseObjects(payload, rlpList);
GetChainMessage getChainMessage = new GetChainMessage(rlpList);
System.out.println(getChainMessage);
if (peerListener != null) peerListener.console(getChainMessage.toString());
}
// got NOTINCHAIN
if ((int) (command & 0xFF) == 0x15) {
System.out.println("[Recv: NOT_IN_CHAIN]");
if (peerListener != null) peerListener.console("[Recv: NOT_IN_CHAIN]");
RLPList rlpList = new RLPList();
RLP.parseObjects(payload, rlpList);
NotInChainMessage notInChainMessage = new NotInChainMessage(rlpList);
System.out.println(notInChainMessage);
if (peerListener != null) peerListener.console(notInChainMessage.toString());
}
// got GETTRANSACTIONS
if ((int) (command & 0xFF) == 0x16) {
System.out.println("[Recv: GET_TRANSACTIONS]");
if (peerListener != null) peerListener.console("[Recv: GET_TRANSACTIONS]");
// todo: send the queue of the transactions
}
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
// limit the size of recieving buffer to 1024
ctx.channel().config().setRecvByteBufAllocator(new FixedRecvByteBufAllocator(32368));
ctx.channel().config().setOption(ChannelOption.SO_RCVBUF, 32368);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
this.tearDown = true;
System.out.println("Lost connection to the server");
cause.printStackTrace();
ctx.close().sync();
timer.cancel();
}
private void sendMsg(Message msg, ChannelHandlerContext ctx){
byte[] data = msg.getPayload();
final ByteBuf buffer = ctx.alloc().buffer(data.length + 8);
byte[] packetLen = calcPacketLength(data);
buffer.writeBytes(MAGIC_PREFIX);
buffer.writeBytes(packetLen);
ctx.writeAndFlush(buffer);
}
private void sendPing(ChannelHandlerContext ctx){
ByteBuf buffer = ctx.alloc().buffer(StaticMessages.PING.length);
buffer.writeBytes(StaticMessages.PING);
ctx.writeAndFlush(buffer);
}
private void sendPong(ChannelHandlerContext ctx){
System.out.println("[Send: PONG]");
ByteBuf buffer = ctx.alloc().buffer(StaticMessages.PONG.length);
buffer.writeBytes(StaticMessages.PONG);
ctx.writeAndFlush(buffer);
}
private void sendGetPeers(ChannelHandlerContext ctx){
ByteBuf buffer = ctx.alloc().buffer(StaticMessages.GET_PEERS.length);
buffer.writeBytes(StaticMessages.GET_PEERS);
ctx.writeAndFlush(buffer);
}
private void sendGetTransactions(ChannelHandlerContext ctx){
ByteBuf buffer = ctx.alloc().buffer(StaticMessages.GET_TRANSACTIONS.length);
buffer.writeBytes(StaticMessages.GET_TRANSACTIONS);
ctx.writeAndFlush(buffer);
}
private void sendGetChain(ChannelHandlerContext ctx){
ByteBuf buffer = ctx.alloc().buffer(StaticMessages.GET_CHAIN.length);
buffer.writeBytes(StaticMessages.GET_CHAIN);
ctx.writeAndFlush(buffer);
}
private void sendTx(ChannelHandlerContext ctx){
byte[] TX_MSG =
Hex.decode("2240089100000070F86E12F86B80881BC16D674EC8000094CD2A3D9F938E13CD947EC05ABC7FE734DF8DD8268609184E72A00064801BA0C52C114D4F5A3BA904A9B3036E5E118FE0DBB987FE3955DA20F2CD8F6C21AB9CA06BA4C2874299A55AD947DBC98A25EE895AABF6B625C26C435E84BFD70EDF2F69");
ByteBuf buffer = ctx.alloc().buffer(TX_MSG.length);
buffer.writeBytes(TX_MSG);
ctx.writeAndFlush(buffer);
}
private static byte[] calcPacketLength(byte[] msg){
int msgLen = msg.length;
byte[] len = {
(byte)((msgLen >> 24) & 0xFF),
(byte)((msgLen >> 16) & 0xFF),
(byte)((msgLen >> 8) & 0xFF),
(byte)((msgLen ) & 0xFF)};
return len;
}
}

View File

@ -0,0 +1,79 @@
package org.ethereum.net.message;
import org.ethereum.net.RLP;
import org.ethereum.net.rlp.RLPItem;
import org.ethereum.net.rlp.RLPList;
import org.ethereum.net.vo.BlockData;
import org.ethereum.net.vo.TransactionData;
import java.util.ArrayList;
import java.util.List;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 06/04/14 14:56
*/
public class BlocksMessage extends Message {
private final byte commandCode = 0x13;
private List<BlockData> blockDataList = new ArrayList<BlockData>();
public BlocksMessage(RLPList rawData) {
super(rawData);
}
public void parseRLP() {
RLPList paramsList = (RLPList) rawData.getElement(0);
if (((RLPItem)(paramsList).getElement(0)).getData()[0] != commandCode){
throw new Error("BlocksMessage: parsing for mal data");
}
for (int i = 1; i < paramsList.size(); ++i){
RLPList rlpData = ((RLPList)paramsList.getElement(i));
BlockData blockData = new BlockData(rlpData);
this.blockDataList.add(blockData);
}
parsed = true;
}
@Override
public byte[] getPayload() {
return null;
}
public List<BlockData> getBlockDataList() {
if (!parsed) parseRLP();
return blockDataList;
}
public String toString(){
StringBuffer sb = new StringBuffer();
for (BlockData blockData : this.getBlockDataList()){
sb.append(" ").append( blockData.toString() ).append("\n");
List<TransactionData> transactions = blockData.getTransactionsList();
for (TransactionData transactionData : transactions){
sb.append("[").append(transactionData).append("]\n");
}
}
return "Blocks Message [\n" +
sb.toString()
+ " ]";
}
}

View File

@ -0,0 +1,72 @@
package org.ethereum.net.message;
import org.ethereum.net.rlp.RLPItem;
import org.ethereum.net.rlp.RLPList;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 06/04/14 14:56
*/
public class DisconnectMessage extends Message {
private final byte commandCode = 0x1;
private byte reason;
public static byte REASON_DISCONNECT_REQUESTED = 0x00;
public static byte REASON_TCP_ERROR = 0x01;
public static byte REASON_BAD_PROTOCOL = 0x02;
public static byte REASON_USELESS_PEER = 0x03;
public static byte REASON_TOO_MANY_PEERS = 0x04;
public static byte REASON_ALREADY_CONNECTED = 0x05;
public static byte REASON_WRONG_GENESIS = 0x06;
public static byte REASON_INCOMPATIBLE_PROTOCOL = 0x07;
public static byte REASON_PEER_QUITING = 0x08;
public DisconnectMessage(RLPList rawData) {
super(rawData);
}
@Override
public void parseRLP() {
RLPList paramsList = (RLPList) rawData.getElement(0);
if (((RLPItem)(paramsList).getElement(0)).getData()[0] != commandCode){
throw new Error("Disconnect: parsing for mal data");
}
byte[] reasonB = ((RLPItem)paramsList.getElement(1)).getData();
if (reasonB == null){
this.reason = 0;
} else {
this.reason = reasonB[0];
}
this.parsed = true;
// todo: what to do when mal data ?
}
@Override
public byte[] getPayload() {
return null;
}
public byte getReason() {
if (!parsed) parseRLP();
return reason;
}
public String toString(){
if (!parsed) parseRLP();
return "Disconnect Message [ reason=" + reason + " ]";
}
}

View File

@ -0,0 +1,85 @@
package org.ethereum.net.message;
import org.ethereum.net.RLP;
import org.ethereum.net.rlp.RLPItem;
import org.ethereum.net.rlp.RLPList;
import org.ethereum.util.Utils;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 06/04/14 14:56
*/
public class GetChainMessage extends Message {
private final byte commandCode = 0x14;
List<byte[]> blockHashList = new ArrayList<byte[]>();
BigInteger blockNum;
public GetChainMessage(RLPList rawData) {
super(rawData);
}
@Override
public void parseRLP() {
RLPList paramsList = (RLPList) rawData.getElement(0);
if (((RLPItem)(paramsList).getElement(0)).getData()[0] != commandCode){
throw new Error("GetChain: parsing for mal data");
}
int size = paramsList.size();
for (int i = 1; i < size - 1; ++i){
blockHashList.add(((RLPItem) paramsList.getElement(i)).getData());
}
// the last element is the num of requested blocks
byte[] blockNumB = ((RLPItem)paramsList.getElement(size - 1)).getData();
this.blockNum = new BigInteger(blockNumB);
this.parsed = true;
// todo: what to do when mal data ?
}
@Override
public byte[] getPayload() {
return null;
}
public List<byte[]> getBlockHashList() {
if (!parsed) parseRLP();
return blockHashList;
}
public BigInteger getBlockNum() {
if (!parsed) parseRLP();
return blockNum;
}
public String toString(){
if (!parsed) parseRLP();
StringBuffer sb = new StringBuffer();
for (byte[] blockHash : blockHashList){
sb.append("").append(Utils.toHexString(blockHash)).append(", ");
}
sb.append(" blockNum=").append(blockNum);
return "GetChain Message [" + sb.toString() + " ]";
}
}

View File

@ -0,0 +1,146 @@
package org.ethereum.net.message;
import org.bouncycastle.util.encoders.Hex;
import org.ethereum.net.RLP;
import org.ethereum.net.rlp.RLPItem;
import org.ethereum.net.rlp.RLPList;
import java.nio.ByteBuffer;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 06/04/14 14:56
*/
public class HelloMessage extends Message {
private final byte commandCode = 0x00;
private byte protocolVersion;
private byte networkId;
private String clientId;
private byte capabilities;
private short peerPort;
private byte[] peerId;
public HelloMessage(RLPList rawData) {
super(rawData);
}
public HelloMessage(byte protocolVersion, byte networkId, String clientId, byte capabilities, short peerPort, byte[] peerId) {
this.protocolVersion = protocolVersion;
this.networkId = networkId;
this.clientId = clientId;
this.capabilities = capabilities;
this.peerPort = peerPort;
this.peerId = peerId;
}
@Override
public void parseRLP() {
RLPList paramsList = (RLPList) rawData.getElement(0);
// the message does no distinguish between the 0 and null so here I check command code for null
// todo: find out if it can be 00
if (((RLPItem)(paramsList).getElement(0)).getData() != null){
throw new Error("HelloMessage: parsing for mal data");
}
this.protocolVersion = ((RLPItem) paramsList.getElement(1)).getData()[0];
byte[] networkIdBytes = ((RLPItem) paramsList.getElement(2)).getData();
this.networkId = networkIdBytes == null ? 0 : networkIdBytes[0] ;
this.clientId = new String(((RLPItem) paramsList.getElement(3)).getData());
this.capabilities = ((RLPItem) paramsList.getElement(4)).getData()[0];
ByteBuffer bb = ByteBuffer.wrap(((RLPItem) paramsList.getElement(5)).getData());
this.peerPort = bb.getShort();
this.peerId = ((RLPItem) paramsList.getElement(6)).getData();
this.parsed = true;
// todo: what to do when mal data ?
}
public byte[] getPayload(){
byte[] command = RLP.encodeByte(this.commandCode);
byte[] protocolVersion = RLP.encodeByte(this.protocolVersion);
byte[] networkId = RLP.encodeByte(this.networkId);
byte[] clientId = RLP.encodeString(this.clientId);
byte[] capabilities = RLP.encodeByte(this.capabilities);
byte[] peerPort = RLP.encodeShort(this.peerPort);
byte[] peerId = RLP.encodeElement(this.peerId);
byte[] data = RLP.encodeList(command, protocolVersion, networkId,
clientId, capabilities, peerPort, peerId);
return data;
}
public byte getCommandCode() {
if (!parsed) parseRLP();
return commandCode;
}
public byte getProtocolVersion() {
if (!parsed) parseRLP();
return protocolVersion;
}
public byte getNetworkId() {
if (!parsed) parseRLP();
return networkId;
}
public String getClientId() {
if (!parsed) parseRLP();
return clientId;
}
public byte getCapabilities() {
if (!parsed) parseRLP();
return capabilities;
}
public short getPeerPort() {
if (!parsed) parseRLP();
return peerPort;
}
public byte[] getPeerId() {
if (!parsed) parseRLP();
return peerId;
}
public String toString(){
return "Hello Message [ command=" + this.commandCode + " " +
" protocolVersion=" + this.protocolVersion + " " +
" networkId=" + this.networkId + " " +
" clientId= " + this.clientId + " " +
" capabilities= " + this.capabilities + " " +
" peerPort= " + this.peerPort + " " +
" peerId= " + Hex.toHexString(this.peerId) + " " +
"]";
}
}

View File

@ -0,0 +1,27 @@
package org.ethereum.net.message;
import org.ethereum.net.rlp.RLPList;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 06/04/14 14:58
*/
public abstract class Message {
RLPList rawData;
boolean parsed = false;
public Message(){}
public Message(RLPList rawData) {
this.rawData = rawData;
parsed = false;
}
public abstract void parseRLP();
public abstract byte[] getPayload();
}

View File

@ -0,0 +1,50 @@
package org.ethereum.net.message;
import org.ethereum.net.message.Message;
import org.ethereum.net.rlp.RLPItem;
import org.ethereum.net.rlp.RLPList;
import org.ethereum.util.Utils;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 06/04/14 14:56
*/
public class NotInChainMessage extends Message {
private final byte commandCode = 0x15;
private byte[] hash;
public NotInChainMessage(RLPList rawData) {
super(rawData);
}
@Override
public void parseRLP() {
RLPList paramsList = (RLPList) rawData.getElement(0);
if ((((RLPItem)(paramsList).getElement(0)).getData()[0] & 0xFF) != commandCode){
throw new Error("NotInChain Message: parsing for mal data");
}
hash = ((RLPItem)paramsList.getElement(1)).getData();
}
@Override
public byte[] getPayload() {
return null;
}
public byte[] getHash() {
return hash;
}
public String toString(){
if (!parsed) parseRLP();
return "NotInChain Message [" + Utils.toHexString(hash) + "]";
}
}

View File

@ -0,0 +1,120 @@
package org.ethereum.net.message;
import org.ethereum.net.RLP;
import org.ethereum.net.message.Message;
import org.ethereum.net.rlp.RLPItem;
import org.ethereum.net.rlp.RLPList;
import org.ethereum.net.vo.PeerData;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 06/04/14 14:56
*/
public class PeersMessage extends Message {
private final byte commandCode = 0x11;
RLPList rawData;
boolean parsed = false;
List<PeerData> peers = new ArrayList<PeerData>();
public PeersMessage(){}
public PeersMessage(RLPList rawData) {
this.rawData = rawData;
parsed = false;
}
@Override
public void parseRLP() {
RLPList paramsList = (RLPList) rawData.getElement(0);
if ((((RLPItem)(paramsList).getElement(0)).getData()[0] & 0xFF) != commandCode){
throw new Error("PeersMessage: parsing for mal data");
}
for (int i = 1; i < paramsList.size(); ++i){
RLPList peerParams = (RLPList)paramsList.getElement(i);
RLPItem ip_a = (RLPItem)((RLPList) peerParams.getElement(0)).getElement(0);
RLPItem ip_b = (RLPItem)((RLPList) peerParams.getElement(0)).getElement(1);
RLPItem ip_c = (RLPItem)((RLPList) peerParams.getElement(0)).getElement(2);
RLPItem ip_d = (RLPItem)((RLPList) peerParams.getElement(0)).getElement(3);
byte ipA = ip_a.getData() == null ? 0 : ip_a.getData()[0];
byte ipB = ip_b.getData() == null ? 0 : ip_b.getData()[0];
byte ipC = ip_c.getData() == null ? 0 : ip_c.getData()[0];
byte ipD = ip_d.getData() == null ? 0 : ip_d.getData()[0];
byte[] ip = new byte[]{ipA, ipB, ipC, ipD};
byte[] shortData = ((RLPItem) peerParams.getElement(1)).getData();
short peerPort = 0;
if (shortData.length == 1)
peerPort = shortData[0];
else{
ByteBuffer bb = ByteBuffer.wrap(shortData, 0, shortData.length);
peerPort = bb.getShort();
}
byte[] peerId = ((RLPItem) peerParams.getElement(2)).getData();
PeerData peer = new PeerData(ip, peerPort, peerId);
peers.add(peer);
}
this.parsed = true;
// todo: what to do when mal data ?
}
@Override
public byte[] getPayload() {
return null;
}
public List<PeerData> getPeers() {
if (!parsed){
parseRLP();
}
return peers;
}
public String toString(){
if (!parsed){
parseRLP();
}
StringBuffer sb = new StringBuffer();
for (PeerData peerData : peers){
sb.append("[").append(peerData).append("] \n ");
}
return "Peers Message [\n " + sb.toString() + "]";
}
}

View File

@ -0,0 +1,81 @@
package org.ethereum.net.message;
import org.ethereum.util.Utils;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 13/04/14 20:19
*/
public class StaticMessages {
public static final byte[] PING = {(byte)0x22, (byte)0x40, (byte)0x08, (byte)0x91,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02,
(byte)0xC1, (byte)0x02 };
public static final byte[] PONG = {(byte)0x22, (byte)0x40, (byte)0x08, (byte)0x91,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02,
(byte)0xC1, (byte)0x03 };
public static final byte[] GET_PEERS = {(byte)0x22, (byte)0x40, (byte)0x08, (byte)0x91,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02,
(byte)0xC1, (byte)0x10 };
public static final byte[] GET_TRANSACTIONS = {(byte)0x22, (byte)0x40, (byte)0x08, (byte)0x91,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02,
(byte)0xC1, (byte)0x16 };
public static final byte[] DISCONNECT_00 = {(byte)0x22, (byte)0x40, (byte)0x08, (byte)0x91,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x03,
(byte)0xC2, (byte)0x01, (byte)0x00};
public static final byte[] DISCONNECT_01 = {(byte) 0x22, (byte) 0x40, (byte) 0x08, (byte) 0x91,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03,
(byte) 0xC2, (byte) 0x01, (byte) 0x01};
public static final byte[] DISCONNECT_02 = {(byte) 0x22, (byte) 0x40, (byte) 0x08, (byte) 0x91,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03,
(byte) 0xC2, (byte) 0x01, (byte) 0x02};
public static final byte[] DISCONNECT_03 = {(byte) 0x22, (byte) 0x40, (byte) 0x08, (byte) 0x91,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03,
(byte) 0xC2, (byte) 0x01, (byte) 0x03};
public static final byte[] DISCONNECT_08 = {(byte) 0x22, (byte) 0x40, (byte) 0x08, (byte) 0x91,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03,
(byte) 0xC2, (byte) 0x01, (byte) 0x08};
public static final byte[] GET_CHAIN = {
(byte) 0x22, (byte) 0x40, (byte) 0x08, (byte) 0x91, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x27,
(byte) 0xF8, (byte) 0x25, (byte) 0x14, (byte) 0xA0, (byte) 0xAB, (byte) 0x6B, (byte) 0x9A, (byte) 0x56, (byte) 0x13,
(byte) 0x97, (byte) 0x0F, (byte) 0xAA, (byte) 0x77, (byte) 0x1B, (byte) 0x12, (byte) 0xD4, (byte) 0x49,
(byte) 0xB2, (byte) 0xE9, (byte) 0xBB, (byte) 0x92, (byte) 0x5A, (byte) 0xB7, (byte) 0xA3, (byte) 0x69,
(byte) 0xF0, (byte) 0xA4, (byte) 0xB8, (byte) 0x6B, (byte) 0x28, (byte) 0x6E, (byte) 0x9D, (byte) 0x54,
(byte) 0x00, (byte) 0x99, (byte) 0xCF, (byte) 0x82, (byte) 0x01, (byte) 0x00,
};
static {
String peerId = "CE 73 F1 F1 F1 F1 6C 1B 3F DA 7B 18 EF 7B A3 CE " +
"17 B6 F1 F1 F1 F1 41 D3 C6 C6 54 B7 AE 88 B2 39 " +
"40 7F F1 F1 F1 F1 19 02 5D 78 57 27 ED 01 7B 6A " +
"DD 21 F1 F1 F1 F1 00 00 01 E3 21 DB C3 18 24 BA ";
byte[] peerIdBytes = Utils.hexStringToByteArr(peerId);
HELLO_MESSAGE = new HelloMessage((byte)0x0C, (byte)0x00, "EthereumJ [v0.0.1] pure java [by Roman Mandeleil]",
(byte)0b00000111, (short)30303, peerIdBytes);
/*
HELLO_MESSAGE = new HelloMessage((byte)0x0B, (byte)0x00, "EthereumJ [v0.0.1] pure java [by Roman Mandeleil]",
(byte)0b00000111, (short)30303, peerIdBytes);
*/
}
public static final HelloMessage HELLO_MESSAGE;
}

View File

@ -0,0 +1,73 @@
package org.ethereum.net.message;
import org.ethereum.net.rlp.RLPItem;
import org.ethereum.net.rlp.RLPList;
import org.ethereum.net.vo.TransactionData;
import java.util.ArrayList;
import java.util.List;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 06/04/14 14:56
*/
public class TransactionsMessage extends Message {
private final byte commandCode = 0x12;
private List<TransactionData> transactions = new ArrayList<TransactionData>();
public TransactionsMessage() {
}
public TransactionsMessage(RLPList rawData) {
super(rawData);
}
@Override
public void parseRLP() {
RLPList paramsList = (RLPList) rawData.getElement(0);
if ((((RLPItem)(paramsList).getElement(0)).getData()[0] & 0xFF) != commandCode){
throw new Error("TransactionMessage: parsing for mal data");
}
transactions = new ArrayList<TransactionData>();
int size = paramsList.getList().size();
for (int i = 1; i < size; ++i){
RLPList rlpTxData = (RLPList) paramsList.getElement(i);
TransactionData tx = new TransactionData(rlpTxData);
transactions.add(tx);
}
parsed = true;
}
public List<TransactionData> getTransactions() {
if (!parsed) parseRLP();
return transactions;
}
@Override
public byte[] getPayload() {
return null;
}
public String toString(){
if(!parsed)parseRLP();
StringBuffer sb = new StringBuffer();
for (TransactionData transactionData : transactions){
sb.append(" ").append(transactionData).append("\n");
}
return "Transactions Message [\n" + sb.toString() + " ]";
}
}

View File

@ -0,0 +1,10 @@
package org.ethereum.net.rlp;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 21/04/14 16:28
*/
public interface RLPElement {
}

View File

@ -0,0 +1,24 @@
package org.ethereum.net.rlp;
import org.bouncycastle.util.Arrays;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 21/04/14 16:26
*/
public class RLPItem implements RLPElement{
byte[] data;
public RLPItem(byte[] data) {
this.data = data;
}
public byte[] getData() {
if (data.length == 0) return null;
return data;
}
}

View File

@ -0,0 +1,77 @@
package org.ethereum.net.rlp;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Hex;
import org.ethereum.util.Utils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 21/04/14 16:26
*/
public class RLPList implements RLPElement{
byte[] rlpData;
List<RLPElement> list;
public RLPList() {
this.list = new ArrayList<RLPElement>();
}
public void addItem(RLPElement element){
list.add(element);
}
public RLPElement getElement(int index){
return list.get(index);
}
public int size(){
return list.size();
}
public List<RLPElement> getList(){
return list;
}
public void setRLPData(byte[] rlpData){
this.rlpData = rlpData;
}
public byte[] getRLPData(){
return rlpData;
}
public static void recursivePrint(RLPElement element){
if (element == null) throw new Error("RLPElement object can't be null");
if (element instanceof RLPList){
RLPList rlpList = (RLPList)element;
System.out.print("[");
for (RLPElement singleElement : rlpList.getList()){
recursivePrint(singleElement);
}
System.out.print("]");
} else {
String hex = Utils.toHexString(((RLPItem) element).getData());
System.out.print(hex + ", ");
}
}
}

View File

@ -0,0 +1,179 @@
package org.ethereum.net.vo;
import org.ethereum.net.rlp.RLPElement;
import org.ethereum.net.rlp.RLPItem;
import org.ethereum.net.rlp.RLPList;
import org.ethereum.util.Utils;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 13/04/14 19:34
*/
public class BlockData {
RLPList rawData;
boolean parsed = false;
private byte[] hash;
private byte[] parentHash;
private byte[] unclesHash;
private byte[] coinbase;
private byte[] stateHash;
private byte[] txListHash;
private byte[] difficulty;
private long timestamp;
private byte[] extraData;
private byte[] nonce;
List<TransactionData> transactionsList = new ArrayList<TransactionData>();
List<BlockData> uncleList = new ArrayList<BlockData>();
public BlockData(RLPList rawData) {
this.rawData = rawData;
this.parsed = false;
}
public BlockData(byte[] parentHash, byte[] unclesHash, byte[] coinbase, byte[] stateHash, byte[] txListHash, byte[] difficulty, long timestamp, byte[] extraData, byte[] nonce, List<TransactionData> transactionsList, List uncleList) {
this.parentHash = parentHash;
this.unclesHash = unclesHash;
this.coinbase = coinbase;
this.stateHash = stateHash;
this.txListHash = txListHash;
this.difficulty = difficulty;
this.timestamp = timestamp;
this.extraData = extraData;
this.nonce = nonce;
this.transactionsList = transactionsList;
this.uncleList = uncleList;
this.parsed = true;
}
// [parent_hash, uncles_hash, coinbase, state_root, tx_list_hash, difficulty, timestamp, extradata, nonce]
private void parseRLP(){
this.hash = Utils.sha3(rawData.getRLPData());
List params = ((RLPList) rawData.getElement(0)).getList();
this.parentHash = ((RLPItem) params.get(0)).getData();
this.unclesHash = ((RLPItem) params.get(1)).getData();
this.coinbase = ((RLPItem) params.get(2)).getData();
this.stateHash = ((RLPItem) params.get(3)).getData();
this.txListHash = ((RLPItem) params.get(4)).getData();
this.difficulty = ((RLPItem) params.get(5)).getData();
byte[] tsBytes = ((RLPItem) params.get(6)).getData();
this.timestamp = (new BigInteger(tsBytes)).longValue();
this.extraData = ((RLPItem) params.get(7)).getData();
this.nonce = ((RLPItem) params.get(8)).getData();
// parse transactions
List<RLPElement> transactions = ((RLPList) rawData.getElement(1)).getList();
for (RLPElement rlpTx : transactions){
TransactionData tx = new TransactionData((RLPList)rlpTx);
this.transactionsList.add(tx);
}
// parse uncles
List<RLPElement> uncleBlocks = ((RLPList) rawData.getElement(2)).getList();
for (RLPElement rawUncle : uncleBlocks){
BlockData blockData = new BlockData((RLPList)rawUncle);
this.uncleList.add(blockData);
}
this.parsed = true;
}
public byte[] getHash(){
if (!parsed) parseRLP();
return hash;
}
public byte[] getParentHash() {
if (!parsed) parseRLP();
return parentHash;
}
public byte[] getUnclesHash() {
if (!parsed) parseRLP();
return unclesHash;
}
public byte[] getCoinbase() {
if (!parsed) parseRLP();
return coinbase;
}
public byte[] getStateHash() {
if (!parsed) parseRLP();
return stateHash;
}
public byte[] getTxListHash() {
if (!parsed) parseRLP();
return txListHash;
}
public byte[] getDifficulty() {
if (!parsed) parseRLP();
return difficulty;
}
public long getTimestamp() {
if (!parsed) parseRLP();
return timestamp;
}
public byte[] getExtraData() {
if (!parsed) parseRLP();
return extraData;
}
public byte[] getNonce() {
if (!parsed) parseRLP();
return nonce;
}
public List<TransactionData> getTransactionsList() {
if (!parsed) parseRLP();
return transactionsList;
}
public List<BlockData> getUncleList() {
if (!parsed) parseRLP();
return uncleList;
}
// [parent_hash, uncles_hash, coinbase, state_root, tx_list_hash, difficulty, timestamp, extradata, nonce]
@Override
public String toString() {
if (!parsed) parseRLP();
return "BlockData [" + " hash=" + Utils.toHexString(hash) +
" parentHash=" + Utils.toHexString(parentHash) +
", unclesHash=" + Utils.toHexString(unclesHash) +
", coinbase=" + Utils.toHexString(coinbase) +
", stateHash=" + Utils.toHexString(stateHash) +
", txListHash=" + Utils.toHexString(txListHash) +
", difficulty=" + Utils.toHexString(difficulty) +
", timestamp=" + timestamp +
", extraData=" + Utils.toHexString(extraData) +
", nonce=" + Utils.toHexString(nonce) +
']';
}
}

View File

@ -0,0 +1,97 @@
package org.ethereum.net.vo;
import org.bouncycastle.util.encoders.Hex;
import org.ethereum.net.rlp.RLPList;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 13/04/14 17:36
*/
public class PeerData {
RLPList rawData;
boolean parsed = false;
byte[] ip;
short port;
byte[] peerId;
transient boolean isOnline = false;
transient long lastCheckTime = 0;
public PeerData(RLPList rlpList){
rawData = rlpList;
parsed = false;
}
public PeerData(byte[] ip, short port, byte[] peerId) {
this.ip = ip;
this.port = port;
this.peerId = peerId;
parsed = true;
}
public InetAddress getInetAddress(){
InetAddress addr = null;
try {
addr = InetAddress.getByAddress(ip);
} catch (UnknownHostException e) {
e.printStackTrace();
throw new Error("malformed ip");
}
return addr;
}
public byte[] getIp() {
return ip;
}
public short getPort() {
return port;
}
public byte[] getPeerId() {
return peerId;
}
public boolean isOnline() {
return isOnline;
}
public void setOnline(boolean online) {
isOnline = online;
}
public long getLastCheckTime() {
return lastCheckTime;
}
public void setLastCheckTime(long lastCheckTime) {
this.lastCheckTime = lastCheckTime;
}
@Override
public String toString() {
return "Peer: [ ip=" + getInetAddress()+ ", port=" + getPort() + ", peerId=" + Hex.toHexString( getPeerId() ) + "]";
}
@Override
public boolean equals(Object obj) {
PeerData peerData2 = (PeerData)obj;
return this.getInetAddress().equals(peerData2.getInetAddress());
}
@Override
public int hashCode() {
return getInetAddress().hashCode();
}
}

View File

@ -0,0 +1,187 @@
package org.ethereum.net.vo;
import org.ethereum.net.rlp.RLPItem;
import org.ethereum.net.rlp.RLPList;
import org.ethereum.util.Utils;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 21/04/14 09:19
*/
public class TransactionData {
RLPList rawData;
boolean parsed = false;
// creation contract tx or simple send tx
// [ nonce, value, receiveAddress, gasPrice, gasDeposit, data, signatureV, signatureR, signatureS ]
// or
// [ nonce, endowment, 0, gasPrice, gasDeposit (for init), body, init, signatureV, signatureR, signatureS ]
byte[] hash;
byte[] nonce;
byte[] value;
// In creation transaction the receive address is - 0
byte[] receiveAddress;
byte[] gasPrice;
byte[] gas;
// Contract creation [data] will hold the contract
// for other transaction [data] can hold data
byte[] data;
byte[] init;
// Signature
byte signatureV;
byte[] signatureR;
byte[] signatureS;
public TransactionData(RLPList rawData) {
this.rawData = rawData;
parsed = false;
}
public TransactionData(byte[] nonce, byte[] value, byte[] recieveAddress, byte[] gasPrice, byte[] gas, byte[] data, byte signatureV, byte[] signatureR, byte[] signatureS) {
this.nonce = nonce;
this.value = value;
this.receiveAddress = recieveAddress;
this.gasPrice = gasPrice;
this.gas = gas;
this.data = data;
this.signatureV = signatureV;
this.signatureR = signatureR;
this.signatureS = signatureS;
parsed = true;
}
public void rlpParse(){
if (rawData.size() == 9){ // Simple transaction
this.hash = Utils.sha3(rawData.getRLPData());
this.nonce = ((RLPItem) rawData.getElement(0)).getData();
this.value = ((RLPItem) rawData.getElement(1)).getData();
this.receiveAddress = ((RLPItem) rawData.getElement(2)).getData();
this.gasPrice = ((RLPItem) rawData.getElement(3)).getData();
this.gas = ((RLPItem) rawData.getElement(4)).getData();
this.data = ((RLPItem) rawData.getElement(5)).getData();
this.signatureV = ((RLPItem) rawData.getElement(6)).getData()[0];
this.signatureR = ((RLPItem) rawData.getElement(7)).getData();
this.signatureS = ((RLPItem) rawData.getElement(8)).getData();
} else if (rawData.size() == 10){ // Contract creation transaction
this.hash = Utils.sha3(rawData.getRLPData());
this.nonce = ((RLPItem) rawData.getElement(0)).getData();
this.value = ((RLPItem) rawData.getElement(1)).getData();
this.receiveAddress = ((RLPItem) rawData.getElement(2)).getData();
this.gasPrice = ((RLPItem) rawData.getElement(3)).getData();
this.gas = ((RLPItem) rawData.getElement(4)).getData();
this.data = ((RLPItem) rawData.getElement(5)).getData();
this.init = ((RLPItem) rawData.getElement(6)).getData();
this.signatureV = ((RLPItem) rawData.getElement(7)).getData()[0];
this.signatureR = ((RLPItem) rawData.getElement(8)).getData();
this.signatureS = ((RLPItem) rawData.getElement(9)).getData();
} else throw new Error("Wrong tx data element list size");
this.parsed = true;
}
public RLPList getRawData() {
return rawData;
}
public boolean isParsed() {
return parsed;
}
public byte[] getHash() {
if (!parsed) rlpParse();
return hash;
}
public byte[] getNonce() {
if (!parsed) rlpParse();
return nonce;
}
public byte[] getValue() {
if (!parsed) rlpParse();
return value;
}
public byte[] getReceiveAddress() {
if (!parsed) rlpParse();
return receiveAddress;
}
public byte[] getGasPrice() {
if (!parsed) rlpParse();
return gasPrice;
}
public byte[] getGas() {
if (!parsed) rlpParse();
return gas;
}
public byte[] getData() {
if (!parsed) rlpParse();
return data;
}
public byte[] getInit() {
if (!parsed) rlpParse();
return init;
}
public byte getSignatureV() {
if (!parsed) rlpParse();
return signatureV;
}
public byte[] getSignatureR() {
if (!parsed) rlpParse();
return signatureR;
}
public byte[] getSignatureS() {
if (!parsed) rlpParse();
return signatureS;
}
@Override
public String toString() {
if (!parsed) rlpParse();
return "TransactionData [" + " hash=" + Utils.toHexString(hash) +
" nonce=" + Utils.toHexString(nonce) +
", value=" + Utils.toHexString(value) +
", receiveAddress=" + Utils.toHexString(receiveAddress) +
", gasPrice=" + Utils.toHexString(gasPrice) +
", gas=" + Utils.toHexString(gas) +
", data=" + Utils.toHexString(data) +
", init=" + Utils.toHexString(init) +
", signatureV=" + signatureV +
", signatureR=" + Utils.toHexString(signatureR) +
", signatureS=" + Utils.toHexString(signatureS) +
']';
}
}

View File

@ -0,0 +1,19 @@
package org.ethereum.serpent;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 25/04/14 17:06
*/
public class GenParser {
public static void main(String args[]){
String userDir = System.getProperty("user.dir");
org.antlr.Tool.main(new String[]{userDir + "\\src\\main\\java\\org\\ethereum\\serpent\\Serpent.g"});
// org.antlr.Tool.main(new String[]{userDir + "\\src\\main\\java\\samples\\antlr\\PyEsque.g"});
}
}

View File

@ -0,0 +1,248 @@
/*******************************************************************************
* Ethereum high level language grammar definition
*******************************************************************************/
grammar Serpent;
options {
//language = Java;
//output = AST;
output = template;
}
@header {
/* (!!!) Do not update this file manually ,
* It was auto generated from the Serpent.g
* grammar file.
*/
package org.ethereum.serpent;
import org.ethereum.util.Utils;
}
@lexer::header {
/* (!!!) Do not update this file manually ,
* It was auto generated from the Serpent.g
* grammar file.
*/
package org.ethereum.serpent;
}
@members {
private java.util.ArrayList<String> globals = new java.util.ArrayList<String>();
private int labelIndex = 0;
}
program
: gen_body
{
String conVars = "";
if (globals.size() > 0){
conVars = "0 " + (globals.size() * 32 - 1) + " MSTORE8";
}
}
-> concat(left={conVars}, right={$gen_body.st})
;
test_1
:
(
set_var -> concat(left={$test_1.st}, right={$set_var.st})
| get_var -> concat(left={$test_1.st}, right={$get_var.st}) )*
;
/*
test_2
:
(
set_var -> concat(left={$test_2.st}, right={$set_var.st})
)*
(
if_stmt -> concat(left={$test_2.st}, right={$if_stmt.st})
| if_else_stmt -> concat(left={$test_2.st}, right={$if_else_stmt.st})
)
;
*/
gen_body
:
(
set_var -> concat(left={$gen_body.st}, right={$set_var.st})
| storage_save -> concat(left={$gen_body.st}, right={$storage_save.st})
| return_stmt -> concat(left={$gen_body.st}, right={$return_stmt.st})
)* ( if_else_stmt -> concat(left={$gen_body.st}, right={$if_else_stmt.st}))?
;
// [if a==10:\n b=20 \n]
// [10, 0, 'MLOAD', 'EQ', 'NOT', 'REF_0', 'JUMPI', 20, 32, 'MSTORE', 'LABEL_0']
if_stmt
:
'if' unr_expr ':' gen_body
// (!!!)RECURSION ON if_stmt ( 'elif' cond_expr ':' elif_body=set_var )*
-> ifStmt(cond={$unr_expr.st}, body={$gen_body.st}, index={labelIndex++})
;
// [if a==10:\n b=20 \nelse: \n b=30]
// [10, 0, 'MLOAD', 'EQ', 'NOT', 'REF_1', 'JUMPI', 20, 32, 'MSTORE', 'REF_0', 'JUMP', 'LABEL_1', 30, 32, 'MSTORE', 'LABEL_0']
// a 10 EQ NOT REF_01 JUMPI 30 0 MSTORE REF_0 JUMP LABEL_01 20 0 MSTORE LABEL_0
if_else_stmt
:
'if' unr_expr ':' if_body=gen_body
// (!!!)RECURSION ON if_stmt ( 'elif' unr_expr ':' elif_body=set_var )*
'else' ':' else_body=gen_body -> ifElseStmt(cond={$unr_expr.st}, if_body={$if_body.st},
else_body={$else_body.st}, if_index={labelIndex++}, else_index={labelIndex++}) ;
// [multi_set_var] (a=set_var->compile(left={$program.st}, right={$a.st}))*
set_var
:
{int varIndex = -1;}
(a=var { // TODO: change it from atom to something else
// check if that variable already defined
// if it didn't add it to list
// if it did use the index * 32 for memory address
varIndex = globals.indexOf($a.st.toString());
if (varIndex == -1 ) {globals.add($a.st.toString()); varIndex = globals.size() - 1; }
}
'=' b=bin_expr) -> set_var(param_a={$b.st}, param_b={32 * varIndex})
;
get_var
:
{int varIndex = -1;}
(a=var {
// If there is no such var throw exception
varIndex = globals.indexOf($a.st.toString());
if (varIndex == -1 ) {
Error err = new Error("var undefined: " + $a.st.toString());
throw err;
}
;}
-> get_var(varIndex={32 * varIndex})
)
;
unr_expr
:
{boolean negative = false;}
('!' {negative = !negative;} )* a=cond_expr -> not(param={negative? $a.st : $a.st + " NOT"})
;
cond_expr
: a=bin_expr
(
'==' b=bin_expr -> equals(left={$a.st},right={$b.st}) |
'<' b=bin_expr -> lessThan(left={$a.st},right={$b.st}) |
'<=' b=bin_expr -> lessEqThan(left={$a.st},right={$b.st}) |
'>=' b=bin_expr -> greatEqThan(left={$a.st},right={$b.st}) |
'>' b=bin_expr -> greatThan(left={$a.st},right={$b.st})
| -> {$a.st}
)
;
storage_save
: 'contract.storage['index=bin_expr']' '=' assignment=bin_expr -> ssave(index={$index.st}, data={$assignment.st})
;
bin_expr
: (a=atom -> {$a.st})
(( '+' b=atom -> add(left={$bin_expr.st}, right={$b.st}) |
'-' b=atom -> sub(left={$bin_expr.st}, right={$b.st}) |
'*' b=atom -> mul(left={$bin_expr.st}, right={$b.st}) |
'/' b=atom -> div(left={$bin_expr.st}, right={$b.st}) |
'^' b=atom -> exp(left={$bin_expr.st}, right={$b.st}) |
'%' b=atom -> mod(left={$bin_expr.st}, right={$b.st}) |
'#/' b=atom -> sdiv(left={$bin_expr.st}, right={$b.st}) |
'#%' b=atom -> smod(left={$bin_expr.st}, right={$b.st})
)*)
;
// "if !a==10:\n b=20 \nelse: \n b=30"
atom
:
storage_load -> iconst(value={$storage_load.st})
| msg_sender -> iconst(value={$msg_sender.st})
| msg_datasize -> iconst(value={$msg_datasize.st})
| msg_load -> iconst(value={$msg_load.st})
| get_var -> iconst(value={$get_var.st})
| INTEGER -> iconst(value={$INTEGER.text})
| hex_num -> iconst(value={$hex_num.st})
;
hex_num
:
HEX_NUMBER
{
String dec_num = Utils.hexStringToDecimalString($HEX_NUMBER.text);
}
-> iconst(value={dec_num})
;
var
: IDENT -> refVar(id={$IDENT.text} )
;
storage_load
: 'contract.storage['bin_expr']' -> sload(index={$bin_expr.st})
;
msg_load
: 'msg.data['bin_expr']' -> calldataload(index={$bin_expr.st})
;
msg_sender
: 'msg.sender' -> msdSender()
;
msg_datasize
: 'msg.datasize' -> msgDatasize()
;
return_stmt
: 'return('bin_expr')' -> returnStmt(index={$bin_expr.st})
;
fragment LETTER : ('a'..'z' | 'A'..'Z') ;
fragment DIGIT : '0'..'9';
INTEGER : DIGIT+ ;
IDENT : LETTER (LETTER | DIGIT)*;
fragment HEX_DIGIT : ('0'..'9' | 'a'..'f' | 'A'..'F');
HEX_NUMBER : ('0x' | '0X' )HEX_DIGIT+;
WS : (' ' | '\t' | '\n' | '\r' | '\f')+ {$channel = HIDDEN;};
COMMENT : '//' .* ('\n'|'\r') {$channel = HIDDEN;};

View File

@ -0,0 +1,116 @@
group Serpent2Asm;
/** https://github.com/rollxx/antlr-php-runtime/blob/master/examples/cminus/Bytecode.stg */
// [10, 0, 'MLOAD', 'EQ', 'NOT', 'REF_0', 'JUMPI', 20, 32, 'MSTORE', 'LABEL_0']
ifStmt(cond, body, index) ::=<<
<cond> NOT REF_<index> JUMPI <body> LABEL_<index>
>>
// [10, 0, MLOAD, EQ, NOT, REF_1, JUMPI, 20, 32, MSTORE, REF_0, JUMP, LABEL_1, 30, 32, MSTORE, LABEL_0]
ifElseStmt(cond, if_body, else_body, if_index, else_index) ::=<<
<cond> NOT REF_<if_index> JUMPI <else_body> REF_<else_index> JUMP LABEL_<if_index> <if_body> LABEL_<else_index>
>>
set_var(param_a, param_b) ::= <<
<param_a> <param_b> MSTORE
>>
get_var(varIndex) ::= <<
<varIndex> MLOAD
>>
compile(left, right) ::= <<
<left> <right>
>>
add(left,right) ::= <<
<left> <right> ADD
>>
sub(left,right) ::= <<
<left> <right> SUB
>>
mul(left,right) ::= <<
<left> <right> MUL
>>
div(left,right) ::= <<
<left> <right> DIV
>>
exp(left,right) ::= <<
<left> <right> EXP
>>
mod(left,right) ::= <<
<left> <right> MOD
>>
sdiv(left,right) ::= <<
<left> <right> SDIV
>>
smod(left,right) ::= <<
<left> <right> SMOD
>>
equals(left,right) ::= <<
<left> <right> EQ
>>
lessThan(left,right) ::= <<
<left> <right> LT
>>
lessEqThan(left,right) ::= <<
<left> <right> GT NOT
>>
greatThan(left,right) ::= <<
<left> <right> GT
>>
greatEqThan(left,right) ::= <<
<left> <right> LT NOT
>>
not(param) ::= <<
<param> NOT
>>
sload(index) ::= <<
<index> SLOAD
>>
ssave(index, data) ::= <<
<data> <index> SSTORE
>>
calldataload(index) ::=<<
<index> 32 MUL CALLDATALOAD
>>
msdSender() ::=<<
CALLER
>>
msgDatasize() ::=<<
32 CALLDATASIZE DIV
>>
returnStmt(index) ::= <<
<index> MSIZE SWAP MSIZE MSTORE 32 SWAP RETURN
>>
concat(left, right) ::= <<
<left> <right>
>>
refVar(id) ::= "<id>"
iconst(value) ::= "<value>"

View File

@ -0,0 +1,43 @@
package org.ethereum.serpent;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.language.AngleBracketTemplateLexer;
import java.io.FileNotFoundException;
import java.io.FileReader;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 29/04/14 12:34
*/
public class SerpentCompiler{
public static String compile(String code) throws FileNotFoundException, RecognitionException {
CharStream stream =
new ANTLRStringStream(code);
SerpentLexer lex = new SerpentLexer(stream);
CommonTokenStream tokens = new CommonTokenStream(lex);
SerpentParser parser = new SerpentParser(tokens);
String userDir = System.getProperty("user.dir");
String templateFileName = userDir + "\\src\\main\\java\\org\\ethereum\\serpent\\Serpent2Asm.stg";
StringTemplateGroup template = new StringTemplateGroup(new FileReader(templateFileName),
AngleBracketTemplateLexer.class);
parser.setTemplateLib(template);
SerpentParser.program_return retVal = parser.program();
return retVal.getTemplate().toString().trim();
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,168 @@
package org.ethereum.util;
import org.bouncycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;
import javax.swing.*;
import java.math.BigInteger;
import java.net.URL;
import java.security.MessageDigest;
import java.security.Security;
import java.util.Arrays;
import java.util.regex.Pattern;
import static java.lang.System.exit;
/**
* www.ethereumj.com
* User: Roman Mandeleil
* Created on: 06/04/14 13:13
*/
public class Utils {
public static byte[] hexStringToByteArr(String hexString){
String hexSymbols = "0123456789ABCDEF";
int arrSize = (int) (hexString.length() / 3);
byte[] result = new byte[arrSize];
for (int i = 0; i < arrSize; ++i){
int digit1 = hexSymbols.indexOf( hexString.charAt(i * 3) );
int digit2 = hexSymbols.indexOf( hexString.charAt(i * 3 + 1) );
result[i] = (byte) (digit1 * 16 + digit2);
}
return result;
}
public static String toHexString(byte[] data){
if (data == null) return "null";
else return Hex.toHexString(data);
}
/**
* @param hexNum should be in form '0x34fabd34....'
* @return
*/
public static String hexStringToDecimalString(String hexNum){
boolean match = Pattern.matches("0[xX][0-9a-fA-F]+", hexNum);
if (!match) throw new Error("The string doesn't conains hex num in form 0x.. : [" + hexNum + "]");
byte[] numberBytes = Hex.decode(hexNum.substring(2));
return (new BigInteger(1, numberBytes)).toString();
}
public static void printHexStringForByte(byte data){
System.out.print("[");
String hexNum = Integer.toHexString ((int) data & 0xFF);
if (((int) data & 0xFF) < 16) {
hexNum = "0" + hexNum;
}
System.out.print( hexNum );
System.out.print("]");
System.out.println();
}
public static void printHexStringForByteArray(byte[] data){
System.out.print("[");
for (int i = 0; i < data.length; ++i){
String hexNum = Integer.toHexString ((int) data[i] & 0xFF);
if (((int) data[i] & 0xFF) < 16) {
hexNum = "0" + hexNum;
}
System.out.print( hexNum );
System.out.print(" ");
}
System.out.print("]");
System.out.println();
}
private static MessageDigest sha3Digest = null;
private static MessageDigest ripemd160Digest = null;
static {
try{
Security.addProvider(new BouncyCastleProvider());
ripemd160Digest = MessageDigest.getInstance("RIPEMD160", "BC");
sha3Digest = MessageDigest.getInstance("SHA3-256", "BC");
} catch (Throwable th){
th.printStackTrace();
exit(0);
}
}
public static byte[] sha3(byte[] token){
return sha3Digest.digest(token);
}
public static byte[] ripemd160(byte[] token){
return ripemd160Digest.digest(token);
}
static X9ECParameters curvParams = SECNamedCurves.getByName("secp256k1");
public static byte[] privToAddress(byte[] priv){
/* address create howto
token = "cow"
step1 = sha3(token) // generate 256 bit privkey
step2 = privtopub(step1)[1:] // generate 512 bit pubkey with secp256k1
step3 = sha3(step2)[12:]
*/
// TODO: validity checks
BigInteger privKey = new BigInteger(1, priv);
ECPoint Q = curvParams.getG().multiply(privKey);
byte[] pubKey = Q.getEncoded();
// TODO: find a performance improvement here - how to omit creation of new byte[]
byte[] _pubKey = Arrays.copyOfRange(pubKey, 1, pubKey.length);
byte[] _addr = Utils.sha3(_pubKey);
// TODO: find a performance improvement here - how to omit creation of new byte[]
byte[] addr = Arrays.copyOfRange(_addr, 12, _addr.length);
return addr;
}
public static ImageIcon getImageIcon(String resource){
URL imageURL = ClassLoader.getSystemResource(resource);
ImageIcon image = new ImageIcon(imageURL);
return image;
}
}

View File

@ -0,0 +1,439 @@
package samples;
// ==================================================================
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
/**
* Deterministic DSA signature generation. This is a sample
* implementation designed to illustrate how deterministic DSA
* chooses the pseudorandom value k when signing a given message.
* This implementation was NOT optimized or hardened against
* side-channel leaks.
*
* An instance is created with a hash function name, which must be
* supported by the underlying Java virtual machine ("SHA-1" and
* "SHA-256" should work everywhere). The data to sign is input
* through the {@code update()} methods. The private key is set with
* {@link #setPrivateKey}. The signature is obtained by calling
* {@link #sign}; alternatively, {@link #signHash} can be used to
* sign some data that has been externally hashed. The private key
* MUST be set before generating the signature itself, but message
* data can be input before setting the key.
*
* Instances are NOT thread-safe. However, once a signature has
* been generated, the same instance can be used again for another
* signature; {@link #setPrivateKey} need not be called again if the
* private key has not changed. {@link #reset} can also be called to
* cancel previously input data. Generating a signature with {@link
* #sign} (not {@link #signHash}) also implicitly causes a
* reset.
*
* ------------------------------------------------------------------
* Copyright (c) 2013 IETF Trust and the persons identified as
* authors of the code. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, is permitted pursuant to, and subject to the license
* terms contained in, the Simplified BSD License set forth in Section
* 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
* (http://trustee.ietf.org/license-info).
*
* Technical remarks and questions can be addressed to:
* pornin@bolet.org
* ------------------------------------------------------------------
*/
public class DeterministicDSA {
private String macName;
private MessageDigest dig;
private Mac hmac;
private BigInteger p, q, g, x;
private int qlen, rlen, rolen, holen;
private byte[] bx;
/**
* Create an instance, using the specified hash function.
* The name is used to obtain from the JVM an implementation
* of the hash function and an implementation of HMAC.
*
* @param hashName the hash function name
* @throws IllegalArgumentException on unsupported name
*/
public DeterministicDSA(String hashName)
{
try {
dig = MessageDigest.getInstance(hashName);
} catch (NoSuchAlgorithmException nsae) {
throw new IllegalArgumentException(nsae);
}
if (hashName.indexOf('-') < 0) {
macName = "Hmac" + hashName;
} else {
StringBuilder sb = new StringBuilder();
sb.append("Hmac");
int n = hashName.length();
for (int i = 0; i < n; i ++) {
char c = hashName.charAt(i);
if (c != '-') {
sb.append(c);
}
}
macName = sb.toString();
}
try {
hmac = Mac.getInstance(macName);
} catch (NoSuchAlgorithmException nsae) {
throw new IllegalArgumentException(nsae);
}
holen = hmac.getMacLength();
}
/**
* Set the private key.
*
* @param p key parameter: field modulus
* @param q key parameter: subgroup order
* @param g key parameter: generator
* @param x private key
*/
public void setPrivateKey(BigInteger p, BigInteger q,
BigInteger g, BigInteger x)
{
/*
* Perform some basic sanity checks. We do not
* check primality of p or q because that would
* be too expensive.
*
* We reject keys where q is longer than 999 bits,
* because it would complicate signature encoding.
* Normal DSA keys do not have a q longer than 256
* bits anyway.
*/
if (p == null || q == null || g == null || x == null
|| p.signum() <= 0 || q.signum() <= 0
|| g.signum() <= 0 || x.signum() <= 0
|| x.compareTo(q) >= 0 || q.compareTo(p) >= 0
|| q.bitLength() > 999
|| g.compareTo(p) >= 0 || g.bitLength() == 1
|| g.modPow(q, p).bitLength() != 1) {
throw new IllegalArgumentException(
"invalid DSA private key");
}
this.p = p;
this.q = q;
this.g = g;
this.x = x;
qlen = q.bitLength();
if (q.signum() <= 0 || qlen < 8) {
throw new IllegalArgumentException(
"bad group order: " + q);
}
rolen = (qlen + 7) >>> 3;
rlen = rolen * 8;
/*
* Convert the private exponent (x) into a sequence
* of octets.
*/
bx = int2octets(x);
}
private BigInteger bits2int(byte[] in)
{
BigInteger v = new BigInteger(1, in);
int vlen = in.length * 8;
if (vlen > qlen) {
v = v.shiftRight(vlen - qlen);
}
return v;
}
private byte[] int2octets(BigInteger v)
{
byte[] out = v.toByteArray();
if (out.length < rolen) {
byte[] out2 = new byte[rolen];
System.arraycopy(out, 0,
out2, rolen - out.length,
out.length);
return out2;
} else if (out.length > rolen) {
byte[] out2 = new byte[rolen];
System.arraycopy(out, out.length - rolen,
out2, 0, rolen);
return out2;
} else {
return out;
}
}
private byte[] bits2octets(byte[] in)
{
BigInteger z1 = bits2int(in);
BigInteger z2 = z1.subtract(q);
return int2octets(z2.signum() < 0 ? z1 : z2);
}
/**
Pornin Informational [Page 73]
RFC 6979 Deterministic DSA and ECDSA August 2013
* Set (or reset) the secret key used for HMAC.
*
* @param K the new secret key
*/
private void setHmacKey(byte[] K)
{
try {
hmac.init(new SecretKeySpec(K, macName));
} catch (InvalidKeyException ike) {
throw new IllegalArgumentException(ike);
}
}
/**
* Compute the pseudorandom k for signature generation,
* using the process specified for deterministic DSA.
*
* @param h1 the hashed message
* @return the pseudorandom k to use
*/
private BigInteger computek(byte[] h1)
{
/*
* Convert hash value into an appropriately truncated
* and/or expanded sequence of octets. The private
* key was already processed (into field bx[]).
*/
byte[] bh = bits2octets(h1);
/*
* HMAC is always used with K as key.
* Whenever K is updated, we reset the
* current HMAC key.
*/
/* step b. */
byte[] V = new byte[holen];
for (int i = 0; i < holen; i ++) {
V[i] = 0x01;
}
/* step c. */
byte[] K = new byte[holen];
setHmacKey(K);
/* step d. */
hmac.update(V);
hmac.update((byte)0x00);
hmac.update(bx);
hmac.update(bh);
K = hmac.doFinal();
setHmacKey(K);
/* step e. */
hmac.update(V);
V = hmac.doFinal();
/* step f. */
hmac.update(V);
hmac.update((byte)0x01);
hmac.update(bx);
hmac.update(bh);
K = hmac.doFinal();
setHmacKey(K);
/* step g. */
hmac.update(V);
V = hmac.doFinal();
/* step h. */
byte[] T = new byte[rolen];
for (;;) {
/*
* We want qlen bits, but we support only
* hash functions with an output length
* multiple of 8;acd hence, we will gather
* rlen bits, i.e., rolen octets.
*/
int toff = 0;
while (toff < rolen) {
hmac.update(V);
V = hmac.doFinal();
int cc = Math.min(V.length,
T.length - toff);
System.arraycopy(V, 0, T, toff, cc);
toff += cc;
}
BigInteger k = bits2int(T);
if (k.signum() > 0 && k.compareTo(q) < 0) {
return k;
}
/*
* k is not in the proper range; update
* K and V, and loop.
*/
hmac.update(V);
hmac.update((byte)0x00);
K = hmac.doFinal();
setHmacKey(K);
hmac.update(V);
V = hmac.doFinal();
}
}
/**
* Process one more byte of input data (message to sign).
*
* @param in the extra input byte
*/
public void update(byte in)
{
dig.update(in);
}
/**
* Process some extra bytes of input data (message to sign).
*
* @param in the extra input bytes
*/
public void update(byte[] in)
{
dig.update(in, 0, in.length);
}
/**
* Process some extra bytes of input data (message to sign).
*
* @param in the extra input buffer
* @param off the extra input offset
* @param len the extra input length (in bytes)
*/
public void update(byte[] in, int off, int len)
{
dig.update(in, off, len);
}
/**
* Produce the signature. {@link #setPrivateKey} MUST have
* been called. The signature is computed over the data
* that was input through the {@code update*()} methods.
* This engine is then reset (made ready for a new
* signature generation).
*
Pornin Informational [Page 76]
RFC 6979 Deterministic DSA and ECDSA August 2013
* @return the signature
*/
public byte[] sign()
{
return signHash(dig.digest());
}
/**
* Produce the signature. {@link #setPrivateKey} MUST
* have been called. The signature is computed over the
* provided hash value (data is assumed to have been hashed
* externally). The data that was input through the
* {@code update*()} methods is ignored, but kept.
*
* If the hash output is longer than the subgroup order
* (the length of q, in bits, denoted 'qlen'), then the
* provided value {@code h1} can be truncated, provided that
* at least qlen leading bits are preserved. In other words,
* bit values in {@code h1} beyond the first qlen bits are
* ignored.
*
* @param h1 the hash value
* @return the signature
*/
public byte[] signHash(byte[] h1)
{
if (p == null) {
throw new IllegalStateException(
"no private key set");
}
try {
BigInteger k = computek(h1);
BigInteger r = g.modPow(k, p).mod(q);
BigInteger s = k.modInverse(q).multiply(
bits2int(h1).add(x.multiply(r)))
.mod(q);
/*
* Signature encoding: ASN.1 SEQUENCE of
* two INTEGERs. The conditions on q
* imply that the encoded version of r and
* s is no longer than 127 bytes for each,
* including DER tag and length.
*/
byte[] br = r.toByteArray();
byte[] bs = s.toByteArray();
int ulen = br.length + bs.length + 4;
int slen = ulen + (ulen >= 128 ? 3 : 2);
byte[] sig = new byte[slen];
int i = 0;
sig[i ++] = 0x30;
if (ulen >= 128) {
sig[i ++] = (byte)0x81;
sig[i ++] = (byte)ulen;
} else {
sig[i ++] = (byte)ulen;
}
sig[i ++] = 0x02;
sig[i ++] = (byte)br.length;
System.arraycopy(br, 0, sig, i, br.length);
i += br.length;
sig[i ++] = 0x02;
sig[i ++] = (byte)bs.length;
System.arraycopy(bs, 0, sig, i, bs.length);
return sig;
} catch (ArithmeticException ae) {
throw new IllegalArgumentException(
"DSA error (bad key ?)", ae);
}
}
/**
* Reset this engine. Data input through the {@code
* update*()} methods is discarded. The current private key,
* if one was set, is kept unchanged.
*/
public void reset()
{
dig.reset();
}
}
// ==================================================================

View File

@ -0,0 +1,191 @@
package samples;
import com.maxmind.geoip.LookupService;
import com.maxmind.geoip.Region;
import com.maxmind.geoip.regionName;
import com.maxmind.geoip2.exception.GeoIp2Exception;
import org.ethereum.net.RLP;
import org.ethereum.util.Utils;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.LinkedList;
import java.util.Queue;
/**
* www.openchain.info
* User: Roman Mandeleil
* Created on: 31/03/14 21:06
*/
public class Main1 {
public static void main(String args[]) throws IOException, GeoIp2Exception, URISyntaxException {
try {
URL flagURL = ClassLoader.getSystemResource("GeoLiteCity.dat");
File file = new File(flagURL.toURI());
LookupService cl = new LookupService(file);
System.out.println(cl.getLocation("110.77.217.185"));
} catch (IOException e) {
System.out.println("IO Exception");
}
}
public static void main1(String args[]) throws IOException {
//22400891000000088400000043414243
String helloPacket = "22400891000000088400000043414243";
String pingPacket = "224008910000000102";
System.out.println(helloPacket);
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("localhost", 20202));
socketChannel.configureBlocking(false);
String helloString = "22 40 08 91 00 00 00 79 F8 77 80 0A 80 AD 45 74 " +
"68 65 72 65 75 6D 28 2B 2B 29 2F 5A 65 72 6F 47 " +
"6F 78 2F 76 30 2E 34 2E 31 2F 6E 63 75 72 73 65 " +
"73 2F 4C 69 6E 75 78 2F 67 2B 2B 07 82 76 5F B8 " +
"40 D8 D6 0C 25 80 FA 79 5C FC 03 13 EF DE BA 86 " +
"9D 21 94 E7 9E 7C B2 B5 22 F7 82 FF A0 39 2C BB " +
"AB 8D 1B AC 30 12 08 B1 37 E0 DE 49 98 33 4F 3B " +
"CF 73 FA 11 7E F2 13 F8 74 17 08 9F EA F8 4C 21 " +
"B0 22 40 08 91 00 00 00 02 C1 02 22 40 08 91 00 " +
"00 00 26 E5 14 A0 AB 6B 9A 56 13 97 0F AA 77 1B " +
"12 D4 49 B2 E9 BB 92 5A B7 A3 69 F0 A4 B8 6B 28 " +
"6E 9D 54 00 99 CF 82 01 00 22 40 08 91 00 00 00 " +
"02 C1 16 22 40 08 91 00 00 00 02 C1 01 ";
String getPeersString = "22 40 08 91 00 00 00 02 C1 10 ";
byte[] helloBytes = hexStringToByteArr(helloString);
// Sending
ByteBuffer outBuffer = ByteBuffer.allocate(helloBytes.length);
outBuffer.clear();
outBuffer.put(helloBytes);
outBuffer.flip();
while (outBuffer.hasRemaining()) {
socketChannel.write(outBuffer);
}
outBuffer.clear();
byte[] getPeersBytes = hexStringToByteArr(getPeersString);
// Sending
outBuffer = ByteBuffer.allocate(getPeersBytes.length);
outBuffer.clear();
outBuffer.put(getPeersBytes);
outBuffer.flip();
while (outBuffer.hasRemaining()) {
socketChannel.write(outBuffer);
}
ByteBuffer inBuffer = ByteBuffer.allocate(1);
int bytesRead = socketChannel.read(inBuffer); //read into buffer.
while (bytesRead != -1) {
inBuffer.flip(); //make buffer ready for read
while (inBuffer.hasRemaining()) {
byte oneByte = inBuffer.get();
System.out.print(Integer.toHexString((int) oneByte & 0x00FF)); // read 1 byte at a time
System.out.print(" ");
}
inBuffer.clear(); //make buffer ready for writing
bytesRead = socketChannel.read(inBuffer);
}
// read 4 bytes sync token 0x22400891
// read 4 bytes packet size token, translate to size
// read packet according the size
}
public static byte[] hexStringToByteArr(String hexString) {
String hexSymbols = "0123456789ABCDEF";
int arrSize = (int) (hexString.length() / 3);
byte[] result = new byte[arrSize];
for (int i = 0; i < arrSize; ++i) {
int digit1 = hexSymbols.indexOf(hexString.charAt(i * 3));
int digit2 = hexSymbols.indexOf(hexString.charAt(i * 3 + 1));
result[i] = (byte) (digit1 * 16 + digit2);
}
return result;
}
public static void main2(String args[]) {
String helloPacket =
"F8 77 80 0B 80 AD 45 74 68 65 72 65 75 6D 28 2B 2B 29 " +
"2F 5A 65 72 6F 47 6F 78 2F 76 30 2E 34 2E 32 2F " +
"6E 63 75 72 73 65 73 2F 4C 69 6E 75 78 2F 67 2B " +
"2B 07 82 76 5F B8 40 80 7D 3E D5 E7 7C BA 05 8D " +
"C0 55 4A E0 90 98 9E FE EA 55 33 52 B3 1A DF DB " +
"80 5E 2A 1A 7D F7 9D 14 FE 8D 9D 2C CE AA D8 E9 " +
"4B 09 37 47 F1 33 C3 EE F3 98 83 96 20 1D 24 17 " +
"93 83 5D 38 70 FF D4";
String peersPacket = "F8 4E 11 F8 4B C5 36 81 " +
"CC 0A 29 82 76 5F B8 40 D8 D6 0C 25 80 FA 79 5C " +
"FC 03 13 EF DE BA 86 9D 21 94 E7 9E 7C B2 B5 22 " +
"F7 82 FF A0 39 2C BB AB 8D 1B AC 30 12 08 B1 37 " +
"E0 DE 49 98 33 4F 3B CF 73 FA 11 7E F2 13 F8 74 " +
"17 08 9F EA F8 4C 21 B0";
byte[] payload = Utils.hexStringToByteArr(peersPacket);
Utils.printHexStringForByteArray(payload);
Queue<Integer> index = new LinkedList<Integer>();
RLP.fullTraverse(payload, 0, 0, payload.length, 1, index);
// for (Integer item : index) System.out.println("ind --> " + item);
// Message newMessage = MessageFactory.createMessage(payload, index);
// System.out.println(newMessage.toString());
}
}

View File

@ -0,0 +1,84 @@
package samples;
import org.ethereum.net.client.ClientPeer;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 10/04/14 12:50
*/
public class Main2 {
public static void main(String args[]){
// 66.49.191.123
// 54.204.10.41
// 130.88.0.226
// 85.65.126.45
// 54.72.31.55
// new ClientPeer().connect("66.49.191.123", 30303);
// new ClientPeer().connect("66.49.191.123", 30303);
// new ClientPeer().connect("54.72.31.55", 30303);
String ip_1 = "131.104.252.4";
String ip_2 = "107.170.57.247";
String ip_3 = "68.48.173.163";
String ip_4 = "86.183.231.205";
String ip_5 = "68.185.234.64";
String ip_6 = "207.219.69.154";
// new ClientPeer().connect("192.168.1.102", 30303);
// new ClientPeer().connect("83.172.226.79", 30303);
// new ClientPeer().connect("68.48.173.163", 31313);
// new ClientPeer().connect("86.150.41.127", 30303);
// new ClientPeer().connect("82.217.72.169", 30303); nicksavers
// new ClientPeer().connect("94.197.120.80", 30303); stephan (ursium)
// new ClientPeer().connect("54.72.31.55", 30303); // peer discovery: capability = 4
new ClientPeer().connect("54.201.28.117", 30303); // poc-5
// new ClientPeer().connect("94.210.200.192", 30303); // poc-5
// new ClientPeer().connect("62.78.198.208", 30303); // poc-5 not stable
}
}
/* POC - 5
Hello: [/206.223.168.190] Canada
Hello: [/94.210.200.192] Netherlands
Hello: [/88.69.198.198] Germany
Hello: [/24.157.83.122] Canada
Hello: [/71.202.162.40] United States
Hello: [/64.231.10.208] Canada
Hello: [/85.65.126.45] Israel
Hello: [/62.78.198.208] Finland
Hello: [/50.133.12.228] United States
Hello: [/77.166.77.107] Netherlands
Hello: [/110.77.217.185] Thailand
Hello: [/64.231.9.30] Canada
Hello: [/213.100.250.57] Sweden
Hello: [/162.243.203.121] United States
Hello: [/82.217.72.169] Netherlands
Hello: [/99.231.80.166] Canada
Hello: [/131.104.252.4] Canada
Hello: [/54.204.10.41] United States
Hello: [/54.201.28.117] United States
Hello: [/67.204.1.162] Canada
Hello: [/82.240.16.5] France
Hello: [/74.79.23.119] United States
*/

View File

@ -0,0 +1,48 @@
package samples;
import org.bouncycastle.jce.ECPointUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.util.encoders.Hex;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.spec.ECFieldF2m;
import java.security.spec.EllipticCurve;
import java.util.Arrays;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 17/04/14 09:37
*/
public class Main3 {
static private byte[] shortMsg = Hex.decode("54686520717569636B2062726F776E20666F78206A756D7073206F76657220746865206C617A7920646F67");
public static void main(String args[]) throws NoSuchProviderException, NoSuchAlgorithmException, IOException {
Security.addProvider(new BouncyCastleProvider());
MessageDigest digest = MessageDigest.getInstance("SHA3-256", "BC");
byte[] result = digest.digest(shortMsg);
byte[] expected = Hex.decode("4D741B6F1EB29CB2A9B9911C82F56FA8D73B04959D3D9D222895DF6C0B28AA15");
if (Arrays.equals(expected, result)){
System.out.println("equal !!!");
} else {
Hex.encode(result, System.out);
System.out.flush();
}
}
}

View File

@ -0,0 +1,64 @@
package samples;
import org.bouncycastle.jce.ECPointUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
import org.ethereum.util.Utils;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.spec.*;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 17/04/14 09:37
*/
public class Main4 {
static private byte[] shortMsg = Hex.decode("54686520717569636B2062726F776E20666F78206A756D7073206F76657220746865206C617A7920646F67");
public static void main(String args[]) throws NoSuchProviderException, NoSuchAlgorithmException, IOException, InvalidKeySpecException {
Security.addProvider(new BouncyCastleProvider());
EllipticCurve curve = new EllipticCurve(
new ECFieldF2m(239, // m
new int[] { 36 }), // k
new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a
new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b
ECParameterSpec params = new ECParameterSpec(
curve,
ECPointUtil.decodePoint(curve,
Hex.decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G
new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783"), // n
4); // h
ECPrivateKeySpec priKeySpec = new ECPrivateKeySpec(
new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990"), // d
params);
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(
ECPointUtil.decodePoint(curve, Hex.decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q
params);
Signature sgr = Signature.getInstance("ECDSA", "BC");
KeyFactory f = KeyFactory.getInstance("ECDSA", "BC");
PrivateKey sKey = f.generatePrivate(priKeySpec);
PublicKey vKey = f.generatePublic(pubKeySpec);
// System.out.println(vKey);
System.out.println(Hex.toHexString(Utils.sha3("coinbase".getBytes())));
// toAddress(sha3("coinbase"));
// toAddress(76ec948a9207fdea26dcba91086bcdd181920ff52a539b0d1eb28e73b4cd92af);
}
}

View File

@ -0,0 +1,81 @@
package samples;
import org.ethereum.gui.PeersTableModel;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 25/04/14 07:11
*/
public class PeersTableMain extends JFrame{
// Instance attributes used in this example
private JPanel topPanel;
private JTable table;
private JScrollPane scrollPane;
// Constructor of main frame
public PeersTableMain()
{
// Set the frame characteristics
setTitle( "Ethereum Peers" );
setSize( 355, 300 );
setLocation(815, 80);
setBackground( Color.gray );
java.net.URL url = ClassLoader.getSystemResource("ethereum-icon.png");
Toolkit kit = Toolkit.getDefaultToolkit();
Image img = kit.createImage(url);
this.setIconImage(img);
// Create a panel to hold all other components
topPanel = new JPanel();
topPanel.setLayout( new BorderLayout() );
getContentPane().add( topPanel );
// Create a new table instance
table = new JTable( );
table.setModel(new PeersTableModel());
table.setFont(new Font("Courier New", Font.PLAIN, 18));
table.setForeground(Color.GRAY);
table.setTableHeader(null);
TableCellRenderer tcr = table.getDefaultRenderer(String.class);
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)tcr;
renderer.setHorizontalAlignment(SwingConstants.CENTER);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setCellSelectionEnabled(true);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getColumnModel().getColumn(0).setPreferredWidth(60);
table.getColumnModel().getColumn(1).setPreferredWidth(200);
table.getColumnModel().getColumn(2).setPreferredWidth(60);
table.setRowMargin(3);
table.setRowHeight(50);
// Add the table to a scrolling pane
scrollPane = new JScrollPane( table );
topPanel.add( scrollPane, BorderLayout.CENTER );
}
public static void main(String args[]){
PeersTableMain mainFrame = new PeersTableMain();
mainFrame.setVisible( true );
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}

View File

@ -0,0 +1,17 @@
package samples.antlr;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 25/04/14 17:06
*/
public class GenParser {
public static void main(String args[]){
String userDir = System.getProperty("user.dir");
String grammarFile = userDir + "\\src\\main\\java\\samples\\antlr\\Sample.g";
org.antlr.Tool.main(new String[]{grammarFile});
}
}

View File

@ -0,0 +1,105 @@
grammar PyEsque;
options {
language = Java;
output = AST;
//output=template;
}
tokens {
BLOCK;
}
@header {
package samples.antlr;
}
@lexer::header {
package samples.antlr;
}
@lexer::members {
private int previousIndents = -1;
private int indentLevel = 0;
java.util.Queue<Token> tokens = new java.util.LinkedList<Token>();
@Override
public void emit(Token t) {
state.token = t;
tokens.offer(t);
}
@Override
public Token nextToken() {
super.nextToken();
return tokens.isEmpty() ? getEOFToken() : tokens.poll();
}
private void jump(int ttype) {
indentLevel += (ttype == Dedent ? -1 : 1);
emit(new CommonToken(ttype, "level=" + indentLevel));
}
}
parse
: block EOF -> block
;
block
: Indent block_atoms Dedent -> ^(BLOCK block_atoms)
;
block_atoms
: (Id | block)+
;
NewLine
: NL SP?
{
int n = $SP.text == null ? 0 : $SP.text.length();
if(n > previousIndents) {
jump(Indent);
previousIndents = n;
}
else if(n < previousIndents) {
jump(Dedent);
previousIndents = n;
}
else if(input.LA(1) == EOF) {
while(indentLevel > 0) {
jump(Dedent);
}
}
else {
skip();
}
}
;
Id
: ('a'..'z' | 'A'..'Z')+
;
SpaceChars
: SP {skip();}
;
fragment NL : '\r'? '\n' | '\r';
fragment SP : (' ' | '\t')+;
fragment Indent : ;
fragment Dedent : ;
expression
: INTEGER*
;
fragment DIGIT : '0'..'9';
INTEGER : DIGIT+ ;

View File

@ -0,0 +1,547 @@
// $ANTLR 3.5.2 E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g 2014-05-01 16:36:17
package samples.antlr;
import org.antlr.runtime.*;
import java.util.Stack;
import java.util.List;
import java.util.ArrayList;
@SuppressWarnings("all")
public class PyEsqueLexer extends Lexer {
public static final int EOF=-1;
public static final int BLOCK=4;
public static final int DIGIT=5;
public static final int Dedent=6;
public static final int INTEGER=7;
public static final int Id=8;
public static final int Indent=9;
public static final int NL=10;
public static final int NewLine=11;
public static final int SP=12;
public static final int SpaceChars=13;
private int previousIndents = -1;
private int indentLevel = 0;
java.util.Queue<Token> tokens = new java.util.LinkedList<Token>();
@Override
public void emit(Token t) {
state.token = t;
tokens.offer(t);
}
@Override
public Token nextToken() {
super.nextToken();
return tokens.isEmpty() ? getEOFToken() : tokens.poll();
}
private void jump(int ttype) {
indentLevel += (ttype == Dedent ? -1 : 1);
emit(new CommonToken(ttype, "level=" + indentLevel));
}
// delegates
// delegators
public Lexer[] getDelegates() {
return new Lexer[] {};
}
public PyEsqueLexer() {}
public PyEsqueLexer(CharStream input) {
this(input, new RecognizerSharedState());
}
public PyEsqueLexer(CharStream input, RecognizerSharedState state) {
super(input,state);
}
@Override public String getGrammarFileName() { return "E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g"; }
// $ANTLR start "NewLine"
public final void mNewLine() throws RecognitionException {
try {
int _type = NewLine;
int _channel = DEFAULT_TOKEN_CHANNEL;
CommonToken SP1=null;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:61:2: ( NL ( SP )? )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:61:4: NL ( SP )?
{
mNL();
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:61:7: ( SP )?
int alt1=2;
int LA1_0 = input.LA(1);
if ( (LA1_0=='\t'||LA1_0==' ') ) {
alt1=1;
}
switch (alt1) {
case 1 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:61:7: SP
{
int SP1Start39 = getCharIndex();
int SP1StartLine39 = getLine();
int SP1StartCharPos39 = getCharPositionInLine();
mSP();
SP1 = new CommonToken(input, Token.INVALID_TOKEN_TYPE, Token.DEFAULT_CHANNEL, SP1Start39, getCharIndex()-1);
SP1.setLine(SP1StartLine39);
SP1.setCharPositionInLine(SP1StartCharPos39);
}
break;
}
int n = (SP1!=null?SP1.getText():null) == null ? 0 : (SP1!=null?SP1.getText():null).length();
if(n > previousIndents) {
jump(Indent);
previousIndents = n;
}
else if(n < previousIndents) {
jump(Dedent);
previousIndents = n;
}
else if(input.LA(1) == EOF) {
while(indentLevel > 0) {
jump(Dedent);
}
}
else {
skip();
}
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "NewLine"
// $ANTLR start "Id"
public final void mId() throws RecognitionException {
try {
int _type = Id;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:85:2: ( ( 'a' .. 'z' | 'A' .. 'Z' )+ )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:85:4: ( 'a' .. 'z' | 'A' .. 'Z' )+
{
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:85:4: ( 'a' .. 'z' | 'A' .. 'Z' )+
int cnt2=0;
loop2:
while (true) {
int alt2=2;
int LA2_0 = input.LA(1);
if ( ((LA2_0 >= 'A' && LA2_0 <= 'Z')||(LA2_0 >= 'a' && LA2_0 <= 'z')) ) {
alt2=1;
}
switch (alt2) {
case 1 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:
{
if ( (input.LA(1) >= 'A' && input.LA(1) <= 'Z')||(input.LA(1) >= 'a' && input.LA(1) <= 'z') ) {
input.consume();
}
else {
MismatchedSetException mse = new MismatchedSetException(null,input);
recover(mse);
throw mse;
}
}
break;
default :
if ( cnt2 >= 1 ) break loop2;
EarlyExitException eee = new EarlyExitException(2, input);
throw eee;
}
cnt2++;
}
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "Id"
// $ANTLR start "SpaceChars"
public final void mSpaceChars() throws RecognitionException {
try {
int _type = SpaceChars;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:89:2: ( SP )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:89:4: SP
{
mSP();
skip();
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "SpaceChars"
// $ANTLR start "NL"
public final void mNL() throws RecognitionException {
try {
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:92:17: ( ( '\\r' )? '\\n' | '\\r' )
int alt4=2;
int LA4_0 = input.LA(1);
if ( (LA4_0=='\r') ) {
int LA4_1 = input.LA(2);
if ( (LA4_1=='\n') ) {
alt4=1;
}
else {
alt4=2;
}
}
else if ( (LA4_0=='\n') ) {
alt4=1;
}
else {
NoViableAltException nvae =
new NoViableAltException("", 4, 0, input);
throw nvae;
}
switch (alt4) {
case 1 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:92:19: ( '\\r' )? '\\n'
{
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:92:19: ( '\\r' )?
int alt3=2;
int LA3_0 = input.LA(1);
if ( (LA3_0=='\r') ) {
alt3=1;
}
switch (alt3) {
case 1 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:92:19: '\\r'
{
match('\r');
}
break;
}
match('\n');
}
break;
case 2 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:92:32: '\\r'
{
match('\r');
}
break;
}
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "NL"
// $ANTLR start "SP"
public final void mSP() throws RecognitionException {
try {
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:93:17: ( ( ' ' | '\\t' )+ )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:93:19: ( ' ' | '\\t' )+
{
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:93:19: ( ' ' | '\\t' )+
int cnt5=0;
loop5:
while (true) {
int alt5=2;
int LA5_0 = input.LA(1);
if ( (LA5_0=='\t'||LA5_0==' ') ) {
alt5=1;
}
switch (alt5) {
case 1 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:
{
if ( input.LA(1)=='\t'||input.LA(1)==' ' ) {
input.consume();
}
else {
MismatchedSetException mse = new MismatchedSetException(null,input);
recover(mse);
throw mse;
}
}
break;
default :
if ( cnt5 >= 1 ) break loop5;
EarlyExitException eee = new EarlyExitException(5, input);
throw eee;
}
cnt5++;
}
}
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "SP"
// $ANTLR start "Indent"
public final void mIndent() throws RecognitionException {
try {
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:94:17: ()
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:94:19:
{
}
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "Indent"
// $ANTLR start "Dedent"
public final void mDedent() throws RecognitionException {
try {
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:95:17: ()
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:95:19:
{
}
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "Dedent"
// $ANTLR start "DIGIT"
public final void mDIGIT() throws RecognitionException {
try {
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:104:16: ( '0' .. '9' )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:
{
if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) {
input.consume();
}
else {
MismatchedSetException mse = new MismatchedSetException(null,input);
recover(mse);
throw mse;
}
}
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "DIGIT"
// $ANTLR start "INTEGER"
public final void mINTEGER() throws RecognitionException {
try {
int _type = INTEGER;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:105:9: ( ( DIGIT )+ )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:105:11: ( DIGIT )+
{
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:105:11: ( DIGIT )+
int cnt6=0;
loop6:
while (true) {
int alt6=2;
int LA6_0 = input.LA(1);
if ( ((LA6_0 >= '0' && LA6_0 <= '9')) ) {
alt6=1;
}
switch (alt6) {
case 1 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:
{
if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) {
input.consume();
}
else {
MismatchedSetException mse = new MismatchedSetException(null,input);
recover(mse);
throw mse;
}
}
break;
default :
if ( cnt6 >= 1 ) break loop6;
EarlyExitException eee = new EarlyExitException(6, input);
throw eee;
}
cnt6++;
}
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "INTEGER"
@Override
public void mTokens() throws RecognitionException {
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:1:8: ( NewLine | Id | SpaceChars | INTEGER )
int alt7=4;
switch ( input.LA(1) ) {
case '\n':
case '\r':
{
alt7=1;
}
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
{
alt7=2;
}
break;
case '\t':
case ' ':
{
alt7=3;
}
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
alt7=4;
}
break;
default:
NoViableAltException nvae =
new NoViableAltException("", 7, 0, input);
throw nvae;
}
switch (alt7) {
case 1 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:1:10: NewLine
{
mNewLine();
}
break;
case 2 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:1:18: Id
{
mId();
}
break;
case 3 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:1:21: SpaceChars
{
mSpaceChars();
}
break;
case 4 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:1:32: INTEGER
{
mINTEGER();
}
break;
}
}
}

View File

@ -0,0 +1,394 @@
// $ANTLR 3.5.2 E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g 2014-05-01 16:36:17
package samples.antlr;
import org.antlr.runtime.*;
import java.util.Stack;
import java.util.List;
import java.util.ArrayList;
import org.antlr.runtime.tree.*;
@SuppressWarnings("all")
public class PyEsqueParser extends Parser {
public static final String[] tokenNames = new String[] {
"<invalid>", "<EOR>", "<DOWN>", "<UP>", "BLOCK", "DIGIT", "Dedent", "INTEGER",
"Id", "Indent", "NL", "NewLine", "SP", "SpaceChars"
};
public static final int EOF=-1;
public static final int BLOCK=4;
public static final int DIGIT=5;
public static final int Dedent=6;
public static final int INTEGER=7;
public static final int Id=8;
public static final int Indent=9;
public static final int NL=10;
public static final int NewLine=11;
public static final int SP=12;
public static final int SpaceChars=13;
// delegates
public Parser[] getDelegates() {
return new Parser[] {};
}
// delegators
public PyEsqueParser(TokenStream input) {
this(input, new RecognizerSharedState());
}
public PyEsqueParser(TokenStream input, RecognizerSharedState state) {
super(input, state);
}
protected TreeAdaptor adaptor = new CommonTreeAdaptor();
public void setTreeAdaptor(TreeAdaptor adaptor) {
this.adaptor = adaptor;
}
public TreeAdaptor getTreeAdaptor() {
return adaptor;
}
@Override public String[] getTokenNames() { return PyEsqueParser.tokenNames; }
@Override public String getGrammarFileName() { return "E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g"; }
public static class parse_return extends ParserRuleReturnScope {
Object tree;
@Override
public Object getTree() { return tree; }
};
// $ANTLR start "parse"
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:48:1: parse : block EOF -> block ;
public final parse_return parse() throws RecognitionException {
parse_return retval = new parse_return();
retval.start = input.LT(1);
Object root_0 = null;
Token EOF2=null;
ParserRuleReturnScope block1 =null;
Object EOF2_tree=null;
RewriteRuleTokenStream stream_EOF=new RewriteRuleTokenStream(adaptor,"token EOF");
RewriteRuleSubtreeStream stream_block=new RewriteRuleSubtreeStream(adaptor,"rule block");
try {
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:49:2: ( block EOF -> block )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:49:4: block EOF
{
pushFollow(FOLLOW_block_in_parse74);
block1=block();
state._fsp--;
stream_block.add(block1.getTree());
EOF2=(Token)match(input,EOF,FOLLOW_EOF_in_parse76);
stream_EOF.add(EOF2);
// AST REWRITE
// elements: block
// token labels:
// rule labels: retval
// token list labels:
// rule list labels:
// wildcard labels:
retval.tree = root_0;
RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null);
root_0 = (Object)adaptor.nil();
// 49:14: -> block
{
adaptor.addChild(root_0, stream_block.nextTree());
}
retval.tree = root_0;
}
retval.stop = input.LT(-1);
retval.tree = (Object)adaptor.rulePostProcessing(root_0);
adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
}
catch (RecognitionException re) {
reportError(re);
recover(input,re);
retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re);
}
finally {
// do for sure before leaving
}
return retval;
}
// $ANTLR end "parse"
public static class block_return extends ParserRuleReturnScope {
Object tree;
@Override
public Object getTree() { return tree; }
};
// $ANTLR start "block"
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:52:1: block : Indent block_atoms Dedent -> ^( BLOCK block_atoms ) ;
public final block_return block() throws RecognitionException {
block_return retval = new block_return();
retval.start = input.LT(1);
Object root_0 = null;
Token Indent3=null;
Token Dedent5=null;
ParserRuleReturnScope block_atoms4 =null;
Object Indent3_tree=null;
Object Dedent5_tree=null;
RewriteRuleTokenStream stream_Indent=new RewriteRuleTokenStream(adaptor,"token Indent");
RewriteRuleTokenStream stream_Dedent=new RewriteRuleTokenStream(adaptor,"token Dedent");
RewriteRuleSubtreeStream stream_block_atoms=new RewriteRuleSubtreeStream(adaptor,"rule block_atoms");
try {
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:53:2: ( Indent block_atoms Dedent -> ^( BLOCK block_atoms ) )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:53:4: Indent block_atoms Dedent
{
Indent3=(Token)match(input,Indent,FOLLOW_Indent_in_block91);
stream_Indent.add(Indent3);
pushFollow(FOLLOW_block_atoms_in_block93);
block_atoms4=block_atoms();
state._fsp--;
stream_block_atoms.add(block_atoms4.getTree());
Dedent5=(Token)match(input,Dedent,FOLLOW_Dedent_in_block95);
stream_Dedent.add(Dedent5);
// AST REWRITE
// elements: block_atoms
// token labels:
// rule labels: retval
// token list labels:
// rule list labels:
// wildcard labels:
retval.tree = root_0;
RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null);
root_0 = (Object)adaptor.nil();
// 53:30: -> ^( BLOCK block_atoms )
{
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:53:33: ^( BLOCK block_atoms )
{
Object root_1 = (Object)adaptor.nil();
root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(BLOCK, "BLOCK"), root_1);
adaptor.addChild(root_1, stream_block_atoms.nextTree());
adaptor.addChild(root_0, root_1);
}
}
retval.tree = root_0;
}
retval.stop = input.LT(-1);
retval.tree = (Object)adaptor.rulePostProcessing(root_0);
adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
}
catch (RecognitionException re) {
reportError(re);
recover(input,re);
retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re);
}
finally {
// do for sure before leaving
}
return retval;
}
// $ANTLR end "block"
public static class block_atoms_return extends ParserRuleReturnScope {
Object tree;
@Override
public Object getTree() { return tree; }
};
// $ANTLR start "block_atoms"
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:56:1: block_atoms : ( Id | block )+ ;
public final block_atoms_return block_atoms() throws RecognitionException {
block_atoms_return retval = new block_atoms_return();
retval.start = input.LT(1);
Object root_0 = null;
Token Id6=null;
ParserRuleReturnScope block7 =null;
Object Id6_tree=null;
try {
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:57:2: ( ( Id | block )+ )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:57:5: ( Id | block )+
{
root_0 = (Object)adaptor.nil();
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:57:5: ( Id | block )+
int cnt1=0;
loop1:
while (true) {
int alt1=3;
int LA1_0 = input.LA(1);
if ( (LA1_0==Id) ) {
alt1=1;
}
else if ( (LA1_0==Indent) ) {
alt1=2;
}
switch (alt1) {
case 1 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:57:6: Id
{
Id6=(Token)match(input,Id,FOLLOW_Id_in_block_atoms116);
Id6_tree = (Object)adaptor.create(Id6);
adaptor.addChild(root_0, Id6_tree);
}
break;
case 2 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:57:11: block
{
pushFollow(FOLLOW_block_in_block_atoms120);
block7=block();
state._fsp--;
adaptor.addChild(root_0, block7.getTree());
}
break;
default :
if ( cnt1 >= 1 ) break loop1;
EarlyExitException eee = new EarlyExitException(1, input);
throw eee;
}
cnt1++;
}
}
retval.stop = input.LT(-1);
retval.tree = (Object)adaptor.rulePostProcessing(root_0);
adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
}
catch (RecognitionException re) {
reportError(re);
recover(input,re);
retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re);
}
finally {
// do for sure before leaving
}
return retval;
}
// $ANTLR end "block_atoms"
public static class expression_return extends ParserRuleReturnScope {
Object tree;
@Override
public Object getTree() { return tree; }
};
// $ANTLR start "expression"
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:98:1: expression : ( INTEGER )* ;
public final expression_return expression() throws RecognitionException {
expression_return retval = new expression_return();
retval.start = input.LT(1);
Object root_0 = null;
Token INTEGER8=null;
Object INTEGER8_tree=null;
try {
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:99:2: ( ( INTEGER )* )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:99:4: ( INTEGER )*
{
root_0 = (Object)adaptor.nil();
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:99:4: ( INTEGER )*
loop2:
while (true) {
int alt2=2;
int LA2_0 = input.LA(1);
if ( (LA2_0==INTEGER) ) {
alt2=1;
}
switch (alt2) {
case 1 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\antlr\\PyEsque.g:99:4: INTEGER
{
INTEGER8=(Token)match(input,INTEGER,FOLLOW_INTEGER_in_expression246);
INTEGER8_tree = (Object)adaptor.create(INTEGER8);
adaptor.addChild(root_0, INTEGER8_tree);
}
break;
default :
break loop2;
}
}
}
retval.stop = input.LT(-1);
retval.tree = (Object)adaptor.rulePostProcessing(root_0);
adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
}
catch (RecognitionException re) {
reportError(re);
recover(input,re);
retval.tree = (Object)adaptor.errorNode(input, retval.start, input.LT(-1), re);
}
finally {
// do for sure before leaving
}
return retval;
}
// $ANTLR end "expression"
// Delegated rules
public static final BitSet FOLLOW_block_in_parse74 = new BitSet(new long[]{0x0000000000000000L});
public static final BitSet FOLLOW_EOF_in_parse76 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_Indent_in_block91 = new BitSet(new long[]{0x0000000000000300L});
public static final BitSet FOLLOW_block_atoms_in_block93 = new BitSet(new long[]{0x0000000000000040L});
public static final BitSet FOLLOW_Dedent_in_block95 = new BitSet(new long[]{0x0000000000000002L});
public static final BitSet FOLLOW_Id_in_block_atoms116 = new BitSet(new long[]{0x0000000000000302L});
public static final BitSet FOLLOW_block_in_block_atoms120 = new BitSet(new long[]{0x0000000000000302L});
public static final BitSet FOLLOW_INTEGER_in_expression246 = new BitSet(new long[]{0x0000000000000082L});
}

View File

@ -0,0 +1,611 @@
/*
[The 'BSD licence']
Copyright (c) 2004 Terence Parr and Loring Craymer
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** Python 2.3.3 Grammar
*
* Terence Parr and Loring Craymer
* February 2004
*
* Converted to ANTLR v3 November 2005 by Terence Parr.
*
* This grammar was derived automatically from the Python 2.3.3
* parser grammar to get a syntactically correct ANTLR grammar
* for Python. Then Terence hand tweaked it to be semantically
* correct; i.e., removed lookahead issues etc... It is LL(1)
* except for the (sometimes optional) trailing commas and semi-colons.
* It needs two symbols of lookahead in this case.
*
* Starting with Loring's preliminary lexer for Python, I modified it
* to do my version of the whole nasty INDENT/DEDENT issue just so I
* could understand the problem better. This grammar requires
* PythonTokenStream.java to work. Also I used some rules from the
* semi-formal grammar on the web for Python (automatically
* translated to ANTLR format by an ANTLR grammar, naturally <grin>).
* The lexical rules for python are particularly nasty and it took me
* a long time to get it 'right'; i.e., think about it in the proper
* way. Resist changing the lexer unless you've used ANTLR a lot. ;)
*
* I (Terence) tested this by running it on the jython-2.1/Lib
* directory of 40k lines of Python.
*
* REQUIRES ANTLR v3
*/
grammar Python;
tokens {
INDENT;
DEDENT;
}
@lexer::members {
/** Handles context-sensitive lexing of implicit line joining such as
* the case where newline is ignored in cases like this:
* a = [3,
* 4]
*/
int implicitLineJoiningLevel = 0;
int startPos=-1;
}
@header {
package org.ethereum.serpent;
}
@lexer::header {
package org.ethereum.serpent;
}
single_input
: NEWLINE
| simple_stmt
| compound_stmt NEWLINE
;
file_input
: (NEWLINE | stmt)*
;
eval_input
: (NEWLINE)* testlist (NEWLINE)*
;
funcdef
: 'def' NAME parameters COLON suite
{System.out.println("found method def "+$NAME.text);}
;
parameters
: LPAREN (varargslist)? RPAREN
;
varargslist
: defparameter (options {greedy=true;}:COMMA defparameter)*
(COMMA
( STAR NAME (COMMA DOUBLESTAR NAME)?
| DOUBLESTAR NAME
)?
)?
| STAR NAME (COMMA DOUBLESTAR NAME)?
| DOUBLESTAR NAME
;
defparameter
: fpdef (ASSIGN test)?
;
fpdef
: NAME
| LPAREN fplist RPAREN
;
fplist
: fpdef (options {greedy=true;}:COMMA fpdef)* (COMMA)?
;
stmt: simple_stmt
| compound_stmt
;
simple_stmt
: small_stmt (options {greedy=true;}:SEMI small_stmt)* (SEMI)? NEWLINE
;
small_stmt: expr_stmt
| print_stmt
| del_stmt
| pass_stmt
| flow_stmt
| import_stmt
| global_stmt
| exec_stmt
| assert_stmt
;
expr_stmt
: testlist
( augassign testlist
| (ASSIGN testlist)+
)?
;
augassign
: PLUSEQUAL
| MINUSEQUAL
| STAREQUAL
| SLASHEQUAL
| PERCENTEQUAL
| AMPEREQUAL
| VBAREQUAL
| CIRCUMFLEXEQUAL
| LEFTSHIFTEQUAL
| RIGHTSHIFTEQUAL
| DOUBLESTAREQUAL
| DOUBLESLASHEQUAL
;
print_stmt:
'print'
( testlist
| RIGHTSHIFT testlist
)?
;
del_stmt: 'del' exprlist
;
pass_stmt: 'pass'
;
flow_stmt: break_stmt
| continue_stmt
| return_stmt
| raise_stmt
| yield_stmt
;
break_stmt: 'break'
;
continue_stmt: 'continue'
;
return_stmt: 'return' (testlist)?
;
yield_stmt: 'yield' testlist
;
raise_stmt: 'raise' (test (COMMA test (COMMA test)?)?)?
;
import_stmt
: 'import' dotted_as_name (COMMA dotted_as_name)*
| 'from' dotted_name 'import'
(STAR | import_as_name (COMMA import_as_name)*)
;
import_as_name
: NAME (NAME NAME)?
;
dotted_as_name: dotted_name (NAME NAME)?
;
dotted_name: NAME (DOT NAME)*
;
global_stmt: 'global' NAME (COMMA NAME)*
;
exec_stmt: 'exec' expr ('in' test (COMMA test)?)?
;
assert_stmt: 'assert' test (COMMA test)?
;
compound_stmt: if_stmt
| while_stmt
| for_stmt
| try_stmt
| funcdef
| classdef
;
if_stmt: 'if' test COLON suite ('elif' test COLON suite)* ('else' COLON suite)?
;
while_stmt: 'while' test COLON suite ('else' COLON suite)?
;
for_stmt: 'for' exprlist 'in' testlist COLON suite ('else' COLON suite)?
;
try_stmt
: 'try' COLON suite
( (except_clause COLON suite)+ ('else' COLON suite)?
| 'finally' COLON suite
)
;
except_clause: 'except' (test (COMMA test)?)?
;
suite: simple_stmt
| NEWLINE INDENT (stmt)+ DEDENT
;
test: and_test ('or' and_test)*
| lambdef
;
and_test
: not_test ('and' not_test)*
;
not_test
: 'not' not_test
| comparison
;
comparison: expr (comp_op expr)*
;
comp_op: LESS
|GREATER
|EQUAL
|GREATEREQUAL
|LESSEQUAL
|ALT_NOTEQUAL
|NOTEQUAL
|'in'
|'not' 'in'
|'is'
|'is' 'not'
;
expr: xor_expr (VBAR xor_expr)*
;
xor_expr: and_expr (CIRCUMFLEX and_expr)*
;
and_expr: shift_expr (AMPER shift_expr)*
;
shift_expr: arith_expr ((LEFTSHIFT|RIGHTSHIFT) arith_expr)*
;
arith_expr: term ((PLUS|MINUS) term)*
;
term: factor ((STAR | SLASH | PERCENT | DOUBLESLASH ) factor)*
;
factor
: (PLUS|MINUS|TILDE) factor
| power
;
power
: atom (trailer)* (options {greedy=true;}:DOUBLESTAR factor)?
;
atom: LPAREN (testlist)? RPAREN
| LBRACK (listmaker)? RBRACK
| LCURLY (dictmaker)? RCURLY
| BACKQUOTE testlist BACKQUOTE
| NAME
| INT
| LONGINT
| FLOAT
| COMPLEX
| (STRING)+
;
listmaker: test ( list_for | (options {greedy=true;}:COMMA test)* ) (COMMA)?
;
lambdef: 'lambda' (varargslist)? COLON test
;
trailer: LPAREN (arglist)? RPAREN
| LBRACK subscriptlist RBRACK
| DOT NAME
;
subscriptlist
: subscript (options {greedy=true;}:COMMA subscript)* (COMMA)?
;
subscript
: DOT DOT DOT
| test (COLON (test)? (sliceop)?)?
| COLON (test)? (sliceop)?
;
sliceop: COLON (test)?
;
exprlist
: expr (options {k=2;}:COMMA expr)* (COMMA)?
;
testlist
: test (options {k=2;}: COMMA test)* (COMMA)?
;
dictmaker
: test COLON test
(options {k=2;}:COMMA test COLON test)* (COMMA)?
;
classdef: 'class' NAME (LPAREN testlist RPAREN)? COLON suite
{System.out.println("found class def "+$NAME.text);}
;
arglist: argument (COMMA argument)*
( COMMA
( STAR test (COMMA DOUBLESTAR test)?
| DOUBLESTAR test
)?
)?
| STAR test (COMMA DOUBLESTAR test)?
| DOUBLESTAR test
;
argument : test (ASSIGN test)?
;
list_iter: list_for
| list_if
;
list_for: 'for' exprlist 'in' testlist (list_iter)?
;
list_if: 'if' test (list_iter)?
;
LPAREN : '(' {implicitLineJoiningLevel++;} ;
RPAREN : ')' {implicitLineJoiningLevel--;} ;
LBRACK : '[' {implicitLineJoiningLevel++;} ;
RBRACK : ']' {implicitLineJoiningLevel--;} ;
COLON : ':' ;
COMMA : ',' ;
SEMI : ';' ;
PLUS : '+' ;
MINUS : '-' ;
STAR : '*' ;
SLASH : '/' ;
VBAR : '|' ;
AMPER : '&' ;
LESS : '<' ;
GREATER : '>' ;
ASSIGN : '=' ;
PERCENT : '%' ;
BACKQUOTE : '`' ;
LCURLY : '{' {implicitLineJoiningLevel++;} ;
RCURLY : '}' {implicitLineJoiningLevel--;} ;
CIRCUMFLEX : '^' ;
TILDE : '~' ;
EQUAL : '==' ;
NOTEQUAL : '!=' ;
ALT_NOTEQUAL: '<>' ;
LESSEQUAL : '<=' ;
LEFTSHIFT : '<<' ;
GREATEREQUAL : '>=' ;
RIGHTSHIFT : '>>' ;
PLUSEQUAL : '+=' ;
MINUSEQUAL : '-=' ;
DOUBLESTAR : '**' ;
STAREQUAL : '*=' ;
DOUBLESLASH : '//' ;
SLASHEQUAL : '/=' ;
VBAREQUAL : '|=' ;
PERCENTEQUAL : '%=' ;
AMPEREQUAL : '&=' ;
CIRCUMFLEXEQUAL : '^=' ;
LEFTSHIFTEQUAL : '<<=' ;
RIGHTSHIFTEQUAL : '>>=' ;
DOUBLESTAREQUAL : '**=' ;
DOUBLESLASHEQUAL : '//=' ;
DOT : '.' ;
FLOAT
: '.' DIGITS (Exponent)?
| DIGITS ('.' (DIGITS (Exponent)?)? | Exponent)
;
LONGINT
: INT ('l'|'L')
;
fragment
Exponent
: ('e' | 'E') ( '+' | '-' )? DIGITS
;
INT : // Hex
'0' ('x' | 'X') ( '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' )+
('l' | 'L')?
| // Octal
'0' DIGITS*
| '1'..'9' DIGITS*
;
COMPLEX
: INT ('j'|'J')
| FLOAT ('j'|'J')
;
fragment
DIGITS : ( '0' .. '9' )+ ;
NAME: ( 'a' .. 'z' | 'A' .. 'Z' | '_')
( 'a' .. 'z' | 'A' .. 'Z' | '_' | '0' .. '9' )*
;
/** Match various string types. Note that greedy=false implies '''
* should make us exit loop not continue.
*/
STRING
: ('r'|'u'|'ur')?
( '\'\'\'' (options {greedy=false;}:.)* '\'\'\''
| '"""' (options {greedy=false;}:.)* '"""'
| '"' (ESC|~('\\'|'\n'|'"'))* '"'
| '\'' (ESC|~('\\'|'\n'|'\''))* '\''
)
;
fragment
ESC
: '\\' .
;
/** Consume a newline and any whitespace at start of next line */
CONTINUED_LINE
: '\\' ('\r')? '\n' (' '|'\t')* { $channel=HIDDEN; }
;
/** Treat a sequence of blank lines as a single blank line. If
* nested within a (..), {..}, or [..], then ignore newlines.
* If the first newline starts in column one, they are to be ignored.
*/
NEWLINE
: (('\r')? '\n' )+
{if ( startPos==0 || implicitLineJoiningLevel>0 )
$channel=HIDDEN;
}
;
WS : {startPos>0}?=> (' '|'\t')+ {$channel=HIDDEN;}
;
/** Grab everything before a real symbol. Then if newline, kill it
* as this is a blank line. If whitespace followed by comment, kill it
* as it's a comment on a line by itself.
*
* Ignore leading whitespace when nested in [..], (..), {..}.
*/
LEADING_WS
@init {
int spaces = 0;
}
: {startPos==0}?=>
( {implicitLineJoiningLevel>0}? ( ' ' | '\t' )+ {$channel=HIDDEN;}
| ( ' ' { spaces++; }
| '\t' { spaces += 8; spaces -= (spaces \% 8); }
)+
{
// make a string of n spaces where n is column number - 1
char[] indentation = new char[spaces];
for (int i=0; i<spaces; i++) {
indentation[i] = ' ';
}
String s = new String(indentation);
emit(new ClassicToken(LEADING_WS,new String(indentation)));
}
// kill trailing newline if present and then ignore
( ('\r')? '\n' {if (state.token!=null) state.token.setChannel(HIDDEN); else $channel=HIDDEN;})*
// {token.setChannel(99); }
)
;
/** Comments not on line by themselves are turned into newlines.
b = a # end of line comment
or
a = [1, # weird
2]
This rule is invoked directly by nextToken when the comment is in
first column or when comment is on end of nonwhitespace line.
Only match \n here if we didn't start on left edge; let NEWLINE return that.
Kill if newlines if we live on a line by ourselves
Consume any leading whitespace if it starts on left edge.
*/
COMMENT
@init {
$channel=HIDDEN;
}
: {startPos==0}?=> (' '|'\t')* '#' (~'\n')* '\n'+
| {startPos>0}?=> '#' (~'\n')* // let NEWLINE handle \n unless char pos==0 for '#'
;

View File

@ -0,0 +1,201 @@
/*******************************************************************************
* Copyright (c) 2009 Scott Stanchfield
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
grammar Sample;
options {
language = Java;
output = AST;
output=template;
}
@header {
package samples.antlr;
}
@lexer::header {
package samples.antlr;
}
program
: 'program' IDENT '='
(constant | variable | function | procedure | typeDecl)*
'begin'
statement*
'end' IDENT '.'
;
constant
: 'constant' IDENT ':' type ':=' expression ';'
;
variable
: 'var' IDENT (',' IDENT)* ':' type (':=' expression)? ';'
;
type
: 'Integer'
| 'Boolean'
| 'String'
| 'Char'
| IDENT
| typeSpec
;
typeDecl
: 'type' IDENT '=' typeSpec ';'
;
typeSpec
: arrayType
| recordType
| enumType
;
arrayType
: 'array' '[' INTEGER '..' INTEGER ']' 'of' type
;
recordType
: 'record' field* 'end' 'record'
;
field
: IDENT ':' type ';'
;
enumType
: '<' IDENT (',' IDENT)* '>'
;
statement
: assignmentStatement
| ifStatement
| loopStatement
| whileStatement
| procedureCallStatement
;
procedureCallStatement
: IDENT '(' actualParameters? ')' ';'
;
actualParameters
: expression (',' expression)*
;
ifStatement
: 'if' expression 'then' statement+
('elsif' expression 'then' statement+)*
('else' statement+)?
'end' 'if' ';'
;
assignmentStatement
: IDENT ':=' expression ';'
;
exitStatement
: 'exit' 'when' expression ';'
;
whileStatement
: 'while' expression 'loop'
(statement|exitStatement)*
'end' 'loop' ';'
;
loopStatement
: 'loop' (statement|exitStatement)* 'end' 'loop' ';'
;
returnStatement
: 'return' expression ';'
;
procedure
: 'procedure' IDENT '(' parameters? ')' '='
(constant | variable)*
'begin'
statement*
'end' IDENT '.'
;
function
: 'function' IDENT '(' parameters? ')' ':' type '='
(constant | variable)*
'begin'
(statement|returnStatement)*
'end' IDENT '.'
;
parameters
: parameter (',' parameter)*
;
parameter
: 'var'? IDENT ':' type
;
// expressions -- fun time!
term
: IDENT
| '(' expression ')'
| INTEGER
| STRING_LITERAL
| CHAR_LITERAL
| IDENT '(' actualParameters ')'
;
negation
: 'not'* term
;
unary
: ('+' | '-')* negation
;
mult
: unary (('*' | '/' | 'mod') unary)*
;
add
: mult (('+' | '-') mult)*
;
relation
: add (('=' | '/=' | '<' | '<=' | '>=' | '>') add)*
;
expression
: relation (('and' | 'or') relation)*
;
MULTILINE_COMMENT : '/*' .* '*/' {$channel = HIDDEN;} ;
STRING_LITERAL
: '"'
{ StringBuilder b = new StringBuilder(); }
( '"' '"' { b.appendCodePoint('"');}
| c=~('"'|'\r'|'\n') { b.appendCodePoint(c);}
)*
'"'
{ setText(b.toString()); }
;
CHAR_LITERAL
: '\'' . '\'' {setText(getText().substring(1,2));}
;
fragment LETTER : ('a'..'z' | 'A'..'Z') ;
fragment DIGIT : '0'..'9';
INTEGER : DIGIT+ ;
IDENT : LETTER (LETTER | DIGIT)*;
WS : (' ' | '\t' | '\n' | '\r' | '\f')+ {$channel = HIDDEN;};
COMMENT : '//' .* ('\n'|'\r') {$channel = HIDDEN;};

View File

@ -0,0 +1,10 @@
/** https://github.com/rollxx/antlr-php-runtime/blob/master/examples/cminus/Bytecode.stg */
variable(type,name) ::= ".var is <name> <type><\n>"
type_int() ::= "I"
type_char() ::= "C"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,81 @@
/*******************************************************************************
* Copyright (c) 2009 Scott Stanchfield
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package samples.antlr;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.DOTTreeGenerator;
import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup;
public class Test1 {
public static void main(String[] args) throws RecognitionException {
CharStream stream =
new ANTLRStringStream("program XLSample1 =\r\n" +
"/*\r\n" +
" constant one : Integer := 1;\r\n" +
" constant two : Integer := 2 * 3;\r\n" +
" var x, y, z : Integer := 42;\r\n" +
"*/\r\n" +
"\r\n" +
" procedure foo() =\r\n" +
" var x : Integer := 2;\r\n" +
" begin\r\n" +
" end foo.\r\n" +
" procedure fee(y : Integer) =\r\n" +
" var x : Integer := 2;\r\n" +
" begin\r\n" +
" end fee.\r\n" +
" function fie(y : Integer) : Integer =\r\n" +
" var x : Integer := 2;\r\n" +
" begin\r\n" +
" return y;\r\n" +
" end fie.\r\n" +
"begin\r\n" +
"end XLSample1.");
SampleLexer lexer = new SampleLexer(stream);
TokenStream tokenStream = new CommonTokenStream(lexer);
SampleParser parser = new SampleParser(tokenStream);
CommonTree astTree = (CommonTree) parser.program().getTree();
DOTTreeGenerator gen = new DOTTreeGenerator();
StringTemplate st = gen.toDOT(astTree);
String userDir = System.getProperty("user.dir");
String stgFile = userDir + "\\src\\main\\java\\samples\\antlr\\Sample2Asm.stg";
StringTemplateGroup stg = new StringTemplateGroup(stgFile);
parser.setTemplateLib(stg);
RuleReturnScope r = parser.program();
// System.out.println(r.getTemplate().toString());
// System.out.println(st);
/*
Lexical Analysis (scanning)
Semantic Analysis (parsing)
Tree Generation ==> Abstract Syntax Tree (AST)
Code Generation ==> using stg file
Interpretation
*/
System.out.println("ok");
}
}

View File

@ -0,0 +1,51 @@
package samples.netty;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import java.nio.channels.SocketChannel;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 10/04/14 08:20
*/
public class Client {
public static void main(String[] args) throws Exception {
String host = "85.65.126.45";
int port = 10101;
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(workerGroup);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.SO_KEEPALIVE, true);
b.handler(new ChannelInitializer<NioSocketChannel>() {
@Override
public void initChannel(NioSocketChannel ch) throws Exception {
ch.pipeline().addLast(new ClientMessageHandler());
}
});
// Start the client.
ChannelFuture f = b.connect(host, port).sync(); // (5)
// Wait until the connection is closed.
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
}
}
}

View File

@ -0,0 +1,70 @@
package samples.netty;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 10/04/14 08:19
*/
public class ClientMessageHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf input = ((ByteBuf)msg);
try {
int inputSize = input.readableBytes();
byte[] payload = new byte[inputSize];
input.readBytes(payload);
if (payload.length < 5){
System.out.println("Not a Roman server disconnect");
ctx.close();
}
String prefix = new String(payload, 0, 5);
if (!prefix.equals("9191-")){
System.out.println("Not a Roman server disconnect");
ctx.close();
}
String newMessage = new String(payload);
System.out.println(newMessage);
Thread.sleep(1000);
String answer = RomanProtocol.getAnswer(newMessage);
final ByteBuf buffer = ctx.alloc().buffer(answer.length());
buffer.writeBytes(answer.getBytes());
ctx.writeAndFlush(buffer);
// String answer2 = "cool sir 2!!!";
// final ByteBuf helloMessage2 = ctx.alloc().buffer(answer2.length());
// helloMessage2.writeBytes(answer2.getBytes());
// ctx.writeAndFlush(helloMessage2);
} finally {
ReferenceCountUtil.release(input);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}

View File

@ -0,0 +1,47 @@
package samples.netty;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 10/04/14 11:19
*/
public class RomanProtocol {
public static String getAnswer(String msg){
if (msg.equals("9191-Hello"))
return ("9191-Good day sir");
if (msg.equals("9191-Good day sir"))
return ("9191-What is you name");
if (msg.equals("9191-What is you name"))
return ("9191-My Name is Ethereum");
if (msg.matches("9191-My Name is ([\\w])*")) {
String name = msg.substring(16);
return ("9191-Good to see you: " + name);
}
if (msg.matches("9191-Good to see you: ([\\w])*")) {
return ("9191-Hello");
}
return "9191-Sorry I don't understand you";
}
public static void main(String args[]){
System.out.println(getAnswer("9191-My Name is Vasia"));
// 1800-0770-77
}
}

View File

@ -0,0 +1,69 @@
package samples.netty;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 10/04/14 08:20
*/
public class Server {
int port;
public Server(int port) {
this.port = port;
}
public void start(){
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
public void initChannel(NioSocketChannel channel){
channel.pipeline().addLast(new ServerMessageHandler());
};
}).option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
try {
System.out.println("Server started");
ChannelFuture future = bootstrap.bind(port).sync();
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public static void main(String args[]){
new Server(10101).start();
}
}

View File

@ -0,0 +1,65 @@
package samples.netty;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.util.ReferenceCountUtil;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 10/04/14 08:19
*/
public class ServerMessageHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(final ChannelHandlerContext ctx) {
String helloString = "9191-Hello";
final ByteBuf helloMessage = ctx.alloc().buffer(helloString.length());
helloMessage.writeBytes(helloString.getBytes());
final ChannelFuture channelFuture = ctx.writeAndFlush(helloMessage);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf input = ((ByteBuf)msg);
try {
int inputSize = input.readableBytes();
byte[] payload = new byte[inputSize];
input.readBytes(payload);
String newMessage = new String(payload);
System.out.println(newMessage);
Thread.sleep(1000);
String answer = RomanProtocol.getAnswer(newMessage);
final ByteBuf buffer = ctx.alloc().buffer(answer.length());
buffer.writeBytes(answer.getBytes());
ctx.writeAndFlush(buffer);
} finally {
ReferenceCountUtil.release(input);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println("Client disconnected");
// cause.printStackTrace();
ctx.close();
}
}

View File

@ -0,0 +1,18 @@
package samples.niotut;
import java.nio.channels.SocketChannel;
public class ChangeRequest {
public static final int REGISTER = 1;
public static final int CHANGEOPS = 2;
public SocketChannel socket;
public int type;
public int ops;
public ChangeRequest(SocketChannel socket, int type, int ops) {
this.socket = socket;
this.type = type;
this.ops = ops;
}
}

View File

@ -0,0 +1,38 @@
package samples.niotut;
import java.nio.channels.SocketChannel;
import java.util.LinkedList;
import java.util.List;
public class EchoWorker implements Runnable {
private List queue = new LinkedList();
public void processData(NioServer server, SocketChannel socket, byte[] data, int count) {
byte[] dataCopy = new byte[count];
System.arraycopy(data, 0, dataCopy, 0, count);
synchronized(queue) {
queue.add(new ServerDataEvent(server, socket, dataCopy));
queue.notify();
}
}
public void run() {
ServerDataEvent dataEvent;
while(true) {
// Wait for data to become available
synchronized(queue) {
while(queue.isEmpty()) {
try {
queue.wait();
} catch (InterruptedException e) {
}
}
dataEvent = (ServerDataEvent) queue.remove(0);
}
// Return to sender
dataEvent.server.send(dataEvent.socket, dataEvent.data);
}
}
}

View File

@ -0,0 +1,403 @@
package samples.niotut;
/* BASED ON: http://rox-xmlrpc.sourceforge.net/niotut/#The client */
import org.ethereum.util.Utils;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.*;
public class NioClient implements Runnable {
// The host:port combination to connect to
private InetAddress hostAddress;
private int port;
// The selector we'll be monitoring
private Selector selector;
// The buffer into which we'll read data when it's available
private ByteBuffer readBuffer = ByteBuffer.allocate(8192);
// A list of PendingChange instances
private List pendingChanges = new LinkedList();
// Maps a SocketChannel to a list of ByteBuffer instances
private Map pendingData = new HashMap();
// Maps a SocketChannel to a RspHandler
private Map rspHandlers = Collections.synchronizedMap(new HashMap());
public SocketChannel socket;
public RspHandler handler;
public static final String helloString = "22 40 08 91 00 00 00 79 F8 77 80 0B 80 AD 45 74 " +
"68 65 72 65 75 6D 28 2B 2B 29 2F 5A 65 72 6F 47 " +
"6F 78 2F 76 30 2E 34 2E 31 2F 6E 63 75 72 73 65 " +
"73 2F 4C 69 6E 75 78 2F 67 2B 2B 07 82 76 5F B8 " +
"40 D8 D6 0C 25 80 FA 79 5C FC 03 13 EF DE BA 86 " +
"9D 21 94 E7 9E 7C B2 B5 22 F7 82 FF A0 39 2C BB " +
"AB 8D 1B AC 30 12 08 B1 37 E0 DE 49 98 33 4F 3B " +
"CF 73 FA 11 7E F2 13 F8 74 17 08 9F EA F8 4C 21 " +
"B0 ";
public static final String pingString = "22 40 08 91 00 00 00 02 C1 02 ";
public static final String pongString = "22 40 08 91 00 00 00 02 C1 03 ";
public static final String getPeersString = "22 40 08 91 00 00 00 02 C1 10 ";
public static final String getTransactions = "22 40 08 91 00 00 00 02 C1 16 ";
public static final String getChain = "22 40 08 91 00 00 00 26 F8 24 14 " +
"AB 6B 9A 56 13 97 0F AA 77 1B 12 D4 49 B2 E9 BB 92 5A B7 A3 69 F0 A4 B8 6B 28 6E 9D 54 00 99 CF " +
"82 01 00 ";
public static final String getTxString = "22 40 08 91 00 00 00 02 C1 16 ";
public NioClient(InetAddress hostAddress, int port) throws IOException {
this.hostAddress = hostAddress;
this.port = port;
this.selector = this.initSelector();
// Start a new connection
this.socket = this.initiateConnection();
// Register the response handler
this.handler = new RspHandler();
this.rspHandlers.put(socket, handler);
}
public void send(byte[] data) throws IOException {
// And queue the data we want written
synchronized (this.pendingData) {
List queue = (List) this.pendingData.get(socket);
if (queue == null) {
queue = new ArrayList();
this.pendingData.put(socket, queue);
}
queue.add(ByteBuffer.wrap(data));
}
// Finally, wake up our selecting thread so it can make the required changes
this.selector.wakeup();
}
public void run() {
while (true) {
try {
// Process any pending changes
synchronized (this.pendingChanges) {
Iterator changes = this.pendingChanges.iterator();
while (changes.hasNext()) {
ChangeRequest change = (ChangeRequest) changes.next();
switch (change.type) {
case ChangeRequest.CHANGEOPS:
SelectionKey key = change.socket.keyFor(this.selector);
key.interestOps(change.ops);
break;
case ChangeRequest.REGISTER:
change.socket.register(this.selector, change.ops);
break;
}
}
this.pendingChanges.clear();
}
// Wait for an event one of the registered channels
// THIS ONE ACTUALLY BLOCKS AND SHOULD AWAKE WHEN SOME I/O HAPPENS
this.selector.select();
// Iterate over the set of keys for which events are available
Iterator selectedKeys = this.selector.selectedKeys().iterator();
while (selectedKeys.hasNext()) {
SelectionKey key = (SelectionKey) selectedKeys.next();
selectedKeys.remove();
if (!key.isValid()) {
continue;
}
// Check what event is available and deal with it
if (key.isConnectable()) {
this.establishConnection(key);
} else if (key.isReadable()) {
this.read(key);
} else if (key.isWritable()) {
this.write(key);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void read(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
// Clear out our read buffer so it's ready for new data
this.readBuffer.clear();
// Attempt to read off the channel
int numRead;
try {
numRead = socketChannel.read(this.readBuffer);
System.out.println("reading: " + numRead);
// key.interestOps(SelectionKey.OP_WRITE);
} catch (IOException e) {
// The remote forcibly closed the connection, cancel
// the selection key and close the channel.
key.cancel();
socketChannel.close();
return;
}
if (numRead == -1) {
// Remote entity shut the socket down cleanly. Do the
// same from our end and cancel the channel.
// key.channel().close();
// key.cancel();
return;
}
// Handle the response
this.handleResponse(socketChannel, this.readBuffer.array(), numRead);
}
private void handleResponse(SocketChannel socketChannel, byte[] data, int numRead) throws IOException {
// Make a correctly sized copy of the data before handing it
// to the client
byte[] rspData = new byte[numRead];
System.arraycopy(data, 0, rspData, 0, numRead);
// Look up the handler for this channel
RspHandler handler = (RspHandler) this.rspHandlers.get(socketChannel);
// And pass the response to it
if (handler.handleResponse(rspData)) {
// The handler has seen enough, close the connection
// socketChannel.close();
// socketChannel.keyFor(this.selector).cancel();
}
}
private void write(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
synchronized (this.pendingData) {
List queue = (List) this.pendingData.get(socketChannel);
// Write until there's not more data ...
while (queue != null && !queue.isEmpty()) {
ByteBuffer buf = (ByteBuffer) queue.get(0);
byte[] packet = buf.array();
System.out.print("write: ");
Utils.printHexStringForByteArray(packet);
socketChannel.write(buf);
if (buf.remaining() > 0) {
// ... or the socket's buffer fills up
break;
}
queue.remove(0);
}
// key.interestOps(SelectionKey.OP_READ);
if (queue == null || queue.isEmpty()) {
// We wrote away all data, so we're no longer interested
// in writing on this socket. Switch back to waiting for
// data.
key.interestOps(SelectionKey.OP_READ);
}
}
}
private void establishConnection(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
// Finish the connection. If the connection operation failed
// this will raise an IOException.
try {
socketChannel.finishConnect();
} catch (IOException e) {
// Cancel the channel's registration with our selector
System.out.println(e);
key.cancel();
return;
}
// Register an interest in writing on this channel
key.interestOps(SelectionKey.OP_WRITE);
}
private SocketChannel initiateConnection() throws IOException {
// Create a non-blocking socket channel
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
// Kick off connection establishment
socketChannel.connect(new InetSocketAddress(this.hostAddress, this.port));
// Queue a channel registration since the caller is not the
// selecting thread. As part of the registration we'll register
// an interest in connection events. These are raised when a channel
// is ready to complete connection establishment.
synchronized(this.pendingChanges) {
this.pendingChanges.add(new ChangeRequest(socketChannel,
ChangeRequest.REGISTER, SelectionKey.OP_CONNECT));
}
return socketChannel;
}
private Selector initSelector() throws IOException {
// Create a new selector
return SelectorProvider.provider().openSelector();
}
public static void main(String[] args) {
try {
NioClient client = new NioClient(InetAddress.getByName("localhost"), 20202);
Thread t = new Thread(client, "ClientThread");
t.setDaemon(true);
t.start();
// client.send(new byte[0]);
// client.handler.waitForResponse();
Thread.sleep(2000);
System.out.println("\nsending HELLO");
client.enableWriting();
// client.send(hexStringToByteArr(helloString));
Thread.sleep(100);
System.out.println("\nsending PONG");
// client.enableWriting();
// client.send(hexStringToByteArr(pongString));
Thread.sleep(100);
System.out.println("\nsending GETCHAIN");
// client.enableWriting();
// client.send(hexStringToByteArr(getChain));
// System.out.println("\nsending PING");
// client.send(hexStringToByteArr(pingString));
// client.handler.waitForResponse();
System.out.println("SLEEPING");
Thread.sleep(5000);
client.handler.waitForResponse();
// System.out.println("\nsending GETCHAIN");
// client.send(hexStringToByteArr(getChain));
// client.handler.waitForResponse();
// System.out.println("\nsending GETPEERS");
// client.send(hexStringToByteArr(getPeersString));
// client.handler.waitForResponse();
// client.handler.waitForResponse();
// System.out.println("\nsending GETTRANSACTIONS");
// client.send(hexStringToByteArr(getTransactions));
System.out.println("\nsleeping 5 secs before death");
Thread.sleep(5000);
client.socket.close();
/*
client.send(hexStringToByteArr(helloString));
client.handler.waitForResponse();
System.out.println("");
client.send(hexStringToByteArr(getPeersString));
client.handler.waitForResponse();
System.out.println("");
client.handler.waitForResponse();
System.out.println("");
client.handler.waitForResponse();
*/
} catch (Exception e) {
e.printStackTrace();
}
}
public static byte[] hexStringToByteArr(String hexString){
String hexSymbols = "0123456789ABCDEF";
int arrSize = (int) (hexString.length() / 3);
byte[] result = new byte[arrSize];
for (int i = 0; i < arrSize; ++i){
int digit1 = hexSymbols.indexOf( hexString.charAt(i * 3) );
int digit2 = hexSymbols.indexOf( hexString.charAt(i * 3 + 1) );
result[i] = (byte) (digit1 * 16 + digit2);
}
return result;
}
public void enableWriting(){
SelectionKey key = this.socket.keyFor(this.selector);
key.interestOps(SelectionKey.OP_WRITE | SelectionKey.OP_READ);
}
public void enableOnlyReading(){
SelectionKey key = this.socket.keyFor(this.selector);
key.interestOps(SelectionKey.OP_READ);
}
}

View File

@ -0,0 +1,213 @@
package samples.niotut;
/* BASED ON: http://rox-xmlrpc.sourceforge.net/niotut/#The client */
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.*;
public class NioServer implements Runnable {
// The host:port combination to listen on
private InetAddress hostAddress;
private int port;
// The channel on which we'll accept connections
private ServerSocketChannel serverChannel;
// The selector we'll be monitoring
private Selector selector;
// The buffer into which we'll read data when it's available
private ByteBuffer readBuffer = ByteBuffer.allocate(8192);
private EchoWorker worker;
// A list of PendingChange instances
private List pendingChanges = new LinkedList();
// Maps a SocketChannel to a list of ByteBuffer instances
private Map pendingData = new HashMap();
public NioServer(InetAddress hostAddress, int port, EchoWorker worker) throws IOException {
this.hostAddress = hostAddress;
this.port = port;
this.selector = this.initSelector();
this.worker = worker;
}
public void send(SocketChannel socket, byte[] data) {
synchronized (this.pendingChanges) {
// Indicate we want the interest ops set changed
this.pendingChanges.add(new ChangeRequest(socket, ChangeRequest.CHANGEOPS, SelectionKey.OP_WRITE));
// And queue the data we want written
synchronized (this.pendingData) {
List queue = (List) this.pendingData.get(socket);
if (queue == null) {
queue = new ArrayList();
this.pendingData.put(socket, queue);
}
queue.add(ByteBuffer.wrap(data));
}
}
// Finally, wake up our selecting thread so it can make the required changes
this.selector.wakeup();
}
public void run() {
while (true) {
try {
// Process any pending changes
synchronized (this.pendingChanges) {
Iterator changes = this.pendingChanges.iterator();
while (changes.hasNext()) {
ChangeRequest change = (ChangeRequest) changes.next();
switch (change.type) {
case ChangeRequest.CHANGEOPS:
SelectionKey key = change.socket.keyFor(this.selector);
key.interestOps(change.ops);
}
}
this.pendingChanges.clear();
}
// Wait for an event one of the registered channels
System.out.println("accepting");
this.selector.select();
// Iterate over the set of keys for which events are available
Iterator selectedKeys = this.selector.selectedKeys().iterator();
while (selectedKeys.hasNext()) {
SelectionKey key = (SelectionKey) selectedKeys.next();
selectedKeys.remove();
if (!key.isValid()) {
continue;
}
// Check what event is available and deal with it
if (key.isAcceptable()) {
System.out.println("new channel");
this.accept(key);
} else if (key.isReadable()) {
System.out.println("reading");
this.read(key);
} else if (key.isWritable()) {
System.out.println("writing");
this.write(key);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void accept(SelectionKey key) throws IOException {
// For an accept to be pending the channel must be a server socket channel.
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
// Accept the connection and make it non-blocking
SocketChannel socketChannel = serverSocketChannel.accept();
Socket socket = socketChannel.socket();
socketChannel.configureBlocking(false);
// Register the new SocketChannel with our Selector, indicating
// we'd like to be notified when there's data waiting to be read
socketChannel.register(this.selector, SelectionKey.OP_READ);
}
private void read(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
// Clear out our read buffer so it's ready for new data
this.readBuffer.clear();
// Attempt to read off the channel
int numRead;
try {
numRead = socketChannel.read(this.readBuffer);
} catch (IOException e) {
// The remote forcibly closed the connection, cancel
// the selection key and close the channel.
key.cancel();
socketChannel.close();
return;
}
if (numRead == -1) {
// Remote entity shut the socket down cleanly. Do the
// same from our end and cancel the channel.
key.channel().close();
key.cancel();
return;
}
// Hand the data off to our worker thread
this.worker.processData(this, socketChannel, this.readBuffer.array(), numRead);
}
private void write(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
synchronized (this.pendingData) {
List queue = (List) this.pendingData.get(socketChannel);
// Write until there's not more data ...
while (!queue.isEmpty()) {
ByteBuffer buf = (ByteBuffer) queue.get(0);
socketChannel.write(buf);
if (buf.remaining() > 0) {
// ... or the socket's buffer fills up
break;
}
queue.remove(0);
}
if (queue.isEmpty()) {
// We wrote away all data, so we're no longer interested
// in writing on this socket. Switch back to waiting for
// data.
key.interestOps(SelectionKey.OP_READ);
}
}
}
private Selector initSelector() throws IOException {
// Create a new selector
Selector socketSelector = SelectorProvider.provider().openSelector();
// Create a new non-blocking server socket channel
this.serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
// Bind the server socket to the specified address and port
InetSocketAddress isa = new InetSocketAddress(this.hostAddress, this.port);
serverChannel.socket().bind(isa);
// Register the server socket channel, indicating an interest in
// accepting new connections
serverChannel.register(socketSelector, SelectionKey.OP_ACCEPT);
return socketSelector;
}
public static void main(String[] args) {
try {
EchoWorker worker = new EchoWorker();
new Thread(worker).start();
new Thread(new NioServer(null, 9090, worker)).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,107 @@
package samples.niotut;
import org.ethereum.net.RLP;
import org.ethereum.util.Utils;
import java.util.LinkedList;
import java.util.Queue;
public class RspHandler {
public Queue<byte[]> packetsRecived = new LinkedList<byte[]>();
public synchronized boolean handleResponse(byte[] rsp) {
packetsRecived.add(rsp);
this.notify();
return true;
}
public synchronized void waitForResponse() {
while(packetsRecived.isEmpty()) {
try {
this.wait();
} catch (InterruptedException e) {
}
}
while (!packetsRecived.isEmpty()) {
byte[] rsp = packetsRecived.remove();
Utils.printHexStringForByteArray(rsp);
if (rsp.length < 9){
// Can't be any ether packet
}
boolean noMoreMessages = false;
// 22 40 08 91 - magic packet
if ((rsp[0] & 0xFF) == 0x22 &&
(rsp[1] & 0xFF) == 0x40 &&
(rsp[2] & 0xFF) == 0x08 &&
(rsp[3] & 0xFF) == 0x91 ){
// Got ethereum message
}
int numMessages = 0;
// count number of messages in the packet
for (int i = 0; i < rsp.length - 3; ++i){
if ( (rsp[i + 0] & 0xFF) == 0x22 &&
(rsp[i + 1] & 0xFF) == 0x40 &&
(rsp[i + 2] & 0xFF) == 0x08 &&
(rsp[i + 3] & 0xFF) == 0x91 ){
++numMessages;
}
}
System.out.println("This packet contains: " + numMessages + " messages");
for (int i = 0; i < numMessages; ++i){
// Callc message length
int messageLength = ((rsp[4] & 0xFF) << 24) +
((rsp[5] & 0xFF) << 16) +
((rsp[6] & 0xFF) << 8) +
((rsp[7] & 0xFF));
byte[] msgPayload = new byte[messageLength];
System.out.println("payload size: " + msgPayload.length );
System.out.println("packet size: " + messageLength );
System.arraycopy(rsp, 8, msgPayload, 0, messageLength);
Utils.printHexStringForByteArray(msgPayload);
Queue<Integer> index = new LinkedList<Integer>();
RLP.fullTraverse(msgPayload, 0, 0, msgPayload.length, 1, index);
// Message msg = MessageFactory.createMessage(msgPayload, index);
// System.out.println("msg: " + msg);
// shift next message to the start of the packet array
if (i + 1 < numMessages){
System.arraycopy(rsp, msgPayload.length + 8, rsp, 0, rsp.length - msgPayload.length - 8);
}
}
System.out.println();
}
}
}

View File

@ -0,0 +1,16 @@
package samples.niotut;
import java.nio.channels.SocketChannel;
class ServerDataEvent {
public NioServer server;
public SocketChannel socket;
public byte[] data;
public ServerDataEvent(NioServer server, SocketChannel socket, byte[] data) {
this.server = server;
this.socket = socket;
this.data = data;
}
}

View File

@ -0,0 +1,74 @@
group Bytecode;
program(globals,functions) ::= <<
.class public Wrapper
.super java/lang/Object
<globals>
<functions>
>>
variable(type,name) ::= ".var is <name> <type><\n>"
globalVariable(type,name) ::= ".field <name> <type><\n>"
function(type,name,args,locals,stats) ::= <<
.method <name>(<args:{<it.type>}>)<type>
<locals>
<stats; separator="\n">
return
.end method
>>
type_int() ::= "I"
type_char() ::= "C"
type_user_object(name) ::= "L<name>;"
parameter(type,name) ::= "<type> <name>"
statement(expr) ::= "<expr>"
statementList(locals,stats) ::= <<
<locals>
<stats; separator="\n">
>>
forLoop(e1,e2,e3,locals,stats) ::= <<
<e1>
start:
<e2>
bf exit
<locals>
<stats; separator="\n">
<e3>
goto start
exit:
>>
assign(lhs,rhs) ::= <<
<rhs>
store <lhs>
>>
equals(left,right) ::= <<
<left>
<right>
equals
>>
lessThan(left,right) ::= <<
<left>
<right>
lt
>>
add(left,right) ::= <<
<left>
<right>
add
>>
refVar(id) ::= "push <id>"
iconst(value) ::= "iconst <value>"

View File

@ -0,0 +1,152 @@
grammar CMinus;
options {output=template;}
scope slist {
List locals; // must be defined one per semicolon
List stats;
}
/*
@slist::init {
locals = new ArrayList();
stats = new ArrayList();
}
*/
@header {
package samples.stg;
import org.antlr.stringtemplate.*;
}
@lexer::header {
package samples.stg;
}
program
scope {
List globals;
List functions;
}
@init {
$program::globals = new ArrayList();
$program::functions = new ArrayList();
}
: declaration+
-> program(globals={$program::globals},functions={$program::functions})
;
declaration
: variable {$program::globals.add($variable.st);}
| f=function {$program::functions.add($f.st);}
;
// ack is $function.st ambig? It can mean the rule's dyn scope or
// the ref in this rule. Ack.
variable
: type declarator ';'
-> {$function.size()>0 && $function::name==null}?
globalVariable(type={$type.st},name={$declarator.st})
-> variable(type={$type.st},name={$declarator.st})
;
declarator
: ID -> {new StringTemplate($ID.text)}
;
function
scope {
String name;
}
scope slist;
@init {
$slist::locals = new ArrayList();
$slist::stats = new ArrayList();
}
: type ID {$function::name=$ID.text;}
'(' ( p+=formalParameter ( ',' p+=formalParameter )* )? ')'
block
-> function(type={$type.st}, name={$function::name},
locals={$slist::locals},
stats={$slist::stats},
args={$p})
;
formalParameter
: type declarator
-> parameter(type={$type.st},name={$declarator.st})
;
type
: 'int' -> type_int()
| 'char' -> type_char()
| ID -> type_user_object(name={$ID.text})
;
block
: '{'
( variable {$slist::locals.add($variable.st);} )*
( stat {$slist::stats.add($stat.st);})*
'}'
;
stat
scope slist;
@init {
$slist::locals = new ArrayList();
$slist::stats = new ArrayList();
}
: forStat -> {$forStat.st}
| expr ';' -> statement(expr={$expr.st})
| block -> statementList(locals={$slist::locals}, stats={$slist::stats})
| assignStat ';' -> {$assignStat.st}
| ';' -> {new StringTemplate(";")}
;
forStat
scope slist;
@init {
$slist::locals = new ArrayList();
$slist::stats = new ArrayList();
}
: 'for' '(' e1=assignStat ';' e2=expr ';' e3=assignStat ')' block
-> forLoop(e1={$e1.st},e2={$e2.st},e3={$e3.st},
locals={$slist::locals}, stats={$slist::stats})
;
assignStat
: ID '=' expr -> assign(lhs={$ID.text}, rhs={$expr.st})
;
expr: condExpr -> {$condExpr.st}
;
condExpr
: a=aexpr
( ( '==' b=aexpr -> equals(left={$a.st},right={$b.st})
| '<' b=aexpr -> lessThan(left={$a.st},right={$b.st})
)
| -> {$a.st} // else just aexpr
)
;
aexpr
: (a=atom -> {$a.st})
( '+' b=atom -> add(left={$aexpr.st}, right={$b.st}) )*
;
atom
: ID -> refVar(id={$ID.text})
| INT -> iconst(value={$INT.text})
| '(' expr ')' -> {$expr.st}
;
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
;
INT : ('0'..'9')+
;
WS : (' ' | '\t' | '\r' | '\n')+ {$channel=HIDDEN;}
;

View File

@ -0,0 +1,824 @@
// $ANTLR 3.5.2 E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g 2014-04-27 13:24:16
package samples.stg;
import org.antlr.runtime.*;
import java.util.Stack;
import java.util.List;
import java.util.ArrayList;
@SuppressWarnings("all")
public class CMinusLexer extends Lexer {
public static final int EOF=-1;
public static final int T__7=7;
public static final int T__8=8;
public static final int T__9=9;
public static final int T__10=10;
public static final int T__11=11;
public static final int T__12=12;
public static final int T__13=13;
public static final int T__14=14;
public static final int T__15=15;
public static final int T__16=16;
public static final int T__17=17;
public static final int T__18=18;
public static final int T__19=19;
public static final int ID=4;
public static final int INT=5;
public static final int WS=6;
// delegates
// delegators
public Lexer[] getDelegates() {
return new Lexer[] {};
}
public CMinusLexer() {}
public CMinusLexer(CharStream input) {
this(input, new RecognizerSharedState());
}
public CMinusLexer(CharStream input, RecognizerSharedState state) {
super(input,state);
}
@Override public String getGrammarFileName() { return "E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g"; }
// $ANTLR start "T__7"
public final void mT__7() throws RecognitionException {
try {
int _type = T__7;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:6:6: ( '(' )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:6:8: '('
{
match('(');
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "T__7"
// $ANTLR start "T__8"
public final void mT__8() throws RecognitionException {
try {
int _type = T__8;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:7:6: ( ')' )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:7:8: ')'
{
match(')');
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "T__8"
// $ANTLR start "T__9"
public final void mT__9() throws RecognitionException {
try {
int _type = T__9;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:8:6: ( '+' )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:8:8: '+'
{
match('+');
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "T__9"
// $ANTLR start "T__10"
public final void mT__10() throws RecognitionException {
try {
int _type = T__10;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:9:7: ( ',' )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:9:9: ','
{
match(',');
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "T__10"
// $ANTLR start "T__11"
public final void mT__11() throws RecognitionException {
try {
int _type = T__11;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:10:7: ( ';' )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:10:9: ';'
{
match(';');
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "T__11"
// $ANTLR start "T__12"
public final void mT__12() throws RecognitionException {
try {
int _type = T__12;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:11:7: ( '<' )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:11:9: '<'
{
match('<');
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "T__12"
// $ANTLR start "T__13"
public final void mT__13() throws RecognitionException {
try {
int _type = T__13;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:12:7: ( '=' )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:12:9: '='
{
match('=');
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "T__13"
// $ANTLR start "T__14"
public final void mT__14() throws RecognitionException {
try {
int _type = T__14;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:13:7: ( '==' )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:13:9: '=='
{
match("==");
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "T__14"
// $ANTLR start "T__15"
public final void mT__15() throws RecognitionException {
try {
int _type = T__15;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:14:7: ( 'char' )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:14:9: 'char'
{
match("char");
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "T__15"
// $ANTLR start "T__16"
public final void mT__16() throws RecognitionException {
try {
int _type = T__16;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:15:7: ( 'for' )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:15:9: 'for'
{
match("for");
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "T__16"
// $ANTLR start "T__17"
public final void mT__17() throws RecognitionException {
try {
int _type = T__17;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:16:7: ( 'int' )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:16:9: 'int'
{
match("int");
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "T__17"
// $ANTLR start "T__18"
public final void mT__18() throws RecognitionException {
try {
int _type = T__18;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:17:7: ( '{' )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:17:9: '{'
{
match('{');
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "T__18"
// $ANTLR start "T__19"
public final void mT__19() throws RecognitionException {
try {
int _type = T__19;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:18:7: ( '}' )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:18:9: '}'
{
match('}');
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "T__19"
// $ANTLR start "ID"
public final void mID() throws RecognitionException {
try {
int _type = ID;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:145:5: ( ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' )* )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:145:9: ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' )*
{
if ( (input.LA(1) >= 'A' && input.LA(1) <= 'Z')||input.LA(1)=='_'||(input.LA(1) >= 'a' && input.LA(1) <= 'z') ) {
input.consume();
}
else {
MismatchedSetException mse = new MismatchedSetException(null,input);
recover(mse);
throw mse;
}
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:145:33: ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' )*
loop1:
while (true) {
int alt1=2;
int LA1_0 = input.LA(1);
if ( ((LA1_0 >= '0' && LA1_0 <= '9')||(LA1_0 >= 'A' && LA1_0 <= 'Z')||LA1_0=='_'||(LA1_0 >= 'a' && LA1_0 <= 'z')) ) {
alt1=1;
}
switch (alt1) {
case 1 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:
{
if ( (input.LA(1) >= '0' && input.LA(1) <= '9')||(input.LA(1) >= 'A' && input.LA(1) <= 'Z')||input.LA(1)=='_'||(input.LA(1) >= 'a' && input.LA(1) <= 'z') ) {
input.consume();
}
else {
MismatchedSetException mse = new MismatchedSetException(null,input);
recover(mse);
throw mse;
}
}
break;
default :
break loop1;
}
}
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "ID"
// $ANTLR start "INT"
public final void mINT() throws RecognitionException {
try {
int _type = INT;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:148:5: ( ( '0' .. '9' )+ )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:148:7: ( '0' .. '9' )+
{
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:148:7: ( '0' .. '9' )+
int cnt2=0;
loop2:
while (true) {
int alt2=2;
int LA2_0 = input.LA(1);
if ( ((LA2_0 >= '0' && LA2_0 <= '9')) ) {
alt2=1;
}
switch (alt2) {
case 1 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:
{
if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) {
input.consume();
}
else {
MismatchedSetException mse = new MismatchedSetException(null,input);
recover(mse);
throw mse;
}
}
break;
default :
if ( cnt2 >= 1 ) break loop2;
EarlyExitException eee = new EarlyExitException(2, input);
throw eee;
}
cnt2++;
}
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "INT"
// $ANTLR start "WS"
public final void mWS() throws RecognitionException {
try {
int _type = WS;
int _channel = DEFAULT_TOKEN_CHANNEL;
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:151:5: ( ( ' ' | '\\t' | '\\r' | '\\n' )+ )
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:151:9: ( ' ' | '\\t' | '\\r' | '\\n' )+
{
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:151:9: ( ' ' | '\\t' | '\\r' | '\\n' )+
int cnt3=0;
loop3:
while (true) {
int alt3=2;
int LA3_0 = input.LA(1);
if ( ((LA3_0 >= '\t' && LA3_0 <= '\n')||LA3_0=='\r'||LA3_0==' ') ) {
alt3=1;
}
switch (alt3) {
case 1 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:
{
if ( (input.LA(1) >= '\t' && input.LA(1) <= '\n')||input.LA(1)=='\r'||input.LA(1)==' ' ) {
input.consume();
}
else {
MismatchedSetException mse = new MismatchedSetException(null,input);
recover(mse);
throw mse;
}
}
break;
default :
if ( cnt3 >= 1 ) break loop3;
EarlyExitException eee = new EarlyExitException(3, input);
throw eee;
}
cnt3++;
}
_channel=HIDDEN;
}
state.type = _type;
state.channel = _channel;
}
finally {
// do for sure before leaving
}
}
// $ANTLR end "WS"
@Override
public void mTokens() throws RecognitionException {
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:1:8: ( T__7 | T__8 | T__9 | T__10 | T__11 | T__12 | T__13 | T__14 | T__15 | T__16 | T__17 | T__18 | T__19 | ID | INT | WS )
int alt4=16;
switch ( input.LA(1) ) {
case '(':
{
alt4=1;
}
break;
case ')':
{
alt4=2;
}
break;
case '+':
{
alt4=3;
}
break;
case ',':
{
alt4=4;
}
break;
case ';':
{
alt4=5;
}
break;
case '<':
{
alt4=6;
}
break;
case '=':
{
int LA4_7 = input.LA(2);
if ( (LA4_7=='=') ) {
alt4=8;
}
else {
alt4=7;
}
}
break;
case 'c':
{
int LA4_8 = input.LA(2);
if ( (LA4_8=='h') ) {
int LA4_18 = input.LA(3);
if ( (LA4_18=='a') ) {
int LA4_21 = input.LA(4);
if ( (LA4_21=='r') ) {
int LA4_24 = input.LA(5);
if ( ((LA4_24 >= '0' && LA4_24 <= '9')||(LA4_24 >= 'A' && LA4_24 <= 'Z')||LA4_24=='_'||(LA4_24 >= 'a' && LA4_24 <= 'z')) ) {
alt4=14;
}
else {
alt4=9;
}
}
else {
alt4=14;
}
}
else {
alt4=14;
}
}
else {
alt4=14;
}
}
break;
case 'f':
{
int LA4_9 = input.LA(2);
if ( (LA4_9=='o') ) {
int LA4_19 = input.LA(3);
if ( (LA4_19=='r') ) {
int LA4_22 = input.LA(4);
if ( ((LA4_22 >= '0' && LA4_22 <= '9')||(LA4_22 >= 'A' && LA4_22 <= 'Z')||LA4_22=='_'||(LA4_22 >= 'a' && LA4_22 <= 'z')) ) {
alt4=14;
}
else {
alt4=10;
}
}
else {
alt4=14;
}
}
else {
alt4=14;
}
}
break;
case 'i':
{
int LA4_10 = input.LA(2);
if ( (LA4_10=='n') ) {
int LA4_20 = input.LA(3);
if ( (LA4_20=='t') ) {
int LA4_23 = input.LA(4);
if ( ((LA4_23 >= '0' && LA4_23 <= '9')||(LA4_23 >= 'A' && LA4_23 <= 'Z')||LA4_23=='_'||(LA4_23 >= 'a' && LA4_23 <= 'z')) ) {
alt4=14;
}
else {
alt4=11;
}
}
else {
alt4=14;
}
}
else {
alt4=14;
}
}
break;
case '{':
{
alt4=12;
}
break;
case '}':
{
alt4=13;
}
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
case '_':
case 'a':
case 'b':
case 'd':
case 'e':
case 'g':
case 'h':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
{
alt4=14;
}
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
alt4=15;
}
break;
case '\t':
case '\n':
case '\r':
case ' ':
{
alt4=16;
}
break;
default:
NoViableAltException nvae =
new NoViableAltException("", 4, 0, input);
throw nvae;
}
switch (alt4) {
case 1 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:1:10: T__7
{
mT__7();
}
break;
case 2 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:1:15: T__8
{
mT__8();
}
break;
case 3 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:1:20: T__9
{
mT__9();
}
break;
case 4 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:1:25: T__10
{
mT__10();
}
break;
case 5 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:1:31: T__11
{
mT__11();
}
break;
case 6 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:1:37: T__12
{
mT__12();
}
break;
case 7 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:1:43: T__13
{
mT__13();
}
break;
case 8 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:1:49: T__14
{
mT__14();
}
break;
case 9 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:1:55: T__15
{
mT__15();
}
break;
case 10 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:1:61: T__16
{
mT__16();
}
break;
case 11 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:1:67: T__17
{
mT__17();
}
break;
case 12 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:1:73: T__18
{
mT__18();
}
break;
case 13 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:1:79: T__19
{
mT__19();
}
break;
case 14 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:1:85: ID
{
mID();
}
break;
case 15 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:1:88: INT
{
mINT();
}
break;
case 16 :
// E:\\WorkingArea\\ethereumJ\\src\\main\\java\\samples\\stg\\CMinus.g:1:92: WS
{
mWS();
}
break;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,17 @@
package samples.stg;
/**
* www.ethereumJ.com
* User: Roman Mandeleil
* Created on: 25/04/14 17:06
*/
public class GenParser {
public static void main(String args[]){
String userDir = System.getProperty("user.dir");
org.antlr.Tool.main(new String[]{userDir + "\\src\\main\\java\\samples\\stg\\CMinus.g"});
}
}

View File

@ -0,0 +1,55 @@
group Java;
program(globals,functions) ::= <<
class Wrapper {
<globals; separator="\n">
<functions; separator="\n">
}
>>
variable(type,name) ::= "<type> <name>;"
globalVariable ::= variable
function(type,name,args,locals,stats) ::= <<
<type> <name>(<args; separator=", ">) {
<locals; separator="\n">
<stats; separator="\n">
}
>>
type_int() ::= "int"
type_char() ::= "char"
type_user_object(name) ::= "<name>"
parameter(type,name) ::= "<type> <name>"
statement(expr) ::= "<expr>;"
statementList(locals,stats) ::= <<
{
<locals; separator="\n">
<stats; separator="\n">
}<\n>
>>
forLoop(e1,e2,e3,locals,stats) ::= <<
for (<e1> <e2>; <e3>) {
<locals; separator="\n">
<stats; separator="\n">
}
>>
assign(lhs,rhs) ::= "<lhs> = <rhs>;"
equals(left,right) ::= "<left> == <right>"
lessThan(left,right) ::= "<left> \< <right>"
add(left,right) ::= "<left> + <right>"
refVar(id) ::= "<id>"
iconst(value) ::= "<value>"

View File

@ -0,0 +1,30 @@
package samples.stg;
import java.io.*;
import org.antlr.runtime.*;
import org.antlr.stringtemplate.*;
import org.antlr.stringtemplate.language.*;
public class Main {
public static StringTemplateGroup templates;
public static void main(String[] args) throws Exception {
String templateFileName;
String userDir = System.getProperty("user.dir");
templateFileName = userDir + "\\src\\main\\java\\samples\\stg\\Bytecode.stg";
templates = new StringTemplateGroup(new FileReader(templateFileName),
AngleBracketTemplateLexer.class);
String srcFile = userDir + "\\src\\main\\java\\samples\\stg\\input";
CharStream input = new ANTLRFileStream(srcFile);
CMinusLexer lexer = new CMinusLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
CMinusParser parser = new CMinusParser(tokens);
parser.setTemplateLib(templates);
RuleReturnScope r = parser.program();
System.out.println(r.getTemplate().toString());
}
}

View File

@ -0,0 +1,48 @@
group Python;
program(globals,functions) ::= <<
<functions; separator="\n">
>>
variable(type,name) ::= " "
globalVariable ::= variable
function(type,name,args,locals,stats) ::= <<
def <name>(<args; separator=", ">):
<stats>
>>
type_int() ::= "int"
type_char() ::= "char"
type_user_object(name) ::= "<name>"
parameter(type,name) ::= "<name>"
statement(expr) ::= "<expr>"
statementList(locals,stats) ::= <<
<stats; separator="\n">
>>
// python has a weird FOR, use a WHILE. :)
forLoop(e1,e2,e3,locals,stats) ::= <<
<e1>
while ( <e2> ):
<stats; separator="\n">
<e3>
>>
assign(lhs,rhs) ::= "<lhs> = <rhs>"
equals(left,right) ::= "<left> == <right>"
lessThan(left,right) ::= "<left> \< <right>"
add(left,right) ::= "<left> + <right>"
refVar(id) ::= "<id>"
iconst(value) ::= "<value>"

View File

@ -0,0 +1,7 @@
Java.stg
Bytecode.stg
Python.stg
Main.java
CMinus.g
input
output

View File

@ -0,0 +1,9 @@
char c;
int x;
int foo(int y, char d) {
int i;
for (i=0; i<3; i=i+1) {
x=3;
y=5;
}
}

View File

@ -0,0 +1,11 @@
class Wrapper {
char c;
int x;
int foo(int y, char d) {
int i;
for (i = 0; i < 3; i = i + 1;) {
x = 3;
y = 5;
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 959 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Some files were not shown because too many files have changed in this diff Show More