Skip to content

Commit

Permalink
block pkg: add Hash method (#185)
Browse files Browse the repository at this point in the history
* go mod tidy

* add .vscode to gitignore

* add GetHash method to Header (block pkg)

* go format

* GetHash returns a chainhash instead of byte[]

* add a testcase for testnet block header

* Header: Serialize + SerializeForHash methods

* GetHash --> Hash
  • Loading branch information
louisinger authored Nov 30, 2021
1 parent 2d0a253 commit 36be5ff
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 35 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@

# WebStorm IDE project config files
.idea

.vscode
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,9 @@ help:
test:
export API_URL=http://localhost:3001; \
export API_BTC_URL=http://localhost:3000; \
go test -count=1 -v ./...
go test -count=1 -v ./...

## fmt: Go Format
fmt:
@echo "Gofmt..."
@gofmt -w -l .
3 changes: 1 addition & 2 deletions block/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ const (

hashSize = 32

proofVersion = 536870912
dynaVersion = 2684354560
DYNAFED_HF_MASK = uint32(1 << 31)
)

type Block struct {
Expand Down
4 changes: 2 additions & 2 deletions block/deserialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ func DeserializeHeader(
return nil, err
}

isDyna := version>>31 == 1
isDyna := DYNAFED_HF_MASK&version != 0
if isDyna {
version &= 0x7fff_ffff
version &= ^DYNAFED_HF_MASK
}

prevBlockHash, err := d.ReadSlice(hashSize)
Expand Down
53 changes: 53 additions & 0 deletions block/hash_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package block

import (
"bytes"
"encoding/hex"
"encoding/json"
"io/ioutil"
"testing"
)

func TestBlockHash(t *testing.T) {
file, err := ioutil.ReadFile("testdata/hash.json")
if err != nil {
t.Fatal(err)
}

var tests []struct {
Name string `json:"name"`
BlockHeaderHex string `json:"blockHeaderHex"`
Hash string `json:"hash"`
}

err = json.Unmarshal(file, &tests)
if err != nil {
t.Fatal(err)
}

for _, v := range tests {
t.Run(v.Name, func(tt *testing.T) {

blockHeader, err := hex.DecodeString(v.BlockHeaderHex)
if err != nil {
tt.Fatal(err)
}

header, err := DeserializeHeader(bytes.NewBuffer(blockHeader))
if err != nil {
tt.Fatal(err)
}

hash, err := header.Hash()
if err != nil {
tt.Fatal(err)
}

hashHex := hash.String()

if hashHex != v.Hash {
tt.Errorf("hash: expected %s, got %s", v.Hash, hashHex)
}
})
}
}
103 changes: 76 additions & 27 deletions block/serialize.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package block

import (
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/vulpemventures/go-elements/internal/bufferutil"
)

Expand All @@ -10,7 +11,7 @@ func (b *Block) SerializeBlock() ([]byte, error) {
return nil, err
}

err = b.Header.SerializeHeader(s)
err = b.Header.serializeHeader(s, false)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -45,19 +46,18 @@ func (t *Transactions) SerializeTransactions(
return nil
}

func (h *Header) SerializeHeader(
func (h *Header) serializeHeader(
s *bufferutil.Serializer,
forHash bool,
) error {
version := h.Version
if h.ExtData.IsDyna {
err := s.WriteUint32(dynaVersion)
if err != nil {
return err
}
} else {
err := s.WriteUint32(proofVersion)
if err != nil {
return err
}
version |= DYNAFED_HF_MASK
}

err := s.WriteUint32(version)
if err != nil {
return err
}

if err := s.WriteSlice(h.PrevBlockHash); err != nil {
Expand All @@ -76,23 +76,66 @@ func (h *Header) SerializeHeader(
return err
}

if err := h.ExtData.serialize(s); err != nil {
if err := h.ExtData.serialize(s, forHash); err != nil {
return err
}

return nil
}

// SerializeForHash returns the block bytes for block hash
// it does not include some data of the block (like witness or solution in case of signed blocks)
func (h *Header) SerializeForHash() ([]byte, error) {
s, err := bufferutil.NewSerializer(nil)
if err != nil {
return nil, err
}

err = h.serializeHeader(s, true)
if err != nil {
return nil, err
}

return s.Bytes(), nil
}

// Serialize returns the block bytes
// includes all the data of the block
func (h *Header) Serialize() ([]byte, error) {
s, err := bufferutil.NewSerializer(nil)
if err != nil {
return nil, err
}

err = h.serializeHeader(s, false)
if err != nil {
return nil, err
}

return s.Bytes(), nil
}

// Hash gets the bytes with SerializeForHash and DoubleHash the bytes
func (h *Header) Hash() (chainhash.Hash, error) {
bytes, err := h.SerializeForHash()
if err != nil {
return chainhash.Hash{}, err
}

return chainhash.DoubleHashH(bytes), nil
}

func (e *ExtData) serialize(
s *bufferutil.Serializer,
forHash bool,
) error {
if e.IsDyna {
err := e.DynamicFederation.serialize(s)
err := e.DynamicFederation.serialize(s, forHash)
if err != nil {
return err
}
} else {
err := e.Proof.serialize(s)
err := e.Proof.serialize(s, forHash)
if err != nil {
return err
}
Expand All @@ -103,6 +146,7 @@ func (e *ExtData) serialize(

func (p *Proof) serialize(
s *bufferutil.Serializer,
forHash bool,
) error {
if err := s.WriteVarInt(uint64(len(p.Challenge))); err != nil {
return err
Expand All @@ -112,19 +156,22 @@ func (p *Proof) serialize(
return err
}

if err := s.WriteVarInt(uint64(len(p.Solution))); err != nil {
return err
}
if !forHash {
if err := s.WriteVarInt(uint64(len(p.Solution))); err != nil {
return err
}

if err := s.WriteSlice(p.Solution); err != nil {
return err
if err := s.WriteSlice(p.Solution); err != nil {
return err
}
}

return nil
}

func (d *DynamicFederation) serialize(
s *bufferutil.Serializer,
forHash bool,
) error {
if d.Current == nil {
if err := s.WriteUint8(null); err != nil {
Expand All @@ -146,17 +193,19 @@ func (d *DynamicFederation) serialize(
}
}

if err := s.WriteVarInt(uint64(len(d.SignBlockWitness))); err != nil {
return err
}

for i := 0; i < len(d.SignBlockWitness); i++ {
if err := s.WriteVarInt(uint64(len(d.SignBlockWitness[i]))); err != nil {
if !forHash {
if err := s.WriteVarInt(uint64(len(d.SignBlockWitness))); err != nil {
return err
}

if err := s.WriteSlice(d.SignBlockWitness[i]); err != nil {
return err
for i := 0; i < len(d.SignBlockWitness); i++ {
if err := s.WriteVarInt(uint64(len(d.SignBlockWitness[i]))); err != nil {
return err
}

if err := s.WriteSlice(d.SignBlockWitness[i]); err != nil {
return err
}
}
}

Expand Down
22 changes: 22 additions & 0 deletions block/testdata/hash.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[
{
"name": "regtest genesis block",
"blockHeaderHex": "0100000000000000000000000000000000000000000000000000000000000000000000002e4bf9e14086c32e38baa4fc6caf94ae73d189468d97153f131bc2489b1941bbdae5494d00000000015100",
"hash": "00902a6b70c2ca83b5d9c815d96a0e2f4202179316970d14ea1847dae5b1ca21"
},
{
"name": "liquid block #1594956",
"blockHeaderHex": "000000a002e54bf28071f3613047b9fea9ab2c84762edc156c71bb79ec321a16afda9999a68aadf4d319e14a483f82e8faf830ce05e08f26c91c3ea482f52f2b4a71d8a256fba4614c56180001220020e51211e91d9cf4aec3bdc370a0303acde5d24baedb12235fdd2786885069d91c880500007e755ded4e96bdcc0f5db0f6d21a46e3c91ab474f1a8c95a04ad3452e8600fff000d00483045022100b2bcad5542a907b154359881dc2e703546ed12adb5c9a02404897e8b152909d1022054857306497141cba1eaf815fec70f4fb63abb836245e9203fbbdee0b42123fc01483045022100a79f3e9e786b96f191ea02ad4b7bcc25f5218aef7537f1f5d83a79b686657a570220350e72574fe3e2272acf3b593b6f18318c594adb78960888447e8b46c28dbd0001473044022043424fd4511e7baba204ec2acfac336d6719a190122a937a689458165ed8859502203d14667b7df6b81aa70ad9082d371f1f66888305ec521fe797f6382356a29a0b01483045022100ed1ce0a0072bbdd1075cb9d30b99c892154a79690e910379cccc0e69ac674b0f022036b7325438e91bbd8c41425248fe26aa25d514ce4b375cee6c0318ed2e68e3f101483045022100c70c4bf23db0ca908811bbba6079b974120da71c32b8d51904c2012d6085acdc0220287cf223fa863263907d8359b8d80c4914c2cb41f6bae7d67e88f511304749cb0147304402206924ba6afbfc96b232c30eb634c6aae55950082b0b3029019dd1db791a47e4d4022044f3442d959355a0ab8d44629478eef8bc36ddc1cb23d9aec2e98dbe93cd6d9f01483045022100a437b5997b59bb935b960d1db864321fef33b160dd878cdcc1263fd3d8fc82ea02206a7b4e9461fc6cf78514d4885ca59ba4c01344ce3e601b03b94e7945d06c3f6401473044022007c8f2b7248f07cb958a9a46486d340d9b5ce64ec40fb43b303d38455d449ed30220787ca0802ebfa3fe5bcc01cbe839e79cf689d8c20a9be5116e893468d73a10a201473044022035d937c11eab9af89d41b8a25a5f6fceebf54ecc740c4e8323078d1ec3fbf5a70220012001594df99aef7082a757c5843db1a47e04b8c842c849c79b12144ede85a601473044022060dcf30cceffe435815a38997043eb046e3af61d17512ab47dc26fee8e4becca02202c94be595068df01ae8312acf459bed85b779b4b0008eedbf33104b4e939bd5901483045022100854cd4df74c6ff394c6291765bc8c1717d602fe97e7e07470da4d84f59736e300220743c7f7165a6c8ccb452173a2ad4b6b0198d0e2f8e20a5d46c915e8f74d5b83d01fd01025b21026a2a106ec32c8a1e8052e5d02a7b0a150423dbd9b116fc48d46630ff6e6a05b92102791646a8b49c2740352b4495c118d876347bf47d0551c01c4332fdc2df526f1a2102888bda53a424466b0451627df22090143bbf7c060e9eacb1e38426f6b07f2ae12102aee8967150dee220f613de3b239320355a498808084a93eaf39a34dcd62024852102d46e9259d0a0bb2bcbc461a3e68f34adca27b8d08fbe985853992b4b104e27412102e9944e35e5750ab621e098145b8e6cf373c273b7c04747d1aa020be0af40ccd62102f9a9d4b10a6d6c56d8c955c547330c589bb45e774551d46d415e51cd9ad5116321033b421566c124dfde4db9defe4084b7aa4e7f36744758d92806b8f72c2e943309210353dcc6b4cf6ad28aceb7f7b2db92a4bf07ac42d357adf756f3eca790664314b621037f55980af0455e4fb55aad9b85a55068bb6dc4740ea87276dc693f4598db45fa210384001daa88dabd23db878dbb1ce5b4c2a5fa72c3113e3514bf602325d0c37b8e21039056d089f2fe72dbc0a14780b4635b0dc8a1b40b7a59106325dd1bc45cc70493210397ab8ea7b0bf85bc7fc56bb27bf85e75502e94e76a6781c409f3f2ec3d1122192103b00e3b5b77884bf3cae204c4b4eac003601da75f96982ffcb3dcb29c5ee419b92103c1f3c0874cfe34b8131af34699589aacec4093399739ae352e8a46f80a6f68375fae",
"hash": "50c2303db2cd11213e357856e2d351bc6ab2a65b69b10643e082175c8c11e8a5"
},
{
"name": "liquid block #15994987",
"blockHeaderHex": "000000a09d08cb00c742c01cb05980eb3ec8f257b392230b8074dcb473f5b0ceee893d2ea13fdd6f4d4931e6de33e858ea58b8d1d6578e797657b6f74d5a463169ee1c7a9a02a5616b56180001220020e51211e91d9cf4aec3bdc370a0303acde5d24baedb12235fdd2786885069d91c880500007e755ded4e96bdcc0f5db0f6d21a46e3c91ab474f1a8c95a04ad3452e8600fff000d0048304502210080fa223bb9e0c3c939a467b3f5e81d5d153a94da9c75d5fceb2f7901b0ab9d920220338da3f8a5dddb7016fba0ed08430e4ba61dc3c45a49ec94234cdc7a3e5d4f490148304502210087c4e2228fa27ebc5d3c0fd8bc92da02c22a4035196fbab92ddebee7eee8d46e0220386bd4dd792bd18a48c9787759fba9886c2dceeeb65578242f9263701205e366014730440220463ea51b3c3015a1b175456ad1abe07bbaae49d714b4f5b4d19a73756053cf98022010d3d14958e134e733c9612f30a2f53b90f08ce763ef8923222204a2fc35402601473044022044dff40f53fc056b60153ae1d83e9f8f96e1e20071562a26d417fc776264bac102203d6847018873f8b5a47da3592caa4eadf3735cb8d77aa9e3839cdf15e70d9ae2014730440220284876935b0da56022340fbae6034ffbb2cc8d52ac34c249b5d88521709d37480220446c8f2a5061cd8d5d982505898fa0ff4b4226a190bc810fc2e97a91c7bd4f8a01473044022067caacacd92c34509ca55c37a06a9ff419fe74697fb46a9702f516afd7ce530602200913d379b9a133ba9c50bdf9a536e96eaf204f7f0d33ed708aa90b4a0e34f4500147304402205c7ee346620047810f4b8be7e2d3b6dfd30eea0a4d438b0a9faf855de2b34bc1022016a4f33275ba32ff3d8059c14050b99e9ed96e7b089ac684a6b40ef002986357014730440220602ef00ddd12a66d38ce294b8f484c1958dcdf5039e24b046b9b5f763919f1b902207375a4fce037a852c18b06c933b1e5adeabcee3fbddd40c5c01267d771c411c901473044022057a679242e1aca3a3a7875acd2211240f49186eef57af98673bf11e82aef22b002207ea9bb1d566701362509e826fff6b34094f64cd9423060e9d0d32cbce54c2c8b0148304502210094707c5d4420101a7c29e11b090492138f3150b62fa53fec1733c8eb4281d3650220697a741b19f2900f897a766dda16f2fe196579b9394bd099c905d246b91b30a30147304402202d58d736afabb41154826b0e527c313c83bea18d61fe11e3c0f9047536e194f3022033f465824d3e5de22df9229fd52420bce0aa1674a0f985c0a3937d1ff80397b301fd01025b21026a2a106ec32c8a1e8052e5d02a7b0a150423dbd9b116fc48d46630ff6e6a05b92102791646a8b49c2740352b4495c118d876347bf47d0551c01c4332fdc2df526f1a2102888bda53a424466b0451627df22090143bbf7c060e9eacb1e38426f6b07f2ae12102aee8967150dee220f613de3b239320355a498808084a93eaf39a34dcd62024852102d46e9259d0a0bb2bcbc461a3e68f34adca27b8d08fbe985853992b4b104e27412102e9944e35e5750ab621e098145b8e6cf373c273b7c04747d1aa020be0af40ccd62102f9a9d4b10a6d6c56d8c955c547330c589bb45e774551d46d415e51cd9ad5116321033b421566c124dfde4db9defe4084b7aa4e7f36744758d92806b8f72c2e943309210353dcc6b4cf6ad28aceb7f7b2db92a4bf07ac42d357adf756f3eca790664314b621037f55980af0455e4fb55aad9b85a55068bb6dc4740ea87276dc693f4598db45fa210384001daa88dabd23db878dbb1ce5b4c2a5fa72c3113e3514bf602325d0c37b8e21039056d089f2fe72dbc0a14780b4635b0dc8a1b40b7a59106325dd1bc45cc70493210397ab8ea7b0bf85bc7fc56bb27bf85e75502e94e76a6781c409f3f2ec3d1122192103b00e3b5b77884bf3cae204c4b4eac003601da75f96982ffcb3dcb29c5ee419b92103c1f3c0874cfe34b8131af34699589aacec4093399739ae352e8a46f80a6f68375fae",
"hash": "59dfa0c8a9420d7e79795d65eda09972dc1cbe9eb24f7639222b2f655fc999d6"
},
{
"name": "liquid testnet block #106432",
"blockHeaderHex": "000000a08619ccdad6d1e95d515cdd3a4bc5098950aaf4c63b435ece4774d436f14b16c34de83159b4cb356028a3ba0799316b6ba82229c8d7920040826fa9c82b88b74108d3a561c09f010001220020e9e4117540f7f23b3edd7c2cad660a17fb33c7959b8c37cf61d92b189133929a96000000fbee9cea00d8efdc49cfbec328537e0d7032194de6ebf3cf42e5c05bb89a08b100030047304402207b7632bd61e4bf2071486938e74fcd855bd56941ddfaad43faabd2bae7940c3f02201fbe57eefeee9f8e5f24ec197f303cf1f3d06c2e5582056d2d948163203a3cef012551210217e403ddb181872c32a0cd468c710040b2f53d8cac69f18dad07985ee37e9a7151ae",
"hash": "5a19865c9200fbde2974c62e2be9a2c4a562945ec2925505c53262fdb0814a04"
}
]
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ require (
github.com/btcsuite/btcutil/psbt v1.0.2
github.com/stretchr/testify v1.7.0
github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941
github.com/vulpemventures/go-secp256k1-zkp v1.1.3
github.com/vulpemventures/go-secp256k1-zkp v1.1.5
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
)
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941 h1:CTcw80hz/Sw8hqlKX5ZYvBUF5gAHSHwdjXxRf/cjDcI=
github.com/vulpemventures/fastsha256 v0.0.0-20160815193821-637e65642941/go.mod h1:GXBJykxW2kUcktGdsgyay7uwwWvkljASfljNcT0mbh8=
github.com/vulpemventures/go-secp256k1-zkp v1.1.3 h1:Jy/OxkPYJYIFrwJkXr5vk86h9ObpqLR+3L5KHWX7Ah0=
github.com/vulpemventures/go-secp256k1-zkp v1.1.3/go.mod h1:zo7CpgkuPgoe7fAV+inyxsI9IhGmcoFgyD8nqZaPSOM=
github.com/vulpemventures/go-secp256k1-zkp v1.1.5 h1:oG1kO8ibVQ1wOvYcnFyuI+2YqnEZluXdRwkOPJlHBQM=
github.com/vulpemventures/go-secp256k1-zkp v1.1.5/go.mod h1:zo7CpgkuPgoe7fAV+inyxsI9IhGmcoFgyD8nqZaPSOM=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
Expand Down

0 comments on commit 36be5ff

Please sign in to comment.