public void Test_External_Signature2() { var crypto = CryptoProvider.GetCrypto(); var rawTx = "0xf86d808504a817c800832dc6c0948e7b7262e0fa4616566591d51f998f16a79fb547880de0b6b3a76400008025a0115105d96a43f41a5ea562bb3e591cbfa431a8cdae9c3030457adca2cb854f78a012fb41922c53c73473563003667ed8e783359c91d95b42301e1955d530b1ca33"; var ethTx = new TransactionChainId(rawTx.HexToBytes()); Console.WriteLine("ETH RLP: " + ethTx.GetRLPEncodedRaw().ToHex()); var nonce = ethTx.Nonce.ToHex(); Console.WriteLine("Nonce " + nonce); Console.WriteLine("ChainId " + Convert.ToUInt64(ethTx.ChainId.ToHex(), 16)); var tx = new Transaction { To = ethTx.ReceiveAddress.ToUInt160(), Value = ethTx.Value.ToUInt256(true), Nonce = Convert.ToUInt64(ethTx.Nonce.ToHex(), 16), GasPrice = Convert.ToUInt64(ethTx.GasPrice.ToHex(), 16), GasLimit = Convert.ToUInt64(ethTx.GasLimit.ToHex(), 16) }; Console.WriteLine("RLP: " + tx.Rlp(true).ToHex()); var address = ethTx.Key.GetPublicAddress().HexToBytes(); var from = ethTx.Key.GetPublicAddress().HexToBytes().ToUInt160(); Console.WriteLine(address.ToHex()); var r = "0x115105d96a43f41a5ea562bb3e591cbfa431a8cdae9c3030457adca2cb854f78".HexToBytes(); var s = "0x12fb41922c53c73473563003667ed8e783359c91d95b42301e1955d530b1ca33".HexToBytes(); var v = "0x25".HexToBytes(); var signature = r.Concat(s).Concat(v).ToArray(); Console.WriteLine(signature.ToHex()); var message = "0xed808504a817c800832dc6c0948e7b7262e0fa4616566591d51f998f16a79fb547880de0b6b3a764000080018080" .HexToBytes().KeccakBytes(); var recoveredPubkey = crypto.RecoverSignatureHashed(message, signature, false); Console.WriteLine(recoveredPubkey.ToHex()); var addr = crypto.ComputeAddress(recoveredPubkey); var same = addr.SequenceEqual(from.ToBytes()); Console.WriteLine(addr.ToHex()); Console.WriteLine(same); }
// 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()); }