public void BasicSigningETC() { var nonce = 9.ToBytesForRLPEncoding(); var gasPrice = BigInteger.Parse("20" + "000" + "000" + "000").ToBytesForRLPEncoding(); var gasLimit = 21000.ToBytesForRLPEncoding(); var to = "0x3535353535353535353535353535353535353535".HexToByteArray(); var amount = BigInteger.Parse("1" + "000" + "000" + "000" + "000" + "000" + "000").ToBytesForRLPEncoding(); var data = "".HexToByteArray(); var chainId = ((int)Chain.ClassicMainNet).ToBytesForRLPEncoding(); //Create a transaction from scratch var tx = new TransactionChainId(nonce, gasPrice, gasLimit, to, amount, data, chainId); var privateKey = "4646464646464646464646464646464646464646464646464646464646464646"; var key = new EthECKey(privateKey); tx.Sign(key); var recoveryTransaction = new TransactionChainId(tx.GetRLPEncoded()); Assert.True(recoveryTransaction.Key.VerifyAllowingOnlyLowS(recoveryTransaction.RawHash, recoveryTransaction.Signature)); Assert.Equal(key.GetPublicAddress(), recoveryTransaction.Key.GetPublicAddress()); }
// ported from the main example in the spec: // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md // Modified from the original pull request of Andres Aragoneses @Knocte public void BasicSigning() { var nonce = 9.ToBytesForRLPEncoding(); var gasPrice = BigInteger.Parse("20" + "000" + "000" + "000").ToBytesForRLPEncoding(); var gasLimit = 21000.ToBytesForRLPEncoding(); var to = "0x3535353535353535353535353535353535353535".HexToByteArray(); var amount = BigInteger.Parse("1" + "000" + "000" + "000" + "000" + "000" + "000").ToBytesForRLPEncoding(); var data = "".HexToByteArray(); byte[] ZERO_BYTE_ARRAY = 0.ToBytesForRLPEncoding(); var chain = 1; var chainId = ((int)chain).ToBytesForRLPEncoding(); //Create a transaction from scratch var tx = new TransactionChainId(nonce, gasPrice, gasLimit, to, amount, data, chainId); Assert.Equal(chainId, tx.ChainId); Assert.Equal(ZERO_BYTE_ARRAY, tx.RHash); Assert.Equal(ZERO_BYTE_ARRAY, tx.SHash); var expectedSigningData = "ec098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a764000080018080"; Assert.Equal(expectedSigningData, tx.GetRLPEncodedRaw().ToHex()); var expectedSigningHash = "daf5a779ae972f972197303d7b574746c7ef83eadac0f2791ad23db92e4c8e53"; Assert.Equal(expectedSigningHash, tx.RawHash.ToHex()); var privateKey = "4646464646464646464646464646464646464646464646464646464646464646"; var key = new EthECKey(privateKey); tx.Sign(key); var rFromSignature = tx.Signature.R.ToBigIntegerFromRLPDecoded(); var expectedRFromSignature = "18515461264373351373200002665853028612451056578545711640558177340181847433846"; Assert.Equal(expectedRFromSignature, rFromSignature.ToString()); var sFromSignature = tx.Signature.S.ToBigIntegerFromRLPDecoded(); var expectedSFromSignature = "46948507304638947509940763649030358759909902576025900602547168820602576006531"; Assert.Equal(expectedSFromSignature, sFromSignature.ToString()); byte[] vFromSignature = tx.Signature.V; Assert.Equal(37, vFromSignature.ToIntFromRLPDecoded()); var expectedSignedTx = "f86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83"; Assert.Equal(expectedSignedTx.Length, tx.GetRLPEncoded().ToHex().Length); Assert.Equal(expectedSignedTx, tx.GetRLPEncoded().ToHex()); var recoveryTransaction = new TransactionChainId(tx.GetRLPEncoded(), 1); Assert.True(recoveryTransaction.Key.VerifyAllowingOnlyLowS(recoveryTransaction.RawHash, recoveryTransaction.Signature)); Assert.Equal(key.GetPublicAddress(), recoveryTransaction.Key.GetPublicAddress()); }
/// <summary> /// Signs a transaction using this IWallet. /// </summary> /// <typeparam name="T"> The type of the popup to display the transaction confirmation for. </typeparam> /// <param name="onTransactionSigned"> The action to call if the transaction is confirmed and signed. </param> /// <param name="gasLimit"> The gas limit to use with the transaction. </param> /// <param name="gasPrice"> The gas price to use with the transaction. </param> /// <param name="value"> The amount of ether in wei being sent along with the transaction. </param> /// <param name="addressFrom"> The address of the wallet signing the transaction. </param> /// <param name="addressTo"> The address the transaction is being sent to. </param> /// <param name="data"> The data sent along with the transaction. </param> /// <param name="path"> The path of the wallet to sign the transaction with. </param> /// <param name="displayInput"> The display input that goes along with the transaction request. </param> public void SignTransaction <T>( Action <TransactionSignedUnityRequest> onTransactionSigned, BigInteger gasLimit, BigInteger gasPrice, BigInteger value, string addressFrom, string addressTo, string data, string path, params object[] displayInput) where T : ConfirmTransactionPopupBase <T> { if (signingTransaction) { return; } signingTransaction = true; TransactionUtils.GetAddressTransactionCount(addressFrom).OnSuccess(async txCount => { var currentPopupType = popupManager.ActivePopupType; var transaction = new Transaction( txCount.ToBytesForRLPEncoding(), gasPrice.ToBytesForRLPEncoding(), gasLimit.ToBytesForRLPEncoding(), addressTo.HexToByteArray(), value.ToBytesForRLPEncoding(), data.HexToByteArray(), new byte[] { 0 }, new byte[] { 0 }, (byte)ethereumNetworkSettings.networkType); var signedTransactionData = await GetSignedTransactionData( transaction, path, () => MainThreadExecutor.QueueAction(() => popupManager.GetPopup <T>(true)?.SetConfirmationValues(null, gasLimit, gasPrice, displayInput))).ConfigureAwait(false); signingTransaction = false; if (signedTransactionData == null) { return; } else if (!signedTransactionData.signed) { if (currentPopupType != popupManager.ActivePopupType) { MainThreadExecutor.QueueAction(() => popupManager.CloseActivePopup()); } return; } var transactionChainId = new TransactionChainId( transaction.Nonce, transaction.GasPrice, transaction.GasLimit, transaction.ReceiveAddress, transaction.Value, transaction.Data, new byte[] { (byte)ethereumNetworkSettings.networkType }, signedTransactionData.r, signedTransactionData.s, new byte[] { (byte)signedTransactionData.v }); MainThreadExecutor.QueueAction(() => { onTransactionSigned?.Invoke(new TransactionSignedUnityRequest(transactionChainId.GetRLPEncoded().ToHex(), ethereumNetworkManager.CurrentNetwork.NetworkUrl)); popupManager.CloseAllPopups(); }); }); }