Created
July 7, 2019 19:57
-
-
Save sipsorcery/9420892747104d72054e6504317d3b24 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
protogen.bat: | |
protoc ^ | |
--csharp_out=. ^ | |
--proto_path=c:\dev\github\libra\types\src\proto ^ | |
--proto_path=c:\dev\github\libra\admission_control\admission_control_proto\src\proto ^ | |
--proto_path=C:\Dev\github\libra\mempool\src\proto ^ | |
--proto_path=C:\Dev\github\libra\mempool\src\proto\shared ^ | |
--proto_path=C:\Dev\github\libra\common\debug_interface\src\proto ^ | |
--proto_path=C:\Dev\github\libra\crypto\secret_service\src\proto ^ | |
access_path.proto ^ | |
account_state_blob.proto ^ | |
events.proto ^ | |
get_with_proof.proto ^ | |
language_storage.proto ^ | |
ledger_info.proto ^ | |
proof.proto ^ | |
transaction.proto ^ | |
transaction_info.proto ^ | |
validator_change.proto ^ | |
validator_public_keys.proto ^ | |
validator_set.proto ^ | |
vm_errors.proto ^ | |
admission_control.proto ^ | |
mempool_status.proto ^ | |
node_debug_interface.proto ^ | |
secret_service.proto | |
grpc.bat: | |
protoc ^ | |
--grpc_out=. ^ | |
--plugin=protoc-gen-grpc=grpc_csharp_plugin.exe ^ | |
--proto_path=c:\dev\github\libra\types\src\proto ^ | |
--proto_path=c:\dev\github\libra\admission_control\admission_control_proto\src\proto ^ | |
--proto_path=C:\Dev\github\libra\mempool\src\proto ^ | |
--proto_path=C:\Dev\github\libra\mempool\src\proto\shared ^ | |
--proto_path=C:\Dev\github\libra\common\debug_interface\src\proto ^ | |
--proto_path=C:\Dev\github\libra\crypto\secret_service\src\proto ^ | |
node_debug_interface.proto ^ | |
admission_control.proto ^ | |
secret_service.proto | |
nuget packages: | |
<ItemGroup> | |
<PackageReference Include="Google.Protobuf" Version="3.8.0" /> | |
<PackageReference Include="Google.Protobuf.Tools" Version="3.8.0" /> | |
<PackageReference Include="Grpc" Version="1.21.0" /> | |
<PackageReference Include="Grpc.Core" Version="1.21.0" /> | |
<PackageReference Include="Grpc.Tools" Version="1.21.0"> | |
<PrivateAssets>all</PrivateAssets> | |
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | |
</PackageReference> | |
<PackageReference Include="NBitcoin" Version="4.1.2.36" /> | |
<PackageReference Include="NSec.Cryptography" Version="19.5.0" /> | |
<PackageReference Include="SHA3.Net" Version="1.1.1" /> | |
</ItemGroup> | |
*/ | |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Net; | |
using System.Security.Cryptography; | |
using System.Text; | |
using System.Threading.Tasks; | |
using Google.Protobuf; | |
using Grpc.Core; | |
using NBitcoin.DataEncoders; | |
using NSec.Cryptography; | |
using SHA3.Net; | |
namespace LibraTestConsole | |
{ | |
class Program | |
{ | |
const string LIBRA_HASH_SUFFIX = "@@$$LIBRA$$@@"; | |
const string RAWTX_HASH_SALT = "RawTransaction"; | |
const string SIGNEDTX_HASH_SALT = "SignedTransaction"; | |
static void Main(string[] args) | |
{ | |
try | |
{ | |
HexEncoder hex = new HexEncoder(); | |
SharedSecret sharedSecret = SharedSecret.Import(Encoding.UTF8.GetBytes("dummy")); | |
HkdfSha512 kdf = new HkdfSha512(); | |
var key = kdf.DeriveKey(sharedSecret, null, null, Ed25519.Ed25519); | |
var sender = key.PublicKey.Export(KeyBlobFormat.RawPublicKey); | |
//Console.WriteLine($"Public Key {hex.EncodeData(sender)}."); | |
Channel channel = new Channel("ac.testnet.libra.org:8000", ChannelCredentials.Insecure); | |
//Channel channel = new Channel("127.0.0.1:8000", ChannelCredentials.Insecure); | |
var client = new AdmissionControl.AdmissionControl.AdmissionControlClient(channel); | |
UInt64 seqNum = 14; | |
string senderHex = hex.EncodeData(Sha3.Sha3256().ComputeHash(sender)); | |
Console.WriteLine($"Sender {senderHex}."); | |
var rawTx = CreateRawTx(senderHex, seqNum, "9c147f48c31695955d78955766eb796ff300bc438b1ce79e465672fad09ca8cb", 0xffffUL, 10000UL, 0, 0UL); | |
Console.WriteLine($"RawTx: {Convert.ToBase64String(rawTx.ToByteArray())}"); | |
Types.SignedTransaction signedTx = new Types.SignedTransaction(); | |
signedTx.SenderPublicKey = Google.Protobuf.ByteString.CopyFrom(sender); | |
signedTx.RawTxnBytes = rawTx.ToByteString(); | |
var seed = Encoding.ASCII.GetBytes(RAWTX_HASH_SALT + LIBRA_HASH_SUFFIX); | |
var seedHash = Sha3.Sha3256().ComputeHash(seed); | |
List<byte> hashInput = new List<byte>(); | |
hashInput.AddRange(seedHash); | |
hashInput.AddRange(signedTx.RawTxnBytes.ToArray()); | |
var hash = Sha3.Sha3256().ComputeHash(hashInput.ToArray()); | |
//Console.WriteLine($"Hash input {hex.EncodeData(hashInput.ToArray())}"); | |
Console.WriteLine($"Raw tx hash {hex.EncodeData(hash)}."); | |
var sig = NSec.Cryptography.Ed25519.Ed25519.Sign(key, hash); | |
signedTx.SenderSignature = Google.Protobuf.ByteString.CopyFrom(sig); | |
Console.WriteLine($"Signature {hex.EncodeData(sig)}."); | |
AdmissionControl.SubmitTransactionRequest submitTxReq = new AdmissionControl.SubmitTransactionRequest(); | |
submitTxReq.SignedTxn = signedTx; | |
Console.WriteLine($"Submitting signed tx for {senderHex} and seqnum {seqNum}."); | |
var reply = client.SubmitTransaction(submitTxReq); | |
Console.WriteLine($"Reply AcStatus {reply.AcStatus}."); | |
Task.Delay(5000).Wait(); | |
GetTransaction(client, senderHex, seqNum); | |
} | |
catch (Exception excp) | |
{ | |
Console.WriteLine($"Exception Main. {excp.Message}"); | |
} | |
} | |
private static Types.RawTransaction CreateRawTx(string senderHex, UInt64 seqNum, string receipientHex, UInt64 recipientAmount, UInt64 maxGasAmount, UInt64 maxGasUnitPrice, UInt64 expirationTime) | |
{ | |
HexEncoder hex = new HexEncoder(); | |
Types.RawTransaction rawTx = new Types.RawTransaction(); | |
rawTx.SenderAccount = Google.Protobuf.ByteString.CopyFrom(hex.DecodeData(senderHex)); | |
rawTx.SequenceNumber = seqNum; | |
rawTx.Program = new Types.Program(); | |
rawTx.Program.Code = Google.Protobuf.ByteString.CopyFrom(Convert.FromBase64String("TElCUkFWTQoBAAcBSgAAAAQAAAADTgAAAAYAAAAMVAAAAAUAAAANWQAAAAQAAAAFXQAAACkAAAAEhgAAACAAAAAHpgAAAA0AAAAAAAABAAIAAQMAAgACBAIDAgQCBjxTRUxGPgxMaWJyYUFjY291bnQEbWFpbg9wYXlfZnJvbV9zZW5kZXIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgAEAAwADAERAQI=")); | |
var recipientArg = new Types.TransactionArgument { Type = Types.TransactionArgument.Types.ArgType.Address }; | |
recipientArg.Data = Google.Protobuf.ByteString.CopyFrom(hex.DecodeData(receipientHex)); | |
rawTx.Program.Arguments.Add(recipientArg); | |
var amountArg = new Types.TransactionArgument { Type = Types.TransactionArgument.Types.ArgType.U64 }; | |
amountArg.Data = Google.Protobuf.ByteString.CopyFrom(BitConverter.GetBytes(recipientAmount)); | |
rawTx.Program.Arguments.Add(amountArg); | |
rawTx.MaxGasAmount = maxGasAmount; | |
rawTx.GasUnitPrice = maxGasUnitPrice; | |
rawTx.ExpirationTime = expirationTime; | |
return rawTx; | |
} | |
private static void GetTransaction(AdmissionControl.AdmissionControl.AdmissionControlClient client, string accountHex, UInt64 seqNum) | |
{ | |
Console.WriteLine($"GetTransaction for {accountHex} and seqnum {seqNum}."); | |
HexEncoder hex = new HexEncoder(); | |
Types.UpdateToLatestLedgerRequest updToLatestLedgerReq = new Types.UpdateToLatestLedgerRequest(); | |
var getTxReq = new Types.GetAccountTransactionBySequenceNumberRequest(); | |
getTxReq.SequenceNumber = seqNum; | |
getTxReq.Account = Google.Protobuf.ByteString.CopyFrom(hex.DecodeData(accountHex)); | |
Types.RequestItem reqItem = new Types.RequestItem(); | |
reqItem.GetAccountTransactionBySequenceNumberRequest = getTxReq; | |
updToLatestLedgerReq.RequestedItems.Add(reqItem); | |
var reply = client.UpdateToLatestLedger(updToLatestLedgerReq); | |
if (reply?.ResponseItems?.Count == 1) | |
{ | |
var resp = reply.ResponseItems[0].GetAccountTransactionBySequenceNumberResponse; | |
if (resp.SignedTransactionWithProof == null) | |
{ | |
Console.WriteLine("GetTransaction request did not return a signed transaction."); | |
} | |
else | |
{ | |
var signedTx = resp.SignedTransactionWithProof; | |
Console.WriteLine($"Sender {hex.EncodeData(signedTx.SignedTransaction.SenderPublicKey.ToByteArray())}."); | |
Console.WriteLine($"RawTxnBytes {hex.EncodeData(signedTx.SignedTransaction.RawTxnBytes.ToByteArray())}"); | |
Types.RawTransaction rawTx = Types.RawTransaction.Parser.ParseFrom(signedTx.SignedTransaction.RawTxnBytes); | |
Console.WriteLine($"SequenceNumber {rawTx.SequenceNumber}."); | |
Console.WriteLine($"MaxGasAmount {rawTx.MaxGasAmount}."); | |
Console.WriteLine($"GasUnitPrice {rawTx.GasUnitPrice}."); | |
Console.WriteLine($"ExpirationTime {rawTx.ExpirationTime}."); | |
var byteCode = rawTx.Program.Code.ToByteArray(); | |
SHA512 sha512 = SHA512.Create(); | |
var byteCodeHash = hex.EncodeData(sha512.ComputeHash(byteCode)); | |
Console.WriteLine($"Program.Code hash {byteCodeHash}."); | |
} | |
} | |
else | |
{ | |
Console.WriteLine("GetTransaction did not return a result."); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment