Skip to content

Instantly share code, notes, and snippets.

@miguelmota
Last active July 29, 2019 06:33
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 miguelmota/8d2d0d1c010137eca271985a1cfaa67d to your computer and use it in GitHub Desktop.
Save miguelmota/8d2d0d1c010137eca271985a1cfaa67d to your computer and use it in GitHub Desktop.
{
"contractName": "Commits",
"abi": [
{
"constant": true,
"inputs": [
{
"name": "",
"type": "bytes20"
}
],
"name": "checkpoints",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "sender",
"type": "address"
},
{
"indexed": true,
"name": "commit",
"type": "bytes20"
}
],
"name": "Checkpointed",
"type": "event"
},
{
"constant": false,
"inputs": [
{
"components": [
{
"name": "tree",
"type": "string"
},
{
"name": "parents",
"type": "string[]"
},
{
"name": "author",
"type": "string"
},
{
"name": "authorDate",
"type": "uint256"
},
{
"name": "authorDateTzOffset",
"type": "string"
},
{
"name": "committer",
"type": "string"
},
{
"name": "commitDate",
"type": "uint256"
},
{
"name": "commitDateTzOffset",
"type": "string"
},
{
"name": "message",
"type": "string"
},
{
"name": "signature",
"type": "string"
}
],
"name": "_commit",
"type": "tuple"
}
],
"name": "checkpoint",
"outputs": [
{
"name": "commitHash",
"type": "bytes20"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "commit",
"type": "bytes20"
}
],
"name": "checkpointed",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "commit",
"type": "bytes20"
},
{
"name": "root",
"type": "bytes20"
},
{
"name": "leaf",
"type": "bytes20"
},
{
"name": "proof",
"type": "bytes20[]"
}
],
"name": "checkpointVerify",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "root",
"type": "bytes20"
},
{
"name": "leaf",
"type": "bytes20"
},
{
"name": "proof",
"type": "bytes20[]"
}
],
"name": "verify",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "pure",
"type": "function"
}
],
"compiler": {
"name": "solc",
"version": "0.5.8+commit.23d335f2.Emscripten.clang"
},
"networks": {
"42": {
"events": {},
"links": {},
"address": "0xBA7619DFA824A168fDD76a77b8236f83528d015C",
"transactionHash": "0x52554e323a127444d04e84b5f3712f2d168d2c325fc288b7ea4e6da2ebb725c2"
}
},
"schemaVersion": "3.0.11",
"updatedAt": "2019-07-28T10:46:05.506Z",
"devdoc": {
"methods": {}
},
"userdoc": {
"methods": {}
}
}
const assert = require('assert')
const fs = require('fs')
const path = require('path')
const { execSync } = require('child_process')
const Web3 = require('web3')
const PrivateKeyProvider = require('truffle-privatekey-provider')
const parseCommit = require('git-parse-commit')
const contractJSON = JSON.parse(fs.readFileSync(path.resolve(__dirname, './Commits.json')))
const { abi } = contractJSON
const networkId = 42 // kovan
const { address: contractAddress } = contractJSON.networks[networkId]
const privateKey = execSync('git config ethereumcheckpoint.privatekey').toString().trim()
const providerUri = execSync('git config ethereumcheckpoint.provideruri').toString().trim()
const provider = new PrivateKeyProvider(privateKey, providerUri)
const web3 = new Web3(provider)
;(async () => {
const { address: sender } = web3.eth.accounts.privateKeyToAccount(`0x${privateKey}`)
const commit = execSync('git cat-file -p HEAD').toString().trim()
const commitHash = execSync('git rev-parse HEAD').toString().trim()
const tag = execSync('git describe --tags `git rev-list --tags --max-count=1`').toString().trim()
const tagCommit = execSync(`git rev-list -n 1 "${tag}"`).toString().trim()
if (tagCommit !== commitHash) {
console.log('Tag not found for commit, skipping checkpoint.')
process.exit(0)
}
console.log(`Tag ${tag} found, checkpointing commit ${commitHash}`)
const {
tree,
parents,
author: {
name: authorName,
email: authorEmail,
timestamp: authorDate,
timezone: authorDateTzOffset
},
committer: {
name: committerName,
email: committerEmail,
timestamp: commitDate,
timezone: commitDateTzOffset
},
pgp,
title,
description
} = parseCommit(`${commitHash}\n${commit}`)
const author = `${authorName} <${authorEmail}>`
const committer = `${committerName} <${committerEmail}>`
const message = `${title}${description}
`
let signature = ''
if (pgp) {
// NOTE: newlines are necessary here
signature = `-----BEGIN PGP SIGNATURE-----
${pgp}
-----END PGP SIGNATURE-----`.split('\n').join('\n ') + '\n'
}
const data = {
tree,
parents,
author,
authorDate,
authorDateTzOffset,
committer,
commitDate,
commitDateTzOffset,
message,
signature
}
const contract = new web3.eth.Contract(abi, contractAddress)
try {
console.log('Checkpointing commit to Ethereum...')
const {
status,
transactionHash
} = await contract.methods.checkpoint(data).send({
from: sender
})
console.log(`Transaction hash: ${transactionHash}`)
assert.ok(status)
const _commitDate = await contract.methods.checkpoints(`0x${commitHash}`).call()
assert.equal(_commitDate.toString(), commitDate.toString())
console.log('Successfully checkpointed commit to Ethereum.')
process.exit(0)
} catch(err) {
console.error(err.message)
}
})()
{
"name": "ethereum-checkpoint-git-commit",
"version": "0.0.1",
"dependencies": {
"git-parse-commit": "^1.0.0",
"web3": "^1.2.0",
"truffle-privatekey-provider": "^1.3.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment