nef: change checksum calculation scheme

It's now being calculated for whole file, not just header.
This commit is contained in:
Roman Khimov 2020-11-27 19:33:36 +03:00
parent d93aa745bb
commit e12c52f588
5 changed files with 21 additions and 22 deletions

Binary file not shown.

View file

@ -57,7 +57,7 @@ type rpcTestCase struct {
} }
const testContractHash = "743ed26f78e29ecd595535b74a943b1f9ccbc444" const testContractHash = "743ed26f78e29ecd595535b74a943b1f9ccbc444"
const deploymentTxHash = "f4abbf6a5af7b79819378cce1576dd72663a95961010383d67d8c4e1f00fac02" const deploymentTxHash = "3f81bc99525ed4b1cbb4a3535feadf73176db646a2879aaf975737348a425edc"
const genesisBlockHash = "a496577895eb8c227bb866dc44f99f21c0cf06417ca8f2a877cc5d761a50dac0" const genesisBlockHash = "a496577895eb8c227bb866dc44f99f21c0cf06417ca8f2a877cc5d761a50dac0"
const verifyContractHash = "a2eb22340979804cb10cc1add0b8822c201f4d8a" const verifyContractHash = "a2eb22340979804cb10cc1add0b8822c201f4d8a"

Binary file not shown.

View file

@ -23,10 +23,10 @@ import (
// | Compiler | 32 bytes | Compiler used | // | Compiler | 32 bytes | Compiler used |
// | Version | 16 bytes | Compiler version (Major, Minor, Build, Version) | // | Version | 16 bytes | Compiler version (Major, Minor, Build, Version) |
// +------------+-----------+------------------------------------------------------------+ // +------------+-----------+------------------------------------------------------------+
// | Checksum | 4 bytes | First four bytes of double SHA256 hash of the header |
// +------------+-----------+------------------------------------------------------------+
// | Script | Var bytes | Var bytes for the payload | // | Script | Var bytes | Var bytes for the payload |
// +------------+-----------+------------------------------------------------------------+ // +------------+-----------+------------------------------------------------------------+
// | Checksum | 4 bytes | First four bytes of double SHA256 hash of the header |
// +------------+-----------+------------------------------------------------------------+
const ( const (
// Magic is a magic File header constant. // Magic is a magic File header constant.
@ -40,8 +40,8 @@ const (
// File represents compiled contract file structure according to the NEF3 standard. // File represents compiled contract file structure according to the NEF3 standard.
type File struct { type File struct {
Header Header Header Header
Checksum uint32
Script []byte Script []byte
Checksum uint32
} }
// Header represents File header. // Header represents File header.
@ -73,7 +73,7 @@ func NewFile(script []byte) (File, error) {
return file, err return file, err
} }
file.Header.Version = v file.Header.Version = v
file.Checksum = file.Header.CalculateChecksum() file.Checksum = file.CalculateChecksum()
return file, nil return file, nil
} }
@ -171,36 +171,35 @@ func (h *Header) DecodeBinary(r *io.BinReader) {
} }
// CalculateChecksum returns first 4 bytes of double-SHA256(Header) converted to uint32. // CalculateChecksum returns first 4 bytes of double-SHA256(Header) converted to uint32.
func (h *Header) CalculateChecksum() uint32 { func (n *File) CalculateChecksum() uint32 {
buf := io.NewBufBinWriter() bb, err := n.Bytes()
h.EncodeBinary(buf.BinWriter) if err != nil {
if buf.Err != nil { panic(err)
panic(buf.Err)
} }
return binary.LittleEndian.Uint32(hash.Checksum(buf.Bytes())) return binary.LittleEndian.Uint32(hash.Checksum(bb[:len(bb)-4]))
} }
// EncodeBinary implements io.Serializable interface. // EncodeBinary implements io.Serializable interface.
func (n *File) EncodeBinary(w *io.BinWriter) { func (n *File) EncodeBinary(w *io.BinWriter) {
n.Header.EncodeBinary(w) n.Header.EncodeBinary(w)
w.WriteU32LE(n.Checksum)
w.WriteVarBytes(n.Script) w.WriteVarBytes(n.Script)
w.WriteU32LE(n.Checksum)
} }
// DecodeBinary implements io.Serializable interface. // DecodeBinary implements io.Serializable interface.
func (n *File) DecodeBinary(r *io.BinReader) { func (n *File) DecodeBinary(r *io.BinReader) {
n.Header.DecodeBinary(r) n.Header.DecodeBinary(r)
n.Checksum = r.ReadU32LE()
checksum := n.Header.CalculateChecksum()
if checksum != n.Checksum {
r.Err = errors.New("CRC verification fail")
return
}
n.Script = r.ReadVarBytes(MaxScriptLength) n.Script = r.ReadVarBytes(MaxScriptLength)
if len(n.Script) == 0 { if len(n.Script) == 0 {
r.Err = errors.New("empty script") r.Err = errors.New("empty script")
return return
} }
n.Checksum = r.ReadU32LE()
checksum := n.CalculateChecksum()
if checksum != n.Checksum {
r.Err = errors.New("checksum verification failure")
return
}
} }
// Bytes returns byte array with serialized NEF File. // Bytes returns byte array with serialized NEF File.

View file

@ -36,20 +36,20 @@ func TestEncodeDecodeBinary(t *testing.T) {
t.Run("zero-length script", func(t *testing.T) { t.Run("zero-length script", func(t *testing.T) {
expected.Script = make([]byte, 0) expected.Script = make([]byte, 0)
expected.Checksum = expected.Header.CalculateChecksum() expected.Checksum = expected.CalculateChecksum()
checkDecodeError(t, expected) checkDecodeError(t, expected)
}) })
t.Run("invalid script length", func(t *testing.T) { t.Run("invalid script length", func(t *testing.T) {
newScript := make([]byte, MaxScriptLength+1) newScript := make([]byte, MaxScriptLength+1)
expected.Script = newScript expected.Script = newScript
expected.Checksum = expected.Header.CalculateChecksum() expected.Checksum = expected.CalculateChecksum()
checkDecodeError(t, expected) checkDecodeError(t, expected)
}) })
t.Run("positive", func(t *testing.T) { t.Run("positive", func(t *testing.T) {
expected.Script = script expected.Script = script
expected.Checksum = expected.Header.CalculateChecksum() expected.Checksum = expected.CalculateChecksum()
expected.Header.Magic = Magic expected.Header.Magic = Magic
testserdes.EncodeDecodeBinary(t, expected, &File{}) testserdes.EncodeDecodeBinary(t, expected, &File{})
}) })
@ -76,7 +76,7 @@ func TestBytesFromBytes(t *testing.T) {
}, },
Script: script, Script: script,
} }
expected.Checksum = expected.Header.CalculateChecksum() expected.Checksum = expected.CalculateChecksum()
bytes, err := expected.Bytes() bytes, err := expected.Bytes()
require.NoError(t, err) require.NoError(t, err)