diff --git a/pom.xml b/pom.xml index 217454c..c99c57c 100644 --- a/pom.xml +++ b/pom.xml @@ -54,5 +54,10 @@ + + + src/main/java/NEO/data + + diff --git a/src/main/java/Demo/GlobalAssetDemo.java b/src/main/java/Demo/GlobalAssetDemo.java new file mode 100644 index 0000000..101003f --- /dev/null +++ b/src/main/java/Demo/GlobalAssetDemo.java @@ -0,0 +1,123 @@ +package Demo; + +import NEO.Core.Blockchain; +import NEO.Core.SignatureContext; +import NEO.Core.Transaction; +import NEO.Fixed8; +import NEO.Helper; +import NEO.IO.Json.JArray; +import NEO.IO.Json.JNumber; +import NEO.IO.Json.JObject; +import NEO.IO.Json.JString; +import NEO.Settings; +import NEO.UInt160; +import NEO.Wallets.Account; +import NEO.Wallets.Contract; +import NEO.Wallets.Wallet; +import NEO.sdk.SmartContractTx; +import NEO.sdk.wallet.AccountManager; + +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class GlobalAssetDemo { + + // exported WIF from wallet + public static final String WALLET_WIF1 = "KxQVgnGyoHNA9h4k2as9TDPczsSwzUbH2Y8Bfku65AJiomB3wkg6"; + public static final String WALLET_WIF2 = "L4vr3XmcqGNJzwVfABiVtZbJajhNUWv6ny9Ggv7HYbhBy8rxMReU"; + public Contract contract; + + public static void main(String[] args) throws Exception { + + // import setting + Settings.getSettings(Settings.CONFIG_PRIVNET); + + // new AccountManager + AccountManager wm = getAccountManager(); + + // start block sync + wm.startSyncBlock(); + + // check height + while (!wm.hasFinishedSyncBlock()) { + Thread.sleep(1000 * 1); + } + + // import two account from WIF + String address1 = wm.createAccountsFromPrivateKey(Helper.toHexString(Wallet.getPrivateKeyFromWIF(WALLET_WIF1))); + Account account1 = wm.getAccount(address1); + Contract contract1 = Contract.createSignatureContract(account1.publicKey); + System.out.println("contract1 address:" + address1); + + String address2 = wm.createAccountsFromPrivateKey(Helper.toHexString(Wallet.getPrivateKeyFromWIF(WALLET_WIF2))); + Account account2 = wm.getAccount(address2); + Contract contract2 = Contract.createSignatureContract(account2.publicKey); + System.out.println("contract2 address:" + address2); + + // check balance + System.out.println(wm.getAccountAsset(address1)); + System.out.println(wm.getAccountAsset(address2)); + + // make transaction + Fixed8 fee = new Fixed8(); + Transaction tx = SmartContractTx.makeContractTransaction(address2, Blockchain.GoverningToken, Fixed8.ONE, fee); + System.out.println(tx.hash().toString()); + tx = wm.makeTransaction(tx, fee, Wallet.toScriptHash(address1)); + + // sign tx + SignatureContext context = new SignatureContext(tx, new UInt160[]{Wallet.toScriptHash(contract1.address())}); + byte[] signature = context.signable.sign(account1); + if (!context.add(contract1, account1.publicKey, signature)) + throw new Exception(); + if (context.isCompleted()) { + tx.scripts = context.getScripts(); + System.out.println("scripts:" + tx.scripts[0].json()); + } + + // checkout transaction + String txHex = Helper.toHexString(tx.toArray()); + System.out.println("tx:" + tx.json()); + + // make request + JObject[] params = new JObject[]{ new JString(Helper.toHexString(tx.toArray())) }; + + JObject request = new JObject(); + request.set("jsonrpc", new JString("2.0")); + request.set("method", new JString("sendrawtransaction")); + request.set("params", new JArray(params)); + request.set("id", new JNumber(1)); + + // send request + HttpURLConnection connection = (HttpURLConnection) new URL(Settings.RPC_LIST.get(0)).openConnection(); + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + + // wait result + try (OutputStreamWriter w = new OutputStreamWriter(connection.getOutputStream())) { + w.write(request.toString()); + } + try (InputStreamReader r = new InputStreamReader(connection.getInputStream())) { + System.out.println(JObject.parse(r)); + } + } + + public static AccountManager getAccountManager() throws MalformedURLException { + // v1.2 + String neoUrl = Settings.RPC_LIST.get(0); + String neoToken = ""; + String path = "./1.db3"; + AccountManager wm = AccountManager.getWallet(path, neoUrl, neoToken); + print(String.format("[param=%s,%s]", neoUrl, path)); + print(String.format("start to test....hh:%s", wm.getBlockHeight())); + return wm; + } + + private static void print(String ss) { + System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + " " + ss); + } +} diff --git a/src/main/java/Demo/RawTxDemo.java b/src/main/java/Demo/RawTxDemo.java new file mode 100644 index 0000000..031130e --- /dev/null +++ b/src/main/java/Demo/RawTxDemo.java @@ -0,0 +1,136 @@ +package Demo; + +import NEO.*; +import NEO.Core.*; +import NEO.Core.Scripts.Program; +import NEO.IO.Json.JArray; +import NEO.IO.Json.JNumber; +import NEO.IO.Json.JObject; +import NEO.IO.Json.JString; +import NEO.Wallets.Account; +import NEO.Wallets.Contract; +import NEO.Wallets.Wallet; +import NEO.sdk.wallet.AccountManager; + +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.HttpURLConnection; +import java.net.URL; + +public class RawTxDemo { + + // exported WIF from wallet + public static final String WALLET_WIF2 = "KxDgvEKzgSBPPfuVfw67oPQBSjidEiqTHURKSDL1R7yGaGYAeYnr"; + public static final String WALLET_WIF1 = "L4vr3XmcqGNJzwVfABiVtZbJajhNUWv6ny9Ggv7HYbhBy8rxMReU"; + public Contract contract; + + public static void main(String[] args) throws Exception { + + // import setting + Settings.getSettings(Settings.CONFIG_PRIVNET); + + // new AccountManager + String neoUrl = Settings.RPC_LIST.get(0); + String neoToken = ""; + String path = "./1.db3"; + AccountManager wm = AccountManager.getWallet(path, neoUrl, neoToken); + System.out.println("[param=" + neoUrl + "," + path + "]"); + System.out.println("start to test....hh:" + wm.getBlockHeight()); + + // start block sync + wm.startSyncBlock(); + + // check height + while (!wm.hasFinishedSyncBlock()) { + Thread.sleep(1000 * 1); + } + + // import two account from WIF + String address1 = wm.createAccountsFromPrivateKey(Helper.toHexString(Wallet.getPrivateKeyFromWIF(WALLET_WIF1))); + Account account1 = wm.getAccount(address1); + Contract contract1 = Contract.createSignatureContract(account1.publicKey); + System.out.println("contract1 address:" + address1); + + String address2 = wm.createAccountsFromPrivateKey(Helper.toHexString(Wallet.getPrivateKeyFromWIF(WALLET_WIF2))); + Account account2 = wm.getAccount(address2); + Contract contract2 = Contract.createSignatureContract(account2.publicKey); + System.out.println("contract2 address:" + address2); + + // check balance + System.out.println(wm.getAccountAsset(address1)); + System.out.println(wm.getAccountAsset(address2)); + + // make transaction + ContractTransaction tx = new ContractTransaction(); + + // neo input + TransactionInput inputN = new TransactionInput(); + inputN.prevIndex = 0; + inputN.prevHash = UInt256.parse("072497994952d898e4f302d7b7022cbfd368d2b2ede4f51a0a3e41af22278e87"); + + // gas input + TransactionInput inputG = new TransactionInput(); + inputG.prevIndex = 0; + inputG.prevHash = UInt256.parse("ede0cfea66811f194c1d82b8d8377f941c8cc8bae3adfed0a77c5eb7bb5e96a9"); + + // neo output + TransactionOutput outputN = new TransactionOutput(); + outputN.assetId = Blockchain.GoverningToken; + outputN.value = Fixed8.ONE; + outputN.scriptHash = Wallet.toScriptHash(address2); + + // gas output + TransactionOutput outputG = new TransactionOutput(); + outputG.assetId = Blockchain.UtilityToken; + outputG.value = new Fixed8((long)(0.999 * (long)Math.pow(10, 8))); + outputG.scriptHash = Wallet.toScriptHash(address1); + + tx.version = 0; + tx.attributes = new TransactionAttribute[0]; + tx.inputs = new TransactionInput[2]; + tx.inputs[0] = inputN; + tx.inputs[1] = inputG; + tx.outputs = new TransactionOutput[2]; + tx.outputs[0] = outputN; + tx.outputs[1] = outputG; + tx.scripts = new Program[0]; + + System.out.println(tx.hash().toString()); + + // sign tx + SignatureContext context = new SignatureContext(tx, new UInt160[]{Wallet.toScriptHash(contract1.address())}); + byte[] signature = context.signable.sign(account1); + if (!context.add(contract1, account1.publicKey, signature)) + throw new Exception(); + if (context.isCompleted()) { + tx.scripts = context.getScripts(); + System.out.println("scripts:" + tx.scripts[0].json()); + } + + // checkout transaction + String txHex = Helper.toHexString(tx.toArray()); + System.out.println("tx:" + tx.json()); + + // make request + JObject[] params = new JObject[]{ new JString(Helper.toHexString(tx.toArray())) }; + + JObject request = new JObject(); + request.set("jsonrpc", new JString("2.0")); + request.set("method", new JString("sendrawtransaction")); + request.set("params", new JArray(params)); + request.set("id", new JNumber(1)); + + // send request + HttpURLConnection connection = (HttpURLConnection) new URL(Settings.RPC_LIST.get(0)).openConnection(); + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + + // wait result + try (OutputStreamWriter w = new OutputStreamWriter(connection.getOutputStream())) { + w.write(request.toString()); + } + try (InputStreamReader r = new InputStreamReader(connection.getInputStream())) { + System.out.println(JObject.parse(r)); + } + } +} diff --git a/src/main/java/NEO/Core/Blockchain.java b/src/main/java/NEO/Core/Blockchain.java index b50d388..4a55a11 100644 --- a/src/main/java/NEO/Core/Blockchain.java +++ b/src/main/java/NEO/Core/Blockchain.java @@ -100,6 +100,10 @@ public abstract class Blockchain implements AutoCloseable { @Override public abstract void close(); + public static final UInt256 GoverningToken = UInt256.parse("c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b"); + + public static final UInt256 UtilityToken = UInt256.parse("602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"); + /** * 判断区块链中是否包含指定的资产 * 资产编号 diff --git a/src/main/java/NEO/Core/ClaimTransaction.java b/src/main/java/NEO/Core/ClaimTransaction.java new file mode 100644 index 0000000..9e5bbfd --- /dev/null +++ b/src/main/java/NEO/Core/ClaimTransaction.java @@ -0,0 +1,58 @@ +package NEO.Core; + +import NEO.IO.BinaryReader; +import NEO.IO.BinaryWriter; +import NEO.UInt160; +import NEO.UInt256; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class ClaimTransaction extends Transaction{ + + public TransactionInput[] claims; + + public ClaimTransaction() { + super(TransactionType.ClaimTransaction); + } + + @Override + protected void deserializeExclusiveData(BinaryReader reader) throws IOException { + try { + claims = reader.readSerializableArray(TransactionInput.class); + } + catch (Exception e) { + throw new IOException(); + } + } + + @Override + public UInt160[] getScriptHashesForVerifying() { + HashSet hashs = new HashSet(Arrays.asList(super.getScriptHashesForVerifying())); + for (Map.Entry> group : Arrays.stream(claims).collect(Collectors.groupingBy(p -> p.prevHash)).entrySet()) { + try { + Transaction tx = Blockchain.current().getTransaction(group.getKey()); + if (tx == null) + throw new IllegalStateException(); + for (TransactionInput claim : group.getValue()) { + if (tx.outputs.length <= claim.prevIndex) + throw new IllegalStateException(); + hashs.add(tx.outputs[claim.prevIndex].scriptHash); + } + } + catch (Exception e) { + throw new IllegalStateException(); + } + } + return hashs.stream().sorted().toArray(UInt160[]::new); + } + + @Override + protected void serializeExclusiveData(BinaryWriter writer) throws IOException { + writer.writeSerializableArray(claims); + } +} diff --git a/src/main/java/NEO/Core/MinerTransaction.java b/src/main/java/NEO/Core/MinerTransaction.java index ca80f50..0068835 100644 --- a/src/main/java/NEO/Core/MinerTransaction.java +++ b/src/main/java/NEO/Core/MinerTransaction.java @@ -14,9 +14,7 @@ public MinerTransaction() { @Override protected void deserializeExclusiveData(BinaryReader reader) throws IOException { - if(version == 3) { - nonce = reader.readLong(); - } + nonce = reader.readInt(); } @Override @@ -25,4 +23,15 @@ protected void serializeExclusiveData(BinaryWriter writer) throws IOException { writer.writeLong(nonce); } } + + @Override + protected void onDeserialized() throws IOException{ + if (inputs.length != 0) + throw new IOException(); + for (TransactionOutput output : outputs) { + //if (output.assetId != Blockchain.utilityToken().hash()) + if (output.assetId != Blockchain.UtilityToken) + throw new IOException(); + } + } } diff --git a/src/main/java/NEO/Core/TransactionAttribute.java b/src/main/java/NEO/Core/TransactionAttribute.java index 92be940..7cb232e 100644 --- a/src/main/java/NEO/Core/TransactionAttribute.java +++ b/src/main/java/NEO/Core/TransactionAttribute.java @@ -31,15 +31,17 @@ public void serialize(BinaryWriter writer) throws IOException { // usage writer.writeByte(usage.value()); // data - if (usage == TransactionAttributeUsage.Script){ + if (usage == TransactionAttributeUsage.DescriptionUrl){ + writer.writeByte((byte)data.length); + } + else if (usage == TransactionAttributeUsage.Description || usage.value() >= TransactionAttributeUsage.Remark.value()) { + writer.writeVarInt(data.length); + } + if (usage == TransactionAttributeUsage.ECDH02 || usage == TransactionAttributeUsage.ECDH03) { + writer.write(data, 1, 32); + } + else writer.write(data); - }else if( usage == TransactionAttributeUsage.DescriptionUrl - || usage == TransactionAttributeUsage.Description - || usage == TransactionAttributeUsage.Nonce) { - writer.writeVarBytes(data); - } else { - throw new IOException(); - } } @Override @@ -47,15 +49,23 @@ public void deserialize(BinaryReader reader) throws IOException { // usage usage = TransactionAttributeUsage.valueOf(reader.readByte()); // data - if (usage == TransactionAttributeUsage.Script){ + if (usage == TransactionAttributeUsage.ContractHash || usage == TransactionAttributeUsage.Vote || (usage.value() >= TransactionAttributeUsage.Hash1.value() && usage.value() <= TransactionAttributeUsage.Hash15.value())) + data = reader.readBytes(32); + else if (usage == TransactionAttributeUsage.ECDH02 || usage == TransactionAttributeUsage.ECDH03) { + byte[] part1 = data.clone(); + byte[] part2 = reader.readBytes(32); + data = new byte[part1.length + part2.length]; + System.arraycopy(part1, 0, data, 0, part1.length); + System.arraycopy(part2, 0, data, part1.length, part2.length); + } + else if (usage == TransactionAttributeUsage.Script) data = reader.readBytes(20); - }else if(usage == TransactionAttributeUsage.DescriptionUrl - || usage == TransactionAttributeUsage.Description - || usage == TransactionAttributeUsage.Nonce) { - data = reader.readVarBytes(255); - } else { - throw new IOException(); - } + else if (usage == TransactionAttributeUsage.DescriptionUrl) + data = reader.readBytes(reader.readByte()); + else if (usage == TransactionAttributeUsage.Description || usage.value() >= TransactionAttributeUsage.Remark.value()) + data = reader.readVarBytes(65535); + else + throw new IOException(); } public JObject json() { diff --git a/src/main/java/NEO/Core/TransactionAttributeUsage.java b/src/main/java/NEO/Core/TransactionAttributeUsage.java index 67ae502..7963e77 100644 --- a/src/main/java/NEO/Core/TransactionAttributeUsage.java +++ b/src/main/java/NEO/Core/TransactionAttributeUsage.java @@ -5,15 +5,66 @@ */ public enum TransactionAttributeUsage { - Nonce(0x00), + /** + * 外部合同散列值 + */ + ContractHash(0x00), + + /** + * 用于ECDH密钥交换的公钥,该公钥的第一个字节为0x02 + */ + ECDH02(0x02), + /** + * 用于ECDH密钥交换的公钥,该公钥的第一个字节为0x03 + */ + ECDH03(0x03), + /** * 用于对交易进行额外的验证 */ Script(0x20), + Vote(0x30), + DescriptionUrl(0x81), Description(0x90), + Hash1(0xa1), + Hash2(0xa2), + Hash3(0xa3), + Hash4(0xa4), + Hash5(0xa5), + Hash6(0xa6), + Hash7(0xa7), + Hash8(0xa8), + Hash9(0xa9), + Hash10(0xaa), + Hash11(0xab), + Hash12(0xac), + Hash13(0xad), + Hash14(0xae), + Hash15(0xaf), + + /** + * 备注 + */ + Remark(0xf0), + Remark1(0xf1), + Remark2(0xf2), + Remark3(0xf3), + Remark4(0xf4), + Remark5(0xf5), + Remark6(0xf6), + Remark7(0xf7), + Remark8(0xf8), + Remark9(0xf9), + Remark10(0xfa), + Remark11(0xfb), + Remark12(0xfc), + Remark13(0xfd), + Remark14(0xfe), + Remark15(0xff), + ; private byte value; diff --git a/src/main/java/NEO/Settings.java b/src/main/java/NEO/Settings.java new file mode 100644 index 0000000..8612d1e --- /dev/null +++ b/src/main/java/NEO/Settings.java @@ -0,0 +1,84 @@ +package NEO; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +public class Settings { + + public static final String CONFIG_MAINNET = "protocol.mainnet.json"; + public static final String CONFIG_TESTNET = "protocol.testnet.json"; + public static final String CONFIG_PRIVNET = "protocol.privnet.json"; + + + public static JSONObject PROTOCOL_CONFIGURATION; + + public static long MAGIC; + public static long ADDRESS_VERSION; + public static List STANDBY_VALIDATORS; + public static List SEED_LIST; + public static List RPC_LIST; + + public static JSONObject ALL_FEES; + public static long ENROLLMENT_TX_FEE; + public static long ISSUE_TX_FEE; + public static long PUBLISH_TX_FEE; + public static long REGISTER_TX_FEE; + + + public static JSONObject APPLICATION_CONFIGURATION; + + public static String DATA_DIRECTORY_PATH; + public static String NOTIFICATION_DATA_PATH; + public static long RPC_PORT; + public static long NODE_PORT; + public static long WS_PORT; + public static List URI_PREFIX; + public static String SSL_CERT; + public static String SSL_CERT_PASSWORD; + public static String BOOTSTRAP_FILE; + public static String NOTIFICATION_BOOTSTRAP_FILE; + public static long DEBUG_STORAGE; + + private Settings(){ + } + + public static void getSettings() throws IOException{ + getSettings(CONFIG_TESTNET); + } + + public static void getSettings(String config_file) throws IOException{ + + // Need a better path solution + String path = Settings.class.getClassLoader().getResource(config_file).getPath(); + InputStream is = new FileInputStream(path); + + byte[] bys = new byte[is.available()]; + is.read(bys); + is.close(); + JSONObject json = JSONObject.parseObject(new String(bys)); + + PROTOCOL_CONFIGURATION = json.getJSONObject("ProtocolConfiguration"); + + MAGIC = PROTOCOL_CONFIGURATION.getLong("Magic"); + ADDRESS_VERSION = PROTOCOL_CONFIGURATION.getLong("AddressVersion"); + STANDBY_VALIDATORS = JSON.parseArray(PROTOCOL_CONFIGURATION.getJSONArray("StandbyValidators").toString(), String.class); + SEED_LIST = JSON.parseArray(PROTOCOL_CONFIGURATION.getJSONArray("SeedList").toString(), String.class); + RPC_LIST = JSON.parseArray(PROTOCOL_CONFIGURATION.getJSONArray("RPCList").toString(), String.class); + + ALL_FEES = PROTOCOL_CONFIGURATION.getJSONObject("SystemFee"); + + ENROLLMENT_TX_FEE = ALL_FEES.getLong("EnrollmentTransaction"); + ISSUE_TX_FEE = ALL_FEES.getLong("IssueTransaction"); + PUBLISH_TX_FEE = ALL_FEES.getLong("PublishTransaction"); + REGISTER_TX_FEE = ALL_FEES.getLong("RegisterTransaction"); + + + APPLICATION_CONFIGURATION = json.getJSONObject("ApplicationConfiguration"); + } +} \ No newline at end of file diff --git a/src/main/java/NEO/data/protocol.json b/src/main/java/NEO/data/protocol.json new file mode 100644 index 0000000..75630cb --- /dev/null +++ b/src/main/java/NEO/data/protocol.json @@ -0,0 +1,30 @@ +{ + "ProtocolConfiguration": { + "Magic": 56753, + "AddressVersion": 23, + "StandbyValidators": [ + "02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2", + "02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e", + "03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699", + "02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62" + ], + "SeedList": [ + "127.0.0.1:20333", + "127.0.0.1:20334", + "127.0.0.1:20335", + "127.0.0.1:20336" + ], + "RPCList":[ + "http://127.0.0.1:30333" + ], + "SystemFee": { + "EnrollmentTransaction": 1000, + "IssueTransaction": 500, + "PublishTransaction": 500, + "RegisterTransaction": 10000 + } + }, + + "ApplicationConfiguration": { + } +} diff --git a/src/main/java/NEO/data/protocol.mainnet.json b/src/main/java/NEO/data/protocol.mainnet.json new file mode 100644 index 0000000..dbe1609 --- /dev/null +++ b/src/main/java/NEO/data/protocol.mainnet.json @@ -0,0 +1,40 @@ +{ + "ProtocolConfiguration": { + "Magic": 7630401, + "AddressVersion": 23, + "StandbyValidators": [ + "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", + "02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093", + "03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a", + "02ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba554", + "024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d", + "02aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e", + "02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70" + ], + "SeedList": [ + "13.58.252.110:10333", + "18.216.146.68:10333", + "18.217.91.255:10333", + "18.218.62.119:10333", + "18.196.141.225:10333", + "seed2.neo.org:10333", + "seed3.neo.org:10333", + "seed1.redpulse.com:10333" + ], + "RPCList":[ + "http://18.217.24.130:8080", + "http://18.220.214.143:8080", + "http://13.58.198.112:8080", + "http://13.59.14.206:8080", + "http://18.216.9.7:8080" + ], + "SystemFee": { + "EnrollmentTransaction": 1000, + "IssueTransaction": 500, + "PublishTransaction": 500, + "RegisterTransaction": 10000 + } + }, + "ApplicationConfiguration": { + } +} diff --git a/src/main/java/NEO/data/protocol.privnet.json b/src/main/java/NEO/data/protocol.privnet.json new file mode 100644 index 0000000..f0fafec --- /dev/null +++ b/src/main/java/NEO/data/protocol.privnet.json @@ -0,0 +1,30 @@ +{ + "ProtocolConfiguration": { + "Magic": 56753, + "AddressVersion": 23, + "StandbyValidators": [ + "02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2", + "02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e", + "03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699", + "02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62" + ], + "SeedList": [ + "127.0.0.1:20333", + "127.0.0.1:20334", + "127.0.0.1:20335", + "127.0.0.1:20336" + ], + "RPCList":[ + "http://127.0.0.1:30333" + ], + "SystemFee": { + "EnrollmentTransaction": 1000, + "IssueTransaction": 500, + "PublishTransaction": 500, + "RegisterTransaction": 10000 + } + }, + + "ApplicationConfiguration": { + } +} diff --git a/src/main/java/NEO/data/protocol.testnet.json b/src/main/java/NEO/data/protocol.testnet.json new file mode 100644 index 0000000..ea3380f --- /dev/null +++ b/src/main/java/NEO/data/protocol.testnet.json @@ -0,0 +1,37 @@ +{ + "ProtocolConfiguration": { + "AddressVersion": 23, + "Magic": 1953787457, + "SeedList": [ + "18.218.97.227:20333", + "18.219.30.120:20333", + "18.219.13.91:20333", + "13.59.116.121:20333", + "18.218.255.178:20333" + ], + "RPCList":[ + "http://18.221.221.195:8880", + "http://18.221.139.152:8880", + "http://52.15.48.60:8880", + "http://18.221.0.152:8880", + "http://52.14.184.44:8880" + ], + "StandbyValidators": [ + "0327da12b5c40200e9f65569476bbff2218da4f32548ff43b6387ec1416a231ee8", + "026ce35b29147ad09e4afe4ec4a7319095f08198fa8babbe3c56e970b143528d22", + "0209e7fd41dfb5c2f8dc72eb30358ac100ea8c72da18847befe06eade68cebfcb9", + "039dafd8571a641058ccc832c5e2111ea39b09c0bde36050914384f7a48bce9bf9", + "038dddc06ce687677a53d54f096d2591ba2302068cf123c1f2d75c2dddc5425579", + "02d02b1873a0863cd042cc717da31cea0d7cf9db32b74d4c72c01b0011503e2e22", + "034ff5ceeac41acf22cd5ed2da17a6df4dd8358fcb2bfb1a43208ad0feaab2746b" + ], + "SystemFee": { + "EnrollmentTransaction": 10, + "IssueTransaction": 5, + "PublishTransaction": 5, + "RegisterTransaction": 100 + } + }, + "ApplicationConfiguration": { + } +} diff --git a/src/main/java/NEO/sdk/SmartContractTx.java b/src/main/java/NEO/sdk/SmartContractTx.java index 70355d1..e6fb8f3 100644 --- a/src/main/java/NEO/sdk/SmartContractTx.java +++ b/src/main/java/NEO/sdk/SmartContractTx.java @@ -6,13 +6,16 @@ import NEO.Core.Scripts.ScriptBuilder; import NEO.Fixed8; import NEO.Helper; +import NEO.UInt256; import NEO.Wallets.Contract; +import NEO.Wallets.Wallet; import NEO.sdk.abi.AbiFunction; import NEO.sdk.abi.Parameter; import com.alibaba.fastjson.JSON; import org.bouncycastle.math.ec.ECPoint; import java.lang.reflect.Array; +import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; @@ -156,4 +159,34 @@ public static InvocationTransaction makeInvocationTransaction(byte[] paramsHexSt tx.gas = new Fixed8(0); return tx; } + + public static ContractTransaction makeContractTransaction(String toAddress, UInt256 assetId, Fixed8 amount, Fixed8 fee) { + ContractTransaction tx = new ContractTransaction(); + + TransactionOutput output = new TransactionOutput(); + output.assetId = assetId; + output.value = amount; + output.scriptHash = Wallet.toScriptHash(toAddress); + + tx.version = 0; + tx.attributes = new TransactionAttribute[0]; + tx.inputs = new TransactionInput[0]; + tx.outputs = new TransactionOutput[1]; + tx.outputs[0] = output; + tx.scripts = new Program[0]; + + Fixed8 gasFee = null; + Fixed8 netFee = null; + if (tx.systemFee().compareTo(Fixed8.ZERO) <= 0) { + gasFee = Fixed8.ZERO; + netFee = Fixed8.fromDecimal(new BigDecimal("0.0001")); + } + else { + gasFee = tx.systemFee(); + netFee = Fixed8.ZERO; + } + + //fee.assign(netFee); + return tx; + } } diff --git a/src/main/java/NEO/sdk/wallet/AccountManager.java b/src/main/java/NEO/sdk/wallet/AccountManager.java index 478fb2c..415de28 100644 --- a/src/main/java/NEO/sdk/wallet/AccountManager.java +++ b/src/main/java/NEO/sdk/wallet/AccountManager.java @@ -10,6 +10,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import NEO.Wallets.*; import com.alibaba.fastjson.JSON; import NEO.Fixed8; @@ -37,10 +38,6 @@ import NEO.Implementations.Wallets.SQLite.UserWallet; import NEO.Network.Rest.RestException; import NEO.Network.Rest.RestNode; -import NEO.Wallets.Account; -import NEO.Wallets.Coin; -import NEO.Wallets.Contract; -import NEO.Wallets.Wallet; import NEO.sdk.helper.OnChainSDKHelper; import NEO.sdk.info.account.AccountAsset; import NEO.sdk.info.account.AccountInfo; @@ -235,7 +232,16 @@ public void setAuthType(String authType) { public void setAccessToken(String accessToken) { this.restNode.setAccessToken(accessToken); } - + + @Deprecated + public Transaction makeTransaction(Transaction tx, Fixed8 fee) throws CoinException { + return this.uw.makeTransaction(tx, fee); + } + + @Deprecated + public Transaction makeTransaction(Transaction tx, Fixed8 fee, UInt160 from) throws CoinException { + return this.uw.makeTransaction(tx, fee, from); + } /** * 注册资产 * @throws Exception