@@ -110,174 +110,163 @@ func TestNormalizeWorkflowName(t *testing.T) {
110110 }
111111}
112112
113- func Test_GenerateWorkflowOwnerAddress_DifferentInputsGenerateDifferentAddresses (t * testing.T ) {
114- tests := []struct {
115- name string
116- prefix1 string
117- ownerKey1 string
118- prefix2 string
119- ownerKey2 string
113+ func Test_GenerateWorkflowOwnerAddress_SameInputsGenerateSameAddress (t * testing.T ) {
114+ prefix := "test_registry"
115+ ownerKey := "test_owner_123"
116+
117+ // Generate address multiple times
118+ addr1 , err := GenerateWorkflowOwnerAddress (prefix , ownerKey )
119+ require .NoError (t , err , "Failed to generate first address" )
120+
121+ addr2 , err := GenerateWorkflowOwnerAddress (prefix , ownerKey )
122+ require .NoError (t , err , "Failed to generate second address" )
123+
124+ // Verify all addresses are identical
125+ addr1Hex := hex .EncodeToString (addr1 )
126+ addr2Hex := hex .EncodeToString (addr2 )
127+
128+ require .Equal (t , addr1Hex , addr2Hex , "Same inputs should generate same address" )
129+ }
130+
131+ func Test_GenerateWorkflowOwnerAddress_OtherTestVectors (t * testing.T ) {
132+ testVectors := []struct {
133+ prefix string
134+ ownerKey string
135+ keccakInput string
136+ keccakHash string
137+ ethAddress string
120138 description string
121139 }{
122140 {
123- name : "different_prefix" ,
124- prefix1 : "registry_v1" ,
125- ownerKey1 : "owner123" ,
126- prefix2 : "registry_v2" ,
127- ownerKey2 : "owner123" ,
128- description : "Same ownerKey, different prefix" ,
141+ prefix : "" ,
142+ ownerKey : "" ,
143+ ethAddress : "0x41305062a5e522A01B7D9460E6744C879113C5dB" ,
144+ description : "Empty prefix and ownerKey" ,
145+ },
146+ {
147+ prefix : "" ,
148+ ownerKey : "non_empty_owner_key" ,
149+ ethAddress : "0xa6b6C2C0D58bD45c83b89F60cae395F7f3c9A0D0" ,
150+ description : "Empty prefix, non-empty ownerKey" ,
151+ },
152+ {
153+ prefix : "non_empty_prefix" ,
154+ ownerKey : "" ,
155+ ethAddress : "0x8Cb3243107cAD0D5584cD8b37393FE7f5200B920" ,
156+ description : "Non-empty prefix, empty ownerKey" ,
157+ },
158+ {
159+ prefix : "x" ,
160+ ownerKey : "yz" ,
161+ ethAddress : "0xb2a39e39664A469bc1d1b5dB8592deda4E9410af" ,
162+ description : "Collision test case 1: x + yz" ,
129163 },
130164 {
131- name : "different_ownerKey" ,
132- prefix1 : "registry_v1" ,
133- ownerKey1 : "owner123" ,
134- prefix2 : "registry_v1" ,
135- ownerKey2 : "owner124" ,
136- description : "Same prefix, different ownerKey" ,
165+ prefix : "xy" ,
166+ ownerKey : "z" ,
167+ ethAddress : "0x561960c471b8B288284073457EB77175C49DA9cd" ,
168+ description : "Collision test case 2: xy + z (should be different from x + yz)" ,
137169 },
138170 {
139- name : "case_sensitive_prefix" ,
140- prefix1 : "Registry" ,
141- ownerKey1 : "owner123" ,
142- prefix2 : "registry" ,
143- ownerKey2 : "owner123" ,
144- description : "Case sensitive prefix difference" ,
171+ prefix : "org_123456789" ,
172+ ownerKey : "cre-storage-service" ,
173+ ethAddress : "0x95b028290D5E2aC912f0bA8e9E35931B90740608" ,
174+ description : "Realistic org ID and service name" ,
145175 },
146176 {
147- name : "case_sensitive_ownerKey" ,
148- prefix1 : "registry" ,
149- ownerKey1 : "Owner123" ,
150- prefix2 : "registry" ,
151- ownerKey2 : "owner123" ,
152- description : "Case sensitive ownerKey difference" ,
177+ prefix : "org_0x1234567890abcdef" ,
178+ ownerKey : "cre-storage-service" ,
179+ ethAddress : "0x102d1d8570F155D4C9AF463C7098B978fEaEDf1C" ,
180+ description : "Hex-prefixed org ID" ,
153181 },
154182 {
155- name : "single_char_difference_prefix" ,
156- prefix1 : "registrya" ,
157- ownerKey1 : "owner123" ,
158- prefix2 : "registryb" ,
159- ownerKey2 : "owner123" ,
160- description : "Single character difference in prefix" ,
183+ prefix : "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ,
184+ ownerKey : "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" ,
185+ ethAddress : "0x31B1AfA30824ab78fF1c3f7b26ef6ce50D9c3221" ,
186+ description : "Long repeating characters" ,
161187 },
162188 {
163- name : "single_char_difference_ownerKey" ,
164- prefix1 : "registry" ,
165- ownerKey1 : "owner123a" ,
166- prefix2 : "registry" ,
167- ownerKey2 : "owner123b" ,
168- description : "Single character difference in ownerKey" ,
189+ prefix : "org_public_key" ,
190+ ownerKey : "0x02aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ,
191+ ethAddress : "0x9Ed0D44aB4B2FCC1B4C280105D641F668b81A6e9" ,
192+ description : "Public key as ownerKey" ,
193+ },
194+ {
195+ prefix : "org@special#chars" ,
196+ ownerKey : "key$with%symbols" ,
197+ ethAddress : "0xAbF538FFffFAE8C139c0BF80e7cEC5c1596D0944" ,
198+ description : "Special characters in both prefix and ownerKey" ,
169199 },
170200 }
171201
172- for _ , tt := range tests {
173- t .Run (tt .name , func (t * testing.T ) {
174- // Generate first address
175- addr1 , err := GenerateWorkflowOwnerAddress (tt .prefix1 , tt .ownerKey1 )
176- require .NoError (t , err , "Failed to generate first address" )
202+ for _ , tv := range testVectors {
203+ t .Run (tv .description , func (t * testing.T ) {
204+ addr , err := GenerateWorkflowOwnerAddress (tv .prefix , tv .ownerKey )
205+ require .NoError (t , err , "Failed to generate address" )
177206
178- // Generate second address
179- addr2 , err := GenerateWorkflowOwnerAddress (tt .prefix2 , tt .ownerKey2 )
180- require .NoError (t , err , "Failed to generate second address" )
207+ expectedAddr := tv .ethAddress
208+ if expectedAddr [:2 ] == "0x" {
209+ expectedAddr = expectedAddr [2 :]
210+ }
211+ expectedAddr = strings .ToLower (expectedAddr )
212+ actualAddr := hex .EncodeToString (addr )
181213
182- // Verify addresses are different
183- require .NotEqual (t , hex .EncodeToString (addr1 ), hex .EncodeToString (addr2 ), "Addresses should not match" )
214+ require .Equal (t , expectedAddr , actualAddr , "Address mismatch" )
184215
185- // Verify addresses are 20 bytes (Ethereum address length)
186- require .Len (t , addr1 , 20 , "First address should be 20 bytes" )
187- require .Len (t , addr2 , 20 , "Second address should be 20 bytes" )
216+ require .Len (t , addr , 20 , "Address should be 20 bytes" )
188217 })
189218 }
190219}
191220
192- func Test_GenerateWorkflowOwnerAddress_SameInputsGenerateSameAddress (t * testing.T ) {
193- prefix := "test_registry"
194- ownerKey := "test_owner_123"
195-
196- // Generate address multiple times
197- addr1 , err := GenerateWorkflowOwnerAddress (prefix , ownerKey )
198- require .NoError (t , err , "Failed to generate first address" )
199-
200- addr2 , err := GenerateWorkflowOwnerAddress (prefix , ownerKey )
201- require .NoError (t , err , "Failed to generate second address" )
202-
203- // Verify all addresses are identical
204- addr1Hex := hex .EncodeToString (addr1 )
205- addr2Hex := hex .EncodeToString (addr2 )
206-
207- require .Equal (t , addr1Hex , addr2Hex , "Same inputs should generate same address" )
208- }
209-
210- func Test_GenerateWorkflowOwnerAddress_SolidityCompatibility (t * testing.T ) {
211- /*
212- // SPDX-License-Identifier: MIT
213- pragma solidity ^0.8.0;
214-
215- contract WorkflowOwnerAddressGenerator {
216-
217- function generateWorkflowOwnerAddress(
218- string memory prefix,
219- string memory ownerKey
220- ) public pure returns (address) {
221- // Step 1: Create nested hash of prefix + ownerKey
222- bytes32 nestedHash = keccak256(abi.encodePacked(prefix, ownerKey));
223-
224- // Step 2: Create the full preimage for outer hash
225- // 0xff + 84 zero bytes + nested hash
226- bytes memory preimage = new bytes(117); // 1 + 84 + 32 = 117 bytes
227-
228- // Set first byte to 0xff
229- preimage[0] = 0xff;
230-
231- // Bytes 1-84 are already zero (default in Solidity)
232-
233- // Copy nested hash to bytes 85-116
234- for (uint256 i = 0; i < 32; i++) {
235- preimage[85 + i] = nestedHash[i];
236- }
237-
238- // Step 3: Hash the full preimage and return last 20 bytes as address
239- bytes32 outerHash = keccak256(preimage);
240- return address(uint160(uint256(outerHash)));
241- }
242- }
243- */
244- // These expected addresses were generated using the Solidity contract above
245- // You can verify these by deploying the contract and calling the function
221+ func Test_GenerateWorkflowOwnerAddress_CollisionResistanceWithLengthPrefixing (t * testing.T ) {
222+ // Test that the length-prefixing prevents collisions
246223 testCases := []struct {
247- prefix string
248- ownerKey string
249- expectedHex string // This should be generated by running the Solidity contract
224+ prefix1 string
225+ owner1 string
226+ prefix2 string
227+ owner2 string
228+ caseName string
250229 }{
251230 {
252- prefix : "registry1" ,
253- ownerKey : "owner123" ,
254- expectedHex : "0x58c0e4aaf5fb13fcaea5790f8a19014ad9646da3" , // convert to lowercase, not checksum
231+ prefix1 : "x" ,
232+ owner1 : "yz" ,
233+ prefix2 : "xy" ,
234+ owner2 : "z" ,
235+ caseName : "x+yz vs xy+z collision resistance" ,
236+ },
237+ {
238+ prefix1 : "a" ,
239+ owner1 : "bc" ,
240+ prefix2 : "ab" ,
241+ owner2 : "c" ,
242+ caseName : "a+bc vs ab+c collision resistance" ,
255243 },
256244 {
257- prefix : "registry2" ,
258- ownerKey : "owner123" ,
259- expectedHex : "0xf094995741cffc6c173fa9edb2e8d766d1524039" , // convert to lowercase, not checksum
245+ prefix1 : "" ,
246+ owner1 : "abc" ,
247+ prefix2 : "a" ,
248+ owner2 : "bc" ,
249+ caseName : "empty+abc vs a+bc collision resistance" ,
260250 },
261251 {
262- prefix : "registry2" ,
263- ownerKey : "ownerSomethingElse" ,
264- expectedHex : "0x4be6a8e38aa493cac0aa4c6dd13bad41f8219f0c" , // convert to lowercase, not checksum
252+ prefix1 : "test" ,
253+ owner1 : "" ,
254+ prefix2 : "tes" ,
255+ owner2 : "t" ,
256+ caseName : "test+empty vs tes+t collision resistance" ,
265257 },
266258 }
267259
268260 for _ , tc := range testCases {
269- t .Run (tc .prefix + "_" + tc . ownerKey , func (t * testing.T ) {
270- goAddr , err := GenerateWorkflowOwnerAddress (tc .prefix , tc .ownerKey )
261+ t .Run (tc .caseName , func (t * testing.T ) {
262+ addr1 , err := GenerateWorkflowOwnerAddress (tc .prefix1 , tc .owner1 )
271263 require .NoError (t , err )
272264
273- goAddrHex := hex .EncodeToString (goAddr )
274-
275- // Remove 0x prefix if present in expected
276- expected := strings .TrimPrefix (tc .expectedHex , "0x" )
265+ addr2 , err := GenerateWorkflowOwnerAddress (tc .prefix2 , tc .owner2 )
266+ require .NoError (t , err )
277267
278- require .Equal (t , expected , goAddrHex ,
279- "Go implementation should match Solidity for prefix='%s', ownerKey='%s'" ,
280- tc .prefix , tc .ownerKey )
268+ require .NotEqual (t , hex .EncodeToString (addr1 ), hex .EncodeToString (addr2 ),
269+ "Addresses should be different" )
281270 })
282271 }
283272}
0 commit comments