Skip to content

Instantly share code, notes, and snippets.

@arberiii
Created March 11, 2020 10:52
Show Gist options
  • Save arberiii/de7533c12a54a00314b5c93b37758e79 to your computer and use it in GitHub Desktop.
Save arberiii/de7533c12a54a00314b5c93b37758e79 to your computer and use it in GitHub Desktop.
Verify witness_signature of a block header of Tron block

Block header of Tron block number 200 is

{
	"blockID": "00000000000000c82a54a3bbdc956e1ddebc903f29b8daf28505b56f55a3f87d",
	"block_header": {
		"raw_data": {
			"number": 200,
			"txTrieRoot": "0000000000000000000000000000000000000000000000000000000000000000",
			"witness_address": "411661f25387370c9cd3a9a5d97e60ca90f4844e7e",
			"parentHash": "00000000000000c7c8f27726916dfddca3c1c3481eb01da8a08938263674cea4",
			"timestamp": 1529892138000
		},
		"witness_signature": "691e9116963b54ef7eb07692266319b029217e4d4ae8e8cb97e341617460f3822eff149c690aac6f2e0ad27d0af4fa8824d113d7a71c091245f778438ca4bde801"
	}
}

If you want to verify the signature in Solidity first run the main.go, which serialize block header and finds its raw hash. Then copy the result from the go program and make a call to contract to validate function with parameters hash=raw hash from go program ,signature is the same as witness_signature and witness_address is the same as in block header but without the first two bytes(41) because this is not part of address(it only tells which network). In Remix ide you can call with these parameters: 0x9df34ad7b14739e82a54a3bbdc956e1ddebc903f29b8daf28505b56f55a3f87d, 0x691e9116963b54ef7eb07692266319b029217e4d4ae8e8cb97e341617460f3822eff149c690aac6f2e0ad27d0af4fa8824d113d7a71c091245f778438ca4bde801, 0x1661f25387370c9cd3a9a5d97e60ca90f4844e7e

package main
import (
"crypto/sha256"
"fmt"
"log"
"github.com/tronprotocol/tron-demo/demo/go-client-api/common/hexutil"
"github.com/gogo/protobuf/proto"
"github.com/sasaxie/go-client-api/service"
)
func main() {
// connect to some grpc client
client := service.NewGrpcClient("grpc.trongrid.io:50051")
client.Start()
defer client.Conn.Close()
block := client.GetBlockByNum(200)
// serialize block header
b, err := proto.Marshal(block.BlockHeader.RawData)
if err != nil {
log.Fatal(err)
}
// hash the raw data
hash := sha256.Sum256(b[:])
// hex encode
fmt.Printf("block hash: %v\n", hexutil.Encode(hash[:]))
}
pragma solidity >=0.4.24 <0.7.0;
contract VerifyTronSignature {
//return the address according to the signature and and the data
function validate(bytes32 hash, bytes memory signature, address witness_addr) public {
bytes memory signedString = signature;
bytes32 r = convertToBytes32(slice(signedString, 0, 32));
bytes32 s = convertToBytes32(slice(signedString, 32, 32));
byte v1 = slice(signedString, 64, 1)[0];
uint8 v = uint8(v1)+27;
require(ecrecover(hash, v, r, s) == witness_addr);
}
//slice function
function slice(bytes memory data, uint start, uint len) public returns (bytes memory){
bytes memory b = new bytes(len);
for(uint i = 0; i < len; i++){
b[i] = data[i + start];
}
return b;
}
//convert bytes to bytes32
function convertToBytes32(bytes memory source) public returns (bytes32 result) {
assembly {
result := mload(add(source, 32))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment