[
  {
    "path": ".gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n/out\n.externalNativeBuild\n/keystore\n*/.DS_Store"
  },
  {
    "path": ".idea/.name",
    "content": "BitcoinDemo"
  },
  {
    "path": ".idea/compiler.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"CompilerConfiguration\">\n    <bytecodeTargetLevel>\n      <module name=\"BitcoinDemo_main\" target=\"1.8\" />\n      <module name=\"BitcoinDemo_test\" target=\"1.8\" />\n    </bytecodeTargetLevel>\n  </component>\n</project>"
  },
  {
    "path": ".idea/gradle.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"GradleSettings\">\n    <option name=\"linkedExternalProjectsSettings\">\n      <GradleProjectSettings>\n        <option name=\"distributionType\" value=\"DEFAULT_WRAPPED\" />\n        <option name=\"externalProjectPath\" value=\"$PROJECT_DIR$\" />\n        <option name=\"gradleJvm\" value=\"1.8\" />\n        <option name=\"modules\">\n          <set>\n            <option value=\"$PROJECT_DIR$\" />\n          </set>\n        </option>\n        <option name=\"useAutoImport\" value=\"true\" />\n      </GradleProjectSettings>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/misc.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectRootManager\" version=\"2\" languageLevel=\"JDK_1_8\" project-jdk-name=\"1.8\" project-jdk-type=\"JavaSDK\">\n    <output url=\"file://$PROJECT_DIR$/out\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/modules.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectModuleManager\">\n    <modules>\n      <module fileurl=\"file://$PROJECT_DIR$/.idea/modules/BitcoinDemo.iml\" filepath=\"$PROJECT_DIR$/.idea/modules/BitcoinDemo.iml\" />\n      <module fileurl=\"file://$PROJECT_DIR$/.idea/modules/BitcoinDemo_main.iml\" filepath=\"$PROJECT_DIR$/.idea/modules/BitcoinDemo_main.iml\" group=\"BitcoinDemo\" />\n      <module fileurl=\"file://$PROJECT_DIR$/.idea/modules/BitcoinDemo_test.iml\" filepath=\"$PROJECT_DIR$/.idea/modules/BitcoinDemo_test.iml\" group=\"BitcoinDemo\" />\n    </modules>\n  </component>\n</project>"
  },
  {
    "path": ".idea/uiDesigner.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"Palette2\">\n    <group name=\"Swing\">\n      <item class=\"com.intellij.uiDesigner.HSpacer\" tooltip-text=\"Horizontal Spacer\" icon=\"/com/intellij/uiDesigner/icons/hspacer.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"1\" hsize-policy=\"6\" anchor=\"0\" fill=\"1\" />\n      </item>\n      <item class=\"com.intellij.uiDesigner.VSpacer\" tooltip-text=\"Vertical Spacer\" icon=\"/com/intellij/uiDesigner/icons/vspacer.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"1\" anchor=\"0\" fill=\"2\" />\n      </item>\n      <item class=\"javax.swing.JPanel\" icon=\"/com/intellij/uiDesigner/icons/panel.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"3\" hsize-policy=\"3\" anchor=\"0\" fill=\"3\" />\n      </item>\n      <item class=\"javax.swing.JScrollPane\" icon=\"/com/intellij/uiDesigner/icons/scrollPane.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"7\" hsize-policy=\"7\" anchor=\"0\" fill=\"3\" />\n      </item>\n      <item class=\"javax.swing.JButton\" icon=\"/com/intellij/uiDesigner/icons/button.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"0\" fill=\"1\" />\n        <initial-values>\n          <property name=\"text\" value=\"Button\" />\n        </initial-values>\n      </item>\n      <item class=\"javax.swing.JRadioButton\" icon=\"/com/intellij/uiDesigner/icons/radioButton.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" />\n        <initial-values>\n          <property name=\"text\" value=\"RadioButton\" />\n        </initial-values>\n      </item>\n      <item class=\"javax.swing.JCheckBox\" icon=\"/com/intellij/uiDesigner/icons/checkBox.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" />\n        <initial-values>\n          <property name=\"text\" value=\"CheckBox\" />\n        </initial-values>\n      </item>\n      <item class=\"javax.swing.JLabel\" icon=\"/com/intellij/uiDesigner/icons/label.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" />\n        <initial-values>\n          <property name=\"text\" value=\"Label\" />\n        </initial-values>\n      </item>\n      <item class=\"javax.swing.JTextField\" icon=\"/com/intellij/uiDesigner/icons/textField.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\">\n          <preferred-size width=\"150\" height=\"-1\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JPasswordField\" icon=\"/com/intellij/uiDesigner/icons/passwordField.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\">\n          <preferred-size width=\"150\" height=\"-1\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JFormattedTextField\" icon=\"/com/intellij/uiDesigner/icons/formattedTextField.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\">\n          <preferred-size width=\"150\" height=\"-1\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JTextArea\" icon=\"/com/intellij/uiDesigner/icons/textArea.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"6\" anchor=\"0\" fill=\"3\">\n          <preferred-size width=\"150\" height=\"50\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JTextPane\" icon=\"/com/intellij/uiDesigner/icons/textPane.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"6\" anchor=\"0\" fill=\"3\">\n          <preferred-size width=\"150\" height=\"50\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JEditorPane\" icon=\"/com/intellij/uiDesigner/icons/editorPane.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"6\" anchor=\"0\" fill=\"3\">\n          <preferred-size width=\"150\" height=\"50\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JComboBox\" icon=\"/com/intellij/uiDesigner/icons/comboBox.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"2\" anchor=\"8\" fill=\"1\" />\n      </item>\n      <item class=\"javax.swing.JTable\" icon=\"/com/intellij/uiDesigner/icons/table.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"6\" anchor=\"0\" fill=\"3\">\n          <preferred-size width=\"150\" height=\"50\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JList\" icon=\"/com/intellij/uiDesigner/icons/list.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"2\" anchor=\"0\" fill=\"3\">\n          <preferred-size width=\"150\" height=\"50\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JTree\" icon=\"/com/intellij/uiDesigner/icons/tree.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"6\" anchor=\"0\" fill=\"3\">\n          <preferred-size width=\"150\" height=\"50\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JTabbedPane\" icon=\"/com/intellij/uiDesigner/icons/tabbedPane.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"3\" hsize-policy=\"3\" anchor=\"0\" fill=\"3\">\n          <preferred-size width=\"200\" height=\"200\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JSplitPane\" icon=\"/com/intellij/uiDesigner/icons/splitPane.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"3\" hsize-policy=\"3\" anchor=\"0\" fill=\"3\">\n          <preferred-size width=\"200\" height=\"200\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JSpinner\" icon=\"/com/intellij/uiDesigner/icons/spinner.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"true\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" />\n      </item>\n      <item class=\"javax.swing.JSlider\" icon=\"/com/intellij/uiDesigner/icons/slider.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" />\n      </item>\n      <item class=\"javax.swing.JSeparator\" icon=\"/com/intellij/uiDesigner/icons/separator.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"6\" anchor=\"0\" fill=\"3\" />\n      </item>\n      <item class=\"javax.swing.JProgressBar\" icon=\"/com/intellij/uiDesigner/icons/progressbar.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"0\" fill=\"1\" />\n      </item>\n      <item class=\"javax.swing.JToolBar\" icon=\"/com/intellij/uiDesigner/icons/toolbar.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"0\" fill=\"1\">\n          <preferred-size width=\"-1\" height=\"20\" />\n        </default-constraints>\n      </item>\n      <item class=\"javax.swing.JToolBar$Separator\" icon=\"/com/intellij/uiDesigner/icons/toolbarSeparator.png\" removable=\"false\" auto-create-binding=\"false\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"0\" fill=\"1\" />\n      </item>\n      <item class=\"javax.swing.JScrollBar\" icon=\"/com/intellij/uiDesigner/icons/scrollbar.png\" removable=\"false\" auto-create-binding=\"true\" can-attach-label=\"false\">\n        <default-constraints vsize-policy=\"6\" hsize-policy=\"0\" anchor=\"0\" fill=\"2\" />\n      </item>\n    </group>\n  </component>\n</project>"
  },
  {
    "path": ".idea/vcs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping directory=\"$PROJECT_DIR$\" vcs=\"Git\" />\n  </component>\n</project>"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 Weitong Jiao\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Ethereum Wallet\n\nGenerating ETH key pairs and address from mnemonic.\n\n\n----------\n\n\n### 1. From entropy to mnemonic\n\n#### 1. Generating 128 digits random entropy\n```java\nUUID uuid = UUID.randomUUID();\nString[] digits = uuid.toString().split(\"\\\\-\");\nStringBuilder randomDigits = new StringBuilder();\nfor (String digit : digits) {\n    randomDigits.append(digit);\n}\n```\n\n#### 2. Doing SHA256 to entropy for checksum, append first 4 bits to the end of entropy\n```java\n//generate sha-256 from entropy\nString encodeStr = \"\";\nbyte[] hash = Sha256.sha256(hexStringToByteArray(entropy));\nencodeStr = String.valueOf(Hex.encodeHex(hash));\nSystem.out.println(encodeStr);\nchar firstSHA = encodeStr.charAt(0);\nString new_entropy = entropy + firstSHA;\nString bin_entropy = \"\";\nfor (int i = 0; i < new_entropy.length(); i++) {\n    bin_entropy += dict[Integer.parseInt(new_entropy.substring(i, i + 1), 16)];\n}\n```\n#### 3. Segment 132 bits entropy into 11 bits long parts\n```java\nString[] segments = new String[12];\nfor (int i = 0; i <= 11; i++) {\n    segments[i] = bin_entropy.substring(i * 11, (i + 1) * 11);\n}\n```\n#### 4. Generating mnemonic from dictionary\n```java\nmnemonic += wordlist[Integer.valueOf(segments[0], 2)];\nfor (int j = 1; j < segments.length; j++) {\n    mnemonic += \" \" + (wordlist[Integer.valueOf(segments[j], 2)]);\n}\n```\n![enter image description here](https://upload-images.jianshu.io/upload_images/10931084-93b10c15c7277420.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)\n\n\n----------\n\n\n### 2. From mnemonic to seed\n\nUsing PBKDF2 function to get 512 bits seed from mnemonic.\nIn this part we need a salt string to generate the seed we needed. Normally the value of salt is \"mnemonic\" for universality\n\n```java\nString seed;\nString salt = \"mnemonic\";\nseed = getSeed(mnemonic, salt);\n```\n![enter image description here](https://upload-images.jianshu.io/upload_images/10931084-eb8d30c6fc836a5b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)\n\n\n----------\n\n\n###3. From seed to master private key\n\nDivide 512 bits seed into two equal parts, the first 256 bits is master private key and the last 256 bits is chain code. We could use BIP32 library to do the jobs by APIs this library provided.\n\n```java\nExtendedPrivateKey rootKey = ExtendedPrivateKey.fromSeed(hexStringToByteArray(seed), Bitcoin.MAIN_NET);\n```\n![enter image description here](https://upload-images.jianshu.io/upload_images/10931084-177ace609e88a5a3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)\n\n----------\n###4. From master private key to child private key\nFirstly, generate address index to get 0th private key generated from master private key and chain code.\n```java\nAddressIndex ethAddressIndex = BIP44.m().purpose44().coinType(60).account(0).external().address(0);\n```\n44.60.0.0.0 is eth address index.\n\nAnd then get key pair and address that we need.\n```java\nExtendedPrivateKey childPrivateKey = rootKey.derive(ethAddressIndex, AddressIndex.DERIVATION);\nbyte[] privateKeyBytes = childPrivateKey.getKey(); \nECKeyPair keyPair = ECKeyPair.create(privateKeyBytes);\nList<String> returnList = EthAddress(childPrivateKey, keyPair);\n```\n\n![enter image description here](https://upload-images.jianshu.io/upload_images/10931084-dfd91a5ee94953e7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)\n"
  },
  {
    "path": "build.gradle",
    "content": "group 'com.terry'\nversion '1.0-SNAPSHOT'\n\napply plugin: 'java'\n\nsourceCompatibility = 1.8\n\nrepositories {\n    jcenter()\n}\n\ndependencies {\n    testCompile group: 'junit', name: 'junit', version: '4.12'\n    compile 'io.github.novacrypto:BIP39:0.1.9'\n    compile group: 'commons-codec', name: 'commons-codec', version: '1.10'\n    compile 'io.github.novacrypto:BIP44:0.0.3'\n    compile 'com.lhalcyon:bip32:1.0.0'\n    compile ('org.web3j:core:3.5.0')\n    compile group: 'org.bitcoinj', name: 'bitcoinj-core', version: '0.14.6'\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Sun Jul 29 20:02:31 CST 2018\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-3.5-rc-2-all.zip\n"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave ( ) {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=$(save \"$@\")\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\n# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong\nif [ \"$(uname)\" = \"Darwin\" ] && [ \"$HOME\" = \"$PWD\" ]; then\n  cd \"$(dirname \"$0\")\"\nfi\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:init\r\n@rem Get command-line arguments, handling Windows variants\r\n\r\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\r\n\r\n:win9xME_args\r\n@rem Slurp the command line arguments.\r\nset CMD_LINE_ARGS=\r\nset _SKIP=2\r\n\r\n:win9xME_args_slurp\r\nif \"x%~1\" == \"x\" goto execute\r\n\r\nset CMD_LINE_ARGS=%*\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "settings.gradle",
    "content": "rootProject.name = 'BitcoinDemo'\n\n"
  },
  {
    "path": "src/main/java/GenerateKeyStore.java",
    "content": "\nimport java.io.FileInputStream;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.OutputStream;\nimport java.security.*;\nimport java.security.KeyStore.ProtectionParameter;\nimport java.security.cert.CertificateException;\nimport javax.crypto.spec.SecretKeySpec;\n\n\npublic class GenerateKeyStore {\n\n    private String fileName = \"\";\n\n    private void execCommand(String[] arstringCommand) {\n        for (int i = 0; i < arstringCommand.length; i++) {\n            System.out.print(arstringCommand[i] + \" \");\n        }\n        try {\n            Runtime.getRuntime().exec(arstringCommand);\n\n        } catch (Exception e) {\n            System.out.println(e.getMessage());\n        }\n    }\n\n    public void execCommand(String arstringCommand) {\n        try {\n            Runtime.getRuntime().exec(arstringCommand);\n\n        } catch (Exception e) {\n            System.out.println(e.getMessage());\n        }\n    }\n\n    /**\n     * 生成密钥\n     */\n    public void genKeyByPrivateKey(String address, String password) {\n        fileName = \"/Users/terry/Documents/GitHub/BitcoinWallet/keystore/\" + address + \"_PrivateKey\" + \".keystore\";\n        String[] arstringCommand = new String[]{\n\n                \"keytool\",\n                \"-genkey\", // -genkey表示生成密钥\n                \"-validity\", // -validity指定证书有效期(单位：天)，这里是36000天\n                \"36500\",\n                \"-keysize\",//     指定密钥长度\n                \"1024\",\n                \"-alias\", // -alias指定别名，这里是ss\n                \"Mnemonic\",\n                \"-keyalg\", // -keyalg 指定密钥的算法 (如 RSA DSA（如果不指定默认采用DSA）)\n                \"RSA\",\n                \"-keystore\", // -keystore指定存储位置，这里是/Users/terry/Documents/GitHub/my/BitcoinDemo/keystore/demo.keystore\n                fileName,\n                \"-dname\",// CN=(名字与姓氏), OU=(组织单位名称), O=(组织名称), L=(城市或区域名称),\n                // ST=(州或省份名称), C=(单位的两字母国家代码)\"\n                \"CN=(user), OU=(imbuff), O=(imbuff), L=(SH), ST=(SH), C=(CN)\",\n                \"-storepass\", // 指定密钥库的密码(获取keystore信息所需的密码)\n                password,\n                \"-keypass\",// 指定别名条目的密码(私钥的密码)\n                password,\n                \"-v\"// -v 显示密钥库中的证书详细信息\n        };\n        execCommand(arstringCommand);\n    }\n\n    /**\n     *\n     */\n    public void genKeyByMnemonic(String address, String password) {\n        fileName = \"/Users/terry/Documents/GitHub/BitcoinWallet/keystore/\" + address + \"_Mnemonic\" + \".keystore\";\n        String[] arstringCommand = new String[]{\n\n                \"keytool\",\n                \"-genkey\", // -genkey表示生成密钥\n                \"-validity\", // -validity指定证书有效期(单位：天)，这里是36000天\n                \"36500\",\n                \"-keysize\",//     指定密钥长度\n                \"1024\",\n                \"-alias\", // -alias指定别名，这里是ss\n                \"Mnemonic\",\n                \"-keyalg\", // -keyalg 指定密钥的算法 (如 RSA DSA（如果不指定默认采用DSA）)\n                \"RSA\",\n                \"-keystore\", // -keystore指定存储位置，这里是/Users/terry/Documents/GitHub/my/BitcoinDemo/keystore/demo.keystore\n                fileName,\n                \"-dname\",// CN=(名字与姓氏), OU=(组织单位名称), O=(组织名称), L=(城市或区域名称),\n                // ST=(州或省份名称), C=(单位的两字母国家代码)\"\n                \"CN=(user), OU=(imbuff), O=(imbuff), L=(SH), ST=(SH), C=(CN)\",\n                \"-storepass\", // 指定密钥库的密码(获取keystore信息所需的密码)\n                password,\n                \"-keypass\",// 指定别名条目的密码(私钥的密码)\n                password,\n                \"-v\"// -v 显示密钥库中的证书详细信息\n        };\n        execCommand(arstringCommand);\n    }\n\n    public void protectContent(String privateKey, String password) {\n        FileInputStream fis = null;\n        OutputStream os = null;\n        try {\n            // 读取keystore文件转换为keystore密钥库对象\n            fis = new FileInputStream(fileName);\n            // 生成证书的类型为jceks\n            KeyStore keyStore = KeyStore.getInstance(\"jceks\");\n            // 该密钥库的密码,storepass指定密钥库的密码(获取keystore信息所需的密码)\n            String storepass = password;\n            keyStore.load(fis, storepass.toCharArray());\n            fis.close();\n            // 一旦加载了 keystore，就能够从 keystore 读取现有条目，或向 keystore 写入新条目：\n            String alias = \"Mnemonic\";// 别名\n            String keypass = password; // 别名密码 ,keypass 指定别名条目的密码(私钥的密码)\n            ProtectionParameter param = new KeyStore.PasswordProtection(keypass.toCharArray());\n            KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, param);\n            PrivateKey myPrivateKey = pkEntry.getPrivateKey();\n            System.out.println(\"获取的私钥是：\" + myPrivateKey.toString());\n            // 根据给定的字节数组构造一个密钥\n            String desPwd = privateKey;// 用户要求保存于keystore文件中的密码\n            javax.crypto.SecretKey mySecretKey = new SecretKeySpec(desPwd.getBytes(), \"JKS\");\n            KeyStore.SecretKeyEntry skEntry = new KeyStore.SecretKeyEntry(mySecretKey);\n            keyStore.setEntry(alias, skEntry, new KeyStore.PasswordProtection(\"decryp pwd\".toCharArray()));\n            //将此 keystore 存储到给定输出流，并用给定密码保护其完整性。\n            os = new FileOutputStream(fileName);\n            keyStore.store(os, storepass.toCharArray());\n            os.close();\n        } catch (KeyStoreException | NoSuchAlgorithmException | IOException | CertificateException | UnrecoverableEntryException e) {\n            e.printStackTrace();\n        } finally {\n            try {\n                if (os != null)\n                    os.close();\n                if (fis != null)\n                    fis.close();\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n        }\n    }\n\n    public void getContent(String password) {\n        String storepass = password;\n        try {\n            FileInputStream fis = null;\n            // 读取keystore文件转换为keystore密钥库对象\n            fis = new FileInputStream(fileName);\n            // 因为生成证书的类型为JKS 也有其他的格式\n            KeyStore keyStore = KeyStore.getInstance(\"jceks\");\n            // 该密钥库的密码\"888999\",storepass指定密钥库的密码(获取keystore信息所需的密码)\n            keyStore.load(fis, storepass.toCharArray());\n            fis.close();\n            // 根据别名（alias=desPws）从证书（keyStore）获取密码并解密\n            //keyStore.getKey返回与给定别名关联的密钥，并用给定密码来恢复它。\n            Key key = keyStore.getKey(\"Mnemonic\", \"decryp pwd\".toCharArray());\n            //key.getEncoded()返回基本编码格式的密钥，如果此密钥不支持编码，则返回 null。\n            byte[] bt = key.getEncoded();\n            StringBuilder privateKey = new StringBuilder();\n            System.out.println(\"从证书中获取的内容是：\");\n            for (int i = 0; i < bt.length; i++) {\n                char ch = (char) bt[i];\n                privateKey.append(ch);\n                System.out.print(ch);\n            }\n\n        } catch (UnrecoverableKeyException | KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {\n            e.printStackTrace();\n            System.out.println(\"wrong password !\");\n        }\n    }\n\n\n}\n\n"
  },
  {
    "path": "src/main/java/Main.java",
    "content": "\n\nimport io.github.novacrypto.base58.Base58;\nimport io.github.novacrypto.hashing.Sha256;\nimport io.github.novacrypto.toruntime.CheckedExceptionToRuntime;\nimport org.apache.commons.codec.binary.*;\n\nimport javax.crypto.SecretKeyFactory;\nimport javax.crypto.spec.PBEKeySpec;\nimport java.io.*;\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\nimport java.security.spec.InvalidKeySpecException;\nimport java.security.spec.KeySpec;\nimport java.text.Normalizer;\nimport java.util.*;\n\nimport io.github.novacrypto.bip32.ExtendedPrivateKey;\nimport io.github.novacrypto.bip32.networks.Bitcoin;\nimport io.github.novacrypto.bip44.AddressIndex;\nimport io.github.novacrypto.bip44.BIP44;\nimport org.bitcoinj.core.Sha256Hash;\nimport org.bitcoinj.core.Utils;\nimport org.bouncycastle.crypto.digests.RIPEMD160Digest;\nimport org.web3j.crypto.*;\n\nimport static io.github.novacrypto.toruntime.CheckedExceptionToRuntime.toRuntime;\n\n\npublic class Main {\n\n    private static final String[] dict =\n            {\"0000\", \"0001\", \"0010\", \"0011\", \"0100\", \"0101\", \"0110\", \"0111\", \"1000\",\n                    \"1001\", \"1010\", \"1011\", \"1100\", \"1101\", \"1110\", \"1111\"};\n\n    private static String[] wordlist = new String[2048];\n    private static GenerateKeyStore ks = new GenerateKeyStore();\n    private static String password = \"password\";\n    private static WalletFile walletFile;\n\n    public static void main(String[] args) throws Exception {\n        String entropy = createEntropy();\n        String mnemonic = generateMnemonic(entropy);\n        System.out.println(mnemonic);\n        List<String> params = generateKeyPairs(mnemonic);\n        //genKeyStoreByPrivateKey(params.get(0), params.get(2), password);\n        try {\n            Thread.sleep(1000); //1000 ms\n        } catch (InterruptedException ex) {\n            Thread.currentThread().interrupt();\n        }\n        //genKeyStoreByMnemonic(mnemonic, params.get(2), password);\n        new SendTransaction().getBalance(\"0x915489e6a7caf14afc874d678879f18fd0e3a684\");\n        new SendTransaction().getBalance(\"0x26857844be5fea27bd48aedced42bb8727501779\");\n        BigDecimal amount = BigDecimal.valueOf(0.01);\n        sendTransaction(\"0x\" + params.get(2), \"0x26857844be5fea27bd48aedced42bb8727501779\", amount, password, walletFile);\n        new SendTransaction().getBalance(\"0x915489e6a7caf14afc874d678879f18fd0e3a684\");\n        new SendTransaction().getBalance(\"0x26857844be5fea27bd48aedced42bb8727501779\");\n    }\n\n    public static String createEntropy() {\n        UUID uuid = UUID.randomUUID();\n        String[] digits = uuid.toString().split(\"\\\\-\");\n        StringBuilder randomDigits = new StringBuilder();\n        for (String digit : digits) {\n            randomDigits.append(digit);\n        }\n        return randomDigits.toString();\n    }\n\n    public static String generateMnemonic(String entropy) {\n        System.out.println(entropy);\n\n        //generate sha-256 from entropy\n        String encodeStr = \"\";\n        byte[] hash = Sha256.sha256(hexStringToByteArray(entropy));\n        encodeStr = String.valueOf(Hex.encodeHex(hash));\n        System.out.println(encodeStr);\n        char firstSHA = encodeStr.charAt(0);\n        String new_entropy = entropy + firstSHA;\n        String bin_entropy = \"\";\n        for (int i = 0; i < new_entropy.length(); i++) {\n            bin_entropy += dict[Integer.parseInt(new_entropy.substring(i, i + 1), 16)];\n        }\n        String[] segments = new String[12];\n        //hardcode\n        for (int i = 0; i <= 11; i++) {\n            segments[i] = bin_entropy.substring(i * 11, (i + 1) * 11);\n        }\n\n        //请修改文件的绝对路径\n        String path = \"/Users/terry/Documents/GitHub/my/BitcoinDemo/src/main/java/english\";\n        readTextFile(path);\n        String mnemonic = \"\";\n\n        //generate mnemonic\n        mnemonic += wordlist[Integer.valueOf(segments[0], 2)];\n        for (int j = 1; j < segments.length; j++) {\n            mnemonic += \" \" + (wordlist[Integer.valueOf(segments[j], 2)]);\n        }\n        return mnemonic;\n    }\n\n\n    public static void readTextFile(String filePath) {\n        try {\n            String encoding = \"utf-8\";\n            File file = new File(filePath);\n            if (file.isFile() && file.exists()) { //判断文件是否存在\n                InputStreamReader read = new InputStreamReader(\n                        new FileInputStream(file), encoding);//考虑到编码格式\n                BufferedReader bufferedReader = new BufferedReader(read);\n                String lineTxt = null;\n                int index = 0;\n                while ((lineTxt = bufferedReader.readLine()) != null) {\n                    wordlist[index++] = lineTxt;\n                }\n                read.close();\n            } else {\n                System.out.println(\"找不到指定的文件\");\n            }\n        } catch (Exception e) {\n            System.out.println(\"读取文件内容出错\");\n            e.printStackTrace();\n        }\n    }\n\n    private static List<String> generateKeyPairs(String mnemonic) throws InvalidKeySpecException, NoSuchAlgorithmException, CipherException {\n\n        // 1. we just need eth wallet for now\n        AddressIndex ethAddressIndex = BIP44.m().purpose44().coinType(60).account(0).external().address(0);\n        AddressIndex btcAddressIndex = BIP44.m().purpose44().coinType(0).account(0).external().address(0);\n        // 2. calculate seed from mnemonics , then get master/root key ; Note that the bip39 passphrase we set \"\" for common\n        String seed;\n        String salt = \"mnemonic\";\n        seed = getSeed(mnemonic, salt);\n        System.out.println(seed);\n\n\n        ExtendedPrivateKey rootKey = ExtendedPrivateKey.fromSeed(hexStringToByteArray(seed), Bitcoin.MAIN_NET);\n        // 3. get child private key deriving from master/root key\n        ExtendedPrivateKey childPrivateKey = rootKey.derive(ethAddressIndex, AddressIndex.DERIVATION);\n\n        // 4. get key pair\n        byte[] privateKeyBytes = childPrivateKey.getKey(); //child private key\n        ECKeyPair keyPair = ECKeyPair.create(privateKeyBytes);\n        walletFile = Wallet.createLight(password, keyPair);\n        List<String> returnList = EthAddress(childPrivateKey, keyPair);\n\n        childPrivateKey = rootKey.derive(btcAddressIndex, AddressIndex.DERIVATION);\n        bitcoinAddress(childPrivateKey);\n\n        return returnList;\n\n    }\n\n\n    /**\n     * generate ETH privatekey, publickey and address.\n     *\n     * @param childPrivateKey\n     * @param keyPair\n     */\n    private static List<String> EthAddress(ExtendedPrivateKey childPrivateKey, ECKeyPair keyPair) {\n        String privateKey = childPrivateKey.getPrivateKey();\n        String publicKey = childPrivateKey.neuter().getPublicKey();\n        String address = Keys.getAddress(keyPair);\n\n        System.out.println(\"ETH privateKey:\" + privateKey);\n        System.out.println(\"ETH publicKey:\" + publicKey);\n        System.out.println(\"ETH address:\" + address);\n\n        List<String> returnList = new ArrayList<>();\n        returnList.add(privateKey);\n        returnList.add(publicKey);\n        returnList.add(address);\n        return returnList;\n    }\n\n    /**\n     * generate bitcoin privatekey, publickey and address.\n     *\n     * @param childPrivateKey\n     */\n    private static void bitcoinAddress(ExtendedPrivateKey childPrivateKey) {\n        // 获取比特币私钥\n        String privateKey = childPrivateKey.getPrivateKey();\n        // 加80前缀和01后缀\n        String rk = \"80\" + privateKey + \"01\";\n        // 生成校验和\n        byte[] checksum = Sha256.sha256(hexStringToByteArray(rk));\n        checksum = Sha256.sha256(checksum);\n        // 取校验和前4位（32bits）\n        String end = String.valueOf(Hex.encodeHex(checksum)).substring(0, 8);\n        rk = rk + end;\n        // 进行base58编码\n        String privateK = Base58.base58Encode(hexStringToByteArray(rk));\n\n\n        // 获取比特币公钥\n        String publicKey = childPrivateKey.neuter().getPublicKey();\n        // 对公钥进行一次sha256\n        byte[] pk256 = hexStringToByteArray(publicKey);\n        pk256 = Sha256.sha256(pk256);\n        // 进行ripe160加密（20位）\n        RIPEMD160Digest digest = new RIPEMD160Digest();\n        digest.update(pk256, 0, pk256.length);\n        byte[] ripemd160Bytes = new byte[digest.getDigestSize()];\n        digest.doFinal(ripemd160Bytes, 0);\n        // 加00前缀（比特币主网）变成21位\n        byte[] extendedRipemd160Bytes = hexStringToByteArray(\"00\" + String.valueOf(Hex.encodeHex(ripemd160Bytes)));\n        // 计算校验和\n        checksum = Sha256.sha256(extendedRipemd160Bytes);\n        checksum = Sha256.sha256(checksum);\n        // 加校验和前4位，变成25位\n        String pk = String.valueOf(Hex.encodeHex(extendedRipemd160Bytes)) + String.valueOf(Hex.encodeHex(checksum)).substring(0, 8);\n        // base58加密\n        String address = Base58.base58Encode(hexStringToByteArray(pk));\n\n        System.out.println(\"bitcoin privateKey:\" + privateK);\n        System.out.println(\"bitcoin publicKey:\" + publicKey);\n        System.out.println(\"bitcoin address:\" + address);\n\n        generateSegwitAddress(address);\n    }\n\n    public static String getSeed(String mnemonic, String salt) throws NoSuchAlgorithmException,\n            InvalidKeySpecException {\n\n        char[] chars = Normalizer.normalize(mnemonic, Normalizer.Form.NFKD).toCharArray();\n        byte[] salt_ = getUtf8Bytes(salt);\n        KeySpec spec = new PBEKeySpec(chars, salt_, 2048, 512);\n        SecretKeyFactory f = SecretKeyFactory.getInstance(\"PBKDF2WithHmacSHA512\");\n        return String.valueOf(Hex.encodeHex(f.generateSecret(spec).getEncoded()));\n    }\n\n    private static void generateSegwitAddress(String address) {\n        byte[] decoded = Utils.parseAsHexOrBase58(address);\n        // We should throw off header byte that is 0 for Bitcoin (Main)\n        byte[] pureBytes = new byte[20];\n        System.arraycopy(decoded, 1, pureBytes, 0, 20);\n        // Than we should prepend the following bytes:\n        byte[] scriptSig = new byte[pureBytes.length + 2];\n        scriptSig[0] = 0x00;\n        scriptSig[1] = 0x14;\n        System.arraycopy(pureBytes, 0, scriptSig, 2, pureBytes.length);\n        byte[] addressBytes = org.bitcoinj.core.Utils.sha256hash160(scriptSig);\n        // Here are the address bytes\n        byte[] readyForAddress = new byte[addressBytes.length + 1 + 4];\n        // prepending p2sh header:\n        readyForAddress[0] = (byte) 5;\n        System.arraycopy(addressBytes, 0, readyForAddress, 1, addressBytes.length);\n        // But we should also append check sum:\n        byte[] checkSum = Sha256Hash.hashTwice(readyForAddress, 0, addressBytes.length + 1);\n        System.arraycopy(checkSum, 0, readyForAddress, addressBytes.length + 1, 4);\n        // To get the final address:\n        String segwitAddress = Base58.base58Encode(readyForAddress);\n        System.out.println(\"segwit address:\" + segwitAddress);\n    }\n\n    /*private static byte[] fromHex(String hex) {\n        byte[] binary = new byte[hex.length() / 2];\n        for (int i = 0; i < binary.length; i++) {\n            binary[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);\n        }\n        return binary;\n\n    }*/\n\n    private static byte[] getUtf8Bytes(final String str) {\n        return toRuntime(new CheckedExceptionToRuntime.Func<byte[]>() {\n            @Override\n            public byte[] run() throws Exception {\n                return str.getBytes(\"UTF-8\");\n            }\n        });\n    }\n\n    public static byte[] hexStringToByteArray(String s) {\n        int len = s.length();\n        byte[] data = new byte[len / 2];\n        for (int i = 0; i < len; i += 2) {\n            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)\n                    + Character.digit(s.charAt(i + 1), 16));\n        }\n        return data;\n    }\n\n    private static void genKeyStoreByPrivateKey(String ksContent, String ksName, String ksPwd) {\n        ks.genKeyByPrivateKey(ksName, ksPwd);\n        try {\n            Thread.sleep(1000); //1000 毫秒，也就是1秒.\n        } catch (InterruptedException ex) {\n            Thread.currentThread().interrupt();\n        }\n        ks.protectContent(ksContent, ksPwd);\n        ks.getContent(ksPwd);\n    }\n\n    private static void genKeyStoreByMnemonic(String ksContent, String ksName, String ksPwd) {\n        ks.genKeyByMnemonic(ksName, ksPwd);\n        try {\n            Thread.sleep(1000); //1000 毫秒，也就是1秒.\n        } catch (InterruptedException ex) {\n            Thread.currentThread().interrupt();\n        }\n        ks.protectContent(ksContent, ksPwd);\n        ks.getContent(ksPwd);\n    }\n\n    public static void sendTransaction(String fromAddress, String toAddress, BigDecimal amount,\n                                       String password, WalletFile walletfile) throws Exception {\n        new SendTransaction().sendTransaction(fromAddress, toAddress, amount, password, walletfile);\n    }\n}\n\n\n"
  },
  {
    "path": "src/main/java/SendTransaction.java",
    "content": "\nimport org.web3j.crypto.WalletFile;\nimport org.web3j.protocol.Web3j;\nimport org.web3j.protocol.core.DefaultBlockParameter;\nimport org.web3j.protocol.core.DefaultBlockParameterName;\nimport org.web3j.protocol.core.Request;\nimport org.web3j.protocol.core.methods.request.Transaction;\nimport org.web3j.protocol.core.methods.response.*;\nimport org.web3j.protocol.http.HttpService;\nimport org.web3j.utils.Convert;\n\nimport java.io.IOException;\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class SendTransaction {\n\n    private Web3j web3j = Web3j.build(new HttpService(\"https://test-eth.nshd.com\"));\n\n    public void sendTransaction(String fromAddress, String toAddress, BigDecimal amount, String password, WalletFile walletfile) throws Exception {\n        BigInteger mNonce = getNonce(fromAddress);\n        BigInteger gasPrice = getGasPrice();\n        BigInteger value = Convert.toWei(amount, Convert.Unit.ETHER).toBigInteger();\n        Transaction transaction = Transaction.createEtherTransaction(fromAddress, null,\n                null, null, toAddress, value);\n        BigInteger gasLimit = getGasLimit(transaction);\n        String sign = new TransactionManager().signedEthTransactionData(toAddress, mNonce, gasPrice,\n                gasLimit, amount, walletfile, password);\n        sendTransaction(sign);\n\n    }\n\n    public BigInteger getBalance(String fromAddress){\n        BigInteger balance = null;\n        try {\n            EthGetBalance ethGetBalance = web3j.ethGetBalance(fromAddress, DefaultBlockParameterName.PENDING).send();\n            balance = ethGetBalance.getBalance();\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n        System.out.println(\"address \" + fromAddress + \" balance \" + balance + \" wei\");\n        return balance;\n    }\n\n    private BigInteger getNonce(String userAddress) {\n        BigInteger nonce = BigInteger.ONE;\n        try {\n            Request<?, EthGetTransactionCount> rs = web3j.ethGetTransactionCount(\n                    userAddress, DefaultBlockParameterName.PENDING);\n            EthGetTransactionCount egtc = rs.sendAsync().get();\n            nonce = egtc.getTransactionCount();\n        } catch (Exception e) {\n            System.out.println(\"\" + e);\n        }\n        return nonce;\n    }\n\n    private BigInteger getGasPrice() {\n        BigInteger gasPrice = BigInteger.ONE;\n        try {\n            Request<?, EthGasPrice> rs = web3j.ethGasPrice();\n            EthGasPrice eGasPrice = rs.sendAsync().get();\n            gasPrice = eGasPrice.getGasPrice();\n        } catch (Exception e) {\n            System.out.println(\"\" + e);\n        }\n        return gasPrice;\n    }\n\n    private BigInteger getGasLimit(Transaction transaction) {\n        BigInteger gasLimit = BigInteger.ONE;\n        try {\n            Request<?, EthEstimateGas> rs = web3j.ethEstimateGas(transaction);\n            EthEstimateGas eGasLimit = rs.sendAsync().get();\n            gasLimit = eGasLimit.getAmountUsed();\n        } catch (Exception e) {\n            System.out.println(\"\" + e);\n        }\n        return gasLimit;\n    }\n\n    private void sendTransaction(String sign){\n        try {\n            Request<?, EthSendTransaction> rs = web3j.ethSendRawTransaction(sign);\n            EthSendTransaction eSendTransaction = rs.sendAsync().get();\n            String res = eSendTransaction.getTransactionHash();\n            System.out.println(\"send hash :  \" + res);\n        } catch (Exception e) {\n            System.out.println(\"\" + e);\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/TransactionManager.java",
    "content": "import io.github.novacrypto.bip32.networks.Bitcoin;\nimport org.web3j.abi.FunctionEncoder;\nimport org.web3j.abi.datatypes.Address;\nimport org.web3j.abi.datatypes.Function;\nimport org.web3j.abi.datatypes.generated.Uint256;\nimport org.web3j.crypto.*;\nimport org.web3j.tx.ChainId;\nimport org.web3j.utils.Convert;\nimport org.web3j.utils.Numeric;\n\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.util.Arrays;\nimport java.util.Collections;\n\npublic class TransactionManager {\n\n    /**\n     * ETH 转账离线签名\n     *\n     * @param to         转入的钱包地址\n     * @param nonce      以太坊nonce\n     * @param gasPrice   gasPrice\n     * @param gasLimit   gasLimit\n     * @param amount     转账的eth数量\n     * @param walletfile 钱包对象\n     * @param password   密码\n     * @return 签名data\n     */\n    public String signedEthTransactionData(String to, BigInteger nonce, BigInteger gasPrice,\n                                           BigInteger gasLimit, BigDecimal amount, WalletFile walletfile,\n                                           String password) throws Exception {\n        // 把十进制的转换成ETH的Wei, 1ETH = 10^18 Wei\n        BigDecimal amountInWei = Convert.toWei(amount.toString(), Convert.Unit.ETHER);\n        RawTransaction rawTransaction =\n                RawTransaction.createEtherTransaction(nonce, gasPrice, gasLimit, to,\n                        amountInWei.toBigInteger());\n        return signData(rawTransaction, walletfile, password);\n    }\n\n    public String signData(RawTransaction rawTransaction, WalletFile walletfile, String password)\n            throws Exception {\n        Credentials credentials = Credentials.create(Wallet.decrypt(password, walletfile));\n        byte[] signMessage =\n                TransactionEncoder.signMessage(rawTransaction, ChainId.ROPSTEN, credentials);\n        return Numeric.toHexString(signMessage);\n\n    }\n\n    public String signContractTransaction(String contractAddress,\n                                          String to,\n                                          BigInteger nonce,\n                                          BigInteger gasPrice,\n                                          BigInteger gasLimit,\n                                          BigDecimal amount,\n                                          BigDecimal decimal,\n                                          WalletFile walletfile,\n                                          String password) throws Exception {\n        BigDecimal realValue = amount.multiply(decimal);\n        Function function = new Function(\"transfer\",\n                Arrays.asList(new Address(to), new Uint256(realValue.toBigInteger())),\n                Collections.emptyList());\n        String data = FunctionEncoder.encode(function);\n        RawTransaction rawTransaction = RawTransaction.createTransaction(\n                nonce,\n                gasPrice,\n                gasLimit,\n                contractAddress,\n                data);\n        return signData(rawTransaction, walletfile, password);\n    }\n\n    // ---------------- singleton stuff --------------------------\n    public static TransactionManager shared() {\n        return TransactionManager.Holder.singleton;\n    }\n\n    public TransactionManager() {\n\n    }\n\n    private static class Holder {\n\n        private static final TransactionManager singleton = new TransactionManager();\n\n    }\n}\n"
  },
  {
    "path": "src/main/java/english",
    "content": "abandon\nability\nable\nabout\nabove\nabsent\nabsorb\nabstract\nabsurd\nabuse\naccess\naccident\naccount\naccuse\nachieve\nacid\nacoustic\nacquire\nacross\nact\naction\nactor\nactress\nactual\nadapt\nadd\naddict\naddress\nadjust\nadmit\nadult\nadvance\nadvice\naerobic\naffair\nafford\nafraid\nagain\nage\nagent\nagree\nahead\naim\nair\nairport\naisle\nalarm\nalbum\nalcohol\nalert\nalien\nall\nalley\nallow\nalmost\nalone\nalpha\nalready\nalso\nalter\nalways\namateur\namazing\namong\namount\namused\nanalyst\nanchor\nancient\nanger\nangle\nangry\nanimal\nankle\nannounce\nannual\nanother\nanswer\nantenna\nantique\nanxiety\nany\napart\napology\nappear\napple\napprove\napril\narch\narctic\narea\narena\nargue\narm\narmed\narmor\narmy\naround\narrange\narrest\narrive\narrow\nart\nartefact\nartist\nartwork\nask\naspect\nassault\nasset\nassist\nassume\nasthma\nathlete\natom\nattack\nattend\nattitude\nattract\nauction\naudit\naugust\naunt\nauthor\nauto\nautumn\naverage\navocado\navoid\nawake\naware\naway\nawesome\nawful\nawkward\naxis\nbaby\nbachelor\nbacon\nbadge\nbag\nbalance\nbalcony\nball\nbamboo\nbanana\nbanner\nbar\nbarely\nbargain\nbarrel\nbase\nbasic\nbasket\nbattle\nbeach\nbean\nbeauty\nbecause\nbecome\nbeef\nbefore\nbegin\nbehave\nbehind\nbelieve\nbelow\nbelt\nbench\nbenefit\nbest\nbetray\nbetter\nbetween\nbeyond\nbicycle\nbid\nbike\nbind\nbiology\nbird\nbirth\nbitter\nblack\nblade\nblame\nblanket\nblast\nbleak\nbless\nblind\nblood\nblossom\nblouse\nblue\nblur\nblush\nboard\nboat\nbody\nboil\nbomb\nbone\nbonus\nbook\nboost\nborder\nboring\nborrow\nboss\nbottom\nbounce\nbox\nboy\nbracket\nbrain\nbrand\nbrass\nbrave\nbread\nbreeze\nbrick\nbridge\nbrief\nbright\nbring\nbrisk\nbroccoli\nbroken\nbronze\nbroom\nbrother\nbrown\nbrush\nbubble\nbuddy\nbudget\nbuffalo\nbuild\nbulb\nbulk\nbullet\nbundle\nbunker\nburden\nburger\nburst\nbus\nbusiness\nbusy\nbutter\nbuyer\nbuzz\ncabbage\ncabin\ncable\ncactus\ncage\ncake\ncall\ncalm\ncamera\ncamp\ncan\ncanal\ncancel\ncandy\ncannon\ncanoe\ncanvas\ncanyon\ncapable\ncapital\ncaptain\ncar\ncarbon\ncard\ncargo\ncarpet\ncarry\ncart\ncase\ncash\ncasino\ncastle\ncasual\ncat\ncatalog\ncatch\ncategory\ncattle\ncaught\ncause\ncaution\ncave\nceiling\ncelery\ncement\ncensus\ncentury\ncereal\ncertain\nchair\nchalk\nchampion\nchange\nchaos\nchapter\ncharge\nchase\nchat\ncheap\ncheck\ncheese\nchef\ncherry\nchest\nchicken\nchief\nchild\nchimney\nchoice\nchoose\nchronic\nchuckle\nchunk\nchurn\ncigar\ncinnamon\ncircle\ncitizen\ncity\ncivil\nclaim\nclap\nclarify\nclaw\nclay\nclean\nclerk\nclever\nclick\nclient\ncliff\nclimb\nclinic\nclip\nclock\nclog\nclose\ncloth\ncloud\nclown\nclub\nclump\ncluster\nclutch\ncoach\ncoast\ncoconut\ncode\ncoffee\ncoil\ncoin\ncollect\ncolor\ncolumn\ncombine\ncome\ncomfort\ncomic\ncommon\ncompany\nconcert\nconduct\nconfirm\ncongress\nconnect\nconsider\ncontrol\nconvince\ncook\ncool\ncopper\ncopy\ncoral\ncore\ncorn\ncorrect\ncost\ncotton\ncouch\ncountry\ncouple\ncourse\ncousin\ncover\ncoyote\ncrack\ncradle\ncraft\ncram\ncrane\ncrash\ncrater\ncrawl\ncrazy\ncream\ncredit\ncreek\ncrew\ncricket\ncrime\ncrisp\ncritic\ncrop\ncross\ncrouch\ncrowd\ncrucial\ncruel\ncruise\ncrumble\ncrunch\ncrush\ncry\ncrystal\ncube\nculture\ncup\ncupboard\ncurious\ncurrent\ncurtain\ncurve\ncushion\ncustom\ncute\ncycle\ndad\ndamage\ndamp\ndance\ndanger\ndaring\ndash\ndaughter\ndawn\nday\ndeal\ndebate\ndebris\ndecade\ndecember\ndecide\ndecline\ndecorate\ndecrease\ndeer\ndefense\ndefine\ndefy\ndegree\ndelay\ndeliver\ndemand\ndemise\ndenial\ndentist\ndeny\ndepart\ndepend\ndeposit\ndepth\ndeputy\nderive\ndescribe\ndesert\ndesign\ndesk\ndespair\ndestroy\ndetail\ndetect\ndevelop\ndevice\ndevote\ndiagram\ndial\ndiamond\ndiary\ndice\ndiesel\ndiet\ndiffer\ndigital\ndignity\ndilemma\ndinner\ndinosaur\ndirect\ndirt\ndisagree\ndiscover\ndisease\ndish\ndismiss\ndisorder\ndisplay\ndistance\ndivert\ndivide\ndivorce\ndizzy\ndoctor\ndocument\ndog\ndoll\ndolphin\ndomain\ndonate\ndonkey\ndonor\ndoor\ndose\ndouble\ndove\ndraft\ndragon\ndrama\ndrastic\ndraw\ndream\ndress\ndrift\ndrill\ndrink\ndrip\ndrive\ndrop\ndrum\ndry\nduck\ndumb\ndune\nduring\ndust\ndutch\nduty\ndwarf\ndynamic\neager\neagle\nearly\nearn\nearth\neasily\neast\neasy\necho\necology\neconomy\nedge\nedit\neducate\neffort\negg\neight\neither\nelbow\nelder\nelectric\nelegant\nelement\nelephant\nelevator\nelite\nelse\nembark\nembody\nembrace\nemerge\nemotion\nemploy\nempower\nempty\nenable\nenact\nend\nendless\nendorse\nenemy\nenergy\nenforce\nengage\nengine\nenhance\nenjoy\nenlist\nenough\nenrich\nenroll\nensure\nenter\nentire\nentry\nenvelope\nepisode\nequal\nequip\nera\nerase\nerode\nerosion\nerror\nerupt\nescape\nessay\nessence\nestate\neternal\nethics\nevidence\nevil\nevoke\nevolve\nexact\nexample\nexcess\nexchange\nexcite\nexclude\nexcuse\nexecute\nexercise\nexhaust\nexhibit\nexile\nexist\nexit\nexotic\nexpand\nexpect\nexpire\nexplain\nexpose\nexpress\nextend\nextra\neye\neyebrow\nfabric\nface\nfaculty\nfade\nfaint\nfaith\nfall\nfalse\nfame\nfamily\nfamous\nfan\nfancy\nfantasy\nfarm\nfashion\nfat\nfatal\nfather\nfatigue\nfault\nfavorite\nfeature\nfebruary\nfederal\nfee\nfeed\nfeel\nfemale\nfence\nfestival\nfetch\nfever\nfew\nfiber\nfiction\nfield\nfigure\nfile\nfilm\nfilter\nfinal\nfind\nfine\nfinger\nfinish\nfire\nfirm\nfirst\nfiscal\nfish\nfit\nfitness\nfix\nflag\nflame\nflash\nflat\nflavor\nflee\nflight\nflip\nfloat\nflock\nfloor\nflower\nfluid\nflush\nfly\nfoam\nfocus\nfog\nfoil\nfold\nfollow\nfood\nfoot\nforce\nforest\nforget\nfork\nfortune\nforum\nforward\nfossil\nfoster\nfound\nfox\nfragile\nframe\nfrequent\nfresh\nfriend\nfringe\nfrog\nfront\nfrost\nfrown\nfrozen\nfruit\nfuel\nfun\nfunny\nfurnace\nfury\nfuture\ngadget\ngain\ngalaxy\ngallery\ngame\ngap\ngarage\ngarbage\ngarden\ngarlic\ngarment\ngas\ngasp\ngate\ngather\ngauge\ngaze\ngeneral\ngenius\ngenre\ngentle\ngenuine\ngesture\nghost\ngiant\ngift\ngiggle\nginger\ngiraffe\ngirl\ngive\nglad\nglance\nglare\nglass\nglide\nglimpse\nglobe\ngloom\nglory\nglove\nglow\nglue\ngoat\ngoddess\ngold\ngood\ngoose\ngorilla\ngospel\ngossip\ngovern\ngown\ngrab\ngrace\ngrain\ngrant\ngrape\ngrass\ngravity\ngreat\ngreen\ngrid\ngrief\ngrit\ngrocery\ngroup\ngrow\ngrunt\nguard\nguess\nguide\nguilt\nguitar\ngun\ngym\nhabit\nhair\nhalf\nhammer\nhamster\nhand\nhappy\nharbor\nhard\nharsh\nharvest\nhat\nhave\nhawk\nhazard\nhead\nhealth\nheart\nheavy\nhedgehog\nheight\nhello\nhelmet\nhelp\nhen\nhero\nhidden\nhigh\nhill\nhint\nhip\nhire\nhistory\nhobby\nhockey\nhold\nhole\nholiday\nhollow\nhome\nhoney\nhood\nhope\nhorn\nhorror\nhorse\nhospital\nhost\nhotel\nhour\nhover\nhub\nhuge\nhuman\nhumble\nhumor\nhundred\nhungry\nhunt\nhurdle\nhurry\nhurt\nhusband\nhybrid\nice\nicon\nidea\nidentify\nidle\nignore\nill\nillegal\nillness\nimage\nimitate\nimmense\nimmune\nimpact\nimpose\nimprove\nimpulse\ninch\ninclude\nincome\nincrease\nindex\nindicate\nindoor\nindustry\ninfant\ninflict\ninform\ninhale\ninherit\ninitial\ninject\ninjury\ninmate\ninner\ninnocent\ninput\ninquiry\ninsane\ninsect\ninside\ninspire\ninstall\nintact\ninterest\ninto\ninvest\ninvite\ninvolve\niron\nisland\nisolate\nissue\nitem\nivory\njacket\njaguar\njar\njazz\njealous\njeans\njelly\njewel\njob\njoin\njoke\njourney\njoy\njudge\njuice\njump\njungle\njunior\njunk\njust\nkangaroo\nkeen\nkeep\nketchup\nkey\nkick\nkid\nkidney\nkind\nkingdom\nkiss\nkit\nkitchen\nkite\nkitten\nkiwi\nknee\nknife\nknock\nknow\nlab\nlabel\nlabor\nladder\nlady\nlake\nlamp\nlanguage\nlaptop\nlarge\nlater\nlatin\nlaugh\nlaundry\nlava\nlaw\nlawn\nlawsuit\nlayer\nlazy\nleader\nleaf\nlearn\nleave\nlecture\nleft\nleg\nlegal\nlegend\nleisure\nlemon\nlend\nlength\nlens\nleopard\nlesson\nletter\nlevel\nliar\nliberty\nlibrary\nlicense\nlife\nlift\nlight\nlike\nlimb\nlimit\nlink\nlion\nliquid\nlist\nlittle\nlive\nlizard\nload\nloan\nlobster\nlocal\nlock\nlogic\nlonely\nlong\nloop\nlottery\nloud\nlounge\nlove\nloyal\nlucky\nluggage\nlumber\nlunar\nlunch\nluxury\nlyrics\nmachine\nmad\nmagic\nmagnet\nmaid\nmail\nmain\nmajor\nmake\nmammal\nman\nmanage\nmandate\nmango\nmansion\nmanual\nmaple\nmarble\nmarch\nmargin\nmarine\nmarket\nmarriage\nmask\nmass\nmaster\nmatch\nmaterial\nmath\nmatrix\nmatter\nmaximum\nmaze\nmeadow\nmean\nmeasure\nmeat\nmechanic\nmedal\nmedia\nmelody\nmelt\nmember\nmemory\nmention\nmenu\nmercy\nmerge\nmerit\nmerry\nmesh\nmessage\nmetal\nmethod\nmiddle\nmidnight\nmilk\nmillion\nmimic\nmind\nminimum\nminor\nminute\nmiracle\nmirror\nmisery\nmiss\nmistake\nmix\nmixed\nmixture\nmobile\nmodel\nmodify\nmom\nmoment\nmonitor\nmonkey\nmonster\nmonth\nmoon\nmoral\nmore\nmorning\nmosquito\nmother\nmotion\nmotor\nmountain\nmouse\nmove\nmovie\nmuch\nmuffin\nmule\nmultiply\nmuscle\nmuseum\nmushroom\nmusic\nmust\nmutual\nmyself\nmystery\nmyth\nnaive\nname\nnapkin\nnarrow\nnasty\nnation\nnature\nnear\nneck\nneed\nnegative\nneglect\nneither\nnephew\nnerve\nnest\nnet\nnetwork\nneutral\nnever\nnews\nnext\nnice\nnight\nnoble\nnoise\nnominee\nnoodle\nnormal\nnorth\nnose\nnotable\nnote\nnothing\nnotice\nnovel\nnow\nnuclear\nnumber\nnurse\nnut\noak\nobey\nobject\noblige\nobscure\nobserve\nobtain\nobvious\noccur\nocean\noctober\nodor\noff\noffer\noffice\noften\noil\nokay\nold\nolive\nolympic\nomit\nonce\none\nonion\nonline\nonly\nopen\nopera\nopinion\noppose\noption\norange\norbit\norchard\norder\nordinary\norgan\norient\noriginal\norphan\nostrich\nother\noutdoor\nouter\noutput\noutside\noval\noven\nover\nown\nowner\noxygen\noyster\nozone\npact\npaddle\npage\npair\npalace\npalm\npanda\npanel\npanic\npanther\npaper\nparade\nparent\npark\nparrot\nparty\npass\npatch\npath\npatient\npatrol\npattern\npause\npave\npayment\npeace\npeanut\npear\npeasant\npelican\npen\npenalty\npencil\npeople\npepper\nperfect\npermit\nperson\npet\nphone\nphoto\nphrase\nphysical\npiano\npicnic\npicture\npiece\npig\npigeon\npill\npilot\npink\npioneer\npipe\npistol\npitch\npizza\nplace\nplanet\nplastic\nplate\nplay\nplease\npledge\npluck\nplug\nplunge\npoem\npoet\npoint\npolar\npole\npolice\npond\npony\npool\npopular\nportion\nposition\npossible\npost\npotato\npottery\npoverty\npowder\npower\npractice\npraise\npredict\nprefer\nprepare\npresent\npretty\nprevent\nprice\npride\nprimary\nprint\npriority\nprison\nprivate\nprize\nproblem\nprocess\nproduce\nprofit\nprogram\nproject\npromote\nproof\nproperty\nprosper\nprotect\nproud\nprovide\npublic\npudding\npull\npulp\npulse\npumpkin\npunch\npupil\npuppy\npurchase\npurity\npurpose\npurse\npush\nput\npuzzle\npyramid\nquality\nquantum\nquarter\nquestion\nquick\nquit\nquiz\nquote\nrabbit\nraccoon\nrace\nrack\nradar\nradio\nrail\nrain\nraise\nrally\nramp\nranch\nrandom\nrange\nrapid\nrare\nrate\nrather\nraven\nraw\nrazor\nready\nreal\nreason\nrebel\nrebuild\nrecall\nreceive\nrecipe\nrecord\nrecycle\nreduce\nreflect\nreform\nrefuse\nregion\nregret\nregular\nreject\nrelax\nrelease\nrelief\nrely\nremain\nremember\nremind\nremove\nrender\nrenew\nrent\nreopen\nrepair\nrepeat\nreplace\nreport\nrequire\nrescue\nresemble\nresist\nresource\nresponse\nresult\nretire\nretreat\nreturn\nreunion\nreveal\nreview\nreward\nrhythm\nrib\nribbon\nrice\nrich\nride\nridge\nrifle\nright\nrigid\nring\nriot\nripple\nrisk\nritual\nrival\nriver\nroad\nroast\nrobot\nrobust\nrocket\nromance\nroof\nrookie\nroom\nrose\nrotate\nrough\nround\nroute\nroyal\nrubber\nrude\nrug\nrule\nrun\nrunway\nrural\nsad\nsaddle\nsadness\nsafe\nsail\nsalad\nsalmon\nsalon\nsalt\nsalute\nsame\nsample\nsand\nsatisfy\nsatoshi\nsauce\nsausage\nsave\nsay\nscale\nscan\nscare\nscatter\nscene\nscheme\nschool\nscience\nscissors\nscorpion\nscout\nscrap\nscreen\nscript\nscrub\nsea\nsearch\nseason\nseat\nsecond\nsecret\nsection\nsecurity\nseed\nseek\nsegment\nselect\nsell\nseminar\nsenior\nsense\nsentence\nseries\nservice\nsession\nsettle\nsetup\nseven\nshadow\nshaft\nshallow\nshare\nshed\nshell\nsheriff\nshield\nshift\nshine\nship\nshiver\nshock\nshoe\nshoot\nshop\nshort\nshoulder\nshove\nshrimp\nshrug\nshuffle\nshy\nsibling\nsick\nside\nsiege\nsight\nsign\nsilent\nsilk\nsilly\nsilver\nsimilar\nsimple\nsince\nsing\nsiren\nsister\nsituate\nsix\nsize\nskate\nsketch\nski\nskill\nskin\nskirt\nskull\nslab\nslam\nsleep\nslender\nslice\nslide\nslight\nslim\nslogan\nslot\nslow\nslush\nsmall\nsmart\nsmile\nsmoke\nsmooth\nsnack\nsnake\nsnap\nsniff\nsnow\nsoap\nsoccer\nsocial\nsock\nsoda\nsoft\nsolar\nsoldier\nsolid\nsolution\nsolve\nsomeone\nsong\nsoon\nsorry\nsort\nsoul\nsound\nsoup\nsource\nsouth\nspace\nspare\nspatial\nspawn\nspeak\nspecial\nspeed\nspell\nspend\nsphere\nspice\nspider\nspike\nspin\nspirit\nsplit\nspoil\nsponsor\nspoon\nsport\nspot\nspray\nspread\nspring\nspy\nsquare\nsqueeze\nsquirrel\nstable\nstadium\nstaff\nstage\nstairs\nstamp\nstand\nstart\nstate\nstay\nsteak\nsteel\nstem\nstep\nstereo\nstick\nstill\nsting\nstock\nstomach\nstone\nstool\nstory\nstove\nstrategy\nstreet\nstrike\nstrong\nstruggle\nstudent\nstuff\nstumble\nstyle\nsubject\nsubmit\nsubway\nsuccess\nsuch\nsudden\nsuffer\nsugar\nsuggest\nsuit\nsummer\nsun\nsunny\nsunset\nsuper\nsupply\nsupreme\nsure\nsurface\nsurge\nsurprise\nsurround\nsurvey\nsuspect\nsustain\nswallow\nswamp\nswap\nswarm\nswear\nsweet\nswift\nswim\nswing\nswitch\nsword\nsymbol\nsymptom\nsyrup\nsystem\ntable\ntackle\ntag\ntail\ntalent\ntalk\ntank\ntape\ntarget\ntask\ntaste\ntattoo\ntaxi\nteach\nteam\ntell\nten\ntenant\ntennis\ntent\nterm\ntest\ntext\nthank\nthat\ntheme\nthen\ntheory\nthere\nthey\nthing\nthis\nthought\nthree\nthrive\nthrow\nthumb\nthunder\nticket\ntide\ntiger\ntilt\ntimber\ntime\ntiny\ntip\ntired\ntissue\ntitle\ntoast\ntobacco\ntoday\ntoddler\ntoe\ntogether\ntoilet\ntoken\ntomato\ntomorrow\ntone\ntongue\ntonight\ntool\ntooth\ntop\ntopic\ntopple\ntorch\ntornado\ntortoise\ntoss\ntotal\ntourist\ntoward\ntower\ntown\ntoy\ntrack\ntrade\ntraffic\ntragic\ntrain\ntransfer\ntrap\ntrash\ntravel\ntray\ntreat\ntree\ntrend\ntrial\ntribe\ntrick\ntrigger\ntrim\ntrip\ntrophy\ntrouble\ntruck\ntrue\ntruly\ntrumpet\ntrust\ntruth\ntry\ntube\ntuition\ntumble\ntuna\ntunnel\nturkey\nturn\nturtle\ntwelve\ntwenty\ntwice\ntwin\ntwist\ntwo\ntype\ntypical\nugly\numbrella\nunable\nunaware\nuncle\nuncover\nunder\nundo\nunfair\nunfold\nunhappy\nuniform\nunique\nunit\nuniverse\nunknown\nunlock\nuntil\nunusual\nunveil\nupdate\nupgrade\nuphold\nupon\nupper\nupset\nurban\nurge\nusage\nuse\nused\nuseful\nuseless\nusual\nutility\nvacant\nvacuum\nvague\nvalid\nvalley\nvalve\nvan\nvanish\nvapor\nvarious\nvast\nvault\nvehicle\nvelvet\nvendor\nventure\nvenue\nverb\nverify\nversion\nvery\nvessel\nveteran\nviable\nvibrant\nvicious\nvictory\nvideo\nview\nvillage\nvintage\nviolin\nvirtual\nvirus\nvisa\nvisit\nvisual\nvital\nvivid\nvocal\nvoice\nvoid\nvolcano\nvolume\nvote\nvoyage\nwage\nwagon\nwait\nwalk\nwall\nwalnut\nwant\nwarfare\nwarm\nwarrior\nwash\nwasp\nwaste\nwater\nwave\nway\nwealth\nweapon\nwear\nweasel\nweather\nweb\nwedding\nweekend\nweird\nwelcome\nwest\nwet\nwhale\nwhat\nwheat\nwheel\nwhen\nwhere\nwhip\nwhisper\nwide\nwidth\nwife\nwild\nwill\nwin\nwindow\nwine\nwing\nwink\nwinner\nwinter\nwire\nwisdom\nwise\nwish\nwitness\nwolf\nwoman\nwonder\nwood\nwool\nword\nwork\nworld\nworry\nworth\nwrap\nwreck\nwrestle\nwrist\nwrite\nwrong\nyard\nyear\nyellow\nyou\nyoung\nyouth\nzebra\nzero\nzone\nzoo"
  }
]