public void TestSignMulti() { txManager = new TransactionManager(rpcClientMock.Object, sender); var multiContract = Contract.CreateMultiSigContract(2, keyPair1.PublicKey, keyPair2.PublicKey); // Cosigner needs multi signature Cosigner[] cosigners = new Cosigner[1] { new Cosigner { Account = multiContract.ScriptHash, Scopes = WitnessScope.Global } }; byte[] script = new byte[1]; txManager.MakeTransaction(script, null, cosigners, 0_10000000) .AddMultiSig(keyPair1, 2, keyPair1.PublicKey, keyPair2.PublicKey) .AddMultiSig(keyPair2, 2, keyPair1.PublicKey, keyPair2.PublicKey) .AddSignature(keyPair1) .Sign(); var store = TestBlockchain.GetStore(); var snapshot = store.GetSnapshot(); var tx = txManager.Tx; Assert.IsTrue(tx.VerifyWitnesses(snapshot, tx.NetworkFee)); }
public void TestAddWitness() { txManager = new TransactionManager(rpcClientMock.Object, sender); // Cosigner as contract scripthash Cosigner[] cosigners = new Cosigner[1] { new Cosigner { Account = UInt160.Zero, Scopes = WitnessScope.Global } }; byte[] script = new byte[1]; txManager.MakeTransaction(script, null, cosigners); txManager.AddWitness(UInt160.Zero); txManager.AddSignature(keyPair1); txManager.Sign(); var tx = txManager.Tx; Assert.AreEqual(2, tx.Witnesses.Length); Assert.AreEqual(0, tx.Witnesses[0].VerificationScript.Length); Assert.AreEqual(0, tx.Witnesses[0].InvocationScript.Length); }
public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_FAULT() { var wallet = TestUtils.GenerateTestWallet(); var snapshot = store.GetSnapshot(); // no password on this wallet using (var unlock = wallet.Unlock("")) { var acc = wallet.CreateAccount(); // Fake balance var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem { Value = new Nep5AccountState().ToByteArray() }); entry.Value = new Nep5AccountState() { Balance = 10000 * NativeContract.GAS.Factor } .ToByteArray(); // Make transaction // Manually creating script byte[] script; using (ScriptBuilder sb = new ScriptBuilder()) { // self-transfer of 1e-8 GAS System.Numerics.BigInteger value = (new BigDecimal(1, 8)).Value; sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value); sb.Emit(OpCode.THROWIFNOT); script = sb.ToArray(); } // trying global scope var cosigners = new Cosigner[] { new Cosigner { Account = acc.ScriptHash, Scopes = WitnessScope.CustomContracts, AllowedContracts = new[] { NativeContract.NEO.Hash } } }; // using this... // expects FAULT on execution of 'transfer' Application script // due to lack of a valid witness validation Transaction tx = null; Assert.ThrowsException <InvalidOperationException>(() => tx = wallet.MakeTransaction(script, acc.ScriptHash, new TransactionAttribute[0], cosigners)); Assert.IsNull(tx); } }
public void Json_Global() { var attr = new Cosigner() { Scopes = WitnessScope.Global, Account = UInt160.Zero }; var json = "{\"type\":\"Cosigner\",\"account\":\"0x0000000000000000000000000000000000000000\",\"scopes\":\"Global\"}"; attr.ToJson().ToString().Should().Be(json); }
public void Json_CustomContracts() { var attr = new Cosigner() { Scopes = WitnessScope.CustomContracts, AllowedContracts = new[] { UInt160.Zero }, Account = UInt160.Zero }; var json = "{\"type\":\"Cosigner\",\"account\":\"0x0000000000000000000000000000000000000000\",\"scopes\":\"CustomContracts\",\"allowedContracts\":[\"0x0000000000000000000000000000000000000000\"]}"; attr.ToJson().ToString().Should().Be(json); }
public void Json_CustomGroups() { var attr = new Cosigner() { Scopes = WitnessScope.CustomGroups, AllowedGroups = new[] { ECPoint.Parse("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", ECCurve.Secp256r1) }, Account = UInt160.Zero }; var json = "{\"type\":\"Cosigner\",\"account\":\"0x0000000000000000000000000000000000000000\",\"scopes\":\"CustomGroups\",\"allowedGroups\":[\"03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c\"]}"; attr.ToJson().ToString().Should().Be(json); }
public void Serialize_Deserialize_CalledByEntry() { var attr = new Cosigner() { Scopes = WitnessScope.CalledByEntry, Account = UInt160.Zero }; var hex = "01000000000000000000000000000000000000000001"; attr.ToArray().ToHexString().Should().Be(hex); var copy = hex.HexToBytes().AsSerializable <Cosigner>(); Assert.AreEqual(attr.Scopes, copy.Scopes); Assert.AreEqual(attr.Account, copy.Account); }
public void Json_Global() { var attr = new Cosigner() { Scopes = WitnessScope.Global, Account = UInt160.Zero }; var json = "{\"account\":\"0x0000000000000000000000000000000000000000\",\"scopes\":\"Global\"}"; attr.ToJson().ToString().Should().Be(json); var copy = Cosigner.FromJson(JObject.Parse(json)); Assert.AreEqual(attr.Scopes, copy.Scopes); Assert.AreEqual(attr.Account, copy.Account); }
public void Json_CustomContracts() { var attr = new Cosigner() { Scopes = WitnessScope.CustomContracts, AllowedContracts = new[] { UInt160.Zero }, Account = UInt160.Zero }; var json = "{\"account\":\"0x0000000000000000000000000000000000000000\",\"scopes\":\"CustomContracts\",\"allowedContracts\":[\"0x0000000000000000000000000000000000000000\"]}"; attr.ToJson().ToString().Should().Be(json); var copy = Cosigner.FromJson(JObject.Parse(json)); Assert.AreEqual(attr.Scopes, copy.Scopes); CollectionAssert.AreEqual(attr.AllowedContracts, copy.AllowedContracts); Assert.AreEqual(attr.Account, copy.Account); }
public void Serialize_Deserialize_CustomContracts() { var attr = new Cosigner() { Scopes = WitnessScope.CustomContracts, AllowedContracts = new[] { UInt160.Zero }, Account = UInt160.Zero }; var hex = "01000000000000000000000000000000000000000010010000000000000000000000000000000000000000"; attr.ToArray().ToHexString().Should().Be(hex); var copy = hex.HexToBytes().AsSerializable <Cosigner>(); Assert.AreEqual(attr.Scopes, copy.Scopes); CollectionAssert.AreEqual(attr.AllowedContracts, copy.AllowedContracts); Assert.AreEqual(attr.Account, copy.Account); }
public void Serialize_Deserialize_CustomGroups() { var attr = new Cosigner() { Scopes = WitnessScope.CustomGroups, AllowedGroups = new[] { ECPoint.Parse("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", ECCurve.Secp256r1) }, Account = UInt160.Zero }; var hex = "010000000000000000000000000000000000000000200103b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c"; attr.ToArray().ToHexString().Should().Be(hex); var copy = hex.HexToBytes().AsSerializable <Cosigner>(); Assert.AreEqual(attr.Scopes, copy.Scopes); CollectionAssert.AreEqual(attr.AllowedGroups, copy.AllowedGroups); Assert.AreEqual(attr.Account, copy.Account); }
public void TestSign() { txManager = new TransactionManager(rpcClientMock.Object, sender); TransactionAttribute[] attributes = new TransactionAttribute[1] { new TransactionAttribute { Usage = TransactionAttributeUsage.Url, Data = "53616d706c6555726c".HexToBytes() // "SampleUrl" } }; Cosigner[] cosigners = new Cosigner[1] { new Cosigner { Account = sender, Scopes = WitnessScope.Global } }; byte[] script = new byte[1]; txManager.MakeTransaction(script, attributes, cosigners) .AddSignature(keyPair1) .Sign(); // get signature from Witnesses var tx = txManager.Tx; byte[] signature = tx.Witnesses[0].InvocationScript.Skip(2).ToArray(); Assert.IsTrue(Crypto.VerifySignature(tx.GetHashData(), signature, keyPair1.PublicKey.EncodePoint(false).Skip(1).ToArray())); // verify network fee long networkFee = tx.Size * (long)1000 + ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] + ApplicationEngine.OpCodePrices[OpCode.PUSHDATA1] + ApplicationEngine.OpCodePrices[OpCode.PUSHNULL] + InteropService.GetPrice(InteropService.Crypto.ECDsaVerify, null, null); Assert.AreEqual(networkFee, tx.NetworkFee); // duplicate sign should not add new witness txManager.AddSignature(keyPair1).Sign(); Assert.AreEqual(1, txManager.Tx.Witnesses.Length); // throw exception when the KeyPair is wrong Assert.ThrowsException <Exception>(() => txManager.AddSignature(keyPair2).Sign()); }
public void Json_CustomGroups() { var attr = new Cosigner() { Scopes = WitnessScope.CustomGroups, AllowedGroups = new[] { ECPoint.Parse("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", ECCurve.Secp256r1) }, Account = UInt160.Zero }; var json = "{\"account\":\"0x0000000000000000000000000000000000000000\",\"scopes\":\"CustomGroups\",\"allowedGroups\":[\"03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c\"]}"; attr.ToJson().ToString().Should().Be(json); var copy = Cosigner.FromJson(JObject.Parse(json)); Assert.AreEqual(attr.Scopes, copy.Scopes); CollectionAssert.AreEqual(attr.AllowedGroups, copy.AllowedGroups); Assert.AreEqual(attr.Account, copy.Account); }
public void TestSignMulti() { txManager = new TransactionManager(rpcClientMock.Object, sender); var multiContract = Contract.CreateMultiSigContract(2, keyPair1.PublicKey, keyPair2.PublicKey); // Cosigner needs multi signature Cosigner[] cosigners = new Cosigner[1] { new Cosigner { Account = multiContract.ScriptHash, Scopes = WitnessScope.Global } }; byte[] script = new byte[1]; txManager.MakeTransaction(script, null, cosigners) .AddMultiSig(keyPair1, 2, keyPair1.PublicKey, keyPair2.PublicKey) .AddMultiSig(keyPair2, 2, keyPair1.PublicKey, keyPair2.PublicKey) .AddSignature(keyPair1) .Sign(); }
public void Transaction_Serialize_Deserialize_MaxSizeCosigners() { // cosigners must respect count int maxCosigners = 16; // -------------------------------------- // this should pass (respecting max size) var cosigners1 = new Cosigner[maxCosigners]; for (int i = 0; i < cosigners1.Length; i++) { string hex = i.ToString("X4"); while (hex.Length < 40) { hex = hex.Insert(0, "0"); } cosigners1[i] = new Cosigner { Account = UInt160.Parse(hex) }; } Transaction txCosigners1 = new Transaction { Version = 0x00, Nonce = 0x01020304, Sender = UInt160.Zero, SystemFee = (long)BigInteger.Pow(10, 8), // 1 GAS NetworkFee = 0x0000000000000001, ValidUntilBlock = 0x01020304, Attributes = new TransactionAttribute[0] { }, Cosigners = cosigners1, // max + 1 (should fail) Script = new byte[] { (byte)OpCode.PUSH1 }, Witnesses = new Witness[0] { } }; byte[] sTx1 = txCosigners1.ToArray(); // back to transaction (should fail, due to non-distinct cosigners) Transaction tx1 = Trustlink.IO.Helper.AsSerializable <Transaction>(sTx1); Assert.IsNotNull(tx1); // ---------------------------- // this should fail (max + 1) var cosigners = new Cosigner[maxCosigners + 1]; for (var i = 0; i < maxCosigners + 1; i++) { string hex = i.ToString("X4"); while (hex.Length < 40) { hex = hex.Insert(0, "0"); } cosigners[i] = new Cosigner { Account = UInt160.Parse(hex) }; } Transaction txCosigners = new Transaction { Version = 0x00, Nonce = 0x01020304, Sender = UInt160.Zero, SystemFee = (long)BigInteger.Pow(10, 8), // 1 GAS NetworkFee = 0x0000000000000001, ValidUntilBlock = 0x01020304, Attributes = new TransactionAttribute[0] { }, Cosigners = cosigners, // max + 1 (should fail) Script = new byte[] { (byte)OpCode.PUSH1 }, Witnesses = new Witness[0] { } }; byte[] sTx2 = txCosigners.ToArray(); // back to transaction (should fail, due to non-distinct cosigners) Transaction tx2 = null; Assert.ThrowsException <FormatException>(() => tx2 = Trustlink.IO.Helper.AsSerializable <Transaction>(sTx2) ); Assert.IsNull(tx2); }
public DisbandingTxSignature GetDisbandingTxSignature(Cosigner cosigner, int input) { return(_disbandingTxSignatureRepo.Get(cosigner, input)); }
public Cosigner Add(Cosigner cosigner) { return(Add <Cosigner>(cosigner)); }
public DisbandingTxSignature Get(Cosigner cosigner, int utxoPos) { return(_context.DisbandingTxSignature.FirstOrDefault(x => x.AddressId == cosigner.AddressId && x.KeyOrder == cosigner.KeyOrder && x.UtxoPos == utxoPos)); }
public void FeeIsSignatureContract_TestScope_CurrentHash_NEO_GAS() { var wallet = TestUtils.GenerateTestWallet(); var snapshot = Blockchain.Singleton.GetSnapshot(); // no password on this wallet using (var unlock = wallet.Unlock("")) { var acc = wallet.CreateAccount(); // Fake balance var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem(new Nep5AccountState())); entry.GetInteroperable <Nep5AccountState>().Balance = 10000 * NativeContract.GAS.Factor; snapshot.Commit(); // Make transaction // Manually creating script byte[] script; using (ScriptBuilder sb = new ScriptBuilder()) { // self-transfer of 1e-8 GAS System.Numerics.BigInteger value = (new BigDecimal(1, 8)).Value; sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value); sb.Emit(OpCode.ASSERT); script = sb.ToArray(); } // trying two custom hashes, for same target account var cosigners = new Cosigner[] { new Cosigner { Account = acc.ScriptHash, Scopes = WitnessScope.CustomContracts, AllowedContracts = new[] { NativeContract.NEO.Hash, NativeContract.GAS.Hash } } }; // using this... var tx = wallet.MakeTransaction(script, acc.ScriptHash, cosigners); Assert.IsNotNull(tx); Assert.IsNull(tx.Witnesses); // ---- // Sign // ---- var data = new ContractParametersContext(tx); bool signed = wallet.Sign(data); Assert.IsTrue(signed); // get witnesses from signed 'data' tx.Witnesses = data.GetWitnesses(); // only a single witness should exist tx.Witnesses.Length.Should().Be(1); // no attributes must exist tx.Attributes.Length.Should().Be(1); // one cosigner must exist tx.Cosigners.Length.Should().Be(1); // Fast check Assert.IsTrue(tx.VerifyWitnesses(snapshot, tx.NetworkFee)); // Check long verificationGas = 0; foreach (var witness in tx.Witnesses) { using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false)) { engine.LoadScript(witness.VerificationScript); engine.LoadScript(witness.InvocationScript); Assert.AreEqual(VMState.HALT, engine.Execute()); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsTrue(engine.ResultStack.Pop().ToBoolean()); verificationGas += engine.GasConsumed; } } // get sizeGas var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); // final check on sum: verification_cost + tx_size Assert.AreEqual(1305390, verificationGas + sizeGas); // final assert Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas); } }
public void FeeIsSignatureContract_TestScope_Global_Default() { // Global is supposed to be default Cosigner cosigner = new Cosigner(); cosigner.Scopes.Should().Be(WitnessScope.Global); var wallet = TestUtils.GenerateTestWallet(); var snapshot = store.GetSnapshot(); // no password on this wallet using (var unlock = wallet.Unlock("")) { var acc = wallet.CreateAccount(); // Fake balance var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem { Value = new Nep5AccountState().ToByteArray() }); entry.Value = new Nep5AccountState() { Balance = 10000 * NativeContract.GAS.Factor } .ToByteArray(); // Make transaction // Manually creating script byte[] script; using (ScriptBuilder sb = new ScriptBuilder()) { // self-transfer of 1e-8 GAS System.Numerics.BigInteger value = (new BigDecimal(1, 8)).Value; sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value); sb.Emit(OpCode.THROWIFNOT); script = sb.ToArray(); } // default to global scope var cosigners = new Cosigner[] { new Cosigner { Account = acc.ScriptHash } }; // using this... var tx = wallet.MakeTransaction(script, acc.ScriptHash, new TransactionAttribute[0], cosigners); Assert.IsNotNull(tx); Assert.IsNull(tx.Witnesses); // ---- // Sign // ---- var data = new ContractParametersContext(tx); bool signed = wallet.Sign(data); Assert.IsTrue(signed); // get witnesses from signed 'data' tx.Witnesses = data.GetWitnesses(); tx.Witnesses.Length.Should().Be(1); // Fast check Assert.IsTrue(tx.VerifyWitnesses(snapshot, tx.NetworkFee)); // Check long verificationGas = 0; foreach (var witness in tx.Witnesses) { using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false)) { engine.LoadScript(witness.VerificationScript); engine.LoadScript(witness.InvocationScript); Assert.AreEqual(VMState.HALT, engine.Execute()); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsTrue(engine.ResultStack.Pop().GetBoolean()); verificationGas += engine.GasConsumed; } } // get sizeGas var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); // final check on sum: verification_cost + tx_size Assert.AreEqual(verificationGas + sizeGas, 1257240); // final assert Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas); } }
public void FeeIsSignatureContract_TestScope_CalledByEntry_Plus_GAS() { var wallet = TestUtils.GenerateTestWallet(); var snapshot = store.GetSnapshot(); // no password on this wallet using (var unlock = wallet.Unlock("")) { var acc = wallet.CreateAccount(); // Fake balance var key = NativeContract.GAS.CreateStorageKey(20, acc.ScriptHash); var entry = snapshot.Storages.GetAndChange(key, () => new StorageItem { Value = new Nep5AccountState().ToByteArray() }); entry.Value = new Nep5AccountState() { Balance = 10000 * NativeContract.GAS.Factor } .ToByteArray(); // Make transaction // Manually creating script byte[] script; using (ScriptBuilder sb = new ScriptBuilder()) { // self-transfer of 1e-8 GAS System.Numerics.BigInteger value = (new BigDecimal(1, 8)).Value; sb.EmitAppCall(NativeContract.GAS.Hash, "transfer", acc.ScriptHash, acc.ScriptHash, value); sb.Emit(OpCode.THROWIFNOT); script = sb.ToArray(); } // trying CalledByEntry together with GAS var cosigners = new Cosigner[] { new Cosigner { Account = acc.ScriptHash, // This combination is supposed to actually be an OR, // where it's valid in both Entry and also for Custom hash provided (in any execution level) // it would be better to test this in the future including situations where a deeper call level uses this custom witness successfully Scopes = WitnessScope.CustomContracts | WitnessScope.CalledByEntry, AllowedContracts = new[] { NativeContract.GAS.Hash } } }; // using this... var tx = wallet.MakeTransaction(script, acc.ScriptHash, new TransactionAttribute[0], cosigners); Assert.IsNotNull(tx); Assert.IsNull(tx.Witnesses); // ---- // Sign // ---- var data = new ContractParametersContext(tx); bool signed = wallet.Sign(data); Assert.IsTrue(signed); // get witnesses from signed 'data' tx.Witnesses = data.GetWitnesses(); tx.Witnesses.Length.Should().Be(1); // Fast check Assert.IsTrue(tx.VerifyWitnesses(snapshot, tx.NetworkFee)); // Check long verificationGas = 0; foreach (var witness in tx.Witnesses) { using (ApplicationEngine engine = new ApplicationEngine(TriggerType.Verification, tx, snapshot, tx.NetworkFee, false)) { engine.LoadScript(witness.VerificationScript); engine.LoadScript(witness.InvocationScript); Assert.AreEqual(VMState.HALT, engine.Execute()); Assert.AreEqual(1, engine.ResultStack.Count); Assert.IsTrue(engine.ResultStack.Pop().GetBoolean()); verificationGas += engine.GasConsumed; } } // get sizeGas var sizeGas = tx.Size * NativeContract.Policy.GetFeePerByte(snapshot); // final check on sum: verification_cost + tx_size Assert.AreEqual(verificationGas + sizeGas, 1278240); // final assert Assert.AreEqual(tx.NetworkFee, verificationGas + sizeGas); } }