Browse Source

parser: finish ZIP243 tests

v2_protobufs
George Tankersley 6 years ago
parent
commit
e3b5a9558d
  1. 306
      parser/transaction_test.go

306
parser/transaction_test.go

@ -28,15 +28,40 @@ type joinSplitTestVector struct {
encCiphertexts []string // 1202 [N_new][601]byte
}
type zip143test struct {
type spendTestVector struct {
cv string // 32
anchor string // 32
nullifier string // 32
rk string // 32
zkproof string // 192
spendAuthSig string // 64
}
type outputTestVector struct {
cv string // 32
cmu string // 32
ephemeralKey string // 32
encCiphertext string // 580
outCiphertext string // 80
zkproof string // 192
}
type txTestVector struct {
// Sprout and Sapling
header, nVersionGroupId, nLockTime, nExpiryHeight string
vin, vout [][]string
vJoinSplits []joinSplitTestVector
joinSplitPubKey, joinSplitSig string
// Sapling-only
valueBalance string // encoded int64
spends []spendTestVector
outputs []outputTestVector
bindingSig string
}
// https://github.com/zcash/zips/blob/master/zip-0143.rst
var zip143tests = []zip143test{
var zip143tests = []txTestVector{
{
// Test vector 1
header: "03000080",
@ -200,7 +225,7 @@ func TestSproutTransactionParser(t *testing.T) {
}
}
func subTestCommonBlockMeta(tt *zip143test, tx *transaction, t *testing.T, caseNum int) bool {
func subTestCommonBlockMeta(tt *txTestVector, tx *transaction, t *testing.T, caseNum int) bool {
headerBytes, _ := hex.DecodeString(tt.header)
header := binary.LittleEndian.Uint32(headerBytes)
if (header >> 31) == 1 != tx.fOverwintered {
@ -478,35 +503,9 @@ func subTestTransparentOutputs(testOutputs [][]string, txOutputs []*txOut, t *te
return success
}
type spendTestVector struct {
cv string // 32
anchor string // 32
nullifier string // 32
rk string // 32
zkproof string // 192
spendAuthSig string // 64
}
type outputTestVector struct {
cv string // 32
cmu string // 32
ephemeralKey string // 32
encCiphertext string // 580
outCiphertext string // 80
zkproof string // 192
}
// https://github.com/zcash/zips/blob/master/zip-0243.rst
var zip243tests = []struct {
header, nVersionGroupId, nLockTime, nExpiryHeight string
vin, vout [][]string
valueBalance string // encoded int64
spends []spendTestVector
outputs []outputTestVector
vJoinSplits []joinSplitTestVector
joinSplitPubKey, joinSplitSig string
bindingSig string
}{
var zip243tests = []txTestVector{
// Test vector 1
{
header: "04000080",
nVersionGroupId: "85202f89",
@ -608,8 +607,251 @@ var zip243tests = []struct {
joinSplitSig: "469b0e272494e5df54f568656cb9c8818d92b72b8bc34db7bb3112487e746eefe4e808bbb287d99bf07d00dabededc5e5f074ffeae0cba7da3a516c173be1c51",
bindingSig: "3323e119f635e8209a074b216b7023fadc2d25949c90037e71e3e550726d210a2c688342e52440635e9cc14afe10102621a9c9accb782e9e4a5fa87f0a956f5b",
},
// Test vector 2
{
header: "04000080",
nVersionGroupId: "85202f89",
vin: [][]string{
{"56e551406a7ee8355656a21e43e38ce129fdadb759eddfa08f00fc8e567cef93", "c6792d01", "0763656300ac63ac", "8df04245"},
{"1a33590d3e8cf49b2627218f0c292fa66ada945fa55bb23548e33a83a562957a", "3149a993", "086a5352516a65006a", "78d97ce4"},
},
vout: [][]string{
{"e91cb65a63b70100", "09516a6a656aac636565"},
{"5cc7c9aae5bd0300", "02636a"},
},
nLockTime: "675cb83e",
nExpiryHeight: "43e29c17",
valueBalance: "44b8b5b99ce30500",
spends: []spendTestVector{
{
cv: "b0f5b874a6ecabe6c56ee58b67d02f5d47db8cc3458435d5088d69b2240c28f3",
anchor: "71c012c415d2382a6eebc8b3db07ea1cbf28288daaa91538de4552eeeef72c24",
nullifier: "c85d83db20efad48be8996fb1bff591efff360fe1199056c56e5feec61a7b8b9",
rk: "f699d6012c2849232f329fef95c7af370098ffe4918e0ca1df47f275867b739e",
zkproof: "0a514d3209325e217045927b479c1ce2e5d54f25488cad1513e3f44a21266cfd841633327dee6cf810fbf7393e317d9e53d1be1d5ae7839b66b943b9ed18f2c530e975422332c3439cce49a29f2a336a4851263c5e9bd13d731109e844b7f8c392a5c1dcaa2ae5f50ff63fab9765e016702c35a67cd7364d3fab552fb349e35c15c50250453fd18f7b855992632e2c76c0fbf1ef963ea80e3223de3277bc559251725829ec03f213ba8955cab2822ff21a9b0a4904d668fcd77224bde3dd01f6",
spendAuthSig: "ffc4828f6b64230b35c6a049873494276ea1d7ed5e92cb4f90ba83a9e49601b194042f2900d99d312d7b70508cf176066d154dbe96ef9d4367e4c840e4a17b5e",
},
{
cv: "26bca7fdd7cc43201c56f468fadc42cff0d81a966417ad8f097ebf3b25879e55",
anchor: "c23e34da91c816d8d1790dfe34bdce040db1727af24d59ef78d3f4aac2b59822",
nullifier: "d6f12f24fd364496b3be0871ca3dd9625348a614b59bde45885649bae36de34d",
rk: "ef8fcec85343475d976ae1e9b27829ce2ac5efd0b399a8b448be6504294ee6b3",
zkproof: "c1c6a5342d7c01ae9d8ad3070c2b1a91573af5e0c5e4cbbf4acdc6b54c9272200d9970250c17c1036f06085c41858ed3a0c48150bc697e4a695fef335f7ad07e1a46dc767ff822db70e6669080b9816b2232c81a4c66cc586abfe1eaa8ca6cf41fc3c3e6c7b886fb6dac9f4822b4fc6fff9d0513d61a21c80a377671d135a668a0ae2bb934c82c4142da69d12ca7de9a7df706400ec79878d868e17e8f71ea31495af819a016cc419e07c501aa8309b2e6c85b79b2763733a37bbc0420d42537",
spendAuthSig: "b871b4294a65d3e055ff718dd9dc8c75e7e5b2efe442637371b7c48f6ee99e3ea38a4b0f2f67fc2b908cda657eae754e037e262e9a9f9bd7ec4267ed8e96930e",
},
{
cv: "eb89a85980f97d7faaed78d8f38beb624b774c73a46ced614be219b3d94873b6",
anchor: "0df7fc90b579abf62037975edd6aacc442190a0ba55b15f81f86bade794ace2a",
nullifier: "9d9a816baf728a955b960b7701fa626687dc3c9cba646337b53e29816e9482dd",
rk: "f5578a8768aae477fce410ac2d5de6095861c111d7feb3e6bb4fbb5a54955495",
zkproof: "972798350a253f05f66c2ecfcbc0ed43f5ec2e6d8dba15a51254d97b1821107c07dd9a16ef8406f943e282b95d4b362530c913d6ba421df6027de5af1e4745d5868106954be6c1962780a2941072e95131b1679df0637625042c37d48ffb152e5ebc185c8a2b7d4385f1c95af937df78dfd8757fab434968b0b57c66574468f160b447ac8221e5060676a842a1c6b7172dd3340f764070ab1fe091c5c74c95a5dc043390723a4c127da14cdde1dc2675a62340b3e6afd0522a31de26e7d1ec3a",
spendAuthSig: "9c8a091ffdc75b7ecfdc7c12995a5e37ce3488bd29f8629d68f696492448dd526697476dc061346ebe3f677217ff9c60efce943af28dfd3f9e59692598a6047c",
},
},
outputs: nil,
vJoinSplits: nil,
joinSplitPubKey: "",
joinSplitSig: "",
bindingSig: "c01400f1ab5730eac0ae8d5843d5051c376240172af218d7a1ecfe65b4f75100638983c14de4974755dade8018c9b8f4543fb095961513e67c61dbc59c607f9b",
},
}
func TestSaplingTransactionParser(t *testing.T) {
// TODO: test Sapling transaction parsing; ZIP243
testData, err := os.Open("testdata/zip243_raw_tx")
if err != nil {
t.Fatal(err)
}
defer testData.Close()
// Parse the raw transactions file
rawTxData := make([][]byte, len(zip243tests))
scan := bufio.NewScanner(testData)
count := 0
for scan.Scan() {
dataLine := scan.Text()
// Skip the comments
if strings.HasPrefix(dataLine, "#") {
continue
}
txData, err := hex.DecodeString(dataLine)
if err != nil {
t.Fatal(err)
}
rawTxData[count] = txData
count++
}
for i, tt := range zip243tests {
tx := newTransaction()
rest, err := tx.ParseFromSlice(rawTxData[i])
if err != nil {
t.Errorf("Test %d: %v", i, err)
continue
}
if len(rest) != 0 {
t.Errorf("Test %d: did not consume entire buffer", i)
continue
}
// Transaction metadata
if ok := subTestCommonBlockMeta(&tt, tx, t, i); !ok {
continue
}
// Transparent inputs and outputs
if ok := subTestTransparentInputs(tt.vin, tx.transparentInputs, t, i); !ok {
continue
}
if ok := subTestTransparentOutputs(tt.vout, tx.transparentOutputs, t, i); !ok {
continue
}
// JoinSplits
if ok := subTestJoinSplits(tt.vJoinSplits, tx.joinSplits, t, i); !ok {
continue
}
testJSPubKey, _ := hex.DecodeString(tt.joinSplitPubKey)
if !bytes.Equal(testJSPubKey, tx.joinSplitPubKey) {
t.Errorf("Test %d: jsPubKey mismatch %x %x", i, testJSPubKey, tx.joinSplitPubKey)
continue
}
testJSSig, _ := hex.DecodeString(tt.joinSplitSig)
if !bytes.Equal(testJSSig, tx.joinSplitSig) {
t.Errorf("Test %d: jsSig mismatch %x %x", i, testJSSig, tx.joinSplitSig)
continue
}
// Begin Sapling-specific tests
testValueBalanceBytes, _ := hex.DecodeString(tt.valueBalance)
testValueBalance := int64(binary.LittleEndian.Uint64(testValueBalanceBytes))
if testValueBalance != tx.valueBalance {
t.Errorf("Test %d: valueBalance mismatch %d %d", i, testValueBalance, tx.valueBalance)
continue
}
if ok := subTestShieldedSpends(tt.spends, tx.shieldedSpends, t, i); !ok {
continue
}
if ok := subTestShieldedOutputs(tt.outputs, tx.shieldedOutputs, t, i); !ok {
continue
}
testBinding, _ := hex.DecodeString(tt.bindingSig)
if !bytes.Equal(testBinding, tx.bindingSig) {
t.Errorf("Test %d: bindingSig %x %x", i, testBinding, tx.bindingSig)
continue
}
}
}
func subTestShieldedSpends(testSpends []spendTestVector, txSpends []*spend, t *testing.T, caseNum int) bool {
if testSpends == nil && txSpends != nil {
t.Errorf("Test %d: non-zero Spends when expected empty vector", caseNum)
return false
}
if len(testSpends) != len(txSpends) {
t.Errorf("Test %d: Spend vector lengths mismatch", caseNum)
return false
}
success := true
for j, tt := range testSpends {
tx := txSpends[j]
testCV, _ := hex.DecodeString(tt.cv)
if !bytes.Equal(testCV, tx.cv) {
t.Errorf("Test %d spend %d: cv %x %x", caseNum, j, testCV, tx.cv)
success = false
continue
}
testAnchor, _ := hex.DecodeString(tt.anchor)
if !bytes.Equal(testAnchor, tx.anchor) {
t.Errorf("Test %d spend %d: anchor %x %x", caseNum, j, testAnchor, tx.anchor)
success = false
continue
}
testNullifier, _ := hex.DecodeString(tt.nullifier)
if !bytes.Equal(testNullifier, tx.nullifier) {
t.Errorf("Test %d spend %d: nullifier %x %x", caseNum, j, testNullifier, tx.nullifier)
success = false
continue
}
testrk, _ := hex.DecodeString(tt.rk)
if !bytes.Equal(testrk, tx.rk) {
t.Errorf("Test %d spend %d: rk %x %x", caseNum, j, testrk, tx.rk)
success = false
continue
}
testzkproof, _ := hex.DecodeString(tt.zkproof)
if !bytes.Equal(testzkproof, tx.zkproof) {
t.Errorf("Test %d spend %d: zkproof %x %x", caseNum, j, testzkproof, tx.zkproof)
success = false
continue
}
testspendAuthSig, _ := hex.DecodeString(tt.spendAuthSig)
if !bytes.Equal(testspendAuthSig, tx.spendAuthSig) {
t.Errorf("Test %d spend %d: spendAuthSig %x %x", caseNum, j, testspendAuthSig, tx.spendAuthSig)
success = false
continue
}
}
return success
}
func subTestShieldedOutputs(testOutputs []outputTestVector, txOutputs []*output, t *testing.T, caseNum int) bool {
if testOutputs == nil && txOutputs != nil {
t.Errorf("Test %d: non-zero Outputs when expected empty vector", caseNum)
return false
}
if len(testOutputs) != len(txOutputs) {
t.Errorf("Test %d: Output vector lengths mismatch", caseNum)
return false
}
success := true
for j, tt := range testOutputs {
tx := txOutputs[j]
testCV, _ := hex.DecodeString(tt.cv)
if !bytes.Equal(testCV, tx.cv) {
t.Errorf("Test %d output %d: cv %x %x", caseNum, j, testCV, tx.cv)
success = false
continue
}
testcmu, _ := hex.DecodeString(tt.cmu)
if !bytes.Equal(testcmu, tx.cmu) {
t.Errorf("Test %d output %d: cmu %x %x", caseNum, j, testcmu, tx.cmu)
success = false
continue
}
testEphemeralKey, _ := hex.DecodeString(tt.ephemeralKey)
if !bytes.Equal(testEphemeralKey, tx.ephemeralKey) {
t.Errorf("Test %d output %d: ephemeralKey %x %x", caseNum, j, testEphemeralKey, tx.ephemeralKey)
success = false
continue
}
testencCiphertext, _ := hex.DecodeString(tt.encCiphertext)
if !bytes.Equal(testencCiphertext, tx.encCiphertext) {
t.Errorf("Test %d output %d: encCiphertext %x %x", caseNum, j, testencCiphertext, tx.encCiphertext)
success = false
continue
}
testzkproof, _ := hex.DecodeString(tt.zkproof)
if !bytes.Equal(testzkproof, tx.zkproof) {
t.Errorf("Test %d output %d: zkproof %x %x", caseNum, j, testzkproof, tx.zkproof)
success = false
continue
}
}
return success
}

Loading…
Cancel
Save