Skip to content

Instantly share code, notes, and snippets.

@sipsorcery
Created July 7, 2019 19:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sipsorcery/9420892747104d72054e6504317d3b24 to your computer and use it in GitHub Desktop.
Save sipsorcery/9420892747104d72054e6504317d3b24 to your computer and use it in GitHub Desktop.
/*
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